#include "mx28_init.h"
-extern void dprintf(const char *fmt, ...);
-
-#undef __arch_getl
-#undef __arch_putl
-
-#define __arch_getl(a) arch_getl(a, __func__, __LINE__)
-static inline unsigned int arch_getl(volatile void *addr,
- const char *fn, unsigned int ln)
-{
- volatile unsigned int *a = addr;
- unsigned int val = *a;
- dprintf("%s@%d: Read %x from %p\n", fn, ln, val, addr);
- return val;
-}
-
-#define __arch_putl(v, a) arch_putl(v, a, __func__, __LINE__)
-static inline void arch_putl(unsigned int val, volatile void *addr,
- const char *fn, unsigned int ln)
-{
- volatile unsigned int *a = addr;
-
- dprintf("%s@%d: Writing %x to %p\n", fn, ln, val, addr);
- *a = val;
-}
-
-#define __static
-
-__static int mx28_power_vdd5v_gt_vddio(void)
-{
-#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
- int power_sts = readl(&power_regs->hw_power_sts);
-
- dprintf("%s@%d: 0\n", __func__, __LINE__,
- !!(power_sts & POWER_STS_VDD5V_GT_VDDIO));
- return power_sts & POWER_STS_VDD5V_GT_VDDIO;
+#ifdef CONFIG_SYS_SPL_VDDD_VAL
+#define VDDD_VAL CONFIG_SYS_SPL_VDDD_VAL
#else
- dprintf("%s@%d: 0\n", __func__, __LINE__);
- return 0;
+#define VDDD_VAL 1350
+#endif
+#ifdef CONFIG_SYS_SPL_VDDIO_VAL
+#define VDDIO_VAL CONFIG_SYS_SPL_VDDIO_VAL
+#else
+#define VDDIO_VAL 3300
+#endif
+#ifdef CONFIG_SYS_SPL_VDDA_VAL
+#define VDDA_VAL CONFIG_SYS_SPL_VDDA_VAL
+#else
+#define VDDA_VAL 1800
+#endif
+#ifdef CONFIG_SYS_SPL_VDDMEM_VAL
+#define VDDMEM_VAL CONFIG_SYS_SPL_VDDMEM_VAL
+#else
+#define VDDMEM_VAL 1500
#endif
-}
-__static int mx28_power_vbus_valid(void)
-{
-#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
- int power_5vctrl = readl(&power_regs->hw_power_5vctrl);
-
- dprintf("%s@%d: 0\n", __func__, __LINE__,
- !!(power_5vctrl & POWER_5VCTRL_VBUSVALID_5VDETECT));
- return power_5vctrl & POWER_5VCTRL_VBUSVALID_5VDETECT;
+#ifdef CONFIG_SYS_SPL_VDDD_BO_VAL
+#define VDDD_BO_VAL CONFIG_SYS_SPL_VDDD_BO_VAL
#else
- dprintf("%s@%d: 0\n", __func__, __LINE__);
- return 0;
+#define VDDD_BO_VAL 150
+#endif
+#ifdef CONFIG_SYS_SPL_VDDIO_BO_VAL
+#define VDDIO_BO_VAL CONFIG_SYS_SPL_VDDIO_BO_VAL
+#else
+#define VDDIO_BO_VAL 150
+#endif
+#ifdef CONFIG_SYS_SPL_VDDA_BO_VAL
+#define VDDA_BO_VAL CONFIG_SYS_SPL_VDDA_BO_VAL
+#else
+#define VDDA_BO_VAL 175
+#endif
+#ifdef CONFIG_SYS_SPL_VDDMEM_BO_VAL
+#define VDDMEM_BO_VAL CONFIG_SYS_SPL_VDDMEM_BO_VAL
+#else
+#define VDDMEM_BO_VAL 25
#endif
-}
-static void memdump(unsigned long addr, unsigned long len)
-{
- int i;
- uint32_t *ptr = (void *)addr;
+#ifdef CONFIG_SYS_SPL_BATT_BO_LEVEL
+#if CONFIG_SYS_SPL_BATT_BO_LEVEL < 2400 || CONFIG_SYS_SPL_BATT_BO_LEVEL > 3640
+#error CONFIG_SYS_SPL_BATT_BO_LEVEL out of range
+#endif
+#define BATT_BO_VAL (((CONFIG_SYS_SPL_BATT_BO_LEVEL) - 2400) / 40)
+#else
+/* Brownout default at 3V */
+#define BATT_BO_VAL ((3000 - 2400) / 40)
+#endif
- for (i = 0; i < len; i++) {
- if (i % 4 == 0)
- dprintf("\n%p:", &ptr[i]);
- dprintf(" %x", ptr[i]);
- }
- dprintf("\n");
-}
+#ifdef CONFIG_SYS_SPL_FIXED_BATT_SUPPLY
+static const int fixed_batt_supply = 1;
+#else
+static const int fixed_batt_supply;
+#endif
-//#undef CONFIG_SPL_FIXED_BATT_SUPPLY
+static struct mx28_power_regs *power_regs = (void *)MXS_POWER_BASE;
-__static void mx28_power_clock2xtal(void)
+static void mx28_power_clock2xtal(void)
{
struct mx28_clkctrl_regs *clkctrl_regs =
(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
- dprintf("%s@%d: \n", __func__, __LINE__);
/* Set XTAL as CPU reference clock */
writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
&clkctrl_regs->hw_clkctrl_clkseq_set);
}
-__static void mx28_power_clock2pll(void)
+static void mx28_power_clock2pll(void)
{
struct mx28_clkctrl_regs *clkctrl_regs =
(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
- dprintf("%s@%d: \n", __func__, __LINE__);
writel(CLKCTRL_PLL0CTRL0_POWER,
&clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
early_delay(100);
&clkctrl_regs->hw_clkctrl_clkseq_clr);
}
-__static void mx28_power_clear_auto_restart(void)
+static void mx28_power_clear_auto_restart(void)
{
struct mx28_rtc_regs *rtc_regs =
(struct mx28_rtc_regs *)MXS_RTC_BASE;
- dprintf("%s@%d: \n", __func__, __LINE__);
writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr);
while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST)
;
writel(RTC_CTRL_CLKGATE, &rtc_regs->hw_rtc_ctrl_clr);
while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE)
;
-#ifdef CONFIG_MACH_MX28EVK
+
/*
* Due to the hardware design bug of mx28 EVK-A
* we need to set the AUTO_RESTART bit.
;
while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_STALE_REGS_MASK)
;
-#endif
}
-__static void mx28_power_set_linreg(void)
+static void mx28_power_set_linreg(void)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
-
- dprintf("%s@%d: \n", __func__, __LINE__);
/* Set linear regulator 25mV below switching converter */
clrsetbits_le32(&power_regs->hw_power_vdddctrl,
POWER_VDDDCTRL_LINREG_OFFSET_MASK,
- POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_ABOVE);
+ POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
clrsetbits_le32(&power_regs->hw_power_vddactrl,
POWER_VDDACTRL_LINREG_OFFSET_MASK,
clrsetbits_le32(&power_regs->hw_power_vddioctrl,
POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
- dprintf("vddioctrl=%x\n", readl(&power_regs->hw_power_vddioctrl));
}
-__static void mx28_power_setup_5v_detect(void)
+static void mx28_power_setup_5v_detect(void)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
-
- dprintf("%s@%d: \n", __func__, __LINE__);
/* Start 5V detection */
clrsetbits_le32(&power_regs->hw_power_5vctrl,
POWER_5VCTRL_VBUSVALID_TRSH_MASK,
POWER_5VCTRL_PWRUP_VBUS_CMPS);
}
-__static void mx28_src_power_init(void)
+static void mx28_src_power_init(void)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
-
- dprintf("%s@%d: \n", __func__, __LINE__);
/* Improve efficieny and reduce transient ripple */
writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST |
POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set);
POWER_DCLIMITS_POSLIMIT_BUCK_MASK,
0x30 << POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET);
- setbits_le32(&power_regs->hw_power_battmonitor,
+ if (!fixed_batt_supply) {
+ /* FIXME: This requires the LRADC to be set up! */
+ setbits_le32(&power_regs->hw_power_battmonitor,
+ POWER_BATTMONITOR_EN_BATADJ);
+ } else {
+ clrbits_le32(&power_regs->hw_power_battmonitor,
POWER_BATTMONITOR_EN_BATADJ);
+ }
/* Increase the RCSCALE level for quick DCDC response to dynamic load */
clrsetbits_le32(&power_regs->hw_power_loopctrl,
clrsetbits_le32(&power_regs->hw_power_minpwr,
POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
-#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY
- /* 5V to battery handoff ... FIXME */
- setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
- early_delay(30);
- clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
-#endif
+
+ if (!fixed_batt_supply) {
+ /* 5V to battery handoff ... FIXME */
+ setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+ early_delay(30);
+ clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+ }
}
-__static void mx28_power_init_4p2_params(void)
+static void mx28_power_init_4p2_params(void)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
-
- dprintf("%s@%d: \n", __func__, __LINE__);
/* Setup 4P2 parameters */
clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK,
clrsetbits_le32(&power_regs->hw_power_5vctrl,
POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
- dprintf("5vctrl=%x\n", readl(&power_regs->hw_power_5vctrl));
- dprintf("dcdc4p2=%x\n", readl(&power_regs->hw_power_dcdc4p2));
}
-__static void mx28_enable_4p2_dcdc_input(int xfer)
+static void mx28_enable_4p2_dcdc_input(int xfer)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo;
uint32_t prev_5v_brnout, prev_5v_droop;
- dprintf("%s@%d: %d\n", __func__, __LINE__, xfer);
prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) &
POWER_5VCTRL_PWDN_5VBRNOUT;
prev_5v_droop = readl(&power_regs->hw_power_ctrl) &
*/
tmp = readl(&power_regs->hw_power_5vctrl);
vbus_thresh = tmp & POWER_5VCTRL_VBUSVALID_TRSH_MASK;
- vbus_5vdetect = mx28_power_vbus_valid();
+ vbus_5vdetect = tmp & POWER_5VCTRL_VBUSVALID_5VDETECT;
pwd_bo = readl(&power_regs->hw_power_minpwr) & POWER_MINPWR_PWD_BO;
&power_regs->hw_power_ctrl_clr);
if (prev_5v_droop)
- setbits_le32(&power_regs->hw_power_ctrl,
+ clrbits_le32(&power_regs->hw_power_ctrl,
POWER_CTRL_ENIRQ_VDD5V_DROOP);
else
- clrbits_le32(&power_regs->hw_power_ctrl,
+ setbits_le32(&power_regs->hw_power_ctrl,
POWER_CTRL_ENIRQ_VDD5V_DROOP);
}
-__static void mx28_power_init_4p2_regulator(void)
+static void mx28_power_init_4p2_regulator(void)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
uint32_t tmp, tmp2;
- dprintf("%s@%d: \n", __func__, __LINE__);
setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2);
writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set);
writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
}
-__static void mx28_power_init_dcdc_4p2_source(void)
+static void mx28_power_init_dcdc_4p2_source(void)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
-
- dprintf("%s@%d: \n", __func__, __LINE__);
-#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY
if (!(readl(&power_regs->hw_power_dcdc4p2) &
POWER_DCDC4P2_ENABLE_DCDC)) {
hang();
writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
&power_regs->hw_power_5vctrl_set);
}
-#else
- clrbits_le32(&power_regs->hw_power_dcdc4p2,
- POWER_DCDC4P2_ENABLE_4P2 | POWER_DCDC4P2_ENABLE_DCDC);
-#endif
}
-__static void mx28_power_enable_4p2(void)
+static void mx28_power_enable_4p2(void)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
uint32_t vdddctrl, vddactrl, vddioctrl;
uint32_t tmp;
- dprintf("%s@%d: \n", __func__, __LINE__);
vdddctrl = readl(&power_regs->hw_power_vdddctrl);
vddactrl = readl(&power_regs->hw_power_vddactrl);
vddioctrl = readl(&power_regs->hw_power_vddioctrl);
mx28_power_init_dcdc_4p2_source();
- readl(&power_regs->hw_power_vdddctrl);
- readl(&power_regs->hw_power_vddactrl);
- readl(&power_regs->hw_power_vddioctrl);
writel(vdddctrl, &power_regs->hw_power_vdddctrl);
early_delay(20);
- memdump(0x80044000, 0x60);
writel(vddactrl, &power_regs->hw_power_vddactrl);
early_delay(20);
writel(vddioctrl, &power_regs->hw_power_vddioctrl);
&power_regs->hw_power_charge_clr);
}
-__static void mx28_boot_valid_5v(void)
+static void mx28_boot_valid_5v(void)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
-
- dprintf("%s@%d: \n", __func__, __LINE__);
/*
* Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V
* disconnect event. FIXME
mx28_power_enable_4p2();
}
-void mx28_powerdown(void)
+static void mx28_powerdown(void)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
-
- dprintf("%s@%d: \n", __func__, __LINE__);
writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset);
writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
&power_regs->hw_power_reset);
}
-__static inline void mx28_handle_5v_conflict(void)
+static void mx28_handle_5v_conflict(void)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
uint32_t tmp;
- dprintf("%s@%d: \n", __func__, __LINE__);
setbits_le32(&power_regs->hw_power_vddioctrl,
POWER_VDDIOCTRL_BO_OFFSET_MASK);
}
}
-__static int mx28_get_batt_volt(void)
+static inline int mx28_get_batt_volt(void)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
uint32_t volt = readl(&power_regs->hw_power_battmonitor);
- dprintf("%s@%d: \n", __func__, __LINE__);
volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
volt *= 8;
return volt;
}
-#define __maybe_unused __attribute__((unused))
-
-__static int __maybe_unused mx28_is_batt_ready(void)
+static inline int mx28_is_batt_ready(void)
{
- dprintf("%s@%d: \n", __func__, __LINE__);
- return (mx28_get_batt_volt() >= 3600);
+ return mx28_get_batt_volt() >= 3600;
}
-__static void mx28_5v_boot(void)
+static void mx28_5v_boot(void)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
-
- dprintf("%s@%d: \n", __func__, __LINE__);
-#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY
/*
* NOTE: In original IMX-Bootlets, this also checks for VBUSVALID,
* but their implementation always returns 1 so we omit it here.
*/
- if (mx28_power_vdd5v_gt_vddio()) {
+ if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
mx28_boot_valid_5v();
return;
}
early_delay(1000);
- if (mx28_power_vdd5v_gt_vddio()) {
+ if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
mx28_boot_valid_5v();
return;
}
mx28_handle_5v_conflict();
-#else
+}
+
+static void mx28_fixed_batt_boot(void)
+{
+ writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
+
+ setbits_le32(&power_regs->hw_power_5vctrl,
+ POWER_5VCTRL_PWDN_5VBRNOUT |
+ POWER_5VCTRL_ENABLE_DCDC |
+ POWER_5VCTRL_ILIMIT_EQ_ZERO |
+ POWER_5VCTRL_PWDN_5VBRNOUT |
+ POWER_5VCTRL_PWD_CHARGE_4P2_MASK);
+
writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
- writel(1 << POWER_5VCTRL_PWD_CHARGE_4P2_OFFSET, &power_regs->hw_power_5vctrl_set);
- clrsetbits_le32(&power_regs->hw_power_vdddctrl,
- POWER_VDDDCTRL_DISABLE_FET,
- POWER_VDDDCTRL_ENABLE_LINREG |
- POWER_VDDDCTRL_DISABLE_STEPPING);
-#endif
-}
+ clrbits_le32(&power_regs->hw_power_vdddctrl,
+ POWER_VDDDCTRL_DISABLE_FET |
+ POWER_VDDDCTRL_ENABLE_LINREG |
+ POWER_VDDDCTRL_DISABLE_STEPPING);
-#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY
-#define BATT_BO_VALUE 15
-#else
-/* Brownout at 3.08V */
-#define BATT_BO_VALUE 17
-#endif
+ clrbits_le32(&power_regs->hw_power_vddactrl,
+ POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG |
+ POWER_VDDACTRL_DISABLE_STEPPING);
-__static void mx28_init_batt_bo(void)
-{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
+ clrbits_le32(&power_regs->hw_power_vddioctrl,
+ POWER_VDDIOCTRL_DISABLE_FET |
+ POWER_VDDIOCTRL_DISABLE_STEPPING);
- dprintf("%s@%d: \n", __func__, __LINE__);
-#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY
- /* Brownout at 3V */
+ /* Stop 5V detection */
+ writel(POWER_5VCTRL_PWRUP_VBUS_CMPS,
+ &power_regs->hw_power_5vctrl_clr);
+}
+
+static void mx28_init_batt_bo(void)
+{
clrsetbits_le32(&power_regs->hw_power_battmonitor,
POWER_BATTMONITOR_BRWNOUT_LVL_MASK,
- 15 << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
+ BATT_BO_VAL << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr);
writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
-#else
- clrbits_le32(&power_regs->hw_power_battmonitor,
- POWER_BATTMONITOR_PWDN_BATTBRNOUT);
- writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr);
-#endif
}
-__static void mx28_switch_vddd_to_dcdc_source(void)
+static void mx28_switch_vddd_to_dcdc_source(void)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
-
- dprintf("%s@%d: \n", __func__, __LINE__);
clrsetbits_le32(&power_regs->hw_power_vdddctrl,
POWER_VDDDCTRL_LINREG_OFFSET_MASK,
POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
POWER_VDDDCTRL_DISABLE_STEPPING);
}
-__static int __maybe_unused mx28_is_batt_good(void)
+static inline int mx28_is_batt_good(void)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
uint32_t volt;
- dprintf("%s@%d: \n", __func__, __LINE__);
- volt = readl(&power_regs->hw_power_battmonitor);
- volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
- volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
- volt *= 8;
+ volt = mx28_get_batt_volt();
if ((volt >= 2400) && (volt <= 4300))
return 1;
early_delay(500000);
- volt = readl(&power_regs->hw_power_battmonitor);
- volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
- volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
- volt *= 8;
+ volt = mx28_get_batt_volt();
if (volt >= 3500)
return 0;
return 0;
}
-__static void mx28_power_configure_power_source(void)
+static void mx28_power_configure_power_source(void)
{
- dprintf("%s@%d: \n", __func__, __LINE__);
-
mx28_src_power_init();
- mx28_5v_boot();
+
+ if (!fixed_batt_supply)
+ mx28_5v_boot();
+ else
+ mx28_fixed_batt_boot();
mx28_power_clock2pll();
mx28_init_batt_bo();
-
-#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY_
mx28_switch_vddd_to_dcdc_source();
-#endif
}
-__static void mx28_enable_output_rail_protection(void)
+static void mx28_enable_output_rail_protection(void)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
-
writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr);
-#if 0
+
setbits_le32(&power_regs->hw_power_vdddctrl,
POWER_VDDDCTRL_PWDN_BRNOUT);
setbits_le32(&power_regs->hw_power_vddactrl,
POWER_VDDACTRL_PWDN_BRNOUT);
-#endif
+
setbits_le32(&power_regs->hw_power_vddioctrl,
POWER_VDDIOCTRL_PWDN_BRNOUT);
}
-__static int mx28_get_vddio_power_source_off(void)
+static inline int mx28_get_vddio_power_source_off(void)
{
-#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY_
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
uint32_t tmp;
- dprintf("%s@%d: \n", __func__, __LINE__);
- if (mx28_power_vdd5v_gt_vddio()) {
+ if ((readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) &&
+ !(readl(&power_regs->hw_power_5vctrl) &
+ POWER_5VCTRL_ILIMIT_EQ_ZERO)) {
+
tmp = readl(&power_regs->hw_power_vddioctrl);
if (tmp & POWER_VDDIOCTRL_DISABLE_FET) {
if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
- dprintf("%s@%d: 1\n", __func__, __LINE__);
return 1;
}
}
POWER_5VCTRL_ENABLE_DCDC)) {
if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
- dprintf("%s@%d: 1\n", __func__, __LINE__);
return 1;
}
}
}
- dprintf("%s@%d: 0\n", __func__, __LINE__);
+
return 0;
-#else
- dprintf("%s@%d: 1\n", __func__, __LINE__);
- return 1;
-#endif
}
-__static int mx28_get_vddd_power_source_off(void)
+static inline int mx28_get_vddd_power_source_off(void)
{
-#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY_
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
uint32_t tmp;
- dprintf("%s@%d: \n", __func__, __LINE__);
tmp = readl(&power_regs->hw_power_vdddctrl);
if (tmp & POWER_VDDDCTRL_DISABLE_FET) {
if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
- dprintf("%s@%d: 1\n", __func__, __LINE__);
return 1;
}
}
if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
if (!(readl(&power_regs->hw_power_5vctrl) &
POWER_5VCTRL_ENABLE_DCDC)) {
- dprintf("%s@%d: 1\n", __func__, __LINE__);
return 1;
}
}
if (!(tmp & POWER_VDDDCTRL_ENABLE_LINREG)) {
if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW) {
- dprintf("%s@%d: 1\n", __func__, __LINE__);
return 1;
}
}
- dprintf("%s@%d: 0\n", __func__, __LINE__);
+
return 0;
-#else
- dprintf("%s@%d: 1\n", __func__, __LINE__);
- return 1;
-#endif
}
-__static void mx28_power_set_vddio(uint32_t new_target, uint32_t new_brownout)
+static inline int mx28_get_vdda_power_source_off(void)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
- uint32_t cur_target, diff, bo_int = 0;
- uint32_t powered_by_linreg;
-
- dprintf("%s@%d: \n", __func__, __LINE__);
- new_brownout = (new_target - new_brownout) / 25;
- if (new_brownout > 7) {
- dprintf("Bad VDDD brownout offset\n");
- new_brownout = 7;
+ uint32_t tmp;
+
+ tmp = readl(&power_regs->hw_power_vddactrl);
+ if (tmp & POWER_VDDACTRL_DISABLE_FET) {
+ if ((tmp & POWER_VDDACTRL_LINREG_OFFSET_MASK) ==
+ POWER_VDDACTRL_LINREG_OFFSET_0STEPS)
+ return 1;
}
- cur_target = readl(&power_regs->hw_power_vddioctrl);
- cur_target &= POWER_VDDIOCTRL_TRG_MASK;
- cur_target *= 50; /* 50 mV step*/
- cur_target += 2800; /* 2800 mV lowest */
+ if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+ if (!(readl(&power_regs->hw_power_5vctrl) &
+ POWER_5VCTRL_ENABLE_DCDC))
+ return 1;
+ }
- powered_by_linreg = mx28_get_vddio_power_source_off();
- if (new_target != cur_target)
- dprintf("%s@%d: stepping VDDIO from %u to %u\n", __func__, __LINE__,
- cur_target, new_target);
- else
- dprintf("%s@%d: VDDIO is at %u\n", __func__, __LINE__,
- cur_target, new_target);
- if (new_target > cur_target) {
+ if (!(tmp & POWER_VDDACTRL_ENABLE_LINREG)) {
+ if ((tmp & POWER_VDDACTRL_LINREG_OFFSET_MASK) ==
+ POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW)
+ return 1;
+ }
+ return 0;
+}
- if (powered_by_linreg) {
- bo_int = readl(&power_regs->hw_power_vddioctrl);
- clrbits_le32(&power_regs->hw_power_vddioctrl,
- POWER_CTRL_ENIRQ_VDDIO_BO);
- }
+static inline void mx28_power_set_vddx(
+ uint32_t new_target, uint32_t new_brownout,
+ uint32_t *reg, const char *name,
+ uint32_t min_trg, uint32_t max_trg,
+ uint8_t step_size,
+ uint32_t trg_mask, uint32_t trg_shift,
+ uint32_t bo_mask, uint32_t bo_shift,
+ int powered_by_linreg)
+{
+ uint32_t cur_target, cur_brownout;
+ uint32_t diff;
- setbits_le32(&power_regs->hw_power_vddioctrl,
- POWER_VDDIOCTRL_BO_OFFSET_MASK);
+ if (new_target < min_trg || new_target > max_trg)
+ new_target = (new_target > max_trg) ? max_trg : min_trg;
+
+ if (new_brownout / step_size > 7)
+ new_brownout = 7 * step_size;
+
+ cur_target = readl(reg);
+
+ cur_brownout = (cur_target & bo_mask) >> bo_shift;
+ cur_brownout *= step_size;
+
+ cur_target = (cur_target & trg_mask) >> trg_shift;
+ cur_target *= step_size;
+ cur_target += min_trg;
+ if (cur_target > max_trg)
+ cur_target = max_trg;
+
+ if (new_target == cur_target && new_brownout == cur_brownout)
+ return;
+
+ if (new_target > cur_target) {
+ setbits_le32(reg, bo_mask);
do {
if (new_target - cur_target > 100)
diff = cur_target + 100;
else
diff = new_target;
- diff -= 2800;
- diff /= 50;
+ diff -= min_trg;
+ diff /= step_size;
- clrsetbits_le32(&power_regs->hw_power_vddioctrl,
- POWER_VDDIOCTRL_TRG_MASK, diff);
- dprintf("vddioctrl=%x\n", readl(&power_regs->hw_power_vddioctrl));
+ clrsetbits_le32(reg, trg_mask, diff);
- if (powered_by_linreg)
+ if (powered_by_linreg) {
early_delay(1500);
- else {
+ } else {
while (!(readl(&power_regs->hw_power_sts) &
- POWER_STS_DC_OK))
- ;
-
+ POWER_STS_DC_OK)) {
+ }
}
- cur_target = readl(&power_regs->hw_power_vddioctrl);
- cur_target &= POWER_VDDIOCTRL_TRG_MASK;
- cur_target *= 50; /* 50 mV step*/
- cur_target += 2800; /* 2800 mV lowest */
+ cur_target = readl(reg);
+ cur_target &= trg_mask;
+ cur_target *= step_size;
+ cur_target += min_trg;
} while (new_target > cur_target);
-
- if (powered_by_linreg) {
- writel(POWER_CTRL_VDDIO_BO_IRQ,
- &power_regs->hw_power_ctrl_clr);
- if (bo_int & POWER_CTRL_ENIRQ_VDDIO_BO)
- setbits_le32(&power_regs->hw_power_vddioctrl,
- POWER_CTRL_ENIRQ_VDDIO_BO);
- dprintf("vddioctrl=%x\n", readl(&power_regs->hw_power_vddioctrl));
- }
- dprintf("%s@%d: Done\n", __func__, __LINE__);
} else {
do {
if (cur_target - new_target > 100)
else
diff = new_target;
- diff -= 2800;
- diff /= 50;
+ diff -= min_trg;
+ diff /= step_size;
- clrsetbits_le32(&power_regs->hw_power_vddioctrl,
- POWER_VDDIOCTRL_TRG_MASK, diff);
+ clrsetbits_le32(reg, trg_mask, diff);
- if (powered_by_linreg)
+ if (powered_by_linreg) {
early_delay(1500);
- else {
+ } else {
while (!(readl(&power_regs->hw_power_sts) &
- POWER_STS_DC_OK))
- ;
-
+ POWER_STS_DC_OK)) {
+ }
}
- cur_target = readl(&power_regs->hw_power_vddioctrl);
- cur_target &= POWER_VDDIOCTRL_TRG_MASK;
- cur_target *= 50; /* 50 mV step*/
- cur_target += 2800; /* 2800 mV lowest */
+ cur_target = readl(reg);
+ cur_target &= trg_mask;
+ cur_target *= step_size;
+ cur_target += min_trg;
} while (new_target < cur_target);
- dprintf("%s@%d: Done\n", __func__, __LINE__);
}
- clrsetbits_le32(&power_regs->hw_power_vddioctrl,
- POWER_VDDDCTRL_BO_OFFSET_MASK,
- new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
- dprintf("vddioctrl=%x\n", readl(&power_regs->hw_power_vddioctrl));
+ clrsetbits_le32(reg, bo_mask, (new_brownout / step_size) << bo_shift);
}
-__static void mx28_power_set_vddd(uint32_t new_target, uint32_t new_brownout)
-{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
- uint32_t cur_target, diff, bo_int = 0;
- uint32_t powered_by_linreg;
-
- dprintf("%s@%d: \n", __func__, __LINE__);
- new_brownout = (new_target - new_brownout) / 25;
- if (new_brownout > 7) {
- dprintf("Bad VDDD brownout offset\n");
- new_brownout = 7;
- }
- cur_target = readl(&power_regs->hw_power_vdddctrl);
- cur_target &= POWER_VDDDCTRL_TRG_MASK;
- cur_target *= 25; /* 25 mV step*/
- cur_target += 800; /* 800 mV lowest */
-
- powered_by_linreg = mx28_get_vddd_power_source_off();
- if (new_target != cur_target)
- dprintf("%s@%d: stepping VDDD from %u to %u\n", __func__, __LINE__,
- cur_target, new_target);
- else
- dprintf("%s@%d: VDDD is at %u\n", __func__, __LINE__,
- cur_target, new_target);
- if (new_target > cur_target) {
- if (powered_by_linreg) {
- bo_int = readl(&power_regs->hw_power_vdddctrl);
- clrbits_le32(&power_regs->hw_power_vdddctrl,
- POWER_CTRL_ENIRQ_VDDD_BO);
- }
-
- setbits_le32(&power_regs->hw_power_vdddctrl,
- POWER_VDDDCTRL_BO_OFFSET_MASK);
-
- do {
- if (new_target - cur_target > 100)
- diff = cur_target + 100;
- else
- diff = new_target;
-
- diff -= 800;
- diff /= 25;
-
- clrsetbits_le32(&power_regs->hw_power_vdddctrl,
- POWER_VDDDCTRL_TRG_MASK, diff);
-
- if (powered_by_linreg)
- early_delay(1500);
- else {
- while (!(readl(&power_regs->hw_power_sts) &
- POWER_STS_DC_OK))
- ;
+#define __mx28_power_set_vddx(trg, bo, min, max, step, reg, name, lr) \
+ mx28_power_set_vddx(trg, bo, \
+ &power_regs->hw_power_##reg##ctrl, #name, \
+ min, max, step, \
+ POWER_##name##CTRL_TRG_MASK, \
+ POWER_##name##CTRL_TRG_OFFSET, \
+ POWER_##name##CTRL_BO_OFFSET_MASK, \
+ POWER_##name##CTRL_BO_OFFSET_OFFSET, lr)
- }
+static inline void mx28_power_set_vddd(uint32_t target, uint32_t brownout)
+{
+ int powered_by_linreg = mx28_get_vddd_power_source_off();
+ uint32_t bo_int = 0;
- cur_target = readl(&power_regs->hw_power_vdddctrl);
- cur_target &= POWER_VDDDCTRL_TRG_MASK;
- cur_target *= 25; /* 25 mV step*/
- cur_target += 800; /* 800 mV lowest */
- } while (new_target > cur_target);
+ if (powered_by_linreg) {
+ bo_int = readl(&power_regs->hw_power_vdddctrl);
+ clrbits_le32(&power_regs->hw_power_vdddctrl,
+ POWER_CTRL_ENIRQ_VDDD_BO);
+ }
- if (powered_by_linreg) {
- writel(POWER_CTRL_VDDD_BO_IRQ,
- &power_regs->hw_power_ctrl_clr);
- if (bo_int & POWER_CTRL_ENIRQ_VDDD_BO)
- setbits_le32(&power_regs->hw_power_vdddctrl,
- POWER_CTRL_ENIRQ_VDDD_BO);
- }
- dprintf("%s@%d: Done\n", __func__, __LINE__);
- } else {
- do {
- if (cur_target - new_target > 100)
- diff = cur_target - 100;
- else
- diff = new_target;
+ __mx28_power_set_vddx(target, brownout, 800, 1575, 25, vddd, VDDD,
+ powered_by_linreg);
- diff -= 800;
- diff /= 25;
+ if (powered_by_linreg) {
+ writel(POWER_CTRL_VDDD_BO_IRQ,
+ &power_regs->hw_power_ctrl_clr);
+ if (bo_int & POWER_CTRL_ENIRQ_VDDD_BO)
+ setbits_le32(&power_regs->hw_power_vdddctrl,
+ POWER_CTRL_ENIRQ_VDDD_BO);
+ }
+}
- clrsetbits_le32(&power_regs->hw_power_vdddctrl,
- POWER_VDDDCTRL_TRG_MASK, diff);
+static inline void mx28_power_set_vddio(uint32_t target, uint32_t brownout)
+{
+ int powered_by_linreg = mx28_get_vddio_power_source_off();
+ uint32_t bo_int = 0;
- if (powered_by_linreg)
- early_delay(1500);
- else {
- while (!(readl(&power_regs->hw_power_sts) &
- POWER_STS_DC_OK))
- ;
+ if (powered_by_linreg) {
+ bo_int = readl(&power_regs->hw_power_vddioctrl);
+ clrbits_le32(&power_regs->hw_power_vddioctrl,
+ POWER_CTRL_ENIRQ_VDDIO_BO);
+ }
+ __mx28_power_set_vddx(target, brownout, 2800, 3600, 50, vddio, VDDIO,
+ powered_by_linreg);
+ if (powered_by_linreg) {
+ writel(POWER_CTRL_VDDIO_BO_IRQ,
+ &power_regs->hw_power_ctrl_clr);
+ if (bo_int & POWER_CTRL_ENIRQ_VDDIO_BO)
+ setbits_le32(&power_regs->hw_power_vddioctrl,
+ POWER_CTRL_ENIRQ_VDDIO_BO);
+ }
+}
- }
+static inline void mx28_power_set_vdda(uint32_t target, uint32_t brownout)
+{
+ int powered_by_linreg = mx28_get_vdda_power_source_off();
+ uint32_t bo_int = 0;
- cur_target = readl(&power_regs->hw_power_vdddctrl);
- cur_target &= POWER_VDDDCTRL_TRG_MASK;
- cur_target *= 25; /* 25 mV step*/
- cur_target += 800; /* 800 mV lowest */
- } while (new_target < cur_target);
- dprintf("%s@%d: Done\n", __func__, __LINE__);
+ if (powered_by_linreg) {
+ bo_int = readl(&power_regs->hw_power_vddioctrl);
+ clrbits_le32(&power_regs->hw_power_vddioctrl,
+ POWER_CTRL_ENIRQ_VDDIO_BO);
}
+ __mx28_power_set_vddx(target, brownout, 1500, 2275, 25, vdda, VDDA,
+ powered_by_linreg);
+ if (powered_by_linreg) {
+ writel(POWER_CTRL_VDDIO_BO_IRQ,
+ &power_regs->hw_power_ctrl_clr);
+ if (bo_int & POWER_CTRL_ENIRQ_VDDIO_BO)
+ setbits_le32(&power_regs->hw_power_vddioctrl,
+ POWER_CTRL_ENIRQ_VDDIO_BO);
+ }
+}
- clrsetbits_le32(&power_regs->hw_power_vdddctrl,
- POWER_VDDDCTRL_BO_OFFSET_MASK,
- new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
+static inline void mx28_power_set_vddmem(uint32_t target, uint32_t brownout)
+{
+ __mx28_power_set_vddx(target, brownout, 1100, 1750, 25, vddmem, VDDMEM,
+ 0);
+
+ clrbits_le32(&power_regs->hw_power_vddmemctrl,
+ POWER_VDDMEMCTRL_ENABLE_LINREG |
+ POWER_VDDMEMCTRL_ENABLE_ILIMIT);
}
void mx28_power_init(void)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
-
- dprintf("%s: %s %s\n", __func__, __DATE__, __TIME__);
- dprintf("ctrl=%x\n", readl(&power_regs->hw_power_ctrl));
- dprintf("sts=%x\n", readl(&power_regs->hw_power_sts));
-#ifdef CONFIG_SPL_FIXED_BATT_SUPPLY_
- writel(0x00018024, &power_regs->hw_power_ctrl);
- writel(0x20100592, &power_regs->hw_power_5vctrl);
- writel(0x00000018, &power_regs->hw_power_dcdc4p2);
- writel(0x0061071c, &power_regs->hw_power_vdddctrl);
- writel(0x0000270c, &power_regs->hw_power_vddactrl);
- writel(0x0004260a, &power_regs->hw_power_vddioctrl);
-#else
- dprintf("%s@%d\n", __func__, __LINE__);
mx28_power_clock2xtal();
- dprintf("%s@%d\n", __func__, __LINE__);
mx28_power_clear_auto_restart();
- dprintf("%s@%d\n", __func__, __LINE__);
mx28_power_set_linreg();
- dprintf("%s@%d\n", __func__, __LINE__);
-#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY
- mx28_power_setup_5v_detect();
- dprintf("%s@%d\n", __func__, __LINE__);
+ if (!fixed_batt_supply)
+ mx28_power_setup_5v_detect();
+
mx28_power_configure_power_source();
-// dprintf("%s@%d\n", __func__, __LINE__);
-// mx28_enable_output_rail_protection();
- dprintf("%s@%d\n", __func__, __LINE__);
+ mx28_enable_output_rail_protection();
- mx28_power_set_vddio(3300, 3150);
- dprintf("%s@%d\n", __func__, __LINE__);
+ mx28_power_set_vddio(VDDIO_VAL, VDDIO_BO_VAL);
- mx28_power_set_vddd(1500, 1325);
- dprintf("%s@%d\n", __func__, __LINE__);
+ mx28_power_set_vddd(VDDD_VAL, VDDD_BO_VAL);
- writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
- POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
- POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ |
- POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+ mx28_power_set_vdda(VDDA_VAL, VDDA_BO_VAL);
-#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY
- writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set);
-#endif
- early_delay(1000);
-#else
- dprintf("%s@%d\n", __func__, __LINE__);
- mx28_src_power_init();
- dprintf("%s@%d\n", __func__, __LINE__);
- mx28_5v_boot();
- dprintf("%s@%d\n", __func__, __LINE__);
- mx28_power_clock2pll();
- dprintf("%s@%d\n", __func__, __LINE__);
- mx28_init_batt_bo();
- dprintf("%s@%d\n", __func__, __LINE__);
- mx28_switch_vddd_to_dcdc_source();
-
- dprintf("%s@%d\n", __func__, __LINE__);
- mx28_power_set_vddio(3300, 3150);
-
- dprintf("%s@%d\n", __func__, __LINE__);
- mx28_power_set_vddd(1500, 1325);
- dprintf("%s@%d\n", __func__, __LINE__);
+ mx28_power_set_vddmem(VDDMEM_VAL, VDDMEM_BO_VAL);
writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ |
POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
-#endif
-#endif
- dprintf("sts=%x\n", readl(&power_regs->hw_power_sts));
- dprintf("vddioctrl=%x\n", readl(&power_regs->hw_power_vddioctrl));
- dprintf("vdddctrl=%x\n", readl(&power_regs->hw_power_vdddctrl));
- dprintf("5vctrl=%x\n", readl(&power_regs->hw_power_5vctrl));
- dprintf("dcdc4p2=%x\n", readl(&power_regs->hw_power_dcdc4p2));
- dprintf("%s@%d: Finished\n", __func__, __LINE__);
- memdump(0x80044000, 0x60);
+ if (!fixed_batt_supply)
+ writel(POWER_5VCTRL_PWDN_5VBRNOUT,
+ &power_regs->hw_power_5vctrl_set);
}
#ifdef CONFIG_SPL_MX28_PSWITCH_WAIT
void mx28_power_wait_pswitch(void)
{
- struct mx28_power_regs *power_regs =
- (struct mx28_power_regs *)MXS_POWER_BASE;
-
- dprintf("%s@%d: \n", __func__, __LINE__);
while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK))
;
}