arm/davinci/da850: add uart0 pinmux
[oweals/u-boot.git] / arch / arm / cpu / arm926ejs / mx28 / spl_power_init.c
index dfb62eb9aa3feb323718d2fead7b762447feb070..4b09b0c3ba80353d99d7fe02a02460057717afa8 100644 (file)
@@ -45,11 +45,11 @@ void mx28_power_clock2pll(void)
        struct mx28_clkctrl_regs *clkctrl_regs =
                (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
 
-       writel(CLKCTRL_PLL0CTRL0_POWER,
-               &clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
+       setbits_le32(&clkctrl_regs->hw_clkctrl_pll0ctrl0,
+                       CLKCTRL_PLL0CTRL0_POWER);
        early_delay(100);
-       writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
-               &clkctrl_regs->hw_clkctrl_clkseq_clr);
+       setbits_le32(&clkctrl_regs->hw_clkctrl_clkseq,
+                       CLKCTRL_CLKSEQ_BYPASS_CPU);
 }
 
 void mx28_power_clear_auto_restart(void)
@@ -104,6 +104,62 @@ void mx28_power_set_linreg(void)
                        POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
 }
 
+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);
+       volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
+       volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
+       volt *= 8;
+       return volt;
+}
+
+int mx28_is_batt_ready(void)
+{
+       return (mx28_get_batt_volt() >= 3600);
+}
+
+int mx28_is_batt_good(void)
+{
+       struct mx28_power_regs *power_regs =
+               (struct mx28_power_regs *)MXS_POWER_BASE;
+       uint32_t volt = mx28_get_batt_volt();
+
+       if ((volt >= 2400) && (volt <= 4300))
+               return 1;
+
+       clrsetbits_le32(&power_regs->hw_power_5vctrl,
+               POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+               0x3 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+       writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+               &power_regs->hw_power_5vctrl_clr);
+
+       clrsetbits_le32(&power_regs->hw_power_charge,
+               POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
+               POWER_CHARGE_STOP_ILIMIT_10MA | 0x3);
+
+       writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_clr);
+       writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+               &power_regs->hw_power_5vctrl_clr);
+
+       early_delay(500000);
+
+       volt = mx28_get_batt_volt();
+
+       if (volt >= 3500)
+               return 0;
+
+       if (volt >= 2400)
+               return 1;
+
+       writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
+               &power_regs->hw_power_charge_clr);
+       writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
+
+       return 0;
+}
+
 void mx28_power_setup_5v_detect(void)
 {
        struct mx28_power_regs *power_regs =
@@ -399,9 +455,14 @@ void mx28_power_enable_4p2(void)
        mx28_power_init_4p2_regulator();
 
        /* Shutdown battery (none present) */
-       clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
-       writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
-       writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, &power_regs->hw_power_ctrl_clr);
+       if (!mx28_is_batt_ready()) {
+               clrbits_le32(&power_regs->hw_power_dcdc4p2,
+                               POWER_DCDC4P2_BO_MASK);
+               writel(POWER_CTRL_DCDC4P2_BO_IRQ,
+                               &power_regs->hw_power_ctrl_clr);
+               writel(POWER_CTRL_ENIRQ_DCDC4P2_BO,
+                               &power_regs->hw_power_ctrl_clr);
+       }
 
        mx28_power_init_dcdc_4p2_source();
 
@@ -459,6 +520,50 @@ void mx28_powerdown(void)
                &power_regs->hw_power_reset);
 }
 
+void mx28_batt_boot(void)
+{
+       struct mx28_power_regs *power_regs =
+               (struct mx28_power_regs *)MXS_POWER_BASE;
+
+       clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
+       clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_ENABLE_DCDC);
+
+       clrbits_le32(&power_regs->hw_power_dcdc4p2,
+                       POWER_DCDC4P2_ENABLE_DCDC | POWER_DCDC4P2_ENABLE_4P2);
+       writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_clr);
+
+       /* 5V to battery handoff. */
+       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);
+
+       writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, &power_regs->hw_power_ctrl_clr);
+
+       clrsetbits_le32(&power_regs->hw_power_minpwr,
+                       POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
+
+       mx28_power_set_linreg();
+
+       clrbits_le32(&power_regs->hw_power_vdddctrl,
+               POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG);
+
+       clrbits_le32(&power_regs->hw_power_vddactrl,
+               POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG);
+
+       clrbits_le32(&power_regs->hw_power_vddioctrl,
+               POWER_VDDIOCTRL_DISABLE_FET);
+
+       setbits_le32(&power_regs->hw_power_5vctrl,
+               POWER_5VCTRL_PWD_CHARGE_4P2_MASK);
+
+       setbits_le32(&power_regs->hw_power_5vctrl,
+               POWER_5VCTRL_ENABLE_DCDC);
+
+       clrsetbits_le32(&power_regs->hw_power_5vctrl,
+               POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+               0x8 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+}
+
 void mx28_handle_5v_conflict(void)
 {
        struct mx28_power_regs *power_regs =
@@ -483,23 +588,12 @@ void mx28_handle_5v_conflict(void)
                        mx28_powerdown();
                        break;
                }
-       }
-}
-
-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);
-       volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
-       volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
-       volt *= 8;
-       return volt;
-}
 
-int mx28_is_batt_ready(void)
-{
-       return (mx28_get_batt_volt() >= 3600);
+               if (tmp & POWER_STS_PSWITCH_MASK) {
+                       mx28_batt_boot();
+                       break;
+               }
+       }
 }
 
 void mx28_5v_boot(void)
@@ -553,62 +647,44 @@ void mx28_switch_vddd_to_dcdc_source(void)
                POWER_VDDDCTRL_DISABLE_STEPPING);
 }
 
-int mx28_is_batt_good(void)
+void mx28_power_configure_power_source(void)
 {
+       int batt_ready, batt_good;
        struct mx28_power_regs *power_regs =
                (struct mx28_power_regs *)MXS_POWER_BASE;
-       uint32_t volt;
-
-       volt = readl(&power_regs->hw_power_battmonitor);
-       volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
-       volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
-       volt *= 8;
-
-       if ((volt >= 2400) && (volt <= 4300))
-               return 1;
-
-       clrsetbits_le32(&power_regs->hw_power_5vctrl,
-               POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
-               0x3 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
-       writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
-               &power_regs->hw_power_5vctrl_clr);
-
-       clrsetbits_le32(&power_regs->hw_power_charge,
-               POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
-               POWER_CHARGE_STOP_ILIMIT_10MA | 0x3);
-
-       writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_clr);
-       writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
-               &power_regs->hw_power_5vctrl_clr);
-
-       early_delay(500000);
-
-       volt = readl(&power_regs->hw_power_battmonitor);
-       volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
-       volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
-       volt *= 8;
-
-       if (volt >= 3500)
-               return 0;
+       struct mx28_lradc_regs *lradc_regs =
+               (struct mx28_lradc_regs *)MXS_LRADC_BASE;
 
-       if (volt >= 2400)
-               return 1;
-
-       writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
-               &power_regs->hw_power_charge_clr);
-       writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
+       mx28_src_power_init();
 
-       return 0;
-}
+       batt_ready = mx28_is_batt_ready();
 
-void mx28_power_configure_power_source(void)
-{
-       mx28_src_power_init();
+       if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+               batt_good = mx28_is_batt_good();
+               if (batt_ready) {
+                       /* 5V source detected, good battery detected. */
+                       mx28_batt_boot();
+               } else {
+                       if (batt_good) {
+                               /* 5V source detected, low battery detceted. */
+                       } else {
+                               /* 5V source detected, bad battery detected. */
+                               writel(LRADC_CONVERSION_AUTOMATIC,
+                                       &lradc_regs->hw_lradc_conversion_clr);
+                               clrbits_le32(&power_regs->hw_power_battmonitor,
+                                       POWER_BATTMONITOR_BATT_VAL_MASK);
+                       }
+                       mx28_5v_boot();
+               }
+       } else {
+               /* 5V not detected, booting from battery. */
+               mx28_batt_boot();
+       }
 
-       mx28_5v_boot();
        mx28_power_clock2pll();
 
        mx28_init_batt_bo();
+
        mx28_switch_vddd_to_dcdc_source();
 }