diff options
Diffstat (limited to 'board/freescale/common')
-rw-r--r-- | board/freescale/common/Kconfig | 16 | ||||
-rw-r--r-- | board/freescale/common/Makefile | 2 | ||||
-rw-r--r-- | board/freescale/common/qixis.c | 22 | ||||
-rw-r--r-- | board/freescale/common/vid.c | 147 |
4 files changed, 185 insertions, 2 deletions
diff --git a/board/freescale/common/Kconfig b/board/freescale/common/Kconfig index 280f7d46b8..8b89c10aba 100644 --- a/board/freescale/common/Kconfig +++ b/board/freescale/common/Kconfig @@ -20,3 +20,19 @@ config CMD_ESBC_VALIDATE esbc_validate - validate signature using RSA verification esbc_halt - put the core in spin loop (Secure Boot Only) + +config VOL_MONITOR_LTC3882_READ + depends on VID + bool "Enable the LTC3882 voltage monitor read" + default n + help + This option enables LTC3882 voltage monitor read + functionality. It is used by common VID driver. + +config VOL_MONITOR_LTC3882_SET + depends on VID + bool "Enable the LTC3882 voltage monitor set" + default n + help + This option enables LTC3882 voltage monitor set + functionality. It is used by common VID driver. diff --git a/board/freescale/common/Makefile b/board/freescale/common/Makefile index e13cb2063c..939e9c66a5 100644 --- a/board/freescale/common/Makefile +++ b/board/freescale/common/Makefile @@ -23,8 +23,8 @@ obj-$(CONFIG_FMAN_ENET) += fman.o obj-$(CONFIG_FSL_PIXIS) += pixis.o ifndef CONFIG_SPL_BUILD obj-$(CONFIG_FSL_NGPIXIS) += ngpixis.o -obj-$(CONFIG_VID) += vid.o endif +obj-$(CONFIG_VID) += vid.o obj-$(CONFIG_FSL_QIXIS) += qixis.o obj-$(CONFIG_PQ_MDS_PIB) += pq-mds-pib.o ifndef CONFIG_SPL_BUILD diff --git a/board/freescale/common/qixis.c b/board/freescale/common/qixis.c index 24459f8635..844c00a9e3 100644 --- a/board/freescale/common/qixis.c +++ b/board/freescale/common/qixis.c @@ -235,6 +235,28 @@ static int qixis_reset_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const ar #else printf("Not implemented\n"); #endif + } else if (strcmp(argv[1], "ifc") == 0) { +#ifdef QIXIS_LBMAP_IFC + QIXIS_WRITE(rst_ctl, 0x30); + QIXIS_WRITE(rcfg_ctl, 0); + set_lbmap(QIXIS_LBMAP_IFC); + set_rcw_src(QIXIS_RCW_SRC_IFC); + QIXIS_WRITE(rcfg_ctl, 0x20); + QIXIS_WRITE(rcfg_ctl, 0x21); +#else + printf("Not implemented\n"); +#endif + } else if (strcmp(argv[1], "emmc") == 0) { +#ifdef QIXIS_LBMAP_EMMC + QIXIS_WRITE(rst_ctl, 0x30); + QIXIS_WRITE(rcfg_ctl, 0); + set_lbmap(QIXIS_LBMAP_EMMC); + set_rcw_src(QIXIS_RCW_SRC_EMMC); + QIXIS_WRITE(rcfg_ctl, 0x20); + QIXIS_WRITE(rcfg_ctl, 0x21); +#else + printf("Not implemented\n"); +#endif } else if (strcmp(argv[1], "sd_qspi") == 0) { #ifdef QIXIS_LBMAP_SD_QSPI QIXIS_WRITE(rst_ctl, 0x30); diff --git a/board/freescale/common/vid.c b/board/freescale/common/vid.c index d6d1bfc861..a9451c5c6e 100644 --- a/board/freescale/common/vid.c +++ b/board/freescale/common/vid.c @@ -34,6 +34,16 @@ int __weak board_vdd_drop_compensation(void) } /* + * Board specific settings for specific voltage value + */ +int __weak board_adjust_vdd(int vdd) +{ + return 0; +} + +#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \ + defined(CONFIG_VOL_MONITOR_IR36021_READ) +/* * Get the i2c address configuration for the IR regulator chip * * There are some variance in the RDB HW regarding the I2C address configuration @@ -65,6 +75,7 @@ static int find_ir_chip_on_i2c(void) } return -1; } +#endif /* Maximum loop count waiting for new voltage to take effect */ #define MAX_LOOP_WAIT_NEW_VOL 100 @@ -163,6 +174,36 @@ static int read_voltage_from_IR(int i2caddress) } #endif +#ifdef CONFIG_VOL_MONITOR_LTC3882_READ +/* read the current value of the LTC Regulator Voltage */ +static int read_voltage_from_LTC(int i2caddress) +{ + int ret, vcode = 0; + u8 chan = PWM_CHANNEL0; + + /* select the PAGE 0 using PMBus commands PAGE for VDD*/ + ret = i2c_write(I2C_VOL_MONITOR_ADDR, + PMBUS_CMD_PAGE, 1, &chan, 1); + if (ret) { + printf("VID: failed to select VDD Page 0\n"); + return ret; + } + + /*read the output voltage using PMBus command READ_VOUT*/ + ret = i2c_read(I2C_VOL_MONITOR_ADDR, + PMBUS_CMD_READ_VOUT, 1, (void *)&vcode, 2); + if (ret) { + printf("VID: failed to read the volatge\n"); + return ret; + } + + /* Scale down to the real mV as LTC resolution is 1/4096V,rounding up */ + vcode = DIV_ROUND_UP(vcode * 1000, 4096); + + return vcode; +} +#endif + static int read_voltage(int i2caddress) { int voltage_read; @@ -170,12 +211,15 @@ static int read_voltage(int i2caddress) voltage_read = read_voltage_from_INA220(i2caddress); #elif defined CONFIG_VOL_MONITOR_IR36021_READ voltage_read = read_voltage_from_IR(i2caddress); +#elif defined CONFIG_VOL_MONITOR_LTC3882_READ + voltage_read = read_voltage_from_LTC(i2caddress); #else return -1; #endif return voltage_read; } +#ifdef CONFIG_VOL_MONITOR_IR36021_SET /* * We need to calculate how long before the voltage stops to drop * or increase. It returns with the loop count. Each loop takes @@ -235,7 +279,6 @@ static int wait_for_voltage_stable(int i2caddress) return vdd_current; } -#ifdef CONFIG_VOL_MONITOR_IR36021_SET /* Set the voltage to the IR chip */ static int set_voltage_to_IR(int i2caddress, int vdd) { @@ -270,6 +313,43 @@ static int set_voltage_to_IR(int i2caddress, int vdd) debug("VID: Current voltage is %d mV\n", vdd_last); return vdd_last; } + +#endif + +#ifdef CONFIG_VOL_MONITOR_LTC3882_SET +/* this function sets the VDD and returns the value set */ +static int set_voltage_to_LTC(int i2caddress, int vdd) +{ + int ret, vdd_last, vdd_target = vdd; + + /* Scale up to the LTC resolution is 1/4096V */ + vdd = (vdd * 4096) / 1000; + + /* 5-byte buffer which needs to be sent following the + * PMBus command PAGE_PLUS_WRITE. + */ + u8 buff[5] = {0x04, PWM_CHANNEL0, PMBUS_CMD_VOUT_COMMAND, + vdd & 0xFF, (vdd & 0xFF00) >> 8}; + + /* Write the desired voltage code to the regulator */ + ret = i2c_write(I2C_VOL_MONITOR_ADDR, + PMBUS_CMD_PAGE_PLUS_WRITE, 1, (void *)&buff, 5); + if (ret) { + printf("VID: I2C failed to write to the volatge regulator\n"); + return -1; + } + + /* Wait for the volatge to get to the desired value */ + do { + vdd_last = read_voltage_from_LTC(i2caddress); + if (vdd_last < 0) { + printf("VID: Couldn't read sensor abort VID adjust\n"); + return -1; + } + } while (vdd_last != vdd_target); + + return vdd_last; +} #endif static int set_voltage(int i2caddress, int vdd) @@ -278,6 +358,8 @@ static int set_voltage(int i2caddress, int vdd) #ifdef CONFIG_VOL_MONITOR_IR36021_SET vdd_last = set_voltage_to_IR(i2caddress, vdd); +#elif defined CONFIG_VOL_MONITOR_LTC3882_SET + vdd_last = set_voltage_to_LTC(i2caddress, vdd); #else #error Specific voltage monitor must be defined #endif @@ -290,11 +372,53 @@ int adjust_vdd(ulong vdd_override) int re_enable = disable_interrupts(); struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); u32 fusesr; +#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \ + defined(CONFIG_VOL_MONITOR_IR36021_READ) u8 vid, buf; +#else + u8 vid; +#endif 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 */ @@ -329,6 +453,7 @@ int adjust_vdd(ulong vdd_override) 0, /* reserved */ 0, /* reserved */ }; +#endif struct vdd_drive { u8 vid; unsigned voltage; @@ -340,6 +465,8 @@ int adjust_vdd(ulong vdd_override) ret = -1; goto exit; } +#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \ + defined(CONFIG_VOL_MONITOR_IR36021_READ) ret = find_ir_chip_on_i2c(); if (ret < 0) { printf("VID: Could not find voltage regulator on I2C.\n"); @@ -364,6 +491,7 @@ int adjust_vdd(ulong vdd_override) ret = -1; goto exit; } +#endif /* get the voltage ID from fuse status register */ fusesr = in_le32(&gur->dcfg_fusesr); @@ -415,6 +543,11 @@ int adjust_vdd(ulong vdd_override) } vdd_current = vdd_last; debug("VID: Core voltage is currently at %d mV\n", vdd_last); + +#ifdef CONFIG_VOL_MONITOR_LTC3882_SET + /* Set the target voltage */ + vdd_last = vdd_current = set_voltage(i2caddress, vdd_target); +#else /* * Adjust voltage to at or one step above target. * As measurements are less precise than setting the values @@ -432,6 +565,12 @@ int adjust_vdd(ulong vdd_override) vdd_last = set_voltage(i2caddress, vdd_current); } +#endif + if (board_adjust_vdd(vdd_target) < 0) { + ret = -1; + goto exit; + } + if (vdd_last > 0) printf("VID: Core voltage after adjustment is at %d mV\n", vdd_last); @@ -498,6 +637,8 @@ int adjust_vdd(ulong vdd_override) ret = -1; goto exit; } +#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \ + defined(CONFIG_VOL_MONITOR_IR36021_READ) ret = find_ir_chip_on_i2c(); if (ret < 0) { printf("VID: Could not find voltage regulator on I2C.\n"); @@ -522,6 +663,7 @@ int adjust_vdd(ulong vdd_override) ret = -1; goto exit; } +#endif /* get the voltage ID from fuse status register */ fusesr = in_be32(&gur->dcfg_fusesr); @@ -632,6 +774,8 @@ static int print_vdd(void) debug("VID : I2c failed to switch channel\n"); return -1; } +#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \ + defined(CONFIG_VOL_MONITOR_IR36021_READ) ret = find_ir_chip_on_i2c(); if (ret < 0) { printf("VID: Could not find voltage regulator on I2C.\n"); @@ -640,6 +784,7 @@ static int print_vdd(void) i2caddress = ret; debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress); } +#endif /* * Read voltage monitor to check real voltage. |