summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPriyanka Jain <priyanka.jain@nxp.com>2017-01-19 05:42:27 (GMT)
committerYork Sun <york.sun@nxp.com>2017-03-14 15:44:03 (GMT)
commit29ca713cc1cfb84b6d1b485859479e81a1479188 (patch)
treedb4a096ef2f3b9c77127449c5475a928fc69417a
parent27f133bbcf2c06b9b74e8694fb08a8cf7249496d (diff)
downloadu-boot-29ca713cc1cfb84b6d1b485859479e81a1479188.tar.xz
armv8: fsl-lsch3: Update VID support
VID support in NXP layerscape Chassis-3 (lsch3) compilant SoCs like LS2088A, LS2080A differs from existing logic. -VDD voltage array is different -Registers are different -VDD calculation logic is different Add new function adjust_vdd() for LSCH3 compliant SoCs Signed-off-by: Priyanka Jain <priyanka.jain@nxp.com> Signed-off-by: Arpit Goel <arpit.goel@nxp.com> Reviewed-by: York Sun <york.sun@nxp.com>
-rw-r--r--arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h4
-rw-r--r--board/freescale/common/vid.c174
2 files changed, 164 insertions, 14 deletions
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h
index 9e6b5e3..08ea8fb 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h
@@ -180,9 +180,9 @@ struct ccsr_gur {
u32 gpporcr3;
u32 gpporcr4;
u8 res_030[0x60-0x30];
-#define FSL_CHASSIS3_DCFG_FUSESR_VID_SHIFT 25
+#define FSL_CHASSIS3_DCFG_FUSESR_VID_SHIFT 2
#define FSL_CHASSIS3_DCFG_FUSESR_VID_MASK 0x1F
-#define FSL_CHASSIS3_DCFG_FUSESR_ALTVID_SHIFT 20
+#define FSL_CHASSIS3_DCFG_FUSESR_ALTVID_SHIFT 7
#define FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK 0x1F
u32 dcfg_fusesr; /* Fuse status register */
u8 res_064[0x70-0x64];
diff --git a/board/freescale/common/vid.c b/board/freescale/common/vid.c
index 1a50304..9b65c13 100644
--- a/board/freescale/common/vid.c
+++ b/board/freescale/common/vid.c
@@ -284,10 +284,170 @@ 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();
-#if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3)
+ 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;
+ 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 */
+ };
+ 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 = getenv(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 =
@@ -364,11 +524,7 @@ int adjust_vdd(ulong vdd_override)
}
/* get the voltage ID from fuse status register */
-#ifdef CONFIG_FSL_LSCH3
- fusesr = in_le32(&gur->dcfg_fusesr);
-#else
fusesr = in_be32(&gur->dcfg_fusesr);
-#endif
/*
* VID is used according to the table below
* ---------------------------------------
@@ -393,13 +549,6 @@ int adjust_vdd(ulong vdd_override)
vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_VID_SHIFT) &
FSL_CHASSIS2_DCFG_FUSESR_VID_MASK;
}
-#elif defined(CONFIG_FSL_LSCH3)
- 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;
- }
#else
vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_ALTVID_SHIFT) &
FSL_CORENET_DCFG_FUSESR_ALTVID_MASK;
@@ -472,6 +621,7 @@ exit:
return ret;
}
+#endif
static int print_vdd(void)
{