aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@stericsson.com>2010-02-28 23:07:47 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-03-19 14:29:45 -0400
commit1df20afce51e7af2a587425d1aafca2608fe0066 (patch)
tree07bde105706ff8396e58f400ef87cb4bac0456cc /arch
parent75a36ee01e860be693220f1c40e2c04fb6cc69ba (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')
-rw-r--r--arch/arm/mach-ux500/board-mop500.c2
-rw-r--r--arch/arm/mach-ux500/clock.c491
-rw-r--r--arch/arm/mach-ux500/clock.h125
-rw-r--r--arch/arm/mach-ux500/cpu-u8500.c7
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 = {
94static struct amba_device pl022_device = { 94static 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
24struct 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
69static DEFINE_SPINLOCK(clocks_lock);
70
71static 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
28int clk_enable(struct clk *clk) 85int 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}
32EXPORT_SYMBOL(clk_enable); 95EXPORT_SYMBOL(clk_enable);
33 96
97static 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
34void clk_disable(struct clk *clk) 111void 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}
37EXPORT_SYMBOL(clk_disable); 121EXPORT_SYMBOL(clk_disable);
38 122
39unsigned long clk_get_rate(struct clk *clk) 123unsigned 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}
43EXPORT_SYMBOL(clk_get_rate); 140EXPORT_SYMBOL(clk_get_rate);
44 141
@@ -56,37 +153,363 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
56} 153}
57EXPORT_SYMBOL(clk_set_rate); 154EXPORT_SYMBOL(clk_set_rate);
58 155
59/* ssp clock */ 156static void clk_prcmu_enable(struct clk *clk)
60static 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
164static 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 */
173static 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
181static 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
189static struct clkops clk_prcmu_ops = {
190 .enable = clk_prcmu_enable,
191 .disable = clk_prcmu_disable,
62}; 192};
63 193
64/* fixed clock */ 194static unsigned int clkrst_base[] = {
65static 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
69static struct clk_lookup lookups[] = { 203static 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 */ 214static 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
225static struct clkops clk_prcc_ops = {
226 .enable = clk_prcc_enable,
227 .disable = clk_prcc_disable,
228};
229
230static struct clk clk_32khz = {
231 .rate = 32000,
232};
233
234/*
235 * PRCMU level clock gating
236 */
237
238/* Bank 0 */
239static DEFINE_PRCMU_CLK(svaclk, 0x0, 2, SVAMMDSPCLK);
240static DEFINE_PRCMU_CLK(siaclk, 0x0, 3, SIAMMDSPCLK);
241static DEFINE_PRCMU_CLK(sgaclk, 0x0, 4, SGACLK);
242static DEFINE_PRCMU_CLK_RATE(uartclk, 0x0, 5, UARTCLK, 38400000);
243static DEFINE_PRCMU_CLK(msp02clk, 0x0, 6, MSP02CLK);
244static DEFINE_PRCMU_CLK(msp1clk, 0x0, 7, MSP1CLK); /* v1 */
245static DEFINE_PRCMU_CLK_RATE(i2cclk, 0x0, 8, I2CCLK, 48000000);
246static DEFINE_PRCMU_CLK_RATE(sdmmcclk, 0x0, 9, SDMMCCLK, 50000000);
247static DEFINE_PRCMU_CLK(slimclk, 0x0, 10, SLIMCLK);
248static DEFINE_PRCMU_CLK(per1clk, 0x0, 11, PER1CLK);
249static DEFINE_PRCMU_CLK(per2clk, 0x0, 12, PER2CLK);
250static DEFINE_PRCMU_CLK(per3clk, 0x0, 13, PER3CLK);
251static DEFINE_PRCMU_CLK(per5clk, 0x0, 14, PER5CLK);
252static DEFINE_PRCMU_CLK_RATE(per6clk, 0x0, 15, PER6CLK, 133330000);
253static DEFINE_PRCMU_CLK_RATE(per7clk, 0x0, 16, PER7CLK, 100000000);
254static DEFINE_PRCMU_CLK(lcdclk, 0x0, 17, LCDCLK);
255static DEFINE_PRCMU_CLK(bmlclk, 0x0, 18, BMLCLK);
256static DEFINE_PRCMU_CLK(hsitxclk, 0x0, 19, HSITXCLK);
257static DEFINE_PRCMU_CLK(hsirxclk, 0x0, 20, HSIRXCLK);
258static DEFINE_PRCMU_CLK(hdmiclk, 0x0, 21, HDMICLK);
259static DEFINE_PRCMU_CLK(apeatclk, 0x0, 22, APEATCLK);
260static DEFINE_PRCMU_CLK(apetraceclk, 0x0, 23, APETRACECLK);
261static DEFINE_PRCMU_CLK(mcdeclk, 0x0, 24, MCDECLK);
262static DEFINE_PRCMU_CLK(ipi2clk, 0x0, 25, IPI2CCLK);
263static DEFINE_PRCMU_CLK(dsialtclk, 0x0, 26, DSIALTCLK); /* v1 */
264static DEFINE_PRCMU_CLK(dmaclk, 0x0, 27, DMACLK);
265static DEFINE_PRCMU_CLK(b2r2clk, 0x0, 28, B2R2CLK);
266static DEFINE_PRCMU_CLK(tvclk, 0x0, 29, TVCLK);
267static DEFINE_PRCMU_CLK(uniproclk, 0x0, 30, UNIPROCLK); /* v1 */
268static DEFINE_PRCMU_CLK_RATE(sspclk, 0x0, 31, SSPCLK, 48000000); /* v1 */
269
270/* Bank 1 */
271static DEFINE_PRCMU_CLK(rngclk, 0x4, 0, RNGCLK); /* v1 */
272static 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 */
280static DEFINE_PRCC_CLK(1, i2c4, 10, 9, &clk_i2cclk);
281static DEFINE_PRCC_CLK(1, gpio0, 9, -1, NULL);
282static DEFINE_PRCC_CLK(1, slimbus0, 8, 8, &clk_slimclk);
283static DEFINE_PRCC_CLK(1, spi3_ed, 7, 7, NULL);
284static DEFINE_PRCC_CLK(1, spi3_v1, 7, -1, NULL);
285static DEFINE_PRCC_CLK(1, i2c2, 6, 6, &clk_i2cclk);
286static DEFINE_PRCC_CLK(1, sdi0, 5, 5, &clk_sdmmcclk);
287static DEFINE_PRCC_CLK(1, msp1_ed, 4, 4, &clk_msp02clk);
288static DEFINE_PRCC_CLK(1, msp1_v1, 4, 4, &clk_msp1clk);
289static DEFINE_PRCC_CLK(1, msp0, 3, 3, &clk_msp02clk);
290static DEFINE_PRCC_CLK(1, i2c1, 2, 2, &clk_i2cclk);
291static DEFINE_PRCC_CLK(1, uart1, 1, 1, &clk_uartclk);
292static DEFINE_PRCC_CLK(1, uart0, 0, 0, &clk_uartclk);
293
294/* Peripheral Cluster #2 */
295
296static DEFINE_PRCC_CLK(2, gpio1_ed, 12, -1, NULL);
297static DEFINE_PRCC_CLK(2, ssitx_ed, 11, -1, NULL);
298static DEFINE_PRCC_CLK(2, ssirx_ed, 10, -1, NULL);
299static DEFINE_PRCC_CLK(2, spi0_ed, 9, -1, NULL);
300static DEFINE_PRCC_CLK(2, sdi3_ed, 8, 6, &clk_sdmmcclk);
301static DEFINE_PRCC_CLK(2, sdi1_ed, 7, 5, &clk_sdmmcclk);
302static DEFINE_PRCC_CLK(2, msp2_ed, 6, 4, &clk_msp02clk);
303static DEFINE_PRCC_CLK(2, sdi4_ed, 4, 2, &clk_sdmmcclk);
304static DEFINE_PRCC_CLK(2, pwl_ed, 3, 1, NULL);
305static DEFINE_PRCC_CLK(2, spi1_ed, 2, -1, NULL);
306static DEFINE_PRCC_CLK(2, spi2_ed, 1, -1, NULL);
307static DEFINE_PRCC_CLK(2, i2c3_ed, 0, 0, &clk_i2cclk);
308
309static DEFINE_PRCC_CLK(2, gpio1_v1, 11, -1, NULL);
310static DEFINE_PRCC_CLK(2, ssitx_v1, 10, 7, NULL);
311static DEFINE_PRCC_CLK(2, ssirx_v1, 9, 6, NULL);
312static DEFINE_PRCC_CLK(2, spi0_v1, 8, -1, NULL);
313static DEFINE_PRCC_CLK(2, sdi3_v1, 7, 5, &clk_sdmmcclk);
314static DEFINE_PRCC_CLK(2, sdi1_v1, 6, 4, &clk_sdmmcclk);
315static DEFINE_PRCC_CLK(2, msp2_v1, 5, 3, &clk_msp02clk);
316static DEFINE_PRCC_CLK(2, sdi4_v1, 4, 2, &clk_sdmmcclk);
317static DEFINE_PRCC_CLK(2, pwl_v1, 3, 1, NULL);
318static DEFINE_PRCC_CLK(2, spi1_v1, 2, -1, NULL);
319static DEFINE_PRCC_CLK(2, spi2_v1, 1, -1, NULL);
320static DEFINE_PRCC_CLK(2, i2c3_v1, 0, 0, &clk_i2cclk);
321
322/* Peripheral Cluster #3 */
323static DEFINE_PRCC_CLK(3, gpio2, 8, -1, NULL);
324static DEFINE_PRCC_CLK(3, sdi5, 7, 7, &clk_sdmmcclk);
325static DEFINE_PRCC_CLK(3, uart2, 6, 6, &clk_uartclk);
326static DEFINE_PRCC_CLK(3, ske, 5, 5, &clk_32khz);
327static DEFINE_PRCC_CLK(3, sdi2, 4, 4, &clk_sdmmcclk);
328static DEFINE_PRCC_CLK(3, i2c0, 3, 3, &clk_i2cclk);
329static DEFINE_PRCC_CLK(3, ssp1_ed, 2, 2, &clk_i2cclk);
330static DEFINE_PRCC_CLK(3, ssp0_ed, 1, 1, &clk_i2cclk);
331static DEFINE_PRCC_CLK(3, ssp1_v1, 2, 2, &clk_sspclk);
332static DEFINE_PRCC_CLK(3, ssp0_v1, 1, 1, &clk_sspclk);
333static DEFINE_PRCC_CLK(3, fsmc, 0, -1, NULL);
334
335/* Peripheral Cluster #4 is in the always on domain */
336
337/* Peripheral Cluster #5 */
338static DEFINE_PRCC_CLK(5, gpio3, 1, -1, NULL);
339static DEFINE_PRCC_CLK(5, usb_ed, 0, 0, &clk_i2cclk);
340static DEFINE_PRCC_CLK(5, usb_v1, 0, 0, NULL);
341
342/* Peripheral Cluster #6 */
343
344static DEFINE_PRCC_CLK(6, mtu1_v1, 8, -1, NULL);
345static DEFINE_PRCC_CLK(6, mtu0_v1, 7, -1, NULL);
346static DEFINE_PRCC_CLK(6, cfgreg_v1, 6, 6, NULL);
347static DEFINE_PRCC_CLK(6, dmc_ed, 6, 6, NULL);
348static DEFINE_PRCC_CLK(6, hash1, 5, -1, NULL);
349static DEFINE_PRCC_CLK(6, unipro_v1, 4, 1, &clk_uniproclk);
350static DEFINE_PRCC_CLK(6, cryp1_ed, 4, -1, NULL);
351static DEFINE_PRCC_CLK(6, pka, 3, -1, NULL);
352static DEFINE_PRCC_CLK(6, hash0, 2, -1, NULL);
353static DEFINE_PRCC_CLK(6, cryp0, 1, -1, NULL);
354static DEFINE_PRCC_CLK(6, rng_ed, 0, 0, &clk_i2cclk);
355static DEFINE_PRCC_CLK(6, rng_v1, 0, 0, &clk_rngclk);
356
357/* Peripheral Cluster #7 */
358
359static DEFINE_PRCC_CLK(7, tzpc0_ed, 4, -1, NULL);
360static DEFINE_PRCC_CLK(7, mtu1_ed, 3, -1, NULL);
361static DEFINE_PRCC_CLK(7, mtu0_ed, 2, -1, NULL);
362static DEFINE_PRCC_CLK(7, wdg_ed, 1, -1, NULL);
363static DEFINE_PRCC_CLK(7, cfgreg_ed, 0, -1, NULL);
364
365static 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
415static 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
454static 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
86static int __init clk_init(void) 500static 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}
92arch_initcall(clk_init); 515arch_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 */
20struct 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 */
66struct 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) \
91struct 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) \
100struct 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) \
110struct 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
48static struct map_desc u8500ed_io_desc[] __initdata = { 54static 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
52static struct map_desc u8500v1_io_desc[] __initdata = { 59static struct map_desc u8500v1_io_desc[] __initdata = {