Merge tag 'u-boot-atmel-fixes-2021.01-b' of https://gitlab.denx.de/u-boot/custodians...
[platform/kernel/u-boot.git] / board / freescale / common / vid.c
index 1bd65a8..2617f61 100644 (file)
@@ -1,22 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2014 Freescale Semiconductor, Inc.
- *
- * SPDX-License-Identifier:     GPL-2.0+
+ * Copyright 2020 NXP
  */
 
 #include <common.h>
 #include <command.h>
+#include <env.h>
 #include <i2c.h>
+#include <irq_func.h>
+#include <log.h>
 #include <asm/io.h>
-#ifdef CONFIG_LS1043A
+#ifdef CONFIG_FSL_LSCH2
 #include <asm/arch/immap_lsch2.h>
+#elif defined(CONFIG_FSL_LSCH3)
+#include <asm/arch/immap_lsch3.h>
 #else
 #include <asm/immap_85xx.h>
 #endif
+#include <linux/delay.h>
 #include "vid.h"
 
-DECLARE_GLOBAL_DATA_PTR;
-
 int __weak i2c_multiplexer_select_vid_channel(u8 channel)
 {
        return 0;
@@ -32,6 +36,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
@@ -51,18 +65,29 @@ static int find_ir_chip_on_i2c(void)
        u8 byte;
        int i;
        const int ir_i2c_addr[] = {0x38, 0x08, 0x09};
+#ifdef CONFIG_DM_I2C
+       struct udevice *dev;
+#endif
 
        /* 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;
        }
        return -1;
 }
+#endif
 
 /* Maximum loop count waiting for new voltage to take effect */
 #define MAX_LOOP_WAIT_NEW_VOL          100
@@ -92,11 +117,21 @@ 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
 
        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
                if (ret) {
                        printf("VID: failed to read core voltage\n");
                        return ret;
@@ -125,11 +160,21 @@ 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
 
        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
                if (ret) {
                        printf("VID: failed to read vcpu\n");
                        return ret;
@@ -161,6 +206,52 @@ 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;
+
+#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;
+
+       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
+       if (ret) {
+               printf("VID: failed to select VDD Page 0\n");
+               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);
+       if (ret) {
+               printf("VID: failed to read the volatge\n");
+               return ret;
+       }
+#endif
+       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;
@@ -168,12 +259,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
@@ -233,7 +327,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)
 {
@@ -245,14 +338,24 @@ static int set_voltage_to_IR(int i2caddress, int vdd)
         * SoC before converting into an IR VID value
         */
        vdd += board_vdd_drop_compensation();
-#ifdef CONFIG_LS1043A
+#ifdef CONFIG_FSL_LSCH2
        vid = DIV_ROUND_UP(vdd - 265, 5);
 #else
        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
        if (ret) {
                printf("VID: failed to write VID\n");
                return -1;
@@ -268,6 +371,91 @@ 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;
+       int count = 100, temp = 0;
+       unsigned char value;
+
+       /* 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 */
+#ifndef CONFIG_DM_I2C
+       /* Check write protect state */
+       ret = i2c_read(I2C_VOL_MONITOR_ADDR,
+                      PMBUS_CMD_WRITE_PROTECT, 1,
+                      (void *)&value, sizeof(value));
+       if (ret)
+               goto exit;
+
+       if (value != EN_WRITE_ALL_CMD) {
+               value = EN_WRITE_ALL_CMD;
+               ret = i2c_write(I2C_VOL_MONITOR_ADDR,
+                               PMBUS_CMD_WRITE_PROTECT, 1,
+                               (void *)&value, sizeof(value));
+               if (ret)
+                       goto exit;
+       }
+
+       ret = i2c_write(I2C_VOL_MONITOR_ADDR,
+                       PMBUS_CMD_PAGE_PLUS_WRITE, 1,
+                       (void *)&buff, sizeof(buff));
+#else
+       struct udevice *dev;
+
+       ret = i2c_get_chip_for_busnum(0, I2C_VOL_MONITOR_ADDR, 1, &dev);
+       if (!ret) {
+               /* Check write protect state */
+               ret = dm_i2c_read(dev,
+                                 PMBUS_CMD_WRITE_PROTECT,
+                                 (void *)&value, sizeof(value));
+               if (ret)
+                       goto exit;
+
+               if (value != EN_WRITE_ALL_CMD) {
+                       value = EN_WRITE_ALL_CMD;
+                       ret = dm_i2c_write(dev,
+                                          PMBUS_CMD_WRITE_PROTECT,
+                                          (void *)&value, sizeof(value));
+                       if (ret)
+                               goto exit;
+               }
+
+               ret = dm_i2c_write(dev, PMBUS_CMD_PAGE_PLUS_WRITE,
+                                  (void *)&buff, sizeof(buff));
+       }
+#endif
+exit:
+       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;
+               }
+               count--;
+               temp = vdd_last - vdd_target;
+       } while ((abs(temp) > 2)  && (count > 0));
+
+       return vdd_last;
+}
 #endif
 
 static int set_voltage(int i2caddress, int vdd)
@@ -276,16 +464,282 @@ 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
        return vdd_last;
 }
 
+#ifdef CONFIG_FSL_LSCH3
 int adjust_vdd(ulong vdd_override)
 {
        int re_enable = disable_interrupts();
-#ifdef CONFIG_LS1043A
+       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 = 0;
+       unsigned long vdd_string_override;
+       char *vdd_string;
+#if defined(CONFIG_ARCH_LX2160A) || defined(CONFIG_ARCH_LX2162A)
+       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;
+       }
+#endif
+
+       /* 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 = 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);
+       }
+
+       /*
+        * 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);
+
+#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);
+       }
+
+#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 =
@@ -336,6 +790,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");
@@ -347,9 +803,18 @@ int adjust_vdd(ulong vdd_override)
        }
 
        /* 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;
@@ -360,6 +825,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);
@@ -380,7 +846,7 @@ int adjust_vdd(ulong vdd_override)
         * | T |          |         |                 |         |
         * ------------------------------------------------------
         */
-#ifdef CONFIG_LS1043A
+#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)) {
@@ -398,7 +864,7 @@ int adjust_vdd(ulong vdd_override)
        vdd_target = vdd[vid];
 
        /* check override variable for overriding VDD */
-       vdd_string = getenv(CONFIG_VID_FLS_ENV);
+       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;
@@ -454,26 +920,33 @@ int adjust_vdd(ulong vdd_override)
 exit:
        if (re_enable)
                enable_interrupts();
+
+       i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
+
        return ret;
 }
+#endif
 
 static int print_vdd(void)
 {
-       int vdd_last, ret, i2caddress;
+       int vdd_last, ret, i2caddress = 0;
 
        ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
        if (ret) {
                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");
-               return -1;
+               goto exit;
        } else {
                i2caddress = ret;
                debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
        }
+#endif
 
        /*
         * Read voltage monitor to check real voltage.
@@ -481,16 +954,19 @@ static int print_vdd(void)
        vdd_last = read_voltage(i2caddress);
        if (vdd_last < 0) {
                printf("VID: Couldn't read sensor abort VID adjustment\n");
-               return -1;
+               goto exit;
        }
        printf("VID: Core voltage is at %d mV\n", vdd_last);
+exit:
+       i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
+
+       return ret < 0 ? -1 : 0;
 
-       return 0;
 }
 
-static int do_vdd_override(cmd_tbl_t *cmdtp,
+static int do_vdd_override(struct cmd_tbl *cmdtp,
                           int flag, int argc,
-                          char * const argv[])
+                          char *const argv[])
 {
        ulong override;
 
@@ -504,9 +980,8 @@ static int do_vdd_override(cmd_tbl_t *cmdtp,
        return 0;
 }
 
-static int do_vdd_read(cmd_tbl_t *cmdtp,
-                        int flag, int argc,
-                        char * const argv[])
+static int do_vdd_read(struct cmd_tbl *cmdtp, int flag, int argc,
+                      char *const argv[])
 {
        if (argc < 1)
                return CMD_RET_USAGE;