Commit 77deb66d authored by Jerome Brunet's avatar Jerome Brunet Committed by Stephen Boyd

clk: mux: add helper function for index/value translation

Add helper functions for the translation between parent index and
register value in the generic multiplexer function. The purpose of
this change is avoid duplicating the code in other clock providers,
using the same generic logic.
Signed-off-by: default avatarJerome Brunet <jbrunet@baylibre.com>
Signed-off-by: default avatarMichael Turquette <mturquette@baylibre.com>
Signed-off-by: default avatarStephen Boyd <sboyd@kernel.org>
parent e6d3cc7b
...@@ -26,35 +26,24 @@ ...@@ -26,35 +26,24 @@
* parent - parent is adjustable through clk_set_parent * parent - parent is adjustable through clk_set_parent
*/ */
static u8 clk_mux_get_parent(struct clk_hw *hw) int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
unsigned int val)
{ {
struct clk_mux *mux = to_clk_mux(hw);
int num_parents = clk_hw_get_num_parents(hw); int num_parents = clk_hw_get_num_parents(hw);
u32 val;
/* if (table) {
* 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) {
int i; int i;
for (i = 0; i < num_parents; i++) for (i = 0; i < num_parents; i++)
if (mux->table[i] == val) if (table[i] == val)
return i; return i;
return -EINVAL; return -EINVAL;
} }
if (val && (mux->flags & CLK_MUX_INDEX_BIT)) if (val && (flags & CLK_MUX_INDEX_BIT))
val = ffs(val) - 1; val = ffs(val) - 1;
if (val && (mux->flags & CLK_MUX_INDEX_ONE)) if (val && (flags & CLK_MUX_INDEX_ONE))
val--; val--;
if (val >= num_parents) if (val >= num_parents)
...@@ -62,36 +51,58 @@ static u8 clk_mux_get_parent(struct clk_hw *hw) ...@@ -62,36 +51,58 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
return val; return val;
} }
EXPORT_SYMBOL_GPL(clk_mux_val_to_index);
static int clk_mux_set_parent(struct clk_hw *hw, u8 index) unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index)
{ {
struct clk_mux *mux = to_clk_mux(hw); unsigned int val = index;
u32 val;
unsigned long flags = 0;
if (mux->table) { if (table) {
index = mux->table[index]; val = table[index];
} else { } else {
if (mux->flags & CLK_MUX_INDEX_BIT) if (flags & CLK_MUX_INDEX_BIT)
index = 1 << index; val = 1 << index;
if (mux->flags & CLK_MUX_INDEX_ONE) if (flags & CLK_MUX_INDEX_ONE)
index++; val++;
} }
return val;
}
EXPORT_SYMBOL_GPL(clk_mux_index_to_val);
static u8 clk_mux_get_parent(struct clk_hw *hw)
{
struct clk_mux *mux = to_clk_mux(hw);
u32 val;
val = clk_readl(mux->reg) >> mux->shift;
val &= mux->mask;
return clk_mux_val_to_index(hw, mux->table, mux->flags, val);
}
static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct clk_mux *mux = to_clk_mux(hw);
u32 val = clk_mux_index_to_val(mux->table, mux->flags, index);
unsigned long flags = 0;
u32 reg;
if (mux->lock) if (mux->lock)
spin_lock_irqsave(mux->lock, flags); spin_lock_irqsave(mux->lock, flags);
else else
__acquire(mux->lock); __acquire(mux->lock);
if (mux->flags & CLK_MUX_HIWORD_MASK) { if (mux->flags & CLK_MUX_HIWORD_MASK) {
val = mux->mask << (mux->shift + 16); reg = mux->mask << (mux->shift + 16);
} else { } else {
val = clk_readl(mux->reg); reg = clk_readl(mux->reg);
val &= ~(mux->mask << mux->shift); reg &= ~(mux->mask << mux->shift);
} }
val |= index << mux->shift; val = val << mux->shift;
clk_writel(val, mux->reg); reg |= val;
clk_writel(reg, mux->reg);
if (mux->lock) if (mux->lock)
spin_unlock_irqrestore(mux->lock, flags); spin_unlock_irqrestore(mux->lock, flags);
......
...@@ -511,6 +511,10 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name, ...@@ -511,6 +511,10 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
void __iomem *reg, u8 shift, u32 mask, void __iomem *reg, u8 shift, u32 mask,
u8 clk_mux_flags, u32 *table, spinlock_t *lock); u8 clk_mux_flags, u32 *table, spinlock_t *lock);
int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
unsigned int val);
unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index);
void clk_unregister_mux(struct clk *clk); void clk_unregister_mux(struct clk *clk);
void clk_hw_unregister_mux(struct clk_hw *hw); void clk_hw_unregister_mux(struct clk_hw *hw);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment