]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
omap2 clock: Standardize DPLL rate recalculation with struct dpll_data
authorPaul Walmsley <paul@pwsan.com>
Mon, 27 Aug 2007 08:39:21 +0000 (02:39 -0600)
committerTony Lindgren <tony@atomide.com>
Fri, 31 Aug 2007 18:14:44 +0000 (11:14 -0700)
Introduce a new data structure, struct dpll_data, that contains DPLL
multiplier, divider, and autoidle information.  Update existing DPLL code
to use struct dpll_data.  The goal here is to set up something that will be
usable for OMAP3430 clock tree.  Note that this does not affect the SRAM DPLL
assembly code - the DPLL register addresses are still hard-coded there.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
include/asm-arm/arch-omap/clock.h

index 0440048c51488b4d76357756640acff2c285373a..62c0a8c1efeebe3b9de2479d39e67c7bed662bdf 100644 (file)
@@ -113,20 +113,38 @@ static void omap2_init_clksel_parent(struct clk *clk)
        return;
 }
 
-static u32 omap2_get_dpll_rate(struct clk * tclk)
+/* Returns the DPLL rate */
+static u32 omap2_get_dpll_rate(struct clk *clk)
 {
        long long dpll_clk;
-       int dpll_mult, dpll_div, amult;
-       u32 dpll;
+       u32 dpll_mult, dpll_div, dpll;
+       const struct dpll_data *dd;
 
-       dpll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
+       dd = clk->dpll_data;
+       /* REVISIT: What do we return on error? */
+       if (!dd)
+               return 0;
+
+       dpll = cm_read_reg(dd->mult_div1_reg);
+       dpll_mult = dpll & dd->mult_mask;
+       dpll_mult >>= mask_to_shift(dd->mult_mask);
+       dpll_div = dpll & dd->div1_mask;
+       dpll_div >>= mask_to_shift(dd->div1_mask);
 
-       dpll_mult = dpll & OMAP24XX_DPLL_MULT_MASK;
-       dpll_mult >>= OMAP24XX_DPLL_MULT_SHIFT;         /* 10 bits */
-       dpll_div = dpll & OMAP24XX_DPLL_DIV_MASK;
-       dpll_div >>= OMAP24XX_DPLL_DIV_SHIFT;           /* 4 bits */
-       dpll_clk = (long long)tclk->parent->rate * dpll_mult;
+       dpll_clk = (long long)clk->parent->rate * dpll_mult;
        do_div(dpll_clk, dpll_div + 1);
+
+       return dpll_clk;
+}
+
+/* This actually returns the rate of core_ck, not dpll_ck. */
+static u32 omap2_get_dpll_rate_24xx(struct clk *tclk)
+{
+       long long dpll_clk;
+       u8 amult;
+
+       dpll_clk = omap2_get_dpll_rate(tclk);
+
        amult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
        amult &= OMAP24XX_CORE_CLK_SRC_MASK;
        dpll_clk *= amult;
@@ -397,7 +415,7 @@ static u32 omap2_dpll_round_rate(unsigned long target_rate)
 
 static void omap2_dpll_recalc(struct clk *clk)
 {
-       clk->rate = omap2_get_dpll_rate(clk);
+       clk->rate = omap2_get_dpll_rate_24xx(clk);
 
        propagate_rate(clk);
 }
@@ -560,10 +578,11 @@ static int omap2_reprogram_dpll(struct clk * clk, unsigned long rate)
        u32 flags, cur_rate, low, mult, div, valid_rate, done_rate;
        u32 bypass = 0;
        struct prcm_config tmpset;
+       const struct dpll_data *dd;
        int ret = -EINVAL;
 
        local_irq_save(flags);
-       cur_rate = omap2_get_dpll_rate(&dpll_ck);
+       cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
        mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
        mult &= OMAP24XX_CORE_CLK_SRC_MASK;
 
@@ -581,9 +600,13 @@ static int omap2_reprogram_dpll(struct clk * clk, unsigned long rate)
                else
                        low = curr_prcm_set->dpll_speed / 2;
 
-               tmpset.cm_clksel1_pll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
-               tmpset.cm_clksel1_pll &= ~(OMAP24XX_DPLL_MULT_MASK |
-                                          OMAP24XX_DPLL_DIV_MASK);
+               dd = clk->dpll_data;
+               if (!dd)
+                       goto dpll_exit;
+
+               tmpset.cm_clksel1_pll = cm_read_reg(dd->mult_div1_reg);
+               tmpset.cm_clksel1_pll &= ~(dd->mult_mask |
+                                          dd->div1_mask);
                div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
                tmpset.cm_clksel2_pll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
                tmpset.cm_clksel2_pll &= ~OMAP24XX_CORE_CLK_SRC_MASK;
@@ -596,8 +619,8 @@ static int omap2_reprogram_dpll(struct clk * clk, unsigned long rate)
                        mult = (rate / 1000000);
                        done_rate = CORE_CLK_SRC_DPLL;
                }
-               tmpset.cm_clksel1_pll |= (div << OMAP24XX_DPLL_DIV_SHIFT);
-               tmpset.cm_clksel1_pll |= (mult << OMAP24XX_DPLL_MULT_SHIFT);
+               tmpset.cm_clksel1_pll |= (div << mask_to_shift(dd->mult_mask));
+               tmpset.cm_clksel1_pll |= (mult << mask_to_shift(dd->div1_mask));
 
                /* Worst case */
                tmpset.base_sdrc_rfr = V24XX_SDRC_RFR_CTRL_BYPASS;
@@ -951,7 +974,7 @@ static int omap2_select_table_rate(struct clk * clk, unsigned long rate)
        }
 
        curr_prcm_set = prcm;
-       cur_rate = omap2_get_dpll_rate(&dpll_ck);
+       cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
 
        if (prcm->dpll_speed == cur_rate / 2) {
                omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
@@ -1138,7 +1161,7 @@ int __init omap2_clk_init(void)
        }
 
        /* Check the MPU rate set by bootloader */
-       clkrate = omap2_get_dpll_rate(&dpll_ck);
+       clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
        for (prcm = rate_table; prcm->mpu_speed; prcm++) {
                if (!(prcm->flags & cpu_mask))
                        continue;
index 4251afc165031872070c994adbcb88ffc30739e5..808ca43a3f2b95b992508eacde71b8712f60872c 100644 (file)
@@ -632,9 +632,19 @@ static struct clk alt_ck = {               /* Typical 54M or 48M, may not exist */
 /* REVISIT: Rate changes on dpll_ck trigger a full set change. ...
  * deal with this
  */
+
+static const struct dpll_data dpll_dd = {
+       .mult_div1_reg          = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+       .mult_mask              = OMAP24XX_DPLL_MULT_MASK,
+       .div1_mask              = OMAP24XX_DPLL_DIV_MASK,
+       .auto_idle_mask         = OMAP24XX_AUTO_DPLL_MASK,
+       .auto_idle_val          = 0x3, /* stop DPLL upon idle */
+};
+
 static struct clk dpll_ck = {
        .name           = "dpll_ck",
        .parent         = &sys_ck,              /* Can be func_32k also */
+       .dpll_data      = &dpll_dd,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                RATE_PROPAGATES | ALWAYS_ENABLED,
        .recalc         = &omap2_dpll_recalc,
index 67b6826d352ba31020342645e8928a76f28b0a9e..85de61d19919dff0b948b9c50708661e2dbbd69e 100644 (file)
@@ -29,6 +29,14 @@ struct clksel {
        const struct clksel_rate *rates;
 };
 
+struct dpll_data {
+       void __iomem            *mult_div1_reg;
+       u32                     mult_mask;
+       u32                     div1_mask;
+       u32                     auto_idle_mask;
+       u8                      auto_idle_val;
+};
+
 #endif
 
 struct clk {
@@ -53,6 +61,7 @@ struct clk {
        void __iomem            *clksel_reg;
        u32                     clksel_mask;
        const struct clksel     *clksel;
+       const struct dpll_data  *dpll_data;
 #else
        __u8                    rate_offset;
        __u8                    src_offset;