ipq806x: fix 3.18 support
[openwrt/staging/lynxis/omap.git] / target / linux / ipq806x / patches-3.18 / 134-clk-mux-Split-out-register-accessors-for-reuse.patch
diff --git a/target/linux/ipq806x/patches-3.18/134-clk-mux-Split-out-register-accessors-for-reuse.patch b/target/linux/ipq806x/patches-3.18/134-clk-mux-Split-out-register-accessors-for-reuse.patch
new file mode 100644 (file)
index 0000000..50022e6
--- /dev/null
@@ -0,0 +1,192 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v3,02/13] clk: mux: Split out register accessors for reuse
+From: Stephen Boyd <sboyd@codeaurora.org>
+X-Patchwork-Id: 6063111
+Message-Id: <1426920332-9340-3-git-send-email-sboyd@codeaurora.org>
+To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
+Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
+       linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
+       Viresh Kumar <viresh.kumar@linaro.org>
+Date: Fri, 20 Mar 2015 23:45:21 -0700
+
+We want to reuse the logic in clk-mux.c for other clock drivers
+that don't use readl as register accessors. Fortunately, there
+really isn't much to the mux code besides the table indirection
+and quirk flags if you assume any bit shifting and masking has
+been done already. Pull that logic out into reusable functions
+that operate on an optional table and some flags so that other
+drivers can use the same logic.
+
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+
+---
+drivers/clk/clk-mux.c        | 76 +++++++++++++++++++++++++++-----------------
+ include/linux/clk-provider.h |  9 ++++--
+ 2 files changed, 54 insertions(+), 31 deletions(-)
+
+--- a/drivers/clk/clk-mux.c
++++ b/drivers/clk/clk-mux.c
+@@ -29,35 +29,24 @@
+ #define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw)
+-static u8 clk_mux_get_parent(struct clk_hw *hw)
++unsigned int clk_mux_get_parent(struct clk_hw *hw, unsigned int val,
++                              unsigned int *table, unsigned long flags)
+ {
+-      struct clk_mux *mux = to_clk_mux(hw);
+       int num_parents = __clk_get_num_parents(hw->clk);
+-      u32 val;
+-      /*
+-       * FIXME need a mux-specific flag to determine if val is bitwise or numeric
+-       * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1
+-       * to 0x7 (index starts at one)
+-       * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
+-       * val = 0x4 really means "bit 2, index starts at bit 0"
+-       */
+-      val = clk_readl(mux->reg) >> mux->shift;
+-      val &= mux->mask;
+-
+-      if (mux->table) {
++      if (table) {
+               int i;
+               for (i = 0; i < num_parents; i++)
+-                      if (mux->table[i] == val)
++                      if (table[i] == val)
+                               return i;
+               return -EINVAL;
+       }
+-      if (val && (mux->flags & CLK_MUX_INDEX_BIT))
++      if (val && (flags & CLK_MUX_INDEX_BIT))
+               val = ffs(val) - 1;
+-      if (val && (mux->flags & CLK_MUX_INDEX_ONE))
++      if (val && (flags & CLK_MUX_INDEX_ONE))
+               val--;
+       if (val >= num_parents)
+@@ -65,24 +54,53 @@ static u8 clk_mux_get_parent(struct clk_
+       return val;
+ }
++EXPORT_SYMBOL_GPL(clk_mux_get_parent);
+-static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
++static u8 _clk_mux_get_parent(struct clk_hw *hw)
+ {
+       struct clk_mux *mux = to_clk_mux(hw);
+       u32 val;
+-      unsigned long flags = 0;
+-      if (mux->table)
+-              index = mux->table[index];
++      /*
++       * FIXME need a mux-specific flag to determine if val is bitwise or numeric
++       * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1
++       * to 0x7 (index starts at one)
++       * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
++       * val = 0x4 really means "bit 2, index starts at bit 0"
++       */
++      val = clk_readl(mux->reg) >> mux->shift;
++      val &= mux->mask;
++
++      return clk_mux_get_parent(hw, val, mux->table, mux->flags);
++}
+-      else {
+-              if (mux->flags & CLK_MUX_INDEX_BIT)
+-                      index = 1 << index;
++unsigned int clk_mux_reindex(u8 index, unsigned int *table,
++                           unsigned long flags)
++{
++      unsigned int val = index;
+-              if (mux->flags & CLK_MUX_INDEX_ONE)
+-                      index++;
++      if (table) {
++              val = table[val];
++      } else {
++              if (flags & CLK_MUX_INDEX_BIT)
++                      val = 1 << index;
++
++              if (flags & CLK_MUX_INDEX_ONE)
++                      val++;
+       }
++      return val;
++}
++EXPORT_SYMBOL_GPL(clk_mux_reindex);
++
++static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
++{
++      struct clk_mux *mux = to_clk_mux(hw);
++      u32 val;
++      unsigned long flags = 0;
++
++      index = clk_mux_reindex(index, mux->table, mux->flags);
++
+       if (mux->lock)
+               spin_lock_irqsave(mux->lock, flags);
+@@ -102,21 +120,21 @@ static int clk_mux_set_parent(struct clk
+ }
+ const struct clk_ops clk_mux_ops = {
+-      .get_parent = clk_mux_get_parent,
++      .get_parent = _clk_mux_get_parent,
+       .set_parent = clk_mux_set_parent,
+       .determine_rate = __clk_mux_determine_rate,
+ };
+ EXPORT_SYMBOL_GPL(clk_mux_ops);
+ const struct clk_ops clk_mux_ro_ops = {
+-      .get_parent = clk_mux_get_parent,
++      .get_parent = _clk_mux_get_parent,
+ };
+ EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
+ struct clk *clk_register_mux_table(struct device *dev, const char *name,
+               const char **parent_names, u8 num_parents, unsigned long flags,
+               void __iomem *reg, u8 shift, u32 mask,
+-              u8 clk_mux_flags, u32 *table, spinlock_t *lock)
++              u8 clk_mux_flags, unsigned int *table, spinlock_t *lock)
+ {
+       struct clk_mux *mux;
+       struct clk *clk;
+--- a/include/linux/clk-provider.h
++++ b/include/linux/clk-provider.h
+@@ -390,7 +390,7 @@ void clk_unregister_divider(struct clk *
+ struct clk_mux {
+       struct clk_hw   hw;
+       void __iomem    *reg;
+-      u32             *table;
++      unsigned int    *table;
+       u32             mask;
+       u8              shift;
+       u8              flags;
+@@ -406,6 +406,11 @@ struct clk_mux {
+ extern const struct clk_ops clk_mux_ops;
+ extern const struct clk_ops clk_mux_ro_ops;
++unsigned int clk_mux_get_parent(struct clk_hw *hw, unsigned int val,
++                              unsigned int *table, unsigned long flags);
++unsigned int clk_mux_reindex(u8 index, unsigned int *table,
++                           unsigned long flags);
++
+ struct clk *clk_register_mux(struct device *dev, const char *name,
+               const char **parent_names, u8 num_parents, unsigned long flags,
+               void __iomem *reg, u8 shift, u8 width,
+@@ -414,7 +419,7 @@ struct clk *clk_register_mux(struct devi
+ struct clk *clk_register_mux_table(struct device *dev, const char *name,
+               const char **parent_names, u8 num_parents, unsigned long flags,
+               void __iomem *reg, u8 shift, u32 mask,
+-              u8 clk_mux_flags, u32 *table, spinlock_t *lock);
++              u8 clk_mux_flags, unsigned int *table, spinlock_t *lock);
+ void clk_unregister_mux(struct clk *clk);