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 * SPDX-License-Identifier: GPL-2.0+
13 #include <asm/arch/imx-regs.h>
17 static void mxs_power_clock2xtal(void)
19 struct mxs_clkctrl_regs *clkctrl_regs =
20 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
22 /* Set XTAL as CPU reference clock */
23 writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
24 &clkctrl_regs->hw_clkctrl_clkseq_set);
27 static void mxs_power_clock2pll(void)
29 struct mxs_clkctrl_regs *clkctrl_regs =
30 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
32 setbits_le32(&clkctrl_regs->hw_clkctrl_pll0ctrl0,
33 CLKCTRL_PLL0CTRL0_POWER);
35 setbits_le32(&clkctrl_regs->hw_clkctrl_clkseq,
36 CLKCTRL_CLKSEQ_BYPASS_CPU);
39 static void mxs_power_set_auto_restart(void)
41 struct mxs_rtc_regs *rtc_regs =
42 (struct mxs_rtc_regs *)MXS_RTC_BASE;
44 writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr);
45 while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST)
48 writel(RTC_CTRL_CLKGATE, &rtc_regs->hw_rtc_ctrl_clr);
49 while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE)
52 /* Do nothing if flag already set */
53 if (readl(&rtc_regs->hw_rtc_persistent0) & RTC_PERSISTENT0_AUTO_RESTART)
56 while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
59 setbits_le32(&rtc_regs->hw_rtc_persistent0,
60 RTC_PERSISTENT0_AUTO_RESTART);
61 writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_set);
62 writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_clr);
63 while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
65 while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_STALE_REGS_MASK)
69 static void mxs_power_set_linreg(void)
71 struct mxs_power_regs *power_regs =
72 (struct mxs_power_regs *)MXS_POWER_BASE;
74 /* Set linear regulator 25mV below switching converter */
75 clrsetbits_le32(&power_regs->hw_power_vdddctrl,
76 POWER_VDDDCTRL_LINREG_OFFSET_MASK,
77 POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
79 clrsetbits_le32(&power_regs->hw_power_vddactrl,
80 POWER_VDDACTRL_LINREG_OFFSET_MASK,
81 POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW);
83 clrsetbits_le32(&power_regs->hw_power_vddioctrl,
84 POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
85 POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
88 static int mxs_get_batt_volt(void)
90 struct mxs_power_regs *power_regs =
91 (struct mxs_power_regs *)MXS_POWER_BASE;
92 uint32_t volt = readl(&power_regs->hw_power_battmonitor);
93 volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
94 volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
99 static int mxs_is_batt_ready(void)
101 return (mxs_get_batt_volt() >= 3600);
104 static int mxs_is_batt_good(void)
106 struct mxs_power_regs *power_regs =
107 (struct mxs_power_regs *)MXS_POWER_BASE;
108 uint32_t volt = mxs_get_batt_volt();
110 if ((volt >= 2400) && (volt <= 4300))
113 clrsetbits_le32(&power_regs->hw_power_5vctrl,
114 POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
115 0x3 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
116 writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
117 &power_regs->hw_power_5vctrl_clr);
119 clrsetbits_le32(&power_regs->hw_power_charge,
120 POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
121 POWER_CHARGE_STOP_ILIMIT_10MA | 0x3);
123 writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_clr);
124 writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
125 &power_regs->hw_power_5vctrl_clr);
129 volt = mxs_get_batt_volt();
137 writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
138 &power_regs->hw_power_charge_clr);
139 writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
144 static void mxs_power_setup_5v_detect(void)
146 struct mxs_power_regs *power_regs =
147 (struct mxs_power_regs *)MXS_POWER_BASE;
149 /* Start 5V detection */
150 clrsetbits_le32(&power_regs->hw_power_5vctrl,
151 POWER_5VCTRL_VBUSVALID_TRSH_MASK,
152 POWER_5VCTRL_VBUSVALID_TRSH_4V4 |
153 POWER_5VCTRL_PWRUP_VBUS_CMPS);
156 static void mxs_src_power_init(void)
158 struct mxs_power_regs *power_regs =
159 (struct mxs_power_regs *)MXS_POWER_BASE;
161 /* Improve efficieny and reduce transient ripple */
162 writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST |
163 POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set);
165 clrsetbits_le32(&power_regs->hw_power_dclimits,
166 POWER_DCLIMITS_POSLIMIT_BUCK_MASK,
167 0x30 << POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET);
169 setbits_le32(&power_regs->hw_power_battmonitor,
170 POWER_BATTMONITOR_EN_BATADJ);
172 /* Increase the RCSCALE level for quick DCDC response to dynamic load */
173 clrsetbits_le32(&power_regs->hw_power_loopctrl,
174 POWER_LOOPCTRL_EN_RCSCALE_MASK,
175 POWER_LOOPCTRL_RCSCALE_THRESH |
176 POWER_LOOPCTRL_EN_RCSCALE_8X);
178 clrsetbits_le32(&power_regs->hw_power_minpwr,
179 POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
181 /* 5V to battery handoff ... FIXME */
182 setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
184 clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
187 static void mxs_power_init_4p2_params(void)
189 struct mxs_power_regs *power_regs =
190 (struct mxs_power_regs *)MXS_POWER_BASE;
192 /* Setup 4P2 parameters */
193 clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
194 POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK,
195 POWER_DCDC4P2_TRG_4V2 | (31 << POWER_DCDC4P2_CMPTRIP_OFFSET));
197 clrsetbits_le32(&power_regs->hw_power_5vctrl,
198 POWER_5VCTRL_HEADROOM_ADJ_MASK,
199 0x4 << POWER_5VCTRL_HEADROOM_ADJ_OFFSET);
201 clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
202 POWER_DCDC4P2_DROPOUT_CTRL_MASK,
203 POWER_DCDC4P2_DROPOUT_CTRL_100MV |
204 POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL);
206 clrsetbits_le32(&power_regs->hw_power_5vctrl,
207 POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
208 0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
211 static void mxs_enable_4p2_dcdc_input(int xfer)
213 struct mxs_power_regs *power_regs =
214 (struct mxs_power_regs *)MXS_POWER_BASE;
215 uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo;
216 uint32_t prev_5v_brnout, prev_5v_droop;
218 prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) &
219 POWER_5VCTRL_PWDN_5VBRNOUT;
220 prev_5v_droop = readl(&power_regs->hw_power_ctrl) &
221 POWER_CTRL_ENIRQ_VDD5V_DROOP;
223 clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
224 writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
225 &power_regs->hw_power_reset);
227 clrbits_le32(&power_regs->hw_power_ctrl, POWER_CTRL_ENIRQ_VDD5V_DROOP);
229 if (xfer && (readl(&power_regs->hw_power_5vctrl) &
230 POWER_5VCTRL_ENABLE_DCDC)) {
235 * Recording orignal values that will be modified temporarlily
236 * to handle a chip bug. See chip errata for CQ ENGR00115837
238 tmp = readl(&power_regs->hw_power_5vctrl);
239 vbus_thresh = tmp & POWER_5VCTRL_VBUSVALID_TRSH_MASK;
240 vbus_5vdetect = tmp & POWER_5VCTRL_VBUSVALID_5VDETECT;
242 pwd_bo = readl(&power_regs->hw_power_minpwr) & POWER_MINPWR_PWD_BO;
245 * Disable mechanisms that get erroneously tripped by when setting
246 * the DCDC4P2 EN_DCDC
248 clrbits_le32(&power_regs->hw_power_5vctrl,
249 POWER_5VCTRL_VBUSVALID_5VDETECT |
250 POWER_5VCTRL_VBUSVALID_TRSH_MASK);
252 writel(POWER_MINPWR_PWD_BO, &power_regs->hw_power_minpwr_set);
255 setbits_le32(&power_regs->hw_power_5vctrl,
256 POWER_5VCTRL_DCDC_XFER);
258 clrbits_le32(&power_regs->hw_power_5vctrl,
259 POWER_5VCTRL_DCDC_XFER);
261 setbits_le32(&power_regs->hw_power_5vctrl,
262 POWER_5VCTRL_ENABLE_DCDC);
264 setbits_le32(&power_regs->hw_power_dcdc4p2,
265 POWER_DCDC4P2_ENABLE_DCDC);
270 clrsetbits_le32(&power_regs->hw_power_5vctrl,
271 POWER_5VCTRL_VBUSVALID_TRSH_MASK, vbus_thresh);
274 writel(vbus_5vdetect, &power_regs->hw_power_5vctrl_set);
277 clrbits_le32(&power_regs->hw_power_minpwr, POWER_MINPWR_PWD_BO);
279 while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ)
280 writel(POWER_CTRL_VBUS_VALID_IRQ,
281 &power_regs->hw_power_ctrl_clr);
283 if (prev_5v_brnout) {
284 writel(POWER_5VCTRL_PWDN_5VBRNOUT,
285 &power_regs->hw_power_5vctrl_set);
286 writel(POWER_RESET_UNLOCK_KEY,
287 &power_regs->hw_power_reset);
289 writel(POWER_5VCTRL_PWDN_5VBRNOUT,
290 &power_regs->hw_power_5vctrl_clr);
291 writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
292 &power_regs->hw_power_reset);
295 while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VDD5V_DROOP_IRQ)
296 writel(POWER_CTRL_VDD5V_DROOP_IRQ,
297 &power_regs->hw_power_ctrl_clr);
300 clrbits_le32(&power_regs->hw_power_ctrl,
301 POWER_CTRL_ENIRQ_VDD5V_DROOP);
303 setbits_le32(&power_regs->hw_power_ctrl,
304 POWER_CTRL_ENIRQ_VDD5V_DROOP);
307 static void mxs_power_init_4p2_regulator(void)
309 struct mxs_power_regs *power_regs =
310 (struct mxs_power_regs *)MXS_POWER_BASE;
313 setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2);
315 writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set);
317 writel(POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
318 &power_regs->hw_power_5vctrl_clr);
319 clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_TRG_MASK);
321 /* Power up the 4p2 rail and logic/control */
322 writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
323 &power_regs->hw_power_5vctrl_clr);
326 * Start charging up the 4p2 capacitor. We ramp of this charge
327 * gradually to avoid large inrush current from the 5V cable which can
328 * cause transients/problems
330 mxs_enable_4p2_dcdc_input(0);
332 if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
334 * If we arrived here, we were unable to recover from mx23 chip
335 * errata 5837. 4P2 is disabled and sufficient battery power is
336 * not present. Exiting to not enable DCDC power during 5V
339 clrbits_le32(&power_regs->hw_power_dcdc4p2,
340 POWER_DCDC4P2_ENABLE_DCDC);
341 writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
342 &power_regs->hw_power_5vctrl_set);
347 * Here we set the 4p2 brownout level to something very close to 4.2V.
348 * We then check the brownout status. If the brownout status is false,
349 * the voltage is already close to the target voltage of 4.2V so we
350 * can go ahead and set the 4P2 current limit to our max target limit.
351 * If the brownout status is true, we need to ramp us the current limit
352 * so that we don't cause large inrush current issues. We step up the
353 * current limit until the brownout status is false or until we've
354 * reached our maximum defined 4p2 current limit.
356 clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
357 POWER_DCDC4P2_BO_MASK,
358 22 << POWER_DCDC4P2_BO_OFFSET); /* 4.15V */
360 if (!(readl(&power_regs->hw_power_sts) & POWER_STS_DCDC_4P2_BO)) {
361 setbits_le32(&power_regs->hw_power_5vctrl,
362 0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
364 tmp = (readl(&power_regs->hw_power_5vctrl) &
365 POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK) >>
366 POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
368 if (!(readl(&power_regs->hw_power_sts) &
369 POWER_STS_DCDC_4P2_BO)) {
370 tmp = readl(&power_regs->hw_power_5vctrl);
371 tmp |= POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
373 writel(tmp, &power_regs->hw_power_5vctrl);
377 tmp2 = readl(&power_regs->hw_power_5vctrl);
378 tmp2 &= ~POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
380 POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
381 writel(tmp2, &power_regs->hw_power_5vctrl);
387 clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
388 writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
391 static void mxs_power_init_dcdc_4p2_source(void)
393 struct mxs_power_regs *power_regs =
394 (struct mxs_power_regs *)MXS_POWER_BASE;
396 if (!(readl(&power_regs->hw_power_dcdc4p2) &
397 POWER_DCDC4P2_ENABLE_DCDC)) {
401 mxs_enable_4p2_dcdc_input(1);
403 if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
404 clrbits_le32(&power_regs->hw_power_dcdc4p2,
405 POWER_DCDC4P2_ENABLE_DCDC);
406 writel(POWER_5VCTRL_ENABLE_DCDC,
407 &power_regs->hw_power_5vctrl_clr);
408 writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
409 &power_regs->hw_power_5vctrl_set);
413 static void mxs_power_enable_4p2(void)
415 struct mxs_power_regs *power_regs =
416 (struct mxs_power_regs *)MXS_POWER_BASE;
417 uint32_t vdddctrl, vddactrl, vddioctrl;
420 vdddctrl = readl(&power_regs->hw_power_vdddctrl);
421 vddactrl = readl(&power_regs->hw_power_vddactrl);
422 vddioctrl = readl(&power_regs->hw_power_vddioctrl);
424 setbits_le32(&power_regs->hw_power_vdddctrl,
425 POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
426 POWER_VDDDCTRL_PWDN_BRNOUT);
428 setbits_le32(&power_regs->hw_power_vddactrl,
429 POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG |
430 POWER_VDDACTRL_PWDN_BRNOUT);
432 setbits_le32(&power_regs->hw_power_vddioctrl,
433 POWER_VDDIOCTRL_DISABLE_FET | POWER_VDDIOCTRL_PWDN_BRNOUT);
435 mxs_power_init_4p2_params();
436 mxs_power_init_4p2_regulator();
438 /* Shutdown battery (none present) */
439 if (!mxs_is_batt_ready()) {
440 clrbits_le32(&power_regs->hw_power_dcdc4p2,
441 POWER_DCDC4P2_BO_MASK);
442 writel(POWER_CTRL_DCDC4P2_BO_IRQ,
443 &power_regs->hw_power_ctrl_clr);
444 writel(POWER_CTRL_ENIRQ_DCDC4P2_BO,
445 &power_regs->hw_power_ctrl_clr);
448 mxs_power_init_dcdc_4p2_source();
450 writel(vdddctrl, &power_regs->hw_power_vdddctrl);
452 writel(vddactrl, &power_regs->hw_power_vddactrl);
454 writel(vddioctrl, &power_regs->hw_power_vddioctrl);
457 * Check if FET is enabled on either powerout and if so,
461 tmp |= !(readl(&power_regs->hw_power_vdddctrl) &
462 POWER_VDDDCTRL_DISABLE_FET);
463 tmp |= !(readl(&power_regs->hw_power_vddactrl) &
464 POWER_VDDACTRL_DISABLE_FET);
465 tmp |= !(readl(&power_regs->hw_power_vddioctrl) &
466 POWER_VDDIOCTRL_DISABLE_FET);
468 writel(POWER_CHARGE_ENABLE_LOAD,
469 &power_regs->hw_power_charge_clr);
472 static void mxs_boot_valid_5v(void)
474 struct mxs_power_regs *power_regs =
475 (struct mxs_power_regs *)MXS_POWER_BASE;
478 * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V
479 * disconnect event. FIXME
481 writel(POWER_5VCTRL_VBUSVALID_5VDETECT,
482 &power_regs->hw_power_5vctrl_set);
484 /* Configure polarity to check for 5V disconnection. */
485 writel(POWER_CTRL_POLARITY_VBUSVALID |
486 POWER_CTRL_POLARITY_VDD5V_GT_VDDIO,
487 &power_regs->hw_power_ctrl_clr);
489 writel(POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_VDD5V_GT_VDDIO_IRQ,
490 &power_regs->hw_power_ctrl_clr);
492 mxs_power_enable_4p2();
495 static void mxs_powerdown(void)
497 struct mxs_power_regs *power_regs =
498 (struct mxs_power_regs *)MXS_POWER_BASE;
499 writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset);
500 writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
501 &power_regs->hw_power_reset);
504 static void mxs_batt_boot(void)
506 struct mxs_power_regs *power_regs =
507 (struct mxs_power_regs *)MXS_POWER_BASE;
509 clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
510 clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_ENABLE_DCDC);
512 clrbits_le32(&power_regs->hw_power_dcdc4p2,
513 POWER_DCDC4P2_ENABLE_DCDC | POWER_DCDC4P2_ENABLE_4P2);
514 writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_clr);
516 /* 5V to battery handoff. */
517 setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
519 clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
521 writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, &power_regs->hw_power_ctrl_clr);
523 clrsetbits_le32(&power_regs->hw_power_minpwr,
524 POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
526 mxs_power_set_linreg();
528 clrbits_le32(&power_regs->hw_power_vdddctrl,
529 POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG);
531 clrbits_le32(&power_regs->hw_power_vddactrl,
532 POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG);
534 clrbits_le32(&power_regs->hw_power_vddioctrl,
535 POWER_VDDIOCTRL_DISABLE_FET);
537 setbits_le32(&power_regs->hw_power_5vctrl,
538 POWER_5VCTRL_PWD_CHARGE_4P2_MASK);
540 setbits_le32(&power_regs->hw_power_5vctrl,
541 POWER_5VCTRL_ENABLE_DCDC);
543 clrsetbits_le32(&power_regs->hw_power_5vctrl,
544 POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
545 0x8 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
548 static void mxs_handle_5v_conflict(void)
550 struct mxs_power_regs *power_regs =
551 (struct mxs_power_regs *)MXS_POWER_BASE;
554 setbits_le32(&power_regs->hw_power_vddioctrl,
555 POWER_VDDIOCTRL_BO_OFFSET_MASK);
558 tmp = readl(&power_regs->hw_power_sts);
560 if (tmp & POWER_STS_VDDIO_BO) {
562 * VDDIO has a brownout, then the VDD5V_GT_VDDIO becomes
569 if (tmp & POWER_STS_VDD5V_GT_VDDIO) {
577 if (tmp & POWER_STS_PSWITCH_MASK) {
584 static void mxs_5v_boot(void)
586 struct mxs_power_regs *power_regs =
587 (struct mxs_power_regs *)MXS_POWER_BASE;
590 * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID,
591 * but their implementation always returns 1 so we omit it here.
593 if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
599 if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
604 mxs_handle_5v_conflict();
607 static void mxs_init_batt_bo(void)
609 struct mxs_power_regs *power_regs =
610 (struct mxs_power_regs *)MXS_POWER_BASE;
613 clrsetbits_le32(&power_regs->hw_power_battmonitor,
614 POWER_BATTMONITOR_BRWNOUT_LVL_MASK,
615 15 << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
617 writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr);
618 writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
621 static void mxs_switch_vddd_to_dcdc_source(void)
623 struct mxs_power_regs *power_regs =
624 (struct mxs_power_regs *)MXS_POWER_BASE;
626 clrsetbits_le32(&power_regs->hw_power_vdddctrl,
627 POWER_VDDDCTRL_LINREG_OFFSET_MASK,
628 POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
630 clrbits_le32(&power_regs->hw_power_vdddctrl,
631 POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
632 POWER_VDDDCTRL_DISABLE_STEPPING);
635 static void mxs_power_configure_power_source(void)
637 int batt_ready, batt_good;
638 struct mxs_power_regs *power_regs =
639 (struct mxs_power_regs *)MXS_POWER_BASE;
640 struct mxs_lradc_regs *lradc_regs =
641 (struct mxs_lradc_regs *)MXS_LRADC_BASE;
643 mxs_src_power_init();
645 if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
646 batt_ready = mxs_is_batt_ready();
648 /* 5V source detected, good battery detected. */
651 batt_good = mxs_is_batt_good();
653 /* 5V source detected, bad battery detected. */
654 writel(LRADC_CONVERSION_AUTOMATIC,
655 &lradc_regs->hw_lradc_conversion_clr);
656 clrbits_le32(&power_regs->hw_power_battmonitor,
657 POWER_BATTMONITOR_BATT_VAL_MASK);
662 /* 5V not detected, booting from battery. */
666 mxs_power_clock2pll();
670 mxs_switch_vddd_to_dcdc_source();
673 /* Fire up the VDDMEM LinReg now that we're all set. */
674 writel(POWER_VDDMEMCTRL_ENABLE_LINREG | POWER_VDDMEMCTRL_ENABLE_ILIMIT,
675 &power_regs->hw_power_vddmemctrl);
679 static void mxs_enable_output_rail_protection(void)
681 struct mxs_power_regs *power_regs =
682 (struct mxs_power_regs *)MXS_POWER_BASE;
684 writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
685 POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr);
687 setbits_le32(&power_regs->hw_power_vdddctrl,
688 POWER_VDDDCTRL_PWDN_BRNOUT);
690 setbits_le32(&power_regs->hw_power_vddactrl,
691 POWER_VDDACTRL_PWDN_BRNOUT);
693 setbits_le32(&power_regs->hw_power_vddioctrl,
694 POWER_VDDIOCTRL_PWDN_BRNOUT);
697 static int mxs_get_vddio_power_source_off(void)
699 struct mxs_power_regs *power_regs =
700 (struct mxs_power_regs *)MXS_POWER_BASE;
703 if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
704 tmp = readl(&power_regs->hw_power_vddioctrl);
705 if (tmp & POWER_VDDIOCTRL_DISABLE_FET) {
706 if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
707 POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS) {
712 if (!(readl(&power_regs->hw_power_5vctrl) &
713 POWER_5VCTRL_ENABLE_DCDC)) {
714 if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
715 POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS) {
725 static int mxs_get_vddd_power_source_off(void)
727 struct mxs_power_regs *power_regs =
728 (struct mxs_power_regs *)MXS_POWER_BASE;
731 tmp = readl(&power_regs->hw_power_vdddctrl);
732 if (tmp & POWER_VDDDCTRL_DISABLE_FET) {
733 if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
734 POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
739 if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
740 if (!(readl(&power_regs->hw_power_5vctrl) &
741 POWER_5VCTRL_ENABLE_DCDC)) {
746 if (!(tmp & POWER_VDDDCTRL_ENABLE_LINREG)) {
747 if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
748 POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW) {
756 struct mxs_vddx_cfg {
760 int (*powered_by_linreg)(void);
764 uint32_t bo_offset_mask;
765 uint32_t bo_offset_offset;
768 static const struct mxs_vddx_cfg mxs_vddio_cfg = {
769 .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
771 #if defined(CONFIG_MX23)
777 .powered_by_linreg = mxs_get_vddio_power_source_off,
778 .trg_mask = POWER_VDDIOCTRL_TRG_MASK,
779 .bo_irq = POWER_CTRL_VDDIO_BO_IRQ,
780 .bo_enirq = POWER_CTRL_ENIRQ_VDDIO_BO,
781 .bo_offset_mask = POWER_VDDIOCTRL_BO_OFFSET_MASK,
782 .bo_offset_offset = POWER_VDDIOCTRL_BO_OFFSET_OFFSET,
785 static const struct mxs_vddx_cfg mxs_vddd_cfg = {
786 .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
790 .powered_by_linreg = mxs_get_vddd_power_source_off,
791 .trg_mask = POWER_VDDDCTRL_TRG_MASK,
792 .bo_irq = POWER_CTRL_VDDD_BO_IRQ,
793 .bo_enirq = POWER_CTRL_ENIRQ_VDDD_BO,
794 .bo_offset_mask = POWER_VDDDCTRL_BO_OFFSET_MASK,
795 .bo_offset_offset = POWER_VDDDCTRL_BO_OFFSET_OFFSET,
799 static const struct mxs_vddx_cfg mxs_vddmem_cfg = {
800 .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
801 hw_power_vddmemctrl),
804 .powered_by_linreg = NULL,
805 .trg_mask = POWER_VDDMEMCTRL_TRG_MASK,
809 .bo_offset_offset = 0,
813 static void mxs_power_set_vddx(const struct mxs_vddx_cfg *cfg,
814 uint32_t new_target, uint32_t new_brownout)
816 struct mxs_power_regs *power_regs =
817 (struct mxs_power_regs *)MXS_POWER_BASE;
818 uint32_t cur_target, diff, bo_int = 0;
819 uint32_t powered_by_linreg = 0;
822 new_brownout = DIV_ROUND(new_target - new_brownout, cfg->step_mV);
824 cur_target = readl(cfg->reg);
825 cur_target &= cfg->trg_mask;
826 cur_target *= cfg->step_mV;
827 cur_target += cfg->lowest_mV;
829 adjust_up = new_target > cur_target;
830 if (cfg->powered_by_linreg)
831 powered_by_linreg = cfg->powered_by_linreg();
833 if (adjust_up && cfg->bo_irq) {
834 if (powered_by_linreg) {
835 bo_int = readl(cfg->reg);
836 clrbits_le32(cfg->reg, cfg->bo_enirq);
838 setbits_le32(cfg->reg, cfg->bo_offset_mask);
842 if (abs(new_target - cur_target) > 100) {
844 diff = cur_target + 100;
846 diff = cur_target - 100;
851 diff -= cfg->lowest_mV;
852 diff /= cfg->step_mV;
854 clrsetbits_le32(cfg->reg, cfg->trg_mask, diff);
856 if (powered_by_linreg ||
857 (readl(&power_regs->hw_power_sts) &
858 POWER_STS_VDD5V_GT_VDDIO))
862 tmp = readl(&power_regs->hw_power_sts);
863 if (tmp & POWER_STS_DC_OK)
868 cur_target = readl(cfg->reg);
869 cur_target &= cfg->trg_mask;
870 cur_target *= cfg->step_mV;
871 cur_target += cfg->lowest_mV;
872 } while (new_target > cur_target);
875 if (adjust_up && powered_by_linreg) {
876 writel(cfg->bo_irq, &power_regs->hw_power_ctrl_clr);
877 if (bo_int & cfg->bo_enirq)
878 setbits_le32(cfg->reg, cfg->bo_enirq);
881 clrsetbits_le32(cfg->reg, cfg->bo_offset_mask,
882 new_brownout << cfg->bo_offset_offset);
886 static void mxs_setup_batt_detect(void)
889 mxs_lradc_enable_batt_measurement();
893 static void mxs_ungate_power(void)
896 struct mxs_power_regs *power_regs =
897 (struct mxs_power_regs *)MXS_POWER_BASE;
899 writel(POWER_CTRL_CLKGATE, &power_regs->hw_power_ctrl_clr);
903 void mxs_power_init(void)
905 struct mxs_power_regs *power_regs =
906 (struct mxs_power_regs *)MXS_POWER_BASE;
910 mxs_power_clock2xtal();
911 mxs_power_set_auto_restart();
912 mxs_power_set_linreg();
913 mxs_power_setup_5v_detect();
915 mxs_setup_batt_detect();
917 mxs_power_configure_power_source();
918 mxs_enable_output_rail_protection();
920 mxs_power_set_vddx(&mxs_vddio_cfg, 3300, 3150);
921 mxs_power_set_vddx(&mxs_vddd_cfg, 1500, 1000);
923 mxs_power_set_vddx(&mxs_vddmem_cfg, 2500, 1700);
925 writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
926 POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
927 POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ |
928 POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
930 writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set);
935 #ifdef CONFIG_SPL_MXS_PSWITCH_WAIT
936 void mxs_power_wait_pswitch(void)
938 struct mxs_power_regs *power_regs =
939 (struct mxs_power_regs *)MXS_POWER_BASE;
941 while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK))