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>
This commit is contained in:
parent
27f133bbcf
commit
29ca713cc1
@ -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];
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user