|
@@ -26,35 +26,24 @@
|
|
|
* 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);
|
|
|
- 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,36 +51,58 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
|
|
|
|
|
|
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);
|
|
|
- u32 val;
|
|
|
- unsigned long flags = 0;
|
|
|
+ unsigned int val = index;
|
|
|
|
|
|
- if (mux->table) {
|
|
|
- index = mux->table[index];
|
|
|
+ if (table) {
|
|
|
+ val = table[index];
|
|
|
} 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_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)
|
|
|
spin_lock_irqsave(mux->lock, flags);
|
|
|
else
|
|
|
__acquire(mux->lock);
|
|
|
|
|
|
if (mux->flags & CLK_MUX_HIWORD_MASK) {
|
|
|
- val = mux->mask << (mux->shift + 16);
|
|
|
+ reg = mux->mask << (mux->shift + 16);
|
|
|
} else {
|
|
|
- val = clk_readl(mux->reg);
|
|
|
- val &= ~(mux->mask << mux->shift);
|
|
|
+ reg = clk_readl(mux->reg);
|
|
|
+ reg &= ~(mux->mask << mux->shift);
|
|
|
}
|
|
|
- val |= index << mux->shift;
|
|
|
- clk_writel(val, mux->reg);
|
|
|
+ val = val << mux->shift;
|
|
|
+ reg |= val;
|
|
|
+ clk_writel(reg, mux->reg);
|
|
|
|
|
|
if (mux->lock)
|
|
|
spin_unlock_irqrestore(mux->lock, flags);
|