aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2008-11-08 15:08:08 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-11-27 07:38:22 -0500
commitd72fbdf01fc77628c0b837d0dd2fd564fa26ede6 (patch)
tree5ea1ba4f2771cfaf454621f8a2f6bdd616aa8e88
parentcf30fb4a4f2d261a6527a654a7fdc8636f1e5b16 (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/Kconfig1
-rw-r--r--arch/arm/mach-integrator/clock.c80
-rw-r--r--arch/arm/mach-integrator/clock.h25
-rw-r--r--arch/arm/mach-integrator/core.c35
-rw-r--r--arch/arm/mach-integrator/impd1.c26
-rw-r--r--arch/arm/mach-integrator/include/mach/clkdev.h25
-rw-r--r--arch/arm/mach-integrator/integrator_cp.c18
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
24static LIST_HEAD(clocks);
25static DEFINE_MUTEX(clocks_mutex);
26
27struct 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}
42EXPORT_SYMBOL(clk_get);
43
44void clk_put(struct clk *clk)
45{
46 module_put(clk->owner);
47}
48EXPORT_SYMBOL(clk_put);
49 19
50int clk_enable(struct clk *clk) 20int clk_enable(struct clk *clk)
51{ 21{
@@ -67,7 +37,6 @@ EXPORT_SYMBOL(clk_get_rate);
67long clk_round_rate(struct clk *clk, unsigned long rate) 37long 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);
76int clk_set_rate(struct clk *clk, unsigned long rate) 45int 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}
93EXPORT_SYMBOL(clk_set_rate); 59EXPORT_SYMBOL(clk_set_rate);
94
95/*
96 * These are fixed clocks.
97 */
98static struct clk kmi_clk = {
99 .name = "KMIREFCLK",
100 .rate = 24000000,
101};
102
103static struct clk uart_clk = {
104 .name = "UARTCLK",
105 .rate = 14745600,
106};
107
108int 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}
115EXPORT_SYMBOL(clk_register);
116
117void clk_unregister(struct clk *clk)
118{
119 mutex_lock(&clocks_mutex);
120 list_del(&clk->node);
121 mutex_unlock(&clocks_mutex);
122}
123EXPORT_SYMBOL(clk_unregister);
124
125static int __init clk_init(void)
126{
127 clk_register(&kmi_clk);
128 clk_register(&uart_clk);
129 return 0;
130}
131arch_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 */
11struct module;
12struct icst525_params;
13
14struct 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
24int clk_register(struct clk *clk);
25void 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 */
116static struct clk clk24mhz = {
117 .rate = 24000000,
118};
119
120static struct clk uartclk = {
121 .rate = 14745600,
122};
123
124static 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
111static int __init integrator_init(void) 143static 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
32static int module_id; 32static int module_id;
33 33
34module_param_named(lmid, module_id, int, 0444); 34module_param_named(lmid, module_id, int, 0444);
@@ -37,6 +37,7 @@ MODULE_PARM_DESC(lmid, "logic module stack position");
37struct impd1_module { 37struct 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
42static const struct icst525_params impd1_vco_params = { 43static const struct icst525_params impd1_vco_params = {
@@ -339,9 +340,8 @@ static struct impd1_device impd1_devs[] = {
339 } 340 }
340}; 341};
341 342
342static const char *impd1_vconames[2] = { 343static struct clk fixed_14745600 = {
343 "CLCDCLK", 344 .rate = 14745600,
344 "AUXVCO2",
345}; 345};
346 346
347static int impd1_probe(struct lm_device *dev) 347static 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
7struct 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
15static inline int __clk_get(struct clk *clk)
16{
17 return try_module_get(clk->owner);
18}
19
20static 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
292static struct clk cp_clcd_clk = { 293static 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
298static struct clk cp_mmci_clk = { 298static 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