diff options
Diffstat (limited to 'drivers/clk')
37 files changed, 1390 insertions, 492 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 7641965d208d..da1b416aa579 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig | |||
@@ -65,10 +65,12 @@ config COMMON_CLK_SI570 | |||
65 | clock generators. | 65 | clock generators. |
66 | 66 | ||
67 | config COMMON_CLK_S2MPS11 | 67 | config COMMON_CLK_S2MPS11 |
68 | tristate "Clock driver for S2MPS11 MFD" | 68 | tristate "Clock driver for S2MPS11/S5M8767 MFD" |
69 | depends on MFD_SEC_CORE | 69 | depends on MFD_SEC_CORE |
70 | ---help--- | 70 | ---help--- |
71 | This driver supports S2MPS11 crystal oscillator clock. | 71 | This driver supports S2MPS11/S5M8767 crystal oscillator clock. These |
72 | multi-function devices have 3 fixed-rate oscillators, clocked at | ||
73 | 32KHz each. | ||
72 | 74 | ||
73 | config CLK_TWL6040 | 75 | config CLK_TWL6040 |
74 | tristate "External McPDM functional clock from twl6040" | 76 | tristate "External McPDM functional clock from twl6040" |
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index a367a9831717..48a7ef3d05f6 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile | |||
@@ -17,6 +17,7 @@ obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o | |||
17 | obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o | 17 | obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o |
18 | obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o | 18 | obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o |
19 | obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o | 19 | obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o |
20 | obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o | ||
20 | obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o | 21 | obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o |
21 | obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o | 22 | obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o |
22 | obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o | 23 | obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o |
diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c index bd313f7816a8..c1af80bcdf20 100644 --- a/drivers/clk/at91/clk-master.c +++ b/drivers/clk/at91/clk-master.c | |||
@@ -242,7 +242,7 @@ of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc, | |||
242 | 242 | ||
243 | irq = irq_of_parse_and_map(np, 0); | 243 | irq = irq_of_parse_and_map(np, 0); |
244 | if (!irq) | 244 | if (!irq) |
245 | return; | 245 | goto out_free_characteristics; |
246 | 246 | ||
247 | clk = at91_clk_register_master(pmc, irq, name, num_parents, | 247 | clk = at91_clk_register_master(pmc, irq, name, num_parents, |
248 | parent_names, layout, | 248 | parent_names, layout, |
diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c index 8137327847c3..1127ee46b802 100644 --- a/drivers/clk/clk-axi-clkgen.c +++ b/drivers/clk/clk-axi-clkgen.c | |||
@@ -17,23 +17,75 @@ | |||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | 19 | ||
20 | #define AXI_CLKGEN_REG_UPDATE_ENABLE 0x04 | 20 | #define AXI_CLKGEN_V1_REG_UPDATE_ENABLE 0x04 |
21 | #define AXI_CLKGEN_REG_CLK_OUT1 0x08 | 21 | #define AXI_CLKGEN_V1_REG_CLK_OUT1 0x08 |
22 | #define AXI_CLKGEN_REG_CLK_OUT2 0x0c | 22 | #define AXI_CLKGEN_V1_REG_CLK_OUT2 0x0c |
23 | #define AXI_CLKGEN_REG_CLK_DIV 0x10 | 23 | #define AXI_CLKGEN_V1_REG_CLK_DIV 0x10 |
24 | #define AXI_CLKGEN_REG_CLK_FB1 0x14 | 24 | #define AXI_CLKGEN_V1_REG_CLK_FB1 0x14 |
25 | #define AXI_CLKGEN_REG_CLK_FB2 0x18 | 25 | #define AXI_CLKGEN_V1_REG_CLK_FB2 0x18 |
26 | #define AXI_CLKGEN_REG_LOCK1 0x1c | 26 | #define AXI_CLKGEN_V1_REG_LOCK1 0x1c |
27 | #define AXI_CLKGEN_REG_LOCK2 0x20 | 27 | #define AXI_CLKGEN_V1_REG_LOCK2 0x20 |
28 | #define AXI_CLKGEN_REG_LOCK3 0x24 | 28 | #define AXI_CLKGEN_V1_REG_LOCK3 0x24 |
29 | #define AXI_CLKGEN_REG_FILTER1 0x28 | 29 | #define AXI_CLKGEN_V1_REG_FILTER1 0x28 |
30 | #define AXI_CLKGEN_REG_FILTER2 0x2c | 30 | #define AXI_CLKGEN_V1_REG_FILTER2 0x2c |
31 | |||
32 | #define AXI_CLKGEN_V2_REG_RESET 0x40 | ||
33 | #define AXI_CLKGEN_V2_REG_DRP_CNTRL 0x70 | ||
34 | #define AXI_CLKGEN_V2_REG_DRP_STATUS 0x74 | ||
35 | |||
36 | #define AXI_CLKGEN_V2_RESET_MMCM_ENABLE BIT(1) | ||
37 | #define AXI_CLKGEN_V2_RESET_ENABLE BIT(0) | ||
38 | |||
39 | #define AXI_CLKGEN_V2_DRP_CNTRL_SEL BIT(29) | ||
40 | #define AXI_CLKGEN_V2_DRP_CNTRL_READ BIT(28) | ||
41 | |||
42 | #define AXI_CLKGEN_V2_DRP_STATUS_BUSY BIT(16) | ||
43 | |||
44 | #define MMCM_REG_CLKOUT0_1 0x08 | ||
45 | #define MMCM_REG_CLKOUT0_2 0x09 | ||
46 | #define MMCM_REG_CLK_FB1 0x14 | ||
47 | #define MMCM_REG_CLK_FB2 0x15 | ||
48 | #define MMCM_REG_CLK_DIV 0x16 | ||
49 | #define MMCM_REG_LOCK1 0x18 | ||
50 | #define MMCM_REG_LOCK2 0x19 | ||
51 | #define MMCM_REG_LOCK3 0x1a | ||
52 | #define MMCM_REG_FILTER1 0x4e | ||
53 | #define MMCM_REG_FILTER2 0x4f | ||
54 | |||
55 | struct axi_clkgen; | ||
56 | |||
57 | struct axi_clkgen_mmcm_ops { | ||
58 | void (*enable)(struct axi_clkgen *axi_clkgen, bool enable); | ||
59 | int (*write)(struct axi_clkgen *axi_clkgen, unsigned int reg, | ||
60 | unsigned int val, unsigned int mask); | ||
61 | int (*read)(struct axi_clkgen *axi_clkgen, unsigned int reg, | ||
62 | unsigned int *val); | ||
63 | }; | ||
31 | 64 | ||
32 | struct axi_clkgen { | 65 | struct axi_clkgen { |
33 | void __iomem *base; | 66 | void __iomem *base; |
67 | const struct axi_clkgen_mmcm_ops *mmcm_ops; | ||
34 | struct clk_hw clk_hw; | 68 | struct clk_hw clk_hw; |
35 | }; | 69 | }; |
36 | 70 | ||
71 | static void axi_clkgen_mmcm_enable(struct axi_clkgen *axi_clkgen, | ||
72 | bool enable) | ||
73 | { | ||
74 | axi_clkgen->mmcm_ops->enable(axi_clkgen, enable); | ||
75 | } | ||
76 | |||
77 | static int axi_clkgen_mmcm_write(struct axi_clkgen *axi_clkgen, | ||
78 | unsigned int reg, unsigned int val, unsigned int mask) | ||
79 | { | ||
80 | return axi_clkgen->mmcm_ops->write(axi_clkgen, reg, val, mask); | ||
81 | } | ||
82 | |||
83 | static int axi_clkgen_mmcm_read(struct axi_clkgen *axi_clkgen, | ||
84 | unsigned int reg, unsigned int *val) | ||
85 | { | ||
86 | return axi_clkgen->mmcm_ops->read(axi_clkgen, reg, val); | ||
87 | } | ||
88 | |||
37 | static uint32_t axi_clkgen_lookup_filter(unsigned int m) | 89 | static uint32_t axi_clkgen_lookup_filter(unsigned int m) |
38 | { | 90 | { |
39 | switch (m) { | 91 | switch (m) { |
@@ -156,6 +208,148 @@ static void axi_clkgen_read(struct axi_clkgen *axi_clkgen, | |||
156 | *val = readl(axi_clkgen->base + reg); | 208 | *val = readl(axi_clkgen->base + reg); |
157 | } | 209 | } |
158 | 210 | ||
211 | static unsigned int axi_clkgen_v1_map_mmcm_reg(unsigned int reg) | ||
212 | { | ||
213 | switch (reg) { | ||
214 | case MMCM_REG_CLKOUT0_1: | ||
215 | return AXI_CLKGEN_V1_REG_CLK_OUT1; | ||
216 | case MMCM_REG_CLKOUT0_2: | ||
217 | return AXI_CLKGEN_V1_REG_CLK_OUT2; | ||
218 | case MMCM_REG_CLK_FB1: | ||
219 | return AXI_CLKGEN_V1_REG_CLK_FB1; | ||
220 | case MMCM_REG_CLK_FB2: | ||
221 | return AXI_CLKGEN_V1_REG_CLK_FB2; | ||
222 | case MMCM_REG_CLK_DIV: | ||
223 | return AXI_CLKGEN_V1_REG_CLK_DIV; | ||
224 | case MMCM_REG_LOCK1: | ||
225 | return AXI_CLKGEN_V1_REG_LOCK1; | ||
226 | case MMCM_REG_LOCK2: | ||
227 | return AXI_CLKGEN_V1_REG_LOCK2; | ||
228 | case MMCM_REG_LOCK3: | ||
229 | return AXI_CLKGEN_V1_REG_LOCK3; | ||
230 | case MMCM_REG_FILTER1: | ||
231 | return AXI_CLKGEN_V1_REG_FILTER1; | ||
232 | case MMCM_REG_FILTER2: | ||
233 | return AXI_CLKGEN_V1_REG_FILTER2; | ||
234 | default: | ||
235 | return 0; | ||
236 | } | ||
237 | } | ||
238 | |||
239 | static int axi_clkgen_v1_mmcm_write(struct axi_clkgen *axi_clkgen, | ||
240 | unsigned int reg, unsigned int val, unsigned int mask) | ||
241 | { | ||
242 | reg = axi_clkgen_v1_map_mmcm_reg(reg); | ||
243 | if (reg == 0) | ||
244 | return -EINVAL; | ||
245 | |||
246 | axi_clkgen_write(axi_clkgen, reg, val); | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | static int axi_clkgen_v1_mmcm_read(struct axi_clkgen *axi_clkgen, | ||
252 | unsigned int reg, unsigned int *val) | ||
253 | { | ||
254 | reg = axi_clkgen_v1_map_mmcm_reg(reg); | ||
255 | if (reg == 0) | ||
256 | return -EINVAL; | ||
257 | |||
258 | axi_clkgen_read(axi_clkgen, reg, val); | ||
259 | |||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | static void axi_clkgen_v1_mmcm_enable(struct axi_clkgen *axi_clkgen, | ||
264 | bool enable) | ||
265 | { | ||
266 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V1_REG_UPDATE_ENABLE, enable); | ||
267 | } | ||
268 | |||
269 | static const struct axi_clkgen_mmcm_ops axi_clkgen_v1_mmcm_ops = { | ||
270 | .write = axi_clkgen_v1_mmcm_write, | ||
271 | .read = axi_clkgen_v1_mmcm_read, | ||
272 | .enable = axi_clkgen_v1_mmcm_enable, | ||
273 | }; | ||
274 | |||
275 | static int axi_clkgen_wait_non_busy(struct axi_clkgen *axi_clkgen) | ||
276 | { | ||
277 | unsigned int timeout = 10000; | ||
278 | unsigned int val; | ||
279 | |||
280 | do { | ||
281 | axi_clkgen_read(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_STATUS, &val); | ||
282 | } while ((val & AXI_CLKGEN_V2_DRP_STATUS_BUSY) && --timeout); | ||
283 | |||
284 | if (val & AXI_CLKGEN_V2_DRP_STATUS_BUSY) | ||
285 | return -EIO; | ||
286 | |||
287 | return val & 0xffff; | ||
288 | } | ||
289 | |||
290 | static int axi_clkgen_v2_mmcm_read(struct axi_clkgen *axi_clkgen, | ||
291 | unsigned int reg, unsigned int *val) | ||
292 | { | ||
293 | unsigned int reg_val; | ||
294 | int ret; | ||
295 | |||
296 | ret = axi_clkgen_wait_non_busy(axi_clkgen); | ||
297 | if (ret < 0) | ||
298 | return ret; | ||
299 | |||
300 | reg_val = AXI_CLKGEN_V2_DRP_CNTRL_SEL | AXI_CLKGEN_V2_DRP_CNTRL_READ; | ||
301 | reg_val |= (reg << 16); | ||
302 | |||
303 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_CNTRL, reg_val); | ||
304 | |||
305 | ret = axi_clkgen_wait_non_busy(axi_clkgen); | ||
306 | if (ret < 0) | ||
307 | return ret; | ||
308 | |||
309 | *val = ret; | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static int axi_clkgen_v2_mmcm_write(struct axi_clkgen *axi_clkgen, | ||
315 | unsigned int reg, unsigned int val, unsigned int mask) | ||
316 | { | ||
317 | unsigned int reg_val = 0; | ||
318 | int ret; | ||
319 | |||
320 | ret = axi_clkgen_wait_non_busy(axi_clkgen); | ||
321 | if (ret < 0) | ||
322 | return ret; | ||
323 | |||
324 | if (mask != 0xffff) { | ||
325 | axi_clkgen_v2_mmcm_read(axi_clkgen, reg, ®_val); | ||
326 | reg_val &= ~mask; | ||
327 | } | ||
328 | |||
329 | reg_val |= AXI_CLKGEN_V2_DRP_CNTRL_SEL | (reg << 16) | (val & mask); | ||
330 | |||
331 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_CNTRL, reg_val); | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static void axi_clkgen_v2_mmcm_enable(struct axi_clkgen *axi_clkgen, | ||
337 | bool enable) | ||
338 | { | ||
339 | unsigned int val = AXI_CLKGEN_V2_RESET_ENABLE; | ||
340 | |||
341 | if (enable) | ||
342 | val |= AXI_CLKGEN_V2_RESET_MMCM_ENABLE; | ||
343 | |||
344 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_RESET, val); | ||
345 | } | ||
346 | |||
347 | static const struct axi_clkgen_mmcm_ops axi_clkgen_v2_mmcm_ops = { | ||
348 | .write = axi_clkgen_v2_mmcm_write, | ||
349 | .read = axi_clkgen_v2_mmcm_read, | ||
350 | .enable = axi_clkgen_v2_mmcm_enable, | ||
351 | }; | ||
352 | |||
159 | static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw) | 353 | static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw) |
160 | { | 354 | { |
161 | return container_of(clk_hw, struct axi_clkgen, clk_hw); | 355 | return container_of(clk_hw, struct axi_clkgen, clk_hw); |
@@ -184,33 +378,29 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw, | |||
184 | filter = axi_clkgen_lookup_filter(m - 1); | 378 | filter = axi_clkgen_lookup_filter(m - 1); |
185 | lock = axi_clkgen_lookup_lock(m - 1); | 379 | lock = axi_clkgen_lookup_lock(m - 1); |
186 | 380 | ||
187 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_UPDATE_ENABLE, 0); | ||
188 | |||
189 | axi_clkgen_calc_clk_params(dout, &low, &high, &edge, &nocount); | 381 | axi_clkgen_calc_clk_params(dout, &low, &high, &edge, &nocount); |
190 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1, | 382 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_1, |
191 | (high << 6) | low); | 383 | (high << 6) | low, 0xefff); |
192 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT2, | 384 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_2, |
193 | (edge << 7) | (nocount << 6)); | 385 | (edge << 7) | (nocount << 6), 0x03ff); |
194 | 386 | ||
195 | axi_clkgen_calc_clk_params(d, &low, &high, &edge, &nocount); | 387 | axi_clkgen_calc_clk_params(d, &low, &high, &edge, &nocount); |
196 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV, | 388 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_DIV, |
197 | (edge << 13) | (nocount << 12) | (high << 6) | low); | 389 | (edge << 13) | (nocount << 12) | (high << 6) | low, 0x3fff); |
198 | 390 | ||
199 | axi_clkgen_calc_clk_params(m, &low, &high, &edge, &nocount); | 391 | axi_clkgen_calc_clk_params(m, &low, &high, &edge, &nocount); |
200 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1, | 392 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB1, |
201 | (high << 6) | low); | 393 | (high << 6) | low, 0xefff); |
202 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_FB2, | 394 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB2, |
203 | (edge << 7) | (nocount << 6)); | 395 | (edge << 7) | (nocount << 6), 0x03ff); |
204 | 396 | ||
205 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK1, lock & 0x3ff); | 397 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK1, lock & 0x3ff, 0x3ff); |
206 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK2, | 398 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK2, |
207 | (((lock >> 16) & 0x1f) << 10) | 0x1); | 399 | (((lock >> 16) & 0x1f) << 10) | 0x1, 0x7fff); |
208 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK3, | 400 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK3, |
209 | (((lock >> 24) & 0x1f) << 10) | 0x3e9); | 401 | (((lock >> 24) & 0x1f) << 10) | 0x3e9, 0x7fff); |
210 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_FILTER1, filter >> 16); | 402 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_FILTER1, filter >> 16, 0x9900); |
211 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_FILTER2, filter); | 403 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_FILTER2, filter, 0x9900); |
212 | |||
213 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_UPDATE_ENABLE, 1); | ||
214 | 404 | ||
215 | return 0; | 405 | return 0; |
216 | } | 406 | } |
@@ -236,11 +426,11 @@ static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw, | |||
236 | unsigned int reg; | 426 | unsigned int reg; |
237 | unsigned long long tmp; | 427 | unsigned long long tmp; |
238 | 428 | ||
239 | axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1, ®); | 429 | axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_1, ®); |
240 | dout = (reg & 0x3f) + ((reg >> 6) & 0x3f); | 430 | dout = (reg & 0x3f) + ((reg >> 6) & 0x3f); |
241 | axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV, ®); | 431 | axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, ®); |
242 | d = (reg & 0x3f) + ((reg >> 6) & 0x3f); | 432 | d = (reg & 0x3f) + ((reg >> 6) & 0x3f); |
243 | axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1, ®); | 433 | axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB1, ®); |
244 | m = (reg & 0x3f) + ((reg >> 6) & 0x3f); | 434 | m = (reg & 0x3f) + ((reg >> 6) & 0x3f); |
245 | 435 | ||
246 | if (d == 0 || dout == 0) | 436 | if (d == 0 || dout == 0) |
@@ -255,14 +445,45 @@ static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw, | |||
255 | return tmp; | 445 | return tmp; |
256 | } | 446 | } |
257 | 447 | ||
448 | static int axi_clkgen_enable(struct clk_hw *clk_hw) | ||
449 | { | ||
450 | struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); | ||
451 | |||
452 | axi_clkgen_mmcm_enable(axi_clkgen, true); | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | static void axi_clkgen_disable(struct clk_hw *clk_hw) | ||
458 | { | ||
459 | struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); | ||
460 | |||
461 | axi_clkgen_mmcm_enable(axi_clkgen, false); | ||
462 | } | ||
463 | |||
258 | static const struct clk_ops axi_clkgen_ops = { | 464 | static const struct clk_ops axi_clkgen_ops = { |
259 | .recalc_rate = axi_clkgen_recalc_rate, | 465 | .recalc_rate = axi_clkgen_recalc_rate, |
260 | .round_rate = axi_clkgen_round_rate, | 466 | .round_rate = axi_clkgen_round_rate, |
261 | .set_rate = axi_clkgen_set_rate, | 467 | .set_rate = axi_clkgen_set_rate, |
468 | .enable = axi_clkgen_enable, | ||
469 | .disable = axi_clkgen_disable, | ||
262 | }; | 470 | }; |
263 | 471 | ||
472 | static const struct of_device_id axi_clkgen_ids[] = { | ||
473 | { | ||
474 | .compatible = "adi,axi-clkgen-1.00.a", | ||
475 | .data = &axi_clkgen_v1_mmcm_ops | ||
476 | }, { | ||
477 | .compatible = "adi,axi-clkgen-2.00.a", | ||
478 | .data = &axi_clkgen_v2_mmcm_ops, | ||
479 | }, | ||
480 | { }, | ||
481 | }; | ||
482 | MODULE_DEVICE_TABLE(of, axi_clkgen_ids); | ||
483 | |||
264 | static int axi_clkgen_probe(struct platform_device *pdev) | 484 | static int axi_clkgen_probe(struct platform_device *pdev) |
265 | { | 485 | { |
486 | const struct of_device_id *id; | ||
266 | struct axi_clkgen *axi_clkgen; | 487 | struct axi_clkgen *axi_clkgen; |
267 | struct clk_init_data init; | 488 | struct clk_init_data init; |
268 | const char *parent_name; | 489 | const char *parent_name; |
@@ -270,10 +491,19 @@ static int axi_clkgen_probe(struct platform_device *pdev) | |||
270 | struct resource *mem; | 491 | struct resource *mem; |
271 | struct clk *clk; | 492 | struct clk *clk; |
272 | 493 | ||
494 | if (!pdev->dev.of_node) | ||
495 | return -ENODEV; | ||
496 | |||
497 | id = of_match_node(axi_clkgen_ids, pdev->dev.of_node); | ||
498 | if (!id) | ||
499 | return -ENODEV; | ||
500 | |||
273 | axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL); | 501 | axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL); |
274 | if (!axi_clkgen) | 502 | if (!axi_clkgen) |
275 | return -ENOMEM; | 503 | return -ENOMEM; |
276 | 504 | ||
505 | axi_clkgen->mmcm_ops = id->data; | ||
506 | |||
277 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 507 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
278 | axi_clkgen->base = devm_ioremap_resource(&pdev->dev, mem); | 508 | axi_clkgen->base = devm_ioremap_resource(&pdev->dev, mem); |
279 | if (IS_ERR(axi_clkgen->base)) | 509 | if (IS_ERR(axi_clkgen->base)) |
@@ -289,10 +519,12 @@ static int axi_clkgen_probe(struct platform_device *pdev) | |||
289 | 519 | ||
290 | init.name = clk_name; | 520 | init.name = clk_name; |
291 | init.ops = &axi_clkgen_ops; | 521 | init.ops = &axi_clkgen_ops; |
292 | init.flags = 0; | 522 | init.flags = CLK_SET_RATE_GATE; |
293 | init.parent_names = &parent_name; | 523 | init.parent_names = &parent_name; |
294 | init.num_parents = 1; | 524 | init.num_parents = 1; |
295 | 525 | ||
526 | axi_clkgen_mmcm_enable(axi_clkgen, false); | ||
527 | |||
296 | axi_clkgen->clk_hw.init = &init; | 528 | axi_clkgen->clk_hw.init = &init; |
297 | clk = devm_clk_register(&pdev->dev, &axi_clkgen->clk_hw); | 529 | clk = devm_clk_register(&pdev->dev, &axi_clkgen->clk_hw); |
298 | if (IS_ERR(clk)) | 530 | if (IS_ERR(clk)) |
@@ -309,12 +541,6 @@ static int axi_clkgen_remove(struct platform_device *pdev) | |||
309 | return 0; | 541 | return 0; |
310 | } | 542 | } |
311 | 543 | ||
312 | static const struct of_device_id axi_clkgen_ids[] = { | ||
313 | { .compatible = "adi,axi-clkgen-1.00.a" }, | ||
314 | { }, | ||
315 | }; | ||
316 | MODULE_DEVICE_TABLE(of, axi_clkgen_ids); | ||
317 | |||
318 | static struct platform_driver axi_clkgen_driver = { | 544 | static struct platform_driver axi_clkgen_driver = { |
319 | .driver = { | 545 | .driver = { |
320 | .name = "adi-axi-clkgen", | 546 | .name = "adi-axi-clkgen", |
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 5543b7df8e16..ec22112e569f 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c | |||
@@ -24,7 +24,7 @@ | |||
24 | * Traits of this clock: | 24 | * Traits of this clock: |
25 | * prepare - clk_prepare only ensures that parents are prepared | 25 | * prepare - clk_prepare only ensures that parents are prepared |
26 | * enable - clk_enable only ensures that parents are enabled | 26 | * enable - clk_enable only ensures that parents are enabled |
27 | * rate - rate is adjustable. clk->rate = parent->rate / divisor | 27 | * rate - rate is adjustable. clk->rate = DIV_ROUND_UP(parent->rate / divisor) |
28 | * parent - fixed parent. No clk_set_parent support | 28 | * parent - fixed parent. No clk_set_parent support |
29 | */ | 29 | */ |
30 | 30 | ||
@@ -115,7 +115,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, | |||
115 | return parent_rate; | 115 | return parent_rate; |
116 | } | 116 | } |
117 | 117 | ||
118 | return parent_rate / div; | 118 | return DIV_ROUND_UP(parent_rate, div); |
119 | } | 119 | } |
120 | 120 | ||
121 | /* | 121 | /* |
@@ -185,7 +185,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, | |||
185 | } | 185 | } |
186 | parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), | 186 | parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), |
187 | MULT_ROUND_UP(rate, i)); | 187 | MULT_ROUND_UP(rate, i)); |
188 | now = parent_rate / i; | 188 | now = DIV_ROUND_UP(parent_rate, i); |
189 | if (now <= rate && now > best) { | 189 | if (now <= rate && now > best) { |
190 | bestdiv = i; | 190 | bestdiv = i; |
191 | best = now; | 191 | best = now; |
@@ -207,7 +207,7 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, | |||
207 | int div; | 207 | int div; |
208 | div = clk_divider_bestdiv(hw, rate, prate); | 208 | div = clk_divider_bestdiv(hw, rate, prate); |
209 | 209 | ||
210 | return *prate / div; | 210 | return DIV_ROUND_UP(*prate, div); |
211 | } | 211 | } |
212 | 212 | ||
213 | static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, | 213 | static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, |
@@ -218,7 +218,7 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, | |||
218 | unsigned long flags = 0; | 218 | unsigned long flags = 0; |
219 | u32 val; | 219 | u32 val; |
220 | 220 | ||
221 | div = parent_rate / rate; | 221 | div = DIV_ROUND_UP(parent_rate, rate); |
222 | value = _get_val(divider, div); | 222 | value = _get_val(divider, div); |
223 | 223 | ||
224 | if (value > div_mask(divider)) | 224 | if (value > div_mask(divider)) |
diff --git a/drivers/clk/clk-moxart.c b/drivers/clk/clk-moxart.c new file mode 100644 index 000000000000..30a3b6999e10 --- /dev/null +++ b/drivers/clk/clk-moxart.c | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * MOXA ART SoCs clock driver. | ||
3 | * | ||
4 | * Copyright (C) 2013 Jonas Jensen | ||
5 | * | ||
6 | * Jonas Jensen <jonas.jensen@gmail.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/clk-provider.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/of_address.h> | ||
16 | #include <linux/clkdev.h> | ||
17 | |||
18 | void __init moxart_of_pll_clk_init(struct device_node *node) | ||
19 | { | ||
20 | static void __iomem *base; | ||
21 | struct clk *clk, *ref_clk; | ||
22 | unsigned int mul; | ||
23 | const char *name = node->name; | ||
24 | const char *parent_name; | ||
25 | |||
26 | of_property_read_string(node, "clock-output-names", &name); | ||
27 | parent_name = of_clk_get_parent_name(node, 0); | ||
28 | |||
29 | base = of_iomap(node, 0); | ||
30 | if (!base) { | ||
31 | pr_err("%s: of_iomap failed\n", node->full_name); | ||
32 | return; | ||
33 | } | ||
34 | |||
35 | mul = readl(base + 0x30) >> 3 & 0x3f; | ||
36 | iounmap(base); | ||
37 | |||
38 | ref_clk = of_clk_get(node, 0); | ||
39 | if (IS_ERR(ref_clk)) { | ||
40 | pr_err("%s: of_clk_get failed\n", node->full_name); | ||
41 | return; | ||
42 | } | ||
43 | |||
44 | clk = clk_register_fixed_factor(NULL, name, parent_name, 0, mul, 1); | ||
45 | if (IS_ERR(clk)) { | ||
46 | pr_err("%s: failed to register clock\n", node->full_name); | ||
47 | return; | ||
48 | } | ||
49 | |||
50 | clk_register_clkdev(clk, NULL, name); | ||
51 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
52 | } | ||
53 | CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock", | ||
54 | moxart_of_pll_clk_init); | ||
55 | |||
56 | void __init moxart_of_apb_clk_init(struct device_node *node) | ||
57 | { | ||
58 | static void __iomem *base; | ||
59 | struct clk *clk, *pll_clk; | ||
60 | unsigned int div, val; | ||
61 | unsigned int div_idx[] = { 2, 3, 4, 6, 8}; | ||
62 | const char *name = node->name; | ||
63 | const char *parent_name; | ||
64 | |||
65 | of_property_read_string(node, "clock-output-names", &name); | ||
66 | parent_name = of_clk_get_parent_name(node, 0); | ||
67 | |||
68 | base = of_iomap(node, 0); | ||
69 | if (!base) { | ||
70 | pr_err("%s: of_iomap failed\n", node->full_name); | ||
71 | return; | ||
72 | } | ||
73 | |||
74 | val = readl(base + 0xc) >> 4 & 0x7; | ||
75 | iounmap(base); | ||
76 | |||
77 | if (val > 4) | ||
78 | val = 0; | ||
79 | div = div_idx[val] * 2; | ||
80 | |||
81 | pll_clk = of_clk_get(node, 0); | ||
82 | if (IS_ERR(pll_clk)) { | ||
83 | pr_err("%s: of_clk_get failed\n", node->full_name); | ||
84 | return; | ||
85 | } | ||
86 | |||
87 | clk = clk_register_fixed_factor(NULL, name, parent_name, 0, 1, div); | ||
88 | if (IS_ERR(clk)) { | ||
89 | pr_err("%s: failed to register clock\n", node->full_name); | ||
90 | return; | ||
91 | } | ||
92 | |||
93 | clk_register_clkdev(clk, NULL, name); | ||
94 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
95 | } | ||
96 | CLK_OF_DECLARE(moxart_apb_clock, "moxa,moxart-apb-clock", | ||
97 | moxart_of_apb_clk_init); | ||
diff --git a/drivers/clk/clk-nomadik.c b/drivers/clk/clk-nomadik.c index 6a934a5296bd..05e04ce0f148 100644 --- a/drivers/clk/clk-nomadik.c +++ b/drivers/clk/clk-nomadik.c | |||
@@ -494,6 +494,9 @@ static const struct file_operations nomadik_src_clk_debugfs_ops = { | |||
494 | 494 | ||
495 | static int __init nomadik_src_clk_init_debugfs(void) | 495 | static int __init nomadik_src_clk_init_debugfs(void) |
496 | { | 496 | { |
497 | /* Vital for multiplatform */ | ||
498 | if (!src_base) | ||
499 | return -ENODEV; | ||
497 | src_pcksr0_boot = readl(src_base + SRC_PCKSR0); | 500 | src_pcksr0_boot = readl(src_base + SRC_PCKSR0); |
498 | src_pcksr1_boot = readl(src_base + SRC_PCKSR1); | 501 | src_pcksr1_boot = readl(src_base + SRC_PCKSR1); |
499 | debugfs_create_file("nomadik-src-clk", S_IFREG | S_IRUGO, | 502 | debugfs_create_file("nomadik-src-clk", S_IFREG | S_IRUGO, |
diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c index 00a3abe103a5..f4c1f0881b6c 100644 --- a/drivers/clk/clk-s2mps11.c +++ b/drivers/clk/clk-s2mps11.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/clk-provider.h> | 27 | #include <linux/clk-provider.h> |
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/mfd/samsung/s2mps11.h> | 29 | #include <linux/mfd/samsung/s2mps11.h> |
30 | #include <linux/mfd/samsung/s5m8767.h> | ||
30 | #include <linux/mfd/samsung/core.h> | 31 | #include <linux/mfd/samsung/core.h> |
31 | 32 | ||
32 | #define s2mps11_name(a) (a->hw.init->name) | 33 | #define s2mps11_name(a) (a->hw.init->name) |
@@ -48,6 +49,7 @@ struct s2mps11_clk { | |||
48 | struct clk_lookup *lookup; | 49 | struct clk_lookup *lookup; |
49 | u32 mask; | 50 | u32 mask; |
50 | bool enabled; | 51 | bool enabled; |
52 | unsigned int reg; | ||
51 | }; | 53 | }; |
52 | 54 | ||
53 | static struct s2mps11_clk *to_s2mps11_clk(struct clk_hw *hw) | 55 | static struct s2mps11_clk *to_s2mps11_clk(struct clk_hw *hw) |
@@ -61,7 +63,7 @@ static int s2mps11_clk_prepare(struct clk_hw *hw) | |||
61 | int ret; | 63 | int ret; |
62 | 64 | ||
63 | ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, | 65 | ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, |
64 | S2MPS11_REG_RTC_CTRL, | 66 | s2mps11->reg, |
65 | s2mps11->mask, s2mps11->mask); | 67 | s2mps11->mask, s2mps11->mask); |
66 | if (!ret) | 68 | if (!ret) |
67 | s2mps11->enabled = true; | 69 | s2mps11->enabled = true; |
@@ -74,7 +76,7 @@ static void s2mps11_clk_unprepare(struct clk_hw *hw) | |||
74 | struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw); | 76 | struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw); |
75 | int ret; | 77 | int ret; |
76 | 78 | ||
77 | ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, S2MPS11_REG_RTC_CTRL, | 79 | ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, s2mps11->reg, |
78 | s2mps11->mask, ~s2mps11->mask); | 80 | s2mps11->mask, ~s2mps11->mask); |
79 | 81 | ||
80 | if (!ret) | 82 | if (!ret) |
@@ -155,6 +157,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev) | |||
155 | struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); | 157 | struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); |
156 | struct s2mps11_clk *s2mps11_clks, *s2mps11_clk; | 158 | struct s2mps11_clk *s2mps11_clks, *s2mps11_clk; |
157 | struct device_node *clk_np = NULL; | 159 | struct device_node *clk_np = NULL; |
160 | unsigned int s2mps11_reg; | ||
158 | int i, ret = 0; | 161 | int i, ret = 0; |
159 | u32 val; | 162 | u32 val; |
160 | 163 | ||
@@ -169,13 +172,26 @@ static int s2mps11_clk_probe(struct platform_device *pdev) | |||
169 | if (IS_ERR(clk_np)) | 172 | if (IS_ERR(clk_np)) |
170 | return PTR_ERR(clk_np); | 173 | return PTR_ERR(clk_np); |
171 | 174 | ||
175 | switch(platform_get_device_id(pdev)->driver_data) { | ||
176 | case S2MPS11X: | ||
177 | s2mps11_reg = S2MPS11_REG_RTC_CTRL; | ||
178 | break; | ||
179 | case S5M8767X: | ||
180 | s2mps11_reg = S5M8767_REG_CTRL1; | ||
181 | break; | ||
182 | default: | ||
183 | dev_err(&pdev->dev, "Invalid device type\n"); | ||
184 | return -EINVAL; | ||
185 | }; | ||
186 | |||
172 | for (i = 0; i < S2MPS11_CLKS_NUM; i++, s2mps11_clk++) { | 187 | for (i = 0; i < S2MPS11_CLKS_NUM; i++, s2mps11_clk++) { |
173 | s2mps11_clk->iodev = iodev; | 188 | s2mps11_clk->iodev = iodev; |
174 | s2mps11_clk->hw.init = &s2mps11_clks_init[i]; | 189 | s2mps11_clk->hw.init = &s2mps11_clks_init[i]; |
175 | s2mps11_clk->mask = 1 << i; | 190 | s2mps11_clk->mask = 1 << i; |
191 | s2mps11_clk->reg = s2mps11_reg; | ||
176 | 192 | ||
177 | ret = regmap_read(s2mps11_clk->iodev->regmap_pmic, | 193 | ret = regmap_read(s2mps11_clk->iodev->regmap_pmic, |
178 | S2MPS11_REG_RTC_CTRL, &val); | 194 | s2mps11_clk->reg, &val); |
179 | if (ret < 0) | 195 | if (ret < 0) |
180 | goto err_reg; | 196 | goto err_reg; |
181 | 197 | ||
@@ -241,7 +257,8 @@ static int s2mps11_clk_remove(struct platform_device *pdev) | |||
241 | } | 257 | } |
242 | 258 | ||
243 | static const struct platform_device_id s2mps11_clk_id[] = { | 259 | static const struct platform_device_id s2mps11_clk_id[] = { |
244 | { "s2mps11-clk", 0}, | 260 | { "s2mps11-clk", S2MPS11X}, |
261 | { "s5m8767-clk", S5M8767X}, | ||
245 | { }, | 262 | { }, |
246 | }; | 263 | }; |
247 | MODULE_DEVICE_TABLE(platform, s2mps11_clk_id); | 264 | MODULE_DEVICE_TABLE(platform, s2mps11_clk_id); |
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 5517944495d8..895b3d204e22 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
@@ -1339,8 +1339,11 @@ static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate) | |||
1339 | if (clk->notifier_count) | 1339 | if (clk->notifier_count) |
1340 | ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate); | 1340 | ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate); |
1341 | 1341 | ||
1342 | if (ret & NOTIFY_STOP_MASK) | 1342 | if (ret & NOTIFY_STOP_MASK) { |
1343 | pr_debug("%s: clk notifier callback for clock %s aborted with error %d\n", | ||
1344 | __func__, clk->name, ret); | ||
1343 | goto out; | 1345 | goto out; |
1346 | } | ||
1344 | 1347 | ||
1345 | hlist_for_each_entry(child, &clk->children, child_node) { | 1348 | hlist_for_each_entry(child, &clk->children, child_node) { |
1346 | ret = __clk_speculate_rates(child, new_rate); | 1349 | ret = __clk_speculate_rates(child, new_rate); |
@@ -2226,24 +2229,25 @@ EXPORT_SYMBOL_GPL(devm_clk_unregister); | |||
2226 | */ | 2229 | */ |
2227 | int __clk_get(struct clk *clk) | 2230 | int __clk_get(struct clk *clk) |
2228 | { | 2231 | { |
2229 | if (clk && !try_module_get(clk->owner)) | 2232 | if (clk) { |
2230 | return 0; | 2233 | if (!try_module_get(clk->owner)) |
2234 | return 0; | ||
2231 | 2235 | ||
2232 | kref_get(&clk->ref); | 2236 | kref_get(&clk->ref); |
2237 | } | ||
2233 | return 1; | 2238 | return 1; |
2234 | } | 2239 | } |
2235 | 2240 | ||
2236 | void __clk_put(struct clk *clk) | 2241 | void __clk_put(struct clk *clk) |
2237 | { | 2242 | { |
2238 | if (WARN_ON_ONCE(IS_ERR(clk))) | 2243 | if (!clk || WARN_ON_ONCE(IS_ERR(clk))) |
2239 | return; | 2244 | return; |
2240 | 2245 | ||
2241 | clk_prepare_lock(); | 2246 | clk_prepare_lock(); |
2242 | kref_put(&clk->ref, __clk_release); | 2247 | kref_put(&clk->ref, __clk_release); |
2243 | clk_prepare_unlock(); | 2248 | clk_prepare_unlock(); |
2244 | 2249 | ||
2245 | if (clk) | 2250 | module_put(clk->owner); |
2246 | module_put(clk->owner); | ||
2247 | } | 2251 | } |
2248 | 2252 | ||
2249 | /*** clk rate change notifiers ***/ | 2253 | /*** clk rate change notifiers ***/ |
@@ -2259,20 +2263,11 @@ void __clk_put(struct clk *clk) | |||
2259 | * re-enter into the clk framework by calling any top-level clk APIs; | 2263 | * re-enter into the clk framework by calling any top-level clk APIs; |
2260 | * this will cause a nested prepare_lock mutex. | 2264 | * this will cause a nested prepare_lock mutex. |
2261 | * | 2265 | * |
2262 | * Pre-change notifier callbacks will be passed the current, pre-change | 2266 | * In all notification cases cases (pre, post and abort rate change) the |
2263 | * rate of the clk via struct clk_notifier_data.old_rate. The new, | 2267 | * original clock rate is passed to the callback via struct |
2264 | * post-change rate of the clk is passed via struct | 2268 | * clk_notifier_data.old_rate and the new frequency is passed via struct |
2265 | * clk_notifier_data.new_rate. | 2269 | * clk_notifier_data.new_rate. |
2266 | * | 2270 | * |
2267 | * Post-change notifiers will pass the now-current, post-change rate of | ||
2268 | * the clk in both struct clk_notifier_data.old_rate and struct | ||
2269 | * clk_notifier_data.new_rate. | ||
2270 | * | ||
2271 | * Abort-change notifiers are effectively the opposite of pre-change | ||
2272 | * notifiers: the original pre-change clk rate is passed in via struct | ||
2273 | * clk_notifier_data.new_rate and the failed post-change rate is passed | ||
2274 | * in via struct clk_notifier_data.old_rate. | ||
2275 | * | ||
2276 | * clk_notifier_register() must be called from non-atomic context. | 2271 | * clk_notifier_register() must be called from non-atomic context. |
2277 | * Returns -EINVAL if called with null arguments, -ENOMEM upon | 2272 | * Returns -EINVAL if called with null arguments, -ENOMEM upon |
2278 | * allocation failure; otherwise, passes along the return value of | 2273 | * allocation failure; otherwise, passes along the return value of |
@@ -2472,7 +2467,7 @@ EXPORT_SYMBOL_GPL(of_clk_del_provider); | |||
2472 | struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec) | 2467 | struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec) |
2473 | { | 2468 | { |
2474 | struct of_clk_provider *provider; | 2469 | struct of_clk_provider *provider; |
2475 | struct clk *clk = ERR_PTR(-ENOENT); | 2470 | struct clk *clk = ERR_PTR(-EPROBE_DEFER); |
2476 | 2471 | ||
2477 | /* Check if we have such a provider in our array */ | 2472 | /* Check if we have such a provider in our array */ |
2478 | list_for_each_entry(provider, &of_clk_providers, link) { | 2473 | list_for_each_entry(provider, &of_clk_providers, link) { |
@@ -2505,8 +2500,12 @@ EXPORT_SYMBOL_GPL(of_clk_get_parent_count); | |||
2505 | const char *of_clk_get_parent_name(struct device_node *np, int index) | 2500 | const char *of_clk_get_parent_name(struct device_node *np, int index) |
2506 | { | 2501 | { |
2507 | struct of_phandle_args clkspec; | 2502 | struct of_phandle_args clkspec; |
2503 | struct property *prop; | ||
2508 | const char *clk_name; | 2504 | const char *clk_name; |
2505 | const __be32 *vp; | ||
2506 | u32 pv; | ||
2509 | int rc; | 2507 | int rc; |
2508 | int count; | ||
2510 | 2509 | ||
2511 | if (index < 0) | 2510 | if (index < 0) |
2512 | return NULL; | 2511 | return NULL; |
@@ -2516,8 +2515,22 @@ const char *of_clk_get_parent_name(struct device_node *np, int index) | |||
2516 | if (rc) | 2515 | if (rc) |
2517 | return NULL; | 2516 | return NULL; |
2518 | 2517 | ||
2518 | index = clkspec.args_count ? clkspec.args[0] : 0; | ||
2519 | count = 0; | ||
2520 | |||
2521 | /* if there is an indices property, use it to transfer the index | ||
2522 | * specified into an array offset for the clock-output-names property. | ||
2523 | */ | ||
2524 | of_property_for_each_u32(clkspec.np, "clock-indices", prop, vp, pv) { | ||
2525 | if (index == pv) { | ||
2526 | index = count; | ||
2527 | break; | ||
2528 | } | ||
2529 | count++; | ||
2530 | } | ||
2531 | |||
2519 | if (of_property_read_string_index(clkspec.np, "clock-output-names", | 2532 | if (of_property_read_string_index(clkspec.np, "clock-output-names", |
2520 | clkspec.args_count ? clkspec.args[0] : 0, | 2533 | index, |
2521 | &clk_name) < 0) | 2534 | &clk_name) < 0) |
2522 | clk_name = clkspec.np->name; | 2535 | clk_name = clkspec.np->name; |
2523 | 2536 | ||
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index 48f67218247c..a360b2eca5cb 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c | |||
@@ -167,6 +167,8 @@ struct clk *clk_get(struct device *dev, const char *con_id) | |||
167 | clk = of_clk_get_by_name(dev->of_node, con_id); | 167 | clk = of_clk_get_by_name(dev->of_node, con_id); |
168 | if (!IS_ERR(clk)) | 168 | if (!IS_ERR(clk)) |
169 | return clk; | 169 | return clk; |
170 | if (PTR_ERR(clk) == -EPROBE_DEFER) | ||
171 | return clk; | ||
170 | } | 172 | } |
171 | 173 | ||
172 | return clk_get_sys(dev_id, con_id); | 174 | return clk_get_sys(dev_id, con_id); |
diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c index f24ad6a3a797..38faa469d288 100644 --- a/drivers/clk/hisilicon/clk-hi3620.c +++ b/drivers/clk/hisilicon/clk-hi3620.c | |||
@@ -240,3 +240,277 @@ static void __init hi3620_clk_init(struct device_node *np) | |||
240 | base); | 240 | base); |
241 | } | 241 | } |
242 | CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init); | 242 | CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init); |
243 | |||
244 | struct hisi_mmc_clock { | ||
245 | unsigned int id; | ||
246 | const char *name; | ||
247 | const char *parent_name; | ||
248 | unsigned long flags; | ||
249 | u32 clken_reg; | ||
250 | u32 clken_bit; | ||
251 | u32 div_reg; | ||
252 | u32 div_off; | ||
253 | u32 div_bits; | ||
254 | u32 drv_reg; | ||
255 | u32 drv_off; | ||
256 | u32 drv_bits; | ||
257 | u32 sam_reg; | ||
258 | u32 sam_off; | ||
259 | u32 sam_bits; | ||
260 | }; | ||
261 | |||
262 | struct clk_mmc { | ||
263 | struct clk_hw hw; | ||
264 | u32 id; | ||
265 | void __iomem *clken_reg; | ||
266 | u32 clken_bit; | ||
267 | void __iomem *div_reg; | ||
268 | u32 div_off; | ||
269 | u32 div_bits; | ||
270 | void __iomem *drv_reg; | ||
271 | u32 drv_off; | ||
272 | u32 drv_bits; | ||
273 | void __iomem *sam_reg; | ||
274 | u32 sam_off; | ||
275 | u32 sam_bits; | ||
276 | }; | ||
277 | |||
278 | #define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw) | ||
279 | |||
280 | static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = { | ||
281 | { HI3620_SD_CIUCLK, "sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4, 4, 0x1f8, 8, 4}, | ||
282 | { HI3620_MMC_CIUCLK1, "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3, 0x1f8, 16, 4, 0x1f8, 20, 4}, | ||
283 | { HI3620_MMC_CIUCLK2, "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3, 0x1f8, 28, 4, 0x1fc, 0, 4}, | ||
284 | { HI3620_MMC_CIUCLK3, "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3, 0x1fc, 8, 4, 0x1fc, 12, 4}, | ||
285 | }; | ||
286 | |||
287 | static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw, | ||
288 | unsigned long parent_rate) | ||
289 | { | ||
290 | switch (parent_rate) { | ||
291 | case 26000000: | ||
292 | return 13000000; | ||
293 | case 180000000: | ||
294 | return 25000000; | ||
295 | case 360000000: | ||
296 | return 50000000; | ||
297 | case 720000000: | ||
298 | return 100000000; | ||
299 | case 1440000000: | ||
300 | return 180000000; | ||
301 | default: | ||
302 | return parent_rate; | ||
303 | } | ||
304 | } | ||
305 | |||
306 | static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate, | ||
307 | unsigned long *best_parent_rate, | ||
308 | struct clk **best_parent_p) | ||
309 | { | ||
310 | struct clk_mmc *mclk = to_mmc(hw); | ||
311 | unsigned long best = 0; | ||
312 | |||
313 | if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) { | ||
314 | rate = 13000000; | ||
315 | best = 26000000; | ||
316 | } else if (rate <= 26000000) { | ||
317 | rate = 25000000; | ||
318 | best = 180000000; | ||
319 | } else if (rate <= 52000000) { | ||
320 | rate = 50000000; | ||
321 | best = 360000000; | ||
322 | } else if (rate <= 100000000) { | ||
323 | rate = 100000000; | ||
324 | best = 720000000; | ||
325 | } else { | ||
326 | /* max is 180M */ | ||
327 | rate = 180000000; | ||
328 | best = 1440000000; | ||
329 | } | ||
330 | *best_parent_rate = best; | ||
331 | return rate; | ||
332 | } | ||
333 | |||
334 | static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len) | ||
335 | { | ||
336 | u32 i; | ||
337 | |||
338 | if (para >= 0) { | ||
339 | for (i = 0; i < len; i++) { | ||
340 | if (para % 2) | ||
341 | val |= 1 << (off + i); | ||
342 | else | ||
343 | val &= ~(1 << (off + i)); | ||
344 | para = para >> 1; | ||
345 | } | ||
346 | } | ||
347 | return val; | ||
348 | } | ||
349 | |||
350 | static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate) | ||
351 | { | ||
352 | struct clk_mmc *mclk = to_mmc(hw); | ||
353 | unsigned long flags; | ||
354 | u32 sam, drv, div, val; | ||
355 | static DEFINE_SPINLOCK(mmc_clk_lock); | ||
356 | |||
357 | switch (rate) { | ||
358 | case 13000000: | ||
359 | sam = 3; | ||
360 | drv = 1; | ||
361 | div = 1; | ||
362 | break; | ||
363 | case 25000000: | ||
364 | sam = 13; | ||
365 | drv = 6; | ||
366 | div = 6; | ||
367 | break; | ||
368 | case 50000000: | ||
369 | sam = 3; | ||
370 | drv = 6; | ||
371 | div = 6; | ||
372 | break; | ||
373 | case 100000000: | ||
374 | sam = 6; | ||
375 | drv = 4; | ||
376 | div = 6; | ||
377 | break; | ||
378 | case 180000000: | ||
379 | sam = 6; | ||
380 | drv = 4; | ||
381 | div = 7; | ||
382 | break; | ||
383 | default: | ||
384 | return -EINVAL; | ||
385 | } | ||
386 | |||
387 | spin_lock_irqsave(&mmc_clk_lock, flags); | ||
388 | |||
389 | val = readl_relaxed(mclk->clken_reg); | ||
390 | val &= ~(1 << mclk->clken_bit); | ||
391 | writel_relaxed(val, mclk->clken_reg); | ||
392 | |||
393 | val = readl_relaxed(mclk->sam_reg); | ||
394 | val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits); | ||
395 | writel_relaxed(val, mclk->sam_reg); | ||
396 | |||
397 | val = readl_relaxed(mclk->drv_reg); | ||
398 | val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits); | ||
399 | writel_relaxed(val, mclk->drv_reg); | ||
400 | |||
401 | val = readl_relaxed(mclk->div_reg); | ||
402 | val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits); | ||
403 | writel_relaxed(val, mclk->div_reg); | ||
404 | |||
405 | val = readl_relaxed(mclk->clken_reg); | ||
406 | val |= 1 << mclk->clken_bit; | ||
407 | writel_relaxed(val, mclk->clken_reg); | ||
408 | |||
409 | spin_unlock_irqrestore(&mmc_clk_lock, flags); | ||
410 | |||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | static int mmc_clk_prepare(struct clk_hw *hw) | ||
415 | { | ||
416 | struct clk_mmc *mclk = to_mmc(hw); | ||
417 | unsigned long rate; | ||
418 | |||
419 | if (mclk->id == HI3620_MMC_CIUCLK1) | ||
420 | rate = 13000000; | ||
421 | else | ||
422 | rate = 25000000; | ||
423 | |||
424 | return mmc_clk_set_timing(hw, rate); | ||
425 | } | ||
426 | |||
427 | static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate, | ||
428 | unsigned long parent_rate) | ||
429 | { | ||
430 | return mmc_clk_set_timing(hw, rate); | ||
431 | } | ||
432 | |||
433 | static struct clk_ops clk_mmc_ops = { | ||
434 | .prepare = mmc_clk_prepare, | ||
435 | .determine_rate = mmc_clk_determine_rate, | ||
436 | .set_rate = mmc_clk_set_rate, | ||
437 | .recalc_rate = mmc_clk_recalc_rate, | ||
438 | }; | ||
439 | |||
440 | static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk, | ||
441 | void __iomem *base, struct device_node *np) | ||
442 | { | ||
443 | struct clk_mmc *mclk; | ||
444 | struct clk *clk; | ||
445 | struct clk_init_data init; | ||
446 | |||
447 | mclk = kzalloc(sizeof(*mclk), GFP_KERNEL); | ||
448 | if (!mclk) { | ||
449 | pr_err("%s: fail to allocate mmc clk\n", __func__); | ||
450 | return ERR_PTR(-ENOMEM); | ||
451 | } | ||
452 | |||
453 | init.name = mmc_clk->name; | ||
454 | init.ops = &clk_mmc_ops; | ||
455 | init.flags = mmc_clk->flags | CLK_IS_BASIC; | ||
456 | init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL); | ||
457 | init.num_parents = (mmc_clk->parent_name ? 1 : 0); | ||
458 | mclk->hw.init = &init; | ||
459 | |||
460 | mclk->id = mmc_clk->id; | ||
461 | mclk->clken_reg = base + mmc_clk->clken_reg; | ||
462 | mclk->clken_bit = mmc_clk->clken_bit; | ||
463 | mclk->div_reg = base + mmc_clk->div_reg; | ||
464 | mclk->div_off = mmc_clk->div_off; | ||
465 | mclk->div_bits = mmc_clk->div_bits; | ||
466 | mclk->drv_reg = base + mmc_clk->drv_reg; | ||
467 | mclk->drv_off = mmc_clk->drv_off; | ||
468 | mclk->drv_bits = mmc_clk->drv_bits; | ||
469 | mclk->sam_reg = base + mmc_clk->sam_reg; | ||
470 | mclk->sam_off = mmc_clk->sam_off; | ||
471 | mclk->sam_bits = mmc_clk->sam_bits; | ||
472 | |||
473 | clk = clk_register(NULL, &mclk->hw); | ||
474 | if (WARN_ON(IS_ERR(clk))) | ||
475 | kfree(mclk); | ||
476 | return clk; | ||
477 | } | ||
478 | |||
479 | static void __init hi3620_mmc_clk_init(struct device_node *node) | ||
480 | { | ||
481 | void __iomem *base; | ||
482 | int i, num = ARRAY_SIZE(hi3620_mmc_clks); | ||
483 | struct clk_onecell_data *clk_data; | ||
484 | |||
485 | if (!node) { | ||
486 | pr_err("failed to find pctrl node in DTS\n"); | ||
487 | return; | ||
488 | } | ||
489 | |||
490 | base = of_iomap(node, 0); | ||
491 | if (!base) { | ||
492 | pr_err("failed to map pctrl\n"); | ||
493 | return; | ||
494 | } | ||
495 | |||
496 | clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); | ||
497 | if (WARN_ON(!clk_data)) | ||
498 | return; | ||
499 | |||
500 | clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL); | ||
501 | if (!clk_data->clks) { | ||
502 | pr_err("%s: fail to allocate mmc clk\n", __func__); | ||
503 | return; | ||
504 | } | ||
505 | |||
506 | for (i = 0; i < num; i++) { | ||
507 | struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i]; | ||
508 | clk_data->clks[mmc_clk->id] = | ||
509 | hisi_register_clk_mmc(mmc_clk, base, node); | ||
510 | } | ||
511 | |||
512 | clk_data->clk_num = num; | ||
513 | of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); | ||
514 | } | ||
515 | |||
516 | CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init); | ||
diff --git a/drivers/clk/keystone/gate.c b/drivers/clk/keystone/gate.c index 17a598398a53..86f1e362eafb 100644 --- a/drivers/clk/keystone/gate.c +++ b/drivers/clk/keystone/gate.c | |||
@@ -179,6 +179,7 @@ static struct clk *clk_register_psc(struct device *dev, | |||
179 | 179 | ||
180 | init.name = name; | 180 | init.name = name; |
181 | init.ops = &clk_psc_ops; | 181 | init.ops = &clk_psc_ops; |
182 | init.flags = 0; | ||
182 | init.parent_names = (parent_name ? &parent_name : NULL); | 183 | init.parent_names = (parent_name ? &parent_name : NULL); |
183 | init.num_parents = (parent_name ? 1 : 0); | 184 | init.num_parents = (parent_name ? 1 : 0); |
184 | 185 | ||
diff --git a/drivers/clk/mvebu/armada-370.c b/drivers/clk/mvebu/armada-370.c index 81a202d12a7a..bef198a83863 100644 --- a/drivers/clk/mvebu/armada-370.c +++ b/drivers/clk/mvebu/armada-370.c | |||
@@ -141,13 +141,6 @@ static const struct coreclk_soc_desc a370_coreclks = { | |||
141 | .num_ratios = ARRAY_SIZE(a370_coreclk_ratios), | 141 | .num_ratios = ARRAY_SIZE(a370_coreclk_ratios), |
142 | }; | 142 | }; |
143 | 143 | ||
144 | static void __init a370_coreclk_init(struct device_node *np) | ||
145 | { | ||
146 | mvebu_coreclk_setup(np, &a370_coreclks); | ||
147 | } | ||
148 | CLK_OF_DECLARE(a370_core_clk, "marvell,armada-370-core-clock", | ||
149 | a370_coreclk_init); | ||
150 | |||
151 | /* | 144 | /* |
152 | * Clock Gating Control | 145 | * Clock Gating Control |
153 | */ | 146 | */ |
@@ -168,9 +161,15 @@ static const struct clk_gating_soc_desc a370_gating_desc[] __initconst = { | |||
168 | { } | 161 | { } |
169 | }; | 162 | }; |
170 | 163 | ||
171 | static void __init a370_clk_gating_init(struct device_node *np) | 164 | static void __init a370_clk_init(struct device_node *np) |
172 | { | 165 | { |
173 | mvebu_clk_gating_setup(np, a370_gating_desc); | 166 | struct device_node *cgnp = |
167 | of_find_compatible_node(NULL, NULL, "marvell,armada-370-gating-clock"); | ||
168 | |||
169 | mvebu_coreclk_setup(np, &a370_coreclks); | ||
170 | |||
171 | if (cgnp) | ||
172 | mvebu_clk_gating_setup(cgnp, a370_gating_desc); | ||
174 | } | 173 | } |
175 | CLK_OF_DECLARE(a370_clk_gating, "marvell,armada-370-gating-clock", | 174 | CLK_OF_DECLARE(a370_clk, "marvell,armada-370-core-clock", a370_clk_init); |
176 | a370_clk_gating_init); | 175 | |
diff --git a/drivers/clk/mvebu/armada-xp.c b/drivers/clk/mvebu/armada-xp.c index 9922c4475aa8..b3094315a3c0 100644 --- a/drivers/clk/mvebu/armada-xp.c +++ b/drivers/clk/mvebu/armada-xp.c | |||
@@ -158,13 +158,6 @@ static const struct coreclk_soc_desc axp_coreclks = { | |||
158 | .num_ratios = ARRAY_SIZE(axp_coreclk_ratios), | 158 | .num_ratios = ARRAY_SIZE(axp_coreclk_ratios), |
159 | }; | 159 | }; |
160 | 160 | ||
161 | static void __init axp_coreclk_init(struct device_node *np) | ||
162 | { | ||
163 | mvebu_coreclk_setup(np, &axp_coreclks); | ||
164 | } | ||
165 | CLK_OF_DECLARE(axp_core_clk, "marvell,armada-xp-core-clock", | ||
166 | axp_coreclk_init); | ||
167 | |||
168 | /* | 161 | /* |
169 | * Clock Gating Control | 162 | * Clock Gating Control |
170 | */ | 163 | */ |
@@ -202,9 +195,14 @@ static const struct clk_gating_soc_desc axp_gating_desc[] __initconst = { | |||
202 | { } | 195 | { } |
203 | }; | 196 | }; |
204 | 197 | ||
205 | static void __init axp_clk_gating_init(struct device_node *np) | 198 | static void __init axp_clk_init(struct device_node *np) |
206 | { | 199 | { |
207 | mvebu_clk_gating_setup(np, axp_gating_desc); | 200 | struct device_node *cgnp = |
201 | of_find_compatible_node(NULL, NULL, "marvell,armada-xp-gating-clock"); | ||
202 | |||
203 | mvebu_coreclk_setup(np, &axp_coreclks); | ||
204 | |||
205 | if (cgnp) | ||
206 | mvebu_clk_gating_setup(cgnp, axp_gating_desc); | ||
208 | } | 207 | } |
209 | CLK_OF_DECLARE(axp_clk_gating, "marvell,armada-xp-gating-clock", | 208 | CLK_OF_DECLARE(axp_clk, "marvell,armada-xp-core-clock", axp_clk_init); |
210 | axp_clk_gating_init); | ||
diff --git a/drivers/clk/mvebu/dove.c b/drivers/clk/mvebu/dove.c index 38aee1e3f242..b8c2424ac926 100644 --- a/drivers/clk/mvebu/dove.c +++ b/drivers/clk/mvebu/dove.c | |||
@@ -154,12 +154,6 @@ static const struct coreclk_soc_desc dove_coreclks = { | |||
154 | .num_ratios = ARRAY_SIZE(dove_coreclk_ratios), | 154 | .num_ratios = ARRAY_SIZE(dove_coreclk_ratios), |
155 | }; | 155 | }; |
156 | 156 | ||
157 | static void __init dove_coreclk_init(struct device_node *np) | ||
158 | { | ||
159 | mvebu_coreclk_setup(np, &dove_coreclks); | ||
160 | } | ||
161 | CLK_OF_DECLARE(dove_core_clk, "marvell,dove-core-clock", dove_coreclk_init); | ||
162 | |||
163 | /* | 157 | /* |
164 | * Clock Gating Control | 158 | * Clock Gating Control |
165 | */ | 159 | */ |
@@ -186,9 +180,14 @@ static const struct clk_gating_soc_desc dove_gating_desc[] __initconst = { | |||
186 | { } | 180 | { } |
187 | }; | 181 | }; |
188 | 182 | ||
189 | static void __init dove_clk_gating_init(struct device_node *np) | 183 | static void __init dove_clk_init(struct device_node *np) |
190 | { | 184 | { |
191 | mvebu_clk_gating_setup(np, dove_gating_desc); | 185 | struct device_node *cgnp = |
186 | of_find_compatible_node(NULL, NULL, "marvell,dove-gating-clock"); | ||
187 | |||
188 | mvebu_coreclk_setup(np, &dove_coreclks); | ||
189 | |||
190 | if (cgnp) | ||
191 | mvebu_clk_gating_setup(cgnp, dove_gating_desc); | ||
192 | } | 192 | } |
193 | CLK_OF_DECLARE(dove_clk_gating, "marvell,dove-gating-clock", | 193 | CLK_OF_DECLARE(dove_clk, "marvell,dove-core-clock", dove_clk_init); |
194 | dove_clk_gating_init); | ||
diff --git a/drivers/clk/mvebu/kirkwood.c b/drivers/clk/mvebu/kirkwood.c index 2636a55f29f9..ddb666a86500 100644 --- a/drivers/clk/mvebu/kirkwood.c +++ b/drivers/clk/mvebu/kirkwood.c | |||
@@ -193,13 +193,6 @@ static const struct coreclk_soc_desc kirkwood_coreclks = { | |||
193 | .num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios), | 193 | .num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios), |
194 | }; | 194 | }; |
195 | 195 | ||
196 | static void __init kirkwood_coreclk_init(struct device_node *np) | ||
197 | { | ||
198 | mvebu_coreclk_setup(np, &kirkwood_coreclks); | ||
199 | } | ||
200 | CLK_OF_DECLARE(kirkwood_core_clk, "marvell,kirkwood-core-clock", | ||
201 | kirkwood_coreclk_init); | ||
202 | |||
203 | static const struct coreclk_soc_desc mv88f6180_coreclks = { | 196 | static const struct coreclk_soc_desc mv88f6180_coreclks = { |
204 | .get_tclk_freq = kirkwood_get_tclk_freq, | 197 | .get_tclk_freq = kirkwood_get_tclk_freq, |
205 | .get_cpu_freq = mv88f6180_get_cpu_freq, | 198 | .get_cpu_freq = mv88f6180_get_cpu_freq, |
@@ -208,13 +201,6 @@ static const struct coreclk_soc_desc mv88f6180_coreclks = { | |||
208 | .num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios), | 201 | .num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios), |
209 | }; | 202 | }; |
210 | 203 | ||
211 | static void __init mv88f6180_coreclk_init(struct device_node *np) | ||
212 | { | ||
213 | mvebu_coreclk_setup(np, &mv88f6180_coreclks); | ||
214 | } | ||
215 | CLK_OF_DECLARE(mv88f6180_core_clk, "marvell,mv88f6180-core-clock", | ||
216 | mv88f6180_coreclk_init); | ||
217 | |||
218 | /* | 204 | /* |
219 | * Clock Gating Control | 205 | * Clock Gating Control |
220 | */ | 206 | */ |
@@ -239,9 +225,21 @@ static const struct clk_gating_soc_desc kirkwood_gating_desc[] __initconst = { | |||
239 | { } | 225 | { } |
240 | }; | 226 | }; |
241 | 227 | ||
242 | static void __init kirkwood_clk_gating_init(struct device_node *np) | 228 | static void __init kirkwood_clk_init(struct device_node *np) |
243 | { | 229 | { |
244 | mvebu_clk_gating_setup(np, kirkwood_gating_desc); | 230 | struct device_node *cgnp = |
231 | of_find_compatible_node(NULL, NULL, "marvell,kirkwood-gating-clock"); | ||
232 | |||
233 | |||
234 | if (of_device_is_compatible(np, "marvell,mv88f6180-core-clock")) | ||
235 | mvebu_coreclk_setup(np, &mv88f6180_coreclks); | ||
236 | else | ||
237 | mvebu_coreclk_setup(np, &kirkwood_coreclks); | ||
238 | |||
239 | if (cgnp) | ||
240 | mvebu_clk_gating_setup(cgnp, kirkwood_gating_desc); | ||
245 | } | 241 | } |
246 | CLK_OF_DECLARE(kirkwood_clk_gating, "marvell,kirkwood-gating-clock", | 242 | CLK_OF_DECLARE(kirkwood_clk, "marvell,kirkwood-core-clock", |
247 | kirkwood_clk_gating_init); | 243 | kirkwood_clk_init); |
244 | CLK_OF_DECLARE(mv88f6180_clk, "marvell,mv88f6180-core-clock", | ||
245 | kirkwood_clk_init); | ||
diff --git a/drivers/clk/shmobile/clk-div6.c b/drivers/clk/shmobile/clk-div6.c index aac4756ec52e..f065f694cb65 100644 --- a/drivers/clk/shmobile/clk-div6.c +++ b/drivers/clk/shmobile/clk-div6.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #define CPG_DIV6_DIV_MASK 0x3f | 23 | #define CPG_DIV6_DIV_MASK 0x3f |
24 | 24 | ||
25 | /** | 25 | /** |
26 | * struct div6_clock - MSTP gating clock | 26 | * struct div6_clock - CPG 6 bit divider clock |
27 | * @hw: handle between common and hardware-specific interfaces | 27 | * @hw: handle between common and hardware-specific interfaces |
28 | * @reg: IO-remapped register | 28 | * @reg: IO-remapped register |
29 | * @div: divisor value (1-64) | 29 | * @div: divisor value (1-64) |
diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c b/drivers/clk/shmobile/clk-rcar-gen2.c index a59ec217a124..dd272a0d1446 100644 --- a/drivers/clk/shmobile/clk-rcar-gen2.c +++ b/drivers/clk/shmobile/clk-rcar-gen2.c | |||
@@ -186,7 +186,7 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg, | |||
186 | const char *name) | 186 | const char *name) |
187 | { | 187 | { |
188 | const struct clk_div_table *table = NULL; | 188 | const struct clk_div_table *table = NULL; |
189 | const char *parent_name = "main"; | 189 | const char *parent_name; |
190 | unsigned int shift; | 190 | unsigned int shift; |
191 | unsigned int mult = 1; | 191 | unsigned int mult = 1; |
192 | unsigned int div = 1; | 192 | unsigned int div = 1; |
@@ -201,23 +201,31 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg, | |||
201 | * the multiplier value. | 201 | * the multiplier value. |
202 | */ | 202 | */ |
203 | u32 value = clk_readl(cpg->reg + CPG_PLL0CR); | 203 | u32 value = clk_readl(cpg->reg + CPG_PLL0CR); |
204 | parent_name = "main"; | ||
204 | mult = ((value >> 24) & ((1 << 7) - 1)) + 1; | 205 | mult = ((value >> 24) & ((1 << 7) - 1)) + 1; |
205 | } else if (!strcmp(name, "pll1")) { | 206 | } else if (!strcmp(name, "pll1")) { |
207 | parent_name = "main"; | ||
206 | mult = config->pll1_mult / 2; | 208 | mult = config->pll1_mult / 2; |
207 | } else if (!strcmp(name, "pll3")) { | 209 | } else if (!strcmp(name, "pll3")) { |
210 | parent_name = "main"; | ||
208 | mult = config->pll3_mult; | 211 | mult = config->pll3_mult; |
209 | } else if (!strcmp(name, "lb")) { | 212 | } else if (!strcmp(name, "lb")) { |
213 | parent_name = "pll1_div2"; | ||
210 | div = cpg_mode & BIT(18) ? 36 : 24; | 214 | div = cpg_mode & BIT(18) ? 36 : 24; |
211 | } else if (!strcmp(name, "qspi")) { | 215 | } else if (!strcmp(name, "qspi")) { |
216 | parent_name = "pll1_div2"; | ||
212 | div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) | 217 | div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) |
213 | ? 16 : 20; | 218 | ? 8 : 10; |
214 | } else if (!strcmp(name, "sdh")) { | 219 | } else if (!strcmp(name, "sdh")) { |
220 | parent_name = "pll1_div2"; | ||
215 | table = cpg_sdh_div_table; | 221 | table = cpg_sdh_div_table; |
216 | shift = 8; | 222 | shift = 8; |
217 | } else if (!strcmp(name, "sd0")) { | 223 | } else if (!strcmp(name, "sd0")) { |
224 | parent_name = "pll1_div2"; | ||
218 | table = cpg_sd01_div_table; | 225 | table = cpg_sd01_div_table; |
219 | shift = 4; | 226 | shift = 4; |
220 | } else if (!strcmp(name, "sd1")) { | 227 | } else if (!strcmp(name, "sd1")) { |
228 | parent_name = "pll1_div2"; | ||
221 | table = cpg_sd01_div_table; | 229 | table = cpg_sd01_div_table; |
222 | shift = 0; | 230 | shift = 0; |
223 | } else if (!strcmp(name, "z")) { | 231 | } else if (!strcmp(name, "z")) { |
diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile index 0303c0b99cd0..7e2d15a0c7b8 100644 --- a/drivers/clk/socfpga/Makefile +++ b/drivers/clk/socfpga/Makefile | |||
@@ -1 +1,4 @@ | |||
1 | obj-y += clk.o | 1 | obj-y += clk.o |
2 | obj-y += clk-gate.o | ||
3 | obj-y += clk-pll.o | ||
4 | obj-y += clk-periph.o | ||
diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c new file mode 100644 index 000000000000..501d513bf890 --- /dev/null +++ b/drivers/clk/socfpga/clk-gate.c | |||
@@ -0,0 +1,263 @@ | |||
1 | /* | ||
2 | * Copyright 2011-2012 Calxeda, Inc. | ||
3 | * Copyright (C) 2012-2013 Altera Corporation <www.altera.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * Based from clk-highbank.c | ||
16 | * | ||
17 | */ | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/clkdev.h> | ||
20 | #include <linux/clk-provider.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/mfd/syscon.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/regmap.h> | ||
25 | |||
26 | #include "clk.h" | ||
27 | |||
28 | #define SOCFPGA_L4_MP_CLK "l4_mp_clk" | ||
29 | #define SOCFPGA_L4_SP_CLK "l4_sp_clk" | ||
30 | #define SOCFPGA_NAND_CLK "nand_clk" | ||
31 | #define SOCFPGA_NAND_X_CLK "nand_x_clk" | ||
32 | #define SOCFPGA_MMC_CLK "sdmmc_clk" | ||
33 | #define SOCFPGA_GPIO_DB_CLK_OFFSET 0xA8 | ||
34 | |||
35 | #define div_mask(width) ((1 << (width)) - 1) | ||
36 | #define streq(a, b) (strcmp((a), (b)) == 0) | ||
37 | |||
38 | #define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw) | ||
39 | |||
40 | /* SDMMC Group for System Manager defines */ | ||
41 | #define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x108 | ||
42 | #define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \ | ||
43 | ((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0)) | ||
44 | |||
45 | static u8 socfpga_clk_get_parent(struct clk_hw *hwclk) | ||
46 | { | ||
47 | u32 l4_src; | ||
48 | u32 perpll_src; | ||
49 | |||
50 | if (streq(hwclk->init->name, SOCFPGA_L4_MP_CLK)) { | ||
51 | l4_src = readl(clk_mgr_base_addr + CLKMGR_L4SRC); | ||
52 | return l4_src &= 0x1; | ||
53 | } | ||
54 | if (streq(hwclk->init->name, SOCFPGA_L4_SP_CLK)) { | ||
55 | l4_src = readl(clk_mgr_base_addr + CLKMGR_L4SRC); | ||
56 | return !!(l4_src & 2); | ||
57 | } | ||
58 | |||
59 | perpll_src = readl(clk_mgr_base_addr + CLKMGR_PERPLL_SRC); | ||
60 | if (streq(hwclk->init->name, SOCFPGA_MMC_CLK)) | ||
61 | return perpll_src &= 0x3; | ||
62 | if (streq(hwclk->init->name, SOCFPGA_NAND_CLK) || | ||
63 | streq(hwclk->init->name, SOCFPGA_NAND_X_CLK)) | ||
64 | return (perpll_src >> 2) & 3; | ||
65 | |||
66 | /* QSPI clock */ | ||
67 | return (perpll_src >> 4) & 3; | ||
68 | |||
69 | } | ||
70 | |||
71 | static int socfpga_clk_set_parent(struct clk_hw *hwclk, u8 parent) | ||
72 | { | ||
73 | u32 src_reg; | ||
74 | |||
75 | if (streq(hwclk->init->name, SOCFPGA_L4_MP_CLK)) { | ||
76 | src_reg = readl(clk_mgr_base_addr + CLKMGR_L4SRC); | ||
77 | src_reg &= ~0x1; | ||
78 | src_reg |= parent; | ||
79 | writel(src_reg, clk_mgr_base_addr + CLKMGR_L4SRC); | ||
80 | } else if (streq(hwclk->init->name, SOCFPGA_L4_SP_CLK)) { | ||
81 | src_reg = readl(clk_mgr_base_addr + CLKMGR_L4SRC); | ||
82 | src_reg &= ~0x2; | ||
83 | src_reg |= (parent << 1); | ||
84 | writel(src_reg, clk_mgr_base_addr + CLKMGR_L4SRC); | ||
85 | } else { | ||
86 | src_reg = readl(clk_mgr_base_addr + CLKMGR_PERPLL_SRC); | ||
87 | if (streq(hwclk->init->name, SOCFPGA_MMC_CLK)) { | ||
88 | src_reg &= ~0x3; | ||
89 | src_reg |= parent; | ||
90 | } else if (streq(hwclk->init->name, SOCFPGA_NAND_CLK) || | ||
91 | streq(hwclk->init->name, SOCFPGA_NAND_X_CLK)) { | ||
92 | src_reg &= ~0xC; | ||
93 | src_reg |= (parent << 2); | ||
94 | } else {/* QSPI clock */ | ||
95 | src_reg &= ~0x30; | ||
96 | src_reg |= (parent << 4); | ||
97 | } | ||
98 | writel(src_reg, clk_mgr_base_addr + CLKMGR_PERPLL_SRC); | ||
99 | } | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk, | ||
105 | unsigned long parent_rate) | ||
106 | { | ||
107 | struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk); | ||
108 | u32 div = 1, val; | ||
109 | |||
110 | if (socfpgaclk->fixed_div) | ||
111 | div = socfpgaclk->fixed_div; | ||
112 | else if (socfpgaclk->div_reg) { | ||
113 | val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift; | ||
114 | val &= div_mask(socfpgaclk->width); | ||
115 | /* Check for GPIO_DB_CLK by its offset */ | ||
116 | if ((int) socfpgaclk->div_reg & SOCFPGA_GPIO_DB_CLK_OFFSET) | ||
117 | div = val + 1; | ||
118 | else | ||
119 | div = (1 << val); | ||
120 | } | ||
121 | |||
122 | return parent_rate / div; | ||
123 | } | ||
124 | |||
125 | static int socfpga_clk_prepare(struct clk_hw *hwclk) | ||
126 | { | ||
127 | struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk); | ||
128 | struct regmap *sys_mgr_base_addr; | ||
129 | int i; | ||
130 | u32 hs_timing; | ||
131 | u32 clk_phase[2]; | ||
132 | |||
133 | if (socfpgaclk->clk_phase[0] || socfpgaclk->clk_phase[1]) { | ||
134 | sys_mgr_base_addr = syscon_regmap_lookup_by_compatible("altr,sys-mgr"); | ||
135 | if (IS_ERR(sys_mgr_base_addr)) { | ||
136 | pr_err("%s: failed to find altr,sys-mgr regmap!\n", __func__); | ||
137 | return -EINVAL; | ||
138 | } | ||
139 | |||
140 | for (i = 0; i < 2; i++) { | ||
141 | switch (socfpgaclk->clk_phase[i]) { | ||
142 | case 0: | ||
143 | clk_phase[i] = 0; | ||
144 | break; | ||
145 | case 45: | ||
146 | clk_phase[i] = 1; | ||
147 | break; | ||
148 | case 90: | ||
149 | clk_phase[i] = 2; | ||
150 | break; | ||
151 | case 135: | ||
152 | clk_phase[i] = 3; | ||
153 | break; | ||
154 | case 180: | ||
155 | clk_phase[i] = 4; | ||
156 | break; | ||
157 | case 225: | ||
158 | clk_phase[i] = 5; | ||
159 | break; | ||
160 | case 270: | ||
161 | clk_phase[i] = 6; | ||
162 | break; | ||
163 | case 315: | ||
164 | clk_phase[i] = 7; | ||
165 | break; | ||
166 | default: | ||
167 | clk_phase[i] = 0; | ||
168 | break; | ||
169 | } | ||
170 | } | ||
171 | hs_timing = SYSMGR_SDMMC_CTRL_SET(clk_phase[0], clk_phase[1]); | ||
172 | regmap_write(sys_mgr_base_addr, SYSMGR_SDMMCGRP_CTRL_OFFSET, | ||
173 | hs_timing); | ||
174 | } | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static struct clk_ops gateclk_ops = { | ||
179 | .prepare = socfpga_clk_prepare, | ||
180 | .recalc_rate = socfpga_clk_recalc_rate, | ||
181 | .get_parent = socfpga_clk_get_parent, | ||
182 | .set_parent = socfpga_clk_set_parent, | ||
183 | }; | ||
184 | |||
185 | static void __init __socfpga_gate_init(struct device_node *node, | ||
186 | const struct clk_ops *ops) | ||
187 | { | ||
188 | u32 clk_gate[2]; | ||
189 | u32 div_reg[3]; | ||
190 | u32 clk_phase[2]; | ||
191 | u32 fixed_div; | ||
192 | struct clk *clk; | ||
193 | struct socfpga_gate_clk *socfpga_clk; | ||
194 | const char *clk_name = node->name; | ||
195 | const char *parent_name[SOCFPGA_MAX_PARENTS]; | ||
196 | struct clk_init_data init; | ||
197 | int rc; | ||
198 | int i = 0; | ||
199 | |||
200 | socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL); | ||
201 | if (WARN_ON(!socfpga_clk)) | ||
202 | return; | ||
203 | |||
204 | rc = of_property_read_u32_array(node, "clk-gate", clk_gate, 2); | ||
205 | if (rc) | ||
206 | clk_gate[0] = 0; | ||
207 | |||
208 | if (clk_gate[0]) { | ||
209 | socfpga_clk->hw.reg = clk_mgr_base_addr + clk_gate[0]; | ||
210 | socfpga_clk->hw.bit_idx = clk_gate[1]; | ||
211 | |||
212 | gateclk_ops.enable = clk_gate_ops.enable; | ||
213 | gateclk_ops.disable = clk_gate_ops.disable; | ||
214 | } | ||
215 | |||
216 | rc = of_property_read_u32(node, "fixed-divider", &fixed_div); | ||
217 | if (rc) | ||
218 | socfpga_clk->fixed_div = 0; | ||
219 | else | ||
220 | socfpga_clk->fixed_div = fixed_div; | ||
221 | |||
222 | rc = of_property_read_u32_array(node, "div-reg", div_reg, 3); | ||
223 | if (!rc) { | ||
224 | socfpga_clk->div_reg = clk_mgr_base_addr + div_reg[0]; | ||
225 | socfpga_clk->shift = div_reg[1]; | ||
226 | socfpga_clk->width = div_reg[2]; | ||
227 | } else { | ||
228 | socfpga_clk->div_reg = 0; | ||
229 | } | ||
230 | |||
231 | rc = of_property_read_u32_array(node, "clk-phase", clk_phase, 2); | ||
232 | if (!rc) { | ||
233 | socfpga_clk->clk_phase[0] = clk_phase[0]; | ||
234 | socfpga_clk->clk_phase[1] = clk_phase[1]; | ||
235 | } | ||
236 | |||
237 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
238 | |||
239 | init.name = clk_name; | ||
240 | init.ops = ops; | ||
241 | init.flags = 0; | ||
242 | while (i < SOCFPGA_MAX_PARENTS && (parent_name[i] = | ||
243 | of_clk_get_parent_name(node, i)) != NULL) | ||
244 | i++; | ||
245 | |||
246 | init.parent_names = parent_name; | ||
247 | init.num_parents = i; | ||
248 | socfpga_clk->hw.hw.init = &init; | ||
249 | |||
250 | clk = clk_register(NULL, &socfpga_clk->hw.hw); | ||
251 | if (WARN_ON(IS_ERR(clk))) { | ||
252 | kfree(socfpga_clk); | ||
253 | return; | ||
254 | } | ||
255 | rc = of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
256 | if (WARN_ON(rc)) | ||
257 | return; | ||
258 | } | ||
259 | |||
260 | void __init socfpga_gate_init(struct device_node *node) | ||
261 | { | ||
262 | __socfpga_gate_init(node, &gateclk_ops); | ||
263 | } | ||
diff --git a/drivers/clk/socfpga/clk-periph.c b/drivers/clk/socfpga/clk-periph.c new file mode 100644 index 000000000000..81623a3736f9 --- /dev/null +++ b/drivers/clk/socfpga/clk-periph.c | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * Copyright 2011-2012 Calxeda, Inc. | ||
3 | * Copyright (C) 2012-2013 Altera Corporation <www.altera.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * Based from clk-highbank.c | ||
16 | * | ||
17 | */ | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/clkdev.h> | ||
20 | #include <linux/clk-provider.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/of.h> | ||
23 | |||
24 | #include "clk.h" | ||
25 | |||
26 | #define to_socfpga_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw) | ||
27 | |||
28 | static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk, | ||
29 | unsigned long parent_rate) | ||
30 | { | ||
31 | struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk); | ||
32 | u32 div; | ||
33 | |||
34 | if (socfpgaclk->fixed_div) | ||
35 | div = socfpgaclk->fixed_div; | ||
36 | else | ||
37 | div = ((readl(socfpgaclk->hw.reg) & 0x1ff) + 1); | ||
38 | |||
39 | return parent_rate / div; | ||
40 | } | ||
41 | |||
42 | static const struct clk_ops periclk_ops = { | ||
43 | .recalc_rate = clk_periclk_recalc_rate, | ||
44 | }; | ||
45 | |||
46 | static __init void __socfpga_periph_init(struct device_node *node, | ||
47 | const struct clk_ops *ops) | ||
48 | { | ||
49 | u32 reg; | ||
50 | struct clk *clk; | ||
51 | struct socfpga_periph_clk *periph_clk; | ||
52 | const char *clk_name = node->name; | ||
53 | const char *parent_name; | ||
54 | struct clk_init_data init; | ||
55 | int rc; | ||
56 | u32 fixed_div; | ||
57 | |||
58 | of_property_read_u32(node, "reg", ®); | ||
59 | |||
60 | periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL); | ||
61 | if (WARN_ON(!periph_clk)) | ||
62 | return; | ||
63 | |||
64 | periph_clk->hw.reg = clk_mgr_base_addr + reg; | ||
65 | |||
66 | rc = of_property_read_u32(node, "fixed-divider", &fixed_div); | ||
67 | if (rc) | ||
68 | periph_clk->fixed_div = 0; | ||
69 | else | ||
70 | periph_clk->fixed_div = fixed_div; | ||
71 | |||
72 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
73 | |||
74 | init.name = clk_name; | ||
75 | init.ops = ops; | ||
76 | init.flags = 0; | ||
77 | parent_name = of_clk_get_parent_name(node, 0); | ||
78 | init.parent_names = &parent_name; | ||
79 | init.num_parents = 1; | ||
80 | |||
81 | periph_clk->hw.hw.init = &init; | ||
82 | |||
83 | clk = clk_register(NULL, &periph_clk->hw.hw); | ||
84 | if (WARN_ON(IS_ERR(clk))) { | ||
85 | kfree(periph_clk); | ||
86 | return; | ||
87 | } | ||
88 | rc = of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
89 | } | ||
90 | |||
91 | void __init socfpga_periph_init(struct device_node *node) | ||
92 | { | ||
93 | __socfpga_periph_init(node, &periclk_ops); | ||
94 | } | ||
diff --git a/drivers/clk/socfpga/clk-pll.c b/drivers/clk/socfpga/clk-pll.c new file mode 100644 index 000000000000..88dafb5e9627 --- /dev/null +++ b/drivers/clk/socfpga/clk-pll.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * Copyright 2011-2012 Calxeda, Inc. | ||
3 | * Copyright (C) 2012-2013 Altera Corporation <www.altera.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * Based from clk-highbank.c | ||
16 | * | ||
17 | */ | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/clkdev.h> | ||
20 | #include <linux/clk-provider.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/of.h> | ||
23 | |||
24 | #include "clk.h" | ||
25 | |||
26 | /* Clock bypass bits */ | ||
27 | #define MAINPLL_BYPASS (1<<0) | ||
28 | #define SDRAMPLL_BYPASS (1<<1) | ||
29 | #define SDRAMPLL_SRC_BYPASS (1<<2) | ||
30 | #define PERPLL_BYPASS (1<<3) | ||
31 | #define PERPLL_SRC_BYPASS (1<<4) | ||
32 | |||
33 | #define SOCFPGA_PLL_BG_PWRDWN 0 | ||
34 | #define SOCFPGA_PLL_EXT_ENA 1 | ||
35 | #define SOCFPGA_PLL_PWR_DOWN 2 | ||
36 | #define SOCFPGA_PLL_DIVF_MASK 0x0000FFF8 | ||
37 | #define SOCFPGA_PLL_DIVF_SHIFT 3 | ||
38 | #define SOCFPGA_PLL_DIVQ_MASK 0x003F0000 | ||
39 | #define SOCFPGA_PLL_DIVQ_SHIFT 16 | ||
40 | |||
41 | #define CLK_MGR_PLL_CLK_SRC_SHIFT 22 | ||
42 | #define CLK_MGR_PLL_CLK_SRC_MASK 0x3 | ||
43 | |||
44 | #define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw) | ||
45 | |||
46 | static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk, | ||
47 | unsigned long parent_rate) | ||
48 | { | ||
49 | struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk); | ||
50 | unsigned long divf, divq, reg; | ||
51 | unsigned long long vco_freq; | ||
52 | unsigned long bypass; | ||
53 | |||
54 | reg = readl(socfpgaclk->hw.reg); | ||
55 | bypass = readl(clk_mgr_base_addr + CLKMGR_BYPASS); | ||
56 | if (bypass & MAINPLL_BYPASS) | ||
57 | return parent_rate; | ||
58 | |||
59 | divf = (reg & SOCFPGA_PLL_DIVF_MASK) >> SOCFPGA_PLL_DIVF_SHIFT; | ||
60 | divq = (reg & SOCFPGA_PLL_DIVQ_MASK) >> SOCFPGA_PLL_DIVQ_SHIFT; | ||
61 | vco_freq = (unsigned long long)parent_rate * (divf + 1); | ||
62 | do_div(vco_freq, (1 + divq)); | ||
63 | return (unsigned long)vco_freq; | ||
64 | } | ||
65 | |||
66 | static u8 clk_pll_get_parent(struct clk_hw *hwclk) | ||
67 | { | ||
68 | u32 pll_src; | ||
69 | struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk); | ||
70 | |||
71 | pll_src = readl(socfpgaclk->hw.reg); | ||
72 | return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) & | ||
73 | CLK_MGR_PLL_CLK_SRC_MASK; | ||
74 | } | ||
75 | |||
76 | static struct clk_ops clk_pll_ops = { | ||
77 | .recalc_rate = clk_pll_recalc_rate, | ||
78 | .get_parent = clk_pll_get_parent, | ||
79 | }; | ||
80 | |||
81 | static __init struct clk *__socfpga_pll_init(struct device_node *node, | ||
82 | const struct clk_ops *ops) | ||
83 | { | ||
84 | u32 reg; | ||
85 | struct clk *clk; | ||
86 | struct socfpga_pll *pll_clk; | ||
87 | const char *clk_name = node->name; | ||
88 | const char *parent_name[SOCFPGA_MAX_PARENTS]; | ||
89 | struct clk_init_data init; | ||
90 | int rc; | ||
91 | int i = 0; | ||
92 | |||
93 | of_property_read_u32(node, "reg", ®); | ||
94 | |||
95 | pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); | ||
96 | if (WARN_ON(!pll_clk)) | ||
97 | return NULL; | ||
98 | |||
99 | pll_clk->hw.reg = clk_mgr_base_addr + reg; | ||
100 | |||
101 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
102 | |||
103 | init.name = clk_name; | ||
104 | init.ops = ops; | ||
105 | init.flags = 0; | ||
106 | |||
107 | while (i < SOCFPGA_MAX_PARENTS && (parent_name[i] = | ||
108 | of_clk_get_parent_name(node, i)) != NULL) | ||
109 | i++; | ||
110 | |||
111 | init.num_parents = i; | ||
112 | init.parent_names = parent_name; | ||
113 | pll_clk->hw.hw.init = &init; | ||
114 | |||
115 | pll_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA; | ||
116 | clk_pll_ops.enable = clk_gate_ops.enable; | ||
117 | clk_pll_ops.disable = clk_gate_ops.disable; | ||
118 | |||
119 | clk = clk_register(NULL, &pll_clk->hw.hw); | ||
120 | if (WARN_ON(IS_ERR(clk))) { | ||
121 | kfree(pll_clk); | ||
122 | return NULL; | ||
123 | } | ||
124 | rc = of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
125 | return clk; | ||
126 | } | ||
127 | |||
128 | void __init socfpga_pll_init(struct device_node *node) | ||
129 | { | ||
130 | __socfpga_pll_init(node, &clk_pll_ops); | ||
131 | } | ||
diff --git a/drivers/clk/socfpga/clk.c b/drivers/clk/socfpga/clk.c index 5983a26a8c5f..6217d5dc6644 100644 --- a/drivers/clk/socfpga/clk.c +++ b/drivers/clk/socfpga/clk.c | |||
@@ -22,325 +22,23 @@ | |||
22 | #include <linux/clk-provider.h> | 22 | #include <linux/clk-provider.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/of.h> | 24 | #include <linux/of.h> |
25 | #include <linux/of_address.h> | ||
25 | 26 | ||
26 | /* Clock Manager offsets */ | 27 | #include "clk.h" |
27 | #define CLKMGR_CTRL 0x0 | ||
28 | #define CLKMGR_BYPASS 0x4 | ||
29 | #define CLKMGR_L4SRC 0x70 | ||
30 | #define CLKMGR_PERPLL_SRC 0xAC | ||
31 | 28 | ||
32 | /* Clock bypass bits */ | 29 | void __iomem *clk_mgr_base_addr; |
33 | #define MAINPLL_BYPASS (1<<0) | ||
34 | #define SDRAMPLL_BYPASS (1<<1) | ||
35 | #define SDRAMPLL_SRC_BYPASS (1<<2) | ||
36 | #define PERPLL_BYPASS (1<<3) | ||
37 | #define PERPLL_SRC_BYPASS (1<<4) | ||
38 | 30 | ||
39 | #define SOCFPGA_PLL_BG_PWRDWN 0 | 31 | static struct of_device_id socfpga_child_clocks[] = { |
40 | #define SOCFPGA_PLL_EXT_ENA 1 | 32 | { .compatible = "altr,socfpga-pll-clock", socfpga_pll_init, }, |
41 | #define SOCFPGA_PLL_PWR_DOWN 2 | 33 | { .compatible = "altr,socfpga-perip-clk", socfpga_periph_init, }, |
42 | #define SOCFPGA_PLL_DIVF_MASK 0x0000FFF8 | 34 | { .compatible = "altr,socfpga-gate-clk", socfpga_gate_init, }, |
43 | #define SOCFPGA_PLL_DIVF_SHIFT 3 | 35 | {}, |
44 | #define SOCFPGA_PLL_DIVQ_MASK 0x003F0000 | ||
45 | #define SOCFPGA_PLL_DIVQ_SHIFT 16 | ||
46 | #define SOCFGPA_MAX_PARENTS 3 | ||
47 | |||
48 | #define SOCFPGA_L4_MP_CLK "l4_mp_clk" | ||
49 | #define SOCFPGA_L4_SP_CLK "l4_sp_clk" | ||
50 | #define SOCFPGA_NAND_CLK "nand_clk" | ||
51 | #define SOCFPGA_NAND_X_CLK "nand_x_clk" | ||
52 | #define SOCFPGA_MMC_CLK "sdmmc_clk" | ||
53 | #define SOCFPGA_DB_CLK "gpio_db_clk" | ||
54 | |||
55 | #define div_mask(width) ((1 << (width)) - 1) | ||
56 | #define streq(a, b) (strcmp((a), (b)) == 0) | ||
57 | |||
58 | extern void __iomem *clk_mgr_base_addr; | ||
59 | |||
60 | struct socfpga_clk { | ||
61 | struct clk_gate hw; | ||
62 | char *parent_name; | ||
63 | char *clk_name; | ||
64 | u32 fixed_div; | ||
65 | void __iomem *div_reg; | ||
66 | u32 width; /* only valid if div_reg != 0 */ | ||
67 | u32 shift; /* only valid if div_reg != 0 */ | ||
68 | }; | ||
69 | #define to_socfpga_clk(p) container_of(p, struct socfpga_clk, hw.hw) | ||
70 | |||
71 | static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk, | ||
72 | unsigned long parent_rate) | ||
73 | { | ||
74 | struct socfpga_clk *socfpgaclk = to_socfpga_clk(hwclk); | ||
75 | unsigned long divf, divq, vco_freq, reg; | ||
76 | unsigned long bypass; | ||
77 | |||
78 | reg = readl(socfpgaclk->hw.reg); | ||
79 | bypass = readl(clk_mgr_base_addr + CLKMGR_BYPASS); | ||
80 | if (bypass & MAINPLL_BYPASS) | ||
81 | return parent_rate; | ||
82 | |||
83 | divf = (reg & SOCFPGA_PLL_DIVF_MASK) >> SOCFPGA_PLL_DIVF_SHIFT; | ||
84 | divq = (reg & SOCFPGA_PLL_DIVQ_MASK) >> SOCFPGA_PLL_DIVQ_SHIFT; | ||
85 | vco_freq = parent_rate * (divf + 1); | ||
86 | return vco_freq / (1 + divq); | ||
87 | } | ||
88 | |||
89 | |||
90 | static struct clk_ops clk_pll_ops = { | ||
91 | .recalc_rate = clk_pll_recalc_rate, | ||
92 | }; | ||
93 | |||
94 | static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk, | ||
95 | unsigned long parent_rate) | ||
96 | { | ||
97 | struct socfpga_clk *socfpgaclk = to_socfpga_clk(hwclk); | ||
98 | u32 div; | ||
99 | |||
100 | if (socfpgaclk->fixed_div) | ||
101 | div = socfpgaclk->fixed_div; | ||
102 | else | ||
103 | div = ((readl(socfpgaclk->hw.reg) & 0x1ff) + 1); | ||
104 | |||
105 | return parent_rate / div; | ||
106 | } | ||
107 | |||
108 | static const struct clk_ops periclk_ops = { | ||
109 | .recalc_rate = clk_periclk_recalc_rate, | ||
110 | }; | ||
111 | |||
112 | static __init struct clk *socfpga_clk_init(struct device_node *node, | ||
113 | const struct clk_ops *ops) | ||
114 | { | ||
115 | u32 reg; | ||
116 | struct clk *clk; | ||
117 | struct socfpga_clk *socfpga_clk; | ||
118 | const char *clk_name = node->name; | ||
119 | const char *parent_name; | ||
120 | struct clk_init_data init; | ||
121 | int rc; | ||
122 | u32 fixed_div; | ||
123 | |||
124 | of_property_read_u32(node, "reg", ®); | ||
125 | |||
126 | socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL); | ||
127 | if (WARN_ON(!socfpga_clk)) | ||
128 | return NULL; | ||
129 | |||
130 | socfpga_clk->hw.reg = clk_mgr_base_addr + reg; | ||
131 | |||
132 | rc = of_property_read_u32(node, "fixed-divider", &fixed_div); | ||
133 | if (rc) | ||
134 | socfpga_clk->fixed_div = 0; | ||
135 | else | ||
136 | socfpga_clk->fixed_div = fixed_div; | ||
137 | |||
138 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
139 | |||
140 | init.name = clk_name; | ||
141 | init.ops = ops; | ||
142 | init.flags = 0; | ||
143 | parent_name = of_clk_get_parent_name(node, 0); | ||
144 | init.parent_names = &parent_name; | ||
145 | init.num_parents = 1; | ||
146 | |||
147 | socfpga_clk->hw.hw.init = &init; | ||
148 | |||
149 | if (streq(clk_name, "main_pll") || | ||
150 | streq(clk_name, "periph_pll") || | ||
151 | streq(clk_name, "sdram_pll")) { | ||
152 | socfpga_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA; | ||
153 | clk_pll_ops.enable = clk_gate_ops.enable; | ||
154 | clk_pll_ops.disable = clk_gate_ops.disable; | ||
155 | } | ||
156 | |||
157 | clk = clk_register(NULL, &socfpga_clk->hw.hw); | ||
158 | if (WARN_ON(IS_ERR(clk))) { | ||
159 | kfree(socfpga_clk); | ||
160 | return NULL; | ||
161 | } | ||
162 | rc = of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
163 | return clk; | ||
164 | } | ||
165 | |||
166 | static u8 socfpga_clk_get_parent(struct clk_hw *hwclk) | ||
167 | { | ||
168 | u32 l4_src; | ||
169 | u32 perpll_src; | ||
170 | |||
171 | if (streq(hwclk->init->name, SOCFPGA_L4_MP_CLK)) { | ||
172 | l4_src = readl(clk_mgr_base_addr + CLKMGR_L4SRC); | ||
173 | return l4_src &= 0x1; | ||
174 | } | ||
175 | if (streq(hwclk->init->name, SOCFPGA_L4_SP_CLK)) { | ||
176 | l4_src = readl(clk_mgr_base_addr + CLKMGR_L4SRC); | ||
177 | return !!(l4_src & 2); | ||
178 | } | ||
179 | |||
180 | perpll_src = readl(clk_mgr_base_addr + CLKMGR_PERPLL_SRC); | ||
181 | if (streq(hwclk->init->name, SOCFPGA_MMC_CLK)) | ||
182 | return perpll_src &= 0x3; | ||
183 | if (streq(hwclk->init->name, SOCFPGA_NAND_CLK) || | ||
184 | streq(hwclk->init->name, SOCFPGA_NAND_X_CLK)) | ||
185 | return (perpll_src >> 2) & 3; | ||
186 | |||
187 | /* QSPI clock */ | ||
188 | return (perpll_src >> 4) & 3; | ||
189 | |||
190 | } | ||
191 | |||
192 | static int socfpga_clk_set_parent(struct clk_hw *hwclk, u8 parent) | ||
193 | { | ||
194 | u32 src_reg; | ||
195 | |||
196 | if (streq(hwclk->init->name, SOCFPGA_L4_MP_CLK)) { | ||
197 | src_reg = readl(clk_mgr_base_addr + CLKMGR_L4SRC); | ||
198 | src_reg &= ~0x1; | ||
199 | src_reg |= parent; | ||
200 | writel(src_reg, clk_mgr_base_addr + CLKMGR_L4SRC); | ||
201 | } else if (streq(hwclk->init->name, SOCFPGA_L4_SP_CLK)) { | ||
202 | src_reg = readl(clk_mgr_base_addr + CLKMGR_L4SRC); | ||
203 | src_reg &= ~0x2; | ||
204 | src_reg |= (parent << 1); | ||
205 | writel(src_reg, clk_mgr_base_addr + CLKMGR_L4SRC); | ||
206 | } else { | ||
207 | src_reg = readl(clk_mgr_base_addr + CLKMGR_PERPLL_SRC); | ||
208 | if (streq(hwclk->init->name, SOCFPGA_MMC_CLK)) { | ||
209 | src_reg &= ~0x3; | ||
210 | src_reg |= parent; | ||
211 | } else if (streq(hwclk->init->name, SOCFPGA_NAND_CLK) || | ||
212 | streq(hwclk->init->name, SOCFPGA_NAND_X_CLK)) { | ||
213 | src_reg &= ~0xC; | ||
214 | src_reg |= (parent << 2); | ||
215 | } else {/* QSPI clock */ | ||
216 | src_reg &= ~0x30; | ||
217 | src_reg |= (parent << 4); | ||
218 | } | ||
219 | writel(src_reg, clk_mgr_base_addr + CLKMGR_PERPLL_SRC); | ||
220 | } | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk, | ||
226 | unsigned long parent_rate) | ||
227 | { | ||
228 | struct socfpga_clk *socfpgaclk = to_socfpga_clk(hwclk); | ||
229 | u32 div = 1, val; | ||
230 | |||
231 | if (socfpgaclk->fixed_div) | ||
232 | div = socfpgaclk->fixed_div; | ||
233 | else if (socfpgaclk->div_reg) { | ||
234 | val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift; | ||
235 | val &= div_mask(socfpgaclk->width); | ||
236 | if (streq(hwclk->init->name, SOCFPGA_DB_CLK)) | ||
237 | div = val + 1; | ||
238 | else | ||
239 | div = (1 << val); | ||
240 | } | ||
241 | |||
242 | return parent_rate / div; | ||
243 | } | ||
244 | |||
245 | static struct clk_ops gateclk_ops = { | ||
246 | .recalc_rate = socfpga_clk_recalc_rate, | ||
247 | .get_parent = socfpga_clk_get_parent, | ||
248 | .set_parent = socfpga_clk_set_parent, | ||
249 | }; | 36 | }; |
250 | 37 | ||
251 | static void __init socfpga_gate_clk_init(struct device_node *node, | 38 | static void __init socfpga_clkmgr_init(struct device_node *node) |
252 | const struct clk_ops *ops) | ||
253 | { | ||
254 | u32 clk_gate[2]; | ||
255 | u32 div_reg[3]; | ||
256 | u32 fixed_div; | ||
257 | struct clk *clk; | ||
258 | struct socfpga_clk *socfpga_clk; | ||
259 | const char *clk_name = node->name; | ||
260 | const char *parent_name[SOCFGPA_MAX_PARENTS]; | ||
261 | struct clk_init_data init; | ||
262 | int rc; | ||
263 | int i = 0; | ||
264 | |||
265 | socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL); | ||
266 | if (WARN_ON(!socfpga_clk)) | ||
267 | return; | ||
268 | |||
269 | rc = of_property_read_u32_array(node, "clk-gate", clk_gate, 2); | ||
270 | if (rc) | ||
271 | clk_gate[0] = 0; | ||
272 | |||
273 | if (clk_gate[0]) { | ||
274 | socfpga_clk->hw.reg = clk_mgr_base_addr + clk_gate[0]; | ||
275 | socfpga_clk->hw.bit_idx = clk_gate[1]; | ||
276 | |||
277 | gateclk_ops.enable = clk_gate_ops.enable; | ||
278 | gateclk_ops.disable = clk_gate_ops.disable; | ||
279 | } | ||
280 | |||
281 | rc = of_property_read_u32(node, "fixed-divider", &fixed_div); | ||
282 | if (rc) | ||
283 | socfpga_clk->fixed_div = 0; | ||
284 | else | ||
285 | socfpga_clk->fixed_div = fixed_div; | ||
286 | |||
287 | rc = of_property_read_u32_array(node, "div-reg", div_reg, 3); | ||
288 | if (!rc) { | ||
289 | socfpga_clk->div_reg = clk_mgr_base_addr + div_reg[0]; | ||
290 | socfpga_clk->shift = div_reg[1]; | ||
291 | socfpga_clk->width = div_reg[2]; | ||
292 | } else { | ||
293 | socfpga_clk->div_reg = NULL; | ||
294 | } | ||
295 | |||
296 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
297 | |||
298 | init.name = clk_name; | ||
299 | init.ops = ops; | ||
300 | init.flags = 0; | ||
301 | while (i < SOCFGPA_MAX_PARENTS && (parent_name[i] = | ||
302 | of_clk_get_parent_name(node, i)) != NULL) | ||
303 | i++; | ||
304 | |||
305 | init.parent_names = parent_name; | ||
306 | init.num_parents = i; | ||
307 | socfpga_clk->hw.hw.init = &init; | ||
308 | |||
309 | clk = clk_register(NULL, &socfpga_clk->hw.hw); | ||
310 | if (WARN_ON(IS_ERR(clk))) { | ||
311 | kfree(socfpga_clk); | ||
312 | return; | ||
313 | } | ||
314 | rc = of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
315 | if (WARN_ON(rc)) | ||
316 | return; | ||
317 | } | ||
318 | |||
319 | static void __init socfpga_pll_init(struct device_node *node) | ||
320 | { | 39 | { |
321 | socfpga_clk_init(node, &clk_pll_ops); | 40 | clk_mgr_base_addr = of_iomap(node, 0); |
41 | of_clk_init(socfpga_child_clocks); | ||
322 | } | 42 | } |
323 | CLK_OF_DECLARE(socfpga_pll, "altr,socfpga-pll-clock", socfpga_pll_init); | 43 | CLK_OF_DECLARE(socfpga_mgr, "altr,clk-mgr", socfpga_clkmgr_init); |
324 | 44 | ||
325 | static void __init socfpga_periph_init(struct device_node *node) | ||
326 | { | ||
327 | socfpga_clk_init(node, &periclk_ops); | ||
328 | } | ||
329 | CLK_OF_DECLARE(socfpga_periph, "altr,socfpga-perip-clk", socfpga_periph_init); | ||
330 | |||
331 | static void __init socfpga_gate_init(struct device_node *node) | ||
332 | { | ||
333 | socfpga_gate_clk_init(node, &gateclk_ops); | ||
334 | } | ||
335 | CLK_OF_DECLARE(socfpga_gate, "altr,socfpga-gate-clk", socfpga_gate_init); | ||
336 | |||
337 | void __init socfpga_init_clocks(void) | ||
338 | { | ||
339 | struct clk *clk; | ||
340 | int ret; | ||
341 | |||
342 | clk = clk_register_fixed_factor(NULL, "smp_twd", "mpuclk", 0, 1, 4); | ||
343 | ret = clk_register_clkdev(clk, NULL, "smp_twd"); | ||
344 | if (ret) | ||
345 | pr_err("smp_twd alias not registered\n"); | ||
346 | } | ||
diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h new file mode 100644 index 000000000000..d2e54019c94f --- /dev/null +++ b/drivers/clk/socfpga/clk.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013, Steffen Trumtrar <s.trumtrar@pengutronix.de> | ||
3 | * | ||
4 | * based on drivers/clk/tegra/clk.h | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef __SOCFPGA_CLK_H | ||
18 | #define __SOCFPGA_CLK_H | ||
19 | |||
20 | #include <linux/clk-provider.h> | ||
21 | #include <linux/clkdev.h> | ||
22 | |||
23 | /* Clock Manager offsets */ | ||
24 | #define CLKMGR_CTRL 0x0 | ||
25 | #define CLKMGR_BYPASS 0x4 | ||
26 | #define CLKMGR_L4SRC 0x70 | ||
27 | #define CLKMGR_PERPLL_SRC 0xAC | ||
28 | |||
29 | #define SOCFPGA_MAX_PARENTS 3 | ||
30 | |||
31 | extern void __iomem *clk_mgr_base_addr; | ||
32 | |||
33 | void __init socfpga_pll_init(struct device_node *node); | ||
34 | void __init socfpga_periph_init(struct device_node *node); | ||
35 | void __init socfpga_gate_init(struct device_node *node); | ||
36 | |||
37 | struct socfpga_pll { | ||
38 | struct clk_gate hw; | ||
39 | }; | ||
40 | |||
41 | struct socfpga_gate_clk { | ||
42 | struct clk_gate hw; | ||
43 | char *parent_name; | ||
44 | u32 fixed_div; | ||
45 | void __iomem *div_reg; | ||
46 | u32 width; /* only valid if div_reg != 0 */ | ||
47 | u32 shift; /* only valid if div_reg != 0 */ | ||
48 | u32 clk_phase[2]; | ||
49 | }; | ||
50 | |||
51 | struct socfpga_periph_clk { | ||
52 | struct clk_gate hw; | ||
53 | char *parent_name; | ||
54 | u32 fixed_div; | ||
55 | }; | ||
56 | |||
57 | #endif /* SOCFPGA_CLK_H */ | ||
diff --git a/drivers/clk/tegra/clk-divider.c b/drivers/clk/tegra/clk-divider.c index 4d75b1f37e3a..290f9c1a3749 100644 --- a/drivers/clk/tegra/clk-divider.c +++ b/drivers/clk/tegra/clk-divider.c | |||
@@ -59,7 +59,7 @@ static int get_div(struct tegra_clk_frac_div *divider, unsigned long rate, | |||
59 | return 0; | 59 | return 0; |
60 | 60 | ||
61 | if (divider_ux1 > get_max_div(divider)) | 61 | if (divider_ux1 > get_max_div(divider)) |
62 | return -EINVAL; | 62 | return get_max_div(divider); |
63 | 63 | ||
64 | return divider_ux1; | 64 | return divider_ux1; |
65 | } | 65 | } |
diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h index cf0c323f2c36..c39613c519af 100644 --- a/drivers/clk/tegra/clk-id.h +++ b/drivers/clk/tegra/clk-id.h | |||
@@ -180,9 +180,13 @@ enum clk_id { | |||
180 | tegra_clk_sbc6_8, | 180 | tegra_clk_sbc6_8, |
181 | tegra_clk_sclk, | 181 | tegra_clk_sclk, |
182 | tegra_clk_sdmmc1, | 182 | tegra_clk_sdmmc1, |
183 | tegra_clk_sdmmc1_8, | ||
183 | tegra_clk_sdmmc2, | 184 | tegra_clk_sdmmc2, |
185 | tegra_clk_sdmmc2_8, | ||
184 | tegra_clk_sdmmc3, | 186 | tegra_clk_sdmmc3, |
187 | tegra_clk_sdmmc3_8, | ||
185 | tegra_clk_sdmmc4, | 188 | tegra_clk_sdmmc4, |
189 | tegra_clk_sdmmc4_8, | ||
186 | tegra_clk_se, | 190 | tegra_clk_se, |
187 | tegra_clk_soc_therm, | 191 | tegra_clk_soc_therm, |
188 | tegra_clk_sor0, | 192 | tegra_clk_sor0, |
diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index 356e9b804421..9e899c18af86 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c | |||
@@ -130,7 +130,7 @@ static const struct clk_ops tegra_clk_periph_nodiv_ops = { | |||
130 | .disable = clk_periph_disable, | 130 | .disable = clk_periph_disable, |
131 | }; | 131 | }; |
132 | 132 | ||
133 | const struct clk_ops tegra_clk_periph_no_gate_ops = { | 133 | static const struct clk_ops tegra_clk_periph_no_gate_ops = { |
134 | .get_parent = clk_periph_get_parent, | 134 | .get_parent = clk_periph_get_parent, |
135 | .set_parent = clk_periph_set_parent, | 135 | .set_parent = clk_periph_set_parent, |
136 | .recalc_rate = clk_periph_recalc_rate, | 136 | .recalc_rate = clk_periph_recalc_rate, |
diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 5c35885f4a7c..1fa5c3f33b20 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c | |||
@@ -371,9 +371,7 @@ static const char *mux_pllp3_pllc_clkm[] = { | |||
371 | static const char *mux_pllm_pllc_pllp_plla_pllc2_c3_clkm[] = { | 371 | static const char *mux_pllm_pllc_pllp_plla_pllc2_c3_clkm[] = { |
372 | "pll_m", "pll_c", "pll_p", "pll_a", "pll_c2", "pll_c3", "clk_m" | 372 | "pll_m", "pll_c", "pll_p", "pll_a", "pll_c2", "pll_c3", "clk_m" |
373 | }; | 373 | }; |
374 | static u32 mux_pllm_pllc_pllp_plla_pllc2_c3_clkm_idx[] = { | 374 | #define mux_pllm_pllc_pllp_plla_pllc2_c3_clkm_idx NULL |
375 | [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6, | ||
376 | }; | ||
377 | 375 | ||
378 | static const char *mux_pllm_pllc2_c_c3_pllp_plla_pllc4[] = { | 376 | static const char *mux_pllm_pllc2_c_c3_pllp_plla_pllc4[] = { |
379 | "pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0", "pll_c4", | 377 | "pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0", "pll_c4", |
@@ -465,6 +463,10 @@ static struct tegra_periph_init_data periph_clks[] = { | |||
465 | MUX("adx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX1, 180, TEGRA_PERIPH_ON_APB, tegra_clk_adx1), | 463 | MUX("adx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX1, 180, TEGRA_PERIPH_ON_APB, tegra_clk_adx1), |
466 | MUX("amx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX1, 185, TEGRA_PERIPH_ON_APB, tegra_clk_amx1), | 464 | MUX("amx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX1, 185, TEGRA_PERIPH_ON_APB, tegra_clk_amx1), |
467 | MUX("vi_sensor2", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR2, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2), | 465 | MUX("vi_sensor2", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR2, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2), |
466 | MUX8("sdmmc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC1, 14, 0, tegra_clk_sdmmc1_8), | ||
467 | MUX8("sdmmc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC2, 9, 0, tegra_clk_sdmmc2_8), | ||
468 | MUX8("sdmmc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC3, 69, 0, tegra_clk_sdmmc3_8), | ||
469 | MUX8("sdmmc4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC4, 15, 0, tegra_clk_sdmmc4_8), | ||
468 | MUX8("sbc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, tegra_clk_sbc1_8), | 470 | MUX8("sbc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, tegra_clk_sbc1_8), |
469 | MUX8("sbc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, tegra_clk_sbc2_8), | 471 | MUX8("sbc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, tegra_clk_sbc2_8), |
470 | MUX8("sbc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, tegra_clk_sbc3_8), | 472 | MUX8("sbc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, tegra_clk_sbc3_8), |
@@ -492,7 +494,7 @@ static struct tegra_periph_init_data periph_clks[] = { | |||
492 | UART("uartb", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, tegra_clk_uartb), | 494 | UART("uartb", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, tegra_clk_uartb), |
493 | UART("uartc", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, tegra_clk_uartc), | 495 | UART("uartc", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, tegra_clk_uartc), |
494 | UART("uartd", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, tegra_clk_uartd), | 496 | UART("uartd", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, tegra_clk_uartd), |
495 | UART("uarte", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTE, 65, tegra_clk_uarte), | 497 | UART("uarte", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTE, 66, tegra_clk_uarte), |
496 | XUSB("xusb_host_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_host_src), | 498 | XUSB("xusb_host_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_host_src), |
497 | XUSB("xusb_falcon_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_falcon_src), | 499 | XUSB("xusb_falcon_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_falcon_src), |
498 | XUSB("xusb_fs_src", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_fs_src), | 500 | XUSB("xusb_fs_src", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_fs_src), |
diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c b/drivers/clk/tegra/clk-tegra-super-gen4.c index 05dce4aa2c11..feb3201c85ce 100644 --- a/drivers/clk/tegra/clk-tegra-super-gen4.c +++ b/drivers/clk/tegra/clk-tegra-super-gen4.c | |||
@@ -120,7 +120,7 @@ void __init tegra_super_clk_gen4_init(void __iomem *clk_base, | |||
120 | ARRAY_SIZE(cclk_lp_parents), | 120 | ARRAY_SIZE(cclk_lp_parents), |
121 | CLK_SET_RATE_PARENT, | 121 | CLK_SET_RATE_PARENT, |
122 | clk_base + CCLKLP_BURST_POLICY, | 122 | clk_base + CCLKLP_BURST_POLICY, |
123 | 0, 4, 8, 9, NULL); | 123 | TEGRA_DIVIDER_2, 4, 8, 9, NULL); |
124 | *dt_clk = clk; | 124 | *dt_clk = clk; |
125 | } | 125 | } |
126 | 126 | ||
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 90d9d25f2228..80431f0fb268 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c | |||
@@ -682,12 +682,12 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = { | |||
682 | [tegra_clk_timer] = { .dt_id = TEGRA114_CLK_TIMER, .present = true }, | 682 | [tegra_clk_timer] = { .dt_id = TEGRA114_CLK_TIMER, .present = true }, |
683 | [tegra_clk_uarta] = { .dt_id = TEGRA114_CLK_UARTA, .present = true }, | 683 | [tegra_clk_uarta] = { .dt_id = TEGRA114_CLK_UARTA, .present = true }, |
684 | [tegra_clk_uartd] = { .dt_id = TEGRA114_CLK_UARTD, .present = true }, | 684 | [tegra_clk_uartd] = { .dt_id = TEGRA114_CLK_UARTD, .present = true }, |
685 | [tegra_clk_sdmmc2] = { .dt_id = TEGRA114_CLK_SDMMC2, .present = true }, | 685 | [tegra_clk_sdmmc2_8] = { .dt_id = TEGRA114_CLK_SDMMC2, .present = true }, |
686 | [tegra_clk_i2s1] = { .dt_id = TEGRA114_CLK_I2S1, .present = true }, | 686 | [tegra_clk_i2s1] = { .dt_id = TEGRA114_CLK_I2S1, .present = true }, |
687 | [tegra_clk_i2c1] = { .dt_id = TEGRA114_CLK_I2C1, .present = true }, | 687 | [tegra_clk_i2c1] = { .dt_id = TEGRA114_CLK_I2C1, .present = true }, |
688 | [tegra_clk_ndflash] = { .dt_id = TEGRA114_CLK_NDFLASH, .present = true }, | 688 | [tegra_clk_ndflash] = { .dt_id = TEGRA114_CLK_NDFLASH, .present = true }, |
689 | [tegra_clk_sdmmc1] = { .dt_id = TEGRA114_CLK_SDMMC1, .present = true }, | 689 | [tegra_clk_sdmmc1_8] = { .dt_id = TEGRA114_CLK_SDMMC1, .present = true }, |
690 | [tegra_clk_sdmmc4] = { .dt_id = TEGRA114_CLK_SDMMC4, .present = true }, | 690 | [tegra_clk_sdmmc4_8] = { .dt_id = TEGRA114_CLK_SDMMC4, .present = true }, |
691 | [tegra_clk_pwm] = { .dt_id = TEGRA114_CLK_PWM, .present = true }, | 691 | [tegra_clk_pwm] = { .dt_id = TEGRA114_CLK_PWM, .present = true }, |
692 | [tegra_clk_i2s0] = { .dt_id = TEGRA114_CLK_I2S0, .present = true }, | 692 | [tegra_clk_i2s0] = { .dt_id = TEGRA114_CLK_I2S0, .present = true }, |
693 | [tegra_clk_i2s2] = { .dt_id = TEGRA114_CLK_I2S2, .present = true }, | 693 | [tegra_clk_i2s2] = { .dt_id = TEGRA114_CLK_I2S2, .present = true }, |
@@ -723,7 +723,7 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = { | |||
723 | [tegra_clk_bsev] = { .dt_id = TEGRA114_CLK_BSEV, .present = true }, | 723 | [tegra_clk_bsev] = { .dt_id = TEGRA114_CLK_BSEV, .present = true }, |
724 | [tegra_clk_i2c3] = { .dt_id = TEGRA114_CLK_I2C3, .present = true }, | 724 | [tegra_clk_i2c3] = { .dt_id = TEGRA114_CLK_I2C3, .present = true }, |
725 | [tegra_clk_sbc4_8] = { .dt_id = TEGRA114_CLK_SBC4, .present = true }, | 725 | [tegra_clk_sbc4_8] = { .dt_id = TEGRA114_CLK_SBC4, .present = true }, |
726 | [tegra_clk_sdmmc3] = { .dt_id = TEGRA114_CLK_SDMMC3, .present = true }, | 726 | [tegra_clk_sdmmc3_8] = { .dt_id = TEGRA114_CLK_SDMMC3, .present = true }, |
727 | [tegra_clk_owr] = { .dt_id = TEGRA114_CLK_OWR, .present = true }, | 727 | [tegra_clk_owr] = { .dt_id = TEGRA114_CLK_OWR, .present = true }, |
728 | [tegra_clk_csite] = { .dt_id = TEGRA114_CLK_CSITE, .present = true }, | 728 | [tegra_clk_csite] = { .dt_id = TEGRA114_CLK_CSITE, .present = true }, |
729 | [tegra_clk_la] = { .dt_id = TEGRA114_CLK_LA, .present = true }, | 729 | [tegra_clk_la] = { .dt_id = TEGRA114_CLK_LA, .present = true }, |
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index aff86b5bc745..166e02f16c8a 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c | |||
@@ -516,11 +516,11 @@ static struct div_nmp pllp_nmp = { | |||
516 | }; | 516 | }; |
517 | 517 | ||
518 | static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { | 518 | static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { |
519 | {12000000, 216000000, 432, 12, 1, 8}, | 519 | {12000000, 408000000, 408, 12, 0, 8}, |
520 | {13000000, 216000000, 432, 13, 1, 8}, | 520 | {13000000, 408000000, 408, 13, 0, 8}, |
521 | {16800000, 216000000, 360, 14, 1, 8}, | 521 | {16800000, 408000000, 340, 14, 0, 8}, |
522 | {19200000, 216000000, 360, 16, 1, 8}, | 522 | {19200000, 408000000, 340, 16, 0, 8}, |
523 | {26000000, 216000000, 432, 26, 1, 8}, | 523 | {26000000, 408000000, 408, 26, 0, 8}, |
524 | {0, 0, 0, 0, 0, 0}, | 524 | {0, 0, 0, 0, 0, 0}, |
525 | }; | 525 | }; |
526 | 526 | ||
@@ -570,6 +570,15 @@ static struct tegra_clk_pll_params pll_a_params = { | |||
570 | .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK, | 570 | .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK, |
571 | }; | 571 | }; |
572 | 572 | ||
573 | static struct div_nmp plld_nmp = { | ||
574 | .divm_shift = 0, | ||
575 | .divm_width = 5, | ||
576 | .divn_shift = 8, | ||
577 | .divn_width = 11, | ||
578 | .divp_shift = 20, | ||
579 | .divp_width = 3, | ||
580 | }; | ||
581 | |||
573 | static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { | 582 | static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { |
574 | {12000000, 216000000, 864, 12, 4, 12}, | 583 | {12000000, 216000000, 864, 12, 4, 12}, |
575 | {13000000, 216000000, 864, 13, 4, 12}, | 584 | {13000000, 216000000, 864, 13, 4, 12}, |
@@ -603,19 +612,18 @@ static struct tegra_clk_pll_params pll_d_params = { | |||
603 | .lock_mask = PLL_BASE_LOCK, | 612 | .lock_mask = PLL_BASE_LOCK, |
604 | .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, | 613 | .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, |
605 | .lock_delay = 1000, | 614 | .lock_delay = 1000, |
606 | .div_nmp = &pllp_nmp, | 615 | .div_nmp = &plld_nmp, |
607 | .freq_table = pll_d_freq_table, | 616 | .freq_table = pll_d_freq_table, |
608 | .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | | 617 | .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | |
609 | TEGRA_PLL_USE_LOCK, | 618 | TEGRA_PLL_USE_LOCK, |
610 | }; | 619 | }; |
611 | 620 | ||
612 | static struct tegra_clk_pll_freq_table tegra124_pll_d2_freq_table[] = { | 621 | static struct tegra_clk_pll_freq_table tegra124_pll_d2_freq_table[] = { |
613 | { 12000000, 148500000, 99, 1, 8}, | 622 | { 12000000, 594000000, 99, 1, 2}, |
614 | { 12000000, 594000000, 99, 1, 1}, | 623 | { 13000000, 594000000, 91, 1, 2}, /* actual: 591.5 MHz */ |
615 | { 13000000, 594000000, 91, 1, 1}, /* actual: 591.5 MHz */ | 624 | { 16800000, 594000000, 71, 1, 2}, /* actual: 596.4 MHz */ |
616 | { 16800000, 594000000, 71, 1, 1}, /* actual: 596.4 MHz */ | 625 | { 19200000, 594000000, 62, 1, 2}, /* actual: 595.2 MHz */ |
617 | { 19200000, 594000000, 62, 1, 1}, /* actual: 595.2 MHz */ | 626 | { 26000000, 594000000, 91, 2, 2}, /* actual: 591.5 MHz */ |
618 | { 26000000, 594000000, 91, 2, 1}, /* actual: 591.5 MHz */ | ||
619 | { 0, 0, 0, 0, 0, 0 }, | 627 | { 0, 0, 0, 0, 0, 0 }, |
620 | }; | 628 | }; |
621 | 629 | ||
@@ -753,21 +761,19 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = { | |||
753 | [tegra_clk_rtc] = { .dt_id = TEGRA124_CLK_RTC, .present = true }, | 761 | [tegra_clk_rtc] = { .dt_id = TEGRA124_CLK_RTC, .present = true }, |
754 | [tegra_clk_timer] = { .dt_id = TEGRA124_CLK_TIMER, .present = true }, | 762 | [tegra_clk_timer] = { .dt_id = TEGRA124_CLK_TIMER, .present = true }, |
755 | [tegra_clk_uarta] = { .dt_id = TEGRA124_CLK_UARTA, .present = true }, | 763 | [tegra_clk_uarta] = { .dt_id = TEGRA124_CLK_UARTA, .present = true }, |
756 | [tegra_clk_sdmmc2] = { .dt_id = TEGRA124_CLK_SDMMC2, .present = true }, | 764 | [tegra_clk_sdmmc2_8] = { .dt_id = TEGRA124_CLK_SDMMC2, .present = true }, |
757 | [tegra_clk_i2s1] = { .dt_id = TEGRA124_CLK_I2S1, .present = true }, | 765 | [tegra_clk_i2s1] = { .dt_id = TEGRA124_CLK_I2S1, .present = true }, |
758 | [tegra_clk_i2c1] = { .dt_id = TEGRA124_CLK_I2C1, .present = true }, | 766 | [tegra_clk_i2c1] = { .dt_id = TEGRA124_CLK_I2C1, .present = true }, |
759 | [tegra_clk_ndflash] = { .dt_id = TEGRA124_CLK_NDFLASH, .present = true }, | 767 | [tegra_clk_ndflash] = { .dt_id = TEGRA124_CLK_NDFLASH, .present = true }, |
760 | [tegra_clk_sdmmc1] = { .dt_id = TEGRA124_CLK_SDMMC1, .present = true }, | 768 | [tegra_clk_sdmmc1_8] = { .dt_id = TEGRA124_CLK_SDMMC1, .present = true }, |
761 | [tegra_clk_sdmmc4] = { .dt_id = TEGRA124_CLK_SDMMC4, .present = true }, | 769 | [tegra_clk_sdmmc4_8] = { .dt_id = TEGRA124_CLK_SDMMC4, .present = true }, |
762 | [tegra_clk_pwm] = { .dt_id = TEGRA124_CLK_PWM, .present = true }, | 770 | [tegra_clk_pwm] = { .dt_id = TEGRA124_CLK_PWM, .present = true }, |
763 | [tegra_clk_i2s2] = { .dt_id = TEGRA124_CLK_I2S2, .present = true }, | 771 | [tegra_clk_i2s2] = { .dt_id = TEGRA124_CLK_I2S2, .present = true }, |
764 | [tegra_clk_gr2d] = { .dt_id = TEGRA124_CLK_GR_2D, .present = true }, | ||
765 | [tegra_clk_usbd] = { .dt_id = TEGRA124_CLK_USBD, .present = true }, | 772 | [tegra_clk_usbd] = { .dt_id = TEGRA124_CLK_USBD, .present = true }, |
766 | [tegra_clk_isp_8] = { .dt_id = TEGRA124_CLK_ISP, .present = true }, | 773 | [tegra_clk_isp_8] = { .dt_id = TEGRA124_CLK_ISP, .present = true }, |
767 | [tegra_clk_gr3d] = { .dt_id = TEGRA124_CLK_GR_3D, .present = true }, | ||
768 | [tegra_clk_disp2] = { .dt_id = TEGRA124_CLK_DISP2, .present = true }, | 774 | [tegra_clk_disp2] = { .dt_id = TEGRA124_CLK_DISP2, .present = true }, |
769 | [tegra_clk_disp1] = { .dt_id = TEGRA124_CLK_DISP1, .present = true }, | 775 | [tegra_clk_disp1] = { .dt_id = TEGRA124_CLK_DISP1, .present = true }, |
770 | [tegra_clk_host1x] = { .dt_id = TEGRA124_CLK_HOST1X, .present = true }, | 776 | [tegra_clk_host1x_8] = { .dt_id = TEGRA124_CLK_HOST1X, .present = true }, |
771 | [tegra_clk_vcp] = { .dt_id = TEGRA124_CLK_VCP, .present = true }, | 777 | [tegra_clk_vcp] = { .dt_id = TEGRA124_CLK_VCP, .present = true }, |
772 | [tegra_clk_i2s0] = { .dt_id = TEGRA124_CLK_I2S0, .present = true }, | 778 | [tegra_clk_i2s0] = { .dt_id = TEGRA124_CLK_I2S0, .present = true }, |
773 | [tegra_clk_apbdma] = { .dt_id = TEGRA124_CLK_APBDMA, .present = true }, | 779 | [tegra_clk_apbdma] = { .dt_id = TEGRA124_CLK_APBDMA, .present = true }, |
@@ -794,7 +800,7 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = { | |||
794 | [tegra_clk_uartd] = { .dt_id = TEGRA124_CLK_UARTD, .present = true }, | 800 | [tegra_clk_uartd] = { .dt_id = TEGRA124_CLK_UARTD, .present = true }, |
795 | [tegra_clk_i2c3] = { .dt_id = TEGRA124_CLK_I2C3, .present = true }, | 801 | [tegra_clk_i2c3] = { .dt_id = TEGRA124_CLK_I2C3, .present = true }, |
796 | [tegra_clk_sbc4] = { .dt_id = TEGRA124_CLK_SBC4, .present = true }, | 802 | [tegra_clk_sbc4] = { .dt_id = TEGRA124_CLK_SBC4, .present = true }, |
797 | [tegra_clk_sdmmc3] = { .dt_id = TEGRA124_CLK_SDMMC3, .present = true }, | 803 | [tegra_clk_sdmmc3_8] = { .dt_id = TEGRA124_CLK_SDMMC3, .present = true }, |
798 | [tegra_clk_pcie] = { .dt_id = TEGRA124_CLK_PCIE, .present = true }, | 804 | [tegra_clk_pcie] = { .dt_id = TEGRA124_CLK_PCIE, .present = true }, |
799 | [tegra_clk_owr] = { .dt_id = TEGRA124_CLK_OWR, .present = true }, | 805 | [tegra_clk_owr] = { .dt_id = TEGRA124_CLK_OWR, .present = true }, |
800 | [tegra_clk_afi] = { .dt_id = TEGRA124_CLK_AFI, .present = true }, | 806 | [tegra_clk_afi] = { .dt_id = TEGRA124_CLK_AFI, .present = true }, |
@@ -1286,9 +1292,9 @@ static void __init tegra124_pll_init(void __iomem *clk_base, | |||
1286 | clk_register_clkdev(clk, "pll_d2", NULL); | 1292 | clk_register_clkdev(clk, "pll_d2", NULL); |
1287 | clks[TEGRA124_CLK_PLL_D2] = clk; | 1293 | clks[TEGRA124_CLK_PLL_D2] = clk; |
1288 | 1294 | ||
1289 | /* PLLD2_OUT0 ?? */ | 1295 | /* PLLD2_OUT0 */ |
1290 | clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2", | 1296 | clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2", |
1291 | CLK_SET_RATE_PARENT, 1, 2); | 1297 | CLK_SET_RATE_PARENT, 1, 1); |
1292 | clk_register_clkdev(clk, "pll_d2_out0", NULL); | 1298 | clk_register_clkdev(clk, "pll_d2_out0", NULL); |
1293 | clks[TEGRA124_CLK_PLL_D2_OUT0] = clk; | 1299 | clks[TEGRA124_CLK_PLL_D2_OUT0] = clk; |
1294 | 1300 | ||
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index dbace152b2fa..dace2b1b5ae6 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c | |||
@@ -574,6 +574,8 @@ static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = { | |||
574 | [tegra_clk_tvdac] = { .dt_id = TEGRA20_CLK_TVDAC, .present = true }, | 574 | [tegra_clk_tvdac] = { .dt_id = TEGRA20_CLK_TVDAC, .present = true }, |
575 | [tegra_clk_vi_sensor] = { .dt_id = TEGRA20_CLK_VI_SENSOR, .present = true }, | 575 | [tegra_clk_vi_sensor] = { .dt_id = TEGRA20_CLK_VI_SENSOR, .present = true }, |
576 | [tegra_clk_afi] = { .dt_id = TEGRA20_CLK_AFI, .present = true }, | 576 | [tegra_clk_afi] = { .dt_id = TEGRA20_CLK_AFI, .present = true }, |
577 | [tegra_clk_fuse] = { .dt_id = TEGRA20_CLK_FUSE, .present = true }, | ||
578 | [tegra_clk_kfuse] = { .dt_id = TEGRA20_CLK_KFUSE, .present = true }, | ||
577 | }; | 579 | }; |
578 | 580 | ||
579 | static unsigned long tegra20_clk_measure_input_freq(void) | 581 | static unsigned long tegra20_clk_measure_input_freq(void) |
diff --git a/drivers/clk/ti/clk-33xx.c b/drivers/clk/ti/clk-33xx.c index 776ee4594bd4..028b33783d38 100644 --- a/drivers/clk/ti/clk-33xx.c +++ b/drivers/clk/ti/clk-33xx.c | |||
@@ -34,7 +34,6 @@ static struct ti_dt_clk am33xx_clks[] = { | |||
34 | DT_CLK(NULL, "dpll_core_m5_ck", "dpll_core_m5_ck"), | 34 | DT_CLK(NULL, "dpll_core_m5_ck", "dpll_core_m5_ck"), |
35 | DT_CLK(NULL, "dpll_core_m6_ck", "dpll_core_m6_ck"), | 35 | DT_CLK(NULL, "dpll_core_m6_ck", "dpll_core_m6_ck"), |
36 | DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"), | 36 | DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"), |
37 | DT_CLK("cpu0", NULL, "dpll_mpu_ck"), | ||
38 | DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"), | 37 | DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"), |
39 | DT_CLK(NULL, "dpll_ddr_ck", "dpll_ddr_ck"), | 38 | DT_CLK(NULL, "dpll_ddr_ck", "dpll_ddr_ck"), |
40 | DT_CLK(NULL, "dpll_ddr_m2_ck", "dpll_ddr_m2_ck"), | 39 | DT_CLK(NULL, "dpll_ddr_m2_ck", "dpll_ddr_m2_ck"), |
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c index a15e445570b2..e6aa10db7bba 100644 --- a/drivers/clk/ti/divider.c +++ b/drivers/clk/ti/divider.c | |||
@@ -112,7 +112,7 @@ static unsigned long ti_clk_divider_recalc_rate(struct clk_hw *hw, | |||
112 | return parent_rate; | 112 | return parent_rate; |
113 | } | 113 | } |
114 | 114 | ||
115 | return parent_rate / div; | 115 | return DIV_ROUND_UP(parent_rate, div); |
116 | } | 116 | } |
117 | 117 | ||
118 | /* | 118 | /* |
@@ -182,7 +182,7 @@ static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, | |||
182 | } | 182 | } |
183 | parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), | 183 | parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), |
184 | MULT_ROUND_UP(rate, i)); | 184 | MULT_ROUND_UP(rate, i)); |
185 | now = parent_rate / i; | 185 | now = DIV_ROUND_UP(parent_rate, i); |
186 | if (now <= rate && now > best) { | 186 | if (now <= rate && now > best) { |
187 | bestdiv = i; | 187 | bestdiv = i; |
188 | best = now; | 188 | best = now; |
@@ -205,7 +205,7 @@ static long ti_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, | |||
205 | int div; | 205 | int div; |
206 | div = ti_clk_divider_bestdiv(hw, rate, prate); | 206 | div = ti_clk_divider_bestdiv(hw, rate, prate); |
207 | 207 | ||
208 | return *prate / div; | 208 | return DIV_ROUND_UP(*prate, div); |
209 | } | 209 | } |
210 | 210 | ||
211 | static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, | 211 | static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, |
@@ -216,7 +216,7 @@ static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, | |||
216 | unsigned long flags = 0; | 216 | unsigned long flags = 0; |
217 | u32 val; | 217 | u32 val; |
218 | 218 | ||
219 | div = parent_rate / rate; | 219 | div = DIV_ROUND_UP(parent_rate, rate); |
220 | value = _get_val(divider, div); | 220 | value = _get_val(divider, div); |
221 | 221 | ||
222 | if (value > div_mask(divider)) | 222 | if (value > div_mask(divider)) |
diff --git a/drivers/clk/ux500/u8500_of_clk.c b/drivers/clk/ux500/u8500_of_clk.c index cdeff299de26..7b55ef89baa5 100644 --- a/drivers/clk/ux500/u8500_of_clk.c +++ b/drivers/clk/ux500/u8500_of_clk.c | |||
@@ -29,7 +29,8 @@ static struct clk *prcc_kclk[(PRCC_NUM_PERIPH_CLUSTERS + 1) * PRCC_PERIPHS_PER_C | |||
29 | #define PRCC_KCLK_STORE(clk, base, bit) \ | 29 | #define PRCC_KCLK_STORE(clk, base, bit) \ |
30 | prcc_kclk[(base * PRCC_PERIPHS_PER_CLUSTER) + bit] = clk | 30 | prcc_kclk[(base * PRCC_PERIPHS_PER_CLUSTER) + bit] = clk |
31 | 31 | ||
32 | struct clk *ux500_twocell_get(struct of_phandle_args *clkspec, void *data) | 32 | static struct clk *ux500_twocell_get(struct of_phandle_args *clkspec, |
33 | void *data) | ||
33 | { | 34 | { |
34 | struct clk **clk_data = data; | 35 | struct clk **clk_data = data; |
35 | unsigned int base, bit; | 36 | unsigned int base, bit; |
diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c index 09dd0173ea0a..e726c1b11218 100644 --- a/drivers/clk/zynq/clkc.c +++ b/drivers/clk/zynq/clkc.c | |||
@@ -148,7 +148,7 @@ static void __init zynq_clk_register_fclk(enum zynq_clk fclk, | |||
148 | clks[fclk] = clk_register_gate(NULL, clk_name, | 148 | clks[fclk] = clk_register_gate(NULL, clk_name, |
149 | div1_name, CLK_SET_RATE_PARENT, fclk_gate_reg, | 149 | div1_name, CLK_SET_RATE_PARENT, fclk_gate_reg, |
150 | 0, CLK_GATE_SET_TO_DISABLE, fclk_gate_lock); | 150 | 0, CLK_GATE_SET_TO_DISABLE, fclk_gate_lock); |
151 | enable_reg = readl(fclk_gate_reg) & 1; | 151 | enable_reg = clk_readl(fclk_gate_reg) & 1; |
152 | if (enable && !enable_reg) { | 152 | if (enable && !enable_reg) { |
153 | if (clk_prepare_enable(clks[fclk])) | 153 | if (clk_prepare_enable(clks[fclk])) |
154 | pr_warn("%s: FCLK%u enable failed\n", __func__, | 154 | pr_warn("%s: FCLK%u enable failed\n", __func__, |
@@ -277,7 +277,7 @@ static void __init zynq_clk_setup(struct device_node *np) | |||
277 | SLCR_IOPLL_CTRL, 4, 1, 0, &iopll_lock); | 277 | SLCR_IOPLL_CTRL, 4, 1, 0, &iopll_lock); |
278 | 278 | ||
279 | /* CPU clocks */ | 279 | /* CPU clocks */ |
280 | tmp = readl(SLCR_621_TRUE) & 1; | 280 | tmp = clk_readl(SLCR_621_TRUE) & 1; |
281 | clk = clk_register_mux(NULL, "cpu_mux", cpu_parents, 4, | 281 | clk = clk_register_mux(NULL, "cpu_mux", cpu_parents, 4, |
282 | CLK_SET_RATE_NO_REPARENT, SLCR_ARM_CLK_CTRL, 4, 2, 0, | 282 | CLK_SET_RATE_NO_REPARENT, SLCR_ARM_CLK_CTRL, 4, 2, 0, |
283 | &armclk_lock); | 283 | &armclk_lock); |
diff --git a/drivers/clk/zynq/pll.c b/drivers/clk/zynq/pll.c index 3226f54fa595..cec97596fe65 100644 --- a/drivers/clk/zynq/pll.c +++ b/drivers/clk/zynq/pll.c | |||
@@ -90,7 +90,7 @@ static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw, | |||
90 | * makes probably sense to redundantly save fbdiv in the struct | 90 | * makes probably sense to redundantly save fbdiv in the struct |
91 | * zynq_pll to save the IO access. | 91 | * zynq_pll to save the IO access. |
92 | */ | 92 | */ |
93 | fbdiv = (readl(clk->pll_ctrl) & PLLCTRL_FBDIV_MASK) >> | 93 | fbdiv = (clk_readl(clk->pll_ctrl) & PLLCTRL_FBDIV_MASK) >> |
94 | PLLCTRL_FBDIV_SHIFT; | 94 | PLLCTRL_FBDIV_SHIFT; |
95 | 95 | ||
96 | return parent_rate * fbdiv; | 96 | return parent_rate * fbdiv; |
@@ -112,7 +112,7 @@ static int zynq_pll_is_enabled(struct clk_hw *hw) | |||
112 | 112 | ||
113 | spin_lock_irqsave(clk->lock, flags); | 113 | spin_lock_irqsave(clk->lock, flags); |
114 | 114 | ||
115 | reg = readl(clk->pll_ctrl); | 115 | reg = clk_readl(clk->pll_ctrl); |
116 | 116 | ||
117 | spin_unlock_irqrestore(clk->lock, flags); | 117 | spin_unlock_irqrestore(clk->lock, flags); |
118 | 118 | ||
@@ -138,10 +138,10 @@ static int zynq_pll_enable(struct clk_hw *hw) | |||
138 | /* Power up PLL and wait for lock */ | 138 | /* Power up PLL and wait for lock */ |
139 | spin_lock_irqsave(clk->lock, flags); | 139 | spin_lock_irqsave(clk->lock, flags); |
140 | 140 | ||
141 | reg = readl(clk->pll_ctrl); | 141 | reg = clk_readl(clk->pll_ctrl); |
142 | reg &= ~(PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK); | 142 | reg &= ~(PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK); |
143 | writel(reg, clk->pll_ctrl); | 143 | clk_writel(reg, clk->pll_ctrl); |
144 | while (!(readl(clk->pll_status) & (1 << clk->lockbit))) | 144 | while (!(clk_readl(clk->pll_status) & (1 << clk->lockbit))) |
145 | ; | 145 | ; |
146 | 146 | ||
147 | spin_unlock_irqrestore(clk->lock, flags); | 147 | spin_unlock_irqrestore(clk->lock, flags); |
@@ -168,9 +168,9 @@ static void zynq_pll_disable(struct clk_hw *hw) | |||
168 | /* shut down PLL */ | 168 | /* shut down PLL */ |
169 | spin_lock_irqsave(clk->lock, flags); | 169 | spin_lock_irqsave(clk->lock, flags); |
170 | 170 | ||
171 | reg = readl(clk->pll_ctrl); | 171 | reg = clk_readl(clk->pll_ctrl); |
172 | reg |= PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK; | 172 | reg |= PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK; |
173 | writel(reg, clk->pll_ctrl); | 173 | clk_writel(reg, clk->pll_ctrl); |
174 | 174 | ||
175 | spin_unlock_irqrestore(clk->lock, flags); | 175 | spin_unlock_irqrestore(clk->lock, flags); |
176 | } | 176 | } |
@@ -225,9 +225,9 @@ struct clk *clk_register_zynq_pll(const char *name, const char *parent, | |||
225 | 225 | ||
226 | spin_lock_irqsave(pll->lock, flags); | 226 | spin_lock_irqsave(pll->lock, flags); |
227 | 227 | ||
228 | reg = readl(pll->pll_ctrl); | 228 | reg = clk_readl(pll->pll_ctrl); |
229 | reg &= ~PLLCTRL_BPQUAL_MASK; | 229 | reg &= ~PLLCTRL_BPQUAL_MASK; |
230 | writel(reg, pll->pll_ctrl); | 230 | clk_writel(reg, pll->pll_ctrl); |
231 | 231 | ||
232 | spin_unlock_irqrestore(pll->lock, flags); | 232 | spin_unlock_irqrestore(pll->lock, flags); |
233 | 233 | ||