diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2008-11-08 15:13:53 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-11-27 07:38:22 -0500 |
commit | 71a06da08c1a100bba7221d140403aa7a6cdebe7 (patch) | |
tree | bafbe34a40779afce6ea689d8e2ac82be91dc6a7 /arch/arm/mach-versatile | |
parent | d72fbdf01fc77628c0b837d0dd2fd564fa26ede6 (diff) |
[ARM] versatile: 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 Versatile implementation, so
it provides a better example of how it should be done.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-versatile')
-rw-r--r-- | arch/arm/mach-versatile/clock.c | 80 | ||||
-rw-r--r-- | arch/arm/mach-versatile/clock.h | 7 | ||||
-rw-r--r-- | arch/arm/mach-versatile/core.c | 56 | ||||
-rw-r--r-- | arch/arm/mach-versatile/include/mach/clkdev.h | 7 |
4 files changed, 61 insertions, 89 deletions
diff --git a/arch/arm/mach-versatile/clock.c b/arch/arm/mach-versatile/clock.c index 58937f1fb38..c50a44ea7ee 100644 --- a/arch/arm/mach-versatile/clock.c +++ b/arch/arm/mach-versatile/clock.c | |||
@@ -10,6 +10,7 @@ | |||
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/device.h> | ||
13 | #include <linux/list.h> | 14 | #include <linux/list.h> |
14 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
15 | #include <linux/err.h> | 16 | #include <linux/err.h> |
@@ -17,36 +18,11 @@ | |||
17 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
18 | #include <linux/mutex.h> | 19 | #include <linux/mutex.h> |
19 | 20 | ||
21 | #include <asm/clkdev.h> | ||
20 | #include <asm/hardware/icst307.h> | 22 | #include <asm/hardware/icst307.h> |
21 | 23 | ||
22 | #include "clock.h" | 24 | #include "clock.h" |
23 | 25 | ||
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 | |||
50 | int clk_enable(struct clk *clk) | 26 | int clk_enable(struct clk *clk) |
51 | { | 27 | { |
52 | return 0; | 28 | return 0; |
@@ -66,7 +42,9 @@ EXPORT_SYMBOL(clk_get_rate); | |||
66 | 42 | ||
67 | long clk_round_rate(struct clk *clk, unsigned long rate) | 43 | long clk_round_rate(struct clk *clk, unsigned long rate) |
68 | { | 44 | { |
69 | return rate; | 45 | struct icst307_vco vco; |
46 | vco = icst307_khz_to_vco(clk->params, rate / 1000); | ||
47 | return icst307_khz(clk->params, vco) * 1000; | ||
70 | } | 48 | } |
71 | EXPORT_SYMBOL(clk_round_rate); | 49 | EXPORT_SYMBOL(clk_round_rate); |
72 | 50 | ||
@@ -79,57 +57,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
79 | 57 | ||
80 | vco = icst307_khz_to_vco(clk->params, rate / 1000); | 58 | vco = icst307_khz_to_vco(clk->params, rate / 1000); |
81 | clk->rate = icst307_khz(clk->params, vco) * 1000; | 59 | clk->rate = icst307_khz(clk->params, vco) * 1000; |
82 | |||
83 | printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n", | ||
84 | clk->name, vco.s, vco.r, vco.v); | ||
85 | |||
86 | clk->setvco(clk, vco); | 60 | clk->setvco(clk, vco); |
87 | ret = 0; | 61 | ret = 0; |
88 | } | 62 | } |
89 | return ret; | 63 | return ret; |
90 | } | 64 | } |
91 | EXPORT_SYMBOL(clk_set_rate); | 65 | EXPORT_SYMBOL(clk_set_rate); |
92 | |||
93 | /* | ||
94 | * These are fixed clocks. | ||
95 | */ | ||
96 | static struct clk kmi_clk = { | ||
97 | .name = "KMIREFCLK", | ||
98 | .rate = 24000000, | ||
99 | }; | ||
100 | |||
101 | static struct clk uart_clk = { | ||
102 | .name = "UARTCLK", | ||
103 | .rate = 24000000, | ||
104 | }; | ||
105 | |||
106 | static struct clk mmci_clk = { | ||
107 | .name = "MCLK", | ||
108 | .rate = 24000000, | ||
109 | }; | ||
110 | |||
111 | int clk_register(struct clk *clk) | ||
112 | { | ||
113 | mutex_lock(&clocks_mutex); | ||
114 | list_add(&clk->node, &clocks); | ||
115 | mutex_unlock(&clocks_mutex); | ||
116 | return 0; | ||
117 | } | ||
118 | EXPORT_SYMBOL(clk_register); | ||
119 | |||
120 | void clk_unregister(struct clk *clk) | ||
121 | { | ||
122 | mutex_lock(&clocks_mutex); | ||
123 | list_del(&clk->node); | ||
124 | mutex_unlock(&clocks_mutex); | ||
125 | } | ||
126 | EXPORT_SYMBOL(clk_unregister); | ||
127 | |||
128 | static int __init clk_init(void) | ||
129 | { | ||
130 | clk_register(&kmi_clk); | ||
131 | clk_register(&uart_clk); | ||
132 | clk_register(&mmci_clk); | ||
133 | return 0; | ||
134 | } | ||
135 | arch_initcall(clk_init); | ||
diff --git a/arch/arm/mach-versatile/clock.h b/arch/arm/mach-versatile/clock.h index 8b0b61dd17e..03468fdc3e5 100644 --- a/arch/arm/mach-versatile/clock.h +++ b/arch/arm/mach-versatile/clock.h | |||
@@ -12,14 +12,9 @@ struct module; | |||
12 | struct icst307_params; | 12 | struct icst307_params; |
13 | 13 | ||
14 | struct clk { | 14 | struct clk { |
15 | struct list_head node; | ||
16 | unsigned long rate; | 15 | unsigned long rate; |
17 | struct module *owner; | ||
18 | const char *name; | ||
19 | const struct icst307_params *params; | 16 | const struct icst307_params *params; |
17 | u32 oscoff; | ||
20 | void *data; | 18 | void *data; |
21 | void (*setvco)(struct clk *, struct icst307_vco vco); | 19 | void (*setvco)(struct clk *, struct icst307_vco vco); |
22 | }; | 20 | }; |
23 | |||
24 | int clk_register(struct clk *clk); | ||
25 | void clk_unregister(struct clk *clk); | ||
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 565e0ba0d67..df25aa13850 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/cnt32_to_63.h> | 31 | #include <linux/cnt32_to_63.h> |
32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
33 | 33 | ||
34 | #include <asm/clkdev.h> | ||
34 | #include <asm/system.h> | 35 | #include <asm/system.h> |
35 | #include <mach/hardware.h> | 36 | #include <mach/hardware.h> |
36 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
@@ -373,22 +374,60 @@ static const struct icst307_params versatile_oscvco_params = { | |||
373 | 374 | ||
374 | static void versatile_oscvco_set(struct clk *clk, struct icst307_vco vco) | 375 | static void versatile_oscvco_set(struct clk *clk, struct icst307_vco vco) |
375 | { | 376 | { |
376 | void __iomem *sys_lock = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LOCK_OFFSET; | 377 | void __iomem *sys = __io_address(VERSATILE_SYS_BASE); |
377 | void __iomem *sys_osc = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSCCLCD_OFFSET; | 378 | void __iomem *sys_lock = sys + VERSATILE_SYS_LOCK_OFFSET; |
378 | u32 val; | 379 | u32 val; |
379 | 380 | ||
380 | val = readl(sys_osc) & ~0x7ffff; | 381 | val = readl(sys + clk->oscoff) & ~0x7ffff; |
381 | val |= vco.v | (vco.r << 9) | (vco.s << 16); | 382 | val |= vco.v | (vco.r << 9) | (vco.s << 16); |
382 | 383 | ||
383 | writel(0xa05f, sys_lock); | 384 | writel(0xa05f, sys_lock); |
384 | writel(val, sys_osc); | 385 | writel(val, sys + clk->oscoff); |
385 | writel(0, sys_lock); | 386 | writel(0, sys_lock); |
386 | } | 387 | } |
387 | 388 | ||
388 | static struct clk versatile_clcd_clk = { | 389 | static struct clk osc4_clk = { |
389 | .name = "CLCDCLK", | ||
390 | .params = &versatile_oscvco_params, | 390 | .params = &versatile_oscvco_params, |
391 | .setvco = versatile_oscvco_set, | 391 | .oscoff = VERSATILE_SYS_OSCCLCD_OFFSET, |
392 | .setvco = versatile_oscvco_set, | ||
393 | }; | ||
394 | |||
395 | /* | ||
396 | * These are fixed clocks. | ||
397 | */ | ||
398 | static struct clk ref24_clk = { | ||
399 | .rate = 24000000, | ||
400 | }; | ||
401 | |||
402 | static struct clk_lookup lookups[] __initdata = { | ||
403 | { /* UART0 */ | ||
404 | .dev_id = "dev:f1", | ||
405 | .clk = &ref24_clk, | ||
406 | }, { /* UART1 */ | ||
407 | .dev_id = "dev:f2", | ||
408 | .clk = &ref24_clk, | ||
409 | }, { /* UART2 */ | ||
410 | .dev_id = "dev:f3", | ||
411 | .clk = &ref24_clk, | ||
412 | }, { /* UART3 */ | ||
413 | .dev_id = "fpga:09", | ||
414 | .clk = &ref24_clk, | ||
415 | }, { /* KMI0 */ | ||
416 | .dev_id = "fpga:06", | ||
417 | .clk = &ref24_clk, | ||
418 | }, { /* KMI1 */ | ||
419 | .dev_id = "fpga:07", | ||
420 | .clk = &ref24_clk, | ||
421 | }, { /* MMC0 */ | ||
422 | .dev_id = "fpga:05", | ||
423 | .clk = &ref24_clk, | ||
424 | }, { /* MMC1 */ | ||
425 | .dev_id = "fpga:0b", | ||
426 | .clk = &ref24_clk, | ||
427 | }, { /* CLCD */ | ||
428 | .dev_id = "dev:20", | ||
429 | .clk = &osc4_clk, | ||
430 | } | ||
392 | }; | 431 | }; |
393 | 432 | ||
394 | /* | 433 | /* |
@@ -786,7 +825,8 @@ void __init versatile_init(void) | |||
786 | { | 825 | { |
787 | int i; | 826 | int i; |
788 | 827 | ||
789 | clk_register(&versatile_clcd_clk); | 828 | for (i = 0; i < ARRAY_SIZE(lookups); i++) |
829 | clkdev_add(&lookups[i]); | ||
790 | 830 | ||
791 | platform_device_register(&versatile_flash_device); | 831 | platform_device_register(&versatile_flash_device); |
792 | platform_device_register(&versatile_i2c_device); | 832 | platform_device_register(&versatile_i2c_device); |
diff --git a/arch/arm/mach-versatile/include/mach/clkdev.h b/arch/arm/mach-versatile/include/mach/clkdev.h new file mode 100644 index 00000000000..04b37a89801 --- /dev/null +++ b/arch/arm/mach-versatile/include/mach/clkdev.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef __ASM_MACH_CLKDEV_H | ||
2 | #define __ASM_MACH_CLKDEV_H | ||
3 | |||
4 | #define __clk_get(clk) ({ 1; }) | ||
5 | #define __clk_put(clk) do { } while (0) | ||
6 | |||
7 | #endif | ||