]> git.sur5r.net Git - u-boot/blob - arch/arm/cpu/arm926ejs/mxs/spl_power_init.c
arm: mxs: Add debug outputs and comments to mxs SPL source files
[u-boot] / arch / arm / cpu / arm926ejs / mxs / spl_power_init.c
1 /*
2  * Freescale i.MX28 Boot PMIC init
3  *
4  * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
5  * on behalf of DENX Software Engineering GmbH
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9
10 #include <common.h>
11 #include <config.h>
12 #include <asm/io.h>
13 #include <asm/arch/imx-regs.h>
14
15 #include "mxs_init.h"
16
17 /**
18  * mxs_power_clock2xtal() - Switch CPU core clock source to 24MHz XTAL
19  *
20  * This function switches the CPU core clock from PLL to 24MHz XTAL
21  * oscilator. This is necessary if the PLL is being reconfigured to
22  * prevent crash of the CPU core.
23  */
24 static void mxs_power_clock2xtal(void)
25 {
26         struct mxs_clkctrl_regs *clkctrl_regs =
27                 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
28
29         debug("SPL: Switching CPU clock to 24MHz XTAL\n");
30
31         /* Set XTAL as CPU reference clock */
32         writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
33                 &clkctrl_regs->hw_clkctrl_clkseq_set);
34 }
35
36 /**
37  * mxs_power_clock2pll() - Switch CPU core clock source to PLL
38  *
39  * This function switches the CPU core clock from 24MHz XTAL oscilator
40  * to PLL. This can only be called once the PLL has re-locked and once
41  * the PLL is stable after reconfiguration.
42  */
43 static void mxs_power_clock2pll(void)
44 {
45         struct mxs_clkctrl_regs *clkctrl_regs =
46                 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
47
48         debug("SPL: Switching CPU core clock source to PLL\n");
49
50         /*
51          * TODO: Are we really? It looks like we turn on PLL0, but we then
52          * set the CLKCTRL_CLKSEQ_BYPASS_CPU bit of the (which was already
53          * set by mxs_power_clock2xtal()). Clearing this bit here seems to
54          * introduce some instability (causing the CPU core to hang). Maybe
55          * we aren't giving PLL0 enough time to stabilise?
56          */
57         setbits_le32(&clkctrl_regs->hw_clkctrl_pll0ctrl0,
58                         CLKCTRL_PLL0CTRL0_POWER);
59         early_delay(100);
60
61         /*
62          * TODO: Should the PLL0 FORCE_LOCK bit be set here followed be a
63          * wait on the PLL0 LOCK bit?
64          */
65         setbits_le32(&clkctrl_regs->hw_clkctrl_clkseq,
66                         CLKCTRL_CLKSEQ_BYPASS_CPU);
67 }
68
69 /**
70  * mxs_power_set_auto_restart() - Set the auto-restart bit
71  *
72  * This function ungates the RTC block and sets the AUTO_RESTART
73  * bit to work around a design bug on MX28EVK Rev. A .
74  */
75
76 static void mxs_power_set_auto_restart(void)
77 {
78         struct mxs_rtc_regs *rtc_regs =
79                 (struct mxs_rtc_regs *)MXS_RTC_BASE;
80
81         debug("SPL: Setting auto-restart bit\n");
82
83         writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr);
84         while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST)
85                 ;
86
87         writel(RTC_CTRL_CLKGATE, &rtc_regs->hw_rtc_ctrl_clr);
88         while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE)
89                 ;
90
91         /* Do nothing if flag already set */
92         if (readl(&rtc_regs->hw_rtc_persistent0) & RTC_PERSISTENT0_AUTO_RESTART)
93                 return;
94
95         while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
96                 ;
97
98         setbits_le32(&rtc_regs->hw_rtc_persistent0,
99                         RTC_PERSISTENT0_AUTO_RESTART);
100         writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_set);
101         writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_clr);
102         while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
103                 ;
104         while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_STALE_REGS_MASK)
105                 ;
106 }
107
108 /**
109  * mxs_power_set_linreg() - Set linear regulators 25mV below DC-DC converter
110  *
111  * This function configures the VDDIO, VDDA and VDDD linear regulators output
112  * to be 25mV below the VDDIO, VDDA and VDDD output from the DC-DC switching
113  * converter. This is the recommended setting for the case where we use both
114  * linear regulators and DC-DC converter to power the VDDIO rail.
115  */
116 static void mxs_power_set_linreg(void)
117 {
118         struct mxs_power_regs *power_regs =
119                 (struct mxs_power_regs *)MXS_POWER_BASE;
120
121         /* Set linear regulator 25mV below switching converter */
122         debug("SPL: Setting VDDD 25mV below DC-DC converters\n");
123         clrsetbits_le32(&power_regs->hw_power_vdddctrl,
124                         POWER_VDDDCTRL_LINREG_OFFSET_MASK,
125                         POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
126
127         debug("SPL: Setting VDDA 25mV below DC-DC converters\n");
128         clrsetbits_le32(&power_regs->hw_power_vddactrl,
129                         POWER_VDDACTRL_LINREG_OFFSET_MASK,
130                         POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW);
131
132         debug("SPL: Setting VDDIO 25mV below DC-DC converters\n");
133         clrsetbits_le32(&power_regs->hw_power_vddioctrl,
134                         POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
135                         POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
136 }
137
138 /**
139  * mxs_get_batt_volt() - Measure battery input voltage
140  *
141  * This function retrieves the battery input voltage and returns it.
142  */
143 static int mxs_get_batt_volt(void)
144 {
145         struct mxs_power_regs *power_regs =
146                 (struct mxs_power_regs *)MXS_POWER_BASE;
147         uint32_t volt = readl(&power_regs->hw_power_battmonitor);
148         volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
149         volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
150         volt *= 8;
151
152         debug("SPL: Battery Voltage = %dmV\n", volt);
153         return volt;
154 }
155
156 /**
157  * mxs_is_batt_ready() - Test if the battery provides enough voltage to boot
158  *
159  * This function checks if the battery input voltage is higher than 3.6V and
160  * therefore allows the system to successfully boot using this power source.
161  */
162 static int mxs_is_batt_ready(void)
163 {
164         return (mxs_get_batt_volt() >= 3600);
165 }
166
167 /**
168  * mxs_is_batt_good() - Test if battery is operational at all
169  *
170  * This function starts recharging the battery and tests if the input current
171  * provided by the 5V input recharging the battery is also sufficient to power
172  * the DC-DC converter.
173  */
174 static int mxs_is_batt_good(void)
175 {
176         struct mxs_power_regs *power_regs =
177                 (struct mxs_power_regs *)MXS_POWER_BASE;
178         uint32_t volt = mxs_get_batt_volt();
179
180         if ((volt >= 2400) && (volt <= 4300)) {
181                 debug("SPL: Battery is good\n");
182                 return 1;
183         }
184
185         clrsetbits_le32(&power_regs->hw_power_5vctrl,
186                 POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
187                 0x3 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
188         writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
189                 &power_regs->hw_power_5vctrl_clr);
190
191         clrsetbits_le32(&power_regs->hw_power_charge,
192                 POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
193                 POWER_CHARGE_STOP_ILIMIT_10MA | 0x3);
194
195         writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_clr);
196         writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
197                 &power_regs->hw_power_5vctrl_clr);
198
199         early_delay(500000);
200
201         volt = mxs_get_batt_volt();
202
203         if (volt >= 3500) {
204                 debug("SPL: Battery Voltage too high\n");
205                 return 0;
206         }
207
208         if (volt >= 2400) {
209                 debug("SPL: Battery is good\n");
210                 return 1;
211         }
212
213         writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
214                 &power_regs->hw_power_charge_clr);
215         writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
216
217         debug("SPL: Battery Voltage too low\n");
218         return 0;
219 }
220
221 /**
222  * mxs_power_setup_5v_detect() - Start the 5V input detection comparator
223  *
224  * This function enables the 5V detection comparator and sets the 5V valid
225  * threshold to 4.4V . We use 4.4V threshold here to make sure that even
226  * under high load, the voltage drop on the 5V input won't be so critical
227  * to cause undervolt on the 4P2 linear regulator supplying the DC-DC
228  * converter and thus making the system crash.
229  */
230 static void mxs_power_setup_5v_detect(void)
231 {
232         struct mxs_power_regs *power_regs =
233                 (struct mxs_power_regs *)MXS_POWER_BASE;
234
235         /* Start 5V detection */
236         debug("SPL: Starting 5V input detection comparator\n");
237         clrsetbits_le32(&power_regs->hw_power_5vctrl,
238                         POWER_5VCTRL_VBUSVALID_TRSH_MASK,
239                         POWER_5VCTRL_VBUSVALID_TRSH_4V4 |
240                         POWER_5VCTRL_PWRUP_VBUS_CMPS);
241 }
242
243 /**
244  * mxs_src_power_init() - Preconfigure the power block
245  *
246  * This function configures reasonable values for the DC-DC control loop
247  * and battery monitor.
248  */
249 static void mxs_src_power_init(void)
250 {
251         struct mxs_power_regs *power_regs =
252                 (struct mxs_power_regs *)MXS_POWER_BASE;
253
254         debug("SPL: Pre-Configuring power block\n");
255
256         /* Improve efficieny and reduce transient ripple */
257         writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST |
258                 POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set);
259
260         clrsetbits_le32(&power_regs->hw_power_dclimits,
261                         POWER_DCLIMITS_POSLIMIT_BUCK_MASK,
262                         0x30 << POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET);
263
264         setbits_le32(&power_regs->hw_power_battmonitor,
265                         POWER_BATTMONITOR_EN_BATADJ);
266
267         /* Increase the RCSCALE level for quick DCDC response to dynamic load */
268         clrsetbits_le32(&power_regs->hw_power_loopctrl,
269                         POWER_LOOPCTRL_EN_RCSCALE_MASK,
270                         POWER_LOOPCTRL_RCSCALE_THRESH |
271                         POWER_LOOPCTRL_EN_RCSCALE_8X);
272
273         clrsetbits_le32(&power_regs->hw_power_minpwr,
274                         POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
275
276         /* 5V to battery handoff ... FIXME */
277         setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
278         early_delay(30);
279         clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
280 }
281
282 /**
283  * mxs_power_init_4p2_params() - Configure the parameters of the 4P2 regulator
284  *
285  * This function configures the necessary parameters for the 4P2 linear
286  * regulator to supply the DC-DC converter from 5V input.
287  */
288 static void mxs_power_init_4p2_params(void)
289 {
290         struct mxs_power_regs *power_regs =
291                 (struct mxs_power_regs *)MXS_POWER_BASE;
292
293         debug("SPL: Configuring common 4P2 regulator params\n");
294
295         /* Setup 4P2 parameters */
296         clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
297                 POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK,
298                 POWER_DCDC4P2_TRG_4V2 | (31 << POWER_DCDC4P2_CMPTRIP_OFFSET));
299
300         clrsetbits_le32(&power_regs->hw_power_5vctrl,
301                 POWER_5VCTRL_HEADROOM_ADJ_MASK,
302                 0x4 << POWER_5VCTRL_HEADROOM_ADJ_OFFSET);
303
304         clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
305                 POWER_DCDC4P2_DROPOUT_CTRL_MASK,
306                 POWER_DCDC4P2_DROPOUT_CTRL_100MV |
307                 POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL);
308
309         clrsetbits_le32(&power_regs->hw_power_5vctrl,
310                 POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
311                 0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
312 }
313
314 /**
315  * mxs_enable_4p2_dcdc_input() - Enable or disable the DCDC input from 4P2
316  * @xfer:       Select if the input shall be enabled or disabled
317  *
318  * This function enables or disables the 4P2 input into the DC-DC converter.
319  */
320 static void mxs_enable_4p2_dcdc_input(int xfer)
321 {
322         struct mxs_power_regs *power_regs =
323                 (struct mxs_power_regs *)MXS_POWER_BASE;
324         uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo;
325         uint32_t prev_5v_brnout, prev_5v_droop;
326
327         debug("SPL: %s 4P2 DC-DC Input\n", xfer ? "Enabling" : "Disabling");
328
329         prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) &
330                                 POWER_5VCTRL_PWDN_5VBRNOUT;
331         prev_5v_droop = readl(&power_regs->hw_power_ctrl) &
332                                 POWER_CTRL_ENIRQ_VDD5V_DROOP;
333
334         clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
335         writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
336                 &power_regs->hw_power_reset);
337
338         clrbits_le32(&power_regs->hw_power_ctrl, POWER_CTRL_ENIRQ_VDD5V_DROOP);
339
340         if (xfer && (readl(&power_regs->hw_power_5vctrl) &
341                         POWER_5VCTRL_ENABLE_DCDC)) {
342                 return;
343         }
344
345         /*
346          * Recording orignal values that will be modified temporarlily
347          * to handle a chip bug. See chip errata for CQ ENGR00115837
348          */
349         tmp = readl(&power_regs->hw_power_5vctrl);
350         vbus_thresh = tmp & POWER_5VCTRL_VBUSVALID_TRSH_MASK;
351         vbus_5vdetect = tmp & POWER_5VCTRL_VBUSVALID_5VDETECT;
352
353         pwd_bo = readl(&power_regs->hw_power_minpwr) & POWER_MINPWR_PWD_BO;
354
355         /*
356          * Disable mechanisms that get erroneously tripped by when setting
357          * the DCDC4P2 EN_DCDC
358          */
359         clrbits_le32(&power_regs->hw_power_5vctrl,
360                 POWER_5VCTRL_VBUSVALID_5VDETECT |
361                 POWER_5VCTRL_VBUSVALID_TRSH_MASK);
362
363         writel(POWER_MINPWR_PWD_BO, &power_regs->hw_power_minpwr_set);
364
365         if (xfer) {
366                 setbits_le32(&power_regs->hw_power_5vctrl,
367                                 POWER_5VCTRL_DCDC_XFER);
368                 early_delay(20);
369                 clrbits_le32(&power_regs->hw_power_5vctrl,
370                                 POWER_5VCTRL_DCDC_XFER);
371
372                 setbits_le32(&power_regs->hw_power_5vctrl,
373                                 POWER_5VCTRL_ENABLE_DCDC);
374         } else {
375                 setbits_le32(&power_regs->hw_power_dcdc4p2,
376                                 POWER_DCDC4P2_ENABLE_DCDC);
377         }
378
379         early_delay(25);
380
381         clrsetbits_le32(&power_regs->hw_power_5vctrl,
382                         POWER_5VCTRL_VBUSVALID_TRSH_MASK, vbus_thresh);
383
384         if (vbus_5vdetect)
385                 writel(vbus_5vdetect, &power_regs->hw_power_5vctrl_set);
386
387         if (!pwd_bo)
388                 clrbits_le32(&power_regs->hw_power_minpwr, POWER_MINPWR_PWD_BO);
389
390         while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ)
391                 writel(POWER_CTRL_VBUS_VALID_IRQ,
392                         &power_regs->hw_power_ctrl_clr);
393
394         if (prev_5v_brnout) {
395                 writel(POWER_5VCTRL_PWDN_5VBRNOUT,
396                         &power_regs->hw_power_5vctrl_set);
397                 writel(POWER_RESET_UNLOCK_KEY,
398                         &power_regs->hw_power_reset);
399         } else {
400                 writel(POWER_5VCTRL_PWDN_5VBRNOUT,
401                         &power_regs->hw_power_5vctrl_clr);
402                 writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
403                         &power_regs->hw_power_reset);
404         }
405
406         while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VDD5V_DROOP_IRQ)
407                 writel(POWER_CTRL_VDD5V_DROOP_IRQ,
408                         &power_regs->hw_power_ctrl_clr);
409
410         if (prev_5v_droop)
411                 clrbits_le32(&power_regs->hw_power_ctrl,
412                                 POWER_CTRL_ENIRQ_VDD5V_DROOP);
413         else
414                 setbits_le32(&power_regs->hw_power_ctrl,
415                                 POWER_CTRL_ENIRQ_VDD5V_DROOP);
416 }
417
418 /**
419  * mxs_power_init_4p2_regulator() - Start the 4P2 regulator
420  *
421  * This function enables the 4P2 regulator and switches the DC-DC converter
422  * to use the 4P2 input.
423  */
424 static void mxs_power_init_4p2_regulator(void)
425 {
426         struct mxs_power_regs *power_regs =
427                 (struct mxs_power_regs *)MXS_POWER_BASE;
428         uint32_t tmp, tmp2;
429
430         debug("SPL: Enabling 4P2 regulator\n");
431
432         setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2);
433
434         writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set);
435
436         writel(POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
437                 &power_regs->hw_power_5vctrl_clr);
438         clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_TRG_MASK);
439
440         /* Power up the 4p2 rail and logic/control */
441         writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
442                 &power_regs->hw_power_5vctrl_clr);
443
444         /*
445          * Start charging up the 4p2 capacitor. We ramp of this charge
446          * gradually to avoid large inrush current from the 5V cable which can
447          * cause transients/problems
448          */
449         debug("SPL: Charging 4P2 capacitor\n");
450         mxs_enable_4p2_dcdc_input(0);
451
452         if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
453                 /*
454                  * If we arrived here, we were unable to recover from mx23 chip
455                  * errata 5837. 4P2 is disabled and sufficient battery power is
456                  * not present. Exiting to not enable DCDC power during 5V
457                  * connected state.
458                  */
459                 clrbits_le32(&power_regs->hw_power_dcdc4p2,
460                         POWER_DCDC4P2_ENABLE_DCDC);
461                 writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
462                         &power_regs->hw_power_5vctrl_set);
463
464                 debug("SPL: Unable to recover from mx23 errata 5837\n");
465                 hang();
466         }
467
468         /*
469          * Here we set the 4p2 brownout level to something very close to 4.2V.
470          * We then check the brownout status. If the brownout status is false,
471          * the voltage is already close to the target voltage of 4.2V so we
472          * can go ahead and set the 4P2 current limit to our max target limit.
473          * If the brownout status is true, we need to ramp us the current limit
474          * so that we don't cause large inrush current issues. We step up the
475          * current limit until the brownout status is false or until we've
476          * reached our maximum defined 4p2 current limit.
477          */
478         debug("SPL: Setting 4P2 brownout level\n");
479         clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
480                         POWER_DCDC4P2_BO_MASK,
481                         22 << POWER_DCDC4P2_BO_OFFSET); /* 4.15V */
482
483         if (!(readl(&power_regs->hw_power_sts) & POWER_STS_DCDC_4P2_BO)) {
484                 setbits_le32(&power_regs->hw_power_5vctrl,
485                         0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
486         } else {
487                 tmp = (readl(&power_regs->hw_power_5vctrl) &
488                         POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK) >>
489                         POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
490                 while (tmp < 0x3f) {
491                         if (!(readl(&power_regs->hw_power_sts) &
492                                         POWER_STS_DCDC_4P2_BO)) {
493                                 tmp = readl(&power_regs->hw_power_5vctrl);
494                                 tmp |= POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
495                                 early_delay(100);
496                                 writel(tmp, &power_regs->hw_power_5vctrl);
497                                 break;
498                         } else {
499                                 tmp++;
500                                 tmp2 = readl(&power_regs->hw_power_5vctrl);
501                                 tmp2 &= ~POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
502                                 tmp2 |= tmp <<
503                                         POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
504                                 writel(tmp2, &power_regs->hw_power_5vctrl);
505                                 early_delay(100);
506                         }
507                 }
508         }
509
510         clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
511         writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
512 }
513
514 /**
515  * mxs_power_init_dcdc_4p2_source() - Switch DC-DC converter to 4P2 source
516  *
517  * This function configures the DC-DC converter to be supplied from the 4P2
518  * linear regulator.
519  */
520 static void mxs_power_init_dcdc_4p2_source(void)
521 {
522         struct mxs_power_regs *power_regs =
523                 (struct mxs_power_regs *)MXS_POWER_BASE;
524
525         debug("SPL: Switching DC-DC converters to 4P2\n");
526
527         if (!(readl(&power_regs->hw_power_dcdc4p2) &
528                 POWER_DCDC4P2_ENABLE_DCDC)) {
529                 debug("SPL: Already switched - aborting\n");
530                 hang();
531         }
532
533         mxs_enable_4p2_dcdc_input(1);
534
535         if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
536                 clrbits_le32(&power_regs->hw_power_dcdc4p2,
537                         POWER_DCDC4P2_ENABLE_DCDC);
538                 writel(POWER_5VCTRL_ENABLE_DCDC,
539                         &power_regs->hw_power_5vctrl_clr);
540                 writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
541                         &power_regs->hw_power_5vctrl_set);
542         }
543 }
544
545 /**
546  * mxs_power_enable_4p2() - Power up the 4P2 regulator
547  *
548  * This function drives the process of powering up the 4P2 linear regulator
549  * and switching the DC-DC converter input over to the 4P2 linear regulator.
550  */
551 static void mxs_power_enable_4p2(void)
552 {
553         struct mxs_power_regs *power_regs =
554                 (struct mxs_power_regs *)MXS_POWER_BASE;
555         uint32_t vdddctrl, vddactrl, vddioctrl;
556         uint32_t tmp;
557
558         debug("SPL: Powering up 4P2 regulator\n");
559
560         vdddctrl = readl(&power_regs->hw_power_vdddctrl);
561         vddactrl = readl(&power_regs->hw_power_vddactrl);
562         vddioctrl = readl(&power_regs->hw_power_vddioctrl);
563
564         setbits_le32(&power_regs->hw_power_vdddctrl,
565                 POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
566                 POWER_VDDDCTRL_PWDN_BRNOUT);
567
568         setbits_le32(&power_regs->hw_power_vddactrl,
569                 POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG |
570                 POWER_VDDACTRL_PWDN_BRNOUT);
571
572         setbits_le32(&power_regs->hw_power_vddioctrl,
573                 POWER_VDDIOCTRL_DISABLE_FET | POWER_VDDIOCTRL_PWDN_BRNOUT);
574
575         mxs_power_init_4p2_params();
576         mxs_power_init_4p2_regulator();
577
578         /* Shutdown battery (none present) */
579         if (!mxs_is_batt_ready()) {
580                 clrbits_le32(&power_regs->hw_power_dcdc4p2,
581                                 POWER_DCDC4P2_BO_MASK);
582                 writel(POWER_CTRL_DCDC4P2_BO_IRQ,
583                                 &power_regs->hw_power_ctrl_clr);
584                 writel(POWER_CTRL_ENIRQ_DCDC4P2_BO,
585                                 &power_regs->hw_power_ctrl_clr);
586         }
587
588         mxs_power_init_dcdc_4p2_source();
589
590         writel(vdddctrl, &power_regs->hw_power_vdddctrl);
591         early_delay(20);
592         writel(vddactrl, &power_regs->hw_power_vddactrl);
593         early_delay(20);
594         writel(vddioctrl, &power_regs->hw_power_vddioctrl);
595
596         /*
597          * Check if FET is enabled on either powerout and if so,
598          * disable load.
599          */
600         tmp = 0;
601         tmp |= !(readl(&power_regs->hw_power_vdddctrl) &
602                         POWER_VDDDCTRL_DISABLE_FET);
603         tmp |= !(readl(&power_regs->hw_power_vddactrl) &
604                         POWER_VDDACTRL_DISABLE_FET);
605         tmp |= !(readl(&power_regs->hw_power_vddioctrl) &
606                         POWER_VDDIOCTRL_DISABLE_FET);
607         if (tmp)
608                 writel(POWER_CHARGE_ENABLE_LOAD,
609                         &power_regs->hw_power_charge_clr);
610
611         debug("SPL: 4P2 regulator powered-up\n");
612 }
613
614 /**
615  * mxs_boot_valid_5v() - Boot from 5V supply
616  *
617  * This function configures the power block to boot from valid 5V input.
618  * This is called only if the 5V is reliable and can properly supply the
619  * CPU. This function proceeds to configure the 4P2 converter to be supplied
620  * from the 5V input.
621  */
622 static void mxs_boot_valid_5v(void)
623 {
624         struct mxs_power_regs *power_regs =
625                 (struct mxs_power_regs *)MXS_POWER_BASE;
626
627         debug("SPL: Booting from 5V supply\n");
628
629         /*
630          * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V
631          * disconnect event. FIXME
632          */
633         writel(POWER_5VCTRL_VBUSVALID_5VDETECT,
634                 &power_regs->hw_power_5vctrl_set);
635
636         /* Configure polarity to check for 5V disconnection. */
637         writel(POWER_CTRL_POLARITY_VBUSVALID |
638                 POWER_CTRL_POLARITY_VDD5V_GT_VDDIO,
639                 &power_regs->hw_power_ctrl_clr);
640
641         writel(POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_VDD5V_GT_VDDIO_IRQ,
642                 &power_regs->hw_power_ctrl_clr);
643
644         mxs_power_enable_4p2();
645 }
646
647 /**
648  * mxs_powerdown() - Shut down the system
649  *
650  * This function powers down the CPU completely.
651  */
652 static void mxs_powerdown(void)
653 {
654         struct mxs_power_regs *power_regs =
655                 (struct mxs_power_regs *)MXS_POWER_BASE;
656
657         debug("Powering Down\n");
658
659         writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset);
660         writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
661                 &power_regs->hw_power_reset);
662 }
663
664 /**
665  * mxs_batt_boot() - Configure the power block to boot from battery input
666  *
667  * This function configures the power block to boot from the battery voltage
668  * supply.
669  */
670 static void mxs_batt_boot(void)
671 {
672         struct mxs_power_regs *power_regs =
673                 (struct mxs_power_regs *)MXS_POWER_BASE;
674
675         debug("SPL: Configuring power block to boot from battery\n");
676
677         clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
678         clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_ENABLE_DCDC);
679
680         clrbits_le32(&power_regs->hw_power_dcdc4p2,
681                         POWER_DCDC4P2_ENABLE_DCDC | POWER_DCDC4P2_ENABLE_4P2);
682         writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_clr);
683
684         /* 5V to battery handoff. */
685         setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
686         early_delay(30);
687         clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
688
689         writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, &power_regs->hw_power_ctrl_clr);
690
691         clrsetbits_le32(&power_regs->hw_power_minpwr,
692                         POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
693
694         mxs_power_set_linreg();
695
696         clrbits_le32(&power_regs->hw_power_vdddctrl,
697                 POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG);
698
699         clrbits_le32(&power_regs->hw_power_vddactrl,
700                 POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG);
701
702         clrbits_le32(&power_regs->hw_power_vddioctrl,
703                 POWER_VDDIOCTRL_DISABLE_FET);
704
705         setbits_le32(&power_regs->hw_power_5vctrl,
706                 POWER_5VCTRL_PWD_CHARGE_4P2_MASK);
707
708         setbits_le32(&power_regs->hw_power_5vctrl,
709                 POWER_5VCTRL_ENABLE_DCDC);
710
711         clrsetbits_le32(&power_regs->hw_power_5vctrl,
712                 POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
713                 0x8 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
714
715         mxs_power_enable_4p2();
716 }
717
718 /**
719  * mxs_handle_5v_conflict() - Test if the 5V input is reliable
720  *
721  * This function tests if the 5V input can reliably supply the system. If it
722  * can, then proceed to configuring the system to boot from 5V source, otherwise
723  * try booting from battery supply. If we can not boot from battery supply
724  * either, shut down the system.
725  */
726 static void mxs_handle_5v_conflict(void)
727 {
728         struct mxs_power_regs *power_regs =
729                 (struct mxs_power_regs *)MXS_POWER_BASE;
730         uint32_t tmp;
731
732         debug("SPL: Resolving 5V conflict\n");
733
734         setbits_le32(&power_regs->hw_power_vddioctrl,
735                         POWER_VDDIOCTRL_BO_OFFSET_MASK);
736
737         for (;;) {
738                 tmp = readl(&power_regs->hw_power_sts);
739
740                 if (tmp & POWER_STS_VDDIO_BO) {
741                         /*
742                          * VDDIO has a brownout, then the VDD5V_GT_VDDIO becomes
743                          * unreliable
744                          */
745                         debug("SPL: VDDIO has a brownout\n");
746                         mxs_powerdown();
747                         break;
748                 }
749
750                 if (tmp & POWER_STS_VDD5V_GT_VDDIO) {
751                         debug("SPL: POWER_STS_VDD5V_GT_VDDIO is set\n");
752                         mxs_boot_valid_5v();
753                         break;
754                 } else {
755                         debug("SPL: POWER_STS_VDD5V_GT_VDDIO is not set\n");
756                         mxs_powerdown();
757                         break;
758                 }
759
760                 /*
761                  * TODO: I can't see this being reached. We'll either
762                  * powerdown or boot from a stable 5V supply.
763                  */
764                 if (tmp & POWER_STS_PSWITCH_MASK) {
765                         debug("SPL: POWER_STS_PSWITCH_MASK is set\n");
766                         mxs_batt_boot();
767                         break;
768                 }
769         }
770 }
771
772 /**
773  * mxs_5v_boot() - Configure the power block to boot from 5V input
774  *
775  * This function handles configuration of the power block when supplied by
776  * a 5V input.
777  */
778 static void mxs_5v_boot(void)
779 {
780         struct mxs_power_regs *power_regs =
781                 (struct mxs_power_regs *)MXS_POWER_BASE;
782
783         debug("SPL: Configuring power block to boot from 5V input\n");
784
785         /*
786          * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID,
787          * but their implementation always returns 1 so we omit it here.
788          */
789         if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
790                 debug("SPL: 5V VDD good\n");
791                 mxs_boot_valid_5v();
792                 return;
793         }
794
795         early_delay(1000);
796         if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
797                 debug("SPL: 5V VDD good (after delay)\n");
798                 mxs_boot_valid_5v();
799                 return;
800         }
801
802         debug("SPL: 5V VDD not good\n");
803         mxs_handle_5v_conflict();
804 }
805
806 /**
807  * mxs_init_batt_bo() - Configure battery brownout threshold
808  *
809  * This function configures the battery input brownout threshold. The value
810  * at which the battery brownout happens is configured to 3.0V in the code.
811  */
812 static void mxs_init_batt_bo(void)
813 {
814         struct mxs_power_regs *power_regs =
815                 (struct mxs_power_regs *)MXS_POWER_BASE;
816
817         debug("SPL: Initialising battery brown-out level to 3.0V\n");
818
819         /* Brownout at 3V */
820         clrsetbits_le32(&power_regs->hw_power_battmonitor,
821                 POWER_BATTMONITOR_BRWNOUT_LVL_MASK,
822                 15 << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
823
824         writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr);
825         writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
826 }
827
828 /**
829  * mxs_switch_vddd_to_dcdc_source() - Switch VDDD rail to DC-DC converter
830  *
831  * This function turns off the VDDD linear regulator and therefore makes
832  * the VDDD rail be supplied only by the DC-DC converter.
833  */
834 static void mxs_switch_vddd_to_dcdc_source(void)
835 {
836         struct mxs_power_regs *power_regs =
837                 (struct mxs_power_regs *)MXS_POWER_BASE;
838
839         debug("SPL: Switching VDDD to DC-DC converters\n");
840
841         clrsetbits_le32(&power_regs->hw_power_vdddctrl,
842                 POWER_VDDDCTRL_LINREG_OFFSET_MASK,
843                 POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
844
845         clrbits_le32(&power_regs->hw_power_vdddctrl,
846                 POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
847                 POWER_VDDDCTRL_DISABLE_STEPPING);
848 }
849
850 /**
851  * mxs_power_configure_power_source() - Configure power block source
852  *
853  * This function is the core of the power configuration logic. The function
854  * selects the power block input source and configures the whole power block
855  * accordingly. After the configuration is complete and the system is stable
856  * again, the function switches the CPU clock source back to PLL. Finally,
857  * the function switches the voltage rails to DC-DC converter.
858  */
859 static void mxs_power_configure_power_source(void)
860 {
861         int batt_ready, batt_good;
862         struct mxs_power_regs *power_regs =
863                 (struct mxs_power_regs *)MXS_POWER_BASE;
864         struct mxs_lradc_regs *lradc_regs =
865                 (struct mxs_lradc_regs *)MXS_LRADC_BASE;
866
867         debug("SPL: Configuring power source\n");
868
869         mxs_src_power_init();
870
871         if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
872                 batt_ready = mxs_is_batt_ready();
873                 if (batt_ready) {
874                         /* 5V source detected, good battery detected. */
875                         mxs_batt_boot();
876                 } else {
877                         batt_good = mxs_is_batt_good();
878                         if (!batt_good) {
879                                 /* 5V source detected, bad battery detected. */
880                                 writel(LRADC_CONVERSION_AUTOMATIC,
881                                         &lradc_regs->hw_lradc_conversion_clr);
882                                 clrbits_le32(&power_regs->hw_power_battmonitor,
883                                         POWER_BATTMONITOR_BATT_VAL_MASK);
884                         }
885                         mxs_5v_boot();
886                 }
887         } else {
888                 /* 5V not detected, booting from battery. */
889                 mxs_batt_boot();
890         }
891
892         /*
893          * TODO: Do not switch CPU clock to PLL if we are VDD5V is sourced
894          * from USB VBUS
895          */
896         mxs_power_clock2pll();
897
898         mxs_init_batt_bo();
899
900         mxs_switch_vddd_to_dcdc_source();
901
902 #ifdef CONFIG_MX23
903         /* Fire up the VDDMEM LinReg now that we're all set. */
904         debug("SPL: Enabling mx23 VDDMEM linear regulator\n");
905         writel(POWER_VDDMEMCTRL_ENABLE_LINREG | POWER_VDDMEMCTRL_ENABLE_ILIMIT,
906                 &power_regs->hw_power_vddmemctrl);
907 #endif
908 }
909
910 /**
911  * mxs_enable_output_rail_protection() - Enable power rail protection
912  *
913  * This function enables overload protection on the power rails. This is
914  * triggered if the power rails' voltage drops rapidly due to overload and
915  * in such case, the supply to the powerrail is cut-off, protecting the
916  * CPU from damage. Note that under such condition, the system will likely
917  * crash or misbehave.
918  */
919 static void mxs_enable_output_rail_protection(void)
920 {
921         struct mxs_power_regs *power_regs =
922                 (struct mxs_power_regs *)MXS_POWER_BASE;
923
924         debug("SPL: Enabling output rail protection\n");
925
926         writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
927                 POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr);
928
929         setbits_le32(&power_regs->hw_power_vdddctrl,
930                         POWER_VDDDCTRL_PWDN_BRNOUT);
931
932         setbits_le32(&power_regs->hw_power_vddactrl,
933                         POWER_VDDACTRL_PWDN_BRNOUT);
934
935         setbits_le32(&power_regs->hw_power_vddioctrl,
936                         POWER_VDDIOCTRL_PWDN_BRNOUT);
937 }
938
939 /**
940  * mxs_get_vddio_power_source_off() - Get VDDIO rail power source
941  *
942  * This function tests if the VDDIO rail is supplied by linear regulator
943  * or by the DC-DC converter. Returns 1 if powered by linear regulator,
944  * returns 0 if powered by the DC-DC converter.
945  */
946 static int mxs_get_vddio_power_source_off(void)
947 {
948         struct mxs_power_regs *power_regs =
949                 (struct mxs_power_regs *)MXS_POWER_BASE;
950         uint32_t tmp;
951
952         if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
953                 tmp = readl(&power_regs->hw_power_vddioctrl);
954                 if (tmp & POWER_VDDIOCTRL_DISABLE_FET) {
955                         if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
956                                 POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS) {
957                                 return 1;
958                         }
959                 }
960
961                 if (!(readl(&power_regs->hw_power_5vctrl) &
962                         POWER_5VCTRL_ENABLE_DCDC)) {
963                         if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
964                                 POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS) {
965                                 return 1;
966                         }
967                 }
968         }
969
970         return 0;
971
972 }
973
974 /**
975  * mxs_get_vddd_power_source_off() - Get VDDD rail power source
976  *
977  * This function tests if the VDDD rail is supplied by linear regulator
978  * or by the DC-DC converter. Returns 1 if powered by linear regulator,
979  * returns 0 if powered by the DC-DC converter.
980  */
981 static int mxs_get_vddd_power_source_off(void)
982 {
983         struct mxs_power_regs *power_regs =
984                 (struct mxs_power_regs *)MXS_POWER_BASE;
985         uint32_t tmp;
986
987         tmp = readl(&power_regs->hw_power_vdddctrl);
988         if (tmp & POWER_VDDDCTRL_DISABLE_FET) {
989                 if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
990                         POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
991                         return 1;
992                 }
993         }
994
995         if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
996                 if (!(readl(&power_regs->hw_power_5vctrl) &
997                         POWER_5VCTRL_ENABLE_DCDC)) {
998                         return 1;
999                 }
1000         }
1001
1002         if (!(tmp & POWER_VDDDCTRL_ENABLE_LINREG)) {
1003                 if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
1004                         POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW) {
1005                         return 1;
1006                 }
1007         }
1008
1009         return 0;
1010 }
1011
1012 struct mxs_vddx_cfg {
1013         uint32_t                *reg;
1014         uint8_t                 step_mV;
1015         uint16_t                lowest_mV;
1016         int                     (*powered_by_linreg)(void);
1017         uint32_t                trg_mask;
1018         uint32_t                bo_irq;
1019         uint32_t                bo_enirq;
1020         uint32_t                bo_offset_mask;
1021         uint32_t                bo_offset_offset;
1022 };
1023
1024 static const struct mxs_vddx_cfg mxs_vddio_cfg = {
1025         .reg                    = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
1026                                         hw_power_vddioctrl),
1027 #if defined(CONFIG_MX23)
1028         .step_mV                = 25,
1029 #else
1030         .step_mV                = 50,
1031 #endif
1032         .lowest_mV              = 2800,
1033         .powered_by_linreg      = mxs_get_vddio_power_source_off,
1034         .trg_mask               = POWER_VDDIOCTRL_TRG_MASK,
1035         .bo_irq                 = POWER_CTRL_VDDIO_BO_IRQ,
1036         .bo_enirq               = POWER_CTRL_ENIRQ_VDDIO_BO,
1037         .bo_offset_mask         = POWER_VDDIOCTRL_BO_OFFSET_MASK,
1038         .bo_offset_offset       = POWER_VDDIOCTRL_BO_OFFSET_OFFSET,
1039 };
1040
1041 static const struct mxs_vddx_cfg mxs_vddd_cfg = {
1042         .reg                    = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
1043                                         hw_power_vdddctrl),
1044         .step_mV                = 25,
1045         .lowest_mV              = 800,
1046         .powered_by_linreg      = mxs_get_vddd_power_source_off,
1047         .trg_mask               = POWER_VDDDCTRL_TRG_MASK,
1048         .bo_irq                 = POWER_CTRL_VDDD_BO_IRQ,
1049         .bo_enirq               = POWER_CTRL_ENIRQ_VDDD_BO,
1050         .bo_offset_mask         = POWER_VDDDCTRL_BO_OFFSET_MASK,
1051         .bo_offset_offset       = POWER_VDDDCTRL_BO_OFFSET_OFFSET,
1052 };
1053
1054 #ifdef CONFIG_MX23
1055 static const struct mxs_vddx_cfg mxs_vddmem_cfg = {
1056         .reg                    = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
1057                                         hw_power_vddmemctrl),
1058         .step_mV                = 50,
1059         .lowest_mV              = 1700,
1060         .powered_by_linreg      = NULL,
1061         .trg_mask               = POWER_VDDMEMCTRL_TRG_MASK,
1062         .bo_irq                 = 0,
1063         .bo_enirq               = 0,
1064         .bo_offset_mask         = 0,
1065         .bo_offset_offset       = 0,
1066 };
1067 #endif
1068
1069 /**
1070  * mxs_power_set_vddx() - Configure voltage on DC-DC converter rail
1071  * @cfg:                Configuration data of the DC-DC converter rail
1072  * @new_target:         New target voltage of the DC-DC converter rail
1073  * @new_brownout:       New brownout trigger voltage
1074  *
1075  * This function configures the output voltage on the DC-DC converter rail.
1076  * The rail is selected by the @cfg argument. The new voltage target is
1077  * selected by the @new_target and the voltage is specified in mV. The
1078  * new brownout value is selected by the @new_brownout argument and the
1079  * value is also in mV.
1080  */
1081 static void mxs_power_set_vddx(const struct mxs_vddx_cfg *cfg,
1082                                 uint32_t new_target, uint32_t new_brownout)
1083 {
1084         struct mxs_power_regs *power_regs =
1085                 (struct mxs_power_regs *)MXS_POWER_BASE;
1086         uint32_t cur_target, diff, bo_int = 0;
1087         uint32_t powered_by_linreg = 0;
1088         int adjust_up, tmp;
1089
1090         new_brownout = DIV_ROUND_CLOSEST(new_target - new_brownout,
1091                                          cfg->step_mV);
1092
1093         cur_target = readl(cfg->reg);
1094         cur_target &= cfg->trg_mask;
1095         cur_target *= cfg->step_mV;
1096         cur_target += cfg->lowest_mV;
1097
1098         adjust_up = new_target > cur_target;
1099         if (cfg->powered_by_linreg)
1100                 powered_by_linreg = cfg->powered_by_linreg();
1101
1102         if (adjust_up && cfg->bo_irq) {
1103                 if (powered_by_linreg) {
1104                         bo_int = readl(cfg->reg);
1105                         clrbits_le32(cfg->reg, cfg->bo_enirq);
1106                 }
1107                 setbits_le32(cfg->reg, cfg->bo_offset_mask);
1108         }
1109
1110         do {
1111                 if (abs(new_target - cur_target) > 100) {
1112                         if (adjust_up)
1113                                 diff = cur_target + 100;
1114                         else
1115                                 diff = cur_target - 100;
1116                 } else {
1117                         diff = new_target;
1118                 }
1119
1120                 diff -= cfg->lowest_mV;
1121                 diff /= cfg->step_mV;
1122
1123                 clrsetbits_le32(cfg->reg, cfg->trg_mask, diff);
1124
1125                 if (powered_by_linreg ||
1126                         (readl(&power_regs->hw_power_sts) &
1127                                 POWER_STS_VDD5V_GT_VDDIO))
1128                         early_delay(500);
1129                 else {
1130                         for (;;) {
1131                                 tmp = readl(&power_regs->hw_power_sts);
1132                                 if (tmp & POWER_STS_DC_OK)
1133                                         break;
1134                         }
1135                 }
1136
1137                 cur_target = readl(cfg->reg);
1138                 cur_target &= cfg->trg_mask;
1139                 cur_target *= cfg->step_mV;
1140                 cur_target += cfg->lowest_mV;
1141         } while (new_target > cur_target);
1142
1143         if (cfg->bo_irq) {
1144                 if (adjust_up && powered_by_linreg) {
1145                         writel(cfg->bo_irq, &power_regs->hw_power_ctrl_clr);
1146                         if (bo_int & cfg->bo_enirq)
1147                                 setbits_le32(cfg->reg, cfg->bo_enirq);
1148                 }
1149
1150                 clrsetbits_le32(cfg->reg, cfg->bo_offset_mask,
1151                                 new_brownout << cfg->bo_offset_offset);
1152         }
1153 }
1154
1155 /**
1156  * mxs_setup_batt_detect() - Start the battery voltage measurement logic
1157  *
1158  * This function starts and configures the LRADC block. This allows the
1159  * power initialization code to measure battery voltage and based on this
1160  * knowledge, decide whether to boot at all, boot from battery or boot
1161  * from 5V input.
1162  */
1163 static void mxs_setup_batt_detect(void)
1164 {
1165         debug("SPL: Starting battery voltage measurement logic\n");
1166
1167         mxs_lradc_init();
1168         mxs_lradc_enable_batt_measurement();
1169         early_delay(10);
1170 }
1171
1172 /**
1173  * mxs_ungate_power() - Ungate the POWER block
1174  *
1175  * This function ungates clock to the power block. In case the power block
1176  * was still gated at this point, it will not be possible to configure the
1177  * block and therefore the power initialization would fail. This function
1178  * is only needed on i.MX233, on i.MX28 the power block is always ungated.
1179  */
1180 static void mxs_ungate_power(void)
1181 {
1182 #ifdef CONFIG_MX23
1183         struct mxs_power_regs *power_regs =
1184                 (struct mxs_power_regs *)MXS_POWER_BASE;
1185
1186         writel(POWER_CTRL_CLKGATE, &power_regs->hw_power_ctrl_clr);
1187 #endif
1188 }
1189
1190 /**
1191  * mxs_power_init() - The power block init main function
1192  *
1193  * This function calls all the power block initialization functions in
1194  * proper sequence to start the power block.
1195  */
1196 void mxs_power_init(void)
1197 {
1198         struct mxs_power_regs *power_regs =
1199                 (struct mxs_power_regs *)MXS_POWER_BASE;
1200
1201         debug("SPL: Initialising Power Block\n");
1202
1203         mxs_ungate_power();
1204
1205         mxs_power_clock2xtal();
1206         mxs_power_set_auto_restart();
1207         mxs_power_set_linreg();
1208         mxs_power_setup_5v_detect();
1209
1210         mxs_setup_batt_detect();
1211
1212         mxs_power_configure_power_source();
1213         mxs_enable_output_rail_protection();
1214
1215         debug("SPL: Setting VDDIO to 3V3 (brownout @ 3v15)\n");
1216         mxs_power_set_vddx(&mxs_vddio_cfg, 3300, 3150);
1217
1218         debug("SPL: Setting VDDD to 1V5 (brownout @ 1v0)\n");
1219         mxs_power_set_vddx(&mxs_vddd_cfg, 1500, 1000);
1220 #ifdef CONFIG_MX23
1221         debug("SPL: Setting mx23 VDDMEM to 2V5 (brownout @ 1v7)\n");
1222         mxs_power_set_vddx(&mxs_vddmem_cfg, 2500, 1700);
1223 #endif
1224         writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
1225                 POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
1226                 POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ |
1227                 POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
1228
1229         writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set);
1230
1231         early_delay(1000);
1232 }
1233
1234 #ifdef  CONFIG_SPL_MXS_PSWITCH_WAIT
1235 /**
1236  * mxs_power_wait_pswitch() - Wait for power switch to be pressed
1237  *
1238  * This function waits until the power-switch was pressed to start booting
1239  * the board.
1240  */
1241 void mxs_power_wait_pswitch(void)
1242 {
1243         struct mxs_power_regs *power_regs =
1244                 (struct mxs_power_regs *)MXS_POWER_BASE;
1245
1246         debug("SPL: Waiting for power switch input\n");
1247         while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK))
1248                 ;
1249 }
1250 #endif