]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/arm926ejs/mx28/spl_power_init.c
Added dbg() macro and converted dprintf()
[karo-tx-uboot.git] / arch / arm / cpu / arm926ejs / mx28 / 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  * 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 "mx28_init.h"
32
33 static struct mx28_power_regs *power_regs = (void *)MXS_POWER_BASE;
34
35 #define DEBUG
36 #define __static
37
38 #include "debug.h"
39
40 #undef __arch_getl
41 #undef __arch_putl
42
43 #define __arch_getl(a)  arch_getl(a, __func__, __LINE__)
44 static inline unsigned int arch_getl(volatile void *addr,
45                         const char *fn, unsigned int ln)
46 {
47         volatile unsigned int *a = addr;
48         unsigned int val = *a;
49         dbg(0, "%s@%d: Read %x from %p\n", fn, ln, val, addr);
50         return val;
51 }
52
53 #define __arch_putl(v, a)       arch_putl(v, a, __func__, __LINE__)
54 static inline void arch_putl(unsigned int val, volatile void *addr,
55                         const char *fn, unsigned int ln)
56 {
57         volatile unsigned int *a = addr;
58
59         dbg(0, "%s@%d: Writing %x to %p\n", fn, ln, val, addr);
60         *a = val;
61 }
62
63 __static int mx28_power_vdd5v_gt_vddio(void)
64 {
65         int power_sts = readl(&power_regs->hw_power_sts);
66 return 0;
67         dbg(3, "%s@%d: %d\n", __func__, __LINE__,
68                 !!(power_sts & POWER_STS_VDD5V_GT_VDDIO));
69         return power_sts & POWER_STS_VDD5V_GT_VDDIO;
70 }
71
72 static void memdump(unsigned long addr, unsigned long len)
73 {
74 #ifdef DEBUG
75         int i;
76         uint32_t *ptr = (void *)addr;
77
78         for (i = 0; i < len; i++) {
79                 if (i % 4 == 0)
80                         dbg(3, "\n%x:", &ptr[i]);
81                 dbg(3, " %x", ptr[i]);
82         }
83         dbg(3, "\n");
84 #endif
85 }
86
87 __static void mx28_power_clock2xtal(void)
88 {
89         struct mx28_clkctrl_regs *clkctrl_regs =
90                 (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
91
92         dbg(3, "%s@%d: \n", __func__, __LINE__);
93         /* Set XTAL as CPU reference clock */
94         writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
95                 &clkctrl_regs->hw_clkctrl_clkseq_set);
96 }
97
98 __static void mx28_power_clock2pll(void)
99 {
100         struct mx28_clkctrl_regs *clkctrl_regs =
101                 (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
102
103         dbg(3, "%s@%d: \n", __func__, __LINE__);
104         writel(CLKCTRL_PLL0CTRL0_POWER,
105                 &clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
106         early_delay(100);
107         writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
108                 &clkctrl_regs->hw_clkctrl_clkseq_clr);
109 }
110
111 __static void mx28_power_clear_auto_restart(void)
112 {
113         struct mx28_rtc_regs *rtc_regs =
114                 (struct mx28_rtc_regs *)MXS_RTC_BASE;
115
116         dbg(3, "%s@%d: \n", __func__, __LINE__);
117         writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr);
118         while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST)
119                 ;
120
121         writel(RTC_CTRL_CLKGATE, &rtc_regs->hw_rtc_ctrl_clr);
122         while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE)
123                 ;
124 #ifdef CONFIG_MACH_MX28EVK
125         /*
126          * Due to the hardware design bug of mx28 EVK-A
127          * we need to set the AUTO_RESTART bit.
128          */
129         if (readl(&rtc_regs->hw_rtc_persistent0) & RTC_PERSISTENT0_AUTO_RESTART)
130                 return;
131
132         while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
133                 ;
134
135         setbits_le32(&rtc_regs->hw_rtc_persistent0,
136                         RTC_PERSISTENT0_AUTO_RESTART);
137         writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_set);
138         writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_clr);
139         while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
140                 ;
141         while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_STALE_REGS_MASK)
142                 ;
143 #endif
144 }
145
146 __static void mx28_power_set_linreg(void)
147 {
148         dbg(3, "%s@%d: \n", __func__, __LINE__);
149         /* Set linear regulator 25mV below switching converter */
150         clrsetbits_le32(&power_regs->hw_power_vdddctrl,
151                         POWER_VDDDCTRL_LINREG_OFFSET_MASK,
152                         POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_ABOVE);
153
154         clrsetbits_le32(&power_regs->hw_power_vddactrl,
155                         POWER_VDDACTRL_LINREG_OFFSET_MASK,
156                         POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW);
157
158         clrsetbits_le32(&power_regs->hw_power_vddioctrl,
159                         POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
160                         POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
161         dbg(3, "%s@%d: vddioctrl=%x\n", __func__, __LINE__,
162                 readl(&power_regs->hw_power_vddioctrl));
163 }
164
165 __static void mx28_src_power_init(void)
166 {
167         dbg(3, "%s@%d: \n", __func__, __LINE__);
168         /* Improve efficieny and reduce transient ripple */
169         writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST |
170                 POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set);
171
172         clrsetbits_le32(&power_regs->hw_power_dclimits,
173                         POWER_DCLIMITS_POSLIMIT_BUCK_MASK,
174                         0x30 << POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET);
175
176         setbits_le32(&power_regs->hw_power_battmonitor,
177                         POWER_BATTMONITOR_EN_BATADJ);
178
179         /* Increase the RCSCALE level for quick DCDC response to dynamic load */
180         clrsetbits_le32(&power_regs->hw_power_loopctrl,
181                         POWER_LOOPCTRL_EN_RCSCALE_MASK,
182                         POWER_LOOPCTRL_RCSCALE_THRESH |
183                         POWER_LOOPCTRL_EN_RCSCALE_8X);
184
185         clrsetbits_le32(&power_regs->hw_power_minpwr,
186                         POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
187 #ifndef CONFIG_SPL_FIXED_BATT_SUPPLY
188         /* 5V to battery handoff ... FIXME */
189         setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
190         early_delay(30);
191         clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
192 #endif
193 }
194
195 void mx28_powerdown(void)
196 {
197         dbg(3, "%s@%d: \n", __func__, __LINE__);
198         writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset);
199         writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
200                 &power_regs->hw_power_reset);
201 }
202
203 __static void mx28_fixed_batt_boot(void)
204 {
205         writel(POWER_5VCTRL_PWDN_5VBRNOUT,
206                 &power_regs->hw_power_5vctrl_set);
207         writel(POWER_5VCTRL_ENABLE_DCDC,
208                 &power_regs->hw_power_5vctrl_set);
209
210         writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
211
212         clrsetbits_le32(&power_regs->hw_power_vdddctrl,
213                         POWER_VDDDCTRL_DISABLE_FET |
214                         POWER_VDDDCTRL_ENABLE_LINREG,
215                         POWER_VDDDCTRL_DISABLE_STEPPING);
216
217         /* Stop 5V detection */
218         writel(POWER_5VCTRL_PWRUP_VBUS_CMPS,
219                 &power_regs->hw_power_5vctrl_clr);
220 }
221
222 #ifndef CONFIG_SPL_FIXED_BATT_SUPPLY
223 #define BATT_BO_VALUE   15
224 #else
225 /* Brownout at 3.08V */
226 #define BATT_BO_VALUE   17
227 #endif
228
229 __static void mx28_init_batt_bo(void)
230 {
231         dbg(3, "%s@%d: \n", __func__, __LINE__);
232 #ifndef CONFIG_SPL_FIXED_BATT_SUPPLY
233         /* Brownout at 3V */
234         clrsetbits_le32(&power_regs->hw_power_battmonitor,
235                 POWER_BATTMONITOR_BRWNOUT_LVL_MASK,
236                 15 << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
237
238         writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr);
239         writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
240 #else
241         setbits_le32(&power_regs->hw_power_battmonitor,
242                 POWER_BATTMONITOR_PWDN_BATTBRNOUT);
243         writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr);
244 #endif
245 }
246
247 __static void mx28_switch_vddd_to_dcdc_source(void)
248 {
249         dbg(3, "%s@%d: \n", __func__, __LINE__);
250         clrsetbits_le32(&power_regs->hw_power_vdddctrl,
251                         POWER_VDDDCTRL_LINREG_OFFSET_MASK,
252                         POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
253
254         clrsetbits_le32(&power_regs->hw_power_vdddctrl,
255                         POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_DISABLE_STEPPING,
256                         POWER_VDDDCTRL_ENABLE_LINREG);
257 }
258
259 __static void mx28_enable_output_rail_protection(void)
260 {
261         writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
262                 POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr);
263 #if 0
264         setbits_le32(&power_regs->hw_power_vdddctrl,
265                         POWER_VDDDCTRL_PWDN_BRNOUT);
266
267         setbits_le32(&power_regs->hw_power_vddactrl,
268                         POWER_VDDACTRL_PWDN_BRNOUT);
269
270         setbits_le32(&power_regs->hw_power_vddioctrl,
271                         POWER_VDDIOCTRL_PWDN_BRNOUT);
272 #else
273         clrbits_le32(&power_regs->hw_power_vdddctrl,
274                         POWER_VDDDCTRL_PWDN_BRNOUT);
275
276         clrbits_le32(&power_regs->hw_power_vddactrl,
277                         POWER_VDDACTRL_PWDN_BRNOUT);
278
279         clrbits_le32(&power_regs->hw_power_vddioctrl,
280                         POWER_VDDIOCTRL_PWDN_BRNOUT);
281 #endif
282 }
283
284 __static int mx28_get_vddio_power_source_off(void)
285 {
286         uint32_t tmp;
287
288         dbg(3, "%s@%d: \n", __func__, __LINE__);
289         if (mx28_power_vdd5v_gt_vddio()) {
290                 tmp = readl(&power_regs->hw_power_vddioctrl);
291                 if (tmp & POWER_VDDIOCTRL_DISABLE_FET) {
292                         if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
293                                 POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
294                                 dbg(3, "%s@%d: 1\n", __func__, __LINE__);
295                                 return 1;
296                         }
297                 }
298
299                 if (!(readl(&power_regs->hw_power_5vctrl) &
300                         POWER_5VCTRL_ENABLE_DCDC)) {
301                         dbg(3, "tmp=%x mask %x = %x == %x?\n",
302                                 tmp, POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
303                                 tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
304                                 POWER_VDDDCTRL_LINREG_OFFSET_0STEPS);
305                         if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
306                                 POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
307                                 dbg(3, "%s@%d: 1\n", __func__, __LINE__);
308                                 return 1;
309                         }
310                         if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
311                                 POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW) {
312                                 dbg(3, "%s@%d: 1\n", __func__, __LINE__);
313                                 return 1;
314                         }
315                 }
316         }
317         dbg(3, "%s@%d: 0\n", __func__, __LINE__);
318         return 0;
319 }
320
321 __static int mx28_get_vddd_power_source_off(void)
322 {
323         uint32_t tmp;
324
325 return 0;
326         dbg(3, "%s@%d: \n", __func__, __LINE__);
327         tmp = readl(&power_regs->hw_power_vdddctrl);
328         if (tmp & POWER_VDDDCTRL_DISABLE_FET) {
329                 if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
330                         POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
331                         dbg(3, "%s@%d: 1\n", __func__, __LINE__);
332                         return 1;
333                 }
334         }
335
336         if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
337                 if (!(readl(&power_regs->hw_power_5vctrl) &
338                         POWER_5VCTRL_ENABLE_DCDC)) {
339                         dbg(3, "%s@%d: 1\n", __func__, __LINE__);
340                         return 1;
341                 }
342         }
343
344         if ((tmp & POWER_VDDDCTRL_ENABLE_LINREG)) {
345                 if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
346                         POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW) {
347                         dbg(3, "%s@%d: 1\n", __func__, __LINE__);
348                         return 1;
349                 }
350         }
351         dbg(3, "%s@%d: 0\n", __func__, __LINE__);
352         return 0;
353 }
354
355 __static void mx28_power_set_vddio(uint32_t new_target, uint32_t new_brownout)
356 {
357         uint32_t cur_target, diff, bo_int = 0;
358         uint32_t powered_by_linreg;
359
360         dbg(3, "%s@%d: \n", __func__, __LINE__);
361         new_brownout = (new_target - new_brownout) / 25;
362         if (new_brownout > 7) {
363                 dbg(3, "Bad VDDD brownout offset\n");
364                 new_brownout = 7;
365         }
366
367         cur_target = readl(&power_regs->hw_power_vddioctrl);
368         cur_target &= POWER_VDDIOCTRL_TRG_MASK;
369         cur_target *= 50;       /* 50 mV step*/
370         cur_target += 2800;     /* 2800 mV lowest */
371
372         powered_by_linreg = mx28_get_vddio_power_source_off();
373         if (new_target != cur_target)
374                 dbg(3, "%s@%d: stepping VDDIO from %u to %u\n", __func__, __LINE__,
375                         cur_target, new_target);
376         else
377                 dbg(3, "%s@%d: VDDIO is at %u\n", __func__, __LINE__,
378                         cur_target, new_target);
379         if (new_target > cur_target) {
380
381                 if (powered_by_linreg) {
382                         bo_int = readl(&power_regs->hw_power_vddioctrl);
383                         clrbits_le32(&power_regs->hw_power_vddioctrl,
384                                         POWER_CTRL_ENIRQ_VDDIO_BO);
385                 }
386
387                 setbits_le32(&power_regs->hw_power_vddioctrl,
388                                 POWER_VDDIOCTRL_BO_OFFSET_MASK);
389                 do {
390                         if (new_target - cur_target > 100)
391                                 diff = cur_target + 100;
392                         else
393                                 diff = new_target;
394
395                         diff -= 2800;
396                         diff /= 50;
397
398                         clrsetbits_le32(&power_regs->hw_power_vddioctrl,
399                                 POWER_VDDIOCTRL_TRG_MASK, diff);
400                         dbg(3, "%s@%d: vddioctrl=%x\n", __func__, __LINE__,
401                                 readl(&power_regs->hw_power_vddioctrl));
402
403                         if (powered_by_linreg)
404                                 early_delay(1500);
405                         else {
406                                 while (!(readl(&power_regs->hw_power_sts) &
407                                                 POWER_STS_DC_OK)) {
408                                         early_delay(1);
409                                 }
410                         }
411                         dbg(3, "%s@%d: sts=%x\n", __func__, __LINE__,
412                                 readl(&power_regs->hw_power_sts));
413
414                         cur_target = readl(&power_regs->hw_power_vddioctrl);
415                         cur_target &= POWER_VDDIOCTRL_TRG_MASK;
416                         cur_target *= 50;       /* 50 mV step*/
417                         cur_target += 2800;     /* 2800 mV lowest */
418                 } while (new_target > cur_target);
419
420                 if (powered_by_linreg) {
421                         writel(POWER_CTRL_VDDIO_BO_IRQ,
422                                 &power_regs->hw_power_ctrl_clr);
423                         if (bo_int & POWER_CTRL_ENIRQ_VDDIO_BO)
424                                 setbits_le32(&power_regs->hw_power_vddioctrl,
425                                                 POWER_CTRL_ENIRQ_VDDIO_BO);
426                         dbg(3, "%s@%d: vddioctrl=%x\n", __func__, __LINE__,
427                                 readl(&power_regs->hw_power_vddioctrl));
428                 }
429                 dbg(3, "%s@%d: Done\n", __func__, __LINE__);
430         } else {
431                 do {
432                         if (cur_target - new_target > 100)
433                                 diff = cur_target - 100;
434                         else
435                                 diff = new_target;
436
437                         diff -= 2800;
438                         diff /= 50;
439
440                         clrsetbits_le32(&power_regs->hw_power_vddioctrl,
441                                 POWER_VDDIOCTRL_TRG_MASK, diff);
442
443                         if (powered_by_linreg)
444                                 early_delay(1500);
445                         else {
446                                 while (!(readl(&power_regs->hw_power_sts) &
447                                                 POWER_STS_DC_OK)) {
448                                         early_delay(1);
449                                 }
450                         }
451                         dbg(3, "%s@%d: sts=%x\n", __func__, __LINE__,
452                                 readl(&power_regs->hw_power_sts));
453
454                         cur_target = readl(&power_regs->hw_power_vddioctrl);
455                         cur_target &= POWER_VDDIOCTRL_TRG_MASK;
456                         cur_target *= 50;       /* 50 mV step*/
457                         cur_target += 2800;     /* 2800 mV lowest */
458                 } while (new_target < cur_target);
459                 dbg(3, "%s@%d: Done\n", __func__, __LINE__);
460         }
461
462         clrsetbits_le32(&power_regs->hw_power_vddioctrl,
463                         POWER_VDDDCTRL_BO_OFFSET_MASK,
464                         new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
465         dbg(3, "%s@%d: vddioctrl=%x\n", __func__, __LINE__,
466                 readl(&power_regs->hw_power_vddioctrl));
467 }
468
469 __static void mx28_power_set_vddd(uint32_t new_target, uint32_t new_brownout)
470 {
471         uint32_t cur_target, diff, bo_int = 0;
472         uint32_t powered_by_linreg;
473
474         dbg(3, "%s@%d: \n", __func__, __LINE__);
475         new_brownout = (new_target - new_brownout) / 25;
476         if (new_brownout > 7) {
477                 dbg(3, "Bad VDDD brownout offset\n");
478                 new_brownout = 7;
479         }
480         cur_target = readl(&power_regs->hw_power_vdddctrl);
481         cur_target &= POWER_VDDDCTRL_TRG_MASK;
482         cur_target *= 25;       /* 25 mV step*/
483         cur_target += 800;      /* 800 mV lowest */
484
485         powered_by_linreg = mx28_get_vddd_power_source_off();
486         if (new_target != cur_target)
487                 dbg(3, "%s@%d: stepping VDDD from %u to %u\n", __func__, __LINE__,
488                         cur_target, new_target);
489         else
490                 dbg(3, "%s@%d: VDDD is at %u\n", __func__, __LINE__,
491                         cur_target, new_target);
492         if (new_target > cur_target) {
493                 if (powered_by_linreg) {
494                         bo_int = readl(&power_regs->hw_power_vdddctrl);
495                         clrbits_le32(&power_regs->hw_power_vdddctrl,
496                                         POWER_CTRL_ENIRQ_VDDD_BO);
497                 }
498
499                 setbits_le32(&power_regs->hw_power_vdddctrl,
500                                 POWER_VDDDCTRL_BO_OFFSET_MASK);
501
502                 do {
503                         if (new_target - cur_target > 100)
504                                 diff = cur_target + 100;
505                         else
506                                 diff = new_target;
507
508                         diff -= 800;
509                         diff /= 25;
510
511                         clrsetbits_le32(&power_regs->hw_power_vdddctrl,
512                                 POWER_VDDDCTRL_TRG_MASK, diff);
513
514                         if (powered_by_linreg)
515                                 early_delay(1500);
516                         else {
517                                 while (!(readl(&power_regs->hw_power_sts) &
518                                                 POWER_STS_DC_OK)) {
519                                         early_delay(1);
520                                 }
521                         }
522                         dbg(3, "%s@%d: sts=%x\n", __func__, __LINE__,
523                                 readl(&power_regs->hw_power_sts));
524
525                         cur_target = readl(&power_regs->hw_power_vdddctrl);
526                         cur_target &= POWER_VDDDCTRL_TRG_MASK;
527                         cur_target *= 25;       /* 25 mV step*/
528                         cur_target += 800;      /* 800 mV lowest */
529                 } while (new_target > cur_target);
530
531                 if (powered_by_linreg) {
532                         writel(POWER_CTRL_VDDD_BO_IRQ,
533                                 &power_regs->hw_power_ctrl_clr);
534                         if (bo_int & POWER_CTRL_ENIRQ_VDDD_BO)
535                                 setbits_le32(&power_regs->hw_power_vdddctrl,
536                                                 POWER_CTRL_ENIRQ_VDDD_BO);
537                 }
538                 dbg(3, "%s@%d: Done\n", __func__, __LINE__);
539         } else {
540                 do {
541                         if (cur_target - new_target > 100)
542                                 diff = cur_target - 100;
543                         else
544                                 diff = new_target;
545
546                         diff -= 800;
547                         diff /= 25;
548
549                         clrsetbits_le32(&power_regs->hw_power_vdddctrl,
550                                         POWER_VDDDCTRL_TRG_MASK, diff);
551
552                         if (powered_by_linreg)
553                                 early_delay(1500);
554                         else {
555                                 while (!(readl(&power_regs->hw_power_sts) &
556                                                 POWER_STS_DC_OK)) {
557                                         early_delay(1);
558                                 }
559                         }
560                         dbg(3, "%s@%d: sts=%x\n", __func__, __LINE__,
561                                 readl(&power_regs->hw_power_sts));
562
563                         cur_target = readl(&power_regs->hw_power_vdddctrl);
564                         cur_target &= POWER_VDDDCTRL_TRG_MASK;
565                         cur_target *= 25;       /* 25 mV step*/
566                         cur_target += 800;      /* 800 mV lowest */
567                 } while (new_target < cur_target);
568                 dbg(3, "%s@%d: Done\n", __func__, __LINE__);
569         }
570
571         clrsetbits_le32(&power_regs->hw_power_vdddctrl,
572                         POWER_VDDDCTRL_BO_OFFSET_MASK,
573                         new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
574 }
575
576 void mx28_power_init(void)
577 {
578         dprintf("%s: %s %s\n", __func__, __DATE__, __TIME__);
579         dbg(0, "ctrl=%x\n", readl(&power_regs->hw_power_ctrl));
580         dbg(0, "sts=%x\n", readl(&power_regs->hw_power_sts));
581
582         dbg(3, "%s@%d\n", __func__, __LINE__);
583         mx28_power_clock2xtal();
584         dbg(3, "%s@%d\n", __func__, __LINE__);
585         mx28_power_clear_auto_restart();
586         dbg(3, "%s@%d\n", __func__, __LINE__);
587         mx28_power_set_linreg();
588         dbg(3, "%s@%d\n", __func__, __LINE__);
589
590         mx28_src_power_init();
591         dbg(3, "%s@%d\n", __func__, __LINE__);
592         early_delay(10000);
593         mx28_fixed_batt_boot();
594         dbg(3, "%s@%d\n", __func__, __LINE__);
595         early_delay(10000);
596         mx28_power_clock2pll();
597         early_delay(10000);
598         dbg(3, "%s@%d\n", __func__, __LINE__);
599         mx28_init_batt_bo();
600         early_delay(10000);
601         dbg(3, "%s@%d\n", __func__, __LINE__);
602         mx28_switch_vddd_to_dcdc_source();
603         early_delay(10000);
604
605         dbg(3, "%s@%d\n", __func__, __LINE__);
606         mx28_enable_output_rail_protection();
607
608         dbg(3, "%s@%d\n", __func__, __LINE__);
609         mx28_power_set_vddio(3300, 3150);
610
611         dbg(3, "%s@%d\n", __func__, __LINE__);
612         mx28_power_set_vddd(1500, 1325);
613         dbg(3, "%s@%d\n", __func__, __LINE__);
614
615         writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
616                 POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
617                 POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ |
618                 POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
619
620         dbg(3, "sts=%x\n", readl(&power_regs->hw_power_sts));
621         dbg(3, "vddioctrl=%x\n", readl(&power_regs->hw_power_vddioctrl));
622         dbg(3, "vdddctrl=%x\n", readl(&power_regs->hw_power_vdddctrl));
623         dbg(3, "5vctrl=%x\n", readl(&power_regs->hw_power_5vctrl));
624         dbg(3, "dcdc4p2=%x\n", readl(&power_regs->hw_power_dcdc4p2));
625         dbg(3, "%s@%d: Finished\n", __func__, __LINE__);
626         memdump(0x80044000, 0x60);
627         early_delay(1000);
628 }
629
630 #ifdef  CONFIG_SPL_MX28_PSWITCH_WAIT
631 void mx28_power_wait_pswitch(void)
632 {
633         dbg(3, "%s@%d: \n", __func__, __LINE__);
634         while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK))
635                 ;
636 }
637 #endif