]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - arch/arm/cpu/arm926ejs/mxs/spl_power_init.c
mtd: resync with Linux-3.7.1
[karo-tx-uboot.git] / arch / arm / cpu / arm926ejs / mxs / spl_power_init.c
index 4b917bd186df4ea62651690c1a99c91ff2b0118a..287c698ff7994fe271d4f3e63c15d5fec94f3534 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "mxs_init.h"
 
-void mxs_power_clock2xtal(void)
+static void mxs_power_clock2xtal(void)
 {
        struct mxs_clkctrl_regs *clkctrl_regs =
                (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
@@ -40,7 +40,7 @@ void mxs_power_clock2xtal(void)
                &clkctrl_regs->hw_clkctrl_clkseq_set);
 }
 
-void mxs_power_clock2pll(void)
+static void mxs_power_clock2pll(void)
 {
        struct mxs_clkctrl_regs *clkctrl_regs =
                (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
@@ -52,7 +52,7 @@ void mxs_power_clock2pll(void)
                        CLKCTRL_CLKSEQ_BYPASS_CPU);
 }
 
-void mxs_power_clear_auto_restart(void)
+static void mxs_power_clear_auto_restart(void)
 {
        struct mxs_rtc_regs *rtc_regs =
                (struct mxs_rtc_regs *)MXS_RTC_BASE;
@@ -85,7 +85,7 @@ void mxs_power_clear_auto_restart(void)
                ;
 }
 
-void mxs_power_set_linreg(void)
+static void mxs_power_set_linreg(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -104,7 +104,7 @@ void mxs_power_set_linreg(void)
                        POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
 }
 
-int mxs_get_batt_volt(void)
+static int mxs_get_batt_volt(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -115,12 +115,12 @@ int mxs_get_batt_volt(void)
        return volt;
 }
 
-int mxs_is_batt_ready(void)
+static int mxs_is_batt_ready(void)
 {
        return (mxs_get_batt_volt() >= 3600);
 }
 
-int mxs_is_batt_good(void)
+static int mxs_is_batt_good(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -160,7 +160,7 @@ int mxs_is_batt_good(void)
        return 0;
 }
 
-void mxs_power_setup_5v_detect(void)
+static void mxs_power_setup_5v_detect(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -172,7 +172,7 @@ void mxs_power_setup_5v_detect(void)
                        POWER_5VCTRL_PWRUP_VBUS_CMPS);
 }
 
-void mxs_src_power_init(void)
+static void mxs_src_power_init(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -203,7 +203,7 @@ void mxs_src_power_init(void)
        clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
 }
 
-void mxs_power_init_4p2_params(void)
+static void mxs_power_init_4p2_params(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -227,7 +227,7 @@ void mxs_power_init_4p2_params(void)
                0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
 }
 
-void mxs_enable_4p2_dcdc_input(int xfer)
+static void mxs_enable_4p2_dcdc_input(int xfer)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -323,7 +323,7 @@ void mxs_enable_4p2_dcdc_input(int xfer)
                                POWER_CTRL_ENIRQ_VDD5V_DROOP);
 }
 
-void mxs_power_init_4p2_regulator(void)
+static void mxs_power_init_4p2_regulator(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -407,7 +407,7 @@ void mxs_power_init_4p2_regulator(void)
        writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
 }
 
-void mxs_power_init_dcdc_4p2_source(void)
+static void mxs_power_init_dcdc_4p2_source(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -429,7 +429,7 @@ void mxs_power_init_dcdc_4p2_source(void)
        }
 }
 
-void mxs_power_enable_4p2(void)
+static void mxs_power_enable_4p2(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -488,7 +488,7 @@ void mxs_power_enable_4p2(void)
                        &power_regs->hw_power_charge_clr);
 }
 
-void mxs_boot_valid_5v(void)
+static void mxs_boot_valid_5v(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -511,7 +511,7 @@ void mxs_boot_valid_5v(void)
        mxs_power_enable_4p2();
 }
 
-void mxs_powerdown(void)
+static void mxs_powerdown(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -520,7 +520,7 @@ void mxs_powerdown(void)
                &power_regs->hw_power_reset);
 }
 
-void mxs_batt_boot(void)
+static void mxs_batt_boot(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -564,7 +564,7 @@ void mxs_batt_boot(void)
                0x8 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
 }
 
-void mxs_handle_5v_conflict(void)
+static void mxs_handle_5v_conflict(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -600,7 +600,7 @@ void mxs_handle_5v_conflict(void)
        }
 }
 
-void mxs_5v_boot(void)
+static void mxs_5v_boot(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -623,7 +623,7 @@ void mxs_5v_boot(void)
        mxs_handle_5v_conflict();
 }
 
-void mxs_init_batt_bo(void)
+static void mxs_init_batt_bo(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -637,7 +637,7 @@ void mxs_init_batt_bo(void)
        writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
 }
 
-void mxs_switch_vddd_to_dcdc_source(void)
+static void mxs_switch_vddd_to_dcdc_source(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -651,7 +651,7 @@ void mxs_switch_vddd_to_dcdc_source(void)
                POWER_VDDDCTRL_DISABLE_STEPPING);
 }
 
-void mxs_power_configure_power_source(void)
+static void mxs_power_configure_power_source(void)
 {
        int batt_ready, batt_good;
        struct mxs_power_regs *power_regs =
@@ -689,7 +689,7 @@ void mxs_power_configure_power_source(void)
        mxs_switch_vddd_to_dcdc_source();
 }
 
-void mxs_enable_output_rail_protection(void)
+static void mxs_enable_output_rail_protection(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -707,7 +707,7 @@ void mxs_enable_output_rail_protection(void)
                        POWER_VDDIOCTRL_PWDN_BRNOUT);
 }
 
-int mxs_get_vddio_power_source_off(void)
+static int mxs_get_vddio_power_source_off(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -735,7 +735,7 @@ int mxs_get_vddio_power_source_off(void)
 
 }
 
-int mxs_get_vddd_power_source_off(void)
+static int mxs_get_vddd_power_source_off(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
@@ -766,212 +766,138 @@ int mxs_get_vddd_power_source_off(void)
        return 0;
 }
 
-void mxs_power_set_vddio(uint32_t new_target, uint32_t new_brownout)
+struct mxs_vddx_cfg {
+       uint32_t                *reg;
+       uint8_t                 step_mV;
+       uint16_t                lowest_mV;
+       int                     (*powered_by_linreg)(void);
+       uint32_t                trg_mask;
+       uint32_t                bo_irq;
+       uint32_t                bo_enirq;
+       uint32_t                bo_offset_mask;
+       uint32_t                bo_offset_offset;
+};
+
+static const struct mxs_vddx_cfg mxs_vddio_cfg = {
+       .reg                    = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
+                                       hw_power_vddioctrl),
+       .step_mV                = 50,
+       .lowest_mV              = 2800,
+       .powered_by_linreg      = mxs_get_vddio_power_source_off,
+       .trg_mask               = POWER_VDDIOCTRL_TRG_MASK,
+       .bo_irq                 = POWER_CTRL_VDDIO_BO_IRQ,
+       .bo_enirq               = POWER_CTRL_ENIRQ_VDDIO_BO,
+       .bo_offset_mask         = POWER_VDDIOCTRL_BO_OFFSET_MASK,
+       .bo_offset_offset       = POWER_VDDIOCTRL_BO_OFFSET_OFFSET,
+};
+
+static const struct mxs_vddx_cfg mxs_vddd_cfg = {
+       .reg                    = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
+                                       hw_power_vdddctrl),
+       .step_mV                = 25,
+       .lowest_mV              = 800,
+       .powered_by_linreg      = mxs_get_vddd_power_source_off,
+       .trg_mask               = POWER_VDDDCTRL_TRG_MASK,
+       .bo_irq                 = POWER_CTRL_VDDD_BO_IRQ,
+       .bo_enirq               = POWER_CTRL_ENIRQ_VDDD_BO,
+       .bo_offset_mask         = POWER_VDDDCTRL_BO_OFFSET_MASK,
+       .bo_offset_offset       = POWER_VDDDCTRL_BO_OFFSET_OFFSET,
+};
+
+static void mxs_power_set_vddx(const struct mxs_vddx_cfg *cfg,
+                               uint32_t new_target, uint32_t new_brownout)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
        uint32_t cur_target, diff, bo_int = 0;
        uint32_t powered_by_linreg = 0;
+       int adjust_up, tmp;
 
-       new_brownout = (new_target - new_brownout + 25) / 50;
+       new_brownout = DIV_ROUND(new_target - new_brownout, cfg->step_mV);
 
-       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(cfg->reg);
+       cur_target &= cfg->trg_mask;
+       cur_target *= cfg->step_mV;
+       cur_target += cfg->lowest_mV;
 
-       powered_by_linreg = mxs_get_vddio_power_source_off();
-       if (new_target > cur_target) {
+       adjust_up = new_target > cur_target;
+       powered_by_linreg = cfg->powered_by_linreg();
 
+       if (adjust_up) {
                if (powered_by_linreg) {
-                       bo_int = readl(&power_regs->hw_power_vddioctrl);
-                       clrbits_le32(&power_regs->hw_power_vddioctrl,
-                                       POWER_CTRL_ENIRQ_VDDIO_BO);
+                       bo_int = readl(cfg->reg);
+                       clrbits_le32(cfg->reg, cfg->bo_enirq);
                }
+               setbits_le32(cfg->reg, cfg->bo_offset_mask);
+       }
 
-               setbits_le32(&power_regs->hw_power_vddioctrl,
-                               POWER_VDDIOCTRL_BO_OFFSET_MASK);
-               do {
-                       if (new_target - cur_target > 100)
+       do {
+               if (abs(new_target - cur_target) > 100) {
+                       if (adjust_up)
                                diff = cur_target + 100;
                        else
-                               diff = new_target;
-
-                       diff -= 2800;
-                       diff /= 50;
-
-                       clrsetbits_le32(&power_regs->hw_power_vddioctrl,
-                               POWER_VDDIOCTRL_TRG_MASK, diff);
-
-                       if (powered_by_linreg ||
-                               (readl(&power_regs->hw_power_sts) &
-                                       POWER_STS_VDD5V_GT_VDDIO))
-                               early_delay(500);
-                       else {
-                               while (!(readl(&power_regs->hw_power_sts) &
-                                       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 */
-               } 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);
-               }
-       } else {
-               do {
-                       if (cur_target - new_target > 100)
                                diff = cur_target - 100;
-                       else
-                               diff = new_target;
-
-                       diff -= 2800;
-                       diff /= 50;
-
-                       clrsetbits_le32(&power_regs->hw_power_vddioctrl,
-                               POWER_VDDIOCTRL_TRG_MASK, diff);
-
-                       if (powered_by_linreg ||
-                               (readl(&power_regs->hw_power_sts) &
-                                       POWER_STS_VDD5V_GT_VDDIO))
-                               early_delay(500);
-                       else {
-                               while (!(readl(&power_regs->hw_power_sts) &
-                                       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 */
-               } while (new_target < cur_target);
-       }
-
-       clrsetbits_le32(&power_regs->hw_power_vddioctrl,
-                       POWER_VDDIOCTRL_BO_OFFSET_MASK,
-                       new_brownout << POWER_VDDIOCTRL_BO_OFFSET_OFFSET);
-}
-
-void mxs_power_set_vddd(uint32_t new_target, uint32_t new_brownout)
-{
-       struct mxs_power_regs *power_regs =
-               (struct mxs_power_regs *)MXS_POWER_BASE;
-       uint32_t cur_target, diff, bo_int = 0;
-       uint32_t powered_by_linreg = 0;
-
-       new_brownout = (new_target - new_brownout + 12) / 25;
-
-       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 = mxs_get_vddd_power_source_off();
-       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);
+               } else {
+                       diff = new_target;
                }
 
-               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;
+               diff -= cfg->lowest_mV;
+               diff /= cfg->step_mV;
 
-                       clrsetbits_le32(&power_regs->hw_power_vdddctrl,
-                               POWER_VDDDCTRL_TRG_MASK, diff);
-
-                       if (powered_by_linreg ||
-                               (readl(&power_regs->hw_power_sts) &
-                                       POWER_STS_VDD5V_GT_VDDIO))
-                               early_delay(500);
-                       else {
-                               while (!(readl(&power_regs->hw_power_sts) &
-                                       POWER_STS_DC_OK))
-                                       ;
+               clrsetbits_le32(cfg->reg, cfg->trg_mask, diff);
 
+               if (powered_by_linreg ||
+                       (readl(&power_regs->hw_power_sts) &
+                               POWER_STS_VDD5V_GT_VDDIO))
+                       early_delay(500);
+               else {
+                       for (;;) {
+                               tmp = readl(&power_regs->hw_power_sts);
+                               if (tmp & POWER_STS_DC_OK)
+                                       break;
                        }
-
-                       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) {
-                       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);
                }
-       } else {
-               do {
-                       if (cur_target - new_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 ||
-                               (readl(&power_regs->hw_power_sts) &
-                                       POWER_STS_VDD5V_GT_VDDIO))
-                               early_delay(500);
-                       else {
-                               while (!(readl(&power_regs->hw_power_sts) &
-                                       POWER_STS_DC_OK))
-                                       ;
 
-                       }
+               cur_target = readl(cfg->reg);
+               cur_target &= cfg->trg_mask;
+               cur_target *= cfg->step_mV;
+               cur_target += cfg->lowest_mV;
+       } while (new_target > cur_target);
 
-                       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 (adjust_up && powered_by_linreg) {
+               writel(cfg->bo_irq, &power_regs->hw_power_ctrl_clr);
+               if (bo_int & cfg->bo_enirq)
+                       setbits_le32(cfg->reg, cfg->bo_enirq);
        }
 
-       clrsetbits_le32(&power_regs->hw_power_vdddctrl,
-                       POWER_VDDDCTRL_BO_OFFSET_MASK,
-                       new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
+       clrsetbits_le32(cfg->reg, cfg->bo_offset_mask,
+                       new_brownout << cfg->bo_offset_offset);
 }
 
-void mxs_setup_batt_detect(void)
+static void mxs_setup_batt_detect(void)
 {
        mxs_lradc_init();
        mxs_lradc_enable_batt_measurement();
        early_delay(10);
 }
 
+static void mxs_ungate_power(void)
+{
+#ifdef CONFIG_MX23
+       struct mxs_power_regs *power_regs =
+               (struct mxs_power_regs *)MXS_POWER_BASE;
+
+       writel(POWER_CTRL_CLKGATE, &power_regs->hw_power_ctrl_clr);
+#endif
+}
+
 void mxs_power_init(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
 
+       mxs_ungate_power();
+
        mxs_power_clock2xtal();
        mxs_power_clear_auto_restart();
        mxs_power_set_linreg();
@@ -982,9 +908,8 @@ void mxs_power_init(void)
        mxs_power_configure_power_source();
        mxs_enable_output_rail_protection();
 
-       mxs_power_set_vddio(3300, 3150);
-
-       mxs_power_set_vddd(1350, 1200);
+       mxs_power_set_vddx(&mxs_vddio_cfg, 3300, 3150);
+       mxs_power_set_vddx(&mxs_vddd_cfg, 1500, 1000);
 
        writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
                POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
@@ -996,7 +921,7 @@ void mxs_power_init(void)
        early_delay(1000);
 }
 
-#ifdef CONFIG_SPL_MX28_PSWITCH_WAIT
+#ifdef CONFIG_SPL_MXS_PSWITCH_WAIT
 void mxs_power_wait_pswitch(void)
 {
        struct mxs_power_regs *power_regs =