diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2008-11-08 15:08:08 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-11-27 07:38:22 -0500 |
commit | d72fbdf01fc77628c0b837d0dd2fd564fa26ede6 (patch) | |
tree | 5ea1ba4f2771cfaf454621f8a2f6bdd616aa8e88 | |
parent | cf30fb4a4f2d261a6527a654a7fdc8636f1e5b16 (diff) |
[ARM] integrator: convert to clkdev and lookup clocks by device name
People often point to the Integrator/Versatile/Realview
implementations to justify using the consumer name as the sole
selector for clocks.
Eliminate this excuse by changing the Integrator implementation, so
it provides a better example of how it should be done.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-integrator/clock.c | 80 | ||||
-rw-r--r-- | arch/arm/mach-integrator/clock.h | 25 | ||||
-rw-r--r-- | arch/arm/mach-integrator/core.c | 35 | ||||
-rw-r--r-- | arch/arm/mach-integrator/impd1.c | 26 | ||||
-rw-r--r-- | arch/arm/mach-integrator/include/mach/clkdev.h | 25 | ||||
-rw-r--r-- | arch/arm/mach-integrator/integrator_cp.c | 18 |
7 files changed, 91 insertions, 119 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index d4fcf3009c38..f1ac3937365e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -210,6 +210,7 @@ config ARCH_INTEGRATOR | |||
210 | bool "ARM Ltd. Integrator family" | 210 | bool "ARM Ltd. Integrator family" |
211 | select ARM_AMBA | 211 | select ARM_AMBA |
212 | select HAVE_CLK | 212 | select HAVE_CLK |
213 | select COMMON_CLKDEV | ||
213 | select ICST525 | 214 | select ICST525 |
214 | help | 215 | help |
215 | Support for ARM's Integrator platform. | 216 | Support for ARM's Integrator platform. |
diff --git a/arch/arm/mach-integrator/clock.c b/arch/arm/mach-integrator/clock.c index 8d761fdd2ecd..989ecf5f5c46 100644 --- a/arch/arm/mach-integrator/clock.c +++ b/arch/arm/mach-integrator/clock.c | |||
@@ -10,42 +10,12 @@ | |||
10 | */ | 10 | */ |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/list.h> | ||
14 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
15 | #include <linux/err.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
18 | #include <linux/mutex.h> | 15 | #include <linux/mutex.h> |
19 | 16 | ||
20 | #include <asm/hardware/icst525.h> | 17 | #include <asm/clkdev.h> |
21 | 18 | #include <mach/clkdev.h> | |
22 | #include "clock.h" | ||
23 | |||
24 | static LIST_HEAD(clocks); | ||
25 | static DEFINE_MUTEX(clocks_mutex); | ||
26 | |||
27 | struct clk *clk_get(struct device *dev, const char *id) | ||
28 | { | ||
29 | struct clk *p, *clk = ERR_PTR(-ENOENT); | ||
30 | |||
31 | mutex_lock(&clocks_mutex); | ||
32 | list_for_each_entry(p, &clocks, node) { | ||
33 | if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { | ||
34 | clk = p; | ||
35 | break; | ||
36 | } | ||
37 | } | ||
38 | mutex_unlock(&clocks_mutex); | ||
39 | |||
40 | return clk; | ||
41 | } | ||
42 | EXPORT_SYMBOL(clk_get); | ||
43 | |||
44 | void clk_put(struct clk *clk) | ||
45 | { | ||
46 | module_put(clk->owner); | ||
47 | } | ||
48 | EXPORT_SYMBOL(clk_put); | ||
49 | 19 | ||
50 | int clk_enable(struct clk *clk) | 20 | int clk_enable(struct clk *clk) |
51 | { | 21 | { |
@@ -67,7 +37,6 @@ EXPORT_SYMBOL(clk_get_rate); | |||
67 | long clk_round_rate(struct clk *clk, unsigned long rate) | 37 | long clk_round_rate(struct clk *clk, unsigned long rate) |
68 | { | 38 | { |
69 | struct icst525_vco vco; | 39 | struct icst525_vco vco; |
70 | |||
71 | vco = icst525_khz_to_vco(clk->params, rate / 1000); | 40 | vco = icst525_khz_to_vco(clk->params, rate / 1000); |
72 | return icst525_khz(clk->params, vco) * 1000; | 41 | return icst525_khz(clk->params, vco) * 1000; |
73 | } | 42 | } |
@@ -76,56 +45,15 @@ EXPORT_SYMBOL(clk_round_rate); | |||
76 | int clk_set_rate(struct clk *clk, unsigned long rate) | 45 | int clk_set_rate(struct clk *clk, unsigned long rate) |
77 | { | 46 | { |
78 | int ret = -EIO; | 47 | int ret = -EIO; |
48 | |||
79 | if (clk->setvco) { | 49 | if (clk->setvco) { |
80 | struct icst525_vco vco; | 50 | struct icst525_vco vco; |
81 | 51 | ||
82 | vco = icst525_khz_to_vco(clk->params, rate / 1000); | 52 | vco = icst525_khz_to_vco(clk->params, rate / 1000); |
83 | clk->rate = icst525_khz(clk->params, vco) * 1000; | 53 | clk->rate = icst525_khz(clk->params, vco) * 1000; |
84 | |||
85 | printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n", | ||
86 | clk->name, vco.s, vco.r, vco.v); | ||
87 | |||
88 | clk->setvco(clk, vco); | 54 | clk->setvco(clk, vco); |
89 | ret = 0; | 55 | ret = 0; |
90 | } | 56 | } |
91 | return 0; | 57 | return ret; |
92 | } | 58 | } |
93 | EXPORT_SYMBOL(clk_set_rate); | 59 | EXPORT_SYMBOL(clk_set_rate); |
94 | |||
95 | /* | ||
96 | * These are fixed clocks. | ||
97 | */ | ||
98 | static struct clk kmi_clk = { | ||
99 | .name = "KMIREFCLK", | ||
100 | .rate = 24000000, | ||
101 | }; | ||
102 | |||
103 | static struct clk uart_clk = { | ||
104 | .name = "UARTCLK", | ||
105 | .rate = 14745600, | ||
106 | }; | ||
107 | |||
108 | int clk_register(struct clk *clk) | ||
109 | { | ||
110 | mutex_lock(&clocks_mutex); | ||
111 | list_add(&clk->node, &clocks); | ||
112 | mutex_unlock(&clocks_mutex); | ||
113 | return 0; | ||
114 | } | ||
115 | EXPORT_SYMBOL(clk_register); | ||
116 | |||
117 | void clk_unregister(struct clk *clk) | ||
118 | { | ||
119 | mutex_lock(&clocks_mutex); | ||
120 | list_del(&clk->node); | ||
121 | mutex_unlock(&clocks_mutex); | ||
122 | } | ||
123 | EXPORT_SYMBOL(clk_unregister); | ||
124 | |||
125 | static int __init clk_init(void) | ||
126 | { | ||
127 | clk_register(&kmi_clk); | ||
128 | clk_register(&uart_clk); | ||
129 | return 0; | ||
130 | } | ||
131 | arch_initcall(clk_init); | ||
diff --git a/arch/arm/mach-integrator/clock.h b/arch/arm/mach-integrator/clock.h index 09e6328ceba9..e69de29bb2d1 100644 --- a/arch/arm/mach-integrator/clock.h +++ b/arch/arm/mach-integrator/clock.h | |||
@@ -1,25 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-integrator/clock.h | ||
3 | * | ||
4 | * Copyright (C) 2004 ARM Limited. | ||
5 | * Written by Deep Blue Solutions Limited. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | struct module; | ||
12 | struct icst525_params; | ||
13 | |||
14 | struct clk { | ||
15 | struct list_head node; | ||
16 | unsigned long rate; | ||
17 | struct module *owner; | ||
18 | const char *name; | ||
19 | const struct icst525_params *params; | ||
20 | void *data; | ||
21 | void (*setvco)(struct clk *, struct icst525_vco vco); | ||
22 | }; | ||
23 | |||
24 | int clk_register(struct clk *clk); | ||
25 | void clk_unregister(struct clk *clk); | ||
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index 595b7392ee4e..c89c949b4d45 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/amba/serial.h> | 21 | #include <linux/amba/serial.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | 23 | ||
24 | #include <asm/clkdev.h> | ||
25 | #include <mach/clkdev.h> | ||
24 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
25 | #include <asm/irq.h> | 27 | #include <asm/irq.h> |
26 | #include <asm/hardware/arm_timer.h> | 28 | #include <asm/hardware/arm_timer.h> |
@@ -108,10 +110,43 @@ static struct amba_device *amba_devs[] __initdata = { | |||
108 | &kmi1_device, | 110 | &kmi1_device, |
109 | }; | 111 | }; |
110 | 112 | ||
113 | /* | ||
114 | * These are fixed clocks. | ||
115 | */ | ||
116 | static struct clk clk24mhz = { | ||
117 | .rate = 24000000, | ||
118 | }; | ||
119 | |||
120 | static struct clk uartclk = { | ||
121 | .rate = 14745600, | ||
122 | }; | ||
123 | |||
124 | static struct clk_lookup lookups[] __initdata = { | ||
125 | { /* UART0 */ | ||
126 | .dev_id = "mb:16", | ||
127 | .clk = &uartclk, | ||
128 | }, { /* UART1 */ | ||
129 | .dev_id = "mb:17", | ||
130 | .clk = &uartclk, | ||
131 | }, { /* KMI0 */ | ||
132 | .dev_id = "mb:18", | ||
133 | .clk = &clk24mhz, | ||
134 | }, { /* KMI1 */ | ||
135 | .dev_id = "mb:19", | ||
136 | .clk = &clk24mhz, | ||
137 | }, { /* MMCI - IntegratorCP */ | ||
138 | .dev_id = "mb:1c", | ||
139 | .clk = &uartclk, | ||
140 | } | ||
141 | }; | ||
142 | |||
111 | static int __init integrator_init(void) | 143 | static int __init integrator_init(void) |
112 | { | 144 | { |
113 | int i; | 145 | int i; |
114 | 146 | ||
147 | for (i = 0; i < ARRAY_SIZE(lookups); i++) | ||
148 | clkdev_add(&lookups[i]); | ||
149 | |||
115 | for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { | 150 | for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { |
116 | struct amba_device *d = amba_devs[i]; | 151 | struct amba_device *d = amba_devs[i]; |
117 | amba_device_register(d, &iomem_resource); | 152 | amba_device_register(d, &iomem_resource); |
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index 172299a78302..0058c937719e 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c | |||
@@ -22,13 +22,13 @@ | |||
22 | #include <linux/amba/clcd.h> | 22 | #include <linux/amba/clcd.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | 24 | ||
25 | #include <asm/clkdev.h> | ||
26 | #include <mach/clkdev.h> | ||
25 | #include <asm/hardware/icst525.h> | 27 | #include <asm/hardware/icst525.h> |
26 | #include <mach/lm.h> | 28 | #include <mach/lm.h> |
27 | #include <mach/impd1.h> | 29 | #include <mach/impd1.h> |
28 | #include <asm/sizes.h> | 30 | #include <asm/sizes.h> |
29 | 31 | ||
30 | #include "clock.h" | ||
31 | |||
32 | static int module_id; | 32 | static int module_id; |
33 | 33 | ||
34 | module_param_named(lmid, module_id, int, 0444); | 34 | module_param_named(lmid, module_id, int, 0444); |
@@ -37,6 +37,7 @@ MODULE_PARM_DESC(lmid, "logic module stack position"); | |||
37 | struct impd1_module { | 37 | struct impd1_module { |
38 | void __iomem *base; | 38 | void __iomem *base; |
39 | struct clk vcos[2]; | 39 | struct clk vcos[2]; |
40 | struct clk_lookup *clks[3]; | ||
40 | }; | 41 | }; |
41 | 42 | ||
42 | static const struct icst525_params impd1_vco_params = { | 43 | static const struct icst525_params impd1_vco_params = { |
@@ -339,9 +340,8 @@ static struct impd1_device impd1_devs[] = { | |||
339 | } | 340 | } |
340 | }; | 341 | }; |
341 | 342 | ||
342 | static const char *impd1_vconames[2] = { | 343 | static struct clk fixed_14745600 = { |
343 | "CLCDCLK", | 344 | .rate = 14745600, |
344 | "AUXVCO2", | ||
345 | }; | 345 | }; |
346 | 346 | ||
347 | static int impd1_probe(struct lm_device *dev) | 347 | static int impd1_probe(struct lm_device *dev) |
@@ -374,14 +374,20 @@ static int impd1_probe(struct lm_device *dev) | |||
374 | 374 | ||
375 | for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++) { | 375 | for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++) { |
376 | impd1->vcos[i].owner = THIS_MODULE, | 376 | impd1->vcos[i].owner = THIS_MODULE, |
377 | impd1->vcos[i].name = impd1_vconames[i], | ||
378 | impd1->vcos[i].params = &impd1_vco_params, | 377 | impd1->vcos[i].params = &impd1_vco_params, |
379 | impd1->vcos[i].data = impd1, | 378 | impd1->vcos[i].data = impd1, |
380 | impd1->vcos[i].setvco = impd1_setvco; | 379 | impd1->vcos[i].setvco = impd1_setvco; |
381 | |||
382 | clk_register(&impd1->vcos[i]); | ||
383 | } | 380 | } |
384 | 381 | ||
382 | impd1->clks[0] = clkdev_alloc(&impd1->vcos[0], NULL, "lm%x:01000", | ||
383 | dev->id); | ||
384 | impd1->clks[1] = clkdev_alloc(&fixed_14745600, NULL, "lm%x:00100", | ||
385 | dev->id); | ||
386 | impd1->clks[2] = clkdev_alloc(&fixed_14745600, NULL, "lm%x:00200", | ||
387 | dev->id); | ||
388 | for (i = 0; i < ARRAY_SIZE(impd1->clks); i++) | ||
389 | clkdev_add(impd1->clks[i]); | ||
390 | |||
385 | for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) { | 391 | for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) { |
386 | struct impd1_device *idev = impd1_devs + i; | 392 | struct impd1_device *idev = impd1_devs + i; |
387 | struct amba_device *d; | 393 | struct amba_device *d; |
@@ -434,8 +440,8 @@ static void impd1_remove(struct lm_device *dev) | |||
434 | 440 | ||
435 | device_for_each_child(&dev->dev, NULL, impd1_remove_one); | 441 | device_for_each_child(&dev->dev, NULL, impd1_remove_one); |
436 | 442 | ||
437 | for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++) | 443 | for (i = 0; i < ARRAY_SIZE(impd1->clks); i++) |
438 | clk_unregister(&impd1->vcos[i]); | 444 | clkdev_drop(impd1->clks[i]); |
439 | 445 | ||
440 | lm_set_drvdata(dev, NULL); | 446 | lm_set_drvdata(dev, NULL); |
441 | 447 | ||
diff --git a/arch/arm/mach-integrator/include/mach/clkdev.h b/arch/arm/mach-integrator/include/mach/clkdev.h new file mode 100644 index 000000000000..9293e410832a --- /dev/null +++ b/arch/arm/mach-integrator/include/mach/clkdev.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #ifndef __ASM_MACH_CLKDEV_H | ||
2 | #define __ASM_MACH_CLKDEV_H | ||
3 | |||
4 | #include <linux/module.h> | ||
5 | #include <asm/hardware/icst525.h> | ||
6 | |||
7 | struct clk { | ||
8 | unsigned long rate; | ||
9 | struct module *owner; | ||
10 | const struct icst525_params *params; | ||
11 | void *data; | ||
12 | void (*setvco)(struct clk *, struct icst525_vco vco); | ||
13 | }; | ||
14 | |||
15 | static inline int __clk_get(struct clk *clk) | ||
16 | { | ||
17 | return try_module_get(clk->owner); | ||
18 | } | ||
19 | |||
20 | static inline void __clk_put(struct clk *clk) | ||
21 | { | ||
22 | module_put(clk->owner); | ||
23 | } | ||
24 | |||
25 | #endif | ||
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 88026ccd5ac9..427c2d8dc123 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/amba/clcd.h> | 21 | #include <linux/amba/clcd.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | 23 | ||
24 | #include <asm/clkdev.h> | ||
25 | #include <mach/clkdev.h> | ||
24 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
25 | #include <asm/irq.h> | 27 | #include <asm/irq.h> |
26 | #include <asm/setup.h> | 28 | #include <asm/setup.h> |
@@ -38,7 +40,6 @@ | |||
38 | #include <asm/mach/time.h> | 40 | #include <asm/mach/time.h> |
39 | 41 | ||
40 | #include "common.h" | 42 | #include "common.h" |
41 | #include "clock.h" | ||
42 | 43 | ||
43 | #define INTCP_PA_MMC_BASE 0x1c000000 | 44 | #define INTCP_PA_MMC_BASE 0x1c000000 |
44 | #define INTCP_PA_AACI_BASE 0x1d000000 | 45 | #define INTCP_PA_AACI_BASE 0x1d000000 |
@@ -289,15 +290,16 @@ static void cp_auxvco_set(struct clk *clk, struct icst525_vco vco) | |||
289 | writel(0, CM_LOCK); | 290 | writel(0, CM_LOCK); |
290 | } | 291 | } |
291 | 292 | ||
292 | static struct clk cp_clcd_clk = { | 293 | static struct clk cp_auxclk = { |
293 | .name = "CLCDCLK", | ||
294 | .params = &cp_auxvco_params, | 294 | .params = &cp_auxvco_params, |
295 | .setvco = cp_auxvco_set, | 295 | .setvco = cp_auxvco_set, |
296 | }; | 296 | }; |
297 | 297 | ||
298 | static struct clk cp_mmci_clk = { | 298 | static struct clk_lookup cp_lookups[] = { |
299 | .name = "MCLK", | 299 | { /* CLCD */ |
300 | .rate = 14745600, | 300 | .dev_id = "mb:c0", |
301 | .clk = &cp_auxclk, | ||
302 | }, | ||
301 | }; | 303 | }; |
302 | 304 | ||
303 | /* | 305 | /* |
@@ -554,8 +556,8 @@ static void __init intcp_init(void) | |||
554 | { | 556 | { |
555 | int i; | 557 | int i; |
556 | 558 | ||
557 | clk_register(&cp_clcd_clk); | 559 | for (i = 0; i < ARRAY_SIZE(cp_lookups); i++) |
558 | clk_register(&cp_mmci_clk); | 560 | clkdev_add(&cp_lookups[i]); |
559 | 561 | ||
560 | platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs)); | 562 | platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs)); |
561 | 563 | ||