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
))