1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright 2014 Freescale Semiconductor, Inc.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <command.h>
9*4882a593Smuzhiyun #include <i2c.h>
10*4882a593Smuzhiyun #include <asm/io.h>
11*4882a593Smuzhiyun #ifdef CONFIG_FSL_LSCH2
12*4882a593Smuzhiyun #include <asm/arch/immap_lsch2.h>
13*4882a593Smuzhiyun #elif defined(CONFIG_FSL_LSCH3)
14*4882a593Smuzhiyun #include <asm/arch/immap_lsch3.h>
15*4882a593Smuzhiyun #else
16*4882a593Smuzhiyun #include <asm/immap_85xx.h>
17*4882a593Smuzhiyun #endif
18*4882a593Smuzhiyun #include "vid.h"
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
21*4882a593Smuzhiyun
i2c_multiplexer_select_vid_channel(u8 channel)22*4882a593Smuzhiyun int __weak i2c_multiplexer_select_vid_channel(u8 channel)
23*4882a593Smuzhiyun {
24*4882a593Smuzhiyun return 0;
25*4882a593Smuzhiyun }
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun /*
28*4882a593Smuzhiyun * Compensate for a board specific voltage drop between regulator and SoC
29*4882a593Smuzhiyun * return a value in mV
30*4882a593Smuzhiyun */
board_vdd_drop_compensation(void)31*4882a593Smuzhiyun int __weak board_vdd_drop_compensation(void)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun return 0;
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun /*
37*4882a593Smuzhiyun * Get the i2c address configuration for the IR regulator chip
38*4882a593Smuzhiyun *
39*4882a593Smuzhiyun * There are some variance in the RDB HW regarding the I2C address configuration
40*4882a593Smuzhiyun * for the IR regulator chip, which is likely a problem of external resistor
41*4882a593Smuzhiyun * accuracy. So we just check each address in a hopefully non-intrusive mode
42*4882a593Smuzhiyun * and use the first one that seems to work
43*4882a593Smuzhiyun *
44*4882a593Smuzhiyun * The IR chip can show up under the following addresses:
45*4882a593Smuzhiyun * 0x08 (Verified on T1040RDB-PA,T4240RDB-PB,X-T4240RDB-16GPA)
46*4882a593Smuzhiyun * 0x09 (Verified on T1040RDB-PA)
47*4882a593Smuzhiyun * 0x38 (Verified on T2080QDS, T2081QDS, T4240RDB)
48*4882a593Smuzhiyun */
find_ir_chip_on_i2c(void)49*4882a593Smuzhiyun static int find_ir_chip_on_i2c(void)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun int i2caddress;
52*4882a593Smuzhiyun int ret;
53*4882a593Smuzhiyun u8 byte;
54*4882a593Smuzhiyun int i;
55*4882a593Smuzhiyun const int ir_i2c_addr[] = {0x38, 0x08, 0x09};
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun /* Check all the address */
58*4882a593Smuzhiyun for (i = 0; i < (sizeof(ir_i2c_addr)/sizeof(ir_i2c_addr[0])); i++) {
59*4882a593Smuzhiyun i2caddress = ir_i2c_addr[i];
60*4882a593Smuzhiyun ret = i2c_read(i2caddress,
61*4882a593Smuzhiyun IR36021_MFR_ID_OFFSET, 1, (void *)&byte,
62*4882a593Smuzhiyun sizeof(byte));
63*4882a593Smuzhiyun if ((ret >= 0) && (byte == IR36021_MFR_ID))
64*4882a593Smuzhiyun return i2caddress;
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun return -1;
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun /* Maximum loop count waiting for new voltage to take effect */
70*4882a593Smuzhiyun #define MAX_LOOP_WAIT_NEW_VOL 100
71*4882a593Smuzhiyun /* Maximum loop count waiting for the voltage to be stable */
72*4882a593Smuzhiyun #define MAX_LOOP_WAIT_VOL_STABLE 100
73*4882a593Smuzhiyun /*
74*4882a593Smuzhiyun * read_voltage from sensor on I2C bus
75*4882a593Smuzhiyun * We use average of 4 readings, waiting for WAIT_FOR_ADC before
76*4882a593Smuzhiyun * another reading
77*4882a593Smuzhiyun */
78*4882a593Smuzhiyun #define NUM_READINGS 4 /* prefer to be power of 2 for efficiency */
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun /* If an INA220 chip is available, we can use it to read back the voltage
81*4882a593Smuzhiyun * as it may have a higher accuracy than the IR chip for the same purpose
82*4882a593Smuzhiyun */
83*4882a593Smuzhiyun #ifdef CONFIG_VOL_MONITOR_INA220
84*4882a593Smuzhiyun #define WAIT_FOR_ADC 532 /* wait for 532 microseconds for ADC */
85*4882a593Smuzhiyun #define ADC_MIN_ACCURACY 4
86*4882a593Smuzhiyun #else
87*4882a593Smuzhiyun #define WAIT_FOR_ADC 138 /* wait for 138 microseconds for ADC */
88*4882a593Smuzhiyun #define ADC_MIN_ACCURACY 4
89*4882a593Smuzhiyun #endif
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun #ifdef CONFIG_VOL_MONITOR_INA220
read_voltage_from_INA220(int i2caddress)92*4882a593Smuzhiyun static int read_voltage_from_INA220(int i2caddress)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun int i, ret, voltage_read = 0;
95*4882a593Smuzhiyun u16 vol_mon;
96*4882a593Smuzhiyun u8 buf[2];
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun for (i = 0; i < NUM_READINGS; i++) {
99*4882a593Smuzhiyun ret = i2c_read(I2C_VOL_MONITOR_ADDR,
100*4882a593Smuzhiyun I2C_VOL_MONITOR_BUS_V_OFFSET, 1,
101*4882a593Smuzhiyun (void *)&buf, 2);
102*4882a593Smuzhiyun if (ret) {
103*4882a593Smuzhiyun printf("VID: failed to read core voltage\n");
104*4882a593Smuzhiyun return ret;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun vol_mon = (buf[0] << 8) | buf[1];
107*4882a593Smuzhiyun if (vol_mon & I2C_VOL_MONITOR_BUS_V_OVF) {
108*4882a593Smuzhiyun printf("VID: Core voltage sensor error\n");
109*4882a593Smuzhiyun return -1;
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun debug("VID: bus voltage reads 0x%04x\n", vol_mon);
112*4882a593Smuzhiyun /* LSB = 4mv */
113*4882a593Smuzhiyun voltage_read += (vol_mon >> I2C_VOL_MONITOR_BUS_V_SHIFT) * 4;
114*4882a593Smuzhiyun udelay(WAIT_FOR_ADC);
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun /* calculate the average */
117*4882a593Smuzhiyun voltage_read /= NUM_READINGS;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun return voltage_read;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun #endif
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun /* read voltage from IR */
124*4882a593Smuzhiyun #ifdef CONFIG_VOL_MONITOR_IR36021_READ
read_voltage_from_IR(int i2caddress)125*4882a593Smuzhiyun static int read_voltage_from_IR(int i2caddress)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun int i, ret, voltage_read = 0;
128*4882a593Smuzhiyun u16 vol_mon;
129*4882a593Smuzhiyun u8 buf;
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun for (i = 0; i < NUM_READINGS; i++) {
132*4882a593Smuzhiyun ret = i2c_read(i2caddress,
133*4882a593Smuzhiyun IR36021_LOOP1_VOUT_OFFSET,
134*4882a593Smuzhiyun 1, (void *)&buf, 1);
135*4882a593Smuzhiyun if (ret) {
136*4882a593Smuzhiyun printf("VID: failed to read vcpu\n");
137*4882a593Smuzhiyun return ret;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun vol_mon = buf;
140*4882a593Smuzhiyun if (!vol_mon) {
141*4882a593Smuzhiyun printf("VID: Core voltage sensor error\n");
142*4882a593Smuzhiyun return -1;
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun debug("VID: bus voltage reads 0x%02x\n", vol_mon);
145*4882a593Smuzhiyun /* Resolution is 1/128V. We scale up here to get 1/128mV
146*4882a593Smuzhiyun * and divide at the end
147*4882a593Smuzhiyun */
148*4882a593Smuzhiyun voltage_read += vol_mon * 1000;
149*4882a593Smuzhiyun udelay(WAIT_FOR_ADC);
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun /* Scale down to the real mV as IR resolution is 1/128V, rounding up */
152*4882a593Smuzhiyun voltage_read = DIV_ROUND_UP(voltage_read, 128);
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun /* calculate the average */
155*4882a593Smuzhiyun voltage_read /= NUM_READINGS;
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun /* Compensate for a board specific voltage drop between regulator and
158*4882a593Smuzhiyun * SoC before converting into an IR VID value
159*4882a593Smuzhiyun */
160*4882a593Smuzhiyun voltage_read -= board_vdd_drop_compensation();
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun return voltage_read;
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun #endif
165*4882a593Smuzhiyun
read_voltage(int i2caddress)166*4882a593Smuzhiyun static int read_voltage(int i2caddress)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun int voltage_read;
169*4882a593Smuzhiyun #ifdef CONFIG_VOL_MONITOR_INA220
170*4882a593Smuzhiyun voltage_read = read_voltage_from_INA220(i2caddress);
171*4882a593Smuzhiyun #elif defined CONFIG_VOL_MONITOR_IR36021_READ
172*4882a593Smuzhiyun voltage_read = read_voltage_from_IR(i2caddress);
173*4882a593Smuzhiyun #else
174*4882a593Smuzhiyun return -1;
175*4882a593Smuzhiyun #endif
176*4882a593Smuzhiyun return voltage_read;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun /*
180*4882a593Smuzhiyun * We need to calculate how long before the voltage stops to drop
181*4882a593Smuzhiyun * or increase. It returns with the loop count. Each loop takes
182*4882a593Smuzhiyun * several readings (WAIT_FOR_ADC)
183*4882a593Smuzhiyun */
wait_for_new_voltage(int vdd,int i2caddress)184*4882a593Smuzhiyun static int wait_for_new_voltage(int vdd, int i2caddress)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun int timeout, vdd_current;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun vdd_current = read_voltage(i2caddress);
189*4882a593Smuzhiyun /* wait until voltage starts to reach the target. Voltage slew
190*4882a593Smuzhiyun * rates by typical regulators will always lead to stable readings
191*4882a593Smuzhiyun * within each fairly long ADC interval in comparison to the
192*4882a593Smuzhiyun * intended voltage delta change until the target voltage is
193*4882a593Smuzhiyun * reached. The fairly small voltage delta change to any target
194*4882a593Smuzhiyun * VID voltage also means that this function will always complete
195*4882a593Smuzhiyun * within few iterations. If the timeout was ever reached, it would
196*4882a593Smuzhiyun * point to a serious failure in the regulator system.
197*4882a593Smuzhiyun */
198*4882a593Smuzhiyun for (timeout = 0;
199*4882a593Smuzhiyun abs(vdd - vdd_current) > (IR_VDD_STEP_UP + IR_VDD_STEP_DOWN) &&
200*4882a593Smuzhiyun timeout < MAX_LOOP_WAIT_NEW_VOL; timeout++) {
201*4882a593Smuzhiyun vdd_current = read_voltage(i2caddress);
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun if (timeout >= MAX_LOOP_WAIT_NEW_VOL) {
204*4882a593Smuzhiyun printf("VID: Voltage adjustment timeout\n");
205*4882a593Smuzhiyun return -1;
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun return timeout;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun /*
211*4882a593Smuzhiyun * this function keeps reading the voltage until it is stable or until the
212*4882a593Smuzhiyun * timeout expires
213*4882a593Smuzhiyun */
wait_for_voltage_stable(int i2caddress)214*4882a593Smuzhiyun static int wait_for_voltage_stable(int i2caddress)
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun int timeout, vdd_current, vdd;
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun vdd = read_voltage(i2caddress);
219*4882a593Smuzhiyun udelay(NUM_READINGS * WAIT_FOR_ADC);
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun /* wait until voltage is stable */
222*4882a593Smuzhiyun vdd_current = read_voltage(i2caddress);
223*4882a593Smuzhiyun /* The maximum timeout is
224*4882a593Smuzhiyun * MAX_LOOP_WAIT_VOL_STABLE * NUM_READINGS * WAIT_FOR_ADC
225*4882a593Smuzhiyun */
226*4882a593Smuzhiyun for (timeout = MAX_LOOP_WAIT_VOL_STABLE;
227*4882a593Smuzhiyun abs(vdd - vdd_current) > ADC_MIN_ACCURACY &&
228*4882a593Smuzhiyun timeout > 0; timeout--) {
229*4882a593Smuzhiyun vdd = vdd_current;
230*4882a593Smuzhiyun udelay(NUM_READINGS * WAIT_FOR_ADC);
231*4882a593Smuzhiyun vdd_current = read_voltage(i2caddress);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun if (timeout == 0)
234*4882a593Smuzhiyun return -1;
235*4882a593Smuzhiyun return vdd_current;
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun #ifdef CONFIG_VOL_MONITOR_IR36021_SET
239*4882a593Smuzhiyun /* Set the voltage to the IR chip */
set_voltage_to_IR(int i2caddress,int vdd)240*4882a593Smuzhiyun static int set_voltage_to_IR(int i2caddress, int vdd)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun int wait, vdd_last;
243*4882a593Smuzhiyun int ret;
244*4882a593Smuzhiyun u8 vid;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun /* Compensate for a board specific voltage drop between regulator and
247*4882a593Smuzhiyun * SoC before converting into an IR VID value
248*4882a593Smuzhiyun */
249*4882a593Smuzhiyun vdd += board_vdd_drop_compensation();
250*4882a593Smuzhiyun #ifdef CONFIG_FSL_LSCH2
251*4882a593Smuzhiyun vid = DIV_ROUND_UP(vdd - 265, 5);
252*4882a593Smuzhiyun #else
253*4882a593Smuzhiyun vid = DIV_ROUND_UP(vdd - 245, 5);
254*4882a593Smuzhiyun #endif
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun ret = i2c_write(i2caddress, IR36021_LOOP1_MANUAL_ID_OFFSET,
257*4882a593Smuzhiyun 1, (void *)&vid, sizeof(vid));
258*4882a593Smuzhiyun if (ret) {
259*4882a593Smuzhiyun printf("VID: failed to write VID\n");
260*4882a593Smuzhiyun return -1;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun wait = wait_for_new_voltage(vdd, i2caddress);
263*4882a593Smuzhiyun if (wait < 0)
264*4882a593Smuzhiyun return -1;
265*4882a593Smuzhiyun debug("VID: Waited %d us\n", wait * NUM_READINGS * WAIT_FOR_ADC);
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun vdd_last = wait_for_voltage_stable(i2caddress);
268*4882a593Smuzhiyun if (vdd_last < 0)
269*4882a593Smuzhiyun return -1;
270*4882a593Smuzhiyun debug("VID: Current voltage is %d mV\n", vdd_last);
271*4882a593Smuzhiyun return vdd_last;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun #endif
274*4882a593Smuzhiyun
set_voltage(int i2caddress,int vdd)275*4882a593Smuzhiyun static int set_voltage(int i2caddress, int vdd)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun int vdd_last = -1;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun #ifdef CONFIG_VOL_MONITOR_IR36021_SET
280*4882a593Smuzhiyun vdd_last = set_voltage_to_IR(i2caddress, vdd);
281*4882a593Smuzhiyun #else
282*4882a593Smuzhiyun #error Specific voltage monitor must be defined
283*4882a593Smuzhiyun #endif
284*4882a593Smuzhiyun return vdd_last;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun #ifdef CONFIG_FSL_LSCH3
adjust_vdd(ulong vdd_override)288*4882a593Smuzhiyun int adjust_vdd(ulong vdd_override)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun int re_enable = disable_interrupts();
291*4882a593Smuzhiyun struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
292*4882a593Smuzhiyun u32 fusesr;
293*4882a593Smuzhiyun u8 vid, buf;
294*4882a593Smuzhiyun int vdd_target, vdd_current, vdd_last;
295*4882a593Smuzhiyun int ret, i2caddress;
296*4882a593Smuzhiyun unsigned long vdd_string_override;
297*4882a593Smuzhiyun char *vdd_string;
298*4882a593Smuzhiyun static const uint16_t vdd[32] = {
299*4882a593Smuzhiyun 10500,
300*4882a593Smuzhiyun 0, /* reserved */
301*4882a593Smuzhiyun 9750,
302*4882a593Smuzhiyun 0, /* reserved */
303*4882a593Smuzhiyun 9500,
304*4882a593Smuzhiyun 0, /* reserved */
305*4882a593Smuzhiyun 0, /* reserved */
306*4882a593Smuzhiyun 0, /* reserved */
307*4882a593Smuzhiyun 0, /* reserved */
308*4882a593Smuzhiyun 0, /* reserved */
309*4882a593Smuzhiyun 0, /* reserved */
310*4882a593Smuzhiyun 0, /* reserved */
311*4882a593Smuzhiyun 0, /* reserved */
312*4882a593Smuzhiyun 0, /* reserved */
313*4882a593Smuzhiyun 0, /* reserved */
314*4882a593Smuzhiyun 0, /* reserved */
315*4882a593Smuzhiyun 10000, /* 1.0000V */
316*4882a593Smuzhiyun 0, /* reserved */
317*4882a593Smuzhiyun 10250,
318*4882a593Smuzhiyun 0, /* reserved */
319*4882a593Smuzhiyun 10500,
320*4882a593Smuzhiyun 0, /* reserved */
321*4882a593Smuzhiyun 0, /* reserved */
322*4882a593Smuzhiyun 0, /* reserved */
323*4882a593Smuzhiyun 0, /* reserved */
324*4882a593Smuzhiyun 0, /* reserved */
325*4882a593Smuzhiyun 0, /* reserved */
326*4882a593Smuzhiyun 0, /* reserved */
327*4882a593Smuzhiyun 0, /* reserved */
328*4882a593Smuzhiyun 0, /* reserved */
329*4882a593Smuzhiyun 0, /* reserved */
330*4882a593Smuzhiyun 0, /* reserved */
331*4882a593Smuzhiyun };
332*4882a593Smuzhiyun struct vdd_drive {
333*4882a593Smuzhiyun u8 vid;
334*4882a593Smuzhiyun unsigned voltage;
335*4882a593Smuzhiyun };
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
338*4882a593Smuzhiyun if (ret) {
339*4882a593Smuzhiyun debug("VID: I2C failed to switch channel\n");
340*4882a593Smuzhiyun ret = -1;
341*4882a593Smuzhiyun goto exit;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun ret = find_ir_chip_on_i2c();
344*4882a593Smuzhiyun if (ret < 0) {
345*4882a593Smuzhiyun printf("VID: Could not find voltage regulator on I2C.\n");
346*4882a593Smuzhiyun ret = -1;
347*4882a593Smuzhiyun goto exit;
348*4882a593Smuzhiyun } else {
349*4882a593Smuzhiyun i2caddress = ret;
350*4882a593Smuzhiyun debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun /* check IR chip work on Intel mode*/
354*4882a593Smuzhiyun ret = i2c_read(i2caddress,
355*4882a593Smuzhiyun IR36021_INTEL_MODE_OOFSET,
356*4882a593Smuzhiyun 1, (void *)&buf, 1);
357*4882a593Smuzhiyun if (ret) {
358*4882a593Smuzhiyun printf("VID: failed to read IR chip mode.\n");
359*4882a593Smuzhiyun ret = -1;
360*4882a593Smuzhiyun goto exit;
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun if ((buf & IR36021_MODE_MASK) != IR36021_INTEL_MODE) {
363*4882a593Smuzhiyun printf("VID: IR Chip is not used in Intel mode.\n");
364*4882a593Smuzhiyun ret = -1;
365*4882a593Smuzhiyun goto exit;
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun /* get the voltage ID from fuse status register */
369*4882a593Smuzhiyun fusesr = in_le32(&gur->dcfg_fusesr);
370*4882a593Smuzhiyun vid = (fusesr >> FSL_CHASSIS3_DCFG_FUSESR_ALTVID_SHIFT) &
371*4882a593Smuzhiyun FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK;
372*4882a593Smuzhiyun if ((vid == 0) || (vid == FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK)) {
373*4882a593Smuzhiyun vid = (fusesr >> FSL_CHASSIS3_DCFG_FUSESR_VID_SHIFT) &
374*4882a593Smuzhiyun FSL_CHASSIS3_DCFG_FUSESR_VID_MASK;
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun vdd_target = vdd[vid];
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun /* check override variable for overriding VDD */
379*4882a593Smuzhiyun vdd_string = env_get(CONFIG_VID_FLS_ENV);
380*4882a593Smuzhiyun if (vdd_override == 0 && vdd_string &&
381*4882a593Smuzhiyun !strict_strtoul(vdd_string, 10, &vdd_string_override))
382*4882a593Smuzhiyun vdd_override = vdd_string_override;
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun if (vdd_override >= VDD_MV_MIN && vdd_override <= VDD_MV_MAX) {
385*4882a593Smuzhiyun vdd_target = vdd_override * 10; /* convert to 1/10 mV */
386*4882a593Smuzhiyun debug("VDD override is %lu\n", vdd_override);
387*4882a593Smuzhiyun } else if (vdd_override != 0) {
388*4882a593Smuzhiyun printf("Invalid value.\n");
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun /* divide and round up by 10 to get a value in mV */
392*4882a593Smuzhiyun vdd_target = DIV_ROUND_UP(vdd_target, 10);
393*4882a593Smuzhiyun if (vdd_target == 0) {
394*4882a593Smuzhiyun debug("VID: VID not used\n");
395*4882a593Smuzhiyun ret = 0;
396*4882a593Smuzhiyun goto exit;
397*4882a593Smuzhiyun } else if (vdd_target < VDD_MV_MIN || vdd_target > VDD_MV_MAX) {
398*4882a593Smuzhiyun /* Check vdd_target is in valid range */
399*4882a593Smuzhiyun printf("VID: Target VID %d mV is not in range.\n",
400*4882a593Smuzhiyun vdd_target);
401*4882a593Smuzhiyun ret = -1;
402*4882a593Smuzhiyun goto exit;
403*4882a593Smuzhiyun } else {
404*4882a593Smuzhiyun debug("VID: vid = %d mV\n", vdd_target);
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun /*
408*4882a593Smuzhiyun * Read voltage monitor to check real voltage.
409*4882a593Smuzhiyun */
410*4882a593Smuzhiyun vdd_last = read_voltage(i2caddress);
411*4882a593Smuzhiyun if (vdd_last < 0) {
412*4882a593Smuzhiyun printf("VID: Couldn't read sensor abort VID adjustment\n");
413*4882a593Smuzhiyun ret = -1;
414*4882a593Smuzhiyun goto exit;
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun vdd_current = vdd_last;
417*4882a593Smuzhiyun debug("VID: Core voltage is currently at %d mV\n", vdd_last);
418*4882a593Smuzhiyun /*
419*4882a593Smuzhiyun * Adjust voltage to at or one step above target.
420*4882a593Smuzhiyun * As measurements are less precise than setting the values
421*4882a593Smuzhiyun * we may run through dummy steps that cancel each other
422*4882a593Smuzhiyun * when stepping up and then down.
423*4882a593Smuzhiyun */
424*4882a593Smuzhiyun while (vdd_last > 0 &&
425*4882a593Smuzhiyun vdd_last < vdd_target) {
426*4882a593Smuzhiyun vdd_current += IR_VDD_STEP_UP;
427*4882a593Smuzhiyun vdd_last = set_voltage(i2caddress, vdd_current);
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun while (vdd_last > 0 &&
430*4882a593Smuzhiyun vdd_last > vdd_target + (IR_VDD_STEP_DOWN - 1)) {
431*4882a593Smuzhiyun vdd_current -= IR_VDD_STEP_DOWN;
432*4882a593Smuzhiyun vdd_last = set_voltage(i2caddress, vdd_current);
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun if (vdd_last > 0)
436*4882a593Smuzhiyun printf("VID: Core voltage after adjustment is at %d mV\n",
437*4882a593Smuzhiyun vdd_last);
438*4882a593Smuzhiyun else
439*4882a593Smuzhiyun ret = -1;
440*4882a593Smuzhiyun exit:
441*4882a593Smuzhiyun if (re_enable)
442*4882a593Smuzhiyun enable_interrupts();
443*4882a593Smuzhiyun i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
444*4882a593Smuzhiyun return ret;
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun #else /* !CONFIG_FSL_LSCH3 */
adjust_vdd(ulong vdd_override)447*4882a593Smuzhiyun int adjust_vdd(ulong vdd_override)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun int re_enable = disable_interrupts();
450*4882a593Smuzhiyun #if defined(CONFIG_FSL_LSCH2)
451*4882a593Smuzhiyun struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
452*4882a593Smuzhiyun #else
453*4882a593Smuzhiyun ccsr_gur_t __iomem *gur =
454*4882a593Smuzhiyun (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
455*4882a593Smuzhiyun #endif
456*4882a593Smuzhiyun u32 fusesr;
457*4882a593Smuzhiyun u8 vid, buf;
458*4882a593Smuzhiyun int vdd_target, vdd_current, vdd_last;
459*4882a593Smuzhiyun int ret, i2caddress;
460*4882a593Smuzhiyun unsigned long vdd_string_override;
461*4882a593Smuzhiyun char *vdd_string;
462*4882a593Smuzhiyun static const uint16_t vdd[32] = {
463*4882a593Smuzhiyun 0, /* unused */
464*4882a593Smuzhiyun 9875, /* 0.9875V */
465*4882a593Smuzhiyun 9750,
466*4882a593Smuzhiyun 9625,
467*4882a593Smuzhiyun 9500,
468*4882a593Smuzhiyun 9375,
469*4882a593Smuzhiyun 9250,
470*4882a593Smuzhiyun 9125,
471*4882a593Smuzhiyun 9000,
472*4882a593Smuzhiyun 8875,
473*4882a593Smuzhiyun 8750,
474*4882a593Smuzhiyun 8625,
475*4882a593Smuzhiyun 8500,
476*4882a593Smuzhiyun 8375,
477*4882a593Smuzhiyun 8250,
478*4882a593Smuzhiyun 8125,
479*4882a593Smuzhiyun 10000, /* 1.0000V */
480*4882a593Smuzhiyun 10125,
481*4882a593Smuzhiyun 10250,
482*4882a593Smuzhiyun 10375,
483*4882a593Smuzhiyun 10500,
484*4882a593Smuzhiyun 10625,
485*4882a593Smuzhiyun 10750,
486*4882a593Smuzhiyun 10875,
487*4882a593Smuzhiyun 11000,
488*4882a593Smuzhiyun 0, /* reserved */
489*4882a593Smuzhiyun };
490*4882a593Smuzhiyun struct vdd_drive {
491*4882a593Smuzhiyun u8 vid;
492*4882a593Smuzhiyun unsigned voltage;
493*4882a593Smuzhiyun };
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
496*4882a593Smuzhiyun if (ret) {
497*4882a593Smuzhiyun debug("VID: I2C failed to switch channel\n");
498*4882a593Smuzhiyun ret = -1;
499*4882a593Smuzhiyun goto exit;
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun ret = find_ir_chip_on_i2c();
502*4882a593Smuzhiyun if (ret < 0) {
503*4882a593Smuzhiyun printf("VID: Could not find voltage regulator on I2C.\n");
504*4882a593Smuzhiyun ret = -1;
505*4882a593Smuzhiyun goto exit;
506*4882a593Smuzhiyun } else {
507*4882a593Smuzhiyun i2caddress = ret;
508*4882a593Smuzhiyun debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun /* check IR chip work on Intel mode*/
512*4882a593Smuzhiyun ret = i2c_read(i2caddress,
513*4882a593Smuzhiyun IR36021_INTEL_MODE_OOFSET,
514*4882a593Smuzhiyun 1, (void *)&buf, 1);
515*4882a593Smuzhiyun if (ret) {
516*4882a593Smuzhiyun printf("VID: failed to read IR chip mode.\n");
517*4882a593Smuzhiyun ret = -1;
518*4882a593Smuzhiyun goto exit;
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun if ((buf & IR36021_MODE_MASK) != IR36021_INTEL_MODE) {
521*4882a593Smuzhiyun printf("VID: IR Chip is not used in Intel mode.\n");
522*4882a593Smuzhiyun ret = -1;
523*4882a593Smuzhiyun goto exit;
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun /* get the voltage ID from fuse status register */
527*4882a593Smuzhiyun fusesr = in_be32(&gur->dcfg_fusesr);
528*4882a593Smuzhiyun /*
529*4882a593Smuzhiyun * VID is used according to the table below
530*4882a593Smuzhiyun * ---------------------------------------
531*4882a593Smuzhiyun * | DA_V |
532*4882a593Smuzhiyun * |-------------------------------------|
533*4882a593Smuzhiyun * | 5b00000 | 5b00001-5b11110 | 5b11111 |
534*4882a593Smuzhiyun * ---------------+---------+-----------------+---------|
535*4882a593Smuzhiyun * | D | 5b00000 | NO VID | VID = DA_V | NO VID |
536*4882a593Smuzhiyun * | A |----------+---------+-----------------+---------|
537*4882a593Smuzhiyun * | _ | 5b00001 |VID = | VID = |VID = |
538*4882a593Smuzhiyun * | V | ~ | DA_V_ALT| DA_V_ALT | DA_A_VLT|
539*4882a593Smuzhiyun * | _ | 5b11110 | | | |
540*4882a593Smuzhiyun * | A |----------+---------+-----------------+---------|
541*4882a593Smuzhiyun * | L | 5b11111 | No VID | VID = DA_V | NO VID |
542*4882a593Smuzhiyun * | T | | | | |
543*4882a593Smuzhiyun * ------------------------------------------------------
544*4882a593Smuzhiyun */
545*4882a593Smuzhiyun #ifdef CONFIG_FSL_LSCH2
546*4882a593Smuzhiyun vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_ALTVID_SHIFT) &
547*4882a593Smuzhiyun FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK;
548*4882a593Smuzhiyun if ((vid == 0) || (vid == FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK)) {
549*4882a593Smuzhiyun vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_VID_SHIFT) &
550*4882a593Smuzhiyun FSL_CHASSIS2_DCFG_FUSESR_VID_MASK;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun #else
553*4882a593Smuzhiyun vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_ALTVID_SHIFT) &
554*4882a593Smuzhiyun FSL_CORENET_DCFG_FUSESR_ALTVID_MASK;
555*4882a593Smuzhiyun if ((vid == 0) || (vid == FSL_CORENET_DCFG_FUSESR_ALTVID_MASK)) {
556*4882a593Smuzhiyun vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_VID_SHIFT) &
557*4882a593Smuzhiyun FSL_CORENET_DCFG_FUSESR_VID_MASK;
558*4882a593Smuzhiyun }
559*4882a593Smuzhiyun #endif
560*4882a593Smuzhiyun vdd_target = vdd[vid];
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun /* check override variable for overriding VDD */
563*4882a593Smuzhiyun vdd_string = env_get(CONFIG_VID_FLS_ENV);
564*4882a593Smuzhiyun if (vdd_override == 0 && vdd_string &&
565*4882a593Smuzhiyun !strict_strtoul(vdd_string, 10, &vdd_string_override))
566*4882a593Smuzhiyun vdd_override = vdd_string_override;
567*4882a593Smuzhiyun if (vdd_override >= VDD_MV_MIN && vdd_override <= VDD_MV_MAX) {
568*4882a593Smuzhiyun vdd_target = vdd_override * 10; /* convert to 1/10 mV */
569*4882a593Smuzhiyun debug("VDD override is %lu\n", vdd_override);
570*4882a593Smuzhiyun } else if (vdd_override != 0) {
571*4882a593Smuzhiyun printf("Invalid value.\n");
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun if (vdd_target == 0) {
574*4882a593Smuzhiyun debug("VID: VID not used\n");
575*4882a593Smuzhiyun ret = 0;
576*4882a593Smuzhiyun goto exit;
577*4882a593Smuzhiyun } else {
578*4882a593Smuzhiyun /* divide and round up by 10 to get a value in mV */
579*4882a593Smuzhiyun vdd_target = DIV_ROUND_UP(vdd_target, 10);
580*4882a593Smuzhiyun debug("VID: vid = %d mV\n", vdd_target);
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun /*
584*4882a593Smuzhiyun * Read voltage monitor to check real voltage.
585*4882a593Smuzhiyun */
586*4882a593Smuzhiyun vdd_last = read_voltage(i2caddress);
587*4882a593Smuzhiyun if (vdd_last < 0) {
588*4882a593Smuzhiyun printf("VID: Couldn't read sensor abort VID adjustment\n");
589*4882a593Smuzhiyun ret = -1;
590*4882a593Smuzhiyun goto exit;
591*4882a593Smuzhiyun }
592*4882a593Smuzhiyun vdd_current = vdd_last;
593*4882a593Smuzhiyun debug("VID: Core voltage is currently at %d mV\n", vdd_last);
594*4882a593Smuzhiyun /*
595*4882a593Smuzhiyun * Adjust voltage to at or one step above target.
596*4882a593Smuzhiyun * As measurements are less precise than setting the values
597*4882a593Smuzhiyun * we may run through dummy steps that cancel each other
598*4882a593Smuzhiyun * when stepping up and then down.
599*4882a593Smuzhiyun */
600*4882a593Smuzhiyun while (vdd_last > 0 &&
601*4882a593Smuzhiyun vdd_last < vdd_target) {
602*4882a593Smuzhiyun vdd_current += IR_VDD_STEP_UP;
603*4882a593Smuzhiyun vdd_last = set_voltage(i2caddress, vdd_current);
604*4882a593Smuzhiyun }
605*4882a593Smuzhiyun while (vdd_last > 0 &&
606*4882a593Smuzhiyun vdd_last > vdd_target + (IR_VDD_STEP_DOWN - 1)) {
607*4882a593Smuzhiyun vdd_current -= IR_VDD_STEP_DOWN;
608*4882a593Smuzhiyun vdd_last = set_voltage(i2caddress, vdd_current);
609*4882a593Smuzhiyun }
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun if (vdd_last > 0)
612*4882a593Smuzhiyun printf("VID: Core voltage after adjustment is at %d mV\n",
613*4882a593Smuzhiyun vdd_last);
614*4882a593Smuzhiyun else
615*4882a593Smuzhiyun ret = -1;
616*4882a593Smuzhiyun exit:
617*4882a593Smuzhiyun if (re_enable)
618*4882a593Smuzhiyun enable_interrupts();
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun return ret;
623*4882a593Smuzhiyun }
624*4882a593Smuzhiyun #endif
625*4882a593Smuzhiyun
print_vdd(void)626*4882a593Smuzhiyun static int print_vdd(void)
627*4882a593Smuzhiyun {
628*4882a593Smuzhiyun int vdd_last, ret, i2caddress;
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
631*4882a593Smuzhiyun if (ret) {
632*4882a593Smuzhiyun debug("VID : I2c failed to switch channel\n");
633*4882a593Smuzhiyun return -1;
634*4882a593Smuzhiyun }
635*4882a593Smuzhiyun ret = find_ir_chip_on_i2c();
636*4882a593Smuzhiyun if (ret < 0) {
637*4882a593Smuzhiyun printf("VID: Could not find voltage regulator on I2C.\n");
638*4882a593Smuzhiyun goto exit;
639*4882a593Smuzhiyun } else {
640*4882a593Smuzhiyun i2caddress = ret;
641*4882a593Smuzhiyun debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
642*4882a593Smuzhiyun }
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun /*
645*4882a593Smuzhiyun * Read voltage monitor to check real voltage.
646*4882a593Smuzhiyun */
647*4882a593Smuzhiyun vdd_last = read_voltage(i2caddress);
648*4882a593Smuzhiyun if (vdd_last < 0) {
649*4882a593Smuzhiyun printf("VID: Couldn't read sensor abort VID adjustment\n");
650*4882a593Smuzhiyun goto exit;
651*4882a593Smuzhiyun }
652*4882a593Smuzhiyun printf("VID: Core voltage is at %d mV\n", vdd_last);
653*4882a593Smuzhiyun exit:
654*4882a593Smuzhiyun i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun return ret < 0 ? -1 : 0;
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun
do_vdd_override(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])660*4882a593Smuzhiyun static int do_vdd_override(cmd_tbl_t *cmdtp,
661*4882a593Smuzhiyun int flag, int argc,
662*4882a593Smuzhiyun char * const argv[])
663*4882a593Smuzhiyun {
664*4882a593Smuzhiyun ulong override;
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun if (argc < 2)
667*4882a593Smuzhiyun return CMD_RET_USAGE;
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun if (!strict_strtoul(argv[1], 10, &override))
670*4882a593Smuzhiyun adjust_vdd(override); /* the value is checked by callee */
671*4882a593Smuzhiyun else
672*4882a593Smuzhiyun return CMD_RET_USAGE;
673*4882a593Smuzhiyun return 0;
674*4882a593Smuzhiyun }
675*4882a593Smuzhiyun
do_vdd_read(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])676*4882a593Smuzhiyun static int do_vdd_read(cmd_tbl_t *cmdtp,
677*4882a593Smuzhiyun int flag, int argc,
678*4882a593Smuzhiyun char * const argv[])
679*4882a593Smuzhiyun {
680*4882a593Smuzhiyun if (argc < 1)
681*4882a593Smuzhiyun return CMD_RET_USAGE;
682*4882a593Smuzhiyun print_vdd();
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun return 0;
685*4882a593Smuzhiyun }
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun U_BOOT_CMD(
688*4882a593Smuzhiyun vdd_override, 2, 0, do_vdd_override,
689*4882a593Smuzhiyun "override VDD",
690*4882a593Smuzhiyun " - override with the voltage specified in mV, eg. 1050"
691*4882a593Smuzhiyun );
692*4882a593Smuzhiyun
693*4882a593Smuzhiyun U_BOOT_CMD(
694*4882a593Smuzhiyun vdd_read, 1, 0, do_vdd_read,
695*4882a593Smuzhiyun "read VDD",
696*4882a593Smuzhiyun " - Read the voltage specified in mV"
697*4882a593Smuzhiyun )
698