blob: df5ae2710ab1744197e1fc8d77bccce41f575622 [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
Russell Kinga0dd0052008-02-17 10:35:15 +000026static struct clk *clk_lookup(struct device *dev, const char *id)
27{
28 struct clk *p;
29
30 list_for_each_entry(p, &clocks, node)
31 if (strcmp(id, p->name) == 0 && p->dev == dev)
32 return p;
33
34 return NULL;
35}
36
Russell King97d654f2006-03-15 15:54:37 +000037struct clk *clk_get(struct device *dev, const char *id)
38{
39 struct clk *p, *clk = ERR_PTR(-ENOENT);
40
Russell Kingf4b6a0a2007-05-15 16:49:02 +010041 mutex_lock(&clocks_mutex);
Russell Kinga0dd0052008-02-17 10:35:15 +000042 p = clk_lookup(dev, id);
43 if (!p)
44 p = clk_lookup(NULL, id);
45 if (p)
46 clk = p;
Russell Kingf4b6a0a2007-05-15 16:49:02 +010047 mutex_unlock(&clocks_mutex);
Russell King97d654f2006-03-15 15:54:37 +000048
49 return clk;
50}
51EXPORT_SYMBOL(clk_get);
52
53void clk_put(struct clk *clk)
54{
Russell King97d654f2006-03-15 15:54:37 +000055}
56EXPORT_SYMBOL(clk_put);
57
58int clk_enable(struct clk *clk)
59{
60 unsigned long flags;
61
62 spin_lock_irqsave(&clocks_lock, flags);
63 if (clk->enabled++ == 0)
Russell Kinga6dba202007-08-20 10:18:02 +010064 clk->ops->enable(clk);
Russell King97d654f2006-03-15 15:54:37 +000065 spin_unlock_irqrestore(&clocks_lock, flags);
Russell Kinga6dba202007-08-20 10:18:02 +010066
67 if (clk->delay)
68 udelay(clk->delay);
69
Russell King97d654f2006-03-15 15:54:37 +000070 return 0;
71}
72EXPORT_SYMBOL(clk_enable);
73
74void clk_disable(struct clk *clk)
75{
76 unsigned long flags;
77
78 WARN_ON(clk->enabled == 0);
79
80 spin_lock_irqsave(&clocks_lock, flags);
81 if (--clk->enabled == 0)
Russell Kinga6dba202007-08-20 10:18:02 +010082 clk->ops->disable(clk);
Russell King97d654f2006-03-15 15:54:37 +000083 spin_unlock_irqrestore(&clocks_lock, flags);
84}
85EXPORT_SYMBOL(clk_disable);
86
87unsigned long clk_get_rate(struct clk *clk)
88{
Russell Kinga6dba202007-08-20 10:18:02 +010089 unsigned long rate;
90
91 rate = clk->rate;
92 if (clk->ops->getrate)
93 rate = clk->ops->getrate(clk);
94
95 return rate;
Russell King97d654f2006-03-15 15:54:37 +000096}
97EXPORT_SYMBOL(clk_get_rate);
98
99
Russell Kinga6dba202007-08-20 10:18:02 +0100100static void clk_gpio27_enable(struct clk *clk)
Russell King97d654f2006-03-15 15:54:37 +0000101{
102 pxa_gpio_mode(GPIO11_3_6MHz_MD);
103}
104
Russell Kinga6dba202007-08-20 10:18:02 +0100105static void clk_gpio27_disable(struct clk *clk)
Russell King97d654f2006-03-15 15:54:37 +0000106{
107}
108
Russell Kinga6dba202007-08-20 10:18:02 +0100109static const struct clkops clk_gpio27_ops = {
Russell King97d654f2006-03-15 15:54:37 +0000110 .enable = clk_gpio27_enable,
111 .disable = clk_gpio27_disable,
112};
113
Russell King97d654f2006-03-15 15:54:37 +0000114
Russell Kinga6dba202007-08-20 10:18:02 +0100115void clk_cken_enable(struct clk *clk)
Russell King97d654f2006-03-15 15:54:37 +0000116{
Russell Kinga6dba202007-08-20 10:18:02 +0100117 CKEN |= 1 << clk->cken;
118}
119
120void clk_cken_disable(struct clk *clk)
121{
122 CKEN &= ~(1 << clk->cken);
123}
124
125const struct clkops clk_cken_ops = {
126 .enable = clk_cken_enable,
127 .disable = clk_cken_disable,
128};
129
130static struct clk common_clks[] = {
131 {
132 .name = "GPIO27_CLK",
133 .ops = &clk_gpio27_ops,
134 .rate = 3686400,
135 },
136};
137
138void clks_register(struct clk *clks, size_t num)
139{
140 int i;
141
Russell Kingf4b6a0a2007-05-15 16:49:02 +0100142 mutex_lock(&clocks_mutex);
Russell Kinga6dba202007-08-20 10:18:02 +0100143 for (i = 0; i < num; i++)
144 list_add(&clks[i].node, &clocks);
Russell Kingf4b6a0a2007-05-15 16:49:02 +0100145 mutex_unlock(&clocks_mutex);
Russell King97d654f2006-03-15 15:54:37 +0000146}
Russell King97d654f2006-03-15 15:54:37 +0000147
148static int __init clk_init(void)
149{
Russell Kinga6dba202007-08-20 10:18:02 +0100150 clks_register(common_clks, ARRAY_SIZE(common_clks));
Russell King97d654f2006-03-15 15:54:37 +0000151 return 0;
152}
153arch_initcall(clk_init);