uboot/board/freescale/common/vid.c
<<
>>
Prefs
   1/*
   2 * Copyright 2014 Freescale Semiconductor, Inc.
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <common.h>
   8#include <command.h>
   9#include <i2c.h>
  10#include <asm/immap_85xx.h>
  11#include "vid.h"
  12
  13DECLARE_GLOBAL_DATA_PTR;
  14
  15int __weak i2c_multiplexer_select_vid_channel(u8 channel)
  16{
  17        return 0;
  18}
  19
  20/*
  21 * Compensate for a board specific voltage drop between regulator and SoC
  22 * return a value in mV
  23 */
  24int __weak board_vdd_drop_compensation(void)
  25{
  26        return 0;
  27}
  28
  29/*
  30 * Get the i2c address configuration for the IR regulator chip
  31 *
  32 * There are some variance in the RDB HW regarding the I2C address configuration
  33 * for the IR regulator chip, which is likely a problem of external resistor
  34 * accuracy. So we just check each address in a hopefully non-intrusive mode
  35 * and use the first one that seems to work
  36 *
  37 * The IR chip can show up under the following addresses:
  38 * 0x08 (Verified on T1040RDB-PA,T4240RDB-PB,X-T4240RDB-16GPA)
  39 * 0x09 (Verified on T1040RDB-PA)
  40 * 0x38 (Verified on T2080QDS, T2081QDS)
  41 */
  42static int find_ir_chip_on_i2c(void)
  43{
  44        int i2caddress;
  45        int ret;
  46        u8 byte;
  47        int i;
  48        const int ir_i2c_addr[] = {0x38, 0x08, 0x09};
  49
  50        /* Check all the address */
  51        for (i = 0; i < (sizeof(ir_i2c_addr)/sizeof(ir_i2c_addr[0])); i++) {
  52                i2caddress = ir_i2c_addr[i];
  53                ret = i2c_read(i2caddress,
  54                               IR36021_MFR_ID_OFFSET, 1, (void *)&byte,
  55                               sizeof(byte));
  56                if ((ret >= 0) && (byte == IR36021_MFR_ID))
  57                        return i2caddress;
  58        }
  59        return -1;
  60}
  61
  62/* Maximum loop count waiting for new voltage to take effect */
  63#define MAX_LOOP_WAIT_NEW_VOL           100
  64/* Maximum loop count waiting for the voltage to be stable */
  65#define MAX_LOOP_WAIT_VOL_STABLE        100
  66/*
  67 * read_voltage from sensor on I2C bus
  68 * We use average of 4 readings, waiting for WAIT_FOR_ADC before
  69 * another reading
  70 */
  71#define NUM_READINGS    4       /* prefer to be power of 2 for efficiency */
  72
  73/* If an INA220 chip is available, we can use it to read back the voltage
  74 * as it may have a higher accuracy than the IR chip for the same purpose
  75 */
  76#ifdef CONFIG_VOL_MONITOR_INA220
  77#define WAIT_FOR_ADC    532     /* wait for 532 microseconds for ADC */
  78#define ADC_MIN_ACCURACY        4
  79#else
  80#define WAIT_FOR_ADC    138     /* wait for 138 microseconds for ADC */
  81#define ADC_MIN_ACCURACY        4
  82#endif
  83
  84#ifdef CONFIG_VOL_MONITOR_INA220
  85static int read_voltage_from_INA220(int i2caddress)
  86{
  87        int i, ret, voltage_read = 0;
  88        u16 vol_mon;
  89        u8 buf[2];
  90
  91        for (i = 0; i < NUM_READINGS; i++) {
  92                ret = i2c_read(I2C_VOL_MONITOR_ADDR,
  93                               I2C_VOL_MONITOR_BUS_V_OFFSET, 1,
  94                               (void *)&buf, 2);
  95                if (ret) {
  96                        printf("VID: failed to read core voltage\n");
  97                        return ret;
  98                }
  99                vol_mon = (buf[0] << 8) | buf[1];
 100                if (vol_mon & I2C_VOL_MONITOR_BUS_V_OVF) {
 101                        printf("VID: Core voltage sensor error\n");
 102                        return -1;
 103                }
 104                debug("VID: bus voltage reads 0x%04x\n", vol_mon);
 105                /* LSB = 4mv */
 106                voltage_read += (vol_mon >> I2C_VOL_MONITOR_BUS_V_SHIFT) * 4;
 107                udelay(WAIT_FOR_ADC);
 108        }
 109        /* calculate the average */
 110        voltage_read /= NUM_READINGS;
 111
 112        return voltage_read;
 113}
 114#endif
 115
 116/* read voltage from IR */
 117#ifdef CONFIG_VOL_MONITOR_IR36021_READ
 118static int read_voltage_from_IR(int i2caddress)
 119{
 120        int i, ret, voltage_read = 0;
 121        u16 vol_mon;
 122        u8 buf;
 123
 124        for (i = 0; i < NUM_READINGS; i++) {
 125                ret = i2c_read(i2caddress,
 126                               IR36021_LOOP1_VOUT_OFFSET,
 127                               1, (void *)&buf, 1);
 128                if (ret) {
 129                        printf("VID: failed to read vcpu\n");
 130                        return ret;
 131                }
 132                vol_mon = buf;
 133                if (!vol_mon) {
 134                        printf("VID: Core voltage sensor error\n");
 135                        return -1;
 136                }
 137                debug("VID: bus voltage reads 0x%02x\n", vol_mon);
 138                /* Resolution is 1/128V. We scale up here to get 1/128mV
 139                 * and divide at the end
 140                 */
 141                voltage_read += vol_mon * 1000;
 142                udelay(WAIT_FOR_ADC);
 143        }
 144        /* Scale down to the real mV as IR resolution is 1/128V, rounding up */
 145        voltage_read = DIV_ROUND_UP(voltage_read, 128);
 146
 147        /* calculate the average */
 148        voltage_read /= NUM_READINGS;
 149
 150        /* Compensate for a board specific voltage drop between regulator and
 151         * SoC before converting into an IR VID value
 152         */
 153        voltage_read -= board_vdd_drop_compensation();
 154
 155        return voltage_read;
 156}
 157#endif
 158
 159static int read_voltage(int i2caddress)
 160{
 161        int voltage_read;
 162#ifdef CONFIG_VOL_MONITOR_INA220
 163        voltage_read = read_voltage_from_INA220(i2caddress);
 164#elif defined CONFIG_VOL_MONITOR_IR36021_READ
 165        voltage_read = read_voltage_from_IR(i2caddress);
 166#else
 167        return -1;
 168#endif
 169        return voltage_read;
 170}
 171
 172/*
 173 * We need to calculate how long before the voltage stops to drop
 174 * or increase. It returns with the loop count. Each loop takes
 175 * several readings (WAIT_FOR_ADC)
 176 */
 177static int wait_for_new_voltage(int vdd, int i2caddress)
 178{
 179        int timeout, vdd_current;
 180
 181        vdd_current = read_voltage(i2caddress);
 182        /* wait until voltage starts to reach the target. Voltage slew
 183         * rates by typical regulators will always lead to stable readings
 184         * within each fairly long ADC interval in comparison to the
 185         * intended voltage delta change until the target voltage is
 186         * reached. The fairly small voltage delta change to any target
 187         * VID voltage also means that this function will always complete
 188         * within few iterations. If the timeout was ever reached, it would
 189         * point to a serious failure in the regulator system.
 190         */
 191        for (timeout = 0;
 192             abs(vdd - vdd_current) > (IR_VDD_STEP_UP + IR_VDD_STEP_DOWN) &&
 193             timeout < MAX_LOOP_WAIT_NEW_VOL; timeout++) {
 194                vdd_current = read_voltage(i2caddress);
 195        }
 196        if (timeout >= MAX_LOOP_WAIT_NEW_VOL) {
 197                printf("VID: Voltage adjustment timeout\n");
 198                return -1;
 199        }
 200        return timeout;
 201}
 202
 203/*
 204 * this function keeps reading the voltage until it is stable or until the
 205 * timeout expires
 206 */
 207static int wait_for_voltage_stable(int i2caddress)
 208{
 209        int timeout, vdd_current, vdd;
 210
 211        vdd = read_voltage(i2caddress);
 212        udelay(NUM_READINGS * WAIT_FOR_ADC);
 213
 214        /* wait until voltage is stable */
 215        vdd_current = read_voltage(i2caddress);
 216        /* The maximum timeout is
 217         * MAX_LOOP_WAIT_VOL_STABLE * NUM_READINGS * WAIT_FOR_ADC
 218         */
 219        for (timeout = MAX_LOOP_WAIT_VOL_STABLE;
 220             abs(vdd - vdd_current) > ADC_MIN_ACCURACY &&
 221             timeout > 0; timeout--) {
 222                vdd = vdd_current;
 223                udelay(NUM_READINGS * WAIT_FOR_ADC);
 224                vdd_current = read_voltage(i2caddress);
 225        }
 226        if (timeout == 0)
 227                return -1;
 228        return vdd_current;
 229}
 230
 231#ifdef CONFIG_VOL_MONITOR_IR36021_SET
 232/* Set the voltage to the IR chip */
 233static int set_voltage_to_IR(int i2caddress, int vdd)
 234{
 235        int wait, vdd_last;
 236        int ret;
 237        u8 vid;
 238
 239        /* Compensate for a board specific voltage drop between regulator and
 240         * SoC before converting into an IR VID value
 241         */
 242        vdd += board_vdd_drop_compensation();
 243        vid = DIV_ROUND_UP(vdd - 245, 5);
 244
 245        ret = i2c_write(i2caddress, IR36021_LOOP1_MANUAL_ID_OFFSET,
 246                        1, (void *)&vid, sizeof(vid));
 247        if (ret) {
 248                printf("VID: failed to write VID\n");
 249                return -1;
 250        }
 251        wait = wait_for_new_voltage(vdd, i2caddress);
 252        if (wait < 0)
 253                return -1;
 254        debug("VID: Waited %d us\n", wait * NUM_READINGS * WAIT_FOR_ADC);
 255
 256        vdd_last = wait_for_voltage_stable(i2caddress);
 257        if (vdd_last < 0)
 258                return -1;
 259        debug("VID: Current voltage is %d mV\n", vdd_last);
 260        return vdd_last;
 261}
 262#endif
 263
 264static int set_voltage(int i2caddress, int vdd)
 265{
 266        int vdd_last = -1;
 267
 268#ifdef CONFIG_VOL_MONITOR_IR36021_SET
 269        vdd_last = set_voltage_to_IR(i2caddress, vdd);
 270#else
 271        #error Specific voltage monitor must be defined
 272#endif
 273        return vdd_last;
 274}
 275
 276int adjust_vdd(ulong vdd_override)
 277{
 278        int re_enable = disable_interrupts();
 279        ccsr_gur_t __iomem *gur =
 280                (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
 281        u32 fusesr;
 282        u8 vid;
 283        int vdd_target, vdd_current, vdd_last;
 284        int ret, i2caddress;
 285        unsigned long vdd_string_override;
 286        char *vdd_string;
 287        static const uint16_t vdd[32] = {
 288                0,      /* unused */
 289                9875,   /* 0.9875V */
 290                9750,
 291                9625,
 292                9500,
 293                9375,
 294                9250,
 295                9125,
 296                9000,
 297                8875,
 298                8750,
 299                8625,
 300                8500,
 301                8375,
 302                8250,
 303                8125,
 304                10000,  /* 1.0000V */
 305                10125,
 306                10250,
 307                10375,
 308                10500,
 309                10625,
 310                10750,
 311                10875,
 312                11000,
 313                0,      /* reserved */
 314        };
 315        struct vdd_drive {
 316                u8 vid;
 317                unsigned voltage;
 318        };
 319
 320        ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
 321        if (ret) {
 322                debug("VID: I2C failed to switch channel\n");
 323                ret = -1;
 324                goto exit;
 325        }
 326        ret = find_ir_chip_on_i2c();
 327        if (ret < 0) {
 328                printf("VID: Could not find voltage regulator on I2C.\n");
 329                ret = -1;
 330                goto exit;
 331        } else {
 332                i2caddress = ret;
 333                debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
 334        }
 335
 336        /* get the voltage ID from fuse status register */
 337        fusesr = in_be32(&gur->dcfg_fusesr);
 338        /*
 339         * VID is used according to the table below
 340         *                ---------------------------------------
 341         *                |                DA_V                 |
 342         *                |-------------------------------------|
 343         *                | 5b00000 | 5b00001-5b11110 | 5b11111 |
 344         * ---------------+---------+-----------------+---------|
 345         * | D | 5b00000  | NO VID  | VID = DA_V      | NO VID  |
 346         * | A |----------+---------+-----------------+---------|
 347         * | _ | 5b00001  |VID =    | VID =           |VID =    |
 348         * | V |   ~      | DA_V_ALT|   DA_V_ALT      | DA_A_VLT|
 349         * | _ | 5b11110  |         |                 |         |
 350         * | A |----------+---------+-----------------+---------|
 351         * | L | 5b11111  | No VID  | VID = DA_V      | NO VID  |
 352         * | T |          |         |                 |         |
 353         * ------------------------------------------------------
 354         */
 355        vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_ALTVID_SHIFT) &
 356                FSL_CORENET_DCFG_FUSESR_ALTVID_MASK;
 357        if ((vid == 0) || (vid == FSL_CORENET_DCFG_FUSESR_ALTVID_MASK)) {
 358                vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_VID_SHIFT) &
 359                        FSL_CORENET_DCFG_FUSESR_VID_MASK;
 360        }
 361        vdd_target = vdd[vid];
 362
 363        /* check override variable for overriding VDD */
 364        vdd_string = getenv(CONFIG_VID_FLS_ENV);
 365        if (vdd_override == 0 && vdd_string &&
 366            !strict_strtoul(vdd_string, 10, &vdd_string_override))
 367                vdd_override = vdd_string_override;
 368        if (vdd_override >= VDD_MV_MIN && vdd_override <= VDD_MV_MAX) {
 369                vdd_target = vdd_override * 10; /* convert to 1/10 mV */
 370                debug("VDD override is %lu\n", vdd_override);
 371        } else if (vdd_override != 0) {
 372                printf("Invalid value.\n");
 373        }
 374        if (vdd_target == 0) {
 375                debug("VID: VID not used\n");
 376                ret = 0;
 377                goto exit;
 378        } else {
 379                /* divide and round up by 10 to get a value in mV */
 380                vdd_target = DIV_ROUND_UP(vdd_target, 10);
 381                debug("VID: vid = %d mV\n", vdd_target);
 382        }
 383
 384        /*
 385         * Read voltage monitor to check real voltage.
 386         */
 387        vdd_last = read_voltage(i2caddress);
 388        if (vdd_last < 0) {
 389                printf("VID: Couldn't read sensor abort VID adjustment\n");
 390                ret = -1;
 391                goto exit;
 392        }
 393        vdd_current = vdd_last;
 394        debug("VID: Core voltage is currently at %d mV\n", vdd_last);
 395        /*
 396          * Adjust voltage to at or one step above target.
 397          * As measurements are less precise than setting the values
 398          * we may run through dummy steps that cancel each other
 399          * when stepping up and then down.
 400          */
 401        while (vdd_last > 0 &&
 402               vdd_last < vdd_target) {
 403                vdd_current += IR_VDD_STEP_UP;
 404                vdd_last = set_voltage(i2caddress, vdd_current);
 405        }
 406        while (vdd_last > 0 &&
 407               vdd_last > vdd_target + (IR_VDD_STEP_DOWN - 1)) {
 408                vdd_current -= IR_VDD_STEP_DOWN;
 409                vdd_last = set_voltage(i2caddress, vdd_current);
 410        }
 411
 412        if (vdd_last > 0)
 413                printf("VID: Core voltage after adjustment is at %d mV\n",
 414                       vdd_last);
 415        else
 416                ret = -1;
 417exit:
 418        if (re_enable)
 419                enable_interrupts();
 420        return ret;
 421}
 422
 423static int print_vdd(void)
 424{
 425        int vdd_last, ret, i2caddress;
 426
 427        ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
 428        if (ret) {
 429                debug("VID : I2c failed to switch channel\n");
 430                return -1;
 431        }
 432        ret = find_ir_chip_on_i2c();
 433        if (ret < 0) {
 434                printf("VID: Could not find voltage regulator on I2C.\n");
 435                return -1;
 436        } else {
 437                i2caddress = ret;
 438                debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
 439        }
 440
 441        /*
 442         * Read voltage monitor to check real voltage.
 443         */
 444        vdd_last = read_voltage(i2caddress);
 445        if (vdd_last < 0) {
 446                printf("VID: Couldn't read sensor abort VID adjustment\n");
 447                return -1;
 448        }
 449        printf("VID: Core voltage is at %d mV\n", vdd_last);
 450
 451        return 0;
 452}
 453
 454static int do_vdd_override(cmd_tbl_t *cmdtp,
 455                           int flag, int argc,
 456                           char * const argv[])
 457{
 458        ulong override;
 459
 460        if (argc < 2)
 461                return CMD_RET_USAGE;
 462
 463        if (!strict_strtoul(argv[1], 10, &override))
 464                adjust_vdd(override);   /* the value is checked by callee */
 465        else
 466                return CMD_RET_USAGE;
 467        return 0;
 468}
 469
 470static int do_vdd_read(cmd_tbl_t *cmdtp,
 471                         int flag, int argc,
 472                         char * const argv[])
 473{
 474        if (argc < 1)
 475                return CMD_RET_USAGE;
 476        print_vdd();
 477
 478        return 0;
 479}
 480
 481U_BOOT_CMD(
 482        vdd_override, 2, 0, do_vdd_override,
 483        "override VDD",
 484        " - override with the voltage specified in mV, eg. 1050"
 485);
 486
 487U_BOOT_CMD(
 488        vdd_read, 1, 0, do_vdd_read,
 489        "read VDD",
 490        " - Read the voltage specified in mV"
 491)
 492