2 * Freescale i.MX28 Boot PMIC init
4 * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
5 * on behalf of DENX Software Engineering GmbH
7 * See file CREDITS for list of people who contributed to this
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.
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.
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,
29 #include <asm/arch/imx-regs.h>
33 #ifdef CONFIG_SYS_SPL_VDDD_VAL
34 #define VDDD_VAL CONFIG_SYS_SPL_VDDD_VAL
38 #ifdef CONFIG_SYS_SPL_VDDIO_VAL
39 #define VDDIO_VAL CONFIG_SYS_SPL_VDDIO_VAL
41 #define VDDIO_VAL 3300
43 #ifdef CONFIG_SYS_SPL_VDDA_VAL
44 #define VDDA_VAL CONFIG_SYS_SPL_VDDA_VAL
48 #ifdef CONFIG_SYS_SPL_VDDMEM_VAL
49 #define VDDMEM_VAL CONFIG_SYS_SPL_VDDMEM_VAL
51 #define VDDMEM_VAL 1500
54 #ifdef CONFIG_SYS_SPL_VDDD_BO_VAL
55 #define VDDD_BO_VAL CONFIG_SYS_SPL_VDDD_BO_VAL
57 #define VDDD_BO_VAL 150
59 #ifdef CONFIG_SYS_SPL_VDDIO_BO_VAL
60 #define VDDIO_BO_VAL CONFIG_SYS_SPL_VDDIO_BO_VAL
62 #define VDDIO_BO_VAL 150
64 #ifdef CONFIG_SYS_SPL_VDDA_BO_VAL
65 #define VDDA_BO_VAL CONFIG_SYS_SPL_VDDA_BO_VAL
67 #define VDDA_BO_VAL 175
69 #ifdef CONFIG_SYS_SPL_VDDMEM_BO_VAL
70 #define VDDMEM_BO_VAL CONFIG_SYS_SPL_VDDMEM_BO_VAL
72 #define VDDMEM_BO_VAL 25
75 #ifdef CONFIG_SYS_SPL_BATT_BO_LEVEL
76 #if CONFIG_SYS_SPL_BATT_BO_LEVEL < 2400 || CONFIG_SYS_SPL_BATT_BO_LEVEL > 3640
77 #error CONFIG_SYS_SPL_BATT_BO_LEVEL out of range
79 #define BATT_BO_VAL (((CONFIG_SYS_SPL_BATT_BO_LEVEL) - 2400) / 40)
81 /* Brownout default at 3V */
82 #define BATT_BO_VAL ((3000 - 2400) / 40)
85 #ifdef CONFIG_SYS_SPL_FIXED_BATT_SUPPLY
86 static const int fixed_batt_supply = 1;
88 static const int fixed_batt_supply;
91 static struct mxs_power_regs *power_regs = (void *)MXS_POWER_BASE;
93 static void mxs_power_clock2xtal(void)
95 struct mxs_clkctrl_regs *clkctrl_regs =
96 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
98 /* Set XTAL as CPU reference clock */
99 writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
100 &clkctrl_regs->hw_clkctrl_clkseq_set);
103 static void mxs_power_clock2pll(void)
105 struct mxs_clkctrl_regs *clkctrl_regs =
106 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
108 setbits_le32(&clkctrl_regs->hw_clkctrl_pll0ctrl0,
109 CLKCTRL_PLL0CTRL0_POWER);
111 setbits_le32(&clkctrl_regs->hw_clkctrl_clkseq,
112 CLKCTRL_CLKSEQ_BYPASS_CPU);
115 static int mxs_power_wait_rtc_stat(u32 mask)
117 int timeout = 5000; /* 3 ms according to i.MX28 Ref. Manual */
119 struct mxs_rtc_regs *rtc_regs = (void *)MXS_RTC_BASE;
121 while ((val = readl(&rtc_regs->hw_rtc_stat)) & mask) {
126 return !!(readl(&rtc_regs->hw_rtc_stat) & mask);
129 static int mxs_power_set_auto_restart(int on)
131 struct mxs_rtc_regs *rtc_regs = (void *)MXS_RTC_BASE;
134 * Due to the hardware design bug of mx28 EVK-A
135 * we need to set the AUTO_RESTART bit.
137 if (mxs_power_wait_rtc_stat(RTC_STAT_STALE_REGS_PERSISTENT0))
140 if ((!(readl(&rtc_regs->hw_rtc_persistent0) &
141 RTC_PERSISTENT0_AUTO_RESTART) ^ !on) == 0)
144 if (mxs_power_wait_rtc_stat(RTC_STAT_NEW_REGS_PERSISTENT0))
147 clrsetbits_le32(&rtc_regs->hw_rtc_persistent0,
148 !on * RTC_PERSISTENT0_AUTO_RESTART,
149 !!on * RTC_PERSISTENT0_AUTO_RESTART);
150 if (mxs_power_wait_rtc_stat(RTC_STAT_NEW_REGS_PERSISTENT0))
156 static void mxs_power_set_linreg(void)
158 /* Set linear regulator 25mV below switching converter */
159 clrsetbits_le32(&power_regs->hw_power_vdddctrl,
160 POWER_VDDDCTRL_LINREG_OFFSET_MASK,
161 POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
163 clrsetbits_le32(&power_regs->hw_power_vddactrl,
164 POWER_VDDACTRL_LINREG_OFFSET_MASK,
165 POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW);
167 clrsetbits_le32(&power_regs->hw_power_vddioctrl,
168 POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
169 POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
172 static int mxs_get_batt_volt(void)
174 uint32_t volt = readl(&power_regs->hw_power_battmonitor);
176 volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
177 volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
182 static int mxs_is_batt_ready(void)
184 return (mxs_get_batt_volt() >= 3600);
187 static int mxs_is_batt_good(void)
189 uint32_t volt = mxs_get_batt_volt();
191 if ((volt >= 2400) && (volt <= 4300))
194 clrsetbits_le32(&power_regs->hw_power_5vctrl,
195 POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
196 0x3 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
197 writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
198 &power_regs->hw_power_5vctrl_clr);
200 clrsetbits_le32(&power_regs->hw_power_charge,
201 POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
202 POWER_CHARGE_STOP_ILIMIT_10MA | 0x3);
204 writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_clr);
205 writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
206 &power_regs->hw_power_5vctrl_clr);
210 volt = mxs_get_batt_volt();
218 writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
219 &power_regs->hw_power_charge_clr);
220 writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
225 static void mxs_power_setup_5v_detect(void)
227 /* Start 5V detection */
228 clrsetbits_le32(&power_regs->hw_power_5vctrl,
229 POWER_5VCTRL_VBUSVALID_TRSH_MASK,
230 POWER_5VCTRL_VBUSVALID_TRSH_4V4 |
231 POWER_5VCTRL_PWRUP_VBUS_CMPS);
234 static void mxs_src_power_init(void)
236 /* Improve efficieny and reduce transient ripple */
237 writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST |
238 POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set);
240 clrsetbits_le32(&power_regs->hw_power_dclimits,
241 POWER_DCLIMITS_POSLIMIT_BUCK_MASK,
242 0x30 << POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET);
244 if (!fixed_batt_supply) {
245 /* FIXME: This requires the LRADC to be set up! */
246 setbits_le32(&power_regs->hw_power_battmonitor,
247 POWER_BATTMONITOR_EN_BATADJ);
249 clrbits_le32(&power_regs->hw_power_battmonitor,
250 POWER_BATTMONITOR_EN_BATADJ);
253 /* Increase the RCSCALE level for quick DCDC response to dynamic load */
254 clrsetbits_le32(&power_regs->hw_power_loopctrl,
255 POWER_LOOPCTRL_EN_RCSCALE_MASK,
256 POWER_LOOPCTRL_RCSCALE_THRESH |
257 POWER_LOOPCTRL_EN_RCSCALE_8X);
259 clrsetbits_le32(&power_regs->hw_power_minpwr,
260 POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
262 if (!fixed_batt_supply) {
263 /* 5V to battery handoff ... FIXME */
264 setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
266 clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
270 static void mxs_power_init_4p2_params(void)
272 /* Setup 4P2 parameters */
273 clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
274 POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK,
275 POWER_DCDC4P2_TRG_4V2 | (31 << POWER_DCDC4P2_CMPTRIP_OFFSET));
277 clrsetbits_le32(&power_regs->hw_power_5vctrl,
278 POWER_5VCTRL_HEADROOM_ADJ_MASK,
279 0x4 << POWER_5VCTRL_HEADROOM_ADJ_OFFSET);
281 clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
282 POWER_DCDC4P2_DROPOUT_CTRL_MASK,
283 POWER_DCDC4P2_DROPOUT_CTRL_100MV |
284 POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL);
286 clrsetbits_le32(&power_regs->hw_power_5vctrl,
287 POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
288 0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
291 static void mxs_enable_4p2_dcdc_input(int xfer)
293 uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo;
294 uint32_t prev_5v_brnout, prev_5v_droop;
296 prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) &
297 POWER_5VCTRL_PWDN_5VBRNOUT;
298 prev_5v_droop = readl(&power_regs->hw_power_ctrl) &
299 POWER_CTRL_ENIRQ_VDD5V_DROOP;
301 clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
302 writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
303 &power_regs->hw_power_reset);
305 clrbits_le32(&power_regs->hw_power_ctrl, POWER_CTRL_ENIRQ_VDD5V_DROOP);
307 if (xfer && (readl(&power_regs->hw_power_5vctrl) &
308 POWER_5VCTRL_ENABLE_DCDC)) {
313 * Recording orignal values that will be modified temporarlily
314 * to handle a chip bug. See chip errata for CQ ENGR00115837
316 tmp = readl(&power_regs->hw_power_5vctrl);
317 vbus_thresh = tmp & POWER_5VCTRL_VBUSVALID_TRSH_MASK;
318 vbus_5vdetect = tmp & POWER_5VCTRL_VBUSVALID_5VDETECT;
320 pwd_bo = readl(&power_regs->hw_power_minpwr) & POWER_MINPWR_PWD_BO;
323 * Disable mechanisms that get erroneously tripped by when setting
324 * the DCDC4P2 EN_DCDC
326 clrbits_le32(&power_regs->hw_power_5vctrl,
327 POWER_5VCTRL_VBUSVALID_5VDETECT |
328 POWER_5VCTRL_VBUSVALID_TRSH_MASK);
330 writel(POWER_MINPWR_PWD_BO, &power_regs->hw_power_minpwr_set);
333 setbits_le32(&power_regs->hw_power_5vctrl,
334 POWER_5VCTRL_DCDC_XFER);
336 clrbits_le32(&power_regs->hw_power_5vctrl,
337 POWER_5VCTRL_DCDC_XFER);
339 setbits_le32(&power_regs->hw_power_5vctrl,
340 POWER_5VCTRL_ENABLE_DCDC);
342 setbits_le32(&power_regs->hw_power_dcdc4p2,
343 POWER_DCDC4P2_ENABLE_DCDC);
348 clrsetbits_le32(&power_regs->hw_power_5vctrl,
349 POWER_5VCTRL_VBUSVALID_TRSH_MASK, vbus_thresh);
352 writel(vbus_5vdetect, &power_regs->hw_power_5vctrl_set);
355 clrbits_le32(&power_regs->hw_power_minpwr, POWER_MINPWR_PWD_BO);
357 while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ)
358 writel(POWER_CTRL_VBUS_VALID_IRQ,
359 &power_regs->hw_power_ctrl_clr);
361 if (prev_5v_brnout) {
362 writel(POWER_5VCTRL_PWDN_5VBRNOUT,
363 &power_regs->hw_power_5vctrl_set);
364 writel(POWER_RESET_UNLOCK_KEY,
365 &power_regs->hw_power_reset);
367 writel(POWER_5VCTRL_PWDN_5VBRNOUT,
368 &power_regs->hw_power_5vctrl_clr);
369 writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
370 &power_regs->hw_power_reset);
373 while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VDD5V_DROOP_IRQ)
374 writel(POWER_CTRL_VDD5V_DROOP_IRQ,
375 &power_regs->hw_power_ctrl_clr);
378 clrbits_le32(&power_regs->hw_power_ctrl,
379 POWER_CTRL_ENIRQ_VDD5V_DROOP);
381 setbits_le32(&power_regs->hw_power_ctrl,
382 POWER_CTRL_ENIRQ_VDD5V_DROOP);
385 static void mxs_power_init_4p2_regulator(void)
389 setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2);
391 writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set);
393 writel(POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
394 &power_regs->hw_power_5vctrl_clr);
395 clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_TRG_MASK);
397 /* Power up the 4p2 rail and logic/control */
398 writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
399 &power_regs->hw_power_5vctrl_clr);
402 * Start charging up the 4p2 capacitor. We ramp of this charge
403 * gradually to avoid large inrush current from the 5V cable which can
404 * cause transients/problems
406 mxs_enable_4p2_dcdc_input(0);
408 if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
410 * If we arrived here, we were unable to recover from mx23 chip
411 * errata 5837. 4P2 is disabled and sufficient battery power is
412 * not present. Exiting to not enable DCDC power during 5V
415 clrbits_le32(&power_regs->hw_power_dcdc4p2,
416 POWER_DCDC4P2_ENABLE_DCDC);
417 writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
418 &power_regs->hw_power_5vctrl_set);
423 * Here we set the 4p2 brownout level to something very close to 4.2V.
424 * We then check the brownout status. If the brownout status is false,
425 * the voltage is already close to the target voltage of 4.2V so we
426 * can go ahead and set the 4P2 current limit to our max target limit.
427 * If the brownout status is true, we need to ramp us the current limit
428 * so that we don't cause large inrush current issues. We step up the
429 * current limit until the brownout status is false or until we've
430 * reached our maximum defined 4p2 current limit.
432 clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
433 POWER_DCDC4P2_BO_MASK,
434 22 << POWER_DCDC4P2_BO_OFFSET); /* 4.15V */
436 if (!(readl(&power_regs->hw_power_sts) & POWER_STS_DCDC_4P2_BO)) {
437 setbits_le32(&power_regs->hw_power_5vctrl,
438 0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
440 tmp = (readl(&power_regs->hw_power_5vctrl) &
441 POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK) >>
442 POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
444 if (!(readl(&power_regs->hw_power_sts) &
445 POWER_STS_DCDC_4P2_BO)) {
446 tmp = readl(&power_regs->hw_power_5vctrl);
447 tmp |= POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
449 writel(tmp, &power_regs->hw_power_5vctrl);
453 tmp2 = readl(&power_regs->hw_power_5vctrl);
454 tmp2 &= ~POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
456 POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
457 writel(tmp2, &power_regs->hw_power_5vctrl);
463 clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
464 writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
467 static void mxs_power_init_dcdc_4p2_source(void)
469 if (!(readl(&power_regs->hw_power_dcdc4p2) &
470 POWER_DCDC4P2_ENABLE_DCDC)) {
474 mxs_enable_4p2_dcdc_input(1);
476 if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
477 clrbits_le32(&power_regs->hw_power_dcdc4p2,
478 POWER_DCDC4P2_ENABLE_DCDC);
479 writel(POWER_5VCTRL_ENABLE_DCDC,
480 &power_regs->hw_power_5vctrl_clr);
481 writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
482 &power_regs->hw_power_5vctrl_set);
486 static void mxs_power_enable_4p2(void)
488 uint32_t vdddctrl, vddactrl, vddioctrl;
491 vdddctrl = readl(&power_regs->hw_power_vdddctrl);
492 vddactrl = readl(&power_regs->hw_power_vddactrl);
493 vddioctrl = readl(&power_regs->hw_power_vddioctrl);
495 setbits_le32(&power_regs->hw_power_vdddctrl,
496 POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
497 POWER_VDDDCTRL_PWDN_BRNOUT);
499 setbits_le32(&power_regs->hw_power_vddactrl,
500 POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG |
501 POWER_VDDACTRL_PWDN_BRNOUT);
503 setbits_le32(&power_regs->hw_power_vddioctrl,
504 POWER_VDDIOCTRL_DISABLE_FET | POWER_VDDIOCTRL_PWDN_BRNOUT);
506 mxs_power_init_4p2_params();
507 mxs_power_init_4p2_regulator();
509 /* Shutdown battery (none present) */
510 if (!mxs_is_batt_ready()) {
511 clrbits_le32(&power_regs->hw_power_dcdc4p2,
512 POWER_DCDC4P2_BO_MASK);
513 writel(POWER_CTRL_DCDC4P2_BO_IRQ,
514 &power_regs->hw_power_ctrl_clr);
515 writel(POWER_CTRL_ENIRQ_DCDC4P2_BO,
516 &power_regs->hw_power_ctrl_clr);
519 mxs_power_init_dcdc_4p2_source();
521 writel(vdddctrl, &power_regs->hw_power_vdddctrl);
523 writel(vddactrl, &power_regs->hw_power_vddactrl);
525 writel(vddioctrl, &power_regs->hw_power_vddioctrl);
528 * Check if FET is enabled on either powerout and if so,
532 tmp |= !(readl(&power_regs->hw_power_vdddctrl) &
533 POWER_VDDDCTRL_DISABLE_FET);
534 tmp |= !(readl(&power_regs->hw_power_vddactrl) &
535 POWER_VDDACTRL_DISABLE_FET);
536 tmp |= !(readl(&power_regs->hw_power_vddioctrl) &
537 POWER_VDDIOCTRL_DISABLE_FET);
539 writel(POWER_CHARGE_ENABLE_LOAD,
540 &power_regs->hw_power_charge_clr);
543 static void mxs_boot_valid_5v(void)
546 * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V
547 * disconnect event. FIXME
549 writel(POWER_5VCTRL_VBUSVALID_5VDETECT,
550 &power_regs->hw_power_5vctrl_set);
552 /* Configure polarity to check for 5V disconnection. */
553 writel(POWER_CTRL_POLARITY_VBUSVALID |
554 POWER_CTRL_POLARITY_VDD5V_GT_VDDIO,
555 &power_regs->hw_power_ctrl_clr);
557 writel(POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_VDD5V_GT_VDDIO_IRQ,
558 &power_regs->hw_power_ctrl_clr);
560 mxs_power_enable_4p2();
563 static void mxs_powerdown(void)
565 writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset);
566 writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
567 &power_regs->hw_power_reset);
570 static void mxs_batt_boot(void)
572 clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
573 clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_ENABLE_DCDC);
575 clrbits_le32(&power_regs->hw_power_dcdc4p2,
576 POWER_DCDC4P2_ENABLE_DCDC | POWER_DCDC4P2_ENABLE_4P2);
577 writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_clr);
579 /* 5V to battery handoff. */
580 setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
582 clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
584 writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, &power_regs->hw_power_ctrl_clr);
586 clrsetbits_le32(&power_regs->hw_power_minpwr,
587 POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
589 mxs_power_set_linreg();
591 clrbits_le32(&power_regs->hw_power_vdddctrl,
592 POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG);
594 clrbits_le32(&power_regs->hw_power_vddactrl,
595 POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG);
597 clrbits_le32(&power_regs->hw_power_vddioctrl,
598 POWER_VDDIOCTRL_DISABLE_FET);
600 setbits_le32(&power_regs->hw_power_5vctrl,
601 POWER_5VCTRL_PWD_CHARGE_4P2_MASK);
603 setbits_le32(&power_regs->hw_power_5vctrl,
604 POWER_5VCTRL_ENABLE_DCDC);
606 clrsetbits_le32(&power_regs->hw_power_5vctrl,
607 POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
608 0x8 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
611 static void mxs_handle_5v_conflict(void)
615 setbits_le32(&power_regs->hw_power_vddioctrl,
616 POWER_VDDIOCTRL_BO_OFFSET_MASK);
619 tmp = readl(&power_regs->hw_power_sts);
621 if (tmp & POWER_STS_VDDIO_BO) {
623 * VDDIO has a brownout, then the VDD5V_GT_VDDIO becomes
630 if (tmp & POWER_STS_VDD5V_GT_VDDIO) {
638 if (tmp & POWER_STS_PSWITCH_MASK) {
645 static void mxs_5v_boot(void)
648 * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID,
649 * but their implementation always returns 1 so we omit it here.
651 if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
657 if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
662 mxs_handle_5v_conflict();
665 static void mxs_fixed_batt_boot(void)
667 writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
669 setbits_le32(&power_regs->hw_power_5vctrl,
670 POWER_5VCTRL_PWDN_5VBRNOUT |
671 POWER_5VCTRL_ENABLE_DCDC |
672 POWER_5VCTRL_ILIMIT_EQ_ZERO |
673 POWER_5VCTRL_PWDN_5VBRNOUT |
674 POWER_5VCTRL_PWD_CHARGE_4P2_MASK);
676 writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
678 clrbits_le32(&power_regs->hw_power_vdddctrl,
679 POWER_VDDDCTRL_DISABLE_FET |
680 POWER_VDDDCTRL_ENABLE_LINREG |
681 POWER_VDDDCTRL_DISABLE_STEPPING);
683 clrbits_le32(&power_regs->hw_power_vddactrl,
684 POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG |
685 POWER_VDDACTRL_DISABLE_STEPPING);
687 clrbits_le32(&power_regs->hw_power_vddioctrl,
688 POWER_VDDIOCTRL_DISABLE_FET |
689 POWER_VDDIOCTRL_DISABLE_STEPPING);
691 /* Stop 5V detection */
692 writel(POWER_5VCTRL_PWRUP_VBUS_CMPS,
693 &power_regs->hw_power_5vctrl_clr);
696 static void mxs_init_batt_bo(void)
698 clrsetbits_le32(&power_regs->hw_power_battmonitor,
699 POWER_BATTMONITOR_BRWNOUT_LVL_MASK,
700 BATT_BO_VAL << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
702 writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr);
703 writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
706 static void mxs_switch_vddd_to_dcdc_source(void)
708 clrsetbits_le32(&power_regs->hw_power_vdddctrl,
709 POWER_VDDDCTRL_LINREG_OFFSET_MASK,
710 POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
712 clrbits_le32(&power_regs->hw_power_vdddctrl,
713 POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
714 POWER_VDDDCTRL_DISABLE_STEPPING);
717 static void mxs_power_configure_power_source(void)
719 struct mxs_lradc_regs *lradc_regs =
720 (struct mxs_lradc_regs *)MXS_LRADC_BASE;
722 mxs_src_power_init();
724 if (!fixed_batt_supply) {
725 if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
726 if (mxs_is_batt_ready()) {
727 /* 5V source detected, good battery detected. */
730 if (!mxs_is_batt_good()) {
731 /* 5V source detected, bad battery detected. */
732 writel(LRADC_CONVERSION_AUTOMATIC,
733 &lradc_regs->hw_lradc_conversion_clr);
734 clrbits_le32(&power_regs->hw_power_battmonitor,
735 POWER_BATTMONITOR_BATT_VAL_MASK);
740 /* 5V not detected, booting from battery. */
744 mxs_fixed_batt_boot();
747 mxs_power_clock2pll();
751 mxs_switch_vddd_to_dcdc_source();
754 static void mxs_enable_output_rail_protection(void)
756 writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
757 POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr);
759 setbits_le32(&power_regs->hw_power_vdddctrl,
760 POWER_VDDDCTRL_PWDN_BRNOUT);
762 setbits_le32(&power_regs->hw_power_vddactrl,
763 POWER_VDDACTRL_PWDN_BRNOUT);
765 setbits_le32(&power_regs->hw_power_vddioctrl,
766 POWER_VDDIOCTRL_PWDN_BRNOUT);
769 static int mxs_get_vddio_power_source_off(void)
773 if ((readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) &&
774 !(readl(&power_regs->hw_power_5vctrl) &
775 POWER_5VCTRL_ILIMIT_EQ_ZERO)) {
777 tmp = readl(&power_regs->hw_power_vddioctrl);
778 if (tmp & POWER_VDDIOCTRL_DISABLE_FET) {
779 if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
780 POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS) {
785 if (!(readl(&power_regs->hw_power_5vctrl) &
786 POWER_5VCTRL_ENABLE_DCDC)) {
787 if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
788 POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS) {
797 static int mxs_get_vddd_power_source_off(void)
801 tmp = readl(&power_regs->hw_power_vdddctrl);
802 if (tmp & POWER_VDDDCTRL_DISABLE_FET) {
803 if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
804 POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
809 if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
810 if (!(readl(&power_regs->hw_power_5vctrl) &
811 POWER_5VCTRL_ENABLE_DCDC)) {
816 if (!(tmp & POWER_VDDDCTRL_ENABLE_LINREG)) {
817 if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
818 POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW) {
826 static int mxs_get_vdda_power_source_off(void)
830 tmp = readl(&power_regs->hw_power_vddactrl);
831 if (tmp & POWER_VDDACTRL_DISABLE_FET) {
832 if ((tmp & POWER_VDDACTRL_LINREG_OFFSET_MASK) ==
833 POWER_VDDACTRL_LINREG_OFFSET_0STEPS) {
838 if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
839 if (!(readl(&power_regs->hw_power_5vctrl) &
840 POWER_5VCTRL_ENABLE_DCDC)) {
845 if (!(tmp & POWER_VDDACTRL_ENABLE_LINREG)) {
846 if ((tmp & POWER_VDDACTRL_LINREG_OFFSET_MASK) ==
847 POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW) {
855 struct mxs_vddx_cfg {
860 int (*powered_by_linreg)(void);
864 uint32_t bo_offset_mask;
865 uint32_t bo_offset_offset;
868 static const struct mxs_vddx_cfg mxs_vddio_cfg = {
869 .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
874 .powered_by_linreg = mxs_get_vddio_power_source_off,
875 .trg_mask = POWER_VDDIOCTRL_TRG_MASK,
876 .bo_irq = POWER_CTRL_VDDIO_BO_IRQ,
877 .bo_enirq = POWER_CTRL_ENIRQ_VDDIO_BO,
878 .bo_offset_mask = POWER_VDDIOCTRL_BO_OFFSET_MASK,
879 .bo_offset_offset = POWER_VDDIOCTRL_BO_OFFSET_OFFSET,
882 static const struct mxs_vddx_cfg mxs_vddd_cfg = {
883 .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
888 .powered_by_linreg = mxs_get_vddd_power_source_off,
889 .trg_mask = POWER_VDDDCTRL_TRG_MASK,
890 .bo_irq = POWER_CTRL_VDDD_BO_IRQ,
891 .bo_enirq = POWER_CTRL_ENIRQ_VDDD_BO,
892 .bo_offset_mask = POWER_VDDDCTRL_BO_OFFSET_MASK,
893 .bo_offset_offset = POWER_VDDDCTRL_BO_OFFSET_OFFSET,
896 static const struct mxs_vddx_cfg mxs_vdda_cfg = {
897 .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
902 .powered_by_linreg = mxs_get_vdda_power_source_off,
903 .trg_mask = POWER_VDDACTRL_TRG_MASK,
904 .bo_irq = POWER_CTRL_VDDA_BO_IRQ,
905 .bo_enirq = POWER_CTRL_ENIRQ_VDDA_BO,
906 .bo_offset_mask = POWER_VDDACTRL_BO_OFFSET_MASK,
907 .bo_offset_offset = POWER_VDDACTRL_BO_OFFSET_OFFSET,
910 static const struct mxs_vddx_cfg mxs_vddmem_cfg = {
911 .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
912 hw_power_vddmemctrl),
916 .bo_offset_mask = POWER_VDDMEMCTRL_BO_OFFSET_MASK,
917 .bo_offset_offset = POWER_VDDMEMCTRL_BO_OFFSET_OFFSET,
920 static void mxs_power_set_vddx(const struct mxs_vddx_cfg *cfg,
921 uint32_t new_target, uint32_t new_brownout)
923 uint32_t cur_target, diff, bo_int = 0;
924 int powered_by_linreg = 0;
927 if (new_target < cfg->lowest_mV)
928 new_target = cfg->lowest_mV;
929 if (new_target > cfg->highest_mV)
930 new_target = cfg->highest_mV;
932 new_brownout = DIV_ROUND(new_target - new_brownout, cfg->step_mV);
934 cur_target = readl(cfg->reg);
935 cur_target &= cfg->trg_mask;
936 cur_target *= cfg->step_mV;
937 cur_target += cfg->lowest_mV;
939 adjust_up = new_target > cur_target;
940 if (cfg->powered_by_linreg)
941 powered_by_linreg = cfg->powered_by_linreg();
944 if (powered_by_linreg) {
945 bo_int = readl(cfg->reg);
946 clrbits_le32(cfg->reg, cfg->bo_enirq);
948 setbits_le32(cfg->reg, cfg->bo_offset_mask);
952 if (abs(new_target - cur_target) > 100) {
954 diff = cur_target + 100;
956 diff = cur_target - 100;
961 diff -= cfg->lowest_mV;
962 diff /= cfg->step_mV;
964 clrsetbits_le32(cfg->reg, cfg->trg_mask, diff);
966 if (powered_by_linreg ||
967 (readl(&power_regs->hw_power_sts) &
968 POWER_STS_VDD5V_GT_VDDIO)) {
971 while (!(readl(&power_regs->hw_power_sts) &
977 cur_target = readl(cfg->reg);
978 cur_target &= cfg->trg_mask;
979 cur_target *= cfg->step_mV;
980 cur_target += cfg->lowest_mV;
981 } while (new_target > cur_target);
983 if (adjust_up && powered_by_linreg) {
984 writel(cfg->bo_irq, &power_regs->hw_power_ctrl_clr);
985 if (bo_int & cfg->bo_enirq)
986 setbits_le32(cfg->reg, cfg->bo_enirq);
989 clrsetbits_le32(cfg->reg, cfg->bo_offset_mask,
990 new_brownout << cfg->bo_offset_offset);
993 static void mxs_setup_batt_detect(void)
996 mxs_lradc_enable_batt_measurement();
1000 #ifdef CONFIG_CONFIG_MACH_MX28EVK
1001 #define auto_restart 1
1003 #define auto_restart 0
1006 void mxs_power_init(void)
1008 mxs_power_clock2xtal();
1009 if (mxs_power_set_auto_restart(auto_restart)) {
1010 serial_puts("Inconsistent value in RTC_PERSISTENT0 register; power-on-reset required\n");
1012 mxs_power_set_linreg();
1014 if (!fixed_batt_supply) {
1015 mxs_power_setup_5v_detect();
1016 mxs_setup_batt_detect();
1019 mxs_power_configure_power_source();
1020 mxs_enable_output_rail_protection();
1022 mxs_power_set_vddx(&mxs_vddio_cfg, VDDIO_VAL, VDDIO_BO_VAL);
1023 mxs_power_set_vddx(&mxs_vddd_cfg, VDDD_VAL, VDDD_BO_VAL);
1024 mxs_power_set_vddx(&mxs_vdda_cfg, VDDA_VAL, VDDA_BO_VAL);
1026 mxs_power_set_vddx(&mxs_vddmem_cfg, VDDMEM_VAL, VDDMEM_BO_VAL);
1028 setbits_le32(&power_regs->hw_power_vddmemctrl,
1029 POWER_VDDMEMCTRL_ENABLE_LINREG);
1031 clrbits_le32(&power_regs->hw_power_vddmemctrl,
1032 POWER_VDDMEMCTRL_ENABLE_ILIMIT);
1034 clrbits_le32(&power_regs->hw_power_vddmemctrl,
1035 POWER_VDDMEMCTRL_ENABLE_LINREG);
1037 writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
1038 POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
1039 POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ |
1040 POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
1041 if (!fixed_batt_supply)
1042 writel(POWER_5VCTRL_PWDN_5VBRNOUT,
1043 &power_regs->hw_power_5vctrl_set);
1046 #ifdef CONFIG_SPL_MX28_PSWITCH_WAIT
1047 void mxs_power_wait_pswitch(void)
1049 while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK))