You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
192 lines
5.9 KiB
192 lines
5.9 KiB
From 9d381d65eae163d8f50d97a3ad9033bba176f62b Mon Sep 17 00:00:00 2001
|
|
From: Stephen Boyd <sboyd@codeaurora.org>
|
|
Date: Fri, 20 Mar 2015 23:45:21 -0700
|
|
Subject: [PATCH 35/69] clk: mux: Split out register accessors for reuse
|
|
|
|
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>
|
|
Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
|
|
---
|
|
drivers/clk/clk-mux.c | 76 ++++++++++++++++++++++++++++----------------
|
|
include/linux/clk-provider.h | 11 +++++--
|
|
2 files changed, 57 insertions(+), 30 deletions(-)
|
|
|
|
--- a/drivers/clk/clk-mux.c
|
|
+++ b/drivers/clk/clk-mux.c
|
|
@@ -26,35 +26,27 @@
|
|
* parent - parent is adjustable through clk_set_parent
|
|
*/
|
|
|
|
-static u8 clk_mux_get_parent(struct clk_hw *hw)
|
|
+#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, 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_hw_get_num_parents(hw);
|
|
- 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)
|
|
@@ -62,23 +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);
|
|
+}
|
|
+
|
|
+unsigned int clk_mux_reindex(u8 index, unsigned int *table,
|
|
+ unsigned long flags)
|
|
+{
|
|
+ unsigned int val = index;
|
|
+
|
|
+ if (table) {
|
|
+ val = table[val];
|
|
} else {
|
|
- if (mux->flags & CLK_MUX_INDEX_BIT)
|
|
- index = 1 << index;
|
|
+ if (flags & CLK_MUX_INDEX_BIT)
|
|
+ val = 1 << index;
|
|
|
|
- if (mux->flags & CLK_MUX_INDEX_ONE)
|
|
- 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);
|
|
else
|
|
@@ -102,14 +124,14 @@ 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);
|
|
|
|
@@ -117,7 +139,7 @@ struct clk_hw *clk_hw_register_mux_table
|
|
const char * const *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_hw *hw;
|
|
--- a/include/linux/clk-provider.h
|
|
+++ b/include/linux/clk-provider.h
|
|
@@ -466,7 +466,7 @@ void clk_hw_unregister_divider(struct cl
|
|
struct clk_mux {
|
|
struct clk_hw hw;
|
|
void __iomem *reg;
|
|
- u32 *table;
|
|
+ unsigned int *table;
|
|
u32 mask;
|
|
u8 shift;
|
|
u8 flags;
|
|
@@ -484,6 +484,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 * const *parent_names, u8 num_parents,
|
|
unsigned long flags,
|
|
@@ -499,12 +504,12 @@ struct clk *clk_register_mux_table(struc
|
|
const char * const *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_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
|
|
const char * const *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);
|
|
void clk_hw_unregister_mux(struct clk_hw *hw);
|
|
|