diff options
author | Rabin Vincent <rabin.vincent@stericsson.com> | 2010-02-28 23:07:47 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-03-19 14:29:45 -0400 |
commit | 1df20afce51e7af2a587425d1aafca2608fe0066 (patch) | |
tree | 07bde105706ff8396e58f400ef87cb4bac0456cc /arch/arm/mach-ux500 | |
parent | 75a36ee01e860be693220f1c40e2c04fb6cc69ba (diff) |
ARM: 5964/1: ux500: support clock gating
Implement clock gating support for the u8500 clocks.
Acked-by: Linus Walleij <linus.walleij@stericsson.com>
Acked-by: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-ux500')
-rw-r--r-- | arch/arm/mach-ux500/board-mop500.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-ux500/clock.c | 491 | ||||
-rw-r--r-- | arch/arm/mach-ux500/clock.h | 125 | ||||
-rw-r--r-- | arch/arm/mach-ux500/cpu-u8500.c | 7 |
4 files changed, 590 insertions, 35 deletions
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index c2b4a35cf01b..4335186135e4 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c | |||
@@ -94,7 +94,7 @@ static struct pl022_ssp_controller ssp0_platform_data = { | |||
94 | static struct amba_device pl022_device = { | 94 | static struct amba_device pl022_device = { |
95 | .dev = { | 95 | .dev = { |
96 | .coherent_dma_mask = ~0, | 96 | .coherent_dma_mask = ~0, |
97 | .init_name = "pl022", | 97 | .init_name = "ssp0", |
98 | .platform_data = &ssp0_platform_data, | 98 | .platform_data = &ssp0_platform_data, |
99 | }, | 99 | }, |
100 | .res = { | 100 | .res = { |
diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index 8359a73d0041..d16b8b5ca8c7 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2009 ST-Ericsson | 2 | * Copyright (C) 2009 ST-Ericsson |
3 | * heavily based on realview platform | 3 | * Copyright (C) 2009 STMicroelectronics |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
@@ -12,33 +12,130 @@ | |||
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
14 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
15 | #include <linux/mutex.h> | 15 | #include <linux/io.h> |
16 | 16 | ||
17 | #include <asm/clkdev.h> | 17 | #include <asm/clkdev.h> |
18 | 18 | ||
19 | /* currently the clk structure | 19 | #include <mach/hardware.h> |
20 | * just supports rate. This would | 20 | #include "clock.h" |
21 | * be extended as and when new devices are | 21 | |
22 | * added - TODO | 22 | #define PRCC_PCKEN 0x00 |
23 | */ | 23 | #define PRCC_PCKDIS 0x04 |
24 | struct clk { | 24 | #define PRCC_KCKEN 0x08 |
25 | unsigned long rate; | 25 | #define PRCC_KCKDIS 0x0C |
26 | }; | 26 | |
27 | #define PRCM_YYCLKEN0_MGT_SET 0x510 | ||
28 | #define PRCM_YYCLKEN1_MGT_SET 0x514 | ||
29 | #define PRCM_YYCLKEN0_MGT_CLR 0x518 | ||
30 | #define PRCM_YYCLKEN1_MGT_CLR 0x51C | ||
31 | #define PRCM_YYCLKEN0_MGT_VAL 0x520 | ||
32 | #define PRCM_YYCLKEN1_MGT_VAL 0x524 | ||
33 | |||
34 | #define PRCM_SVAMMDSPCLK_MGT 0x008 | ||
35 | #define PRCM_SIAMMDSPCLK_MGT 0x00C | ||
36 | #define PRCM_SGACLK_MGT 0x014 | ||
37 | #define PRCM_UARTCLK_MGT 0x018 | ||
38 | #define PRCM_MSP02CLK_MGT 0x01C | ||
39 | #define PRCM_MSP1CLK_MGT 0x288 | ||
40 | #define PRCM_I2CCLK_MGT 0x020 | ||
41 | #define PRCM_SDMMCCLK_MGT 0x024 | ||
42 | #define PRCM_SLIMCLK_MGT 0x028 | ||
43 | #define PRCM_PER1CLK_MGT 0x02C | ||
44 | #define PRCM_PER2CLK_MGT 0x030 | ||
45 | #define PRCM_PER3CLK_MGT 0x034 | ||
46 | #define PRCM_PER5CLK_MGT 0x038 | ||
47 | #define PRCM_PER6CLK_MGT 0x03C | ||
48 | #define PRCM_PER7CLK_MGT 0x040 | ||
49 | #define PRCM_LCDCLK_MGT 0x044 | ||
50 | #define PRCM_BMLCLK_MGT 0x04C | ||
51 | #define PRCM_HSITXCLK_MGT 0x050 | ||
52 | #define PRCM_HSIRXCLK_MGT 0x054 | ||
53 | #define PRCM_HDMICLK_MGT 0x058 | ||
54 | #define PRCM_APEATCLK_MGT 0x05C | ||
55 | #define PRCM_APETRACECLK_MGT 0x060 | ||
56 | #define PRCM_MCDECLK_MGT 0x064 | ||
57 | #define PRCM_IPI2CCLK_MGT 0x068 | ||
58 | #define PRCM_DSIALTCLK_MGT 0x06C | ||
59 | #define PRCM_DMACLK_MGT 0x074 | ||
60 | #define PRCM_B2R2CLK_MGT 0x078 | ||
61 | #define PRCM_TVCLK_MGT 0x07C | ||
62 | #define PRCM_UNIPROCLK_MGT 0x278 | ||
63 | #define PRCM_SSPCLK_MGT 0x280 | ||
64 | #define PRCM_RNGCLK_MGT 0x284 | ||
65 | #define PRCM_UICCCLK_MGT 0x27C | ||
66 | |||
67 | #define PRCM_MGT_ENABLE (1 << 8) | ||
68 | |||
69 | static DEFINE_SPINLOCK(clocks_lock); | ||
70 | |||
71 | static void __clk_enable(struct clk *clk) | ||
72 | { | ||
73 | if (clk->enabled++ == 0) { | ||
74 | if (clk->parent_cluster) | ||
75 | __clk_enable(clk->parent_cluster); | ||
76 | |||
77 | if (clk->parent_periph) | ||
78 | __clk_enable(clk->parent_periph); | ||
79 | |||
80 | if (clk->ops && clk->ops->enable) | ||
81 | clk->ops->enable(clk); | ||
82 | } | ||
83 | } | ||
27 | 84 | ||
28 | int clk_enable(struct clk *clk) | 85 | int clk_enable(struct clk *clk) |
29 | { | 86 | { |
87 | unsigned long flags; | ||
88 | |||
89 | spin_lock_irqsave(&clocks_lock, flags); | ||
90 | __clk_enable(clk); | ||
91 | spin_unlock_irqrestore(&clocks_lock, flags); | ||
92 | |||
30 | return 0; | 93 | return 0; |
31 | } | 94 | } |
32 | EXPORT_SYMBOL(clk_enable); | 95 | EXPORT_SYMBOL(clk_enable); |
33 | 96 | ||
97 | static void __clk_disable(struct clk *clk) | ||
98 | { | ||
99 | if (--clk->enabled == 0) { | ||
100 | if (clk->ops && clk->ops->disable) | ||
101 | clk->ops->disable(clk); | ||
102 | |||
103 | if (clk->parent_periph) | ||
104 | __clk_disable(clk->parent_periph); | ||
105 | |||
106 | if (clk->parent_cluster) | ||
107 | __clk_disable(clk->parent_cluster); | ||
108 | } | ||
109 | } | ||
110 | |||
34 | void clk_disable(struct clk *clk) | 111 | void clk_disable(struct clk *clk) |
35 | { | 112 | { |
113 | unsigned long flags; | ||
114 | |||
115 | WARN_ON(!clk->enabled); | ||
116 | |||
117 | spin_lock_irqsave(&clocks_lock, flags); | ||
118 | __clk_disable(clk); | ||
119 | spin_unlock_irqrestore(&clocks_lock, flags); | ||
36 | } | 120 | } |
37 | EXPORT_SYMBOL(clk_disable); | 121 | EXPORT_SYMBOL(clk_disable); |
38 | 122 | ||
39 | unsigned long clk_get_rate(struct clk *clk) | 123 | unsigned long clk_get_rate(struct clk *clk) |
40 | { | 124 | { |
41 | return clk->rate; | 125 | unsigned long rate; |
126 | |||
127 | if (clk->ops && clk->ops->get_rate) | ||
128 | return clk->ops->get_rate(clk); | ||
129 | |||
130 | rate = clk->rate; | ||
131 | if (!rate) { | ||
132 | if (clk->parent_periph) | ||
133 | rate = clk_get_rate(clk->parent_periph); | ||
134 | else if (clk->parent_cluster) | ||
135 | rate = clk_get_rate(clk->parent_cluster); | ||
136 | } | ||
137 | |||
138 | return rate; | ||
42 | } | 139 | } |
43 | EXPORT_SYMBOL(clk_get_rate); | 140 | EXPORT_SYMBOL(clk_get_rate); |
44 | 141 | ||
@@ -56,37 +153,363 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
56 | } | 153 | } |
57 | EXPORT_SYMBOL(clk_set_rate); | 154 | EXPORT_SYMBOL(clk_set_rate); |
58 | 155 | ||
59 | /* ssp clock */ | 156 | static void clk_prcmu_enable(struct clk *clk) |
60 | static struct clk ssp_clk = { | 157 | { |
61 | .rate = 48000000, | 158 | void __iomem *cg_set_reg = __io_address(U8500_PRCMU_BASE) |
159 | + PRCM_YYCLKEN0_MGT_SET + clk->prcmu_cg_off; | ||
160 | |||
161 | writel(1 << clk->prcmu_cg_bit, cg_set_reg); | ||
162 | } | ||
163 | |||
164 | static void clk_prcmu_disable(struct clk *clk) | ||
165 | { | ||
166 | void __iomem *cg_clr_reg = __io_address(U8500_PRCMU_BASE) | ||
167 | + PRCM_YYCLKEN0_MGT_CLR + clk->prcmu_cg_off; | ||
168 | |||
169 | writel(1 << clk->prcmu_cg_bit, cg_clr_reg); | ||
170 | } | ||
171 | |||
172 | /* ED doesn't have the combined set/clr registers */ | ||
173 | static void clk_prcmu_ed_enable(struct clk *clk) | ||
174 | { | ||
175 | void __iomem *addr = __io_address(U8500_PRCMU_BASE) | ||
176 | + clk->prcmu_cg_mgt; | ||
177 | |||
178 | writel(readl(addr) | PRCM_MGT_ENABLE, addr); | ||
179 | } | ||
180 | |||
181 | static void clk_prcmu_ed_disable(struct clk *clk) | ||
182 | { | ||
183 | void __iomem *addr = __io_address(U8500_PRCMU_BASE) | ||
184 | + clk->prcmu_cg_mgt; | ||
185 | |||
186 | writel(readl(addr) & ~PRCM_MGT_ENABLE, addr); | ||
187 | } | ||
188 | |||
189 | static struct clkops clk_prcmu_ops = { | ||
190 | .enable = clk_prcmu_enable, | ||
191 | .disable = clk_prcmu_disable, | ||
62 | }; | 192 | }; |
63 | 193 | ||
64 | /* fixed clock */ | 194 | static unsigned int clkrst_base[] = { |
65 | static struct clk f38_clk = { | 195 | [1] = U8500_CLKRST1_BASE, |
66 | .rate = 38400000, | 196 | [2] = U8500_CLKRST2_BASE, |
197 | [3] = U8500_CLKRST3_BASE, | ||
198 | [5] = U8500_CLKRST5_BASE, | ||
199 | [6] = U8500_CLKRST6_BASE, | ||
200 | [7] = U8500_CLKRST7_BASE_ED, | ||
67 | }; | 201 | }; |
68 | 202 | ||
69 | static struct clk_lookup lookups[] = { | 203 | static void clk_prcc_enable(struct clk *clk) |
70 | { | 204 | { |
71 | /* UART0 */ | 205 | void __iomem *addr = __io_address(clkrst_base[clk->cluster]); |
72 | .dev_id = "uart0", | 206 | |
73 | .clk = &f38_clk, | 207 | if (clk->prcc_kernel != -1) |
74 | }, { /* UART1 */ | 208 | writel(1 << clk->prcc_kernel, addr + PRCC_KCKEN); |
75 | .dev_id = "uart1", | 209 | |
76 | .clk = &f38_clk, | 210 | if (clk->prcc_bus != -1) |
77 | }, { /* UART2 */ | 211 | writel(1 << clk->prcc_bus, addr + PRCC_PCKEN); |
78 | .dev_id = "uart2", | 212 | } |
79 | .clk = &f38_clk, | 213 | |
80 | }, { /* SSP */ | 214 | static void clk_prcc_disable(struct clk *clk) |
81 | .dev_id = "pl022", | 215 | { |
82 | .clk = &ssp_clk, | 216 | void __iomem *addr = __io_address(clkrst_base[clk->cluster]); |
83 | } | 217 | |
218 | if (clk->prcc_bus != -1) | ||
219 | writel(1 << clk->prcc_bus, addr + PRCC_PCKDIS); | ||
220 | |||
221 | if (clk->prcc_kernel != -1) | ||
222 | writel(1 << clk->prcc_kernel, addr + PRCC_KCKDIS); | ||
223 | } | ||
224 | |||
225 | static struct clkops clk_prcc_ops = { | ||
226 | .enable = clk_prcc_enable, | ||
227 | .disable = clk_prcc_disable, | ||
228 | }; | ||
229 | |||
230 | static struct clk clk_32khz = { | ||
231 | .rate = 32000, | ||
232 | }; | ||
233 | |||
234 | /* | ||
235 | * PRCMU level clock gating | ||
236 | */ | ||
237 | |||
238 | /* Bank 0 */ | ||
239 | static DEFINE_PRCMU_CLK(svaclk, 0x0, 2, SVAMMDSPCLK); | ||
240 | static DEFINE_PRCMU_CLK(siaclk, 0x0, 3, SIAMMDSPCLK); | ||
241 | static DEFINE_PRCMU_CLK(sgaclk, 0x0, 4, SGACLK); | ||
242 | static DEFINE_PRCMU_CLK_RATE(uartclk, 0x0, 5, UARTCLK, 38400000); | ||
243 | static DEFINE_PRCMU_CLK(msp02clk, 0x0, 6, MSP02CLK); | ||
244 | static DEFINE_PRCMU_CLK(msp1clk, 0x0, 7, MSP1CLK); /* v1 */ | ||
245 | static DEFINE_PRCMU_CLK_RATE(i2cclk, 0x0, 8, I2CCLK, 48000000); | ||
246 | static DEFINE_PRCMU_CLK_RATE(sdmmcclk, 0x0, 9, SDMMCCLK, 50000000); | ||
247 | static DEFINE_PRCMU_CLK(slimclk, 0x0, 10, SLIMCLK); | ||
248 | static DEFINE_PRCMU_CLK(per1clk, 0x0, 11, PER1CLK); | ||
249 | static DEFINE_PRCMU_CLK(per2clk, 0x0, 12, PER2CLK); | ||
250 | static DEFINE_PRCMU_CLK(per3clk, 0x0, 13, PER3CLK); | ||
251 | static DEFINE_PRCMU_CLK(per5clk, 0x0, 14, PER5CLK); | ||
252 | static DEFINE_PRCMU_CLK_RATE(per6clk, 0x0, 15, PER6CLK, 133330000); | ||
253 | static DEFINE_PRCMU_CLK_RATE(per7clk, 0x0, 16, PER7CLK, 100000000); | ||
254 | static DEFINE_PRCMU_CLK(lcdclk, 0x0, 17, LCDCLK); | ||
255 | static DEFINE_PRCMU_CLK(bmlclk, 0x0, 18, BMLCLK); | ||
256 | static DEFINE_PRCMU_CLK(hsitxclk, 0x0, 19, HSITXCLK); | ||
257 | static DEFINE_PRCMU_CLK(hsirxclk, 0x0, 20, HSIRXCLK); | ||
258 | static DEFINE_PRCMU_CLK(hdmiclk, 0x0, 21, HDMICLK); | ||
259 | static DEFINE_PRCMU_CLK(apeatclk, 0x0, 22, APEATCLK); | ||
260 | static DEFINE_PRCMU_CLK(apetraceclk, 0x0, 23, APETRACECLK); | ||
261 | static DEFINE_PRCMU_CLK(mcdeclk, 0x0, 24, MCDECLK); | ||
262 | static DEFINE_PRCMU_CLK(ipi2clk, 0x0, 25, IPI2CCLK); | ||
263 | static DEFINE_PRCMU_CLK(dsialtclk, 0x0, 26, DSIALTCLK); /* v1 */ | ||
264 | static DEFINE_PRCMU_CLK(dmaclk, 0x0, 27, DMACLK); | ||
265 | static DEFINE_PRCMU_CLK(b2r2clk, 0x0, 28, B2R2CLK); | ||
266 | static DEFINE_PRCMU_CLK(tvclk, 0x0, 29, TVCLK); | ||
267 | static DEFINE_PRCMU_CLK(uniproclk, 0x0, 30, UNIPROCLK); /* v1 */ | ||
268 | static DEFINE_PRCMU_CLK_RATE(sspclk, 0x0, 31, SSPCLK, 48000000); /* v1 */ | ||
269 | |||
270 | /* Bank 1 */ | ||
271 | static DEFINE_PRCMU_CLK(rngclk, 0x4, 0, RNGCLK); /* v1 */ | ||
272 | static DEFINE_PRCMU_CLK(uiccclk, 0x4, 1, UICCCLK); /* v1 */ | ||
273 | |||
274 | /* | ||
275 | * PRCC level clock gating | ||
276 | * Format: per#, clk, PCKEN bit, KCKEN bit, parent | ||
277 | */ | ||
278 | |||
279 | /* Peripheral Cluster #1 */ | ||
280 | static DEFINE_PRCC_CLK(1, i2c4, 10, 9, &clk_i2cclk); | ||
281 | static DEFINE_PRCC_CLK(1, gpio0, 9, -1, NULL); | ||
282 | static DEFINE_PRCC_CLK(1, slimbus0, 8, 8, &clk_slimclk); | ||
283 | static DEFINE_PRCC_CLK(1, spi3_ed, 7, 7, NULL); | ||
284 | static DEFINE_PRCC_CLK(1, spi3_v1, 7, -1, NULL); | ||
285 | static DEFINE_PRCC_CLK(1, i2c2, 6, 6, &clk_i2cclk); | ||
286 | static DEFINE_PRCC_CLK(1, sdi0, 5, 5, &clk_sdmmcclk); | ||
287 | static DEFINE_PRCC_CLK(1, msp1_ed, 4, 4, &clk_msp02clk); | ||
288 | static DEFINE_PRCC_CLK(1, msp1_v1, 4, 4, &clk_msp1clk); | ||
289 | static DEFINE_PRCC_CLK(1, msp0, 3, 3, &clk_msp02clk); | ||
290 | static DEFINE_PRCC_CLK(1, i2c1, 2, 2, &clk_i2cclk); | ||
291 | static DEFINE_PRCC_CLK(1, uart1, 1, 1, &clk_uartclk); | ||
292 | static DEFINE_PRCC_CLK(1, uart0, 0, 0, &clk_uartclk); | ||
293 | |||
294 | /* Peripheral Cluster #2 */ | ||
295 | |||
296 | static DEFINE_PRCC_CLK(2, gpio1_ed, 12, -1, NULL); | ||
297 | static DEFINE_PRCC_CLK(2, ssitx_ed, 11, -1, NULL); | ||
298 | static DEFINE_PRCC_CLK(2, ssirx_ed, 10, -1, NULL); | ||
299 | static DEFINE_PRCC_CLK(2, spi0_ed, 9, -1, NULL); | ||
300 | static DEFINE_PRCC_CLK(2, sdi3_ed, 8, 6, &clk_sdmmcclk); | ||
301 | static DEFINE_PRCC_CLK(2, sdi1_ed, 7, 5, &clk_sdmmcclk); | ||
302 | static DEFINE_PRCC_CLK(2, msp2_ed, 6, 4, &clk_msp02clk); | ||
303 | static DEFINE_PRCC_CLK(2, sdi4_ed, 4, 2, &clk_sdmmcclk); | ||
304 | static DEFINE_PRCC_CLK(2, pwl_ed, 3, 1, NULL); | ||
305 | static DEFINE_PRCC_CLK(2, spi1_ed, 2, -1, NULL); | ||
306 | static DEFINE_PRCC_CLK(2, spi2_ed, 1, -1, NULL); | ||
307 | static DEFINE_PRCC_CLK(2, i2c3_ed, 0, 0, &clk_i2cclk); | ||
308 | |||
309 | static DEFINE_PRCC_CLK(2, gpio1_v1, 11, -1, NULL); | ||
310 | static DEFINE_PRCC_CLK(2, ssitx_v1, 10, 7, NULL); | ||
311 | static DEFINE_PRCC_CLK(2, ssirx_v1, 9, 6, NULL); | ||
312 | static DEFINE_PRCC_CLK(2, spi0_v1, 8, -1, NULL); | ||
313 | static DEFINE_PRCC_CLK(2, sdi3_v1, 7, 5, &clk_sdmmcclk); | ||
314 | static DEFINE_PRCC_CLK(2, sdi1_v1, 6, 4, &clk_sdmmcclk); | ||
315 | static DEFINE_PRCC_CLK(2, msp2_v1, 5, 3, &clk_msp02clk); | ||
316 | static DEFINE_PRCC_CLK(2, sdi4_v1, 4, 2, &clk_sdmmcclk); | ||
317 | static DEFINE_PRCC_CLK(2, pwl_v1, 3, 1, NULL); | ||
318 | static DEFINE_PRCC_CLK(2, spi1_v1, 2, -1, NULL); | ||
319 | static DEFINE_PRCC_CLK(2, spi2_v1, 1, -1, NULL); | ||
320 | static DEFINE_PRCC_CLK(2, i2c3_v1, 0, 0, &clk_i2cclk); | ||
321 | |||
322 | /* Peripheral Cluster #3 */ | ||
323 | static DEFINE_PRCC_CLK(3, gpio2, 8, -1, NULL); | ||
324 | static DEFINE_PRCC_CLK(3, sdi5, 7, 7, &clk_sdmmcclk); | ||
325 | static DEFINE_PRCC_CLK(3, uart2, 6, 6, &clk_uartclk); | ||
326 | static DEFINE_PRCC_CLK(3, ske, 5, 5, &clk_32khz); | ||
327 | static DEFINE_PRCC_CLK(3, sdi2, 4, 4, &clk_sdmmcclk); | ||
328 | static DEFINE_PRCC_CLK(3, i2c0, 3, 3, &clk_i2cclk); | ||
329 | static DEFINE_PRCC_CLK(3, ssp1_ed, 2, 2, &clk_i2cclk); | ||
330 | static DEFINE_PRCC_CLK(3, ssp0_ed, 1, 1, &clk_i2cclk); | ||
331 | static DEFINE_PRCC_CLK(3, ssp1_v1, 2, 2, &clk_sspclk); | ||
332 | static DEFINE_PRCC_CLK(3, ssp0_v1, 1, 1, &clk_sspclk); | ||
333 | static DEFINE_PRCC_CLK(3, fsmc, 0, -1, NULL); | ||
334 | |||
335 | /* Peripheral Cluster #4 is in the always on domain */ | ||
336 | |||
337 | /* Peripheral Cluster #5 */ | ||
338 | static DEFINE_PRCC_CLK(5, gpio3, 1, -1, NULL); | ||
339 | static DEFINE_PRCC_CLK(5, usb_ed, 0, 0, &clk_i2cclk); | ||
340 | static DEFINE_PRCC_CLK(5, usb_v1, 0, 0, NULL); | ||
341 | |||
342 | /* Peripheral Cluster #6 */ | ||
343 | |||
344 | static DEFINE_PRCC_CLK(6, mtu1_v1, 8, -1, NULL); | ||
345 | static DEFINE_PRCC_CLK(6, mtu0_v1, 7, -1, NULL); | ||
346 | static DEFINE_PRCC_CLK(6, cfgreg_v1, 6, 6, NULL); | ||
347 | static DEFINE_PRCC_CLK(6, dmc_ed, 6, 6, NULL); | ||
348 | static DEFINE_PRCC_CLK(6, hash1, 5, -1, NULL); | ||
349 | static DEFINE_PRCC_CLK(6, unipro_v1, 4, 1, &clk_uniproclk); | ||
350 | static DEFINE_PRCC_CLK(6, cryp1_ed, 4, -1, NULL); | ||
351 | static DEFINE_PRCC_CLK(6, pka, 3, -1, NULL); | ||
352 | static DEFINE_PRCC_CLK(6, hash0, 2, -1, NULL); | ||
353 | static DEFINE_PRCC_CLK(6, cryp0, 1, -1, NULL); | ||
354 | static DEFINE_PRCC_CLK(6, rng_ed, 0, 0, &clk_i2cclk); | ||
355 | static DEFINE_PRCC_CLK(6, rng_v1, 0, 0, &clk_rngclk); | ||
356 | |||
357 | /* Peripheral Cluster #7 */ | ||
358 | |||
359 | static DEFINE_PRCC_CLK(7, tzpc0_ed, 4, -1, NULL); | ||
360 | static DEFINE_PRCC_CLK(7, mtu1_ed, 3, -1, NULL); | ||
361 | static DEFINE_PRCC_CLK(7, mtu0_ed, 2, -1, NULL); | ||
362 | static DEFINE_PRCC_CLK(7, wdg_ed, 1, -1, NULL); | ||
363 | static DEFINE_PRCC_CLK(7, cfgreg_ed, 0, -1, NULL); | ||
364 | |||
365 | static struct clk_lookup u8500_common_clks[] = { | ||
366 | /* Peripheral Cluster #1 */ | ||
367 | CLK(gpio0, "gpioblock0", NULL), | ||
368 | CLK(slimbus0, "slimbus0", NULL), | ||
369 | CLK(i2c2, "nmk-i2c.2", NULL), | ||
370 | CLK(sdi0, "sdi0", NULL), | ||
371 | CLK(msp0, "msp0", NULL), | ||
372 | CLK(i2c1, "nmk-i2c.1", NULL), | ||
373 | CLK(uart1, "uart1", NULL), | ||
374 | CLK(uart0, "uart0", NULL), | ||
375 | |||
376 | /* Peripheral Cluster #3 */ | ||
377 | CLK(gpio2, "gpioblock2", NULL), | ||
378 | CLK(sdi5, "sdi5", NULL), | ||
379 | CLK(uart2, "uart2", NULL), | ||
380 | CLK(ske, "ske", NULL), | ||
381 | CLK(sdi2, "sdi2", NULL), | ||
382 | CLK(i2c0, "nmk-i2c.0", NULL), | ||
383 | CLK(fsmc, "fsmc", NULL), | ||
384 | |||
385 | /* Peripheral Cluster #5 */ | ||
386 | CLK(gpio3, "gpioblock3", NULL), | ||
387 | |||
388 | /* Peripheral Cluster #6 */ | ||
389 | CLK(hash1, "hash1", NULL), | ||
390 | CLK(pka, "pka", NULL), | ||
391 | CLK(hash0, "hash0", NULL), | ||
392 | CLK(cryp0, "cryp0", NULL), | ||
393 | |||
394 | /* PRCMU level clock gating */ | ||
395 | |||
396 | /* Bank 0 */ | ||
397 | CLK(svaclk, "sva", NULL), | ||
398 | CLK(siaclk, "sia", NULL), | ||
399 | CLK(sgaclk, "sga", NULL), | ||
400 | CLK(slimclk, "slim", NULL), | ||
401 | CLK(lcdclk, "lcd", NULL), | ||
402 | CLK(bmlclk, "bml", NULL), | ||
403 | CLK(hsitxclk, "stm-hsi.0", NULL), | ||
404 | CLK(hsirxclk, "stm-hsi.1", NULL), | ||
405 | CLK(hdmiclk, "hdmi", NULL), | ||
406 | CLK(apeatclk, "apeat", NULL), | ||
407 | CLK(apetraceclk, "apetrace", NULL), | ||
408 | CLK(mcdeclk, "mcde", NULL), | ||
409 | CLK(ipi2clk, "ipi2", NULL), | ||
410 | CLK(dmaclk, "dma40", NULL), | ||
411 | CLK(b2r2clk, "b2r2", NULL), | ||
412 | CLK(tvclk, "tv", NULL), | ||
413 | }; | ||
414 | |||
415 | static struct clk_lookup u8500_ed_clks[] = { | ||
416 | /* Peripheral Cluster #1 */ | ||
417 | CLK(spi3_ed, "spi3", NULL), | ||
418 | CLK(msp1_ed, "msp1", NULL), | ||
419 | |||
420 | /* Peripheral Cluster #2 */ | ||
421 | CLK(gpio1_ed, "gpioblock1", NULL), | ||
422 | CLK(ssitx_ed, "ssitx", NULL), | ||
423 | CLK(ssirx_ed, "ssirx", NULL), | ||
424 | CLK(spi0_ed, "spi0", NULL), | ||
425 | CLK(sdi3_ed, "sdi3", NULL), | ||
426 | CLK(sdi1_ed, "sdi1", NULL), | ||
427 | CLK(msp2_ed, "msp2", NULL), | ||
428 | CLK(sdi4_ed, "sdi4", NULL), | ||
429 | CLK(pwl_ed, "pwl", NULL), | ||
430 | CLK(spi1_ed, "spi1", NULL), | ||
431 | CLK(spi2_ed, "spi2", NULL), | ||
432 | CLK(i2c3_ed, "nmk-i2c.3", NULL), | ||
433 | |||
434 | /* Peripheral Cluster #3 */ | ||
435 | CLK(ssp1_ed, "ssp1", NULL), | ||
436 | CLK(ssp0_ed, "ssp0", NULL), | ||
437 | |||
438 | /* Peripheral Cluster #5 */ | ||
439 | CLK(usb_ed, "musb_hdrc.0", "usb"), | ||
440 | |||
441 | /* Peripheral Cluster #6 */ | ||
442 | CLK(dmc_ed, "dmc", NULL), | ||
443 | CLK(cryp1_ed, "cryp1", NULL), | ||
444 | CLK(rng_ed, "rng", NULL), | ||
445 | |||
446 | /* Peripheral Cluster #7 */ | ||
447 | CLK(tzpc0_ed, "tzpc0", NULL), | ||
448 | CLK(mtu1_ed, "mtu1", NULL), | ||
449 | CLK(mtu0_ed, "mtu0", NULL), | ||
450 | CLK(wdg_ed, "wdg", NULL), | ||
451 | CLK(cfgreg_ed, "cfgreg", NULL), | ||
452 | }; | ||
453 | |||
454 | static struct clk_lookup u8500_v1_clks[] = { | ||
455 | /* Peripheral Cluster #1 */ | ||
456 | CLK(i2c4, "nmk-i2c.4", NULL), | ||
457 | CLK(spi3_v1, "spi3", NULL), | ||
458 | CLK(msp1_v1, "msp1", NULL), | ||
459 | |||
460 | /* Peripheral Cluster #2 */ | ||
461 | CLK(gpio1_v1, "gpioblock1", NULL), | ||
462 | CLK(ssitx_v1, "ssitx", NULL), | ||
463 | CLK(ssirx_v1, "ssirx", NULL), | ||
464 | CLK(spi0_v1, "spi0", NULL), | ||
465 | CLK(sdi3_v1, "sdi3", NULL), | ||
466 | CLK(sdi1_v1, "sdi1", NULL), | ||
467 | CLK(msp2_v1, "msp2", NULL), | ||
468 | CLK(sdi4_v1, "sdi4", NULL), | ||
469 | CLK(pwl_v1, "pwl", NULL), | ||
470 | CLK(spi1_v1, "spi1", NULL), | ||
471 | CLK(spi2_v1, "spi2", NULL), | ||
472 | CLK(i2c3_v1, "nmk-i2c.3", NULL), | ||
473 | |||
474 | /* Peripheral Cluster #3 */ | ||
475 | CLK(ssp1_v1, "ssp1", NULL), | ||
476 | CLK(ssp0_v1, "ssp0", NULL), | ||
477 | |||
478 | /* Peripheral Cluster #5 */ | ||
479 | CLK(usb_v1, "musb_hdrc.0", "usb"), | ||
480 | |||
481 | /* Peripheral Cluster #6 */ | ||
482 | CLK(mtu1_v1, "mtu1", NULL), | ||
483 | CLK(mtu0_v1, "mtu0", NULL), | ||
484 | CLK(cfgreg_v1, "cfgreg", NULL), | ||
485 | CLK(hash1, "hash1", NULL), | ||
486 | CLK(unipro_v1, "unipro", NULL), | ||
487 | CLK(rng_v1, "rng", NULL), | ||
488 | |||
489 | /* PRCMU level clock gating */ | ||
490 | |||
491 | /* Bank 0 */ | ||
492 | CLK(uniproclk, "uniproclk", NULL), | ||
493 | CLK(dsialtclk, "dsialt", NULL), | ||
494 | |||
495 | /* Bank 1 */ | ||
496 | CLK(rngclk, "rng", NULL), | ||
497 | CLK(uiccclk, "uicc", NULL), | ||
84 | }; | 498 | }; |
85 | 499 | ||
86 | static int __init clk_init(void) | 500 | static int __init clk_init(void) |
87 | { | 501 | { |
88 | /* register the clock lookups */ | 502 | if (cpu_is_u8500ed()) { |
89 | clkdev_add_table(lookups, ARRAY_SIZE(lookups)); | 503 | clk_prcmu_ops.enable = clk_prcmu_ed_enable; |
504 | clk_prcmu_ops.disable = clk_prcmu_ed_disable; | ||
505 | } | ||
506 | |||
507 | clkdev_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks)); | ||
508 | if (cpu_is_u8500ed()) | ||
509 | clkdev_add_table(u8500_ed_clks, ARRAY_SIZE(u8500_ed_clks)); | ||
510 | else | ||
511 | clkdev_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks)); | ||
512 | |||
90 | return 0; | 513 | return 0; |
91 | } | 514 | } |
92 | arch_initcall(clk_init); | 515 | arch_initcall(clk_init); |
diff --git a/arch/arm/mach-ux500/clock.h b/arch/arm/mach-ux500/clock.h new file mode 100644 index 000000000000..e4f99b65026f --- /dev/null +++ b/arch/arm/mach-ux500/clock.h | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 ST-Ericsson | ||
3 | * Copyright (C) 2009 STMicroelectronics | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | /** | ||
11 | * struct clkops - ux500 clock operations | ||
12 | * @enable: function to enable the clock | ||
13 | * @disable: function to disable the clock | ||
14 | * @get_rate: function to get the current clock rate | ||
15 | * | ||
16 | * This structure contains function pointers to functions that will be used to | ||
17 | * control the clock. All of these functions are optional. If get_rate is | ||
18 | * NULL, the rate in the struct clk will be used. | ||
19 | */ | ||
20 | struct clkops { | ||
21 | void (*enable) (struct clk *); | ||
22 | void (*disable) (struct clk *); | ||
23 | unsigned long (*get_rate) (struct clk *); | ||
24 | }; | ||
25 | |||
26 | /** | ||
27 | * struct clk - ux500 clock structure | ||
28 | * @ops: pointer to clkops struct used to control this clock | ||
29 | * @name: name, for debugging | ||
30 | * @enabled: refcount. positive if enabled, zero if disabled | ||
31 | * @rate: fixed rate for clocks which don't implement | ||
32 | * ops->getrate | ||
33 | * @prcmu_cg_off: address offset of the combined enable/disable register | ||
34 | * (used on u8500v1) | ||
35 | * @prcmu_cg_bit: bit in the combined enable/disable register (used on | ||
36 | * u8500v1) | ||
37 | * @prcmu_cg_mgt: address of the enable/disable register (used on | ||
38 | * u8500ed) | ||
39 | * @cluster: peripheral cluster number | ||
40 | * @prcc_bus: bit for the bus clock in the peripheral's CLKRST | ||
41 | * @prcc_kernel: bit for the kernel clock in the peripheral's CLKRST. | ||
42 | * -1 if no kernel clock exists. | ||
43 | * @parent_cluster: pointer to parent's cluster clk struct | ||
44 | * @parent_periph: pointer to parent's peripheral clk struct | ||
45 | * | ||
46 | * Peripherals are organised into clusters, and each cluster has an associated | ||
47 | * bus clock. Some peripherals also have a parent peripheral clock. | ||
48 | * | ||
49 | * In order to enable a clock for a peripheral, we need to enable: | ||
50 | * (1) the parent cluster (bus) clock at the PRCMU level | ||
51 | * (2) the parent peripheral clock (if any) at the PRCMU level | ||
52 | * (3) the peripheral's bus & kernel clock at the PRCC level | ||
53 | * | ||
54 | * (1) and (2) are handled by defining clk structs (DEFINE_PRCMU_CLK) for each | ||
55 | * of the cluster and peripheral clocks, and hooking these as the parents of | ||
56 | * the individual peripheral clocks. | ||
57 | * | ||
58 | * (3) is handled by specifying the bits in the PRCC control registers required | ||
59 | * to enable these clocks and modifying them in the ->enable and | ||
60 | * ->disable callbacks of the peripheral clocks (DEFINE_PRCC_CLK). | ||
61 | * | ||
62 | * This structure describes both the PRCMU-level clocks and PRCC-level clocks. | ||
63 | * The prcmu_* fields are only used for the PRCMU clocks, and the cluster, | ||
64 | * prcc, and parent pointers are only used for the PRCC-level clocks. | ||
65 | */ | ||
66 | struct clk { | ||
67 | const struct clkops *ops; | ||
68 | const char *name; | ||
69 | unsigned int enabled; | ||
70 | |||
71 | unsigned long rate; | ||
72 | struct list_head list; | ||
73 | |||
74 | /* These three are only for PRCMU clks */ | ||
75 | |||
76 | unsigned int prcmu_cg_off; | ||
77 | unsigned int prcmu_cg_bit; | ||
78 | unsigned int prcmu_cg_mgt; | ||
79 | |||
80 | /* The rest are only for PRCC clks */ | ||
81 | |||
82 | int cluster; | ||
83 | unsigned int prcc_bus; | ||
84 | unsigned int prcc_kernel; | ||
85 | |||
86 | struct clk *parent_cluster; | ||
87 | struct clk *parent_periph; | ||
88 | }; | ||
89 | |||
90 | #define DEFINE_PRCMU_CLK(_name, _cg_off, _cg_bit, _reg) \ | ||
91 | struct clk clk_##_name = { \ | ||
92 | .name = #_name, \ | ||
93 | .ops = &clk_prcmu_ops, \ | ||
94 | .prcmu_cg_off = _cg_off, \ | ||
95 | .prcmu_cg_bit = _cg_bit, \ | ||
96 | .prcmu_cg_mgt = PRCM_##_reg##_MGT \ | ||
97 | } | ||
98 | |||
99 | #define DEFINE_PRCMU_CLK_RATE(_name, _cg_off, _cg_bit, _reg, _rate) \ | ||
100 | struct clk clk_##_name = { \ | ||
101 | .name = #_name, \ | ||
102 | .ops = &clk_prcmu_ops, \ | ||
103 | .prcmu_cg_off = _cg_off, \ | ||
104 | .prcmu_cg_bit = _cg_bit, \ | ||
105 | .rate = _rate, \ | ||
106 | .prcmu_cg_mgt = PRCM_##_reg##_MGT \ | ||
107 | } | ||
108 | |||
109 | #define DEFINE_PRCC_CLK(_pclust, _name, _bus_en, _kernel_en, _kernclk) \ | ||
110 | struct clk clk_##_name = { \ | ||
111 | .name = #_name, \ | ||
112 | .ops = &clk_prcc_ops, \ | ||
113 | .cluster = _pclust, \ | ||
114 | .prcc_bus = _bus_en, \ | ||
115 | .prcc_kernel = _kernel_en, \ | ||
116 | .parent_cluster = &clk_per##_pclust##clk, \ | ||
117 | .parent_periph = _kernclk \ | ||
118 | } | ||
119 | |||
120 | #define CLK(_clk, _devname, _conname) \ | ||
121 | { \ | ||
122 | .clk = &clk_##_clk, \ | ||
123 | .dev_id = _devname, \ | ||
124 | .con_id = _conname, \ | ||
125 | } | ||
diff --git a/arch/arm/mach-ux500/cpu-u8500.c b/arch/arm/mach-ux500/cpu-u8500.c index f368504d2af7..09bcba1ccef1 100644 --- a/arch/arm/mach-ux500/cpu-u8500.c +++ b/arch/arm/mach-ux500/cpu-u8500.c | |||
@@ -43,10 +43,17 @@ static struct map_desc u8500_io_desc[] __initdata = { | |||
43 | __IO_DEV_DESC(U8500_TWD_BASE, SZ_4K), | 43 | __IO_DEV_DESC(U8500_TWD_BASE, SZ_4K), |
44 | __IO_DEV_DESC(U8500_SCU_BASE, SZ_4K), | 44 | __IO_DEV_DESC(U8500_SCU_BASE, SZ_4K), |
45 | __IO_DEV_DESC(U8500_BACKUPRAM0_BASE, SZ_8K), | 45 | __IO_DEV_DESC(U8500_BACKUPRAM0_BASE, SZ_8K), |
46 | __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K), | ||
47 | __IO_DEV_DESC(U8500_CLKRST1_BASE, SZ_4K), | ||
48 | __IO_DEV_DESC(U8500_CLKRST2_BASE, SZ_4K), | ||
49 | __IO_DEV_DESC(U8500_CLKRST3_BASE, SZ_4K), | ||
50 | __IO_DEV_DESC(U8500_CLKRST5_BASE, SZ_4K), | ||
51 | __IO_DEV_DESC(U8500_CLKRST6_BASE, SZ_4K), | ||
46 | }; | 52 | }; |
47 | 53 | ||
48 | static struct map_desc u8500ed_io_desc[] __initdata = { | 54 | static struct map_desc u8500ed_io_desc[] __initdata = { |
49 | __IO_DEV_DESC(U8500_MTU0_BASE_ED, SZ_4K), | 55 | __IO_DEV_DESC(U8500_MTU0_BASE_ED, SZ_4K), |
56 | __IO_DEV_DESC(U8500_CLKRST7_BASE_ED, SZ_8K), | ||
50 | }; | 57 | }; |
51 | 58 | ||
52 | static struct map_desc u8500v1_io_desc[] __initdata = { | 59 | static struct map_desc u8500v1_io_desc[] __initdata = { |