blob: 83ef5ecaf432513eabe2c6e9f09c72dbedae9139 [file] [log] [blame]
Russell King97d654f2006-03-15 15:54:37 +00001/*
2 * linux/arch/arm/mach-sa1100/clock.c
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>
Russell Kinga6dba202007-08-20 10:18:02 +010012#include <linux/platform_device.h>
13#include <linux/delay.h>
Russell King97d654f2006-03-15 15:54:37 +000014
15#include <asm/arch/pxa-regs.h>
16#include <asm/hardware.h>
Russell King97d654f2006-03-15 15:54:37 +000017
Russell Kinga6dba202007-08-20 10:18:02 +010018#include "devices.h"
19#include "generic.h"
20#include "clock.h"
Russell King97d654f2006-03-15 15:54:37 +000021
22static LIST_HEAD(clocks);
Russell Kingf4b6a0a2007-05-15 16:49:02 +010023static DEFINE_MUTEX(clocks_mutex);
Russell King97d654f2006-03-15 15:54:37 +000024static 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
Russell Kingf4b6a0a2007-05-15 16:49:02 +010030 mutex_lock(&clocks_mutex);
Russell King97d654f2006-03-15 15:54:37 +000031 list_for_each_entry(p, &clocks, node) {
Russell Kinga6dba202007-08-20 10:18:02 +010032 if (strcmp(id, p->name) == 0 &&
33 (p->dev == NULL || p->dev == dev)) {
Russell King97d654f2006-03-15 15:54:37 +000034 clk = p;
35 break;
36 }
37 }
Russell Kingf4b6a0a2007-05-15 16:49:02 +010038 mutex_unlock(&clocks_mutex);
Russell King97d654f2006-03-15 15:54:37 +000039
40 return clk;
41}
42EXPORT_SYMBOL(clk_get);
43
44void clk_put(struct clk *clk)
45{
Russell King97d654f2006-03-15 15:54:37 +000046}
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)
Russell Kinga6dba202007-08-20 10:18:02 +010055 clk->ops->enable(clk);
Russell King97d654f2006-03-15 15:54:37 +000056 spin_unlock_irqrestore(&clocks_lock, flags);
Russell Kinga6dba202007-08-20 10:18:02 +010057
58 if (clk->delay)
59 udelay(clk->delay);
60
Russell King97d654f2006-03-15 15:54:37 +000061 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)
Russell Kinga6dba202007-08-20 10:18:02 +010073 clk->ops->disable(clk);
Russell King97d654f2006-03-15 15:54:37 +000074 spin_unlock_irqrestore(&clocks_lock, flags);
75}
76EXPORT_SYMBOL(clk_disable);
77
78unsigned long clk_get_rate(struct clk *clk)
79{
Russell Kinga6dba202007-08-20 10:18:02 +010080 unsigned long rate;
81
82 rate = clk->rate;
83 if (clk->ops->getrate)
84 rate = clk->ops->getrate(clk);
85
86 return rate;
Russell King97d654f2006-03-15 15:54:37 +000087}
88EXPORT_SYMBOL(clk_get_rate);
89
90
Russell Kinga6dba202007-08-20 10:18:02 +010091static void clk_gpio27_enable(struct clk *clk)
Russell King97d654f2006-03-15 15:54:37 +000092{
93 pxa_gpio_mode(GPIO11_3_6MHz_MD);
94}
95
Russell Kinga6dba202007-08-20 10:18:02 +010096static void clk_gpio27_disable(struct clk *clk)
Russell King97d654f2006-03-15 15:54:37 +000097{
98}
99
Russell Kinga6dba202007-08-20 10:18:02 +0100100static const struct clkops clk_gpio27_ops = {
Russell King97d654f2006-03-15 15:54:37 +0000101 .enable = clk_gpio27_enable,
102 .disable = clk_gpio27_disable,
103};
104
Russell King97d654f2006-03-15 15:54:37 +0000105
Russell Kinga6dba202007-08-20 10:18:02 +0100106void clk_cken_enable(struct clk *clk)
Russell King97d654f2006-03-15 15:54:37 +0000107{
Russell Kinga6dba202007-08-20 10:18:02 +0100108 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
Russell Kingf4b6a0a2007-05-15 16:49:02 +0100133 mutex_lock(&clocks_mutex);
Russell Kinga6dba202007-08-20 10:18:02 +0100134 for (i = 0; i < num; i++)
135 list_add(&clks[i].node, &clocks);
Russell Kingf4b6a0a2007-05-15 16:49:02 +0100136 mutex_unlock(&clocks_mutex);
Russell King97d654f2006-03-15 15:54:37 +0000137}
Russell King97d654f2006-03-15 15:54:37 +0000138
139static int __init clk_init(void)
140{
Russell Kinga6dba202007-08-20 10:18:02 +0100141 clks_register(common_clks, ARRAY_SIZE(common_clks));
Russell King97d654f2006-03-15 15:54:37 +0000142 return 0;
143}
144arch_initcall(clk_init);