aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/clk-mux.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/clk-mux.c')
-rw-r--r--drivers/clk/clk-mux.c75
1 files changed, 43 insertions, 32 deletions
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 39cabe157163..ac4a042f8658 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -26,35 +26,24 @@
26 * parent - parent is adjustable through clk_set_parent 26 * parent - parent is adjustable through clk_set_parent
27 */ 27 */
28 28
29static u8 clk_mux_get_parent(struct clk_hw *hw) 29int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
30 unsigned int val)
30{ 31{
31 struct clk_mux *mux = to_clk_mux(hw);
32 int num_parents = clk_hw_get_num_parents(hw); 32 int num_parents = clk_hw_get_num_parents(hw);
33 u32 val;
34 33
35 /* 34 if (table) {
36 * FIXME need a mux-specific flag to determine if val is bitwise or numeric
37 * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1
38 * to 0x7 (index starts at one)
39 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
40 * val = 0x4 really means "bit 2, index starts at bit 0"
41 */
42 val = clk_readl(mux->reg) >> mux->shift;
43 val &= mux->mask;
44
45 if (mux->table) {
46 int i; 35 int i;
47 36
48 for (i = 0; i < num_parents; i++) 37 for (i = 0; i < num_parents; i++)
49 if (mux->table[i] == val) 38 if (table[i] == val)
50 return i; 39 return i;
51 return -EINVAL; 40 return -EINVAL;
52 } 41 }
53 42
54 if (val && (mux->flags & CLK_MUX_INDEX_BIT)) 43 if (val && (flags & CLK_MUX_INDEX_BIT))
55 val = ffs(val) - 1; 44 val = ffs(val) - 1;
56 45
57 if (val && (mux->flags & CLK_MUX_INDEX_ONE)) 46 if (val && (flags & CLK_MUX_INDEX_ONE))
58 val--; 47 val--;
59 48
60 if (val >= num_parents) 49 if (val >= num_parents)
@@ -62,36 +51,58 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
62 51
63 return val; 52 return val;
64} 53}
54EXPORT_SYMBOL_GPL(clk_mux_val_to_index);
65 55
66static int clk_mux_set_parent(struct clk_hw *hw, u8 index) 56unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index)
67{ 57{
68 struct clk_mux *mux = to_clk_mux(hw); 58 unsigned int val = index;
69 u32 val;
70 unsigned long flags = 0;
71 59
72 if (mux->table) { 60 if (table) {
73 index = mux->table[index]; 61 val = table[index];
74 } else { 62 } else {
75 if (mux->flags & CLK_MUX_INDEX_BIT) 63 if (flags & CLK_MUX_INDEX_BIT)
76 index = 1 << index; 64 val = 1 << index;
77 65
78 if (mux->flags & CLK_MUX_INDEX_ONE) 66 if (flags & CLK_MUX_INDEX_ONE)
79 index++; 67 val++;
80 } 68 }
81 69
70 return val;
71}
72EXPORT_SYMBOL_GPL(clk_mux_index_to_val);
73
74static u8 clk_mux_get_parent(struct clk_hw *hw)
75{
76 struct clk_mux *mux = to_clk_mux(hw);
77 u32 val;
78
79 val = clk_readl(mux->reg) >> mux->shift;
80 val &= mux->mask;
81
82 return clk_mux_val_to_index(hw, mux->table, mux->flags, val);
83}
84
85static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
86{
87 struct clk_mux *mux = to_clk_mux(hw);
88 u32 val = clk_mux_index_to_val(mux->table, mux->flags, index);
89 unsigned long flags = 0;
90 u32 reg;
91
82 if (mux->lock) 92 if (mux->lock)
83 spin_lock_irqsave(mux->lock, flags); 93 spin_lock_irqsave(mux->lock, flags);
84 else 94 else
85 __acquire(mux->lock); 95 __acquire(mux->lock);
86 96
87 if (mux->flags & CLK_MUX_HIWORD_MASK) { 97 if (mux->flags & CLK_MUX_HIWORD_MASK) {
88 val = mux->mask << (mux->shift + 16); 98 reg = mux->mask << (mux->shift + 16);
89 } else { 99 } else {
90 val = clk_readl(mux->reg); 100 reg = clk_readl(mux->reg);
91 val &= ~(mux->mask << mux->shift); 101 reg &= ~(mux->mask << mux->shift);
92 } 102 }
93 val |= index << mux->shift; 103 val = val << mux->shift;
94 clk_writel(val, mux->reg); 104 reg |= val;
105 clk_writel(reg, mux->reg);
95 106
96 if (mux->lock) 107 if (mux->lock)
97 spin_unlock_irqrestore(mux->lock, flags); 108 spin_unlock_irqrestore(mux->lock, flags);