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