]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - board/freescale/common/vid.c
board: common:vid: Add LS1088A VID Supported voltage values
[people/ms/u-boot.git] / board / freescale / common / vid.c
index 1ea1b88a10470efcdf0c362c3c2f6b69a48a6bda..bf63ce007aade879687130fea005e66f1782085f 100644 (file)
@@ -8,8 +8,10 @@
 #include <command.h>
 #include <i2c.h>
 #include <asm/io.h>
-#ifdef CONFIG_LS1043A
+#ifdef CONFIG_FSL_LSCH2
 #include <asm/arch/immap_lsch2.h>
+#elif defined(CONFIG_FSL_LSCH3)
+#include <asm/arch/immap_lsch3.h>
 #else
 #include <asm/immap_85xx.h>
 #endif
@@ -42,7 +44,7 @@ int __weak board_vdd_drop_compensation(void)
  * The IR chip can show up under the following addresses:
  * 0x08 (Verified on T1040RDB-PA,T4240RDB-PB,X-T4240RDB-16GPA)
  * 0x09 (Verified on T1040RDB-PA)
- * 0x38 (Verified on T2080QDS, T2081QDS)
+ * 0x38 (Verified on T2080QDS, T2081QDS, T4240RDB)
  */
 static int find_ir_chip_on_i2c(void)
 {
@@ -245,7 +247,7 @@ static int set_voltage_to_IR(int i2caddress, int vdd)
         * SoC before converting into an IR VID value
         */
        vdd += board_vdd_drop_compensation();
-#ifdef CONFIG_LS1043A
+#ifdef CONFIG_FSL_LSCH2
        vid = DIV_ROUND_UP(vdd - 265, 5);
 #else
        vid = DIV_ROUND_UP(vdd - 245, 5);
@@ -282,10 +284,208 @@ static int set_voltage(int i2caddress, int vdd)
        return vdd_last;
 }
 
+#ifdef CONFIG_FSL_LSCH3
 int adjust_vdd(ulong vdd_override)
 {
        int re_enable = disable_interrupts();
-#ifdef CONFIG_LS1043A
+       struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+       u32 fusesr;
+       u8 vid, buf;
+       int vdd_target, vdd_current, vdd_last;
+       int ret, i2caddress;
+       unsigned long vdd_string_override;
+       char *vdd_string;
+#ifdef CONFIG_ARCH_LS1088A
+       static const uint16_t vdd[32] = {
+               10250,
+               9875,
+               9750,
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               9000,
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               10000,  /* 1.0000V */
+               10125,
+               10250,
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+       };
+
+#else
+       static const uint16_t vdd[32] = {
+               10500,
+               0,      /* reserved */
+               9750,
+               0,      /* reserved */
+               9500,
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               10000,  /* 1.0000V */
+               0,      /* reserved */
+               10250,
+               0,      /* reserved */
+               10500,
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+               0,      /* reserved */
+       };
+#endif
+       struct vdd_drive {
+               u8 vid;
+               unsigned voltage;
+       };
+
+       ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
+       if (ret) {
+               debug("VID: I2C failed to switch channel\n");
+               ret = -1;
+               goto exit;
+       }
+       ret = find_ir_chip_on_i2c();
+       if (ret < 0) {
+               printf("VID: Could not find voltage regulator on I2C.\n");
+               ret = -1;
+               goto exit;
+       } else {
+               i2caddress = ret;
+               debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
+       }
+
+       /* check IR chip work on Intel mode*/
+       ret = i2c_read(i2caddress,
+                      IR36021_INTEL_MODE_OOFSET,
+                      1, (void *)&buf, 1);
+       if (ret) {
+               printf("VID: failed to read IR chip mode.\n");
+               ret = -1;
+               goto exit;
+       }
+       if ((buf & IR36021_MODE_MASK) != IR36021_INTEL_MODE) {
+               printf("VID: IR Chip is not used in Intel mode.\n");
+               ret = -1;
+               goto exit;
+       }
+
+       /* get the voltage ID from fuse status register */
+       fusesr = in_le32(&gur->dcfg_fusesr);
+       vid = (fusesr >> FSL_CHASSIS3_DCFG_FUSESR_ALTVID_SHIFT) &
+               FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK;
+       if ((vid == 0) || (vid == FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK)) {
+               vid = (fusesr >> FSL_CHASSIS3_DCFG_FUSESR_VID_SHIFT) &
+                       FSL_CHASSIS3_DCFG_FUSESR_VID_MASK;
+       }
+       vdd_target = vdd[vid];
+
+       /* check override variable for overriding VDD */
+       vdd_string = env_get(CONFIG_VID_FLS_ENV);
+       if (vdd_override == 0 && vdd_string &&
+           !strict_strtoul(vdd_string, 10, &vdd_string_override))
+               vdd_override = vdd_string_override;
+
+       if (vdd_override >= VDD_MV_MIN && vdd_override <= VDD_MV_MAX) {
+               vdd_target = vdd_override * 10; /* convert to 1/10 mV */
+               debug("VDD override is %lu\n", vdd_override);
+       } else if (vdd_override != 0) {
+               printf("Invalid value.\n");
+       }
+
+       /* divide and round up by 10 to get a value in mV */
+       vdd_target = DIV_ROUND_UP(vdd_target, 10);
+       if (vdd_target == 0) {
+               debug("VID: VID not used\n");
+               ret = 0;
+               goto exit;
+       } else if (vdd_target < VDD_MV_MIN || vdd_target > VDD_MV_MAX) {
+               /* Check vdd_target is in valid range */
+               printf("VID: Target VID %d mV is not in range.\n",
+                      vdd_target);
+               ret = -1;
+               goto exit;
+       } else {
+               debug("VID: vid = %d mV\n", vdd_target);
+       }
+
+       /*
+        * Read voltage monitor to check real voltage.
+        */
+       vdd_last = read_voltage(i2caddress);
+       if (vdd_last < 0) {
+               printf("VID: Couldn't read sensor abort VID adjustment\n");
+               ret = -1;
+               goto exit;
+       }
+       vdd_current = vdd_last;
+       debug("VID: Core voltage is currently at %d mV\n", vdd_last);
+       /*
+         * Adjust voltage to at or one step above target.
+         * As measurements are less precise than setting the values
+         * we may run through dummy steps that cancel each other
+         * when stepping up and then down.
+         */
+       while (vdd_last > 0 &&
+              vdd_last < vdd_target) {
+               vdd_current += IR_VDD_STEP_UP;
+               vdd_last = set_voltage(i2caddress, vdd_current);
+       }
+       while (vdd_last > 0 &&
+              vdd_last > vdd_target + (IR_VDD_STEP_DOWN - 1)) {
+               vdd_current -= IR_VDD_STEP_DOWN;
+               vdd_last = set_voltage(i2caddress, vdd_current);
+       }
+
+       if (vdd_last > 0)
+               printf("VID: Core voltage after adjustment is at %d mV\n",
+                      vdd_last);
+       else
+               ret = -1;
+exit:
+       if (re_enable)
+               enable_interrupts();
+       i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
+       return ret;
+}
+#else /* !CONFIG_FSL_LSCH3 */
+int adjust_vdd(ulong vdd_override)
+{
+       int re_enable = disable_interrupts();
+#if defined(CONFIG_FSL_LSCH2)
        struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
 #else
        ccsr_gur_t __iomem *gur =
@@ -380,7 +580,7 @@ int adjust_vdd(ulong vdd_override)
         * | T |          |         |                 |         |
         * ------------------------------------------------------
         */
-#ifdef CONFIG_LS1043A
+#ifdef CONFIG_FSL_LSCH2
        vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_ALTVID_SHIFT) &
                FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK;
        if ((vid == 0) || (vid == FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK)) {
@@ -398,7 +598,7 @@ int adjust_vdd(ulong vdd_override)
        vdd_target = vdd[vid];
 
        /* check override variable for overriding VDD */
-       vdd_string = getenv(CONFIG_VID_FLS_ENV);
+       vdd_string = env_get(CONFIG_VID_FLS_ENV);
        if (vdd_override == 0 && vdd_string &&
            !strict_strtoul(vdd_string, 10, &vdd_string_override))
                vdd_override = vdd_string_override;
@@ -454,8 +654,12 @@ int adjust_vdd(ulong vdd_override)
 exit:
        if (re_enable)
                enable_interrupts();
+
+       i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
+
        return ret;
 }
+#endif
 
 static int print_vdd(void)
 {
@@ -469,7 +673,7 @@ static int print_vdd(void)
        ret = find_ir_chip_on_i2c();
        if (ret < 0) {
                printf("VID: Could not find voltage regulator on I2C.\n");
-               return -1;
+               goto exit;
        } else {
                i2caddress = ret;
                debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
@@ -481,11 +685,14 @@ static int print_vdd(void)
        vdd_last = read_voltage(i2caddress);
        if (vdd_last < 0) {
                printf("VID: Couldn't read sensor abort VID adjustment\n");
-               return -1;
+               goto exit;
        }
        printf("VID: Core voltage is at %d mV\n", vdd_last);
+exit:
+       i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
+
+       return ret < 0 ? -1 : 0;
 
-       return 0;
 }
 
 static int do_vdd_override(cmd_tbl_t *cmdtp,