diff options
author | Haojian Zhuang <haojian.zhuang@linaro.org> | 2013-06-08 10:47:17 -0400 |
---|---|---|
committer | Mike Turquette <mturquette@linaro.org> | 2013-06-15 23:23:36 -0400 |
commit | ba492e900704ba00d43c7af9d94b00da4df52587 (patch) | |
tree | 497484f3a3a8c796ccab042ba7be5a81e15d871b | |
parent | f3aab5d61400b794ec759b9345e93e7ba57eb369 (diff) |
clk: mux: add CLK_MUX_HIWORD_MASK
In both Hisilicon & Rockchip Cortex-A9 based chips, they don't use the
paradigm of reading-changing-writing the register contents.
Instead they use a hiword mask to indicate the changed bits.
When b01 should be set as switching mux, it also needs to indicate
the change by setting hiword mask (b11 << 16).
The patch adds mux flag for this usage.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Signed-off-by: Mike Turquette <mturquette@linaro.org>
-rw-r--r-- | drivers/clk/clk-mux.c | 17 | ||||
-rw-r--r-- | include/linux/clk-provider.h | 5 |
2 files changed, 20 insertions, 2 deletions
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 25b1734560d0..614444ca40cd 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c | |||
@@ -86,8 +86,12 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index) | |||
86 | if (mux->lock) | 86 | if (mux->lock) |
87 | spin_lock_irqsave(mux->lock, flags); | 87 | spin_lock_irqsave(mux->lock, flags); |
88 | 88 | ||
89 | val = readl(mux->reg); | 89 | if (mux->flags & CLK_MUX_HIWORD_MASK) { |
90 | val &= ~(mux->mask << mux->shift); | 90 | val = mux->mask << (mux->shift + 16); |
91 | } else { | ||
92 | val = readl(mux->reg); | ||
93 | val &= ~(mux->mask << mux->shift); | ||
94 | } | ||
91 | val |= index << mux->shift; | 95 | val |= index << mux->shift; |
92 | writel(val, mux->reg); | 96 | writel(val, mux->reg); |
93 | 97 | ||
@@ -111,6 +115,15 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name, | |||
111 | struct clk_mux *mux; | 115 | struct clk_mux *mux; |
112 | struct clk *clk; | 116 | struct clk *clk; |
113 | struct clk_init_data init; | 117 | struct clk_init_data init; |
118 | u8 width = 0; | ||
119 | |||
120 | if (clk_mux_flags & CLK_MUX_HIWORD_MASK) { | ||
121 | width = fls(mask) - ffs(mask) + 1; | ||
122 | if (width + shift > 16) { | ||
123 | pr_err("mux value exceeds LOWORD field\n"); | ||
124 | return ERR_PTR(-EINVAL); | ||
125 | } | ||
126 | } | ||
114 | 127 | ||
115 | /* allocate the mux */ | 128 | /* allocate the mux */ |
116 | mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); | 129 | mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); |
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 265f384f1e01..37ad97961e5a 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h | |||
@@ -299,6 +299,10 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name, | |||
299 | * Flags: | 299 | * Flags: |
300 | * CLK_MUX_INDEX_ONE - register index starts at 1, not 0 | 300 | * CLK_MUX_INDEX_ONE - register index starts at 1, not 0 |
301 | * CLK_MUX_INDEX_BIT - register index is a single bit (power of two) | 301 | * CLK_MUX_INDEX_BIT - register index is a single bit (power of two) |
302 | * CLK_MUX_HIWORD_MASK - The mux settings are only in lower 16-bit of this | ||
303 | * register, and mask of mux bits are in higher 16-bit of this register. | ||
304 | * While setting the mux bits, higher 16-bit should also be updated to | ||
305 | * indicate changing mux bits. | ||
302 | */ | 306 | */ |
303 | struct clk_mux { | 307 | struct clk_mux { |
304 | struct clk_hw hw; | 308 | struct clk_hw hw; |
@@ -312,6 +316,7 @@ struct clk_mux { | |||
312 | 316 | ||
313 | #define CLK_MUX_INDEX_ONE BIT(0) | 317 | #define CLK_MUX_INDEX_ONE BIT(0) |
314 | #define CLK_MUX_INDEX_BIT BIT(1) | 318 | #define CLK_MUX_INDEX_BIT BIT(1) |
319 | #define CLK_MUX_HIWORD_MASK BIT(2) | ||
315 | 320 | ||
316 | extern const struct clk_ops clk_mux_ops; | 321 | extern const struct clk_ops clk_mux_ops; |
317 | 322 | ||