summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/Kconfig.nxp4
-rw-r--r--board/nxp/common/vid.c110
-rw-r--r--board/nxp/common/vid.h15
-rw-r--r--board/nxp/ls1088a/ls1088a.c11
4 files changed, 80 insertions, 60 deletions
diff --git a/arch/Kconfig.nxp b/arch/Kconfig.nxp
index ef9087d0197..152692e3230 100644
--- a/arch/Kconfig.nxp
+++ b/arch/Kconfig.nxp
@@ -242,24 +242,28 @@ config VOL_MONITOR_IR36021_SET
config VOL_MONITOR_LTC3882_READ
bool "Enable the LTC3882 voltage monitor read"
+ select PMBUS
help
This option enables LTC3882 voltage monitor read
functionality. It is used by the common VID driver.
config VOL_MONITOR_LTC3882_SET
bool "Enable the LTC3882 voltage monitor set"
+ select PMBUS
help
This option enables LTC3882 voltage monitor set
functionality. It is used by the common VID driver.
config VOL_MONITOR_ISL68233_READ
bool "Enable the ISL68233 voltage monitor read"
+ select PMBUS
help
This option enables ISL68233 voltage monitor read
functionality. It is used by the common VID driver.
config VOL_MONITOR_ISL68233_SET
bool "Enable the ISL68233 voltage monitor set"
+ select PMBUS
help
This option enables ISL68233 voltage monitor set
functionality. It is used by the common VID driver.
diff --git a/board/nxp/common/vid.c b/board/nxp/common/vid.c
index 84cb43fad56..70c3b3ecfd8 100644
--- a/board/nxp/common/vid.c
+++ b/board/nxp/common/vid.c
@@ -11,6 +11,7 @@
#include <i2c.h>
#include <irq_func.h>
#include <log.h>
+#include <pmbus.h>
#include <vsprintf.h>
#include <asm/io.h>
#ifdef CONFIG_FSL_LSCH2
@@ -260,45 +261,38 @@ static int read_voltage_from_IR(int i2caddress)
*/
#define VOUT_WARNING "VID: VOUT_MODE exponent has resolution worse than 1 V!\n"
-/* Checks the PMBus voltage monitor for the format used for voltage values */
-static int get_pmbus_multiplier(DEVICE_HANDLE_T dev)
+/*
+ * Read VOUT_MODE for downstream LINEAR16 decode/encode through the
+ * tree level <pmbus.h> helpers (pmbus_reg2data_linear16,
+ * pmbus_data2reg_linear16). Stores the raw VOUT_MODE byte in *mode
+ * and returns 0 on success, or the negative bus error (a failed read
+ * must not be decoded: raw 0 aliases Linear mode with exponent 0).
+ * Emits VOUT_WARNING on Linear mode chips with a non negative
+ * exponent (resolution >= 1 V is unusable for sub volt SoC rails)
+ * and an informational note on the unsupported VID format.
+ */
+static int vid_read_vout_mode(DEVICE_HANDLE_T dev, u8 *mode)
{
- u8 mode;
- int exponent, multiplier, ret;
+ int ret;
- ret = I2C_READ(dev, PMBUS_CMD_VOUT_MODE, &mode, sizeof(mode));
+ ret = pmbus_read_byte(dev, PMBUS_VOUT_MODE, mode);
if (ret) {
printf("VID: unable to determine voltage multiplier\n");
- return 1;
+ return ret;
}
- /* Upper 3 bits is mode, lower 5 bits is exponent */
- exponent = (int)mode & 0x1F;
- mode >>= 5;
- switch (mode) {
- case 0:
- /* Linear, 5 bit twos component exponent */
- if (exponent & 0x10) {
- multiplier = 1 << (16 - (exponent & 0xF));
- } else {
- /* If exponent is >= 0, then resolution is 1 V! */
+ switch (*mode & PB_VOUT_MODE_MODE_MASK) {
+ case PB_VOUT_MODE_LINEAR:
+ if (!(*mode & 0x10))
printf(VOUT_WARNING);
- multiplier = 1;
- }
break;
- case 1:
- /* VID code identifier */
+ case PB_VOUT_MODE_VID:
printf("VID: custom VID codes are not supported\n");
- multiplier = MV_PER_V;
break;
default:
- /* Direct, in mV */
- multiplier = MV_PER_V;
break;
}
-
- debug("VID: calculated multiplier is %d\n", multiplier);
- return multiplier;
+ return 0;
}
#endif
@@ -306,8 +300,8 @@ static int get_pmbus_multiplier(DEVICE_HANDLE_T dev)
defined(CONFIG_VOL_MONITOR_LTC3882_READ)
static int read_voltage_from_pmbus(int i2caddress)
{
- int ret, multiplier, vout;
- u8 channel = PWM_CHANNEL0;
+ int ret, vout;
+ u8 channel = PWM_CHANNEL0, vout_mode;
u16 vcode;
DEVICE_HANDLE_T dev;
@@ -317,25 +311,33 @@ static int read_voltage_from_pmbus(int i2caddress)
return ret;
/* Select the right page */
- ret = I2C_WRITE(dev, PMBUS_CMD_PAGE, &channel, sizeof(channel));
+ ret = pmbus_write_byte(dev, PMBUS_PAGE, channel);
if (ret) {
printf("VID: failed to select VDD page %d\n", channel);
return ret;
}
- /* VOUT is little endian */
- ret = I2C_READ(dev, PMBUS_CMD_READ_VOUT, (void *)&vcode, sizeof(vcode));
+ ret = pmbus_read_word(dev, PMBUS_READ_VOUT, &vcode);
if (ret) {
printf("VID: failed to read core voltage\n");
return ret;
}
- /* Scale down to the real mV */
- multiplier = get_pmbus_multiplier(dev);
- vout = (int)vcode;
- /* Multiplier 1000 (direct mode) requires no change to convert */
- if (multiplier != MV_PER_V)
- vout = DIV_ROUND_UP(vout * MV_PER_V, multiplier);
+ /*
+ * Decode LINEAR16 via the tree level helper from <pmbus.h>. For
+ * non Linear VOUT_MODE settings the helper returns 0; fall back
+ * to the historic mV pass through so existing LSCH boards keep.
+ */
+ ret = vid_read_vout_mode(dev, &vout_mode);
+ if (ret)
+ return ret;
+ if ((vout_mode & PB_VOUT_MODE_MODE_MASK) == PB_VOUT_MODE_LINEAR) {
+ s64 uv = pmbus_reg2data_linear16(vcode, vout_mode);
+
+ vout = (int)((uv + 500) / 1000); /* round to mV */
+ } else {
+ vout = (int)vcode;
+ }
return vout - board_vdd_drop_compensation();
}
#endif
@@ -463,11 +465,13 @@ static int set_voltage_to_IR(int i2caddress, int vdd)
static int set_voltage_to_pmbus(int i2caddress, int vdd)
{
int ret, vdd_last, vdd_target = vdd;
- int count = MAX_LOOP_WAIT_NEW_VOL, temp = 0, multiplier;
+ int count = MAX_LOOP_WAIT_NEW_VOL, temp = 0;
+ u8 vout_mode;
+ u16 raw;
unsigned char value;
/* The data to be sent with the PMBus command PAGE_PLUS_WRITE */
- u8 buffer[5] = { 0x04, PWM_CHANNEL0, PMBUS_CMD_VOUT_COMMAND, 0, 0 };
+ u8 buffer[5] = { 0x04, PWM_CHANNEL0, PMBUS_VOUT_COMMAND, 0, 0 };
DEVICE_HANDLE_T dev;
/* Open device handle */
@@ -475,24 +479,32 @@ static int set_voltage_to_pmbus(int i2caddress, int vdd)
if (ret)
return ret;
- /* Scale up to the proper value for the VOUT command, little endian */
- multiplier = get_pmbus_multiplier(dev);
+ /*
+ * Encode target mV as LINEAR16 raw via the tree level helper
+ * from <pmbus.h>. For non Linear VOUT_MODE settings the helper
+ * returns 0; fall back to the historic mV pass through. A failed
+ * VOUT_MODE read aborts: never write a voltage code whose
+ * encoding could not be determined.
+ */
vdd += board_vdd_drop_compensation();
- if (multiplier != MV_PER_V)
- vdd = DIV_ROUND_UP(vdd * multiplier, MV_PER_V);
- buffer[3] = vdd & 0xFF;
- buffer[4] = (vdd & 0xFF00) >> 8;
+ ret = vid_read_vout_mode(dev, &vout_mode);
+ if (ret)
+ return ret;
+ if ((vout_mode & PB_VOUT_MODE_MODE_MASK) == PB_VOUT_MODE_LINEAR)
+ raw = pmbus_data2reg_linear16((s64)vdd * 1000LL, vout_mode);
+ else
+ raw = (u16)vdd;
+ buffer[3] = raw & 0xFF;
+ buffer[4] = (raw & 0xFF00) >> 8;
/* Check write protect state */
- ret = I2C_READ(dev, PMBUS_CMD_WRITE_PROTECT, (void *)&value,
- sizeof(value));
+ ret = pmbus_read_byte(dev, PMBUS_WRITE_PROTECT, &value);
if (ret)
goto exit;
if (value != EN_WRITE_ALL_CMD) {
value = EN_WRITE_ALL_CMD;
- ret = I2C_WRITE(dev, PMBUS_CMD_WRITE_PROTECT,
- (void *)&value, sizeof(value));
+ ret = pmbus_write_byte(dev, PMBUS_WRITE_PROTECT, value);
if (ret)
goto exit;
}
diff --git a/board/nxp/common/vid.h b/board/nxp/common/vid.h
index b34c080b4ba..72c1c089aa1 100644
--- a/board/nxp/common/vid.h
+++ b/board/nxp/common/vid.h
@@ -22,8 +22,9 @@
#define IR_VDD_STEP_UP 5
/* LTC3882 */
-#define PMBUS_CMD_WRITE_PROTECT 0x10
/*
+ * PMBUS_WRITE_PROTECT (10h) provided by <pmbus.h>
+ *
* WRITE_PROTECT command supported values
* 0x80: Disable all writes except WRITE_PROTECT, PAGE,
* STORE_USER_ALL and MFR_EE_UNLOCK commands.
@@ -51,12 +52,14 @@
#define VDD_MV_MAX 925
#endif
-/* PM Bus commands code for LTC3882*/
+/*
+ * PM Bus commands code for LTC3882. PMBUS_PAGE / PMBUS_READ_VOUT /
+ * PMBUS_VOUT_MODE / PMBUS_VOUT_COMMAND are provided by <pmbus.h>.
+ * PMBUS_CMD_PAGE_PLUS_WRITE (05h) is the LTC3882 SMBus block write
+ * transaction not in <pmbus.h>'s standard subset, so keep its
+ * definition here.
+ */
#define PWM_CHANNEL0 0x0
-#define PMBUS_CMD_PAGE 0x0
-#define PMBUS_CMD_READ_VOUT 0x8B
-#define PMBUS_CMD_VOUT_MODE 0x20
-#define PMBUS_CMD_VOUT_COMMAND 0x21
#define PMBUS_CMD_PAGE_PLUS_WRITE 0x05
#if defined(CONFIG_TARGET_LX2160AQDS) || defined(CONFIG_TARGET_LX2162AQDS) || \
diff --git a/board/nxp/ls1088a/ls1088a.c b/board/nxp/ls1088a/ls1088a.c
index 1b477e83676..8ea76fe3760 100644
--- a/board/nxp/ls1088a/ls1088a.c
+++ b/board/nxp/ls1088a/ls1088a.c
@@ -7,6 +7,7 @@
#include <display_options.h>
#include <env.h>
#include <i2c.h>
+#include <pmbus.h>
#include <init.h>
#include <log.h>
#include <malloc.h>
@@ -667,13 +668,13 @@ int get_serdes_volt(void)
/* Select the PAGE 0 using PMBus commands PAGE for VDD */
#if !CONFIG_IS_ENABLED(DM_I2C)
ret = i2c_write(I2C_SVDD_MONITOR_ADDR,
- PMBUS_CMD_PAGE, 1, &chan, 1);
+ PMBUS_PAGE, 1, &chan, 1);
#else
struct udevice *dev;
ret = i2c_get_chip_for_busnum(0, I2C_SVDD_MONITOR_ADDR, 1, &dev);
if (!ret)
- ret = dm_i2c_write(dev, PMBUS_CMD_PAGE,
+ ret = dm_i2c_write(dev, PMBUS_PAGE,
&chan, 1);
#endif
@@ -685,9 +686,9 @@ int get_serdes_volt(void)
/* Read the output voltage using PMBus command READ_VOUT */
#if !CONFIG_IS_ENABLED(DM_I2C)
ret = i2c_read(I2C_SVDD_MONITOR_ADDR,
- PMBUS_CMD_READ_VOUT, 1, (void *)&vcode, 2);
+ PMBUS_READ_VOUT, 1, (void *)&vcode, 2);
#else
- dm_i2c_read(dev, PMBUS_CMD_READ_VOUT, (void *)&vcode, 2);
+ dm_i2c_read(dev, PMBUS_READ_VOUT, (void *)&vcode, 2);
#endif
if (ret) {
printf("VID: failed to read the voltage\n");
@@ -700,7 +701,7 @@ int get_serdes_volt(void)
int set_serdes_volt(int svdd)
{
int ret, vdd_last;
- u8 buff[5] = {0x04, PWM_CHANNEL0, PMBUS_CMD_VOUT_COMMAND,
+ u8 buff[5] = {0x04, PWM_CHANNEL0, PMBUS_VOUT_COMMAND,
svdd & 0xFF, (svdd & 0xFF00) >> 8};
/* Write the desired voltage code to the SVDD regulator */