1
2
3
4#include <linux/module.h>
5#include <linux/kernel.h>
6#include <linux/list.h>
7#include <linux/errno.h>
8#include <linux/err.h>
9#include <linux/string.h>
10#include <linux/clk.h>
11#include <linux/spinlock.h>
12#include <linux/platform_device.h>
13#include <linux/delay.h>
14
15#include <asm/arch/pxa-regs.h>
16#include <asm/hardware.h>
17
18#include "devices.h"
19#include "generic.h"
20#include "clock.h"
21
22static LIST_HEAD(clocks);
23static DEFINE_MUTEX(clocks_mutex);
24static DEFINE_SPINLOCK(clocks_lock);
25
26struct clk *clk_get(struct device *dev, const char *id)
27{
28 struct clk *p, *clk = ERR_PTR(-ENOENT);
29
30 mutex_lock(&clocks_mutex);
31 list_for_each_entry(p, &clocks, node) {
32 if (strcmp(id, p->name) == 0 &&
33 (p->dev == NULL || p->dev == dev)) {
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}
47EXPORT_SYMBOL(clk_put);
48
49int clk_enable(struct clk *clk)
50{
51 unsigned long flags;
52
53 spin_lock_irqsave(&clocks_lock, flags);
54 if (clk->enabled++ == 0)
55 clk->ops->enable(clk);
56 spin_unlock_irqrestore(&clocks_lock, flags);
57
58 if (clk->delay)
59 udelay(clk->delay);
60
61 return 0;
62}
63EXPORT_SYMBOL(clk_enable);
64
65void clk_disable(struct clk *clk)
66{
67 unsigned long flags;
68
69 WARN_ON(clk->enabled == 0);
70
71 spin_lock_irqsave(&clocks_lock, flags);
72 if (--clk->enabled == 0)
73 clk->ops->disable(clk);
74 spin_unlock_irqrestore(&clocks_lock, flags);
75}
76EXPORT_SYMBOL(clk_disable);
77
78unsigned long clk_get_rate(struct clk *clk)
79{
80 unsigned long rate;
81
82 rate = clk->rate;
83 if (clk->ops->getrate)
84 rate = clk->ops->getrate(clk);
85
86 return rate;
87}
88EXPORT_SYMBOL(clk_get_rate);
89
90
91static void clk_gpio27_enable(struct clk *clk)
92{
93 pxa_gpio_mode(GPIO11_3_6MHz_MD);
94}
95
96static void clk_gpio27_disable(struct clk *clk)
97{
98}
99
100static const struct clkops clk_gpio27_ops = {
101 .enable = clk_gpio27_enable,
102 .disable = clk_gpio27_disable,
103};
104
105
106void clk_cken_enable(struct clk *clk)
107{
108 CKEN |= 1 << clk->cken;
109}
110
111void clk_cken_disable(struct clk *clk)
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
133 mutex_lock(&clocks_mutex);
134 for (i = 0; i < num; i++)
135 list_add(&clks[i].node, &clocks);
136 mutex_unlock(&clocks_mutex);
137}
138
139static int __init clk_init(void)
140{
141 clks_register(common_clks, ARRAY_SIZE(common_clks));
142 return 0;
143}
144arch_initcall(clk_init);
145