aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-pxa/clock.c
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2007-08-20 05:18:02 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2007-10-12 16:14:55 -0400
commita6dba20c5c7b3a18d69bcbd60a1d2ebc0536f0ce (patch)
tree954e4f3aa86f730fc4b8834126e7886022c0dccf /arch/arm/mach-pxa/clock.c
parent00dc4f949e7423769de1a160c590840534ea3a70 (diff)
[ARM] pxa: introduce clk support for PXA SoC clocks
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-pxa/clock.c')
-rw-r--r--arch/arm/mach-pxa/clock.c79
1 files changed, 50 insertions, 29 deletions
diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
index 34a31caa6f9d..83ef5ecaf432 100644
--- a/arch/arm/mach-pxa/clock.c
+++ b/arch/arm/mach-pxa/clock.c
@@ -9,19 +9,15 @@
9#include <linux/string.h> 9#include <linux/string.h>
10#include <linux/clk.h> 10#include <linux/clk.h>
11#include <linux/spinlock.h> 11#include <linux/spinlock.h>
12#include <linux/platform_device.h>
13#include <linux/delay.h>
12 14
13#include <asm/arch/pxa-regs.h> 15#include <asm/arch/pxa-regs.h>
14#include <asm/hardware.h> 16#include <asm/hardware.h>
15 17
16struct clk { 18#include "devices.h"
17 struct list_head node; 19#include "generic.h"
18 unsigned long rate; 20#include "clock.h"
19 struct module *owner;
20 const char *name;
21 unsigned int enabled;
22 void (*enable)(void);
23 void (*disable)(void);
24};
25 21
26static LIST_HEAD(clocks); 22static LIST_HEAD(clocks);
27static DEFINE_MUTEX(clocks_mutex); 23static DEFINE_MUTEX(clocks_mutex);
@@ -33,7 +29,8 @@ struct clk *clk_get(struct device *dev, const char *id)
33 29
34 mutex_lock(&clocks_mutex); 30 mutex_lock(&clocks_mutex);
35 list_for_each_entry(p, &clocks, node) { 31 list_for_each_entry(p, &clocks, node) {
36 if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { 32 if (strcmp(id, p->name) == 0 &&
33 (p->dev == NULL || p->dev == dev)) {
37 clk = p; 34 clk = p;
38 break; 35 break;
39 } 36 }
@@ -46,7 +43,6 @@ EXPORT_SYMBOL(clk_get);
46 43
47void clk_put(struct clk *clk) 44void clk_put(struct clk *clk)
48{ 45{
49 module_put(clk->owner);
50} 46}
51EXPORT_SYMBOL(clk_put); 47EXPORT_SYMBOL(clk_put);
52 48
@@ -56,8 +52,12 @@ int clk_enable(struct clk *clk)
56 52
57 spin_lock_irqsave(&clocks_lock, flags); 53 spin_lock_irqsave(&clocks_lock, flags);
58 if (clk->enabled++ == 0) 54 if (clk->enabled++ == 0)
59 clk->enable(); 55 clk->ops->enable(clk);
60 spin_unlock_irqrestore(&clocks_lock, flags); 56 spin_unlock_irqrestore(&clocks_lock, flags);
57
58 if (clk->delay)
59 udelay(clk->delay);
60
61 return 0; 61 return 0;
62} 62}
63EXPORT_SYMBOL(clk_enable); 63EXPORT_SYMBOL(clk_enable);
@@ -70,54 +70,75 @@ void clk_disable(struct clk *clk)
70 70
71 spin_lock_irqsave(&clocks_lock, flags); 71 spin_lock_irqsave(&clocks_lock, flags);
72 if (--clk->enabled == 0) 72 if (--clk->enabled == 0)
73 clk->disable(); 73 clk->ops->disable(clk);
74 spin_unlock_irqrestore(&clocks_lock, flags); 74 spin_unlock_irqrestore(&clocks_lock, flags);
75} 75}
76EXPORT_SYMBOL(clk_disable); 76EXPORT_SYMBOL(clk_disable);
77 77
78unsigned long clk_get_rate(struct clk *clk) 78unsigned long clk_get_rate(struct clk *clk)
79{ 79{
80 return clk->rate; 80 unsigned long rate;
81
82 rate = clk->rate;
83 if (clk->ops->getrate)
84 rate = clk->ops->getrate(clk);
85
86 return rate;
81} 87}
82EXPORT_SYMBOL(clk_get_rate); 88EXPORT_SYMBOL(clk_get_rate);
83 89
84 90
85static void clk_gpio27_enable(void) 91static void clk_gpio27_enable(struct clk *clk)
86{ 92{
87 pxa_gpio_mode(GPIO11_3_6MHz_MD); 93 pxa_gpio_mode(GPIO11_3_6MHz_MD);
88} 94}
89 95
90static void clk_gpio27_disable(void) 96static void clk_gpio27_disable(struct clk *clk)
91{ 97{
92} 98}
93 99
94static struct clk clk_gpio27 = { 100static const struct clkops clk_gpio27_ops = {
95 .name = "GPIO27_CLK",
96 .rate = 3686400,
97 .enable = clk_gpio27_enable, 101 .enable = clk_gpio27_enable,
98 .disable = clk_gpio27_disable, 102 .disable = clk_gpio27_disable,
99}; 103};
100 104
101int clk_register(struct clk *clk) 105
106void clk_cken_enable(struct clk *clk)
102{ 107{
103 mutex_lock(&clocks_mutex); 108 CKEN |= 1 << clk->cken;
104 list_add(&clk->node, &clocks);
105 mutex_unlock(&clocks_mutex);
106 return 0;
107} 109}
108EXPORT_SYMBOL(clk_register);
109 110
110void clk_unregister(struct clk *clk) 111void clk_cken_disable(struct clk *clk)
111{ 112{
113 CKEN &= ~(1 << clk->cken);
114}
115
116const struct clkops clk_cken_ops = {
117 .enable = clk_cken_enable,
118 .disable = clk_cken_disable,
119};
120
121static struct clk common_clks[] = {
122 {
123 .name = "GPIO27_CLK",
124 .ops = &clk_gpio27_ops,
125 .rate = 3686400,
126 },
127};
128
129void clks_register(struct clk *clks, size_t num)
130{
131 int i;
132
112 mutex_lock(&clocks_mutex); 133 mutex_lock(&clocks_mutex);
113 list_del(&clk->node); 134 for (i = 0; i < num; i++)
135 list_add(&clks[i].node, &clocks);
114 mutex_unlock(&clocks_mutex); 136 mutex_unlock(&clocks_mutex);
115} 137}
116EXPORT_SYMBOL(clk_unregister);
117 138
118static int __init clk_init(void) 139static int __init clk_init(void)
119{ 140{
120 clk_register(&clk_gpio27); 141 clks_register(common_clks, ARRAY_SIZE(common_clks));
121 return 0; 142 return 0;
122} 143}
123arch_initcall(clk_init); 144arch_initcall(clk_init);