diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-23 21:56:08 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-23 21:56:08 -0500 |
commit | 7e21774db5cc9cf8fe93a64a2f0c6cf47db8ab24 (patch) | |
tree | 460812792bc3b23789a83968b7bad840cc3eb047 /drivers/clk/mvebu | |
parent | 0ba3307a8ec35252f7b1e222e32889a6f3d9ceb3 (diff) | |
parent | 2e84d75116c17c2034e917b411250d2d11755435 (diff) |
Merge tag 'clk-for-linus-3.14-part1' of git://git.linaro.org/people/mike.turquette/linux
Pull clk framework changes from Mike Turquette:
"The first half of the clk framework pull request is made up almost
entirely of new platform/driver support. There are some conversions
of existing drivers to the common-clock Device Tree binding, and a few
non-critical fixes to the framework.
Due to an entirely unnecessary cyclical dependency with the arm-soc
tree this pull request is broken into two pieces. The second piece
will be sent out after arm-soc sends you the pull request that merged
in core support for the HiSilicon 3620 platform. That same pull
request from arm-soc depends on this pull request to merge in those
HiSilicon bits without causing build failures"
[ Just did the ARM SoC merges, so getting ready for the second clk tree
pull request - Linus ]
* tag 'clk-for-linus-3.14-part1' of git://git.linaro.org/people/mike.turquette/linux: (97 commits)
devicetree: bindings: Document qcom,mmcc
devicetree: bindings: Document qcom,gcc
clk: qcom: Add support for MSM8660's global clock controller (GCC)
clk: qcom: Add support for MSM8974's multimedia clock controller (MMCC)
clk: qcom: Add support for MSM8974's global clock controller (GCC)
clk: qcom: Add support for MSM8960's multimedia clock controller (MMCC)
clk: qcom: Add support for MSM8960's global clock controller (GCC)
clk: qcom: Add reset controller support
clk: qcom: Add support for branches/gate clocks
clk: qcom: Add support for root clock generators (RCGs)
clk: qcom: Add support for phase locked loops (PLLs)
clk: qcom: Add a regmap type clock struct
clk: Add set_rate_and_parent() op
reset: Silence warning in reset-controller.h
clk: sirf: re-arch to make the codes support both prima2 and atlas6
clk: composite: pass mux_hw into determine_rate
clk: shmobile: Fix MSTP clock array initialization
clk: shmobile: Fix MSTP clock index
ARM: dts: Add clock provider specific properties to max77686 node
clk: max77686: Register OF clock provider
...
Diffstat (limited to 'drivers/clk/mvebu')
-rw-r--r-- | drivers/clk/mvebu/Kconfig | 5 | ||||
-rw-r--r-- | drivers/clk/mvebu/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/mvebu/clk-corediv.c | 223 | ||||
-rw-r--r-- | drivers/clk/mvebu/clk-cpu.c | 2 |
4 files changed, 230 insertions, 1 deletions
diff --git a/drivers/clk/mvebu/Kconfig b/drivers/clk/mvebu/Kconfig index 0b0f3e729cf7..c339b829d3e3 100644 --- a/drivers/clk/mvebu/Kconfig +++ b/drivers/clk/mvebu/Kconfig | |||
@@ -4,15 +4,20 @@ config MVEBU_CLK_COMMON | |||
4 | config MVEBU_CLK_CPU | 4 | config MVEBU_CLK_CPU |
5 | bool | 5 | bool |
6 | 6 | ||
7 | config MVEBU_CLK_COREDIV | ||
8 | bool | ||
9 | |||
7 | config ARMADA_370_CLK | 10 | config ARMADA_370_CLK |
8 | bool | 11 | bool |
9 | select MVEBU_CLK_COMMON | 12 | select MVEBU_CLK_COMMON |
10 | select MVEBU_CLK_CPU | 13 | select MVEBU_CLK_CPU |
14 | select MVEBU_CLK_COREDIV | ||
11 | 15 | ||
12 | config ARMADA_XP_CLK | 16 | config ARMADA_XP_CLK |
13 | bool | 17 | bool |
14 | select MVEBU_CLK_COMMON | 18 | select MVEBU_CLK_COMMON |
15 | select MVEBU_CLK_CPU | 19 | select MVEBU_CLK_CPU |
20 | select MVEBU_CLK_COREDIV | ||
16 | 21 | ||
17 | config DOVE_CLK | 22 | config DOVE_CLK |
18 | bool | 23 | bool |
diff --git a/drivers/clk/mvebu/Makefile b/drivers/clk/mvebu/Makefile index 1c7e70c63fb2..21bbfb4a9f42 100644 --- a/drivers/clk/mvebu/Makefile +++ b/drivers/clk/mvebu/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | obj-$(CONFIG_MVEBU_CLK_COMMON) += common.o | 1 | obj-$(CONFIG_MVEBU_CLK_COMMON) += common.o |
2 | obj-$(CONFIG_MVEBU_CLK_CPU) += clk-cpu.o | 2 | obj-$(CONFIG_MVEBU_CLK_CPU) += clk-cpu.o |
3 | obj-$(CONFIG_MVEBU_CLK_COREDIV) += clk-corediv.o | ||
3 | 4 | ||
4 | obj-$(CONFIG_ARMADA_370_CLK) += armada-370.o | 5 | obj-$(CONFIG_ARMADA_370_CLK) += armada-370.o |
5 | obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o | 6 | obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o |
diff --git a/drivers/clk/mvebu/clk-corediv.c b/drivers/clk/mvebu/clk-corediv.c new file mode 100644 index 000000000000..7162615bcdcd --- /dev/null +++ b/drivers/clk/mvebu/clk-corediv.c | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * MVEBU Core divider clock | ||
3 | * | ||
4 | * Copyright (C) 2013 Marvell | ||
5 | * | ||
6 | * Ezequiel Garcia <ezequiel.garcia@free-electrons.com> | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public | ||
9 | * License version 2. This program is licensed "as is" without any | ||
10 | * warranty of any kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/clk-provider.h> | ||
15 | #include <linux/of_address.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include "common.h" | ||
19 | |||
20 | #define CORE_CLK_DIV_RATIO_MASK 0xff | ||
21 | #define CORE_CLK_DIV_RATIO_RELOAD BIT(8) | ||
22 | #define CORE_CLK_DIV_ENABLE_OFFSET 24 | ||
23 | #define CORE_CLK_DIV_RATIO_OFFSET 0x8 | ||
24 | |||
25 | struct clk_corediv_desc { | ||
26 | unsigned int mask; | ||
27 | unsigned int offset; | ||
28 | unsigned int fieldbit; | ||
29 | }; | ||
30 | |||
31 | struct clk_corediv { | ||
32 | struct clk_hw hw; | ||
33 | void __iomem *reg; | ||
34 | struct clk_corediv_desc desc; | ||
35 | spinlock_t lock; | ||
36 | }; | ||
37 | |||
38 | static struct clk_onecell_data clk_data; | ||
39 | |||
40 | static const struct clk_corediv_desc mvebu_corediv_desc[] __initconst = { | ||
41 | { .mask = 0x3f, .offset = 8, .fieldbit = 1 }, /* NAND clock */ | ||
42 | }; | ||
43 | |||
44 | #define to_corediv_clk(p) container_of(p, struct clk_corediv, hw) | ||
45 | |||
46 | static int clk_corediv_is_enabled(struct clk_hw *hwclk) | ||
47 | { | ||
48 | struct clk_corediv *corediv = to_corediv_clk(hwclk); | ||
49 | struct clk_corediv_desc *desc = &corediv->desc; | ||
50 | u32 enable_mask = BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET; | ||
51 | |||
52 | return !!(readl(corediv->reg) & enable_mask); | ||
53 | } | ||
54 | |||
55 | static int clk_corediv_enable(struct clk_hw *hwclk) | ||
56 | { | ||
57 | struct clk_corediv *corediv = to_corediv_clk(hwclk); | ||
58 | struct clk_corediv_desc *desc = &corediv->desc; | ||
59 | unsigned long flags = 0; | ||
60 | u32 reg; | ||
61 | |||
62 | spin_lock_irqsave(&corediv->lock, flags); | ||
63 | |||
64 | reg = readl(corediv->reg); | ||
65 | reg |= (BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET); | ||
66 | writel(reg, corediv->reg); | ||
67 | |||
68 | spin_unlock_irqrestore(&corediv->lock, flags); | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static void clk_corediv_disable(struct clk_hw *hwclk) | ||
74 | { | ||
75 | struct clk_corediv *corediv = to_corediv_clk(hwclk); | ||
76 | struct clk_corediv_desc *desc = &corediv->desc; | ||
77 | unsigned long flags = 0; | ||
78 | u32 reg; | ||
79 | |||
80 | spin_lock_irqsave(&corediv->lock, flags); | ||
81 | |||
82 | reg = readl(corediv->reg); | ||
83 | reg &= ~(BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET); | ||
84 | writel(reg, corediv->reg); | ||
85 | |||
86 | spin_unlock_irqrestore(&corediv->lock, flags); | ||
87 | } | ||
88 | |||
89 | static unsigned long clk_corediv_recalc_rate(struct clk_hw *hwclk, | ||
90 | unsigned long parent_rate) | ||
91 | { | ||
92 | struct clk_corediv *corediv = to_corediv_clk(hwclk); | ||
93 | struct clk_corediv_desc *desc = &corediv->desc; | ||
94 | u32 reg, div; | ||
95 | |||
96 | reg = readl(corediv->reg + CORE_CLK_DIV_RATIO_OFFSET); | ||
97 | div = (reg >> desc->offset) & desc->mask; | ||
98 | return parent_rate / div; | ||
99 | } | ||
100 | |||
101 | static long clk_corediv_round_rate(struct clk_hw *hwclk, unsigned long rate, | ||
102 | unsigned long *parent_rate) | ||
103 | { | ||
104 | /* Valid ratio are 1:4, 1:5, 1:6 and 1:8 */ | ||
105 | u32 div; | ||
106 | |||
107 | div = *parent_rate / rate; | ||
108 | if (div < 4) | ||
109 | div = 4; | ||
110 | else if (div > 6) | ||
111 | div = 8; | ||
112 | |||
113 | return *parent_rate / div; | ||
114 | } | ||
115 | |||
116 | static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate, | ||
117 | unsigned long parent_rate) | ||
118 | { | ||
119 | struct clk_corediv *corediv = to_corediv_clk(hwclk); | ||
120 | struct clk_corediv_desc *desc = &corediv->desc; | ||
121 | unsigned long flags = 0; | ||
122 | u32 reg, div; | ||
123 | |||
124 | div = parent_rate / rate; | ||
125 | |||
126 | spin_lock_irqsave(&corediv->lock, flags); | ||
127 | |||
128 | /* Write new divider to the divider ratio register */ | ||
129 | reg = readl(corediv->reg + CORE_CLK_DIV_RATIO_OFFSET); | ||
130 | reg &= ~(desc->mask << desc->offset); | ||
131 | reg |= (div & desc->mask) << desc->offset; | ||
132 | writel(reg, corediv->reg + CORE_CLK_DIV_RATIO_OFFSET); | ||
133 | |||
134 | /* Set reload-force for this clock */ | ||
135 | reg = readl(corediv->reg) | BIT(desc->fieldbit); | ||
136 | writel(reg, corediv->reg); | ||
137 | |||
138 | /* Now trigger the clock update */ | ||
139 | reg = readl(corediv->reg) | CORE_CLK_DIV_RATIO_RELOAD; | ||
140 | writel(reg, corediv->reg); | ||
141 | |||
142 | /* | ||
143 | * Wait for clocks to settle down, and then clear all the | ||
144 | * ratios request and the reload request. | ||
145 | */ | ||
146 | udelay(1000); | ||
147 | reg &= ~(CORE_CLK_DIV_RATIO_MASK | CORE_CLK_DIV_RATIO_RELOAD); | ||
148 | writel(reg, corediv->reg); | ||
149 | udelay(1000); | ||
150 | |||
151 | spin_unlock_irqrestore(&corediv->lock, flags); | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static const struct clk_ops corediv_ops = { | ||
157 | .enable = clk_corediv_enable, | ||
158 | .disable = clk_corediv_disable, | ||
159 | .is_enabled = clk_corediv_is_enabled, | ||
160 | .recalc_rate = clk_corediv_recalc_rate, | ||
161 | .round_rate = clk_corediv_round_rate, | ||
162 | .set_rate = clk_corediv_set_rate, | ||
163 | }; | ||
164 | |||
165 | static void __init mvebu_corediv_clk_init(struct device_node *node) | ||
166 | { | ||
167 | struct clk_init_data init; | ||
168 | struct clk_corediv *corediv; | ||
169 | struct clk **clks; | ||
170 | void __iomem *base; | ||
171 | const char *parent_name; | ||
172 | const char *clk_name; | ||
173 | int i; | ||
174 | |||
175 | base = of_iomap(node, 0); | ||
176 | if (WARN_ON(!base)) | ||
177 | return; | ||
178 | |||
179 | parent_name = of_clk_get_parent_name(node, 0); | ||
180 | |||
181 | clk_data.clk_num = ARRAY_SIZE(mvebu_corediv_desc); | ||
182 | |||
183 | /* clks holds the clock array */ | ||
184 | clks = kcalloc(clk_data.clk_num, sizeof(struct clk *), | ||
185 | GFP_KERNEL); | ||
186 | if (WARN_ON(!clks)) | ||
187 | goto err_unmap; | ||
188 | /* corediv holds the clock specific array */ | ||
189 | corediv = kcalloc(clk_data.clk_num, sizeof(struct clk_corediv), | ||
190 | GFP_KERNEL); | ||
191 | if (WARN_ON(!corediv)) | ||
192 | goto err_free_clks; | ||
193 | |||
194 | spin_lock_init(&corediv->lock); | ||
195 | |||
196 | for (i = 0; i < clk_data.clk_num; i++) { | ||
197 | of_property_read_string_index(node, "clock-output-names", | ||
198 | i, &clk_name); | ||
199 | init.num_parents = 1; | ||
200 | init.parent_names = &parent_name; | ||
201 | init.name = clk_name; | ||
202 | init.ops = &corediv_ops; | ||
203 | init.flags = 0; | ||
204 | |||
205 | corediv[i].desc = mvebu_corediv_desc[i]; | ||
206 | corediv[i].reg = base; | ||
207 | corediv[i].hw.init = &init; | ||
208 | |||
209 | clks[i] = clk_register(NULL, &corediv[i].hw); | ||
210 | WARN_ON(IS_ERR(clks[i])); | ||
211 | } | ||
212 | |||
213 | clk_data.clks = clks; | ||
214 | of_clk_add_provider(node, of_clk_src_onecell_get, &clk_data); | ||
215 | return; | ||
216 | |||
217 | err_free_clks: | ||
218 | kfree(clks); | ||
219 | err_unmap: | ||
220 | iounmap(base); | ||
221 | } | ||
222 | CLK_OF_DECLARE(mvebu_corediv_clk, "marvell,armada-370-corediv-clock", | ||
223 | mvebu_corediv_clk_init); | ||
diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c index 1466865b0743..8ebf757d29e2 100644 --- a/drivers/clk/mvebu/clk-cpu.c +++ b/drivers/clk/mvebu/clk-cpu.c | |||
@@ -101,7 +101,7 @@ static const struct clk_ops cpu_ops = { | |||
101 | .set_rate = clk_cpu_set_rate, | 101 | .set_rate = clk_cpu_set_rate, |
102 | }; | 102 | }; |
103 | 103 | ||
104 | void __init of_cpu_clk_setup(struct device_node *node) | 104 | static void __init of_cpu_clk_setup(struct device_node *node) |
105 | { | 105 | { |
106 | struct cpu_clk *cpuclk; | 106 | struct cpu_clk *cpuclk; |
107 | void __iomem *clock_complex_base = of_iomap(node, 0); | 107 | void __iomem *clock_complex_base = of_iomap(node, 0); |