global: Migrate CONFIG_SYS_FSL* symbols to the CFG_SYS namespace
[platform/kernel/u-boot.git] / board / freescale / common / vid.c
index bf8a5d8..5ec3f2a 100644 (file)
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2014 Freescale Semiconductor, Inc.
+ * Copyright 2020-21 NXP
+ * Copyright 2020 Stephen Carlson <stcarlso@linux.microsoft.com>
  */
 
 #include <common.h>
 #include <asm/immap_85xx.h>
 #endif
 #include <linux/delay.h>
+#include "i2c_common.h"
 #include "vid.h"
 
+#ifndef I2C_VOL_MONITOR_BUS
+#define I2C_VOL_MONITOR_BUS                    0
+#endif
+
+/* Voltages are generally handled in mV to keep them as integers */
+#define MV_PER_V 1000
+
+/*
+ * Select the channel on the I2C mux (on some NXP boards) that contains
+ * the voltage regulator to use for VID. Return 0 for success or nonzero
+ * for failure.
+ */
 int __weak i2c_multiplexer_select_vid_channel(u8 channel)
 {
        return 0;
 }
 
 /*
- * Compensate for a board specific voltage drop between regulator and SoC
- * return a value in mV
+ * Compensate for a board specific voltage drop between regulator and SoC.
+ * Returns the voltage offset in mV.
  */
 int __weak board_vdd_drop_compensation(void)
 {
@@ -35,13 +50,56 @@ int __weak board_vdd_drop_compensation(void)
 }
 
 /*
- * Board specific settings for specific voltage value
+ * Performs any board specific adjustments after the VID voltage has been
+ * set. Return 0 for success or nonzero for failure.
  */
 int __weak board_adjust_vdd(int vdd)
 {
        return 0;
 }
 
+/*
+ * Processor specific method of converting the fuse value read from VID
+ * registers into the core voltage to supply. Return the voltage in mV.
+ */
+u16 __weak soc_get_fuse_vid(int vid_index)
+{
+       /* Default VDD for Layerscape Chassis 1 devices */
+       static const u16 vdd[32] = {
+               0,      /* unused */
+               9875,   /* 0.9875V */
+               9750,
+               9625,
+               9500,
+               9375,
+               9250,
+               9125,
+               9000,
+               8875,
+               8750,
+               8625,
+               8500,
+               8375,
+               8250,
+               8125,
+               10000,  /* 1.0000V */
+               10125,
+               10250,
+               10375,
+               10500,
+               10625,
+               10750,
+               10875,
+               11000,
+               0,      /* reserved */
+       };
+       return vdd[vid_index];
+}
+
+#ifndef I2C_VOL_MONITOR_ADDR
+#define I2C_VOL_MONITOR_ADDR                    0
+#endif
+
 #if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
        defined(CONFIG_VOL_MONITOR_IR36021_READ)
 /*
@@ -59,30 +117,22 @@ int __weak board_adjust_vdd(int vdd)
  */
 static int find_ir_chip_on_i2c(void)
 {
-       int i2caddress;
-       int ret;
-       u8 byte;
-       int i;
+       int i2caddress, ret, i;
+       u8 mfrID;
        const int ir_i2c_addr[] = {0x38, 0x08, 0x09};
-#ifdef CONFIG_DM_I2C
-       struct udevice *dev;
-#endif
+       DEVICE_HANDLE_T dev;
 
        /* Check all the address */
        for (i = 0; i < (sizeof(ir_i2c_addr)/sizeof(ir_i2c_addr[0])); i++) {
                i2caddress = ir_i2c_addr[i];
-#ifndef CONFIG_DM_I2C
-               ret = i2c_read(i2caddress,
-                              IR36021_MFR_ID_OFFSET, 1, (void *)&byte,
-                              sizeof(byte));
-#else
-               ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
-               if (!ret)
-                       ret = dm_i2c_read(dev, IR36021_MFR_ID_OFFSET,
-                                         (void *)&byte, sizeof(byte));
-#endif
-               if ((ret >= 0) && (byte == IR36021_MFR_ID))
-                       return i2caddress;
+               ret = fsl_i2c_get_device(i2caddress, I2C_VOL_MONITOR_BUS, &dev);
+               if (!ret) {
+                       ret = I2C_READ(dev, IR36021_MFR_ID_OFFSET,
+                                      (void *)&mfrID, sizeof(mfrID));
+                       /* If manufacturer ID matches the IR36021 */
+                       if (!ret && mfrID == IR36021_MFR_ID)
+                               return i2caddress;
+               }
        }
        return -1;
 }
@@ -116,35 +166,33 @@ static int read_voltage_from_INA220(int i2caddress)
        int i, ret, voltage_read = 0;
        u16 vol_mon;
        u8 buf[2];
-#ifdef CONFIG_DM_I2C
-       struct udevice *dev;
-#endif
+       DEVICE_HANDLE_T dev;
+
+       /* Open device handle */
+       ret = fsl_i2c_get_device(i2caddress, I2C_VOL_MONITOR_BUS, &dev);
+       if (ret)
+               return ret;
 
        for (i = 0; i < NUM_READINGS; i++) {
-#ifndef CONFIG_DM_I2C
-               ret = i2c_read(I2C_VOL_MONITOR_ADDR,
-                              I2C_VOL_MONITOR_BUS_V_OFFSET, 1,
-                              (void *)&buf, 2);
-#else
-               ret = i2c_get_chip_for_busnum(0, I2C_VOL_MONITOR_ADDR, 1, &dev);
-               if (!ret)
-                       ret = dm_i2c_read(dev, I2C_VOL_MONITOR_BUS_V_OFFSET,
-                                         (void *)&buf, 2);
-#endif
+               ret = I2C_READ(dev, I2C_VOL_MONITOR_BUS_V_OFFSET,
+                              (void *)&buf[0], sizeof(buf));
                if (ret) {
                        printf("VID: failed to read core voltage\n");
                        return ret;
                }
+
                vol_mon = (buf[0] << 8) | buf[1];
                if (vol_mon & I2C_VOL_MONITOR_BUS_V_OVF) {
                        printf("VID: Core voltage sensor error\n");
                        return -1;
                }
+
                debug("VID: bus voltage reads 0x%04x\n", vol_mon);
                /* LSB = 4mv */
                voltage_read += (vol_mon >> I2C_VOL_MONITOR_BUS_V_SHIFT) * 4;
                udelay(WAIT_FOR_ADC);
        }
+
        /* calculate the average */
        voltage_read /= NUM_READINGS;
 
@@ -152,30 +200,25 @@ static int read_voltage_from_INA220(int i2caddress)
 }
 #endif
 
-/* read voltage from IR */
 #ifdef CONFIG_VOL_MONITOR_IR36021_READ
+/* read voltage from IR */
 static int read_voltage_from_IR(int i2caddress)
 {
        int i, ret, voltage_read = 0;
        u16 vol_mon;
        u8 buf;
-#ifdef CONFIG_DM_I2C
-       struct udevice *dev;
-#endif
+       DEVICE_HANDLE_T dev;
+
+       /* Open device handle */
+       ret = fsl_i2c_get_device(i2caddress, I2C_VOL_MONITOR_BUS, &dev);
+       if (ret)
+               return ret;
 
        for (i = 0; i < NUM_READINGS; i++) {
-#ifndef CONFIG_DM_I2C
-               ret = i2c_read(i2caddress,
-                              IR36021_LOOP1_VOUT_OFFSET,
-                              1, (void *)&buf, 1);
-#else
-               ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
-               if (!ret)
-                       ret = dm_i2c_read(dev, IR36021_LOOP1_VOUT_OFFSET,
-                                         (void *)&buf, 1);
-#endif
+               ret = I2C_READ(dev, IR36021_LOOP1_VOUT_OFFSET, (void *)&buf,
+                              sizeof(buf));
                if (ret) {
-                       printf("VID: failed to read vcpu\n");
+                       printf("VID: failed to read core voltage\n");
                        return ret;
                }
                vol_mon = buf;
@@ -187,7 +230,7 @@ static int read_voltage_from_IR(int i2caddress)
                /* Resolution is 1/128V. We scale up here to get 1/128mV
                 * and divide at the end
                 */
-               voltage_read += vol_mon * 1000;
+               voltage_read += vol_mon * MV_PER_V;
                udelay(WAIT_FOR_ADC);
        }
        /* Scale down to the real mV as IR resolution is 1/128V, rounding up */
@@ -205,49 +248,94 @@ 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;
+#if defined(CONFIG_VOL_MONITOR_ISL68233_READ) || \
+       defined(CONFIG_VOL_MONITOR_LTC3882_READ) || \
+       defined(CONFIG_VOL_MONITOR_ISL68233_SET) || \
+       defined(CONFIG_VOL_MONITOR_LTC3882_SET)
 
-#ifndef CONFIG_DM_I2C
-       /* select the PAGE 0 using PMBus commands PAGE for VDD*/
-       ret = i2c_write(I2C_VOL_MONITOR_ADDR,
-                       PMBUS_CMD_PAGE, 1, &chan, 1);
-#else
-       struct udevice *dev;
+/*
+ * The message displayed if the VOUT exponent causes a resolution
+ * worse than 1.0 V (if exponent is >= 0).
+ */
+#define VOUT_WARNING "VID: VOUT_MODE exponent has resolution worse than 1 V!\n"
 
-       ret = i2c_get_chip_for_busnum(0, I2C_VOL_MONITOR_ADDR, 1, &dev);
-       if (!ret)
-               ret = dm_i2c_write(dev, PMBUS_CMD_PAGE, &chan, 1);
-#endif
+/* Checks the PMBus voltage monitor for the format used for voltage values */
+static int get_pmbus_multiplier(DEVICE_HANDLE_T dev)
+{
+       u8 mode;
+       int exponent, multiplier, ret;
+
+       ret = I2C_READ(dev, PMBUS_CMD_VOUT_MODE, &mode, sizeof(mode));
        if (ret) {
-               printf("VID: failed to select VDD Page 0\n");
+               printf("VID: unable to determine voltage multiplier\n");
+               return 1;
+       }
+
+       /* 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! */
+                       printf(VOUT_WARNING);
+                       multiplier = 1;
+               }
+               break;
+       case 1:
+               /* VID code identifier */
+               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;
+}
+#endif
+
+#if defined(CONFIG_VOL_MONITOR_ISL68233_READ) || \
+       defined(CONFIG_VOL_MONITOR_LTC3882_READ)
+static int read_voltage_from_pmbus(int i2caddress)
+{
+       int ret, multiplier, vout;
+       u8 channel = PWM_CHANNEL0;
+       u16 vcode;
+       DEVICE_HANDLE_T dev;
+
+       /* Open device handle */
+       ret = fsl_i2c_get_device(i2caddress, I2C_VOL_MONITOR_BUS, &dev);
+       if (ret)
                return ret;
-       }
 
-#ifndef CONFIG_DM_I2C
-       /*read the output voltage using PMBus command READ_VOUT*/
-       ret = i2c_read(I2C_VOL_MONITOR_ADDR,
-                      PMBUS_CMD_READ_VOUT, 1, (void *)&vcode, 2);
-#else
-       ret = dm_i2c_read(dev, PMBUS_CMD_READ_VOUT, (void *)&vcode, 2);
+       /* Select the right page */
+       ret = I2C_WRITE(dev, PMBUS_CMD_PAGE, &channel, sizeof(channel));
        if (ret) {
-               printf("VID: failed to read the volatge\n");
+               printf("VID: failed to select VDD page %d\n", channel);
                return ret;
        }
-#endif
+
+       /* VOUT is little endian */
+       ret = I2C_READ(dev, PMBUS_CMD_READ_VOUT, (void *)&vcode, sizeof(vcode));
        if (ret) {
-               printf("VID: failed to read the volatge\n");
+               printf("VID: failed to read core voltage\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;
+       /* 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);
+       return vout - board_vdd_drop_compensation();
 }
 #endif
 
@@ -255,13 +343,14 @@ static int read_voltage(int i2caddress)
 {
        int voltage_read;
 #ifdef CONFIG_VOL_MONITOR_INA220
-       voltage_read = read_voltage_from_INA220(i2caddress);
+       voltage_read = read_voltage_from_INA220(I2C_VOL_MONITOR_ADDR);
 #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);
+#elif defined(CONFIG_VOL_MONITOR_ISL68233_READ) || \
+         defined(CONFIG_VOL_MONITOR_LTC3882_READ)
+       voltage_read = read_voltage_from_pmbus(i2caddress);
 #else
-       return -1;
+       voltage_read = -1;
 #endif
        return voltage_read;
 }
@@ -299,7 +388,7 @@ static int wait_for_new_voltage(int vdd, int i2caddress)
 }
 
 /*
- * this function keeps reading the voltage until it is stable or until the
+ * Blocks and reads the VID voltage until it stabilizes, or the
  * timeout expires
  */
 static int wait_for_voltage_stable(int i2caddress)
@@ -309,9 +398,9 @@ static int wait_for_voltage_stable(int i2caddress)
        vdd = read_voltage(i2caddress);
        udelay(NUM_READINGS * WAIT_FOR_ADC);
 
-       /* wait until voltage is stable */
        vdd_current = read_voltage(i2caddress);
-       /* The maximum timeout is
+       /*
+        * The maximum timeout is
         * MAX_LOOP_WAIT_VOL_STABLE * NUM_READINGS * WAIT_FOR_ADC
         */
        for (timeout = MAX_LOOP_WAIT_VOL_STABLE;
@@ -326,12 +415,18 @@ static int wait_for_voltage_stable(int i2caddress)
        return vdd_current;
 }
 
-/* Set the voltage to the IR chip */
+/* Sets the VID voltage using the IR36021 */
 static int set_voltage_to_IR(int i2caddress, int vdd)
 {
        int wait, vdd_last;
        int ret;
        u8 vid;
+       DEVICE_HANDLE_T dev;
+
+       /* Open device handle */
+       ret = fsl_i2c_get_device(i2caddress, I2C_VOL_MONITOR_BUS, &dev);
+       if (ret)
+               return ret;
 
        /* Compensate for a board specific voltage drop between regulator and
         * SoC before converting into an IR VID value
@@ -343,20 +438,10 @@ static int set_voltage_to_IR(int i2caddress, int vdd)
        vid = DIV_ROUND_UP(vdd - 245, 5);
 #endif
 
-#ifndef CONFIG_DM_I2C
-       ret = i2c_write(i2caddress, IR36021_LOOP1_MANUAL_ID_OFFSET,
-                       1, (void *)&vid, sizeof(vid));
-#else
-       struct udevice *dev;
-
-       ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
-       if (!ret)
-               ret = dm_i2c_write(dev, IR36021_LOOP1_MANUAL_ID_OFFSET,
-                                  (void *)&vid, sizeof(vid));
-
-#endif
+       ret = I2C_WRITE(dev, IR36021_LOOP1_MANUAL_ID_OFFSET, (void *)&vid,
+                       sizeof(vid));
        if (ret) {
-               printf("VID: failed to write VID\n");
+               printf("VID: failed to write new voltage\n");
                return -1;
        }
        wait = wait_for_new_voltage(vdd, i2caddress);
@@ -370,45 +455,59 @@ 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)
+#if defined(CONFIG_VOL_MONITOR_ISL68233_SET) || \
+       defined(CONFIG_VOL_MONITOR_LTC3882_SET)
+static int set_voltage_to_pmbus(int i2caddress, int vdd)
 {
        int ret, vdd_last, vdd_target = vdd;
-       int count = 100, temp = 0;
+       int count = MAX_LOOP_WAIT_NEW_VOL, temp = 0, multiplier;
+       unsigned char value;
 
-       /* Scale up to the LTC resolution is 1/4096V */
-       vdd = (vdd * 4096) / 1000;
+       /* The data to be sent with the PMBus command PAGE_PLUS_WRITE */
+       u8 buffer[5] = { 0x04, PWM_CHANNEL0, PMBUS_CMD_VOUT_COMMAND, 0, 0 };
+       DEVICE_HANDLE_T dev;
 
-       /* 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};
+       /* Open device handle */
+       ret = fsl_i2c_get_device(i2caddress, I2C_VOL_MONITOR_BUS, &dev);
+       if (ret)
+               return ret;
 
-       /* Write the desired voltage code to the regulator */
-#ifndef CONFIG_DM_I2C
-       ret = i2c_write(I2C_VOL_MONITOR_ADDR,
-                       PMBUS_CMD_PAGE_PLUS_WRITE, 1, (void *)&buff, 5);
-#else
-       struct udevice *dev;
+       /* Scale up to the proper value for the VOUT command, little endian */
+       multiplier = get_pmbus_multiplier(dev);
+       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;
+
+       /* Check write protect state */
+       ret = I2C_READ(dev, PMBUS_CMD_WRITE_PROTECT, (void *)&value,
+                      sizeof(value));
+       if (ret)
+               goto exit;
 
-       ret = i2c_get_chip_for_busnum(0, I2C_VOL_MONITOR_ADDR, 1, &dev);
-       if (!ret)
-               ret = dm_i2c_write(dev, PMBUS_CMD_PAGE_PLUS_WRITE,
-                                  (void *)&buff, 5);
-#endif
+       if (value != EN_WRITE_ALL_CMD) {
+               value = EN_WRITE_ALL_CMD;
+               ret = I2C_WRITE(dev, PMBUS_CMD_WRITE_PROTECT,
+                               (void *)&value, sizeof(value));
+               if (ret)
+                       goto exit;
+       }
+
+       /* Write the desired voltage code to the regulator */
+       ret = I2C_WRITE(dev, PMBUS_CMD_PAGE_PLUS_WRITE, (void *)&buffer[0],
+                       sizeof(buffer));
        if (ret) {
-               printf("VID: I2C failed to write to the volatge regulator\n");
+               printf("VID: I2C failed to write to the voltage regulator\n");
                return -1;
        }
 
-       /* Wait for the volatge to get to the desired value */
+exit:
+       /* Wait for the voltage to get to the desired value */
        do {
-               vdd_last = read_voltage_from_LTC(i2caddress);
+               vdd_last = read_voltage_from_pmbus(i2caddress);
                if (vdd_last < 0) {
                        printf("VID: Couldn't read sensor abort VID adjust\n");
                        return -1;
@@ -427,325 +526,80 @@ 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);
+#elif defined(CONFIG_VOL_MONITOR_ISL68233_SET) || \
+         defined(CONFIG_VOL_MONITOR_LTC3882_SET)
+       vdd_last = set_voltage_to_pmbus(i2caddress, vdd);
 #else
        #error Specific voltage monitor must be defined
 #endif
        return vdd_last;
 }
 
-#ifdef CONFIG_FSL_LSCH3
 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;
+#if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3)
+       struct ccsr_gur *gur = (void *)(CFG_SYS_FSL_GUTS_ADDR);
 #else
-       u8 vid;
+       ccsr_gur_t __iomem *gur =
+               (void __iomem *)(CFG_SYS_MPC85xx_GUTS_ADDR);
 #endif
-       int vdd_target, vdd_current, vdd_last;
-       int ret, i2caddress;
+       u8 vid;
+       u32 fusesr;
+       int vdd_current, vdd_last, vdd_target;
+       int ret, i2caddress = I2C_VOL_MONITOR_ADDR;
        unsigned long vdd_string_override;
        char *vdd_string;
-#ifdef CONFIG_ARCH_LX2160A
-       static const u16 vdd[32] = {
-               8250,
-               7875,
-               7750,
-               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 */
-               8000,
-               8125,
-               8250,
-               0,      /* reserved */
-               8500,
-               0,      /* reserved */
-               0,      /* reserved */
-               0,      /* reserved */
-               0,      /* reserved */
-               0,      /* reserved */
-               0,      /* reserved */
-               0,      /* reserved */
-               0,      /* reserved */
-               0,      /* reserved */
-               0,      /* reserved */
-               0,      /* reserved */
-       };
-#else
-#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 */
-               9000,      /* 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
-#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;
-       }
 #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");
-               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*/
-#ifndef CONFIG_DM_I2C
-       ret = i2c_read(i2caddress,
-                      IR36021_INTEL_MODE_OOFSET,
-                      1, (void *)&buf, 1);
-#else
-       struct udevice *dev;
-
-       ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
-       if (!ret)
-               ret = dm_i2c_read(dev, IR36021_INTEL_MODE_OOFSET,
-                                 (void *)&buf, 1);
-#endif
-       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;
-       }
+       u8 buf;
+       DEVICE_HANDLE_T dev;
 #endif
 
-       /* get the voltage ID from fuse status register */
+       /*
+        * VID is used according to the table below
+        *                ---------------------------------------
+        *                |                DA_V                 |
+        *                |-------------------------------------|
+        *                | 5b00000 | 5b00001-5b11110 | 5b11111 |
+        * ---------------+---------+-----------------+---------|
+        * | D | 5b00000  | NO VID  | VID = DA_V      | NO VID  |
+        * | A |----------+---------+-----------------+---------|
+        * | _ | 5b00001  |VID =    | VID =           |VID =    |
+        * | V |   ~      | DA_V_ALT|   DA_V_ALT      | DA_A_VLT|
+        * | _ | 5b11110  |         |                 |         |
+        * | A |----------+---------+-----------------+---------|
+        * | L | 5b11111  | No VID  | VID = DA_V      | NO VID  |
+        * | T |          |         |                 |         |
+        * ------------------------------------------------------
+        */
+#if defined(CONFIG_FSL_LSCH3)
        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)) {
+              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);
+                      FSL_CHASSIS3_DCFG_FUSESR_VID_MASK;
        }
-
-       /*
-        * 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;
+#elif defined(CONFIG_FSL_LSCH2)
+       fusesr = in_be32(&gur->dcfg_fusesr);
+       vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_ALTVID_SHIFT) &
+              FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK;
+       if (vid == 0 || vid == FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK) {
+               vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_VID_SHIFT) &
+                      FSL_CHASSIS2_DCFG_FUSESR_VID_MASK;
        }
-       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
-         * 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);
+       fusesr = in_be32(&gur->dcfg_fusesr);
+       vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_ALTVID_SHIFT) &
+              FSL_CORENET_DCFG_FUSESR_ALTVID_MASK;
+       if (vid == 0 || vid == FSL_CORENET_DCFG_FUSESR_ALTVID_MASK) {
+               vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_VID_SHIFT) &
+                      FSL_CORENET_DCFG_FUSESR_VID_MASK;
        }
-
 #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);
-       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 =
-               (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
-#endif
-       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] = {
-               0,      /* unused */
-               9875,   /* 0.9875V */
-               9750,
-               9625,
-               9500,
-               9375,
-               9250,
-               9125,
-               9000,
-               8875,
-               8750,
-               8625,
-               8500,
-               8375,
-               8250,
-               8125,
-               10000,  /* 1.0000V */
-               10125,
-               10250,
-               10375,
-               10500,
-               10625,
-               10750,
-               10875,
-               11000,
-               0,      /* reserved */
-       };
-       struct vdd_drive {
-               u8 vid;
-               unsigned voltage;
-       };
+       vdd_target = soc_get_fuse_vid((int)vid);
 
        ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
        if (ret) {
@@ -753,6 +607,7 @@ 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();
@@ -765,19 +620,13 @@ int adjust_vdd(ulong vdd_override)
                debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
        }
 
-       /* check IR chip work on Intel mode*/
-#ifndef CONFIG_DM_I2C
-       ret = i2c_read(i2caddress,
-                      IR36021_INTEL_MODE_OOFSET,
-                      1, (void *)&buf, 1);
-#else
-       struct udevice *dev;
+       ret = fsl_i2c_get_device(i2caddress, I2C_VOL_MONITOR_BUS, &dev);
+       if (ret)
+               return ret;
 
-       ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
-       if (!ret)
-               ret = dm_i2c_read(dev, IR36021_INTEL_MODE_OOFSET,
-                                 (void *)&buf, 1);
-#endif
+       /* check IR chip work on Intel mode */
+       ret = I2C_READ(dev, IR36021_INTEL_MODE_OFFSET, (void *)&buf,
+                      sizeof(buf));
        if (ret) {
                printf("VID: failed to read IR chip mode.\n");
                ret = -1;
@@ -790,52 +639,18 @@ int adjust_vdd(ulong vdd_override)
        }
 #endif
 
-       /* get the voltage ID from fuse status register */
-       fusesr = in_be32(&gur->dcfg_fusesr);
-       /*
-        * VID is used according to the table below
-        *                ---------------------------------------
-        *                |                DA_V                 |
-        *                |-------------------------------------|
-        *                | 5b00000 | 5b00001-5b11110 | 5b11111 |
-        * ---------------+---------+-----------------+---------|
-        * | D | 5b00000  | NO VID  | VID = DA_V      | NO VID  |
-        * | A |----------+---------+-----------------+---------|
-        * | _ | 5b00001  |VID =    | VID =           |VID =    |
-        * | V |   ~      | DA_V_ALT|   DA_V_ALT      | DA_A_VLT|
-        * | _ | 5b11110  |         |                 |         |
-        * | A |----------+---------+-----------------+---------|
-        * | L | 5b11111  | No VID  | VID = DA_V      | NO VID  |
-        * | T |          |         |                 |         |
-        * ------------------------------------------------------
-        */
-#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)) {
-               vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_VID_SHIFT) &
-                       FSL_CHASSIS2_DCFG_FUSESR_VID_MASK;
-       }
-#else
-       vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_ALTVID_SHIFT) &
-               FSL_CORENET_DCFG_FUSESR_ALTVID_MASK;
-       if ((vid == 0) || (vid == FSL_CORENET_DCFG_FUSESR_ALTVID_MASK)) {
-               vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_VID_SHIFT) &
-                       FSL_CORENET_DCFG_FUSESR_VID_MASK;
-       }
-#endif
-       vdd_target = vdd[vid];
-
        /* check override variable for overriding VDD */
        vdd_string = env_get(CONFIG_VID_FLS_ENV);
+       debug("VID: Initial VDD value is %d mV\n",
+             DIV_ROUND_UP(vdd_target, 10));
        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);
+               debug("VID: VDD override is %lu\n", vdd_override);
        } else if (vdd_override != 0) {
-               printf("Invalid value.\n");
+               printf("VID: Invalid VDD value.\n");
        }
        if (vdd_target == 0) {
                debug("VID: VID not used\n");
@@ -858,6 +673,13 @@ int adjust_vdd(ulong vdd_override)
        }
        vdd_current = vdd_last;
        debug("VID: Core voltage is currently at %d mV\n", vdd_last);
+
+#if defined(CONFIG_VOL_MONITOR_LTC3882_SET) || \
+       defined(CONFIG_VOL_MONITOR_ISL68233_SET)
+       /* Set the target voltage */
+       vdd_current = set_voltage(i2caddress, vdd_target);
+       vdd_last = vdd_current;
+#else
        /*
          * Adjust voltage to at or one step above target.
          * As measurements are less precise than setting the values
@@ -874,6 +696,13 @@ int adjust_vdd(ulong vdd_override)
                vdd_current -= IR_VDD_STEP_DOWN;
                vdd_last = set_voltage(i2caddress, vdd_current);
        }
+#endif
+
+       /* Board specific adjustments */
+       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",
@@ -888,11 +717,10 @@ exit:
 
        return ret;
 }
-#endif
 
 static int print_vdd(void)
 {
-       int vdd_last, ret, i2caddress = 0;
+       int vdd_last, ret, i2caddress = I2C_VOL_MONITOR_ADDR;
 
        ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
        if (ret) {
@@ -924,7 +752,6 @@ exit:
        i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
 
        return ret < 0 ? -1 : 0;
-
 }
 
 static int do_vdd_override(struct cmd_tbl *cmdtp,
@@ -932,13 +759,16 @@ static int do_vdd_override(struct cmd_tbl *cmdtp,
                           char *const argv[])
 {
        ulong override;
+       int ret = 0;
 
        if (argc < 2)
                return CMD_RET_USAGE;
 
-       if (!strict_strtoul(argv[1], 10, &override))
-               adjust_vdd(override);   /* the value is checked by callee */
-       else
+       if (!strict_strtoul(argv[1], 10, &override)) {
+               ret = adjust_vdd(override);
+               if (ret < 0)
+                       return CMD_RET_FAILURE;
+       } else
                return CMD_RET_USAGE;
        return 0;
 }