1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
23a0398d7SOtavio Salvador /*
33a0398d7SOtavio Salvador * Freescale i.MX28 Boot PMIC init
43a0398d7SOtavio Salvador *
53a0398d7SOtavio Salvador * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
63a0398d7SOtavio Salvador * on behalf of DENX Software Engineering GmbH
73a0398d7SOtavio Salvador */
83a0398d7SOtavio Salvador
93a0398d7SOtavio Salvador #include <common.h>
103a0398d7SOtavio Salvador #include <config.h>
113a0398d7SOtavio Salvador #include <asm/io.h>
123a0398d7SOtavio Salvador #include <asm/arch/imx-regs.h>
133a0398d7SOtavio Salvador
141e0cf5c3SOtavio Salvador #include "mxs_init.h"
153a0398d7SOtavio Salvador
167a086037SGraeme Russ #ifdef CONFIG_SYS_MXS_VDD5V_ONLY
177a086037SGraeme Russ #define DCDC4P2_DROPOUT_CONFIG POWER_DCDC4P2_DROPOUT_CTRL_100MV | \
187a086037SGraeme Russ POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2
197a086037SGraeme Russ #else
207a086037SGraeme Russ #define DCDC4P2_DROPOUT_CONFIG POWER_DCDC4P2_DROPOUT_CTRL_100MV | \
217a086037SGraeme Russ POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL
227a086037SGraeme Russ #endif
23d4c9135cSMarek Vasut /**
24d4c9135cSMarek Vasut * mxs_power_clock2xtal() - Switch CPU core clock source to 24MHz XTAL
25d4c9135cSMarek Vasut *
26d4c9135cSMarek Vasut * This function switches the CPU core clock from PLL to 24MHz XTAL
27d4c9135cSMarek Vasut * oscilator. This is necessary if the PLL is being reconfigured to
28d4c9135cSMarek Vasut * prevent crash of the CPU core.
29d4c9135cSMarek Vasut */
mxs_power_clock2xtal(void)30a918a53cSMarek Vasut static void mxs_power_clock2xtal(void)
313a0398d7SOtavio Salvador {
329c471142SOtavio Salvador struct mxs_clkctrl_regs *clkctrl_regs =
339c471142SOtavio Salvador (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
343a0398d7SOtavio Salvador
35950eaf62SGraeme Russ debug("SPL: Switching CPU clock to 24MHz XTAL\n");
36950eaf62SGraeme Russ
373a0398d7SOtavio Salvador /* Set XTAL as CPU reference clock */
383a0398d7SOtavio Salvador writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
393a0398d7SOtavio Salvador &clkctrl_regs->hw_clkctrl_clkseq_set);
403a0398d7SOtavio Salvador }
413a0398d7SOtavio Salvador
42d4c9135cSMarek Vasut /**
43d4c9135cSMarek Vasut * mxs_power_clock2pll() - Switch CPU core clock source to PLL
44d4c9135cSMarek Vasut *
45d4c9135cSMarek Vasut * This function switches the CPU core clock from 24MHz XTAL oscilator
46d4c9135cSMarek Vasut * to PLL. This can only be called once the PLL has re-locked and once
47d4c9135cSMarek Vasut * the PLL is stable after reconfiguration.
48d4c9135cSMarek Vasut */
mxs_power_clock2pll(void)49a918a53cSMarek Vasut static void mxs_power_clock2pll(void)
503a0398d7SOtavio Salvador {
519c471142SOtavio Salvador struct mxs_clkctrl_regs *clkctrl_regs =
529c471142SOtavio Salvador (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
533a0398d7SOtavio Salvador
54950eaf62SGraeme Russ debug("SPL: Switching CPU core clock source to PLL\n");
55950eaf62SGraeme Russ
56950eaf62SGraeme Russ /*
57950eaf62SGraeme Russ * TODO: Are we really? It looks like we turn on PLL0, but we then
58950eaf62SGraeme Russ * set the CLKCTRL_CLKSEQ_BYPASS_CPU bit of the (which was already
59950eaf62SGraeme Russ * set by mxs_power_clock2xtal()). Clearing this bit here seems to
60950eaf62SGraeme Russ * introduce some instability (causing the CPU core to hang). Maybe
61950eaf62SGraeme Russ * we aren't giving PLL0 enough time to stabilise?
62950eaf62SGraeme Russ */
633a0398d7SOtavio Salvador setbits_le32(&clkctrl_regs->hw_clkctrl_pll0ctrl0,
643a0398d7SOtavio Salvador CLKCTRL_PLL0CTRL0_POWER);
653a0398d7SOtavio Salvador early_delay(100);
66950eaf62SGraeme Russ
67950eaf62SGraeme Russ /*
68950eaf62SGraeme Russ * TODO: Should the PLL0 FORCE_LOCK bit be set here followed be a
69950eaf62SGraeme Russ * wait on the PLL0 LOCK bit?
70950eaf62SGraeme Russ */
713a0398d7SOtavio Salvador setbits_le32(&clkctrl_regs->hw_clkctrl_clkseq,
723a0398d7SOtavio Salvador CLKCTRL_CLKSEQ_BYPASS_CPU);
733a0398d7SOtavio Salvador }
743a0398d7SOtavio Salvador
75d4c9135cSMarek Vasut /**
76d4c9135cSMarek Vasut * mxs_power_set_auto_restart() - Set the auto-restart bit
77d4c9135cSMarek Vasut *
78d4c9135cSMarek Vasut * This function ungates the RTC block and sets the AUTO_RESTART
79d4c9135cSMarek Vasut * bit to work around a design bug on MX28EVK Rev. A .
80d4c9135cSMarek Vasut */
81d4c9135cSMarek Vasut
mxs_power_set_auto_restart(void)826f6059e0SHector Palacios static void mxs_power_set_auto_restart(void)
833a0398d7SOtavio Salvador {
849c471142SOtavio Salvador struct mxs_rtc_regs *rtc_regs =
859c471142SOtavio Salvador (struct mxs_rtc_regs *)MXS_RTC_BASE;
863a0398d7SOtavio Salvador
87950eaf62SGraeme Russ debug("SPL: Setting auto-restart bit\n");
88950eaf62SGraeme Russ
893a0398d7SOtavio Salvador writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr);
903a0398d7SOtavio Salvador while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST)
913a0398d7SOtavio Salvador ;
923a0398d7SOtavio Salvador
933a0398d7SOtavio Salvador writel(RTC_CTRL_CLKGATE, &rtc_regs->hw_rtc_ctrl_clr);
943a0398d7SOtavio Salvador while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE)
953a0398d7SOtavio Salvador ;
963a0398d7SOtavio Salvador
976f6059e0SHector Palacios /* Do nothing if flag already set */
983a0398d7SOtavio Salvador if (readl(&rtc_regs->hw_rtc_persistent0) & RTC_PERSISTENT0_AUTO_RESTART)
993a0398d7SOtavio Salvador return;
1003a0398d7SOtavio Salvador
1013a0398d7SOtavio Salvador while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
1023a0398d7SOtavio Salvador ;
1033a0398d7SOtavio Salvador
1043a0398d7SOtavio Salvador setbits_le32(&rtc_regs->hw_rtc_persistent0,
1053a0398d7SOtavio Salvador RTC_PERSISTENT0_AUTO_RESTART);
1063a0398d7SOtavio Salvador writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_set);
1073a0398d7SOtavio Salvador writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_clr);
1083a0398d7SOtavio Salvador while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
1093a0398d7SOtavio Salvador ;
1103a0398d7SOtavio Salvador while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_STALE_REGS_MASK)
1113a0398d7SOtavio Salvador ;
1123a0398d7SOtavio Salvador }
1133a0398d7SOtavio Salvador
114d4c9135cSMarek Vasut /**
115d4c9135cSMarek Vasut * mxs_power_set_linreg() - Set linear regulators 25mV below DC-DC converter
116d4c9135cSMarek Vasut *
117d4c9135cSMarek Vasut * This function configures the VDDIO, VDDA and VDDD linear regulators output
118d4c9135cSMarek Vasut * to be 25mV below the VDDIO, VDDA and VDDD output from the DC-DC switching
119d4c9135cSMarek Vasut * converter. This is the recommended setting for the case where we use both
120d4c9135cSMarek Vasut * linear regulators and DC-DC converter to power the VDDIO rail.
121d4c9135cSMarek Vasut */
mxs_power_set_linreg(void)122a918a53cSMarek Vasut static void mxs_power_set_linreg(void)
1233a0398d7SOtavio Salvador {
1249c471142SOtavio Salvador struct mxs_power_regs *power_regs =
1259c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
1263a0398d7SOtavio Salvador
1273a0398d7SOtavio Salvador /* Set linear regulator 25mV below switching converter */
128950eaf62SGraeme Russ debug("SPL: Setting VDDD 25mV below DC-DC converters\n");
1293a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_vdddctrl,
1303a0398d7SOtavio Salvador POWER_VDDDCTRL_LINREG_OFFSET_MASK,
1313a0398d7SOtavio Salvador POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
1323a0398d7SOtavio Salvador
133950eaf62SGraeme Russ debug("SPL: Setting VDDA 25mV below DC-DC converters\n");
1343a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_vddactrl,
1353a0398d7SOtavio Salvador POWER_VDDACTRL_LINREG_OFFSET_MASK,
1363a0398d7SOtavio Salvador POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW);
1373a0398d7SOtavio Salvador
138950eaf62SGraeme Russ debug("SPL: Setting VDDIO 25mV below DC-DC converters\n");
1393a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_vddioctrl,
1403a0398d7SOtavio Salvador POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
1413a0398d7SOtavio Salvador POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
1423a0398d7SOtavio Salvador }
1433a0398d7SOtavio Salvador
144d4c9135cSMarek Vasut /**
145d4c9135cSMarek Vasut * mxs_get_batt_volt() - Measure battery input voltage
146d4c9135cSMarek Vasut *
147d4c9135cSMarek Vasut * This function retrieves the battery input voltage and returns it.
148d4c9135cSMarek Vasut */
mxs_get_batt_volt(void)149a918a53cSMarek Vasut static int mxs_get_batt_volt(void)
1503a0398d7SOtavio Salvador {
1519c471142SOtavio Salvador struct mxs_power_regs *power_regs =
1529c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
1533a0398d7SOtavio Salvador uint32_t volt = readl(&power_regs->hw_power_battmonitor);
1543a0398d7SOtavio Salvador volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
1553a0398d7SOtavio Salvador volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
1563a0398d7SOtavio Salvador volt *= 8;
157950eaf62SGraeme Russ
158950eaf62SGraeme Russ debug("SPL: Battery Voltage = %dmV\n", volt);
1593a0398d7SOtavio Salvador return volt;
1603a0398d7SOtavio Salvador }
1613a0398d7SOtavio Salvador
162d4c9135cSMarek Vasut /**
163d4c9135cSMarek Vasut * mxs_is_batt_ready() - Test if the battery provides enough voltage to boot
164d4c9135cSMarek Vasut *
165d4c9135cSMarek Vasut * This function checks if the battery input voltage is higher than 3.6V and
166d4c9135cSMarek Vasut * therefore allows the system to successfully boot using this power source.
167d4c9135cSMarek Vasut */
mxs_is_batt_ready(void)168a918a53cSMarek Vasut static int mxs_is_batt_ready(void)
1693a0398d7SOtavio Salvador {
1701e0cf5c3SOtavio Salvador return (mxs_get_batt_volt() >= 3600);
1713a0398d7SOtavio Salvador }
1723a0398d7SOtavio Salvador
173d4c9135cSMarek Vasut /**
174d4c9135cSMarek Vasut * mxs_is_batt_good() - Test if battery is operational at all
175d4c9135cSMarek Vasut *
176d4c9135cSMarek Vasut * This function starts recharging the battery and tests if the input current
177d4c9135cSMarek Vasut * provided by the 5V input recharging the battery is also sufficient to power
178d4c9135cSMarek Vasut * the DC-DC converter.
179d4c9135cSMarek Vasut */
mxs_is_batt_good(void)180a918a53cSMarek Vasut static int mxs_is_batt_good(void)
1813a0398d7SOtavio Salvador {
1829c471142SOtavio Salvador struct mxs_power_regs *power_regs =
1839c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
1841e0cf5c3SOtavio Salvador uint32_t volt = mxs_get_batt_volt();
1853a0398d7SOtavio Salvador
186950eaf62SGraeme Russ if ((volt >= 2400) && (volt <= 4300)) {
187950eaf62SGraeme Russ debug("SPL: Battery is good\n");
1883a0398d7SOtavio Salvador return 1;
189950eaf62SGraeme Russ }
1903a0398d7SOtavio Salvador
1913a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_5vctrl,
1923a0398d7SOtavio Salvador POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
1933a0398d7SOtavio Salvador 0x3 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
1943a0398d7SOtavio Salvador writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
1953a0398d7SOtavio Salvador &power_regs->hw_power_5vctrl_clr);
1963a0398d7SOtavio Salvador
1973a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_charge,
1983a0398d7SOtavio Salvador POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
1993a0398d7SOtavio Salvador POWER_CHARGE_STOP_ILIMIT_10MA | 0x3);
2003a0398d7SOtavio Salvador
2013a0398d7SOtavio Salvador writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_clr);
2023a0398d7SOtavio Salvador writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
2033a0398d7SOtavio Salvador &power_regs->hw_power_5vctrl_clr);
2043a0398d7SOtavio Salvador
2053a0398d7SOtavio Salvador early_delay(500000);
2063a0398d7SOtavio Salvador
2071e0cf5c3SOtavio Salvador volt = mxs_get_batt_volt();
2083a0398d7SOtavio Salvador
209950eaf62SGraeme Russ if (volt >= 3500) {
210950eaf62SGraeme Russ debug("SPL: Battery Voltage too high\n");
2113a0398d7SOtavio Salvador return 0;
212950eaf62SGraeme Russ }
2133a0398d7SOtavio Salvador
214950eaf62SGraeme Russ if (volt >= 2400) {
215950eaf62SGraeme Russ debug("SPL: Battery is good\n");
2163a0398d7SOtavio Salvador return 1;
217950eaf62SGraeme Russ }
2183a0398d7SOtavio Salvador
2193a0398d7SOtavio Salvador writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
2203a0398d7SOtavio Salvador &power_regs->hw_power_charge_clr);
2213a0398d7SOtavio Salvador writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
2223a0398d7SOtavio Salvador
223950eaf62SGraeme Russ debug("SPL: Battery Voltage too low\n");
2243a0398d7SOtavio Salvador return 0;
2253a0398d7SOtavio Salvador }
2263a0398d7SOtavio Salvador
227d4c9135cSMarek Vasut /**
228d4c9135cSMarek Vasut * mxs_power_setup_5v_detect() - Start the 5V input detection comparator
229d4c9135cSMarek Vasut *
230d4c9135cSMarek Vasut * This function enables the 5V detection comparator and sets the 5V valid
231d4c9135cSMarek Vasut * threshold to 4.4V . We use 4.4V threshold here to make sure that even
232d4c9135cSMarek Vasut * under high load, the voltage drop on the 5V input won't be so critical
233d4c9135cSMarek Vasut * to cause undervolt on the 4P2 linear regulator supplying the DC-DC
234d4c9135cSMarek Vasut * converter and thus making the system crash.
235d4c9135cSMarek Vasut */
mxs_power_setup_5v_detect(void)236a918a53cSMarek Vasut static void mxs_power_setup_5v_detect(void)
2373a0398d7SOtavio Salvador {
2389c471142SOtavio Salvador struct mxs_power_regs *power_regs =
2399c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
2403a0398d7SOtavio Salvador
2413a0398d7SOtavio Salvador /* Start 5V detection */
242950eaf62SGraeme Russ debug("SPL: Starting 5V input detection comparator\n");
2433a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_5vctrl,
2443a0398d7SOtavio Salvador POWER_5VCTRL_VBUSVALID_TRSH_MASK,
2453a0398d7SOtavio Salvador POWER_5VCTRL_VBUSVALID_TRSH_4V4 |
2463a0398d7SOtavio Salvador POWER_5VCTRL_PWRUP_VBUS_CMPS);
2473a0398d7SOtavio Salvador }
2483a0398d7SOtavio Salvador
249d4c9135cSMarek Vasut /**
250fe21eaf9SMichael Heimpold * mxs_power_switch_dcdc_clocksource() - Switch PLL clock for DC-DC converters
251fe21eaf9SMichael Heimpold * @freqsel: One of the POWER_MISC_FREQSEL_xxx defines to select the clock
252fe21eaf9SMichael Heimpold *
253fe21eaf9SMichael Heimpold * This function configures and then enables an alternative PLL clock source
254fe21eaf9SMichael Heimpold * for the DC-DC converters.
255fe21eaf9SMichael Heimpold */
mxs_power_switch_dcdc_clocksource(uint32_t freqsel)256fe21eaf9SMichael Heimpold void mxs_power_switch_dcdc_clocksource(uint32_t freqsel)
257fe21eaf9SMichael Heimpold {
258fe21eaf9SMichael Heimpold struct mxs_power_regs *power_regs =
259fe21eaf9SMichael Heimpold (struct mxs_power_regs *)MXS_POWER_BASE;
260fe21eaf9SMichael Heimpold
261fe21eaf9SMichael Heimpold /* Select clocksource for DC-DC converters */
262fe21eaf9SMichael Heimpold clrsetbits_le32(&power_regs->hw_power_misc,
263fe21eaf9SMichael Heimpold POWER_MISC_FREQSEL_MASK,
264fe21eaf9SMichael Heimpold freqsel);
265fe21eaf9SMichael Heimpold setbits_le32(&power_regs->hw_power_misc,
266fe21eaf9SMichael Heimpold POWER_MISC_SEL_PLLCLK);
267fe21eaf9SMichael Heimpold }
268fe21eaf9SMichael Heimpold
269fe21eaf9SMichael Heimpold /**
270fe21eaf9SMichael Heimpold * mxs_power_setup_dcdc_clocksource() - Setup PLL clock source for DC-DC converters
271fe21eaf9SMichael Heimpold *
272fe21eaf9SMichael Heimpold * Normally, there is no need to switch DC-DC clocksource. This is the reason,
273fe21eaf9SMichael Heimpold * why this function is a stub and does nothing. However, boards can implement
274fe21eaf9SMichael Heimpold * this function when required and call mxs_power_switch_dcdc_clocksource() to
275fe21eaf9SMichael Heimpold * switch to an alternative clock source.
276fe21eaf9SMichael Heimpold */
mxs_power_setup_dcdc_clocksource(void)277fe21eaf9SMichael Heimpold __weak void mxs_power_setup_dcdc_clocksource(void)
278fe21eaf9SMichael Heimpold {
279fe21eaf9SMichael Heimpold debug("SPL: Using default DC-DC clocksource\n");
280fe21eaf9SMichael Heimpold }
281fe21eaf9SMichael Heimpold
282fe21eaf9SMichael Heimpold /**
283d4c9135cSMarek Vasut * mxs_src_power_init() - Preconfigure the power block
284d4c9135cSMarek Vasut *
285d4c9135cSMarek Vasut * This function configures reasonable values for the DC-DC control loop
286d4c9135cSMarek Vasut * and battery monitor.
287d4c9135cSMarek Vasut */
mxs_src_power_init(void)288a918a53cSMarek Vasut static void mxs_src_power_init(void)
2893a0398d7SOtavio Salvador {
2909c471142SOtavio Salvador struct mxs_power_regs *power_regs =
2919c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
2923a0398d7SOtavio Salvador
293950eaf62SGraeme Russ debug("SPL: Pre-Configuring power block\n");
294950eaf62SGraeme Russ
2953a0398d7SOtavio Salvador /* Improve efficieny and reduce transient ripple */
2963a0398d7SOtavio Salvador writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST |
2973a0398d7SOtavio Salvador POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set);
2983a0398d7SOtavio Salvador
2993a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_dclimits,
3003a0398d7SOtavio Salvador POWER_DCLIMITS_POSLIMIT_BUCK_MASK,
3013a0398d7SOtavio Salvador 0x30 << POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET);
3023a0398d7SOtavio Salvador
3033a0398d7SOtavio Salvador setbits_le32(&power_regs->hw_power_battmonitor,
3043a0398d7SOtavio Salvador POWER_BATTMONITOR_EN_BATADJ);
3053a0398d7SOtavio Salvador
3063a0398d7SOtavio Salvador /* Increase the RCSCALE level for quick DCDC response to dynamic load */
3073a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_loopctrl,
3083a0398d7SOtavio Salvador POWER_LOOPCTRL_EN_RCSCALE_MASK,
3093a0398d7SOtavio Salvador POWER_LOOPCTRL_RCSCALE_THRESH |
3103a0398d7SOtavio Salvador POWER_LOOPCTRL_EN_RCSCALE_8X);
3113a0398d7SOtavio Salvador
3123a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_minpwr,
3133a0398d7SOtavio Salvador POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
3143a0398d7SOtavio Salvador
3153a0398d7SOtavio Salvador /* 5V to battery handoff ... FIXME */
3163a0398d7SOtavio Salvador setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
3173a0398d7SOtavio Salvador early_delay(30);
3183a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
3193a0398d7SOtavio Salvador }
3203a0398d7SOtavio Salvador
321d4c9135cSMarek Vasut /**
322d4c9135cSMarek Vasut * mxs_power_init_4p2_params() - Configure the parameters of the 4P2 regulator
323d4c9135cSMarek Vasut *
324d4c9135cSMarek Vasut * This function configures the necessary parameters for the 4P2 linear
325d4c9135cSMarek Vasut * regulator to supply the DC-DC converter from 5V input.
326d4c9135cSMarek Vasut */
mxs_power_init_4p2_params(void)327a918a53cSMarek Vasut static void mxs_power_init_4p2_params(void)
3283a0398d7SOtavio Salvador {
3299c471142SOtavio Salvador struct mxs_power_regs *power_regs =
3309c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
3313a0398d7SOtavio Salvador
332950eaf62SGraeme Russ debug("SPL: Configuring common 4P2 regulator params\n");
333950eaf62SGraeme Russ
3343a0398d7SOtavio Salvador /* Setup 4P2 parameters */
3353a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
3363a0398d7SOtavio Salvador POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK,
3373a0398d7SOtavio Salvador POWER_DCDC4P2_TRG_4V2 | (31 << POWER_DCDC4P2_CMPTRIP_OFFSET));
3383a0398d7SOtavio Salvador
3393a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_5vctrl,
3403a0398d7SOtavio Salvador POWER_5VCTRL_HEADROOM_ADJ_MASK,
3413a0398d7SOtavio Salvador 0x4 << POWER_5VCTRL_HEADROOM_ADJ_OFFSET);
3423a0398d7SOtavio Salvador
3433a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
3443a0398d7SOtavio Salvador POWER_DCDC4P2_DROPOUT_CTRL_MASK,
3457a086037SGraeme Russ DCDC4P2_DROPOUT_CONFIG);
3463a0398d7SOtavio Salvador
3473a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_5vctrl,
3483a0398d7SOtavio Salvador POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
3493a0398d7SOtavio Salvador 0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
3503a0398d7SOtavio Salvador }
3513a0398d7SOtavio Salvador
352d4c9135cSMarek Vasut /**
353d4c9135cSMarek Vasut * mxs_enable_4p2_dcdc_input() - Enable or disable the DCDC input from 4P2
354d4c9135cSMarek Vasut * @xfer: Select if the input shall be enabled or disabled
355d4c9135cSMarek Vasut *
356d4c9135cSMarek Vasut * This function enables or disables the 4P2 input into the DC-DC converter.
357d4c9135cSMarek Vasut */
mxs_enable_4p2_dcdc_input(int xfer)358a918a53cSMarek Vasut static void mxs_enable_4p2_dcdc_input(int xfer)
3593a0398d7SOtavio Salvador {
3609c471142SOtavio Salvador struct mxs_power_regs *power_regs =
3619c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
3623a0398d7SOtavio Salvador uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo;
3633a0398d7SOtavio Salvador uint32_t prev_5v_brnout, prev_5v_droop;
3643a0398d7SOtavio Salvador
365950eaf62SGraeme Russ debug("SPL: %s 4P2 DC-DC Input\n", xfer ? "Enabling" : "Disabling");
366950eaf62SGraeme Russ
3677bbc5ff7SStefan Wahren if (xfer && (readl(&power_regs->hw_power_5vctrl) &
3687bbc5ff7SStefan Wahren POWER_5VCTRL_ENABLE_DCDC)) {
3697bbc5ff7SStefan Wahren return;
3707bbc5ff7SStefan Wahren }
3717bbc5ff7SStefan Wahren
3723a0398d7SOtavio Salvador prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) &
3733a0398d7SOtavio Salvador POWER_5VCTRL_PWDN_5VBRNOUT;
3743a0398d7SOtavio Salvador prev_5v_droop = readl(&power_regs->hw_power_ctrl) &
3753a0398d7SOtavio Salvador POWER_CTRL_ENIRQ_VDD5V_DROOP;
3763a0398d7SOtavio Salvador
3773a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
3783a0398d7SOtavio Salvador writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
3793a0398d7SOtavio Salvador &power_regs->hw_power_reset);
3803a0398d7SOtavio Salvador
3813a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_ctrl, POWER_CTRL_ENIRQ_VDD5V_DROOP);
3823a0398d7SOtavio Salvador
3833a0398d7SOtavio Salvador /*
3843a0398d7SOtavio Salvador * Recording orignal values that will be modified temporarlily
3853a0398d7SOtavio Salvador * to handle a chip bug. See chip errata for CQ ENGR00115837
3863a0398d7SOtavio Salvador */
3873a0398d7SOtavio Salvador tmp = readl(&power_regs->hw_power_5vctrl);
3883a0398d7SOtavio Salvador vbus_thresh = tmp & POWER_5VCTRL_VBUSVALID_TRSH_MASK;
3893a0398d7SOtavio Salvador vbus_5vdetect = tmp & POWER_5VCTRL_VBUSVALID_5VDETECT;
3903a0398d7SOtavio Salvador
3913a0398d7SOtavio Salvador pwd_bo = readl(&power_regs->hw_power_minpwr) & POWER_MINPWR_PWD_BO;
3923a0398d7SOtavio Salvador
3933a0398d7SOtavio Salvador /*
3943a0398d7SOtavio Salvador * Disable mechanisms that get erroneously tripped by when setting
3953a0398d7SOtavio Salvador * the DCDC4P2 EN_DCDC
3963a0398d7SOtavio Salvador */
3973a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_5vctrl,
3983a0398d7SOtavio Salvador POWER_5VCTRL_VBUSVALID_5VDETECT |
3993a0398d7SOtavio Salvador POWER_5VCTRL_VBUSVALID_TRSH_MASK);
4003a0398d7SOtavio Salvador
4013a0398d7SOtavio Salvador writel(POWER_MINPWR_PWD_BO, &power_regs->hw_power_minpwr_set);
4023a0398d7SOtavio Salvador
4033a0398d7SOtavio Salvador if (xfer) {
4043a0398d7SOtavio Salvador setbits_le32(&power_regs->hw_power_5vctrl,
4053a0398d7SOtavio Salvador POWER_5VCTRL_DCDC_XFER);
4063a0398d7SOtavio Salvador early_delay(20);
4073a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_5vctrl,
4083a0398d7SOtavio Salvador POWER_5VCTRL_DCDC_XFER);
4093a0398d7SOtavio Salvador
4103a0398d7SOtavio Salvador setbits_le32(&power_regs->hw_power_5vctrl,
4113a0398d7SOtavio Salvador POWER_5VCTRL_ENABLE_DCDC);
4123a0398d7SOtavio Salvador } else {
4133a0398d7SOtavio Salvador setbits_le32(&power_regs->hw_power_dcdc4p2,
4143a0398d7SOtavio Salvador POWER_DCDC4P2_ENABLE_DCDC);
4153a0398d7SOtavio Salvador }
4163a0398d7SOtavio Salvador
4173a0398d7SOtavio Salvador early_delay(25);
4183a0398d7SOtavio Salvador
4193a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_5vctrl,
4203a0398d7SOtavio Salvador POWER_5VCTRL_VBUSVALID_TRSH_MASK, vbus_thresh);
4213a0398d7SOtavio Salvador
4223a0398d7SOtavio Salvador if (vbus_5vdetect)
4233a0398d7SOtavio Salvador writel(vbus_5vdetect, &power_regs->hw_power_5vctrl_set);
4243a0398d7SOtavio Salvador
4253a0398d7SOtavio Salvador if (!pwd_bo)
4263a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_minpwr, POWER_MINPWR_PWD_BO);
4273a0398d7SOtavio Salvador
4283a0398d7SOtavio Salvador while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ)
4293a0398d7SOtavio Salvador writel(POWER_CTRL_VBUS_VALID_IRQ,
4303a0398d7SOtavio Salvador &power_regs->hw_power_ctrl_clr);
4313a0398d7SOtavio Salvador
4323a0398d7SOtavio Salvador if (prev_5v_brnout) {
4333a0398d7SOtavio Salvador writel(POWER_5VCTRL_PWDN_5VBRNOUT,
4343a0398d7SOtavio Salvador &power_regs->hw_power_5vctrl_set);
4353a0398d7SOtavio Salvador writel(POWER_RESET_UNLOCK_KEY,
4363a0398d7SOtavio Salvador &power_regs->hw_power_reset);
4373a0398d7SOtavio Salvador } else {
4383a0398d7SOtavio Salvador writel(POWER_5VCTRL_PWDN_5VBRNOUT,
4393a0398d7SOtavio Salvador &power_regs->hw_power_5vctrl_clr);
4403a0398d7SOtavio Salvador writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
4413a0398d7SOtavio Salvador &power_regs->hw_power_reset);
4423a0398d7SOtavio Salvador }
4433a0398d7SOtavio Salvador
4443a0398d7SOtavio Salvador while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VDD5V_DROOP_IRQ)
4453a0398d7SOtavio Salvador writel(POWER_CTRL_VDD5V_DROOP_IRQ,
4463a0398d7SOtavio Salvador &power_regs->hw_power_ctrl_clr);
4473a0398d7SOtavio Salvador
4483a0398d7SOtavio Salvador if (prev_5v_droop)
4493a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_ctrl,
4503a0398d7SOtavio Salvador POWER_CTRL_ENIRQ_VDD5V_DROOP);
4513a0398d7SOtavio Salvador else
4523a0398d7SOtavio Salvador setbits_le32(&power_regs->hw_power_ctrl,
4533a0398d7SOtavio Salvador POWER_CTRL_ENIRQ_VDD5V_DROOP);
4543a0398d7SOtavio Salvador }
4553a0398d7SOtavio Salvador
456d4c9135cSMarek Vasut /**
457d4c9135cSMarek Vasut * mxs_power_init_4p2_regulator() - Start the 4P2 regulator
458d4c9135cSMarek Vasut *
459d4c9135cSMarek Vasut * This function enables the 4P2 regulator and switches the DC-DC converter
460d4c9135cSMarek Vasut * to use the 4P2 input.
461d4c9135cSMarek Vasut */
mxs_power_init_4p2_regulator(void)462a918a53cSMarek Vasut static void mxs_power_init_4p2_regulator(void)
4633a0398d7SOtavio Salvador {
4649c471142SOtavio Salvador struct mxs_power_regs *power_regs =
4659c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
4663a0398d7SOtavio Salvador uint32_t tmp, tmp2;
4673a0398d7SOtavio Salvador
468950eaf62SGraeme Russ debug("SPL: Enabling 4P2 regulator\n");
469950eaf62SGraeme Russ
4703a0398d7SOtavio Salvador setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2);
4713a0398d7SOtavio Salvador
4723a0398d7SOtavio Salvador writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set);
4733a0398d7SOtavio Salvador
4743a0398d7SOtavio Salvador writel(POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
4753a0398d7SOtavio Salvador &power_regs->hw_power_5vctrl_clr);
4763a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_TRG_MASK);
4773a0398d7SOtavio Salvador
4783a0398d7SOtavio Salvador /* Power up the 4p2 rail and logic/control */
4793a0398d7SOtavio Salvador writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
4803a0398d7SOtavio Salvador &power_regs->hw_power_5vctrl_clr);
4813a0398d7SOtavio Salvador
4823a0398d7SOtavio Salvador /*
4833a0398d7SOtavio Salvador * Start charging up the 4p2 capacitor. We ramp of this charge
4843a0398d7SOtavio Salvador * gradually to avoid large inrush current from the 5V cable which can
4853a0398d7SOtavio Salvador * cause transients/problems
4863a0398d7SOtavio Salvador */
487950eaf62SGraeme Russ debug("SPL: Charging 4P2 capacitor\n");
4881e0cf5c3SOtavio Salvador mxs_enable_4p2_dcdc_input(0);
4893a0398d7SOtavio Salvador
4903a0398d7SOtavio Salvador if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
4913a0398d7SOtavio Salvador /*
4923a0398d7SOtavio Salvador * If we arrived here, we were unable to recover from mx23 chip
4933a0398d7SOtavio Salvador * errata 5837. 4P2 is disabled and sufficient battery power is
4943a0398d7SOtavio Salvador * not present. Exiting to not enable DCDC power during 5V
4953a0398d7SOtavio Salvador * connected state.
4963a0398d7SOtavio Salvador */
4973a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_dcdc4p2,
4983a0398d7SOtavio Salvador POWER_DCDC4P2_ENABLE_DCDC);
4993a0398d7SOtavio Salvador writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
5003a0398d7SOtavio Salvador &power_regs->hw_power_5vctrl_set);
501950eaf62SGraeme Russ
502950eaf62SGraeme Russ debug("SPL: Unable to recover from mx23 errata 5837\n");
5033a0398d7SOtavio Salvador hang();
5043a0398d7SOtavio Salvador }
5053a0398d7SOtavio Salvador
5063a0398d7SOtavio Salvador /*
5073a0398d7SOtavio Salvador * Here we set the 4p2 brownout level to something very close to 4.2V.
5083a0398d7SOtavio Salvador * We then check the brownout status. If the brownout status is false,
5093a0398d7SOtavio Salvador * the voltage is already close to the target voltage of 4.2V so we
5103a0398d7SOtavio Salvador * can go ahead and set the 4P2 current limit to our max target limit.
5113a0398d7SOtavio Salvador * If the brownout status is true, we need to ramp us the current limit
5123a0398d7SOtavio Salvador * so that we don't cause large inrush current issues. We step up the
5133a0398d7SOtavio Salvador * current limit until the brownout status is false or until we've
5143a0398d7SOtavio Salvador * reached our maximum defined 4p2 current limit.
5153a0398d7SOtavio Salvador */
516950eaf62SGraeme Russ debug("SPL: Setting 4P2 brownout level\n");
5173a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
5183a0398d7SOtavio Salvador POWER_DCDC4P2_BO_MASK,
5193a0398d7SOtavio Salvador 22 << POWER_DCDC4P2_BO_OFFSET); /* 4.15V */
5203a0398d7SOtavio Salvador
5213a0398d7SOtavio Salvador if (!(readl(&power_regs->hw_power_sts) & POWER_STS_DCDC_4P2_BO)) {
5223a0398d7SOtavio Salvador setbits_le32(&power_regs->hw_power_5vctrl,
5233a0398d7SOtavio Salvador 0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
5243a0398d7SOtavio Salvador } else {
5253a0398d7SOtavio Salvador tmp = (readl(&power_regs->hw_power_5vctrl) &
5263a0398d7SOtavio Salvador POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK) >>
5273a0398d7SOtavio Salvador POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
5283a0398d7SOtavio Salvador while (tmp < 0x3f) {
5293a0398d7SOtavio Salvador if (!(readl(&power_regs->hw_power_sts) &
5303a0398d7SOtavio Salvador POWER_STS_DCDC_4P2_BO)) {
5313a0398d7SOtavio Salvador tmp = readl(&power_regs->hw_power_5vctrl);
5323a0398d7SOtavio Salvador tmp |= POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
5333a0398d7SOtavio Salvador early_delay(100);
5343a0398d7SOtavio Salvador writel(tmp, &power_regs->hw_power_5vctrl);
5353a0398d7SOtavio Salvador break;
5363a0398d7SOtavio Salvador } else {
5373a0398d7SOtavio Salvador tmp++;
5383a0398d7SOtavio Salvador tmp2 = readl(&power_regs->hw_power_5vctrl);
5393a0398d7SOtavio Salvador tmp2 &= ~POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
5403a0398d7SOtavio Salvador tmp2 |= tmp <<
5413a0398d7SOtavio Salvador POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
5423a0398d7SOtavio Salvador writel(tmp2, &power_regs->hw_power_5vctrl);
5433a0398d7SOtavio Salvador early_delay(100);
5443a0398d7SOtavio Salvador }
5453a0398d7SOtavio Salvador }
5463a0398d7SOtavio Salvador }
5473a0398d7SOtavio Salvador
5483a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
5493a0398d7SOtavio Salvador writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
5503a0398d7SOtavio Salvador }
5513a0398d7SOtavio Salvador
552d4c9135cSMarek Vasut /**
553d4c9135cSMarek Vasut * mxs_power_init_dcdc_4p2_source() - Switch DC-DC converter to 4P2 source
554d4c9135cSMarek Vasut *
555d4c9135cSMarek Vasut * This function configures the DC-DC converter to be supplied from the 4P2
556d4c9135cSMarek Vasut * linear regulator.
557d4c9135cSMarek Vasut */
mxs_power_init_dcdc_4p2_source(void)558a918a53cSMarek Vasut static void mxs_power_init_dcdc_4p2_source(void)
5593a0398d7SOtavio Salvador {
5609c471142SOtavio Salvador struct mxs_power_regs *power_regs =
5619c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
5623a0398d7SOtavio Salvador
563950eaf62SGraeme Russ debug("SPL: Switching DC-DC converters to 4P2\n");
564950eaf62SGraeme Russ
5653a0398d7SOtavio Salvador if (!(readl(&power_regs->hw_power_dcdc4p2) &
5663a0398d7SOtavio Salvador POWER_DCDC4P2_ENABLE_DCDC)) {
567950eaf62SGraeme Russ debug("SPL: Already switched - aborting\n");
5683a0398d7SOtavio Salvador hang();
5693a0398d7SOtavio Salvador }
5703a0398d7SOtavio Salvador
5711e0cf5c3SOtavio Salvador mxs_enable_4p2_dcdc_input(1);
5723a0398d7SOtavio Salvador
5733a0398d7SOtavio Salvador if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
5743a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_dcdc4p2,
5753a0398d7SOtavio Salvador POWER_DCDC4P2_ENABLE_DCDC);
5763a0398d7SOtavio Salvador writel(POWER_5VCTRL_ENABLE_DCDC,
5773a0398d7SOtavio Salvador &power_regs->hw_power_5vctrl_clr);
5783a0398d7SOtavio Salvador writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
5793a0398d7SOtavio Salvador &power_regs->hw_power_5vctrl_set);
5803a0398d7SOtavio Salvador }
5813a0398d7SOtavio Salvador }
5823a0398d7SOtavio Salvador
583d4c9135cSMarek Vasut /**
584d4c9135cSMarek Vasut * mxs_power_enable_4p2() - Power up the 4P2 regulator
585d4c9135cSMarek Vasut *
586d4c9135cSMarek Vasut * This function drives the process of powering up the 4P2 linear regulator
587d4c9135cSMarek Vasut * and switching the DC-DC converter input over to the 4P2 linear regulator.
588d4c9135cSMarek Vasut */
mxs_power_enable_4p2(void)589a918a53cSMarek Vasut static void mxs_power_enable_4p2(void)
5903a0398d7SOtavio Salvador {
5919c471142SOtavio Salvador struct mxs_power_regs *power_regs =
5929c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
5933a0398d7SOtavio Salvador uint32_t vdddctrl, vddactrl, vddioctrl;
5943a0398d7SOtavio Salvador uint32_t tmp;
5953a0398d7SOtavio Salvador
596950eaf62SGraeme Russ debug("SPL: Powering up 4P2 regulator\n");
597950eaf62SGraeme Russ
5983a0398d7SOtavio Salvador vdddctrl = readl(&power_regs->hw_power_vdddctrl);
5993a0398d7SOtavio Salvador vddactrl = readl(&power_regs->hw_power_vddactrl);
6003a0398d7SOtavio Salvador vddioctrl = readl(&power_regs->hw_power_vddioctrl);
6013a0398d7SOtavio Salvador
6023a0398d7SOtavio Salvador setbits_le32(&power_regs->hw_power_vdddctrl,
6033a0398d7SOtavio Salvador POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
6043a0398d7SOtavio Salvador POWER_VDDDCTRL_PWDN_BRNOUT);
6053a0398d7SOtavio Salvador
6063a0398d7SOtavio Salvador setbits_le32(&power_regs->hw_power_vddactrl,
6073a0398d7SOtavio Salvador POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG |
6083a0398d7SOtavio Salvador POWER_VDDACTRL_PWDN_BRNOUT);
6093a0398d7SOtavio Salvador
6103a0398d7SOtavio Salvador setbits_le32(&power_regs->hw_power_vddioctrl,
6113a0398d7SOtavio Salvador POWER_VDDIOCTRL_DISABLE_FET | POWER_VDDIOCTRL_PWDN_BRNOUT);
6123a0398d7SOtavio Salvador
6131e0cf5c3SOtavio Salvador mxs_power_init_4p2_params();
6141e0cf5c3SOtavio Salvador mxs_power_init_4p2_regulator();
6153a0398d7SOtavio Salvador
6163a0398d7SOtavio Salvador /* Shutdown battery (none present) */
6171e0cf5c3SOtavio Salvador if (!mxs_is_batt_ready()) {
6183a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_dcdc4p2,
6193a0398d7SOtavio Salvador POWER_DCDC4P2_BO_MASK);
6203a0398d7SOtavio Salvador writel(POWER_CTRL_DCDC4P2_BO_IRQ,
6213a0398d7SOtavio Salvador &power_regs->hw_power_ctrl_clr);
6223a0398d7SOtavio Salvador writel(POWER_CTRL_ENIRQ_DCDC4P2_BO,
6233a0398d7SOtavio Salvador &power_regs->hw_power_ctrl_clr);
6243a0398d7SOtavio Salvador }
6253a0398d7SOtavio Salvador
6261e0cf5c3SOtavio Salvador mxs_power_init_dcdc_4p2_source();
6273a0398d7SOtavio Salvador
6283a0398d7SOtavio Salvador writel(vdddctrl, &power_regs->hw_power_vdddctrl);
6293a0398d7SOtavio Salvador early_delay(20);
6303a0398d7SOtavio Salvador writel(vddactrl, &power_regs->hw_power_vddactrl);
6313a0398d7SOtavio Salvador early_delay(20);
6323a0398d7SOtavio Salvador writel(vddioctrl, &power_regs->hw_power_vddioctrl);
6333a0398d7SOtavio Salvador
6343a0398d7SOtavio Salvador /*
6353a0398d7SOtavio Salvador * Check if FET is enabled on either powerout and if so,
6363a0398d7SOtavio Salvador * disable load.
6373a0398d7SOtavio Salvador */
6383a0398d7SOtavio Salvador tmp = 0;
6393a0398d7SOtavio Salvador tmp |= !(readl(&power_regs->hw_power_vdddctrl) &
6403a0398d7SOtavio Salvador POWER_VDDDCTRL_DISABLE_FET);
6413a0398d7SOtavio Salvador tmp |= !(readl(&power_regs->hw_power_vddactrl) &
6423a0398d7SOtavio Salvador POWER_VDDACTRL_DISABLE_FET);
6433a0398d7SOtavio Salvador tmp |= !(readl(&power_regs->hw_power_vddioctrl) &
6443a0398d7SOtavio Salvador POWER_VDDIOCTRL_DISABLE_FET);
6453a0398d7SOtavio Salvador if (tmp)
6463a0398d7SOtavio Salvador writel(POWER_CHARGE_ENABLE_LOAD,
6473a0398d7SOtavio Salvador &power_regs->hw_power_charge_clr);
648950eaf62SGraeme Russ
649950eaf62SGraeme Russ debug("SPL: 4P2 regulator powered-up\n");
6503a0398d7SOtavio Salvador }
6513a0398d7SOtavio Salvador
652d4c9135cSMarek Vasut /**
653d4c9135cSMarek Vasut * mxs_boot_valid_5v() - Boot from 5V supply
654d4c9135cSMarek Vasut *
655d4c9135cSMarek Vasut * This function configures the power block to boot from valid 5V input.
656d4c9135cSMarek Vasut * This is called only if the 5V is reliable and can properly supply the
657d4c9135cSMarek Vasut * CPU. This function proceeds to configure the 4P2 converter to be supplied
658d4c9135cSMarek Vasut * from the 5V input.
659d4c9135cSMarek Vasut */
mxs_boot_valid_5v(void)660a918a53cSMarek Vasut static void mxs_boot_valid_5v(void)
6613a0398d7SOtavio Salvador {
6629c471142SOtavio Salvador struct mxs_power_regs *power_regs =
6639c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
6643a0398d7SOtavio Salvador
665950eaf62SGraeme Russ debug("SPL: Booting from 5V supply\n");
666950eaf62SGraeme Russ
6673a0398d7SOtavio Salvador /*
6683a0398d7SOtavio Salvador * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V
6693a0398d7SOtavio Salvador * disconnect event. FIXME
6703a0398d7SOtavio Salvador */
6713a0398d7SOtavio Salvador writel(POWER_5VCTRL_VBUSVALID_5VDETECT,
6723a0398d7SOtavio Salvador &power_regs->hw_power_5vctrl_set);
6733a0398d7SOtavio Salvador
6743a0398d7SOtavio Salvador /* Configure polarity to check for 5V disconnection. */
6753a0398d7SOtavio Salvador writel(POWER_CTRL_POLARITY_VBUSVALID |
6763a0398d7SOtavio Salvador POWER_CTRL_POLARITY_VDD5V_GT_VDDIO,
6773a0398d7SOtavio Salvador &power_regs->hw_power_ctrl_clr);
6783a0398d7SOtavio Salvador
6793a0398d7SOtavio Salvador writel(POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_VDD5V_GT_VDDIO_IRQ,
6803a0398d7SOtavio Salvador &power_regs->hw_power_ctrl_clr);
6813a0398d7SOtavio Salvador
6821e0cf5c3SOtavio Salvador mxs_power_enable_4p2();
6833a0398d7SOtavio Salvador }
6843a0398d7SOtavio Salvador
685d4c9135cSMarek Vasut /**
686d4c9135cSMarek Vasut * mxs_powerdown() - Shut down the system
687d4c9135cSMarek Vasut *
688d4c9135cSMarek Vasut * This function powers down the CPU completely.
689d4c9135cSMarek Vasut */
mxs_powerdown(void)690a918a53cSMarek Vasut static void mxs_powerdown(void)
6913a0398d7SOtavio Salvador {
6929c471142SOtavio Salvador struct mxs_power_regs *power_regs =
6939c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
694950eaf62SGraeme Russ
695950eaf62SGraeme Russ debug("Powering Down\n");
696950eaf62SGraeme Russ
6973a0398d7SOtavio Salvador writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset);
6983a0398d7SOtavio Salvador writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
6993a0398d7SOtavio Salvador &power_regs->hw_power_reset);
7003a0398d7SOtavio Salvador }
7013a0398d7SOtavio Salvador
702d4c9135cSMarek Vasut /**
703d4c9135cSMarek Vasut * mxs_batt_boot() - Configure the power block to boot from battery input
704d4c9135cSMarek Vasut *
705d4c9135cSMarek Vasut * This function configures the power block to boot from the battery voltage
706d4c9135cSMarek Vasut * supply.
707d4c9135cSMarek Vasut */
mxs_batt_boot(void)708a918a53cSMarek Vasut static void mxs_batt_boot(void)
7093a0398d7SOtavio Salvador {
7109c471142SOtavio Salvador struct mxs_power_regs *power_regs =
7119c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
7123a0398d7SOtavio Salvador
713950eaf62SGraeme Russ debug("SPL: Configuring power block to boot from battery\n");
714950eaf62SGraeme Russ
7153a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
7163a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_ENABLE_DCDC);
7173a0398d7SOtavio Salvador
7183a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_dcdc4p2,
7193a0398d7SOtavio Salvador POWER_DCDC4P2_ENABLE_DCDC | POWER_DCDC4P2_ENABLE_4P2);
7203a0398d7SOtavio Salvador writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_clr);
7213a0398d7SOtavio Salvador
7223a0398d7SOtavio Salvador /* 5V to battery handoff. */
7233a0398d7SOtavio Salvador setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
7243a0398d7SOtavio Salvador early_delay(30);
7253a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
7263a0398d7SOtavio Salvador
7273a0398d7SOtavio Salvador writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, &power_regs->hw_power_ctrl_clr);
7283a0398d7SOtavio Salvador
7293a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_minpwr,
7303a0398d7SOtavio Salvador POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
7313a0398d7SOtavio Salvador
7321e0cf5c3SOtavio Salvador mxs_power_set_linreg();
7333a0398d7SOtavio Salvador
7343a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_vdddctrl,
7353a0398d7SOtavio Salvador POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG);
7363a0398d7SOtavio Salvador
7373a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_vddactrl,
7383a0398d7SOtavio Salvador POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG);
7393a0398d7SOtavio Salvador
7403a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_vddioctrl,
7413a0398d7SOtavio Salvador POWER_VDDIOCTRL_DISABLE_FET);
7423a0398d7SOtavio Salvador
7433a0398d7SOtavio Salvador setbits_le32(&power_regs->hw_power_5vctrl,
7443a0398d7SOtavio Salvador POWER_5VCTRL_PWD_CHARGE_4P2_MASK);
7453a0398d7SOtavio Salvador
7463a0398d7SOtavio Salvador setbits_le32(&power_regs->hw_power_5vctrl,
7473a0398d7SOtavio Salvador POWER_5VCTRL_ENABLE_DCDC);
7483a0398d7SOtavio Salvador
7493a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_5vctrl,
7503a0398d7SOtavio Salvador POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
7513a0398d7SOtavio Salvador 0x8 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
752a0f97610SMarek Vasut
753a0f97610SMarek Vasut mxs_power_enable_4p2();
7543a0398d7SOtavio Salvador }
7553a0398d7SOtavio Salvador
756d4c9135cSMarek Vasut /**
757d4c9135cSMarek Vasut * mxs_handle_5v_conflict() - Test if the 5V input is reliable
758d4c9135cSMarek Vasut *
759d4c9135cSMarek Vasut * This function tests if the 5V input can reliably supply the system. If it
760d4c9135cSMarek Vasut * can, then proceed to configuring the system to boot from 5V source, otherwise
761d4c9135cSMarek Vasut * try booting from battery supply. If we can not boot from battery supply
762d4c9135cSMarek Vasut * either, shut down the system.
763d4c9135cSMarek Vasut */
mxs_handle_5v_conflict(void)764a918a53cSMarek Vasut static void mxs_handle_5v_conflict(void)
7653a0398d7SOtavio Salvador {
7669c471142SOtavio Salvador struct mxs_power_regs *power_regs =
7679c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
7683a0398d7SOtavio Salvador uint32_t tmp;
7693a0398d7SOtavio Salvador
770950eaf62SGraeme Russ debug("SPL: Resolving 5V conflict\n");
771950eaf62SGraeme Russ
7723a0398d7SOtavio Salvador setbits_le32(&power_regs->hw_power_vddioctrl,
7733a0398d7SOtavio Salvador POWER_VDDIOCTRL_BO_OFFSET_MASK);
7743a0398d7SOtavio Salvador
7753a0398d7SOtavio Salvador for (;;) {
7763a0398d7SOtavio Salvador tmp = readl(&power_regs->hw_power_sts);
7773a0398d7SOtavio Salvador
7783a0398d7SOtavio Salvador if (tmp & POWER_STS_VDDIO_BO) {
77905c823bdSOtavio Salvador /*
78005c823bdSOtavio Salvador * VDDIO has a brownout, then the VDD5V_GT_VDDIO becomes
78105c823bdSOtavio Salvador * unreliable
78205c823bdSOtavio Salvador */
783950eaf62SGraeme Russ debug("SPL: VDDIO has a brownout\n");
7841e0cf5c3SOtavio Salvador mxs_powerdown();
7853a0398d7SOtavio Salvador break;
7863a0398d7SOtavio Salvador }
7873a0398d7SOtavio Salvador
7883a0398d7SOtavio Salvador if (tmp & POWER_STS_VDD5V_GT_VDDIO) {
789950eaf62SGraeme Russ debug("SPL: POWER_STS_VDD5V_GT_VDDIO is set\n");
7901e0cf5c3SOtavio Salvador mxs_boot_valid_5v();
7913a0398d7SOtavio Salvador break;
7923a0398d7SOtavio Salvador } else {
793950eaf62SGraeme Russ debug("SPL: POWER_STS_VDD5V_GT_VDDIO is not set\n");
7941e0cf5c3SOtavio Salvador mxs_powerdown();
7953a0398d7SOtavio Salvador break;
7963a0398d7SOtavio Salvador }
7973a0398d7SOtavio Salvador
798950eaf62SGraeme Russ /*
799950eaf62SGraeme Russ * TODO: I can't see this being reached. We'll either
800950eaf62SGraeme Russ * powerdown or boot from a stable 5V supply.
801950eaf62SGraeme Russ */
8023a0398d7SOtavio Salvador if (tmp & POWER_STS_PSWITCH_MASK) {
803950eaf62SGraeme Russ debug("SPL: POWER_STS_PSWITCH_MASK is set\n");
8041e0cf5c3SOtavio Salvador mxs_batt_boot();
8053a0398d7SOtavio Salvador break;
8063a0398d7SOtavio Salvador }
8073a0398d7SOtavio Salvador }
8083a0398d7SOtavio Salvador }
8093a0398d7SOtavio Salvador
810d4c9135cSMarek Vasut /**
811d4c9135cSMarek Vasut * mxs_5v_boot() - Configure the power block to boot from 5V input
812d4c9135cSMarek Vasut *
813d4c9135cSMarek Vasut * This function handles configuration of the power block when supplied by
814d4c9135cSMarek Vasut * a 5V input.
815d4c9135cSMarek Vasut */
mxs_5v_boot(void)816a918a53cSMarek Vasut static void mxs_5v_boot(void)
8173a0398d7SOtavio Salvador {
8189c471142SOtavio Salvador struct mxs_power_regs *power_regs =
8199c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
8203a0398d7SOtavio Salvador
821950eaf62SGraeme Russ debug("SPL: Configuring power block to boot from 5V input\n");
822950eaf62SGraeme Russ
8233a0398d7SOtavio Salvador /*
8243a0398d7SOtavio Salvador * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID,
8253a0398d7SOtavio Salvador * but their implementation always returns 1 so we omit it here.
8263a0398d7SOtavio Salvador */
8273a0398d7SOtavio Salvador if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
828950eaf62SGraeme Russ debug("SPL: 5V VDD good\n");
8291e0cf5c3SOtavio Salvador mxs_boot_valid_5v();
8303a0398d7SOtavio Salvador return;
8313a0398d7SOtavio Salvador }
8323a0398d7SOtavio Salvador
8333a0398d7SOtavio Salvador early_delay(1000);
8343a0398d7SOtavio Salvador if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
835950eaf62SGraeme Russ debug("SPL: 5V VDD good (after delay)\n");
8361e0cf5c3SOtavio Salvador mxs_boot_valid_5v();
8373a0398d7SOtavio Salvador return;
8383a0398d7SOtavio Salvador }
8393a0398d7SOtavio Salvador
840950eaf62SGraeme Russ debug("SPL: 5V VDD not good\n");
8411e0cf5c3SOtavio Salvador mxs_handle_5v_conflict();
8423a0398d7SOtavio Salvador }
8433a0398d7SOtavio Salvador
844d4c9135cSMarek Vasut /**
845d4c9135cSMarek Vasut * mxs_init_batt_bo() - Configure battery brownout threshold
846d4c9135cSMarek Vasut *
847d4c9135cSMarek Vasut * This function configures the battery input brownout threshold. The value
848d4c9135cSMarek Vasut * at which the battery brownout happens is configured to 3.0V in the code.
849d4c9135cSMarek Vasut */
mxs_init_batt_bo(void)850a918a53cSMarek Vasut static void mxs_init_batt_bo(void)
8513a0398d7SOtavio Salvador {
8529c471142SOtavio Salvador struct mxs_power_regs *power_regs =
8539c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
8543a0398d7SOtavio Salvador
855950eaf62SGraeme Russ debug("SPL: Initialising battery brown-out level to 3.0V\n");
856950eaf62SGraeme Russ
8573a0398d7SOtavio Salvador /* Brownout at 3V */
8583a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_battmonitor,
8593a0398d7SOtavio Salvador POWER_BATTMONITOR_BRWNOUT_LVL_MASK,
8603a0398d7SOtavio Salvador 15 << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
8613a0398d7SOtavio Salvador
8623a0398d7SOtavio Salvador writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr);
8633a0398d7SOtavio Salvador writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
8643a0398d7SOtavio Salvador }
8653a0398d7SOtavio Salvador
866d4c9135cSMarek Vasut /**
867d4c9135cSMarek Vasut * mxs_switch_vddd_to_dcdc_source() - Switch VDDD rail to DC-DC converter
868d4c9135cSMarek Vasut *
869d4c9135cSMarek Vasut * This function turns off the VDDD linear regulator and therefore makes
870d4c9135cSMarek Vasut * the VDDD rail be supplied only by the DC-DC converter.
871d4c9135cSMarek Vasut */
mxs_switch_vddd_to_dcdc_source(void)872a918a53cSMarek Vasut static void mxs_switch_vddd_to_dcdc_source(void)
8733a0398d7SOtavio Salvador {
8749c471142SOtavio Salvador struct mxs_power_regs *power_regs =
8759c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
8763a0398d7SOtavio Salvador
877950eaf62SGraeme Russ debug("SPL: Switching VDDD to DC-DC converters\n");
878950eaf62SGraeme Russ
8793a0398d7SOtavio Salvador clrsetbits_le32(&power_regs->hw_power_vdddctrl,
8803a0398d7SOtavio Salvador POWER_VDDDCTRL_LINREG_OFFSET_MASK,
8813a0398d7SOtavio Salvador POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
8823a0398d7SOtavio Salvador
8833a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_vdddctrl,
8843a0398d7SOtavio Salvador POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
8853a0398d7SOtavio Salvador POWER_VDDDCTRL_DISABLE_STEPPING);
8863a0398d7SOtavio Salvador }
8873a0398d7SOtavio Salvador
888d4c9135cSMarek Vasut /**
889d4c9135cSMarek Vasut * mxs_power_configure_power_source() - Configure power block source
890d4c9135cSMarek Vasut *
891d4c9135cSMarek Vasut * This function is the core of the power configuration logic. The function
892d4c9135cSMarek Vasut * selects the power block input source and configures the whole power block
893d4c9135cSMarek Vasut * accordingly. After the configuration is complete and the system is stable
894d4c9135cSMarek Vasut * again, the function switches the CPU clock source back to PLL. Finally,
895d4c9135cSMarek Vasut * the function switches the voltage rails to DC-DC converter.
896d4c9135cSMarek Vasut */
mxs_power_configure_power_source(void)897a918a53cSMarek Vasut static void mxs_power_configure_power_source(void)
8983a0398d7SOtavio Salvador {
8993a0398d7SOtavio Salvador int batt_ready, batt_good;
9009c471142SOtavio Salvador struct mxs_power_regs *power_regs =
9019c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
9029c471142SOtavio Salvador struct mxs_lradc_regs *lradc_regs =
9039c471142SOtavio Salvador (struct mxs_lradc_regs *)MXS_LRADC_BASE;
9043a0398d7SOtavio Salvador
905950eaf62SGraeme Russ debug("SPL: Configuring power source\n");
906950eaf62SGraeme Russ
907fe21eaf9SMichael Heimpold mxs_power_setup_dcdc_clocksource();
9081e0cf5c3SOtavio Salvador mxs_src_power_init();
9093a0398d7SOtavio Salvador
9103a0398d7SOtavio Salvador if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
911fdb00b81SMarek Vasut batt_ready = mxs_is_batt_ready();
9123a0398d7SOtavio Salvador if (batt_ready) {
9133a0398d7SOtavio Salvador /* 5V source detected, good battery detected. */
9141e0cf5c3SOtavio Salvador mxs_batt_boot();
9153a0398d7SOtavio Salvador } else {
916fdb00b81SMarek Vasut batt_good = mxs_is_batt_good();
917fdb00b81SMarek Vasut if (!batt_good) {
9183a0398d7SOtavio Salvador /* 5V source detected, bad battery detected. */
9193a0398d7SOtavio Salvador writel(LRADC_CONVERSION_AUTOMATIC,
9203a0398d7SOtavio Salvador &lradc_regs->hw_lradc_conversion_clr);
9213a0398d7SOtavio Salvador clrbits_le32(&power_regs->hw_power_battmonitor,
9223a0398d7SOtavio Salvador POWER_BATTMONITOR_BATT_VAL_MASK);
9233a0398d7SOtavio Salvador }
9241e0cf5c3SOtavio Salvador mxs_5v_boot();
9253a0398d7SOtavio Salvador }
9263a0398d7SOtavio Salvador } else {
9273a0398d7SOtavio Salvador /* 5V not detected, booting from battery. */
9281e0cf5c3SOtavio Salvador mxs_batt_boot();
9293a0398d7SOtavio Salvador }
9303a0398d7SOtavio Salvador
931950eaf62SGraeme Russ /*
932950eaf62SGraeme Russ * TODO: Do not switch CPU clock to PLL if we are VDD5V is sourced
933950eaf62SGraeme Russ * from USB VBUS
934950eaf62SGraeme Russ */
9351e0cf5c3SOtavio Salvador mxs_power_clock2pll();
9363a0398d7SOtavio Salvador
9371e0cf5c3SOtavio Salvador mxs_init_batt_bo();
9383a0398d7SOtavio Salvador
9391e0cf5c3SOtavio Salvador mxs_switch_vddd_to_dcdc_source();
940dd3ecf02SMarek Vasut
941dd3ecf02SMarek Vasut #ifdef CONFIG_MX23
942dd3ecf02SMarek Vasut /* Fire up the VDDMEM LinReg now that we're all set. */
943950eaf62SGraeme Russ debug("SPL: Enabling mx23 VDDMEM linear regulator\n");
944dd3ecf02SMarek Vasut writel(POWER_VDDMEMCTRL_ENABLE_LINREG | POWER_VDDMEMCTRL_ENABLE_ILIMIT,
945dd3ecf02SMarek Vasut &power_regs->hw_power_vddmemctrl);
946dd3ecf02SMarek Vasut #endif
9473a0398d7SOtavio Salvador }
9483a0398d7SOtavio Salvador
949d4c9135cSMarek Vasut /**
950d4c9135cSMarek Vasut * mxs_enable_output_rail_protection() - Enable power rail protection
951d4c9135cSMarek Vasut *
952d4c9135cSMarek Vasut * This function enables overload protection on the power rails. This is
953d4c9135cSMarek Vasut * triggered if the power rails' voltage drops rapidly due to overload and
954d4c9135cSMarek Vasut * in such case, the supply to the powerrail is cut-off, protecting the
955d4c9135cSMarek Vasut * CPU from damage. Note that under such condition, the system will likely
956d4c9135cSMarek Vasut * crash or misbehave.
957d4c9135cSMarek Vasut */
mxs_enable_output_rail_protection(void)958a918a53cSMarek Vasut static void mxs_enable_output_rail_protection(void)
9593a0398d7SOtavio Salvador {
9609c471142SOtavio Salvador struct mxs_power_regs *power_regs =
9619c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
9623a0398d7SOtavio Salvador
963950eaf62SGraeme Russ debug("SPL: Enabling output rail protection\n");
964950eaf62SGraeme Russ
9653a0398d7SOtavio Salvador writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
9663a0398d7SOtavio Salvador POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr);
9673a0398d7SOtavio Salvador
9683a0398d7SOtavio Salvador setbits_le32(&power_regs->hw_power_vdddctrl,
9693a0398d7SOtavio Salvador POWER_VDDDCTRL_PWDN_BRNOUT);
9703a0398d7SOtavio Salvador
9713a0398d7SOtavio Salvador setbits_le32(&power_regs->hw_power_vddactrl,
9723a0398d7SOtavio Salvador POWER_VDDACTRL_PWDN_BRNOUT);
9733a0398d7SOtavio Salvador
9743a0398d7SOtavio Salvador setbits_le32(&power_regs->hw_power_vddioctrl,
9753a0398d7SOtavio Salvador POWER_VDDIOCTRL_PWDN_BRNOUT);
9763a0398d7SOtavio Salvador }
9773a0398d7SOtavio Salvador
978d4c9135cSMarek Vasut /**
979d4c9135cSMarek Vasut * mxs_get_vddio_power_source_off() - Get VDDIO rail power source
980d4c9135cSMarek Vasut *
981d4c9135cSMarek Vasut * This function tests if the VDDIO rail is supplied by linear regulator
982d4c9135cSMarek Vasut * or by the DC-DC converter. Returns 1 if powered by linear regulator,
983d4c9135cSMarek Vasut * returns 0 if powered by the DC-DC converter.
984d4c9135cSMarek Vasut */
mxs_get_vddio_power_source_off(void)985a918a53cSMarek Vasut static int mxs_get_vddio_power_source_off(void)
9863a0398d7SOtavio Salvador {
9879c471142SOtavio Salvador struct mxs_power_regs *power_regs =
9889c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
9893a0398d7SOtavio Salvador uint32_t tmp;
9903a0398d7SOtavio Salvador
9913a0398d7SOtavio Salvador if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
9923a0398d7SOtavio Salvador tmp = readl(&power_regs->hw_power_vddioctrl);
9933a0398d7SOtavio Salvador if (tmp & POWER_VDDIOCTRL_DISABLE_FET) {
9943a0398d7SOtavio Salvador if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
9958b165a53SStathis Voukelatos POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS) {
9963a0398d7SOtavio Salvador return 1;
9973a0398d7SOtavio Salvador }
9983a0398d7SOtavio Salvador }
9993a0398d7SOtavio Salvador
10003a0398d7SOtavio Salvador if (!(readl(&power_regs->hw_power_5vctrl) &
10013a0398d7SOtavio Salvador POWER_5VCTRL_ENABLE_DCDC)) {
10023a0398d7SOtavio Salvador if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
10038b165a53SStathis Voukelatos POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS) {
10043a0398d7SOtavio Salvador return 1;
10053a0398d7SOtavio Salvador }
10063a0398d7SOtavio Salvador }
10073a0398d7SOtavio Salvador }
10083a0398d7SOtavio Salvador
10093a0398d7SOtavio Salvador return 0;
10103a0398d7SOtavio Salvador
10113a0398d7SOtavio Salvador }
10123a0398d7SOtavio Salvador
1013d4c9135cSMarek Vasut /**
1014d4c9135cSMarek Vasut * mxs_get_vddd_power_source_off() - Get VDDD rail power source
1015d4c9135cSMarek Vasut *
1016d4c9135cSMarek Vasut * This function tests if the VDDD rail is supplied by linear regulator
1017d4c9135cSMarek Vasut * or by the DC-DC converter. Returns 1 if powered by linear regulator,
1018d4c9135cSMarek Vasut * returns 0 if powered by the DC-DC converter.
1019d4c9135cSMarek Vasut */
mxs_get_vddd_power_source_off(void)1020a918a53cSMarek Vasut static int mxs_get_vddd_power_source_off(void)
10213a0398d7SOtavio Salvador {
10229c471142SOtavio Salvador struct mxs_power_regs *power_regs =
10239c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
10243a0398d7SOtavio Salvador uint32_t tmp;
10253a0398d7SOtavio Salvador
10263a0398d7SOtavio Salvador tmp = readl(&power_regs->hw_power_vdddctrl);
10273a0398d7SOtavio Salvador if (tmp & POWER_VDDDCTRL_DISABLE_FET) {
10283a0398d7SOtavio Salvador if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
10293a0398d7SOtavio Salvador POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
10303a0398d7SOtavio Salvador return 1;
10313a0398d7SOtavio Salvador }
10323a0398d7SOtavio Salvador }
10333a0398d7SOtavio Salvador
10343a0398d7SOtavio Salvador if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
10353a0398d7SOtavio Salvador if (!(readl(&power_regs->hw_power_5vctrl) &
10363a0398d7SOtavio Salvador POWER_5VCTRL_ENABLE_DCDC)) {
10373a0398d7SOtavio Salvador return 1;
10383a0398d7SOtavio Salvador }
10393a0398d7SOtavio Salvador }
10403a0398d7SOtavio Salvador
10413a0398d7SOtavio Salvador if (!(tmp & POWER_VDDDCTRL_ENABLE_LINREG)) {
10423a0398d7SOtavio Salvador if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
10433a0398d7SOtavio Salvador POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW) {
10443a0398d7SOtavio Salvador return 1;
10453a0398d7SOtavio Salvador }
10463a0398d7SOtavio Salvador }
10473a0398d7SOtavio Salvador
10483a0398d7SOtavio Salvador return 0;
10493a0398d7SOtavio Salvador }
10503a0398d7SOtavio Salvador
105177cb33bdSMarek Vasut struct mxs_vddx_cfg {
105277cb33bdSMarek Vasut uint32_t *reg;
105377cb33bdSMarek Vasut uint8_t step_mV;
105477cb33bdSMarek Vasut uint16_t lowest_mV;
105577cb33bdSMarek Vasut int (*powered_by_linreg)(void);
105677cb33bdSMarek Vasut uint32_t trg_mask;
105777cb33bdSMarek Vasut uint32_t bo_irq;
105877cb33bdSMarek Vasut uint32_t bo_enirq;
105977cb33bdSMarek Vasut uint32_t bo_offset_mask;
106077cb33bdSMarek Vasut uint32_t bo_offset_offset;
106177cb33bdSMarek Vasut };
106277cb33bdSMarek Vasut
1063a918a53cSMarek Vasut static const struct mxs_vddx_cfg mxs_vddio_cfg = {
106477cb33bdSMarek Vasut .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
106577cb33bdSMarek Vasut hw_power_vddioctrl),
1066dd3ecf02SMarek Vasut #if defined(CONFIG_MX23)
1067dd3ecf02SMarek Vasut .step_mV = 25,
1068dd3ecf02SMarek Vasut #else
106977cb33bdSMarek Vasut .step_mV = 50,
1070dd3ecf02SMarek Vasut #endif
107177cb33bdSMarek Vasut .lowest_mV = 2800,
107277cb33bdSMarek Vasut .powered_by_linreg = mxs_get_vddio_power_source_off,
107377cb33bdSMarek Vasut .trg_mask = POWER_VDDIOCTRL_TRG_MASK,
107477cb33bdSMarek Vasut .bo_irq = POWER_CTRL_VDDIO_BO_IRQ,
107577cb33bdSMarek Vasut .bo_enirq = POWER_CTRL_ENIRQ_VDDIO_BO,
107677cb33bdSMarek Vasut .bo_offset_mask = POWER_VDDIOCTRL_BO_OFFSET_MASK,
107777cb33bdSMarek Vasut .bo_offset_offset = POWER_VDDIOCTRL_BO_OFFSET_OFFSET,
107877cb33bdSMarek Vasut };
107977cb33bdSMarek Vasut
1080a918a53cSMarek Vasut static const struct mxs_vddx_cfg mxs_vddd_cfg = {
108177cb33bdSMarek Vasut .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
108277cb33bdSMarek Vasut hw_power_vdddctrl),
108377cb33bdSMarek Vasut .step_mV = 25,
108477cb33bdSMarek Vasut .lowest_mV = 800,
108577cb33bdSMarek Vasut .powered_by_linreg = mxs_get_vddd_power_source_off,
108677cb33bdSMarek Vasut .trg_mask = POWER_VDDDCTRL_TRG_MASK,
108777cb33bdSMarek Vasut .bo_irq = POWER_CTRL_VDDD_BO_IRQ,
108877cb33bdSMarek Vasut .bo_enirq = POWER_CTRL_ENIRQ_VDDD_BO,
108977cb33bdSMarek Vasut .bo_offset_mask = POWER_VDDDCTRL_BO_OFFSET_MASK,
109077cb33bdSMarek Vasut .bo_offset_offset = POWER_VDDDCTRL_BO_OFFSET_OFFSET,
109177cb33bdSMarek Vasut };
109277cb33bdSMarek Vasut
1093dd3ecf02SMarek Vasut #ifdef CONFIG_MX23
1094dd3ecf02SMarek Vasut static const struct mxs_vddx_cfg mxs_vddmem_cfg = {
1095dd3ecf02SMarek Vasut .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
1096dd3ecf02SMarek Vasut hw_power_vddmemctrl),
1097dd3ecf02SMarek Vasut .step_mV = 50,
1098dd3ecf02SMarek Vasut .lowest_mV = 1700,
1099dd3ecf02SMarek Vasut .powered_by_linreg = NULL,
1100dd3ecf02SMarek Vasut .trg_mask = POWER_VDDMEMCTRL_TRG_MASK,
1101dd3ecf02SMarek Vasut .bo_irq = 0,
1102dd3ecf02SMarek Vasut .bo_enirq = 0,
1103dd3ecf02SMarek Vasut .bo_offset_mask = 0,
1104dd3ecf02SMarek Vasut .bo_offset_offset = 0,
1105dd3ecf02SMarek Vasut };
1106dd3ecf02SMarek Vasut #endif
1107dd3ecf02SMarek Vasut
1108d4c9135cSMarek Vasut /**
1109d4c9135cSMarek Vasut * mxs_power_set_vddx() - Configure voltage on DC-DC converter rail
1110d4c9135cSMarek Vasut * @cfg: Configuration data of the DC-DC converter rail
1111d4c9135cSMarek Vasut * @new_target: New target voltage of the DC-DC converter rail
1112d4c9135cSMarek Vasut * @new_brownout: New brownout trigger voltage
1113d4c9135cSMarek Vasut *
1114d4c9135cSMarek Vasut * This function configures the output voltage on the DC-DC converter rail.
1115d4c9135cSMarek Vasut * The rail is selected by the @cfg argument. The new voltage target is
1116d4c9135cSMarek Vasut * selected by the @new_target and the voltage is specified in mV. The
1117d4c9135cSMarek Vasut * new brownout value is selected by the @new_brownout argument and the
1118d4c9135cSMarek Vasut * value is also in mV.
1119d4c9135cSMarek Vasut */
mxs_power_set_vddx(const struct mxs_vddx_cfg * cfg,uint32_t new_target,uint32_t new_brownout)112077cb33bdSMarek Vasut static void mxs_power_set_vddx(const struct mxs_vddx_cfg *cfg,
112177cb33bdSMarek Vasut uint32_t new_target, uint32_t new_brownout)
11223a0398d7SOtavio Salvador {
11239c471142SOtavio Salvador struct mxs_power_regs *power_regs =
11249c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
11253a0398d7SOtavio Salvador uint32_t cur_target, diff, bo_int = 0;
11263a0398d7SOtavio Salvador uint32_t powered_by_linreg = 0;
112777cb33bdSMarek Vasut int adjust_up, tmp;
11283a0398d7SOtavio Salvador
11294515992fSMasahiro Yamada new_brownout = DIV_ROUND_CLOSEST(new_target - new_brownout,
11304515992fSMasahiro Yamada cfg->step_mV);
11313a0398d7SOtavio Salvador
113277cb33bdSMarek Vasut cur_target = readl(cfg->reg);
113377cb33bdSMarek Vasut cur_target &= cfg->trg_mask;
113477cb33bdSMarek Vasut cur_target *= cfg->step_mV;
113577cb33bdSMarek Vasut cur_target += cfg->lowest_mV;
11363a0398d7SOtavio Salvador
113777cb33bdSMarek Vasut adjust_up = new_target > cur_target;
1138dd3ecf02SMarek Vasut if (cfg->powered_by_linreg)
113977cb33bdSMarek Vasut powered_by_linreg = cfg->powered_by_linreg();
11403a0398d7SOtavio Salvador
1141dd3ecf02SMarek Vasut if (adjust_up && cfg->bo_irq) {
11423a0398d7SOtavio Salvador if (powered_by_linreg) {
114377cb33bdSMarek Vasut bo_int = readl(cfg->reg);
114477cb33bdSMarek Vasut clrbits_le32(cfg->reg, cfg->bo_enirq);
114577cb33bdSMarek Vasut }
114677cb33bdSMarek Vasut setbits_le32(cfg->reg, cfg->bo_offset_mask);
11473a0398d7SOtavio Salvador }
11483a0398d7SOtavio Salvador
11493a0398d7SOtavio Salvador do {
115077cb33bdSMarek Vasut if (abs(new_target - cur_target) > 100) {
115177cb33bdSMarek Vasut if (adjust_up)
11523a0398d7SOtavio Salvador diff = cur_target + 100;
11533a0398d7SOtavio Salvador else
115477cb33bdSMarek Vasut diff = cur_target - 100;
115577cb33bdSMarek Vasut } else {
11563a0398d7SOtavio Salvador diff = new_target;
115777cb33bdSMarek Vasut }
11583a0398d7SOtavio Salvador
115977cb33bdSMarek Vasut diff -= cfg->lowest_mV;
116077cb33bdSMarek Vasut diff /= cfg->step_mV;
11613a0398d7SOtavio Salvador
116277cb33bdSMarek Vasut clrsetbits_le32(cfg->reg, cfg->trg_mask, diff);
11633a0398d7SOtavio Salvador
11643a0398d7SOtavio Salvador if (powered_by_linreg ||
11653a0398d7SOtavio Salvador (readl(&power_regs->hw_power_sts) &
11663a0398d7SOtavio Salvador POWER_STS_VDD5V_GT_VDDIO))
11673a0398d7SOtavio Salvador early_delay(500);
11683a0398d7SOtavio Salvador else {
116977cb33bdSMarek Vasut for (;;) {
117077cb33bdSMarek Vasut tmp = readl(&power_regs->hw_power_sts);
117177cb33bdSMarek Vasut if (tmp & POWER_STS_DC_OK)
117277cb33bdSMarek Vasut break;
117377cb33bdSMarek Vasut }
11743a0398d7SOtavio Salvador }
11753a0398d7SOtavio Salvador
117677cb33bdSMarek Vasut cur_target = readl(cfg->reg);
117777cb33bdSMarek Vasut cur_target &= cfg->trg_mask;
117877cb33bdSMarek Vasut cur_target *= cfg->step_mV;
117977cb33bdSMarek Vasut cur_target += cfg->lowest_mV;
11803a0398d7SOtavio Salvador } while (new_target > cur_target);
11813a0398d7SOtavio Salvador
1182dd3ecf02SMarek Vasut if (cfg->bo_irq) {
118377cb33bdSMarek Vasut if (adjust_up && powered_by_linreg) {
118477cb33bdSMarek Vasut writel(cfg->bo_irq, &power_regs->hw_power_ctrl_clr);
118577cb33bdSMarek Vasut if (bo_int & cfg->bo_enirq)
118677cb33bdSMarek Vasut setbits_le32(cfg->reg, cfg->bo_enirq);
11873a0398d7SOtavio Salvador }
11883a0398d7SOtavio Salvador
118977cb33bdSMarek Vasut clrsetbits_le32(cfg->reg, cfg->bo_offset_mask,
119077cb33bdSMarek Vasut new_brownout << cfg->bo_offset_offset);
11913a0398d7SOtavio Salvador }
1192dd3ecf02SMarek Vasut }
11933a0398d7SOtavio Salvador
1194d4c9135cSMarek Vasut /**
1195d4c9135cSMarek Vasut * mxs_setup_batt_detect() - Start the battery voltage measurement logic
1196d4c9135cSMarek Vasut *
1197d4c9135cSMarek Vasut * This function starts and configures the LRADC block. This allows the
1198d4c9135cSMarek Vasut * power initialization code to measure battery voltage and based on this
1199d4c9135cSMarek Vasut * knowledge, decide whether to boot at all, boot from battery or boot
1200d4c9135cSMarek Vasut * from 5V input.
1201d4c9135cSMarek Vasut */
mxs_setup_batt_detect(void)1202a918a53cSMarek Vasut static void mxs_setup_batt_detect(void)
12033a0398d7SOtavio Salvador {
1204950eaf62SGraeme Russ debug("SPL: Starting battery voltage measurement logic\n");
1205950eaf62SGraeme Russ
12061e0cf5c3SOtavio Salvador mxs_lradc_init();
12071e0cf5c3SOtavio Salvador mxs_lradc_enable_batt_measurement();
12083a0398d7SOtavio Salvador early_delay(10);
12093a0398d7SOtavio Salvador }
12103a0398d7SOtavio Salvador
1211d4c9135cSMarek Vasut /**
1212d4c9135cSMarek Vasut * mxs_ungate_power() - Ungate the POWER block
1213d4c9135cSMarek Vasut *
1214d4c9135cSMarek Vasut * This function ungates clock to the power block. In case the power block
1215d4c9135cSMarek Vasut * was still gated at this point, it will not be possible to configure the
1216d4c9135cSMarek Vasut * block and therefore the power initialization would fail. This function
1217d4c9135cSMarek Vasut * is only needed on i.MX233, on i.MX28 the power block is always ungated.
1218d4c9135cSMarek Vasut */
mxs_ungate_power(void)12197788bf06SMarek Vasut static void mxs_ungate_power(void)
12207788bf06SMarek Vasut {
12217788bf06SMarek Vasut #ifdef CONFIG_MX23
12227788bf06SMarek Vasut struct mxs_power_regs *power_regs =
12237788bf06SMarek Vasut (struct mxs_power_regs *)MXS_POWER_BASE;
12247788bf06SMarek Vasut
12257788bf06SMarek Vasut writel(POWER_CTRL_CLKGATE, &power_regs->hw_power_ctrl_clr);
12267788bf06SMarek Vasut #endif
12277788bf06SMarek Vasut }
12287788bf06SMarek Vasut
1229d4c9135cSMarek Vasut /**
1230d4c9135cSMarek Vasut * mxs_power_init() - The power block init main function
1231d4c9135cSMarek Vasut *
1232d4c9135cSMarek Vasut * This function calls all the power block initialization functions in
1233d4c9135cSMarek Vasut * proper sequence to start the power block.
1234d4c9135cSMarek Vasut */
mxs_power_init(void)12351e0cf5c3SOtavio Salvador void mxs_power_init(void)
12363a0398d7SOtavio Salvador {
12379c471142SOtavio Salvador struct mxs_power_regs *power_regs =
12389c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
12393a0398d7SOtavio Salvador
1240950eaf62SGraeme Russ debug("SPL: Initialising Power Block\n");
1241950eaf62SGraeme Russ
12427788bf06SMarek Vasut mxs_ungate_power();
12437788bf06SMarek Vasut
12441e0cf5c3SOtavio Salvador mxs_power_clock2xtal();
12456f6059e0SHector Palacios mxs_power_set_auto_restart();
12461e0cf5c3SOtavio Salvador mxs_power_set_linreg();
12471e0cf5c3SOtavio Salvador mxs_power_setup_5v_detect();
12483a0398d7SOtavio Salvador
12491e0cf5c3SOtavio Salvador mxs_setup_batt_detect();
12503a0398d7SOtavio Salvador
12511e0cf5c3SOtavio Salvador mxs_power_configure_power_source();
12521e0cf5c3SOtavio Salvador mxs_enable_output_rail_protection();
12533a0398d7SOtavio Salvador
1254950eaf62SGraeme Russ debug("SPL: Setting VDDIO to 3V3 (brownout @ 3v15)\n");
125577cb33bdSMarek Vasut mxs_power_set_vddx(&mxs_vddio_cfg, 3300, 3150);
1256950eaf62SGraeme Russ
1257a6b1e25fSMichael Heimpold debug("SPL: Setting VDDD to 1V5 (brownout @ 1v315)\n");
1258a6b1e25fSMichael Heimpold mxs_power_set_vddx(&mxs_vddd_cfg, 1500, 1315);
1259dd3ecf02SMarek Vasut #ifdef CONFIG_MX23
1260950eaf62SGraeme Russ debug("SPL: Setting mx23 VDDMEM to 2V5 (brownout @ 1v7)\n");
1261dd3ecf02SMarek Vasut mxs_power_set_vddx(&mxs_vddmem_cfg, 2500, 1700);
1262dd3ecf02SMarek Vasut #endif
12633a0398d7SOtavio Salvador writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
12643a0398d7SOtavio Salvador POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
12653a0398d7SOtavio Salvador POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ |
12663a0398d7SOtavio Salvador POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
12673a0398d7SOtavio Salvador
12683a0398d7SOtavio Salvador writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set);
12693a0398d7SOtavio Salvador
12703a0398d7SOtavio Salvador early_delay(1000);
12713a0398d7SOtavio Salvador }
12723a0398d7SOtavio Salvador
1273a74dbf27SOtavio Salvador #ifdef CONFIG_SPL_MXS_PSWITCH_WAIT
1274d4c9135cSMarek Vasut /**
1275d4c9135cSMarek Vasut * mxs_power_wait_pswitch() - Wait for power switch to be pressed
1276d4c9135cSMarek Vasut *
1277d4c9135cSMarek Vasut * This function waits until the power-switch was pressed to start booting
1278d4c9135cSMarek Vasut * the board.
1279d4c9135cSMarek Vasut */
mxs_power_wait_pswitch(void)12801e0cf5c3SOtavio Salvador void mxs_power_wait_pswitch(void)
12813a0398d7SOtavio Salvador {
12829c471142SOtavio Salvador struct mxs_power_regs *power_regs =
12839c471142SOtavio Salvador (struct mxs_power_regs *)MXS_POWER_BASE;
12843a0398d7SOtavio Salvador
1285950eaf62SGraeme Russ debug("SPL: Waiting for power switch input\n");
12863a0398d7SOtavio Salvador while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK))
12873a0398d7SOtavio Salvador ;
12883a0398d7SOtavio Salvador }
12893a0398d7SOtavio Salvador #endif
1290