aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/clk/clk-mux.c50
-rw-r--r--drivers/clk/tegra/clk.h27
-rw-r--r--include/linux/clk-private.h2
-rw-r--r--include/linux/clk-provider.h9
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 @@
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}
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,
297struct clk_mux { 297struct 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
309extern const struct clk_ops clk_mux_ops; 310extern const struct clk_ops clk_mux_ops;
311
310struct clk *clk_register_mux(struct device *dev, const char *name, 312struct 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
317struct 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 *