blob: b37f3bf4f8fea213e455f3dfb0ea2c1549536646 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Ying Zhang3ad27372014-10-31 18:06:18 +08002/*
3 * Copyright 2014 Freescale Semiconductor, Inc.
Ying Zhang3ad27372014-10-31 18:06:18 +08004 */
5
6#include <common.h>
7#include <command.h>
Simon Glass7b51b572019-08-01 09:46:52 -06008#include <env.h>
Ying Zhang3ad27372014-10-31 18:06:18 +08009#include <i2c.h>
Shaohui Xie02b5d2e2015-11-11 17:58:37 +080010#include <asm/io.h>
Shaohui Xie126fe702016-09-07 17:56:14 +080011#ifdef CONFIG_FSL_LSCH2
Shaohui Xie02b5d2e2015-11-11 17:58:37 +080012#include <asm/arch/immap_lsch2.h>
Rai Harnindered2530d2016-03-23 17:04:38 +053013#elif defined(CONFIG_FSL_LSCH3)
14#include <asm/arch/immap_lsch3.h>
Shaohui Xie02b5d2e2015-11-11 17:58:37 +080015#else
Ying Zhang3ad27372014-10-31 18:06:18 +080016#include <asm/immap_85xx.h>
Shaohui Xie02b5d2e2015-11-11 17:58:37 +080017#endif
Ying Zhang3ad27372014-10-31 18:06:18 +080018#include "vid.h"
19
Ying Zhang3ad27372014-10-31 18:06:18 +080020int __weak i2c_multiplexer_select_vid_channel(u8 channel)
21{
22 return 0;
23}
24
25/*
26 * Compensate for a board specific voltage drop between regulator and SoC
27 * return a value in mV
28 */
29int __weak board_vdd_drop_compensation(void)
30{
31 return 0;
32}
33
34/*
Rajesh Bhagat36075702018-01-17 16:13:02 +053035 * Board specific settings for specific voltage value
36 */
37int __weak board_adjust_vdd(int vdd)
38{
39 return 0;
40}
41
Rajesh Bhagat94583162018-01-17 16:13:03 +053042#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
43 defined(CONFIG_VOL_MONITOR_IR36021_READ)
Rajesh Bhagat36075702018-01-17 16:13:02 +053044/*
Ying Zhang3ad27372014-10-31 18:06:18 +080045 * Get the i2c address configuration for the IR regulator chip
46 *
47 * There are some variance in the RDB HW regarding the I2C address configuration
48 * for the IR regulator chip, which is likely a problem of external resistor
49 * accuracy. So we just check each address in a hopefully non-intrusive mode
50 * and use the first one that seems to work
51 *
52 * The IR chip can show up under the following addresses:
53 * 0x08 (Verified on T1040RDB-PA,T4240RDB-PB,X-T4240RDB-16GPA)
54 * 0x09 (Verified on T1040RDB-PA)
Ying Zhang2f66a822016-01-22 12:15:13 +080055 * 0x38 (Verified on T2080QDS, T2081QDS, T4240RDB)
Ying Zhang3ad27372014-10-31 18:06:18 +080056 */
57static int find_ir_chip_on_i2c(void)
58{
59 int i2caddress;
60 int ret;
61 u8 byte;
62 int i;
63 const int ir_i2c_addr[] = {0x38, 0x08, 0x09};
Chuanhua Han0eba65d2019-07-10 21:00:20 +080064#ifdef CONFIG_DM_I2C
65 struct udevice *dev;
66#endif
Ying Zhang3ad27372014-10-31 18:06:18 +080067
68 /* Check all the address */
69 for (i = 0; i < (sizeof(ir_i2c_addr)/sizeof(ir_i2c_addr[0])); i++) {
70 i2caddress = ir_i2c_addr[i];
Chuanhua Han0eba65d2019-07-10 21:00:20 +080071#ifndef CONFIG_DM_I2C
Ying Zhang3ad27372014-10-31 18:06:18 +080072 ret = i2c_read(i2caddress,
73 IR36021_MFR_ID_OFFSET, 1, (void *)&byte,
74 sizeof(byte));
Chuanhua Han0eba65d2019-07-10 21:00:20 +080075#else
76 ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
77 if (!ret)
78 ret = dm_i2c_read(dev, IR36021_MFR_ID_OFFSET,
79 (void *)&byte, sizeof(byte));
80#endif
Ying Zhang3ad27372014-10-31 18:06:18 +080081 if ((ret >= 0) && (byte == IR36021_MFR_ID))
82 return i2caddress;
83 }
84 return -1;
85}
Rajesh Bhagat94583162018-01-17 16:13:03 +053086#endif
Ying Zhang3ad27372014-10-31 18:06:18 +080087
88/* Maximum loop count waiting for new voltage to take effect */
89#define MAX_LOOP_WAIT_NEW_VOL 100
90/* Maximum loop count waiting for the voltage to be stable */
91#define MAX_LOOP_WAIT_VOL_STABLE 100
92/*
93 * read_voltage from sensor on I2C bus
94 * We use average of 4 readings, waiting for WAIT_FOR_ADC before
95 * another reading
96 */
97#define NUM_READINGS 4 /* prefer to be power of 2 for efficiency */
98
99/* If an INA220 chip is available, we can use it to read back the voltage
100 * as it may have a higher accuracy than the IR chip for the same purpose
101 */
102#ifdef CONFIG_VOL_MONITOR_INA220
103#define WAIT_FOR_ADC 532 /* wait for 532 microseconds for ADC */
104#define ADC_MIN_ACCURACY 4
105#else
106#define WAIT_FOR_ADC 138 /* wait for 138 microseconds for ADC */
107#define ADC_MIN_ACCURACY 4
108#endif
109
110#ifdef CONFIG_VOL_MONITOR_INA220
111static int read_voltage_from_INA220(int i2caddress)
112{
113 int i, ret, voltage_read = 0;
114 u16 vol_mon;
115 u8 buf[2];
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800116#ifdef CONFIG_DM_I2C
117 struct udevice *dev;
118#endif
Ying Zhang3ad27372014-10-31 18:06:18 +0800119
120 for (i = 0; i < NUM_READINGS; i++) {
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800121#ifndef CONFIG_DM_I2C
Ying Zhang3ad27372014-10-31 18:06:18 +0800122 ret = i2c_read(I2C_VOL_MONITOR_ADDR,
123 I2C_VOL_MONITOR_BUS_V_OFFSET, 1,
124 (void *)&buf, 2);
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800125#else
126 ret = i2c_get_chip_for_busnum(0, I2C_VOL_MONITOR_ADDR, 1, &dev);
127 if (!ret)
128 ret = dm_i2c_read(dev, I2C_VOL_MONITOR_BUS_V_OFFSET,
129 (void *)&buf, 2);
130#endif
Ying Zhang3ad27372014-10-31 18:06:18 +0800131 if (ret) {
132 printf("VID: failed to read core voltage\n");
133 return ret;
134 }
135 vol_mon = (buf[0] << 8) | buf[1];
136 if (vol_mon & I2C_VOL_MONITOR_BUS_V_OVF) {
137 printf("VID: Core voltage sensor error\n");
138 return -1;
139 }
140 debug("VID: bus voltage reads 0x%04x\n", vol_mon);
141 /* LSB = 4mv */
142 voltage_read += (vol_mon >> I2C_VOL_MONITOR_BUS_V_SHIFT) * 4;
143 udelay(WAIT_FOR_ADC);
144 }
145 /* calculate the average */
146 voltage_read /= NUM_READINGS;
147
148 return voltage_read;
149}
150#endif
151
152/* read voltage from IR */
153#ifdef CONFIG_VOL_MONITOR_IR36021_READ
154static int read_voltage_from_IR(int i2caddress)
155{
156 int i, ret, voltage_read = 0;
157 u16 vol_mon;
158 u8 buf;
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800159#ifdef CONFIG_DM_I2C
160 struct udevice *dev;
161#endif
Ying Zhang3ad27372014-10-31 18:06:18 +0800162
163 for (i = 0; i < NUM_READINGS; i++) {
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800164#ifndef CONFIG_DM_I2C
Ying Zhang3ad27372014-10-31 18:06:18 +0800165 ret = i2c_read(i2caddress,
166 IR36021_LOOP1_VOUT_OFFSET,
167 1, (void *)&buf, 1);
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800168#else
169 ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
170 if (!ret)
171 ret = dm_i2c_read(dev, IR36021_LOOP1_VOUT_OFFSET,
172 (void *)&buf, 1);
173#endif
Ying Zhang3ad27372014-10-31 18:06:18 +0800174 if (ret) {
175 printf("VID: failed to read vcpu\n");
176 return ret;
177 }
178 vol_mon = buf;
179 if (!vol_mon) {
180 printf("VID: Core voltage sensor error\n");
181 return -1;
182 }
183 debug("VID: bus voltage reads 0x%02x\n", vol_mon);
184 /* Resolution is 1/128V. We scale up here to get 1/128mV
185 * and divide at the end
186 */
187 voltage_read += vol_mon * 1000;
188 udelay(WAIT_FOR_ADC);
189 }
190 /* Scale down to the real mV as IR resolution is 1/128V, rounding up */
191 voltage_read = DIV_ROUND_UP(voltage_read, 128);
192
193 /* calculate the average */
194 voltage_read /= NUM_READINGS;
195
196 /* Compensate for a board specific voltage drop between regulator and
197 * SoC before converting into an IR VID value
198 */
199 voltage_read -= board_vdd_drop_compensation();
200
201 return voltage_read;
202}
203#endif
204
Rajesh Bhagat23a12cb2018-01-17 16:13:05 +0530205#ifdef CONFIG_VOL_MONITOR_LTC3882_READ
206/* read the current value of the LTC Regulator Voltage */
207static int read_voltage_from_LTC(int i2caddress)
208{
209 int ret, vcode = 0;
210 u8 chan = PWM_CHANNEL0;
211
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800212#ifndef CONFIG_DM_I2C
Rajesh Bhagat23a12cb2018-01-17 16:13:05 +0530213 /* select the PAGE 0 using PMBus commands PAGE for VDD*/
214 ret = i2c_write(I2C_VOL_MONITOR_ADDR,
215 PMBUS_CMD_PAGE, 1, &chan, 1);
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800216#else
217 struct udevice *dev;
218
219 ret = i2c_get_chip_for_busnum(0, I2C_VOL_MONITOR_ADDR, 1, &dev);
220 if (!ret)
221 ret = dm_i2c_write(dev, PMBUS_CMD_PAGE, &chan, 1);
222#endif
Rajesh Bhagat23a12cb2018-01-17 16:13:05 +0530223 if (ret) {
224 printf("VID: failed to select VDD Page 0\n");
225 return ret;
226 }
227
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800228#ifndef CONFIG_DM_I2C
Rajesh Bhagat23a12cb2018-01-17 16:13:05 +0530229 /*read the output voltage using PMBus command READ_VOUT*/
230 ret = i2c_read(I2C_VOL_MONITOR_ADDR,
231 PMBUS_CMD_READ_VOUT, 1, (void *)&vcode, 2);
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800232#else
233 ret = dm_i2c_read(dev, PMBUS_CMD_READ_VOUT, (void *)&vcode, 2);
234 if (ret) {
235 printf("VID: failed to read the volatge\n");
236 return ret;
237 }
238#endif
Rajesh Bhagat23a12cb2018-01-17 16:13:05 +0530239 if (ret) {
240 printf("VID: failed to read the volatge\n");
241 return ret;
242 }
243
244 /* Scale down to the real mV as LTC resolution is 1/4096V,rounding up */
245 vcode = DIV_ROUND_UP(vcode * 1000, 4096);
246
247 return vcode;
248}
249#endif
250
Ying Zhang3ad27372014-10-31 18:06:18 +0800251static int read_voltage(int i2caddress)
252{
253 int voltage_read;
254#ifdef CONFIG_VOL_MONITOR_INA220
255 voltage_read = read_voltage_from_INA220(i2caddress);
256#elif defined CONFIG_VOL_MONITOR_IR36021_READ
257 voltage_read = read_voltage_from_IR(i2caddress);
Rajesh Bhagat23a12cb2018-01-17 16:13:05 +0530258#elif defined CONFIG_VOL_MONITOR_LTC3882_READ
259 voltage_read = read_voltage_from_LTC(i2caddress);
Ying Zhang3ad27372014-10-31 18:06:18 +0800260#else
261 return -1;
262#endif
263 return voltage_read;
264}
265
Rajesh Bhagat94583162018-01-17 16:13:03 +0530266#ifdef CONFIG_VOL_MONITOR_IR36021_SET
Ying Zhang3ad27372014-10-31 18:06:18 +0800267/*
268 * We need to calculate how long before the voltage stops to drop
269 * or increase. It returns with the loop count. Each loop takes
270 * several readings (WAIT_FOR_ADC)
271 */
272static int wait_for_new_voltage(int vdd, int i2caddress)
273{
274 int timeout, vdd_current;
275
276 vdd_current = read_voltage(i2caddress);
277 /* wait until voltage starts to reach the target. Voltage slew
278 * rates by typical regulators will always lead to stable readings
279 * within each fairly long ADC interval in comparison to the
280 * intended voltage delta change until the target voltage is
281 * reached. The fairly small voltage delta change to any target
282 * VID voltage also means that this function will always complete
283 * within few iterations. If the timeout was ever reached, it would
284 * point to a serious failure in the regulator system.
285 */
286 for (timeout = 0;
287 abs(vdd - vdd_current) > (IR_VDD_STEP_UP + IR_VDD_STEP_DOWN) &&
288 timeout < MAX_LOOP_WAIT_NEW_VOL; timeout++) {
289 vdd_current = read_voltage(i2caddress);
290 }
291 if (timeout >= MAX_LOOP_WAIT_NEW_VOL) {
292 printf("VID: Voltage adjustment timeout\n");
293 return -1;
294 }
295 return timeout;
296}
297
298/*
299 * this function keeps reading the voltage until it is stable or until the
300 * timeout expires
301 */
302static int wait_for_voltage_stable(int i2caddress)
303{
304 int timeout, vdd_current, vdd;
305
306 vdd = read_voltage(i2caddress);
307 udelay(NUM_READINGS * WAIT_FOR_ADC);
308
309 /* wait until voltage is stable */
310 vdd_current = read_voltage(i2caddress);
311 /* The maximum timeout is
312 * MAX_LOOP_WAIT_VOL_STABLE * NUM_READINGS * WAIT_FOR_ADC
313 */
314 for (timeout = MAX_LOOP_WAIT_VOL_STABLE;
315 abs(vdd - vdd_current) > ADC_MIN_ACCURACY &&
316 timeout > 0; timeout--) {
317 vdd = vdd_current;
318 udelay(NUM_READINGS * WAIT_FOR_ADC);
319 vdd_current = read_voltage(i2caddress);
320 }
321 if (timeout == 0)
322 return -1;
323 return vdd_current;
324}
325
Ying Zhang3ad27372014-10-31 18:06:18 +0800326/* Set the voltage to the IR chip */
327static int set_voltage_to_IR(int i2caddress, int vdd)
328{
329 int wait, vdd_last;
330 int ret;
331 u8 vid;
332
333 /* Compensate for a board specific voltage drop between regulator and
334 * SoC before converting into an IR VID value
335 */
336 vdd += board_vdd_drop_compensation();
Shaohui Xie126fe702016-09-07 17:56:14 +0800337#ifdef CONFIG_FSL_LSCH2
Shaohui Xie02b5d2e2015-11-11 17:58:37 +0800338 vid = DIV_ROUND_UP(vdd - 265, 5);
339#else
Ying Zhang3ad27372014-10-31 18:06:18 +0800340 vid = DIV_ROUND_UP(vdd - 245, 5);
Shaohui Xie02b5d2e2015-11-11 17:58:37 +0800341#endif
Ying Zhang3ad27372014-10-31 18:06:18 +0800342
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800343#ifndef CONFIG_DM_I2C
Ying Zhang3ad27372014-10-31 18:06:18 +0800344 ret = i2c_write(i2caddress, IR36021_LOOP1_MANUAL_ID_OFFSET,
345 1, (void *)&vid, sizeof(vid));
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800346#else
347 struct udevice *dev;
348
349 ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
350 if (!ret)
351 ret = dm_i2c_write(dev, IR36021_LOOP1_MANUAL_ID_OFFSET,
352 (void *)&vid, sizeof(vid));
353
354#endif
Ying Zhang3ad27372014-10-31 18:06:18 +0800355 if (ret) {
356 printf("VID: failed to write VID\n");
357 return -1;
358 }
359 wait = wait_for_new_voltage(vdd, i2caddress);
360 if (wait < 0)
361 return -1;
362 debug("VID: Waited %d us\n", wait * NUM_READINGS * WAIT_FOR_ADC);
363
364 vdd_last = wait_for_voltage_stable(i2caddress);
365 if (vdd_last < 0)
366 return -1;
367 debug("VID: Current voltage is %d mV\n", vdd_last);
368 return vdd_last;
369}
Rajesh Bhagat23a12cb2018-01-17 16:13:05 +0530370
371#endif
372
373#ifdef CONFIG_VOL_MONITOR_LTC3882_SET
374/* this function sets the VDD and returns the value set */
375static int set_voltage_to_LTC(int i2caddress, int vdd)
376{
377 int ret, vdd_last, vdd_target = vdd;
Priyanka Jaindf182a42018-10-11 05:11:23 +0000378 int count = 100, temp = 0;
Rajesh Bhagat23a12cb2018-01-17 16:13:05 +0530379
380 /* Scale up to the LTC resolution is 1/4096V */
381 vdd = (vdd * 4096) / 1000;
382
383 /* 5-byte buffer which needs to be sent following the
384 * PMBus command PAGE_PLUS_WRITE.
385 */
386 u8 buff[5] = {0x04, PWM_CHANNEL0, PMBUS_CMD_VOUT_COMMAND,
387 vdd & 0xFF, (vdd & 0xFF00) >> 8};
388
389 /* Write the desired voltage code to the regulator */
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800390#ifndef CONFIG_DM_I2C
Rajesh Bhagat23a12cb2018-01-17 16:13:05 +0530391 ret = i2c_write(I2C_VOL_MONITOR_ADDR,
392 PMBUS_CMD_PAGE_PLUS_WRITE, 1, (void *)&buff, 5);
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800393#else
394 struct udevice *dev;
395
396 ret = i2c_get_chip_for_busnum(0, I2C_VOL_MONITOR_ADDR, 1, &dev);
397 if (!ret)
398 ret = dm_i2c_write(dev, PMBUS_CMD_PAGE_PLUS_WRITE,
399 (void *)&buff, 5);
400#endif
Rajesh Bhagat23a12cb2018-01-17 16:13:05 +0530401 if (ret) {
402 printf("VID: I2C failed to write to the volatge regulator\n");
403 return -1;
404 }
405
406 /* Wait for the volatge to get to the desired value */
407 do {
408 vdd_last = read_voltage_from_LTC(i2caddress);
409 if (vdd_last < 0) {
410 printf("VID: Couldn't read sensor abort VID adjust\n");
411 return -1;
412 }
Priyanka Jaindf182a42018-10-11 05:11:23 +0000413 count--;
414 temp = vdd_last - vdd_target;
415 } while ((abs(temp) > 2) && (count > 0));
Rajesh Bhagat23a12cb2018-01-17 16:13:05 +0530416
417 return vdd_last;
418}
Ying Zhang3ad27372014-10-31 18:06:18 +0800419#endif
420
421static int set_voltage(int i2caddress, int vdd)
422{
423 int vdd_last = -1;
424
425#ifdef CONFIG_VOL_MONITOR_IR36021_SET
426 vdd_last = set_voltage_to_IR(i2caddress, vdd);
Rajesh Bhagat23a12cb2018-01-17 16:13:05 +0530427#elif defined CONFIG_VOL_MONITOR_LTC3882_SET
428 vdd_last = set_voltage_to_LTC(i2caddress, vdd);
Ying Zhang3ad27372014-10-31 18:06:18 +0800429#else
430 #error Specific voltage monitor must be defined
431#endif
432 return vdd_last;
433}
434
Priyanka Jain29ca7132017-01-19 11:12:27 +0530435#ifdef CONFIG_FSL_LSCH3
Ying Zhang3ad27372014-10-31 18:06:18 +0800436int adjust_vdd(ulong vdd_override)
437{
438 int re_enable = disable_interrupts();
Priyanka Jain29ca7132017-01-19 11:12:27 +0530439 struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
440 u32 fusesr;
Rajesh Bhagat94583162018-01-17 16:13:03 +0530441#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
442 defined(CONFIG_VOL_MONITOR_IR36021_READ)
Priyanka Jain29ca7132017-01-19 11:12:27 +0530443 u8 vid, buf;
Rajesh Bhagat94583162018-01-17 16:13:03 +0530444#else
445 u8 vid;
446#endif
Priyanka Jain29ca7132017-01-19 11:12:27 +0530447 int vdd_target, vdd_current, vdd_last;
448 int ret, i2caddress;
449 unsigned long vdd_string_override;
450 char *vdd_string;
Priyanka Jaindb1e3df2018-10-11 05:22:34 +0000451#ifdef CONFIG_ARCH_LX2160A
452 static const u16 vdd[32] = {
453 8250,
454 7875,
455 7750,
456 0, /* reserved */
457 0, /* reserved */
458 0, /* reserved */
459 0, /* reserved */
460 0, /* reserved */
461 0, /* reserved */
462 0, /* reserved */
463 0, /* reserved */
464 0, /* reserved */
465 0, /* reserved */
466 0, /* reserved */
467 0, /* reserved */
468 0, /* reserved */
469 8000,
470 8125,
471 8250,
472 0, /* reserved */
473 8500,
474 0, /* reserved */
475 0, /* reserved */
476 0, /* reserved */
477 0, /* reserved */
478 0, /* reserved */
479 0, /* reserved */
480 0, /* reserved */
481 0, /* reserved */
482 0, /* reserved */
483 0, /* reserved */
484 0, /* reserved */
485 };
486#else
Rajesh Bhagatc535ad42018-01-17 16:13:01 +0530487#ifdef CONFIG_ARCH_LS1088A
488 static const uint16_t vdd[32] = {
489 10250,
490 9875,
491 9750,
492 0, /* reserved */
493 0, /* reserved */
494 0, /* reserved */
495 0, /* reserved */
496 0, /* reserved */
497 9000,
498 0, /* reserved */
499 0, /* reserved */
500 0, /* reserved */
501 0, /* reserved */
502 0, /* reserved */
503 0, /* reserved */
504 0, /* reserved */
505 10000, /* 1.0000V */
506 10125,
507 10250,
508 0, /* reserved */
509 0, /* reserved */
510 0, /* reserved */
511 0, /* reserved */
512 0, /* reserved */
513 0, /* reserved */
514 0, /* reserved */
515 0, /* reserved */
516 0, /* reserved */
517 0, /* reserved */
518 0, /* reserved */
519 0, /* reserved */
520 0, /* reserved */
521 };
522
523#else
Priyanka Jain29ca7132017-01-19 11:12:27 +0530524 static const uint16_t vdd[32] = {
525 10500,
526 0, /* reserved */
527 9750,
528 0, /* reserved */
529 9500,
530 0, /* reserved */
531 0, /* reserved */
532 0, /* reserved */
533 0, /* reserved */
534 0, /* reserved */
535 0, /* reserved */
Priyanka Jain49119482018-05-09 12:54:38 +0530536 9000, /* reserved */
Priyanka Jain29ca7132017-01-19 11:12:27 +0530537 0, /* reserved */
538 0, /* reserved */
539 0, /* reserved */
540 0, /* reserved */
541 10000, /* 1.0000V */
542 0, /* reserved */
543 10250,
544 0, /* reserved */
545 10500,
546 0, /* reserved */
547 0, /* reserved */
548 0, /* reserved */
549 0, /* reserved */
550 0, /* reserved */
551 0, /* reserved */
552 0, /* reserved */
553 0, /* reserved */
554 0, /* reserved */
555 0, /* reserved */
556 0, /* reserved */
557 };
Rajesh Bhagatc535ad42018-01-17 16:13:01 +0530558#endif
Priyanka Jaindb1e3df2018-10-11 05:22:34 +0000559#endif
Priyanka Jain29ca7132017-01-19 11:12:27 +0530560 struct vdd_drive {
561 u8 vid;
562 unsigned voltage;
563 };
564
565 ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
566 if (ret) {
567 debug("VID: I2C failed to switch channel\n");
568 ret = -1;
569 goto exit;
570 }
Rajesh Bhagat94583162018-01-17 16:13:03 +0530571#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
572 defined(CONFIG_VOL_MONITOR_IR36021_READ)
Priyanka Jain29ca7132017-01-19 11:12:27 +0530573 ret = find_ir_chip_on_i2c();
574 if (ret < 0) {
575 printf("VID: Could not find voltage regulator on I2C.\n");
576 ret = -1;
577 goto exit;
578 } else {
579 i2caddress = ret;
580 debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
581 }
582
583 /* check IR chip work on Intel mode*/
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800584#ifndef CONFIG_DM_I2C
Priyanka Jain29ca7132017-01-19 11:12:27 +0530585 ret = i2c_read(i2caddress,
586 IR36021_INTEL_MODE_OOFSET,
587 1, (void *)&buf, 1);
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800588#else
589 struct udevice *dev;
590
591 ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
592 if (!ret)
593 ret = dm_i2c_read(dev, IR36021_INTEL_MODE_OOFSET,
594 (void *)&buf, 1);
595#endif
Priyanka Jain29ca7132017-01-19 11:12:27 +0530596 if (ret) {
597 printf("VID: failed to read IR chip mode.\n");
598 ret = -1;
599 goto exit;
600 }
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800601
Priyanka Jain29ca7132017-01-19 11:12:27 +0530602 if ((buf & IR36021_MODE_MASK) != IR36021_INTEL_MODE) {
603 printf("VID: IR Chip is not used in Intel mode.\n");
604 ret = -1;
605 goto exit;
606 }
Rajesh Bhagat94583162018-01-17 16:13:03 +0530607#endif
Priyanka Jain29ca7132017-01-19 11:12:27 +0530608
609 /* get the voltage ID from fuse status register */
610 fusesr = in_le32(&gur->dcfg_fusesr);
611 vid = (fusesr >> FSL_CHASSIS3_DCFG_FUSESR_ALTVID_SHIFT) &
612 FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK;
613 if ((vid == 0) || (vid == FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK)) {
614 vid = (fusesr >> FSL_CHASSIS3_DCFG_FUSESR_VID_SHIFT) &
615 FSL_CHASSIS3_DCFG_FUSESR_VID_MASK;
616 }
617 vdd_target = vdd[vid];
618
619 /* check override variable for overriding VDD */
Simon Glass00caae62017-08-03 12:22:12 -0600620 vdd_string = env_get(CONFIG_VID_FLS_ENV);
Priyanka Jain29ca7132017-01-19 11:12:27 +0530621 if (vdd_override == 0 && vdd_string &&
622 !strict_strtoul(vdd_string, 10, &vdd_string_override))
623 vdd_override = vdd_string_override;
624
625 if (vdd_override >= VDD_MV_MIN && vdd_override <= VDD_MV_MAX) {
626 vdd_target = vdd_override * 10; /* convert to 1/10 mV */
627 debug("VDD override is %lu\n", vdd_override);
628 } else if (vdd_override != 0) {
629 printf("Invalid value.\n");
630 }
631
632 /* divide and round up by 10 to get a value in mV */
633 vdd_target = DIV_ROUND_UP(vdd_target, 10);
634 if (vdd_target == 0) {
635 debug("VID: VID not used\n");
636 ret = 0;
637 goto exit;
638 } else if (vdd_target < VDD_MV_MIN || vdd_target > VDD_MV_MAX) {
639 /* Check vdd_target is in valid range */
640 printf("VID: Target VID %d mV is not in range.\n",
641 vdd_target);
642 ret = -1;
643 goto exit;
644 } else {
645 debug("VID: vid = %d mV\n", vdd_target);
646 }
647
648 /*
649 * Read voltage monitor to check real voltage.
650 */
651 vdd_last = read_voltage(i2caddress);
652 if (vdd_last < 0) {
653 printf("VID: Couldn't read sensor abort VID adjustment\n");
654 ret = -1;
655 goto exit;
656 }
657 vdd_current = vdd_last;
658 debug("VID: Core voltage is currently at %d mV\n", vdd_last);
Rajesh Bhagat23a12cb2018-01-17 16:13:05 +0530659
660#ifdef CONFIG_VOL_MONITOR_LTC3882_SET
661 /* Set the target voltage */
662 vdd_last = vdd_current = set_voltage(i2caddress, vdd_target);
663#else
Priyanka Jain29ca7132017-01-19 11:12:27 +0530664 /*
665 * Adjust voltage to at or one step above target.
666 * As measurements are less precise than setting the values
667 * we may run through dummy steps that cancel each other
668 * when stepping up and then down.
669 */
670 while (vdd_last > 0 &&
671 vdd_last < vdd_target) {
672 vdd_current += IR_VDD_STEP_UP;
673 vdd_last = set_voltage(i2caddress, vdd_current);
674 }
675 while (vdd_last > 0 &&
676 vdd_last > vdd_target + (IR_VDD_STEP_DOWN - 1)) {
677 vdd_current -= IR_VDD_STEP_DOWN;
678 vdd_last = set_voltage(i2caddress, vdd_current);
679 }
680
Rajesh Bhagat23a12cb2018-01-17 16:13:05 +0530681#endif
Rajesh Bhagat36075702018-01-17 16:13:02 +0530682 if (board_adjust_vdd(vdd_target) < 0) {
683 ret = -1;
684 goto exit;
685 }
686
Priyanka Jain29ca7132017-01-19 11:12:27 +0530687 if (vdd_last > 0)
688 printf("VID: Core voltage after adjustment is at %d mV\n",
689 vdd_last);
690 else
691 ret = -1;
692exit:
693 if (re_enable)
694 enable_interrupts();
695 i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
696 return ret;
697}
698#else /* !CONFIG_FSL_LSCH3 */
699int adjust_vdd(ulong vdd_override)
700{
701 int re_enable = disable_interrupts();
702#if defined(CONFIG_FSL_LSCH2)
Shaohui Xie02b5d2e2015-11-11 17:58:37 +0800703 struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
704#else
Ying Zhang3ad27372014-10-31 18:06:18 +0800705 ccsr_gur_t __iomem *gur =
706 (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
Shaohui Xie02b5d2e2015-11-11 17:58:37 +0800707#endif
Ying Zhang3ad27372014-10-31 18:06:18 +0800708 u32 fusesr;
Ying Zhangcabe4d22016-01-22 12:15:12 +0800709 u8 vid, buf;
Ying Zhang3ad27372014-10-31 18:06:18 +0800710 int vdd_target, vdd_current, vdd_last;
711 int ret, i2caddress;
712 unsigned long vdd_string_override;
713 char *vdd_string;
714 static const uint16_t vdd[32] = {
715 0, /* unused */
716 9875, /* 0.9875V */
717 9750,
718 9625,
719 9500,
720 9375,
721 9250,
722 9125,
723 9000,
724 8875,
725 8750,
726 8625,
727 8500,
728 8375,
729 8250,
730 8125,
731 10000, /* 1.0000V */
732 10125,
733 10250,
734 10375,
735 10500,
736 10625,
737 10750,
738 10875,
739 11000,
740 0, /* reserved */
741 };
742 struct vdd_drive {
743 u8 vid;
744 unsigned voltage;
745 };
746
747 ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
748 if (ret) {
749 debug("VID: I2C failed to switch channel\n");
750 ret = -1;
751 goto exit;
752 }
Rajesh Bhagat94583162018-01-17 16:13:03 +0530753#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
754 defined(CONFIG_VOL_MONITOR_IR36021_READ)
Ying Zhang3ad27372014-10-31 18:06:18 +0800755 ret = find_ir_chip_on_i2c();
756 if (ret < 0) {
757 printf("VID: Could not find voltage regulator on I2C.\n");
758 ret = -1;
759 goto exit;
760 } else {
761 i2caddress = ret;
762 debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
763 }
764
Ying Zhangcabe4d22016-01-22 12:15:12 +0800765 /* check IR chip work on Intel mode*/
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800766#ifndef CONFIG_DM_I2C
Ying Zhangcabe4d22016-01-22 12:15:12 +0800767 ret = i2c_read(i2caddress,
768 IR36021_INTEL_MODE_OOFSET,
769 1, (void *)&buf, 1);
Chuanhua Han0eba65d2019-07-10 21:00:20 +0800770#else
771 struct udevice *dev;
772
773 ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
774 if (!ret)
775 ret = dm_i2c_read(dev, IR36021_INTEL_MODE_OOFSET,
776 (void *)&buf, 1);
777#endif
Ying Zhangcabe4d22016-01-22 12:15:12 +0800778 if (ret) {
779 printf("VID: failed to read IR chip mode.\n");
780 ret = -1;
781 goto exit;
782 }
783 if ((buf & IR36021_MODE_MASK) != IR36021_INTEL_MODE) {
784 printf("VID: IR Chip is not used in Intel mode.\n");
785 ret = -1;
786 goto exit;
787 }
Rajesh Bhagat94583162018-01-17 16:13:03 +0530788#endif
Ying Zhangcabe4d22016-01-22 12:15:12 +0800789
Ying Zhang3ad27372014-10-31 18:06:18 +0800790 /* get the voltage ID from fuse status register */
791 fusesr = in_be32(&gur->dcfg_fusesr);
792 /*
793 * VID is used according to the table below
794 * ---------------------------------------
795 * | DA_V |
796 * |-------------------------------------|
797 * | 5b00000 | 5b00001-5b11110 | 5b11111 |
798 * ---------------+---------+-----------------+---------|
799 * | D | 5b00000 | NO VID | VID = DA_V | NO VID |
800 * | A |----------+---------+-----------------+---------|
801 * | _ | 5b00001 |VID = | VID = |VID = |
802 * | V | ~ | DA_V_ALT| DA_V_ALT | DA_A_VLT|
803 * | _ | 5b11110 | | | |
804 * | A |----------+---------+-----------------+---------|
805 * | L | 5b11111 | No VID | VID = DA_V | NO VID |
806 * | T | | | | |
807 * ------------------------------------------------------
808 */
Shaohui Xie126fe702016-09-07 17:56:14 +0800809#ifdef CONFIG_FSL_LSCH2
Shaohui Xie02b5d2e2015-11-11 17:58:37 +0800810 vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_ALTVID_SHIFT) &
811 FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK;
812 if ((vid == 0) || (vid == FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK)) {
813 vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_VID_SHIFT) &
814 FSL_CHASSIS2_DCFG_FUSESR_VID_MASK;
815 }
816#else
Ying Zhang3ad27372014-10-31 18:06:18 +0800817 vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_ALTVID_SHIFT) &
818 FSL_CORENET_DCFG_FUSESR_ALTVID_MASK;
819 if ((vid == 0) || (vid == FSL_CORENET_DCFG_FUSESR_ALTVID_MASK)) {
820 vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_VID_SHIFT) &
821 FSL_CORENET_DCFG_FUSESR_VID_MASK;
822 }
Shaohui Xie02b5d2e2015-11-11 17:58:37 +0800823#endif
Ying Zhang3ad27372014-10-31 18:06:18 +0800824 vdd_target = vdd[vid];
825
826 /* check override variable for overriding VDD */
Simon Glass00caae62017-08-03 12:22:12 -0600827 vdd_string = env_get(CONFIG_VID_FLS_ENV);
Ying Zhang3ad27372014-10-31 18:06:18 +0800828 if (vdd_override == 0 && vdd_string &&
829 !strict_strtoul(vdd_string, 10, &vdd_string_override))
830 vdd_override = vdd_string_override;
831 if (vdd_override >= VDD_MV_MIN && vdd_override <= VDD_MV_MAX) {
832 vdd_target = vdd_override * 10; /* convert to 1/10 mV */
833 debug("VDD override is %lu\n", vdd_override);
834 } else if (vdd_override != 0) {
835 printf("Invalid value.\n");
836 }
837 if (vdd_target == 0) {
838 debug("VID: VID not used\n");
839 ret = 0;
840 goto exit;
841 } else {
842 /* divide and round up by 10 to get a value in mV */
843 vdd_target = DIV_ROUND_UP(vdd_target, 10);
844 debug("VID: vid = %d mV\n", vdd_target);
845 }
846
847 /*
848 * Read voltage monitor to check real voltage.
849 */
850 vdd_last = read_voltage(i2caddress);
851 if (vdd_last < 0) {
852 printf("VID: Couldn't read sensor abort VID adjustment\n");
853 ret = -1;
854 goto exit;
855 }
856 vdd_current = vdd_last;
857 debug("VID: Core voltage is currently at %d mV\n", vdd_last);
858 /*
859 * Adjust voltage to at or one step above target.
860 * As measurements are less precise than setting the values
861 * we may run through dummy steps that cancel each other
862 * when stepping up and then down.
863 */
864 while (vdd_last > 0 &&
865 vdd_last < vdd_target) {
866 vdd_current += IR_VDD_STEP_UP;
867 vdd_last = set_voltage(i2caddress, vdd_current);
868 }
869 while (vdd_last > 0 &&
870 vdd_last > vdd_target + (IR_VDD_STEP_DOWN - 1)) {
871 vdd_current -= IR_VDD_STEP_DOWN;
872 vdd_last = set_voltage(i2caddress, vdd_current);
873 }
874
875 if (vdd_last > 0)
876 printf("VID: Core voltage after adjustment is at %d mV\n",
877 vdd_last);
878 else
879 ret = -1;
880exit:
881 if (re_enable)
882 enable_interrupts();
Wenbin Song1be8d102016-03-09 13:38:23 +0800883
884 i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
885
Ying Zhang3ad27372014-10-31 18:06:18 +0800886 return ret;
887}
Priyanka Jain29ca7132017-01-19 11:12:27 +0530888#endif
Ying Zhang3ad27372014-10-31 18:06:18 +0800889
890static int print_vdd(void)
891{
892 int vdd_last, ret, i2caddress;
893
894 ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
895 if (ret) {
896 debug("VID : I2c failed to switch channel\n");
897 return -1;
898 }
Rajesh Bhagat94583162018-01-17 16:13:03 +0530899#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
900 defined(CONFIG_VOL_MONITOR_IR36021_READ)
Ying Zhang3ad27372014-10-31 18:06:18 +0800901 ret = find_ir_chip_on_i2c();
902 if (ret < 0) {
903 printf("VID: Could not find voltage regulator on I2C.\n");
Wenbin Song1be8d102016-03-09 13:38:23 +0800904 goto exit;
Ying Zhang3ad27372014-10-31 18:06:18 +0800905 } else {
906 i2caddress = ret;
907 debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
908 }
Rajesh Bhagat94583162018-01-17 16:13:03 +0530909#endif
Ying Zhang3ad27372014-10-31 18:06:18 +0800910
911 /*
912 * Read voltage monitor to check real voltage.
913 */
914 vdd_last = read_voltage(i2caddress);
915 if (vdd_last < 0) {
916 printf("VID: Couldn't read sensor abort VID adjustment\n");
Wenbin Song1be8d102016-03-09 13:38:23 +0800917 goto exit;
Ying Zhang3ad27372014-10-31 18:06:18 +0800918 }
919 printf("VID: Core voltage is at %d mV\n", vdd_last);
Wenbin Song1be8d102016-03-09 13:38:23 +0800920exit:
921 i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
Ying Zhang3ad27372014-10-31 18:06:18 +0800922
Wenbin Song1be8d102016-03-09 13:38:23 +0800923 return ret < 0 ? -1 : 0;
924
Ying Zhang3ad27372014-10-31 18:06:18 +0800925}
926
927static int do_vdd_override(cmd_tbl_t *cmdtp,
928 int flag, int argc,
929 char * const argv[])
930{
931 ulong override;
932
933 if (argc < 2)
934 return CMD_RET_USAGE;
935
936 if (!strict_strtoul(argv[1], 10, &override))
937 adjust_vdd(override); /* the value is checked by callee */
938 else
939 return CMD_RET_USAGE;
940 return 0;
941}
942
943static int do_vdd_read(cmd_tbl_t *cmdtp,
944 int flag, int argc,
945 char * const argv[])
946{
947 if (argc < 1)
948 return CMD_RET_USAGE;
949 print_vdd();
950
951 return 0;
952}
953
954U_BOOT_CMD(
955 vdd_override, 2, 0, do_vdd_override,
956 "override VDD",
957 " - override with the voltage specified in mV, eg. 1050"
958);
959
960U_BOOT_CMD(
961 vdd_read, 1, 0, do_vdd_read,
962 "read VDD",
963 " - Read the voltage specified in mV"
964)