]>
Commit | Line | Data |
---|---|---|
97d654f8 RK |
1 | /* |
2 | * linux/arch/arm/mach-sa1100/clock.c | |
3 | */ | |
4 | #include <linux/module.h> | |
5 | #include <linux/kernel.h> | |
5e1dbdb4 | 6 | #include <linux/device.h> |
97d654f8 RK |
7 | #include <linux/list.h> |
8 | #include <linux/errno.h> | |
9 | #include <linux/err.h> | |
10 | #include <linux/string.h> | |
11 | #include <linux/clk.h> | |
12 | #include <linux/spinlock.h> | |
d0a9d75b | 13 | #include <linux/mutex.h> |
4a8f8340 JZ |
14 | #include <linux/io.h> |
15 | #include <linux/clkdev.h> | |
97d654f8 | 16 | |
a09e64fb | 17 | #include <mach/hardware.h> |
97d654f8 | 18 | |
4a8f8340 JZ |
19 | struct clkops { |
20 | void (*enable)(struct clk *); | |
21 | void (*disable)(struct clk *); | |
22 | }; | |
23 | ||
97d654f8 | 24 | struct clk { |
4a8f8340 | 25 | const struct clkops *ops; |
97d654f8 | 26 | unsigned int enabled; |
97d654f8 RK |
27 | }; |
28 | ||
4a8f8340 JZ |
29 | #define DEFINE_CLK(_name, _ops) \ |
30 | struct clk clk_##_name = { \ | |
31 | .ops = _ops, \ | |
32 | } | |
33 | ||
34 | static DEFINE_SPINLOCK(clocks_lock); | |
35 | ||
36 | static void clk_gpio27_enable(struct clk *clk) | |
5e1dbdb4 RK |
37 | { |
38 | /* | |
39 | * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111: | |
40 | * (SA-1110 Developer's Manual, section 9.1.2.1) | |
41 | */ | |
42 | GAFR |= GPIO_32_768kHz; | |
43 | GPDR |= GPIO_32_768kHz; | |
44 | TUCR = TUCR_3_6864MHz; | |
45 | } | |
46 | ||
4a8f8340 | 47 | static void clk_gpio27_disable(struct clk *clk) |
5e1dbdb4 RK |
48 | { |
49 | TUCR = 0; | |
50 | GPDR &= ~GPIO_32_768kHz; | |
51 | GAFR &= ~GPIO_32_768kHz; | |
52 | } | |
53 | ||
97d654f8 RK |
54 | int clk_enable(struct clk *clk) |
55 | { | |
56 | unsigned long flags; | |
57 | ||
4a8f8340 JZ |
58 | if (clk) { |
59 | spin_lock_irqsave(&clocks_lock, flags); | |
60 | if (clk->enabled++ == 0) | |
61 | clk->ops->enable(clk); | |
62 | spin_unlock_irqrestore(&clocks_lock, flags); | |
63 | } | |
64 | ||
97d654f8 RK |
65 | return 0; |
66 | } | |
67 | EXPORT_SYMBOL(clk_enable); | |
68 | ||
69 | void clk_disable(struct clk *clk) | |
70 | { | |
71 | unsigned long flags; | |
72 | ||
4a8f8340 JZ |
73 | if (clk) { |
74 | WARN_ON(clk->enabled == 0); | |
75 | spin_lock_irqsave(&clocks_lock, flags); | |
76 | if (--clk->enabled == 0) | |
77 | clk->ops->disable(clk); | |
78 | spin_unlock_irqrestore(&clocks_lock, flags); | |
79 | } | |
97d654f8 RK |
80 | } |
81 | EXPORT_SYMBOL(clk_disable); | |
82 | ||
4a8f8340 JZ |
83 | const struct clkops clk_gpio27_ops = { |
84 | .enable = clk_gpio27_enable, | |
85 | .disable = clk_gpio27_disable, | |
86 | }; | |
87 | ||
88 | static DEFINE_CLK(gpio27, &clk_gpio27_ops); | |
89 | ||
90 | static struct clk_lookup sa11xx_clkregs[] = { | |
91 | CLKDEV_INIT("sa1111.0", NULL, &clk_gpio27), | |
92 | CLKDEV_INIT("sa1100-rtc", NULL, NULL), | |
93 | }; | |
94 | ||
95 | static int __init sa11xx_clk_init(void) | |
97d654f8 | 96 | { |
4a8f8340 JZ |
97 | clkdev_add_table(sa11xx_clkregs, ARRAY_SIZE(sa11xx_clkregs)); |
98 | return 0; | |
97d654f8 | 99 | } |
4a8f8340 | 100 | core_initcall(sa11xx_clk_init); |