aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/clk-mux.c
diff options
context:
space:
mode:
authorPeter De Schrijver <pdeschrijver@nvidia.com>2013-03-22 08:07:53 -0400
committerMike Turquette <mturquette@linaro.org>2013-03-22 18:18:18 -0400
commitce4f3313b05c836c21a91ac89f87dccf84ce9561 (patch)
treeab0f642d4ad1cc37b5a08ca0db5ac34f83ca84a8 /drivers/clk/clk-mux.c
parent5fda6858a49c2d8706adcc05f083b64af172d3eb (diff)
clk: add table lookup to mux
Add a table lookup feature to the mux clock. Also allow arbitrary masks instead of the width. This will be used by some clocks on Tegra114. Also adapt the tegra periph clk because it uses struct clk_mux directly. Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com> Tested-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Mike Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk/clk-mux.c')
-rw-r--r--drivers/clk/clk-mux.c50
1 files changed, 39 insertions, 11 deletions
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 508c032edce4..25b1734560d0 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -32,6 +32,7 @@
32static u8 clk_mux_get_parent(struct clk_hw *hw) 32static u8 clk_mux_get_parent(struct clk_hw *hw)
33{ 33{
34 struct clk_mux *mux = to_clk_mux(hw); 34 struct clk_mux *mux = to_clk_mux(hw);
35 int num_parents = __clk_get_num_parents(hw->clk);
35 u32 val; 36 u32 val;
36 37
37 /* 38 /*
@@ -42,7 +43,16 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
42 * val = 0x4 really means "bit 2, index starts at bit 0" 43 * val = 0x4 really means "bit 2, index starts at bit 0"
43 */ 44 */
44 val = readl(mux->reg) >> mux->shift; 45 val = readl(mux->reg) >> mux->shift;
45 val &= (1 << mux->width) - 1; 46 val &= mux->mask;
47
48 if (mux->table) {
49 int i;
50
51 for (i = 0; i < num_parents; i++)
52 if (mux->table[i] == val)
53 return i;
54 return -EINVAL;
55 }
46 56
47 if (val && (mux->flags & CLK_MUX_INDEX_BIT)) 57 if (val && (mux->flags & CLK_MUX_INDEX_BIT))
48 val = ffs(val) - 1; 58 val = ffs(val) - 1;
@@ -50,7 +60,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
50 if (val && (mux->flags & CLK_MUX_INDEX_ONE)) 60 if (val && (mux->flags & CLK_MUX_INDEX_ONE))
51 val--; 61 val--;
52 62
53 if (val >= __clk_get_num_parents(hw->clk)) 63 if (val >= num_parents)
54 return -EINVAL; 64 return -EINVAL;
55 65
56 return val; 66 return val;
@@ -62,17 +72,22 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
62 u32 val; 72 u32 val;
63 unsigned long flags = 0; 73 unsigned long flags = 0;
64 74
65 if (mux->flags & CLK_MUX_INDEX_BIT) 75 if (mux->table)
66 index = (1 << ffs(index)); 76 index = mux->table[index];
67 77
68 if (mux->flags & CLK_MUX_INDEX_ONE) 78 else {
69 index++; 79 if (mux->flags & CLK_MUX_INDEX_BIT)
80 index = (1 << ffs(index));
81
82 if (mux->flags & CLK_MUX_INDEX_ONE)
83 index++;
84 }
70 85
71 if (mux->lock) 86 if (mux->lock)
72 spin_lock_irqsave(mux->lock, flags); 87 spin_lock_irqsave(mux->lock, flags);
73 88
74 val = readl(mux->reg); 89 val = readl(mux->reg);
75 val &= ~(((1 << mux->width) - 1) << mux->shift); 90 val &= ~(mux->mask << mux->shift);
76 val |= index << mux->shift; 91 val |= index << mux->shift;
77 writel(val, mux->reg); 92 writel(val, mux->reg);
78 93
@@ -88,10 +103,10 @@ const struct clk_ops clk_mux_ops = {
88}; 103};
89EXPORT_SYMBOL_GPL(clk_mux_ops); 104EXPORT_SYMBOL_GPL(clk_mux_ops);
90 105
91struct clk *clk_register_mux(struct device *dev, const char *name, 106struct clk *clk_register_mux_table(struct device *dev, const char *name,
92 const char **parent_names, u8 num_parents, unsigned long flags, 107 const char **parent_names, u8 num_parents, unsigned long flags,
93 void __iomem *reg, u8 shift, u8 width, 108 void __iomem *reg, u8 shift, u32 mask,
94 u8 clk_mux_flags, spinlock_t *lock) 109 u8 clk_mux_flags, u32 *table, spinlock_t *lock)
95{ 110{
96 struct clk_mux *mux; 111 struct clk_mux *mux;
97 struct clk *clk; 112 struct clk *clk;
@@ -113,9 +128,10 @@ struct clk *clk_register_mux(struct device *dev, const char *name,
113 /* struct clk_mux assignments */ 128 /* struct clk_mux assignments */
114 mux->reg = reg; 129 mux->reg = reg;
115 mux->shift = shift; 130 mux->shift = shift;
116 mux->width = width; 131 mux->mask = mask;
117 mux->flags = clk_mux_flags; 132 mux->flags = clk_mux_flags;
118 mux->lock = lock; 133 mux->lock = lock;
134 mux->table = table;
119 mux->hw.init = &init; 135 mux->hw.init = &init;
120 136
121 clk = clk_register(dev, &mux->hw); 137 clk = clk_register(dev, &mux->hw);
@@ -125,3 +141,15 @@ struct clk *clk_register_mux(struct device *dev, const char *name,
125 141
126 return clk; 142 return clk;
127} 143}
144
145struct clk *clk_register_mux(struct device *dev, const char *name,
146 const char **parent_names, u8 num_parents, unsigned long flags,
147 void __iomem *reg, u8 shift, u8 width,
148 u8 clk_mux_flags, spinlock_t *lock)
149{
150 u32 mask = BIT(width) - 1;
151
152 return clk_register_mux_table(dev, name, parent_names, num_parents,
153 flags, reg, shift, mask, clk_mux_flags,
154 NULL, lock);
155}