diff options
Diffstat (limited to 'drivers/clk/clk-mux.c')
-rw-r--r-- | drivers/clk/clk-mux.c | 75 |
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 | ||
29 | static u8 clk_mux_get_parent(struct clk_hw *hw) | 29 | int 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 | } |
54 | EXPORT_SYMBOL_GPL(clk_mux_val_to_index); | ||
65 | 55 | ||
66 | static int clk_mux_set_parent(struct clk_hw *hw, u8 index) | 56 | unsigned 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 | } | ||
72 | EXPORT_SYMBOL_GPL(clk_mux_index_to_val); | ||
73 | |||
74 | static 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 | |||
85 | static 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); |