clk: meson: add fractional part of meson8b fixed_pll
[linux-2.6-microblaze.git] / drivers / clk / meson / clk-mpll.c
index 5144360..0df1227 100644 (file)
 #define N2_MIN 4
 #define N2_MAX 511
 
-#define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw)
+static inline struct meson_clk_mpll_data *
+meson_clk_mpll_data(struct clk_regmap *clk)
+{
+       return (struct meson_clk_mpll_data *)clk->data;
+}
 
 static long rate_from_params(unsigned long parent_rate,
-                                     unsigned long sdm,
-                                     unsigned long n2)
+                            unsigned int sdm,
+                            unsigned int n2)
 {
        unsigned long divisor = (SDM_DEN * n2) + sdm;
 
@@ -84,8 +88,8 @@ static long rate_from_params(unsigned long parent_rate,
 
 static void params_from_rate(unsigned long requested_rate,
                             unsigned long parent_rate,
-                            unsigned long *sdm,
-                            unsigned long *n2)
+                            unsigned int *sdm,
+                            unsigned int *n2)
 {
        uint64_t div = parent_rate;
        unsigned long rem = do_div(div, requested_rate);
@@ -105,31 +109,23 @@ static void params_from_rate(unsigned long requested_rate,
 static unsigned long mpll_recalc_rate(struct clk_hw *hw,
                unsigned long parent_rate)
 {
-       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
-       struct parm *p;
-       unsigned long reg, sdm, n2;
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk);
+       unsigned int sdm, n2;
        long rate;
 
-       p = &mpll->sdm;
-       reg = readl(mpll->base + p->reg_off);
-       sdm = PARM_GET(p->width, p->shift, reg);
-
-       p = &mpll->n2;
-       reg = readl(mpll->base + p->reg_off);
-       n2 = PARM_GET(p->width, p->shift, reg);
+       sdm = meson_parm_read(clk->map, &mpll->sdm);
+       n2 = meson_parm_read(clk->map, &mpll->n2);
 
        rate = rate_from_params(parent_rate, sdm, n2);
-       if (rate < 0)
-               return 0;
-
-       return rate;
+       return rate < 0 ? 0 : rate;
 }
 
 static long mpll_round_rate(struct clk_hw *hw,
                            unsigned long rate,
                            unsigned long *parent_rate)
 {
-       unsigned long sdm, n2;
+       unsigned int sdm, n2;
 
        params_from_rate(rate, *parent_rate, &sdm, &n2);
        return rate_from_params(*parent_rate, sdm, n2);
@@ -139,9 +135,9 @@ static int mpll_set_rate(struct clk_hw *hw,
                         unsigned long rate,
                         unsigned long parent_rate)
 {
-       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
-       struct parm *p;
-       unsigned long reg, sdm, n2;
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk);
+       unsigned int sdm, n2;
        unsigned long flags = 0;
 
        params_from_rate(rate, parent_rate, &sdm, &n2);
@@ -151,97 +147,36 @@ static int mpll_set_rate(struct clk_hw *hw,
        else
                __acquire(mpll->lock);
 
-       p = &mpll->sdm;
-       reg = readl(mpll->base + p->reg_off);
-       reg = PARM_SET(p->width, p->shift, reg, sdm);
-       writel(reg, mpll->base + p->reg_off);
-
-       p = &mpll->sdm_en;
-       reg = readl(mpll->base + p->reg_off);
-       reg = PARM_SET(p->width, p->shift, reg, 1);
-       writel(reg, mpll->base + p->reg_off);
-
-       p = &mpll->ssen;
-       if (p->width != 0) {
-               reg = readl(mpll->base + p->reg_off);
-               reg = PARM_SET(p->width, p->shift, reg, 1);
-               writel(reg, mpll->base + p->reg_off);
-       }
-
-       p = &mpll->n2;
-       reg = readl(mpll->base + p->reg_off);
-       reg = PARM_SET(p->width, p->shift, reg, n2);
-       writel(reg, mpll->base + p->reg_off);
-
-       if (mpll->lock)
-               spin_unlock_irqrestore(mpll->lock, flags);
-       else
-               __release(mpll->lock);
-
-       return 0;
-}
+       /* Enable and set the fractional part */
+       meson_parm_write(clk->map, &mpll->sdm, sdm);
+       meson_parm_write(clk->map, &mpll->sdm_en, 1);
 
-static void mpll_enable_core(struct clk_hw *hw, int enable)
-{
-       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
-       struct parm *p;
-       unsigned long reg;
-       unsigned long flags = 0;
+       /* Set additional fractional part enable if required */
+       if (MESON_PARM_APPLICABLE(&mpll->ssen))
+               meson_parm_write(clk->map, &mpll->ssen, 1);
 
-       if (mpll->lock)
-               spin_lock_irqsave(mpll->lock, flags);
-       else
-               __acquire(mpll->lock);
+       /* Set the integer divider part */
+       meson_parm_write(clk->map, &mpll->n2, n2);
 
-       p = &mpll->en;
-       reg = readl(mpll->base + p->reg_off);
-       reg = PARM_SET(p->width, p->shift, reg, enable ? 1 : 0);
-       writel(reg, mpll->base + p->reg_off);
+       /* Set the magic misc bit if required */
+       if (MESON_PARM_APPLICABLE(&mpll->misc))
+               meson_parm_write(clk->map, &mpll->misc, 1);
 
        if (mpll->lock)
                spin_unlock_irqrestore(mpll->lock, flags);
        else
                __release(mpll->lock);
-}
-
-
-static int mpll_enable(struct clk_hw *hw)
-{
-       mpll_enable_core(hw, 1);
 
        return 0;
 }
 
-static void mpll_disable(struct clk_hw *hw)
-{
-       mpll_enable_core(hw, 0);
-}
-
-static int mpll_is_enabled(struct clk_hw *hw)
-{
-       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
-       struct parm *p;
-       unsigned long reg;
-       int en;
-
-       p = &mpll->en;
-       reg = readl(mpll->base + p->reg_off);
-       en = PARM_GET(p->width, p->shift, reg);
-
-       return en;
-}
-
 const struct clk_ops meson_clk_mpll_ro_ops = {
        .recalc_rate    = mpll_recalc_rate,
        .round_rate     = mpll_round_rate,
-       .is_enabled     = mpll_is_enabled,
 };
 
 const struct clk_ops meson_clk_mpll_ops = {
        .recalc_rate    = mpll_recalc_rate,
        .round_rate     = mpll_round_rate,
        .set_rate       = mpll_set_rate,
-       .enable         = mpll_enable,
-       .disable        = mpll_disable,
-       .is_enabled     = mpll_is_enabled,
 };