]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/denx/m28evk/power_init.c
Merge branch 'sr@denx.de' of git://git.denx.de/u-boot-staging
[karo-tx-uboot.git] / board / denx / m28evk / 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  * See file CREDITS for list of people who contributed to this
8  * project.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of
13  * the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23  * MA 02111-1307 USA
24  */
25
26 #include <common.h>
27 #include <config.h>
28 #include <asm/io.h>
29 #include <asm/arch/imx-regs.h>
30
31 #include "m28_init.h"
32
33 void mx28_power_clock2xtal(void)
34 {
35         struct mx28_clkctrl_regs *clkctrl_regs =
36                 (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
37
38         /* Set XTAL as CPU reference clock */
39         writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
40                 &clkctrl_regs->hw_clkctrl_clkseq_set);
41 }
42
43 void mx28_power_clock2pll(void)
44 {
45         struct mx28_clkctrl_regs *clkctrl_regs =
46                 (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
47
48         writel(CLKCTRL_PLL0CTRL0_POWER,
49                 &clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
50         early_delay(100);
51         writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
52                 &clkctrl_regs->hw_clkctrl_clkseq_clr);
53 }
54
55 void mx28_power_clear_auto_restart(void)
56 {
57         struct mx28_rtc_regs *rtc_regs =
58                 (struct mx28_rtc_regs *)MXS_RTC_BASE;
59
60         writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr);
61         while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST)
62                 ;
63
64         writel(RTC_CTRL_CLKGATE, &rtc_regs->hw_rtc_ctrl_clr);
65         while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE)
66                 ;
67
68         /*
69          * Due to the hardware design bug of mx28 EVK-A
70          * we need to set the AUTO_RESTART bit.
71          */
72         if (readl(&rtc_regs->hw_rtc_persistent0) & RTC_PERSISTENT0_AUTO_RESTART)
73                 return;
74
75         while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
76                 ;
77
78         setbits_le32(&rtc_regs->hw_rtc_persistent0,
79                         RTC_PERSISTENT0_AUTO_RESTART);
80         writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_set);
81         writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_clr);
82         while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
83                 ;
84         while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_STALE_REGS_MASK)
85                 ;
86 }
87
88 void mx28_power_set_linreg(void)
89 {
90         struct mx28_power_regs *power_regs =
91                 (struct mx28_power_regs *)MXS_POWER_BASE;
92
93         /* Set linear regulator 25mV below switching converter */
94         clrsetbits_le32(&power_regs->hw_power_vdddctrl,
95                         POWER_VDDDCTRL_LINREG_OFFSET_MASK,
96                         POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
97
98         clrsetbits_le32(&power_regs->hw_power_vddactrl,
99                         POWER_VDDACTRL_LINREG_OFFSET_MASK,
100                         POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW);
101
102         clrsetbits_le32(&power_regs->hw_power_vddioctrl,
103                         POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
104                         POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
105 }
106
107 void mx28_power_setup_5v_detect(void)
108 {
109         struct mx28_power_regs *power_regs =
110                 (struct mx28_power_regs *)MXS_POWER_BASE;
111
112         /* Start 5V detection */
113         clrsetbits_le32(&power_regs->hw_power_5vctrl,
114                         POWER_5VCTRL_VBUSVALID_TRSH_MASK,
115                         POWER_5VCTRL_VBUSVALID_TRSH_4V4 |
116                         POWER_5VCTRL_PWRUP_VBUS_CMPS);
117 }
118
119 void mx28_src_power_init(void)
120 {
121         struct mx28_power_regs *power_regs =
122                 (struct mx28_power_regs *)MXS_POWER_BASE;
123
124         /* Improve efficieny and reduce transient ripple */
125         writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST |
126                 POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set);
127
128         clrsetbits_le32(&power_regs->hw_power_dclimits,
129                         POWER_DCLIMITS_POSLIMIT_BUCK_MASK,
130                         0x30 << POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET);
131
132         setbits_le32(&power_regs->hw_power_battmonitor,
133                         POWER_BATTMONITOR_EN_BATADJ);
134
135         /* Increase the RCSCALE level for quick DCDC response to dynamic load */
136         clrsetbits_le32(&power_regs->hw_power_loopctrl,
137                         POWER_LOOPCTRL_EN_RCSCALE_MASK,
138                         POWER_LOOPCTRL_RCSCALE_THRESH |
139                         POWER_LOOPCTRL_EN_RCSCALE_8X);
140
141         clrsetbits_le32(&power_regs->hw_power_minpwr,
142                         POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
143
144         /* 5V to battery handoff ... FIXME */
145         setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
146         early_delay(30);
147         clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
148 }
149
150 void mx28_power_init_4p2_params(void)
151 {
152         struct mx28_power_regs *power_regs =
153                 (struct mx28_power_regs *)MXS_POWER_BASE;
154
155         /* Setup 4P2 parameters */
156         clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
157                 POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK,
158                 POWER_DCDC4P2_TRG_4V2 | (31 << POWER_DCDC4P2_CMPTRIP_OFFSET));
159
160         clrsetbits_le32(&power_regs->hw_power_5vctrl,
161                 POWER_5VCTRL_HEADROOM_ADJ_MASK,
162                 0x4 << POWER_5VCTRL_HEADROOM_ADJ_OFFSET);
163
164         clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
165                 POWER_DCDC4P2_DROPOUT_CTRL_MASK,
166                 POWER_DCDC4P2_DROPOUT_CTRL_100MV |
167                 POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL);
168
169         clrsetbits_le32(&power_regs->hw_power_5vctrl,
170                 POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
171                 0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
172 }
173
174 void mx28_enable_4p2_dcdc_input(int xfer)
175 {
176         struct mx28_power_regs *power_regs =
177                 (struct mx28_power_regs *)MXS_POWER_BASE;
178         uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo;
179         uint32_t prev_5v_brnout, prev_5v_droop;
180
181         prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) &
182                                 POWER_5VCTRL_PWDN_5VBRNOUT;
183         prev_5v_droop = readl(&power_regs->hw_power_ctrl) &
184                                 POWER_CTRL_ENIRQ_VDD5V_DROOP;
185
186         clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
187         writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
188                 &power_regs->hw_power_reset);
189
190         clrbits_le32(&power_regs->hw_power_ctrl, POWER_CTRL_ENIRQ_VDD5V_DROOP);
191
192         if (xfer && (readl(&power_regs->hw_power_5vctrl) &
193                         POWER_5VCTRL_ENABLE_DCDC)) {
194                 return;
195         }
196
197         /*
198          * Recording orignal values that will be modified temporarlily
199          * to handle a chip bug. See chip errata for CQ ENGR00115837
200          */
201         tmp = readl(&power_regs->hw_power_5vctrl);
202         vbus_thresh = tmp & POWER_5VCTRL_VBUSVALID_TRSH_MASK;
203         vbus_5vdetect = tmp & POWER_5VCTRL_VBUSVALID_5VDETECT;
204
205         pwd_bo = readl(&power_regs->hw_power_minpwr) & POWER_MINPWR_PWD_BO;
206
207         /*
208          * Disable mechanisms that get erroneously tripped by when setting
209          * the DCDC4P2 EN_DCDC
210          */
211         clrbits_le32(&power_regs->hw_power_5vctrl,
212                 POWER_5VCTRL_VBUSVALID_5VDETECT |
213                 POWER_5VCTRL_VBUSVALID_TRSH_MASK);
214
215         writel(POWER_MINPWR_PWD_BO, &power_regs->hw_power_minpwr_set);
216
217         if (xfer) {
218                 setbits_le32(&power_regs->hw_power_5vctrl,
219                                 POWER_5VCTRL_DCDC_XFER);
220                 early_delay(20);
221                 clrbits_le32(&power_regs->hw_power_5vctrl,
222                                 POWER_5VCTRL_DCDC_XFER);
223
224                 setbits_le32(&power_regs->hw_power_5vctrl,
225                                 POWER_5VCTRL_ENABLE_DCDC);
226         } else {
227                 setbits_le32(&power_regs->hw_power_dcdc4p2,
228                                 POWER_DCDC4P2_ENABLE_DCDC);
229         }
230
231         early_delay(25);
232
233         clrsetbits_le32(&power_regs->hw_power_5vctrl,
234                         POWER_5VCTRL_VBUSVALID_TRSH_MASK, vbus_thresh);
235
236         if (vbus_5vdetect)
237                 writel(vbus_5vdetect, &power_regs->hw_power_5vctrl_set);
238
239         if (!pwd_bo)
240                 clrbits_le32(&power_regs->hw_power_minpwr, POWER_MINPWR_PWD_BO);
241
242         while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ)
243                 clrbits_le32(&power_regs->hw_power_ctrl,
244                                 POWER_CTRL_VBUS_VALID_IRQ);
245
246         if (prev_5v_brnout) {
247                 writel(POWER_5VCTRL_PWDN_5VBRNOUT,
248                         &power_regs->hw_power_5vctrl_set);
249                 writel(POWER_RESET_UNLOCK_KEY,
250                         &power_regs->hw_power_reset);
251         } else {
252                 writel(POWER_5VCTRL_PWDN_5VBRNOUT,
253                         &power_regs->hw_power_5vctrl_clr);
254                 writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
255                         &power_regs->hw_power_reset);
256         }
257
258         while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VDD5V_DROOP_IRQ)
259                 clrbits_le32(&power_regs->hw_power_ctrl,
260                                 POWER_CTRL_VDD5V_DROOP_IRQ);
261
262         if (prev_5v_droop)
263                 clrbits_le32(&power_regs->hw_power_ctrl,
264                                 POWER_CTRL_ENIRQ_VDD5V_DROOP);
265         else
266                 setbits_le32(&power_regs->hw_power_ctrl,
267                                 POWER_CTRL_ENIRQ_VDD5V_DROOP);
268 }
269
270 void mx28_power_init_4p2_regulator(void)
271 {
272         struct mx28_power_regs *power_regs =
273                 (struct mx28_power_regs *)MXS_POWER_BASE;
274         uint32_t tmp, tmp2;
275
276         setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2);
277
278         writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set);
279
280         writel(POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
281                 &power_regs->hw_power_5vctrl_clr);
282         clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_TRG_MASK);
283
284         /* Power up the 4p2 rail and logic/control */
285         writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
286                 &power_regs->hw_power_5vctrl_clr);
287
288         /*
289          * Start charging up the 4p2 capacitor. We ramp of this charge
290          * gradually to avoid large inrush current from the 5V cable which can
291          * cause transients/problems
292          */
293         mx28_enable_4p2_dcdc_input(0);
294
295         if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
296                 /*
297                  * If we arrived here, we were unable to recover from mx23 chip
298                  * errata 5837. 4P2 is disabled and sufficient battery power is
299                  * not present. Exiting to not enable DCDC power during 5V
300                  * connected state.
301                  */
302                 clrbits_le32(&power_regs->hw_power_dcdc4p2,
303                         POWER_DCDC4P2_ENABLE_DCDC);
304                 writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
305                         &power_regs->hw_power_5vctrl_set);
306                 hang();
307         }
308
309         /*
310          * Here we set the 4p2 brownout level to something very close to 4.2V.
311          * We then check the brownout status. If the brownout status is false,
312          * the voltage is already close to the target voltage of 4.2V so we
313          * can go ahead and set the 4P2 current limit to our max target limit.
314          * If the brownout status is true, we need to ramp us the current limit
315          * so that we don't cause large inrush current issues. We step up the
316          * current limit until the brownout status is false or until we've
317          * reached our maximum defined 4p2 current limit.
318          */
319         clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
320                         POWER_DCDC4P2_BO_MASK,
321                         22 << POWER_DCDC4P2_BO_OFFSET); /* 4.15V */
322
323         if (!(readl(&power_regs->hw_power_sts) & POWER_STS_DCDC_4P2_BO)) {
324                 setbits_le32(&power_regs->hw_power_5vctrl,
325                         0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
326         } else {
327                 tmp = (readl(&power_regs->hw_power_5vctrl) &
328                         POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK) >>
329                         POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
330                 while (tmp < 0x3f) {
331                         if (!(readl(&power_regs->hw_power_sts) &
332                                         POWER_STS_DCDC_4P2_BO)) {
333                                 tmp = readl(&power_regs->hw_power_5vctrl);
334                                 tmp |= POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
335                                 early_delay(100);
336                                 writel(tmp, &power_regs->hw_power_5vctrl);
337                                 break;
338                         } else {
339                                 tmp++;
340                                 tmp2 = readl(&power_regs->hw_power_5vctrl);
341                                 tmp2 &= ~POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
342                                 tmp2 |= tmp <<
343                                         POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
344                                 writel(tmp2, &power_regs->hw_power_5vctrl);
345                                 early_delay(100);
346                         }
347                 }
348         }
349
350         clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
351         writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
352 }
353
354 void mx28_power_init_dcdc_4p2_source(void)
355 {
356         struct mx28_power_regs *power_regs =
357                 (struct mx28_power_regs *)MXS_POWER_BASE;
358
359         if (!(readl(&power_regs->hw_power_dcdc4p2) &
360                 POWER_DCDC4P2_ENABLE_DCDC)) {
361                 hang();
362         }
363
364         mx28_enable_4p2_dcdc_input(1);
365
366         if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
367                 clrbits_le32(&power_regs->hw_power_dcdc4p2,
368                         POWER_DCDC4P2_ENABLE_DCDC);
369                 writel(POWER_5VCTRL_ENABLE_DCDC,
370                         &power_regs->hw_power_5vctrl_clr);
371                 writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
372                         &power_regs->hw_power_5vctrl_set);
373         }
374 }
375
376 void mx28_power_enable_4p2(void)
377 {
378         struct mx28_power_regs *power_regs =
379                 (struct mx28_power_regs *)MXS_POWER_BASE;
380         uint32_t vdddctrl, vddactrl, vddioctrl;
381         uint32_t tmp;
382
383         vdddctrl = readl(&power_regs->hw_power_vdddctrl);
384         vddactrl = readl(&power_regs->hw_power_vddactrl);
385         vddioctrl = readl(&power_regs->hw_power_vddioctrl);
386
387         setbits_le32(&power_regs->hw_power_vdddctrl,
388                 POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
389                 POWER_VDDDCTRL_PWDN_BRNOUT);
390
391         setbits_le32(&power_regs->hw_power_vddactrl,
392                 POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG |
393                 POWER_VDDACTRL_PWDN_BRNOUT);
394
395         setbits_le32(&power_regs->hw_power_vddioctrl,
396                 POWER_VDDIOCTRL_DISABLE_FET | POWER_VDDIOCTRL_PWDN_BRNOUT);
397
398         mx28_power_init_4p2_params();
399         mx28_power_init_4p2_regulator();
400
401         /* Shutdown battery (none present) */
402         clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
403         writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
404         writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, &power_regs->hw_power_ctrl_clr);
405
406         mx28_power_init_dcdc_4p2_source();
407
408         writel(vdddctrl, &power_regs->hw_power_vdddctrl);
409         early_delay(20);
410         writel(vddactrl, &power_regs->hw_power_vddactrl);
411         early_delay(20);
412         writel(vddioctrl, &power_regs->hw_power_vddioctrl);
413
414         /*
415          * Check if FET is enabled on either powerout and if so,
416          * disable load.
417          */
418         tmp = 0;
419         tmp |= !(readl(&power_regs->hw_power_vdddctrl) &
420                         POWER_VDDDCTRL_DISABLE_FET);
421         tmp |= !(readl(&power_regs->hw_power_vddactrl) &
422                         POWER_VDDACTRL_DISABLE_FET);
423         tmp |= !(readl(&power_regs->hw_power_vddioctrl) &
424                         POWER_VDDIOCTRL_DISABLE_FET);
425         if (tmp)
426                 writel(POWER_CHARGE_ENABLE_LOAD,
427                         &power_regs->hw_power_charge_clr);
428 }
429
430 void mx28_boot_valid_5v(void)
431 {
432         struct mx28_power_regs *power_regs =
433                 (struct mx28_power_regs *)MXS_POWER_BASE;
434
435         /*
436          * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V
437          * disconnect event. FIXME
438          */
439         writel(POWER_5VCTRL_VBUSVALID_5VDETECT,
440                 &power_regs->hw_power_5vctrl_set);
441
442         /* Configure polarity to check for 5V disconnection. */
443         writel(POWER_CTRL_POLARITY_VBUSVALID |
444                 POWER_CTRL_POLARITY_VDD5V_GT_VDDIO,
445                 &power_regs->hw_power_ctrl_clr);
446
447         writel(POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_VDD5V_GT_VDDIO_IRQ,
448                 &power_regs->hw_power_ctrl_clr);
449
450         mx28_power_enable_4p2();
451 }
452
453 void mx28_powerdown(void)
454 {
455         struct mx28_power_regs *power_regs =
456                 (struct mx28_power_regs *)MXS_POWER_BASE;
457         writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset);
458         writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
459                 &power_regs->hw_power_reset);
460 }
461
462 void mx28_handle_5v_conflict(void)
463 {
464         struct mx28_power_regs *power_regs =
465                 (struct mx28_power_regs *)MXS_POWER_BASE;
466         uint32_t tmp;
467
468         setbits_le32(&power_regs->hw_power_vddioctrl,
469                         POWER_VDDIOCTRL_BO_OFFSET_MASK);
470
471         for (;;) {
472                 tmp = readl(&power_regs->hw_power_sts);
473
474                 if (tmp & POWER_STS_VDDIO_BO) {
475                         mx28_powerdown();
476                         break;
477                 }
478
479                 if (tmp & POWER_STS_VDD5V_GT_VDDIO) {
480                         mx28_boot_valid_5v();
481                         break;
482                 } else {
483                         mx28_powerdown();
484                         break;
485                 }
486         }
487 }
488
489 int mx28_get_batt_volt(void)
490 {
491         struct mx28_power_regs *power_regs =
492                 (struct mx28_power_regs *)MXS_POWER_BASE;
493         uint32_t volt = readl(&power_regs->hw_power_battmonitor);
494         volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
495         volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
496         volt *= 8;
497         return volt;
498 }
499
500 int mx28_is_batt_ready(void)
501 {
502         return (mx28_get_batt_volt() >= 3600);
503 }
504
505 void mx28_5v_boot(void)
506 {
507         struct mx28_power_regs *power_regs =
508                 (struct mx28_power_regs *)MXS_POWER_BASE;
509
510         /*
511          * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID,
512          * but their implementation always returns 1 so we omit it here.
513          */
514         if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
515                 mx28_boot_valid_5v();
516                 return;
517         }
518
519         early_delay(1000);
520         if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
521                 mx28_boot_valid_5v();
522                 return;
523         }
524
525         mx28_handle_5v_conflict();
526 }
527
528 void mx28_init_batt_bo(void)
529 {
530         struct mx28_power_regs *power_regs =
531                 (struct mx28_power_regs *)MXS_POWER_BASE;
532
533         /* Brownout at 3V */
534         clrsetbits_le32(&power_regs->hw_power_battmonitor,
535                 POWER_BATTMONITOR_BRWNOUT_LVL_MASK,
536                 15 << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
537
538         writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr);
539         writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
540 }
541
542 void mx28_switch_vddd_to_dcdc_source(void)
543 {
544         struct mx28_power_regs *power_regs =
545                 (struct mx28_power_regs *)MXS_POWER_BASE;
546
547         clrsetbits_le32(&power_regs->hw_power_vdddctrl,
548                 POWER_VDDDCTRL_LINREG_OFFSET_MASK,
549                 POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
550
551         clrbits_le32(&power_regs->hw_power_vdddctrl,
552                 POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
553                 POWER_VDDDCTRL_DISABLE_STEPPING);
554 }
555
556 int mx28_is_batt_good(void)
557 {
558         struct mx28_power_regs *power_regs =
559                 (struct mx28_power_regs *)MXS_POWER_BASE;
560         uint32_t volt;
561
562         volt = readl(&power_regs->hw_power_battmonitor);
563         volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
564         volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
565         volt *= 8;
566
567         if ((volt >= 2400) && (volt <= 4300))
568                 return 1;
569
570         clrsetbits_le32(&power_regs->hw_power_5vctrl,
571                 POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
572                 0x3 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
573         writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
574                 &power_regs->hw_power_5vctrl_clr);
575
576         clrsetbits_le32(&power_regs->hw_power_charge,
577                 POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
578                 POWER_CHARGE_STOP_ILIMIT_10MA | 0x3);
579
580         writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_clr);
581         writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
582                 &power_regs->hw_power_5vctrl_clr);
583
584         early_delay(500000);
585
586         volt = readl(&power_regs->hw_power_battmonitor);
587         volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
588         volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
589         volt *= 8;
590
591         if (volt >= 3500)
592                 return 0;
593
594         if (volt >= 2400)
595                 return 1;
596
597         writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
598                 &power_regs->hw_power_charge_clr);
599         writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
600
601         return 0;
602 }
603
604 void mx28_power_configure_power_source(void)
605 {
606         mx28_src_power_init();
607
608         mx28_5v_boot();
609         mx28_power_clock2pll();
610
611         mx28_init_batt_bo();
612         mx28_switch_vddd_to_dcdc_source();
613 }
614
615 void mx28_enable_output_rail_protection(void)
616 {
617         struct mx28_power_regs *power_regs =
618                 (struct mx28_power_regs *)MXS_POWER_BASE;
619
620         writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
621                 POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr);
622
623         setbits_le32(&power_regs->hw_power_vdddctrl,
624                         POWER_VDDDCTRL_PWDN_BRNOUT);
625
626         setbits_le32(&power_regs->hw_power_vddactrl,
627                         POWER_VDDACTRL_PWDN_BRNOUT);
628
629         setbits_le32(&power_regs->hw_power_vddioctrl,
630                         POWER_VDDIOCTRL_PWDN_BRNOUT);
631 }
632
633 int mx28_get_vddio_power_source_off(void)
634 {
635         struct mx28_power_regs *power_regs =
636                 (struct mx28_power_regs *)MXS_POWER_BASE;
637         uint32_t tmp;
638
639         if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
640                 tmp = readl(&power_regs->hw_power_vddioctrl);
641                 if (tmp & POWER_VDDIOCTRL_DISABLE_FET) {
642                         if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
643                                 POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
644                                 return 1;
645                         }
646                 }
647
648                 if (!(readl(&power_regs->hw_power_5vctrl) &
649                         POWER_5VCTRL_ENABLE_DCDC)) {
650                         if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
651                                 POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
652                                 return 1;
653                         }
654                 }
655         }
656
657         return 0;
658
659 }
660
661 int mx28_get_vddd_power_source_off(void)
662 {
663         struct mx28_power_regs *power_regs =
664                 (struct mx28_power_regs *)MXS_POWER_BASE;
665         uint32_t tmp;
666
667         tmp = readl(&power_regs->hw_power_vdddctrl);
668         if (tmp & POWER_VDDDCTRL_DISABLE_FET) {
669                 if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
670                         POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
671                         return 1;
672                 }
673         }
674
675         if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
676                 if (!(readl(&power_regs->hw_power_5vctrl) &
677                         POWER_5VCTRL_ENABLE_DCDC)) {
678                         return 1;
679                 }
680         }
681
682         if (!(tmp & POWER_VDDDCTRL_ENABLE_LINREG)) {
683                 if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
684                         POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW) {
685                         return 1;
686                 }
687         }
688
689         return 0;
690 }
691
692 void mx28_power_set_vddio(uint32_t new_target, uint32_t new_brownout)
693 {
694         struct mx28_power_regs *power_regs =
695                 (struct mx28_power_regs *)MXS_POWER_BASE;
696         uint32_t cur_target, diff, bo_int = 0;
697         uint32_t powered_by_linreg = 0;
698
699         new_brownout = new_target - new_brownout;
700
701         cur_target = readl(&power_regs->hw_power_vddioctrl);
702         cur_target &= POWER_VDDIOCTRL_TRG_MASK;
703         cur_target *= 50;       /* 50 mV step*/
704         cur_target += 2800;     /* 2800 mV lowest */
705
706         powered_by_linreg = mx28_get_vddio_power_source_off();
707         if (new_target > cur_target) {
708
709                 if (powered_by_linreg) {
710                         bo_int = readl(&power_regs->hw_power_vddioctrl);
711                         clrbits_le32(&power_regs->hw_power_vddioctrl,
712                                         POWER_CTRL_ENIRQ_VDDIO_BO);
713                 }
714
715                 setbits_le32(&power_regs->hw_power_vddioctrl,
716                                 POWER_VDDIOCTRL_BO_OFFSET_MASK);
717                 do {
718                         if (new_target - cur_target > 100)
719                                 diff = cur_target + 100;
720                         else
721                                 diff = new_target;
722
723                         diff -= 2800;
724                         diff /= 50;
725
726                         clrsetbits_le32(&power_regs->hw_power_vddioctrl,
727                                 POWER_VDDIOCTRL_TRG_MASK, diff);
728
729                         if (powered_by_linreg)
730                                 early_delay(1500);
731                         else {
732                                 while (!(readl(&power_regs->hw_power_sts) &
733                                         POWER_STS_DC_OK))
734                                         ;
735
736                         }
737
738                         cur_target = readl(&power_regs->hw_power_vddioctrl);
739                         cur_target &= POWER_VDDIOCTRL_TRG_MASK;
740                         cur_target *= 50;       /* 50 mV step*/
741                         cur_target += 2800;     /* 2800 mV lowest */
742                 } while (new_target > cur_target);
743
744                 if (powered_by_linreg) {
745                         writel(POWER_CTRL_VDDIO_BO_IRQ,
746                                 &power_regs->hw_power_ctrl_clr);
747                         if (bo_int & POWER_CTRL_ENIRQ_VDDIO_BO)
748                                 setbits_le32(&power_regs->hw_power_vddioctrl,
749                                                 POWER_CTRL_ENIRQ_VDDIO_BO);
750                 }
751         } else {
752                 do {
753                         if (cur_target - new_target > 100)
754                                 diff = cur_target - 100;
755                         else
756                                 diff = new_target;
757
758                         diff -= 2800;
759                         diff /= 50;
760
761                         clrsetbits_le32(&power_regs->hw_power_vddioctrl,
762                                 POWER_VDDIOCTRL_TRG_MASK, diff);
763
764                         if (powered_by_linreg)
765                                 early_delay(1500);
766                         else {
767                                 while (!(readl(&power_regs->hw_power_sts) &
768                                         POWER_STS_DC_OK))
769                                         ;
770
771                         }
772
773                         cur_target = readl(&power_regs->hw_power_vddioctrl);
774                         cur_target &= POWER_VDDIOCTRL_TRG_MASK;
775                         cur_target *= 50;       /* 50 mV step*/
776                         cur_target += 2800;     /* 2800 mV lowest */
777                 } while (new_target < cur_target);
778         }
779
780         clrsetbits_le32(&power_regs->hw_power_vddioctrl,
781                         POWER_VDDDCTRL_BO_OFFSET_MASK,
782                         new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
783 }
784
785 void mx28_power_set_vddd(uint32_t new_target, uint32_t new_brownout)
786 {
787         struct mx28_power_regs *power_regs =
788                 (struct mx28_power_regs *)MXS_POWER_BASE;
789         uint32_t cur_target, diff, bo_int = 0;
790         uint32_t powered_by_linreg = 0;
791
792         new_brownout = new_target - new_brownout;
793
794         cur_target = readl(&power_regs->hw_power_vdddctrl);
795         cur_target &= POWER_VDDDCTRL_TRG_MASK;
796         cur_target *= 25;       /* 25 mV step*/
797         cur_target += 800;      /* 800 mV lowest */
798
799         powered_by_linreg = mx28_get_vddd_power_source_off();
800         if (new_target > cur_target) {
801                 if (powered_by_linreg) {
802                         bo_int = readl(&power_regs->hw_power_vdddctrl);
803                         clrbits_le32(&power_regs->hw_power_vdddctrl,
804                                         POWER_CTRL_ENIRQ_VDDD_BO);
805                 }
806
807                 setbits_le32(&power_regs->hw_power_vdddctrl,
808                                 POWER_VDDDCTRL_BO_OFFSET_MASK);
809
810                 do {
811                         if (new_target - cur_target > 100)
812                                 diff = cur_target + 100;
813                         else
814                                 diff = new_target;
815
816                         diff -= 800;
817                         diff /= 25;
818
819                         clrsetbits_le32(&power_regs->hw_power_vdddctrl,
820                                 POWER_VDDDCTRL_TRG_MASK, diff);
821
822                         if (powered_by_linreg)
823                                 early_delay(1500);
824                         else {
825                                 while (!(readl(&power_regs->hw_power_sts) &
826                                         POWER_STS_DC_OK))
827                                         ;
828
829                         }
830
831                         cur_target = readl(&power_regs->hw_power_vdddctrl);
832                         cur_target &= POWER_VDDDCTRL_TRG_MASK;
833                         cur_target *= 25;       /* 25 mV step*/
834                         cur_target += 800;      /* 800 mV lowest */
835                 } while (new_target > cur_target);
836
837                 if (powered_by_linreg) {
838                         writel(POWER_CTRL_VDDD_BO_IRQ,
839                                 &power_regs->hw_power_ctrl_clr);
840                         if (bo_int & POWER_CTRL_ENIRQ_VDDD_BO)
841                                 setbits_le32(&power_regs->hw_power_vdddctrl,
842                                                 POWER_CTRL_ENIRQ_VDDD_BO);
843                 }
844         } else {
845                 do {
846                         if (cur_target - new_target > 100)
847                                 diff = cur_target - 100;
848                         else
849                                 diff = new_target;
850
851                         diff -= 800;
852                         diff /= 25;
853
854                         clrsetbits_le32(&power_regs->hw_power_vdddctrl,
855                                         POWER_VDDDCTRL_TRG_MASK, diff);
856
857                         if (powered_by_linreg)
858                                 early_delay(1500);
859                         else {
860                                 while (!(readl(&power_regs->hw_power_sts) &
861                                         POWER_STS_DC_OK))
862                                         ;
863
864                         }
865
866                         cur_target = readl(&power_regs->hw_power_vdddctrl);
867                         cur_target &= POWER_VDDDCTRL_TRG_MASK;
868                         cur_target *= 25;       /* 25 mV step*/
869                         cur_target += 800;      /* 800 mV lowest */
870                 } while (new_target < cur_target);
871         }
872
873         clrsetbits_le32(&power_regs->hw_power_vdddctrl,
874                         POWER_VDDDCTRL_BO_OFFSET_MASK,
875                         new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
876 }
877
878 void mx28_power_init(void)
879 {
880         struct mx28_power_regs *power_regs =
881                 (struct mx28_power_regs *)MXS_POWER_BASE;
882
883         mx28_power_clock2xtal();
884         mx28_power_clear_auto_restart();
885         mx28_power_set_linreg();
886         mx28_power_setup_5v_detect();
887         mx28_power_configure_power_source();
888         mx28_enable_output_rail_protection();
889
890         mx28_power_set_vddio(3300, 3150);
891
892         mx28_power_set_vddd(1350, 1200);
893
894         writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
895                 POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
896                 POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ |
897                 POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
898
899         writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set);
900
901         early_delay(1000);
902 }
903
904 #ifdef  CONFIG_SPL_MX28_PSWITCH_WAIT
905 void mx28_power_wait_pswitch(void)
906 {
907         struct mx28_power_regs *power_regs =
908                 (struct mx28_power_regs *)MXS_POWER_BASE;
909
910         while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK))
911                 ;
912 }
913 #endif