diff options
Diffstat (limited to 'drivers/clk/clk-mux.c')
-rw-r--r-- | drivers/clk/clk-mux.c | 50 |
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 @@ | |||
32 | static u8 clk_mux_get_parent(struct clk_hw *hw) | 32 | static 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 | }; |
89 | EXPORT_SYMBOL_GPL(clk_mux_ops); | 104 | EXPORT_SYMBOL_GPL(clk_mux_ops); |
90 | 105 | ||
91 | struct clk *clk_register_mux(struct device *dev, const char *name, | 106 | struct 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 | |||
145 | struct 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 | } | ||