diff options
-rw-r--r-- | drivers/clk/clk-mux.c | 50 | ||||
-rw-r--r-- | drivers/clk/tegra/clk.h | 27 | ||||
-rw-r--r-- | include/linux/clk-private.h | 2 | ||||
-rw-r--r-- | include/linux/clk-provider.h | 9 |
4 files changed, 67 insertions, 21 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 | } | ||
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 0744731c6229..a09d7dcaf183 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h | |||
@@ -355,15 +355,16 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name, | |||
355 | struct tegra_clk_periph *periph, void __iomem *clk_base, | 355 | struct tegra_clk_periph *periph, void __iomem *clk_base, |
356 | u32 offset); | 356 | u32 offset); |
357 | 357 | ||
358 | #define TEGRA_CLK_PERIPH(_mux_shift, _mux_width, _mux_flags, \ | 358 | #define TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, _mux_flags, \ |
359 | _div_shift, _div_width, _div_frac_width, \ | 359 | _div_shift, _div_width, _div_frac_width, \ |
360 | _div_flags, _clk_num, _enb_refcnt, _regs, \ | 360 | _div_flags, _clk_num, _enb_refcnt, _regs, \ |
361 | _gate_flags) \ | 361 | _gate_flags, _table) \ |
362 | { \ | 362 | { \ |
363 | .mux = { \ | 363 | .mux = { \ |
364 | .flags = _mux_flags, \ | 364 | .flags = _mux_flags, \ |
365 | .shift = _mux_shift, \ | 365 | .shift = _mux_shift, \ |
366 | .width = _mux_width, \ | 366 | .mask = _mux_mask, \ |
367 | .table = _table, \ | ||
367 | }, \ | 368 | }, \ |
368 | .divider = { \ | 369 | .divider = { \ |
369 | .flags = _div_flags, \ | 370 | .flags = _div_flags, \ |
@@ -393,26 +394,36 @@ struct tegra_periph_init_data { | |||
393 | const char *dev_id; | 394 | const char *dev_id; |
394 | }; | 395 | }; |
395 | 396 | ||
396 | #define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset, \ | 397 | #define TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\ |
397 | _mux_shift, _mux_width, _mux_flags, _div_shift, \ | 398 | _mux_shift, _mux_mask, _mux_flags, _div_shift, \ |
398 | _div_width, _div_frac_width, _div_flags, _regs, \ | 399 | _div_width, _div_frac_width, _div_flags, _regs, \ |
399 | _clk_num, _enb_refcnt, _gate_flags, _clk_id) \ | 400 | _clk_num, _enb_refcnt, _gate_flags, _clk_id, _table) \ |
400 | { \ | 401 | { \ |
401 | .name = _name, \ | 402 | .name = _name, \ |
402 | .clk_id = _clk_id, \ | 403 | .clk_id = _clk_id, \ |
403 | .parent_names = _parent_names, \ | 404 | .parent_names = _parent_names, \ |
404 | .num_parents = ARRAY_SIZE(_parent_names), \ | 405 | .num_parents = ARRAY_SIZE(_parent_names), \ |
405 | .periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_width, \ | 406 | .periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, \ |
406 | _mux_flags, _div_shift, \ | 407 | _mux_flags, _div_shift, \ |
407 | _div_width, _div_frac_width, \ | 408 | _div_width, _div_frac_width, \ |
408 | _div_flags, _clk_num, \ | 409 | _div_flags, _clk_num, \ |
409 | _enb_refcnt, _regs, \ | 410 | _enb_refcnt, _regs, \ |
410 | _gate_flags), \ | 411 | _gate_flags, _table), \ |
411 | .offset = _offset, \ | 412 | .offset = _offset, \ |
412 | .con_id = _con_id, \ | 413 | .con_id = _con_id, \ |
413 | .dev_id = _dev_id, \ | 414 | .dev_id = _dev_id, \ |
414 | } | 415 | } |
415 | 416 | ||
417 | #define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset,\ | ||
418 | _mux_shift, _mux_width, _mux_flags, _div_shift, \ | ||
419 | _div_width, _div_frac_width, _div_flags, _regs, \ | ||
420 | _clk_num, _enb_refcnt, _gate_flags, _clk_id) \ | ||
421 | TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\ | ||
422 | _mux_shift, BIT(_mux_width) - 1, _mux_flags, \ | ||
423 | _div_shift, _div_width, _div_frac_width, _div_flags, \ | ||
424 | _regs, _clk_num, _enb_refcnt, _gate_flags, _clk_id,\ | ||
425 | NULL) | ||
426 | |||
416 | /** | 427 | /** |
417 | * struct clk_super_mux - super clock | 428 | * struct clk_super_mux - super clock |
418 | * | 429 | * |
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h index 9c7f5807824b..dd7adff76e81 100644 --- a/include/linux/clk-private.h +++ b/include/linux/clk-private.h | |||
@@ -152,7 +152,7 @@ struct clk { | |||
152 | }, \ | 152 | }, \ |
153 | .reg = _reg, \ | 153 | .reg = _reg, \ |
154 | .shift = _shift, \ | 154 | .shift = _shift, \ |
155 | .width = _width, \ | 155 | .mask = BIT(_width) - 1, \ |
156 | .flags = _mux_flags, \ | 156 | .flags = _mux_flags, \ |
157 | .lock = _lock, \ | 157 | .lock = _lock, \ |
158 | }; \ | 158 | }; \ |
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 56e6cc12c796..63ba3b740794 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h | |||
@@ -297,8 +297,9 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name, | |||
297 | struct clk_mux { | 297 | struct clk_mux { |
298 | struct clk_hw hw; | 298 | struct clk_hw hw; |
299 | void __iomem *reg; | 299 | void __iomem *reg; |
300 | u32 *table; | ||
301 | u32 mask; | ||
300 | u8 shift; | 302 | u8 shift; |
301 | u8 width; | ||
302 | u8 flags; | 303 | u8 flags; |
303 | spinlock_t *lock; | 304 | spinlock_t *lock; |
304 | }; | 305 | }; |
@@ -307,11 +308,17 @@ struct clk_mux { | |||
307 | #define CLK_MUX_INDEX_BIT BIT(1) | 308 | #define CLK_MUX_INDEX_BIT BIT(1) |
308 | 309 | ||
309 | extern const struct clk_ops clk_mux_ops; | 310 | extern const struct clk_ops clk_mux_ops; |
311 | |||
310 | struct clk *clk_register_mux(struct device *dev, const char *name, | 312 | struct clk *clk_register_mux(struct device *dev, const char *name, |
311 | const char **parent_names, u8 num_parents, unsigned long flags, | 313 | const char **parent_names, u8 num_parents, unsigned long flags, |
312 | void __iomem *reg, u8 shift, u8 width, | 314 | void __iomem *reg, u8 shift, u8 width, |
313 | u8 clk_mux_flags, spinlock_t *lock); | 315 | u8 clk_mux_flags, spinlock_t *lock); |
314 | 316 | ||
317 | struct clk *clk_register_mux_table(struct device *dev, const char *name, | ||
318 | const char **parent_names, u8 num_parents, unsigned long flags, | ||
319 | void __iomem *reg, u8 shift, u32 mask, | ||
320 | u8 clk_mux_flags, u32 *table, spinlock_t *lock); | ||
321 | |||
315 | /** | 322 | /** |
316 | * struct clk_fixed_factor - fixed multiplier and divider clock | 323 | * struct clk_fixed_factor - fixed multiplier and divider clock |
317 | * | 324 | * |