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