Commit 404fd02e96d33840f58f83f88815e2a259cdc532

Authored by Robin Gong
1 parent 53118db42d

ENGR00326277-1: imx6: ldo_bypass: fix VDDARM voltage setting violate datasheet

Current only set VDDARM_IN@1.175V/VDDSOC_IN@1.175V before ldo bypass switch.
So untile ldo bypass switch happened, these voltage setting is set in ldo-enable
mode. But in datasheet, we need 1.15V + 125mV = 1.275V for VDDARM_IN. We need
to downgrade cpufreq to 400Mhz and restore after ldo bypass mode switch.

Signed-off-by: Robin Gong <b38343@freescale.com>

Showing 4 changed files with 145 additions and 11 deletions Side-by-side Diff

arch/arm/cpu/armv7/mx6/soc.c
... ... @@ -835,15 +835,58 @@
835 835 return result;
836 836 }
837 837  
838   -void set_anatop_bypass(void)
  838 +static int arm_orig_podf;
  839 +void set_arm_freq_400M(bool is_400M)
839 840 {
  841 + struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
  842 +
  843 + if (is_400M)
  844 + writel(0x1, &mxc_ccm->cacrr);
  845 + else
  846 + writel(arm_orig_podf, &mxc_ccm->cacrr);
  847 +}
  848 +
  849 +void prep_anatop_bypass(void)
  850 +{
  851 + struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
  852 +
  853 + arm_orig_podf = readl(&mxc_ccm->cacrr);
  854 + /*
  855 + * Downgrade ARM speed to 400Mhz as half of boot 800Mhz before ldo
  856 + * bypassed, also downgrade internal vddarm ldo to 0.975V.
  857 + * VDDARM_IN 0.975V + 125mV = 1.1V < Max(1.3V)
  858 + * otherwise at 800Mhz(i.mx6dl):
  859 + * VDDARM_IN 1.175V + 125mV = 1.3V = Max(1.3V)
  860 + * We need provide enough gap in this case.
  861 + * skip if boot from 400M.
  862 + */
  863 + if (!arm_orig_podf)
  864 + set_arm_freq_400M(true);
  865 +#ifndef CONFIG_MX6DL
  866 + set_ldo_voltage(LDO_ARM, 975);
  867 +#else
  868 + set_ldo_voltage(LDO_ARM, 1150);
  869 +#endif
  870 +}
  871 +
  872 +int set_anatop_bypass(void)
  873 +{
840 874 struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
841 875 u32 reg = readl(&anatop->reg_core);
842 876  
843 877 /* bypass VDDARM/VDDSOC */
844 878 reg = reg | (0x1F << 18) | 0x1F;
845 879 writel(reg, &anatop->reg_core);
  880 +
  881 + return arm_orig_podf;
846 882 }
  883 +
  884 +void finish_anatop_bypass(void)
  885 +{
  886 + if (!arm_orig_podf)
  887 + set_arm_freq_400M(false);
  888 +}
  889 +
847 890 #endif
848 891  
849 892 #ifdef CONFIG_IMX_HDMI
arch/arm/include/asm/arch-mx6/sys_proto.h
... ... @@ -26,8 +26,10 @@
26 26 #ifdef CONFIG_LDO_BYPASS_CHECK
27 27 int check_ldo_bypass(void);
28 28 int check_1_2G(void);
29   -void set_anatop_bypass(void);
  29 +int set_anatop_bypass(void);
30 30 void ldo_mode_set(int ldo_bypass);
  31 +void prep_anatop_bypass(void);
  32 +void finish_anatop_bypass(void);
31 33 #endif
32 34  
33 35 #ifdef CONFIG_MX6SX
board/freescale/mx6sabresd/mx6sabresd.c
... ... @@ -387,6 +387,9 @@
387 387 void ldo_mode_set(int ldo_bypass)
388 388 {
389 389 unsigned char value;
  390 + int is_400M;
  391 + unsigned char vddarm;
  392 +
390 393 /* increase VDDARM/VDDSOC to support 1.2G chip */
391 394 if (check_1_2G()) {
392 395 ldo_bypass = 0; /* ldo_enable on 1.2G chip */
393 396  
394 397  
395 398  
396 399  
... ... @@ -416,30 +419,80 @@
416 419 }
417 420 /* switch to ldo_bypass mode , boot on 800Mhz */
418 421 if (ldo_bypass) {
419   - /* decrease VDDARM to 1.175V */
  422 + prep_anatop_bypass();
  423 +
  424 + /* decrease VDDARM for 400Mhz DQ:1.1V, DL:1.275V */
420 425 if (i2c_read(0x8, 0x20, 1, &value, 1)) {
421 426 printf("Read SW1AB error!\n");
422 427 return;
423 428 }
424 429 value &= ~0x3f;
425   - value |= 0x23;
  430 +#if defined(CONFIG_MX6DL)
  431 + value |= 0x27;
  432 +#else
  433 + value |= 0x20;
  434 +#endif
426 435 if (i2c_write(0x8, 0x20, 1, &value, 1)) {
427 436 printf("Set SW1AB error!\n");
428 437 return;
429 438 }
430   - /* increase VDDSOC to 1.175V */
  439 + /* increase VDDSOC to 1.3V */
431 440 if (i2c_read(0x8, 0x2e, 1, &value, 1)) {
432 441 printf("Read SW1C error!\n");
433 442 return;
434 443 }
435 444 value &= ~0x3f;
  445 + value |= 0x28;
  446 + if (i2c_write(0x8, 0x2e, 1, &value, 1)) {
  447 + printf("Set SW1C error!\n");
  448 + return;
  449 + }
  450 +
  451 + /*
  452 + * MX6Q:
  453 + * VDDARM:1.15V@800M; VDDSOC:1.175V@800M
  454 + * VDDARM:0.975V@400M; VDDSOC:1.175V@400M
  455 + * MX6DL:
  456 + * VDDARM:1.175V@800M; VDDSOC:1.175V@800M
  457 + * VDDARM:1.075V@400M; VDDSOC:1.175V@400M
  458 + */
  459 + is_400M = set_anatop_bypass();
  460 + if (is_400M)
  461 +#if defined(CONFIG_MX6DL)
  462 + vddarm = 0x1f;
  463 +#else
  464 + vddarm = 0x1b;
  465 +#endif
  466 + else
  467 +#if defined(CONFIG_MX6DL)
  468 + vddarm = 0x23;
  469 +#else
  470 + vddarm = 0x22;
  471 +#endif
  472 + if (i2c_read(0x8, 0x20, 1, &value, 1)) {
  473 + printf("Read SW1AB error!\n");
  474 + return;
  475 + }
  476 + value &= ~0x3f;
  477 + value |= vddarm;
  478 + if (i2c_write(0x8, 0x20, 1, &value, 1)) {
  479 + printf("Set SW1AB error!\n");
  480 + return;
  481 + }
  482 +
  483 + /* decrease VDDSOC to 1.175V */
  484 + if (i2c_read(0x8, 0x2e, 1, &value, 1)) {
  485 + printf("Read SW1C error!\n");
  486 + return;
  487 + }
  488 + value &= ~0x3f;
436 489 value |= 0x23;
437 490 if (i2c_write(0x8, 0x2e, 1, &value, 1)) {
438 491 printf("Set SW1C error!\n");
439 492 return;
440 493 }
441 494  
442   - set_anatop_bypass();
  495 + finish_anatop_bypass();
443 496 printf("switch to ldo_bypass mode!\n");
444 497 }
445 498 }
board/freescale/mx6slevk/mx6slevk.c
... ... @@ -758,32 +758,68 @@
758 758 void ldo_mode_set(int ldo_bypass)
759 759 {
760 760 unsigned char value;
  761 + int is_400M;
  762 +
761 763 /* swith to ldo_bypass mode */
762 764 if (ldo_bypass) {
763   - /* decrease VDDARM to 1.15V */
  765 + prep_anatop_bypass();
  766 +
  767 + /* decrease VDDARM to 1.1V */
764 768 if (i2c_read(0x8, 0x20, 1, &value, 1)) {
765 769 printf("Read SW1AB error!\n");
766 770 return;
767 771 }
768 772 value &= ~0x3f;
769   - value |= 0x22;
  773 + value |= 0x20;
770 774 if (i2c_write(0x8, 0x20, 1, &value, 1)) {
771 775 printf("Set SW1AB error!\n");
772 776 return;
773 777 }
774   - /* increase VDDSOC to 1.15V */
  778 + /* increase VDDSOC to 1.3V */
775 779 if (i2c_read(0x8, 0x2e, 1, &value, 1)) {
776 780 printf("Read SW1C error!\n");
777 781 return;
778 782 }
779 783 value &= ~0x3f;
780   - value |= 0x22;
  784 + value |= 0x28;
781 785 if (i2c_write(0x8, 0x2e, 1, &value, 1)) {
782 786 printf("Set SW1C error!\n");
783 787 return;
784 788 }
785 789  
786   - set_anatop_bypass();
  790 + is_400M = set_anatop_bypass();
  791 +
  792 + /*
  793 + * MX6SL: VDDARM:1.175V@800M; VDDSOC:1.175V@800M
  794 + * VDDARM:0.975V@400M; VDDSOC:1.175V@400M
  795 + */
  796 + if (i2c_read(0x8, 0x20, 1, &value, 1)) {
  797 + printf("Read SW1AB error!\n");
  798 + return;
  799 + }
  800 + value &= ~0x3f;
  801 + if (is_400M)
  802 + value |= 0x1b;
  803 + else
  804 + value |= 0x23;
  805 + if (i2c_write(0x8, 0x20, 1, &value, 1)) {
  806 + printf("Set SW1AB error!\n");
  807 + return;
  808 + }
  809 +
  810 + /* decrease VDDSOC to 1.175V */
  811 + if (i2c_read(0x8, 0x2e, 1, &value, 1)) {
  812 + printf("Read SW1C error!\n");
  813 + return;
  814 + }
  815 + value &= ~0x3f;
  816 + value |= 0x23;
  817 + if (i2c_write(0x8, 0x2e, 1, &value, 1)) {
  818 + printf("Set SW1C error!\n");
  819 + return;
  820 + }
  821 +
  822 + finish_anatop_bypass();
787 823 printf("switch to ldo_bypass mode!\n");
788 824 }
789 825