blob: 32ce90840ee1509dbc877a037298b956ea18b4ba [file] [log] [blame]
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +01001/*
2 * Copyright (C) 2009 ST-Ericsson
Rabin Vincent1df20af2010-03-01 05:07:47 +01003 * Copyright (C) 2009 STMicroelectronics
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +01004 *
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#include <linux/module.h>
10#include <linux/kernel.h>
11#include <linux/list.h>
12#include <linux/errno.h>
13#include <linux/err.h>
14#include <linux/clk.h>
Rabin Vincent1df20af2010-03-01 05:07:47 +010015#include <linux/io.h>
Jean-Christop PLAGNIOL-VILLARD6d803ba2010-11-17 10:04:33 +010016#include <linux/clkdev.h>
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +010017
Linus Walleijba327b12010-05-26 07:38:54 +010018#include <plat/mtu.h>
Rabin Vincent1df20af2010-03-01 05:07:47 +010019#include <mach/hardware.h>
20#include "clock.h"
21
Vincent Guittot763eef82010-12-03 18:18:39 +010022#ifdef CONFIG_DEBUG_FS
23#include <linux/debugfs.h>
24#include <linux/uaccess.h> /* for copy_from_user */
25static LIST_HEAD(clk_list);
26#endif
27
Rabin Vincent1df20af2010-03-01 05:07:47 +010028#define PRCC_PCKEN 0x00
29#define PRCC_PCKDIS 0x04
30#define PRCC_KCKEN 0x08
31#define PRCC_KCKDIS 0x0C
32
33#define PRCM_YYCLKEN0_MGT_SET 0x510
34#define PRCM_YYCLKEN1_MGT_SET 0x514
35#define PRCM_YYCLKEN0_MGT_CLR 0x518
36#define PRCM_YYCLKEN1_MGT_CLR 0x51C
37#define PRCM_YYCLKEN0_MGT_VAL 0x520
38#define PRCM_YYCLKEN1_MGT_VAL 0x524
39
40#define PRCM_SVAMMDSPCLK_MGT 0x008
41#define PRCM_SIAMMDSPCLK_MGT 0x00C
42#define PRCM_SGACLK_MGT 0x014
43#define PRCM_UARTCLK_MGT 0x018
44#define PRCM_MSP02CLK_MGT 0x01C
45#define PRCM_MSP1CLK_MGT 0x288
46#define PRCM_I2CCLK_MGT 0x020
47#define PRCM_SDMMCCLK_MGT 0x024
48#define PRCM_SLIMCLK_MGT 0x028
49#define PRCM_PER1CLK_MGT 0x02C
50#define PRCM_PER2CLK_MGT 0x030
51#define PRCM_PER3CLK_MGT 0x034
52#define PRCM_PER5CLK_MGT 0x038
53#define PRCM_PER6CLK_MGT 0x03C
54#define PRCM_PER7CLK_MGT 0x040
55#define PRCM_LCDCLK_MGT 0x044
56#define PRCM_BMLCLK_MGT 0x04C
57#define PRCM_HSITXCLK_MGT 0x050
58#define PRCM_HSIRXCLK_MGT 0x054
59#define PRCM_HDMICLK_MGT 0x058
60#define PRCM_APEATCLK_MGT 0x05C
61#define PRCM_APETRACECLK_MGT 0x060
62#define PRCM_MCDECLK_MGT 0x064
63#define PRCM_IPI2CCLK_MGT 0x068
64#define PRCM_DSIALTCLK_MGT 0x06C
65#define PRCM_DMACLK_MGT 0x074
66#define PRCM_B2R2CLK_MGT 0x078
67#define PRCM_TVCLK_MGT 0x07C
Linus Walleijba327b12010-05-26 07:38:54 +010068#define PRCM_TCR 0x1C8
69#define PRCM_TCR_STOPPED (1 << 16)
70#define PRCM_TCR_DOZE_MODE (1 << 17)
Rabin Vincent1df20af2010-03-01 05:07:47 +010071#define PRCM_UNIPROCLK_MGT 0x278
72#define PRCM_SSPCLK_MGT 0x280
73#define PRCM_RNGCLK_MGT 0x284
74#define PRCM_UICCCLK_MGT 0x27C
75
76#define PRCM_MGT_ENABLE (1 << 8)
77
78static DEFINE_SPINLOCK(clocks_lock);
79
80static void __clk_enable(struct clk *clk)
81{
82 if (clk->enabled++ == 0) {
83 if (clk->parent_cluster)
84 __clk_enable(clk->parent_cluster);
85
86 if (clk->parent_periph)
87 __clk_enable(clk->parent_periph);
88
89 if (clk->ops && clk->ops->enable)
90 clk->ops->enable(clk);
91 }
92}
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +010093
94int clk_enable(struct clk *clk)
95{
Rabin Vincent1df20af2010-03-01 05:07:47 +010096 unsigned long flags;
97
98 spin_lock_irqsave(&clocks_lock, flags);
99 __clk_enable(clk);
100 spin_unlock_irqrestore(&clocks_lock, flags);
101
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100102 return 0;
103}
104EXPORT_SYMBOL(clk_enable);
105
Rabin Vincent1df20af2010-03-01 05:07:47 +0100106static void __clk_disable(struct clk *clk)
107{
108 if (--clk->enabled == 0) {
109 if (clk->ops && clk->ops->disable)
110 clk->ops->disable(clk);
111
112 if (clk->parent_periph)
113 __clk_disable(clk->parent_periph);
114
115 if (clk->parent_cluster)
116 __clk_disable(clk->parent_cluster);
117 }
118}
119
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100120void clk_disable(struct clk *clk)
121{
Rabin Vincent1df20af2010-03-01 05:07:47 +0100122 unsigned long flags;
123
124 WARN_ON(!clk->enabled);
125
126 spin_lock_irqsave(&clocks_lock, flags);
127 __clk_disable(clk);
128 spin_unlock_irqrestore(&clocks_lock, flags);
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100129}
130EXPORT_SYMBOL(clk_disable);
131
Linus Walleijba327b12010-05-26 07:38:54 +0100132/*
133 * The MTU has a separate, rather complex muxing setup
134 * with alternative parents (peripheral cluster or
135 * ULP or fixed 32768 Hz) depending on settings
136 */
137static unsigned long clk_mtu_get_rate(struct clk *clk)
138{
Rabin Vincent92389ca2010-12-08 11:07:57 +0530139 void __iomem *addr;
Sundar Iyerf3069542010-12-03 20:35:51 +0530140 u32 tcr;
Linus Walleijba327b12010-05-26 07:38:54 +0100141 int mtu = (int) clk->data;
142 /*
143 * One of these is selected eventually
144 * TODO: Replace the constant with a reference
145 * to the ULP source once this is modeled.
146 */
147 unsigned long clk32k = 32768;
148 unsigned long mturate;
149 unsigned long retclk;
150
Rabin Vincent92389ca2010-12-08 11:07:57 +0530151 if (cpu_is_u5500())
152 addr = __io_address(U5500_PRCMU_BASE);
153 else if (cpu_is_u8500())
154 addr = __io_address(U8500_PRCMU_BASE);
155 else
156 ux500_unknown_soc();
157
Sundar Iyerf3069542010-12-03 20:35:51 +0530158 /*
159 * On a startup, always conifgure the TCR to the doze mode;
160 * bootloaders do it for us. Do this in the kernel too.
161 */
Rabin Vincent92389ca2010-12-08 11:07:57 +0530162 writel(PRCM_TCR_DOZE_MODE, addr + PRCM_TCR);
Sundar Iyerf3069542010-12-03 20:35:51 +0530163
Rabin Vincent92389ca2010-12-08 11:07:57 +0530164 tcr = readl(addr + PRCM_TCR);
Sundar Iyerf3069542010-12-03 20:35:51 +0530165
Linus Walleijba327b12010-05-26 07:38:54 +0100166 /* Get the rate from the parent as a default */
167 if (clk->parent_periph)
168 mturate = clk_get_rate(clk->parent_periph);
169 else if (clk->parent_cluster)
170 mturate = clk_get_rate(clk->parent_cluster);
171 else
172 /* We need to be connected SOMEWHERE */
173 BUG();
174
Linus Walleijba327b12010-05-26 07:38:54 +0100175 /* Return the clock selected for this MTU */
176 if (tcr & (1 << mtu))
177 retclk = clk32k;
178 else
179 retclk = mturate;
180
181 pr_info("MTU%d clock rate: %lu Hz\n", mtu, retclk);
182 return retclk;
183}
184
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100185unsigned long clk_get_rate(struct clk *clk)
186{
Rabin Vincent1df20af2010-03-01 05:07:47 +0100187 unsigned long rate;
188
Linus Walleijba327b12010-05-26 07:38:54 +0100189 /*
190 * If there is a custom getrate callback for this clock,
191 * it will take precedence.
192 */
193 if (clk->get_rate)
194 return clk->get_rate(clk);
195
Rabin Vincent1df20af2010-03-01 05:07:47 +0100196 if (clk->ops && clk->ops->get_rate)
197 return clk->ops->get_rate(clk);
198
199 rate = clk->rate;
200 if (!rate) {
201 if (clk->parent_periph)
202 rate = clk_get_rate(clk->parent_periph);
203 else if (clk->parent_cluster)
204 rate = clk_get_rate(clk->parent_cluster);
205 }
206
207 return rate;
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100208}
209EXPORT_SYMBOL(clk_get_rate);
210
211long clk_round_rate(struct clk *clk, unsigned long rate)
212{
213 /*TODO*/
214 return rate;
215}
216EXPORT_SYMBOL(clk_round_rate);
217
218int clk_set_rate(struct clk *clk, unsigned long rate)
219{
220 clk->rate = rate;
221 return 0;
222}
223EXPORT_SYMBOL(clk_set_rate);
224
Rabin Vincent1df20af2010-03-01 05:07:47 +0100225static void clk_prcmu_enable(struct clk *clk)
226{
227 void __iomem *cg_set_reg = __io_address(U8500_PRCMU_BASE)
228 + PRCM_YYCLKEN0_MGT_SET + clk->prcmu_cg_off;
229
230 writel(1 << clk->prcmu_cg_bit, cg_set_reg);
231}
232
233static void clk_prcmu_disable(struct clk *clk)
234{
235 void __iomem *cg_clr_reg = __io_address(U8500_PRCMU_BASE)
236 + PRCM_YYCLKEN0_MGT_CLR + clk->prcmu_cg_off;
237
238 writel(1 << clk->prcmu_cg_bit, cg_clr_reg);
239}
240
241/* ED doesn't have the combined set/clr registers */
242static void clk_prcmu_ed_enable(struct clk *clk)
243{
244 void __iomem *addr = __io_address(U8500_PRCMU_BASE)
245 + clk->prcmu_cg_mgt;
246
247 writel(readl(addr) | PRCM_MGT_ENABLE, addr);
248}
249
250static void clk_prcmu_ed_disable(struct clk *clk)
251{
252 void __iomem *addr = __io_address(U8500_PRCMU_BASE)
253 + clk->prcmu_cg_mgt;
254
255 writel(readl(addr) & ~PRCM_MGT_ENABLE, addr);
256}
257
258static struct clkops clk_prcmu_ops = {
259 .enable = clk_prcmu_enable,
260 .disable = clk_prcmu_disable,
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100261};
262
Rabin Vincent1df20af2010-03-01 05:07:47 +0100263static unsigned int clkrst_base[] = {
264 [1] = U8500_CLKRST1_BASE,
265 [2] = U8500_CLKRST2_BASE,
266 [3] = U8500_CLKRST3_BASE,
267 [5] = U8500_CLKRST5_BASE,
268 [6] = U8500_CLKRST6_BASE,
269 [7] = U8500_CLKRST7_BASE_ED,
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100270};
271
Rabin Vincent1df20af2010-03-01 05:07:47 +0100272static void clk_prcc_enable(struct clk *clk)
273{
274 void __iomem *addr = __io_address(clkrst_base[clk->cluster]);
275
276 if (clk->prcc_kernel != -1)
277 writel(1 << clk->prcc_kernel, addr + PRCC_KCKEN);
278
279 if (clk->prcc_bus != -1)
280 writel(1 << clk->prcc_bus, addr + PRCC_PCKEN);
281}
282
283static void clk_prcc_disable(struct clk *clk)
284{
285 void __iomem *addr = __io_address(clkrst_base[clk->cluster]);
286
287 if (clk->prcc_bus != -1)
288 writel(1 << clk->prcc_bus, addr + PRCC_PCKDIS);
289
290 if (clk->prcc_kernel != -1)
291 writel(1 << clk->prcc_kernel, addr + PRCC_KCKDIS);
292}
293
294static struct clkops clk_prcc_ops = {
295 .enable = clk_prcc_enable,
296 .disable = clk_prcc_disable,
297};
298
299static struct clk clk_32khz = {
Vincent Guittot763eef82010-12-03 18:18:39 +0100300 .name = "clk_32khz",
Rabin Vincent1df20af2010-03-01 05:07:47 +0100301 .rate = 32000,
302};
303
304/*
305 * PRCMU level clock gating
306 */
307
308/* Bank 0 */
309static DEFINE_PRCMU_CLK(svaclk, 0x0, 2, SVAMMDSPCLK);
310static DEFINE_PRCMU_CLK(siaclk, 0x0, 3, SIAMMDSPCLK);
311static DEFINE_PRCMU_CLK(sgaclk, 0x0, 4, SGACLK);
312static DEFINE_PRCMU_CLK_RATE(uartclk, 0x0, 5, UARTCLK, 38400000);
313static DEFINE_PRCMU_CLK(msp02clk, 0x0, 6, MSP02CLK);
314static DEFINE_PRCMU_CLK(msp1clk, 0x0, 7, MSP1CLK); /* v1 */
315static DEFINE_PRCMU_CLK_RATE(i2cclk, 0x0, 8, I2CCLK, 48000000);
Philippe Langlaisfbdc6d12011-01-27 14:37:07 +0100316static DEFINE_PRCMU_CLK_RATE(sdmmcclk, 0x0, 9, SDMMCCLK, 100000000);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100317static DEFINE_PRCMU_CLK(slimclk, 0x0, 10, SLIMCLK);
318static DEFINE_PRCMU_CLK(per1clk, 0x0, 11, PER1CLK);
319static DEFINE_PRCMU_CLK(per2clk, 0x0, 12, PER2CLK);
320static DEFINE_PRCMU_CLK(per3clk, 0x0, 13, PER3CLK);
321static DEFINE_PRCMU_CLK(per5clk, 0x0, 14, PER5CLK);
322static DEFINE_PRCMU_CLK_RATE(per6clk, 0x0, 15, PER6CLK, 133330000);
323static DEFINE_PRCMU_CLK_RATE(per7clk, 0x0, 16, PER7CLK, 100000000);
324static DEFINE_PRCMU_CLK(lcdclk, 0x0, 17, LCDCLK);
325static DEFINE_PRCMU_CLK(bmlclk, 0x0, 18, BMLCLK);
326static DEFINE_PRCMU_CLK(hsitxclk, 0x0, 19, HSITXCLK);
327static DEFINE_PRCMU_CLK(hsirxclk, 0x0, 20, HSIRXCLK);
328static DEFINE_PRCMU_CLK(hdmiclk, 0x0, 21, HDMICLK);
329static DEFINE_PRCMU_CLK(apeatclk, 0x0, 22, APEATCLK);
330static DEFINE_PRCMU_CLK(apetraceclk, 0x0, 23, APETRACECLK);
331static DEFINE_PRCMU_CLK(mcdeclk, 0x0, 24, MCDECLK);
332static DEFINE_PRCMU_CLK(ipi2clk, 0x0, 25, IPI2CCLK);
333static DEFINE_PRCMU_CLK(dsialtclk, 0x0, 26, DSIALTCLK); /* v1 */
334static DEFINE_PRCMU_CLK(dmaclk, 0x0, 27, DMACLK);
335static DEFINE_PRCMU_CLK(b2r2clk, 0x0, 28, B2R2CLK);
336static DEFINE_PRCMU_CLK(tvclk, 0x0, 29, TVCLK);
337static DEFINE_PRCMU_CLK(uniproclk, 0x0, 30, UNIPROCLK); /* v1 */
338static DEFINE_PRCMU_CLK_RATE(sspclk, 0x0, 31, SSPCLK, 48000000); /* v1 */
339
340/* Bank 1 */
341static DEFINE_PRCMU_CLK(rngclk, 0x4, 0, RNGCLK); /* v1 */
342static DEFINE_PRCMU_CLK(uiccclk, 0x4, 1, UICCCLK); /* v1 */
343
344/*
345 * PRCC level clock gating
346 * Format: per#, clk, PCKEN bit, KCKEN bit, parent
347 */
348
349/* Peripheral Cluster #1 */
Sundar Iyer592b2f22010-12-03 20:35:52 +0530350static DEFINE_PRCC_CLK(1, i2c4, 10, 9, &clk_i2cclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100351static DEFINE_PRCC_CLK(1, gpio0, 9, -1, NULL);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530352static DEFINE_PRCC_CLK(1, slimbus0, 8, 8, &clk_slimclk);
353static DEFINE_PRCC_CLK(1, spi3_ed, 7, 7, NULL);
354static DEFINE_PRCC_CLK(1, spi3_v1, 7, -1, NULL);
355static DEFINE_PRCC_CLK(1, i2c2, 6, 6, &clk_i2cclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100356static DEFINE_PRCC_CLK(1, sdi0, 5, 5, &clk_sdmmcclk);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530357static DEFINE_PRCC_CLK(1, msp1_ed, 4, 4, &clk_msp02clk);
358static DEFINE_PRCC_CLK(1, msp1_v1, 4, 4, &clk_msp1clk);
359static DEFINE_PRCC_CLK(1, msp0, 3, 3, &clk_msp02clk);
360static DEFINE_PRCC_CLK(1, i2c1, 2, 2, &clk_i2cclk);
361static DEFINE_PRCC_CLK(1, uart1, 1, 1, &clk_uartclk);
362static DEFINE_PRCC_CLK(1, uart0, 0, 0, &clk_uartclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100363
364/* Peripheral Cluster #2 */
365
366static DEFINE_PRCC_CLK(2, gpio1_ed, 12, -1, NULL);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530367static DEFINE_PRCC_CLK(2, ssitx_ed, 11, -1, NULL);
368static DEFINE_PRCC_CLK(2, ssirx_ed, 10, -1, NULL);
369static DEFINE_PRCC_CLK(2, spi0_ed, 9, -1, NULL);
370static DEFINE_PRCC_CLK(2, sdi3_ed, 8, 6, &clk_sdmmcclk);
371static DEFINE_PRCC_CLK(2, sdi1_ed, 7, 5, &clk_sdmmcclk);
372static DEFINE_PRCC_CLK(2, msp2_ed, 6, 4, &clk_msp02clk);
373static DEFINE_PRCC_CLK(2, sdi4_ed, 4, 2, &clk_sdmmcclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100374static DEFINE_PRCC_CLK(2, pwl_ed, 3, 1, NULL);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530375static DEFINE_PRCC_CLK(2, spi1_ed, 2, -1, NULL);
376static DEFINE_PRCC_CLK(2, spi2_ed, 1, -1, NULL);
377static DEFINE_PRCC_CLK(2, i2c3_ed, 0, 0, &clk_i2cclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100378
379static DEFINE_PRCC_CLK(2, gpio1_v1, 11, -1, NULL);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530380static DEFINE_PRCC_CLK(2, ssitx_v1, 10, 7, NULL);
381static DEFINE_PRCC_CLK(2, ssirx_v1, 9, 6, NULL);
382static DEFINE_PRCC_CLK(2, spi0_v1, 8, -1, NULL);
383static DEFINE_PRCC_CLK(2, sdi3_v1, 7, 5, &clk_sdmmcclk);
384static DEFINE_PRCC_CLK(2, sdi1_v1, 6, 4, &clk_sdmmcclk);
385static DEFINE_PRCC_CLK(2, msp2_v1, 5, 3, &clk_msp02clk);
386static DEFINE_PRCC_CLK(2, sdi4_v1, 4, 2, &clk_sdmmcclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100387static DEFINE_PRCC_CLK(2, pwl_v1, 3, 1, NULL);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530388static DEFINE_PRCC_CLK(2, spi1_v1, 2, -1, NULL);
389static DEFINE_PRCC_CLK(2, spi2_v1, 1, -1, NULL);
390static DEFINE_PRCC_CLK(2, i2c3_v1, 0, 0, &clk_i2cclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100391
392/* Peripheral Cluster #3 */
Sundar Iyer592b2f22010-12-03 20:35:52 +0530393static DEFINE_PRCC_CLK(3, gpio2, 8, -1, NULL);
394static DEFINE_PRCC_CLK(3, sdi5, 7, 7, &clk_sdmmcclk);
395static DEFINE_PRCC_CLK(3, uart2, 6, 6, &clk_uartclk);
396static DEFINE_PRCC_CLK(3, ske, 5, 5, &clk_32khz);
397static DEFINE_PRCC_CLK(3, sdi2, 4, 4, &clk_sdmmcclk);
398static DEFINE_PRCC_CLK(3, i2c0, 3, 3, &clk_i2cclk);
399static DEFINE_PRCC_CLK(3, ssp1_ed, 2, 2, &clk_i2cclk);
400static DEFINE_PRCC_CLK(3, ssp0_ed, 1, 1, &clk_i2cclk);
401static DEFINE_PRCC_CLK(3, ssp1_v1, 2, 2, &clk_sspclk);
402static DEFINE_PRCC_CLK(3, ssp0_v1, 1, 1, &clk_sspclk);
403static DEFINE_PRCC_CLK(3, fsmc, 0, -1, NULL);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100404
405/* Peripheral Cluster #4 is in the always on domain */
406
407/* Peripheral Cluster #5 */
Sundar Iyer592b2f22010-12-03 20:35:52 +0530408static DEFINE_PRCC_CLK(5, gpio3, 1, -1, NULL);
409static DEFINE_PRCC_CLK(5, usb_ed, 0, 0, &clk_i2cclk);
410static DEFINE_PRCC_CLK(5, usb_v1, 0, 0, NULL);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100411
412/* Peripheral Cluster #6 */
413
Linus Walleijba327b12010-05-26 07:38:54 +0100414/* MTU ID in data */
415static DEFINE_PRCC_CLK_CUSTOM(6, mtu1_v1, 8, -1, NULL, clk_mtu_get_rate, 1);
416static DEFINE_PRCC_CLK_CUSTOM(6, mtu0_v1, 7, -1, NULL, clk_mtu_get_rate, 0);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530417static DEFINE_PRCC_CLK(6, cfgreg_v1, 6, 6, NULL);
418static DEFINE_PRCC_CLK(6, dmc_ed, 6, 6, NULL);
419static DEFINE_PRCC_CLK(6, hash1, 5, -1, NULL);
420static DEFINE_PRCC_CLK(6, unipro_v1, 4, 1, &clk_uniproclk);
421static DEFINE_PRCC_CLK(6, cryp1_ed, 4, -1, NULL);
422static DEFINE_PRCC_CLK(6, pka, 3, -1, NULL);
423static DEFINE_PRCC_CLK(6, hash0, 2, -1, NULL);
424static DEFINE_PRCC_CLK(6, cryp0, 1, -1, NULL);
425static DEFINE_PRCC_CLK(6, rng_ed, 0, 0, &clk_i2cclk);
426static DEFINE_PRCC_CLK(6, rng_v1, 0, 0, &clk_rngclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100427
428/* Peripheral Cluster #7 */
429
Sundar Iyer592b2f22010-12-03 20:35:52 +0530430static DEFINE_PRCC_CLK(7, tzpc0_ed, 4, -1, NULL);
Linus Walleijba327b12010-05-26 07:38:54 +0100431/* MTU ID in data */
432static DEFINE_PRCC_CLK_CUSTOM(7, mtu1_ed, 3, -1, NULL, clk_mtu_get_rate, 1);
433static DEFINE_PRCC_CLK_CUSTOM(7, mtu0_ed, 2, -1, NULL, clk_mtu_get_rate, 0);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530434static DEFINE_PRCC_CLK(7, wdg_ed, 1, -1, NULL);
435static DEFINE_PRCC_CLK(7, cfgreg_ed, 0, -1, NULL);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100436
Vincent Guittot763eef82010-12-03 18:18:39 +0100437static struct clk clk_dummy_apb_pclk = {
438 .name = "apb_pclk",
439};
Russell King3126c7b2010-07-15 11:01:17 +0100440
Rabin Vincent1df20af2010-03-01 05:07:47 +0100441static struct clk_lookup u8500_common_clks[] = {
Russell King3126c7b2010-07-15 11:01:17 +0100442 CLK(dummy_apb_pclk, NULL, "apb_pclk"),
443
Rabin Vincent1df20af2010-03-01 05:07:47 +0100444 /* Peripheral Cluster #1 */
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100445 CLK(gpio0, "gpio.0", NULL),
446 CLK(gpio0, "gpio.1", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100447 CLK(slimbus0, "slimbus0", NULL),
448 CLK(i2c2, "nmk-i2c.2", NULL),
449 CLK(sdi0, "sdi0", NULL),
450 CLK(msp0, "msp0", NULL),
451 CLK(i2c1, "nmk-i2c.1", NULL),
452 CLK(uart1, "uart1", NULL),
453 CLK(uart0, "uart0", NULL),
454
455 /* Peripheral Cluster #3 */
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100456 CLK(gpio2, "gpio.2", NULL),
457 CLK(gpio2, "gpio.3", NULL),
458 CLK(gpio2, "gpio.4", NULL),
459 CLK(gpio2, "gpio.5", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100460 CLK(sdi5, "sdi5", NULL),
461 CLK(uart2, "uart2", NULL),
462 CLK(ske, "ske", NULL),
Sundar Iyer4c61c842010-09-29 19:43:09 -0700463 CLK(ske, "nmk-ske-keypad", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100464 CLK(sdi2, "sdi2", NULL),
465 CLK(i2c0, "nmk-i2c.0", NULL),
466 CLK(fsmc, "fsmc", NULL),
467
468 /* Peripheral Cluster #5 */
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100469 CLK(gpio3, "gpio.8", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100470
471 /* Peripheral Cluster #6 */
472 CLK(hash1, "hash1", NULL),
473 CLK(pka, "pka", NULL),
474 CLK(hash0, "hash0", NULL),
475 CLK(cryp0, "cryp0", NULL),
476
477 /* PRCMU level clock gating */
478
479 /* Bank 0 */
480 CLK(svaclk, "sva", NULL),
481 CLK(siaclk, "sia", NULL),
482 CLK(sgaclk, "sga", NULL),
483 CLK(slimclk, "slim", NULL),
484 CLK(lcdclk, "lcd", NULL),
485 CLK(bmlclk, "bml", NULL),
486 CLK(hsitxclk, "stm-hsi.0", NULL),
487 CLK(hsirxclk, "stm-hsi.1", NULL),
488 CLK(hdmiclk, "hdmi", NULL),
489 CLK(apeatclk, "apeat", NULL),
490 CLK(apetraceclk, "apetrace", NULL),
491 CLK(mcdeclk, "mcde", NULL),
492 CLK(ipi2clk, "ipi2", NULL),
Linus Walleij7b8ddb02010-05-27 15:21:26 -0700493 CLK(dmaclk, "dma40.0", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100494 CLK(b2r2clk, "b2r2", NULL),
495 CLK(tvclk, "tv", NULL),
496};
497
498static struct clk_lookup u8500_ed_clks[] = {
499 /* Peripheral Cluster #1 */
500 CLK(spi3_ed, "spi3", NULL),
501 CLK(msp1_ed, "msp1", NULL),
502
503 /* Peripheral Cluster #2 */
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100504 CLK(gpio1_ed, "gpio.6", NULL),
505 CLK(gpio1_ed, "gpio.7", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100506 CLK(ssitx_ed, "ssitx", NULL),
507 CLK(ssirx_ed, "ssirx", NULL),
508 CLK(spi0_ed, "spi0", NULL),
509 CLK(sdi3_ed, "sdi3", NULL),
510 CLK(sdi1_ed, "sdi1", NULL),
511 CLK(msp2_ed, "msp2", NULL),
512 CLK(sdi4_ed, "sdi4", NULL),
513 CLK(pwl_ed, "pwl", NULL),
514 CLK(spi1_ed, "spi1", NULL),
515 CLK(spi2_ed, "spi2", NULL),
516 CLK(i2c3_ed, "nmk-i2c.3", NULL),
517
518 /* Peripheral Cluster #3 */
519 CLK(ssp1_ed, "ssp1", NULL),
520 CLK(ssp0_ed, "ssp0", NULL),
521
522 /* Peripheral Cluster #5 */
Mian Yousaf Kaukab7f0709e2011-01-21 18:05:40 +0100523 CLK(usb_ed, "musb-ux500.0", "usb"),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100524
525 /* Peripheral Cluster #6 */
526 CLK(dmc_ed, "dmc", NULL),
527 CLK(cryp1_ed, "cryp1", NULL),
528 CLK(rng_ed, "rng", NULL),
529
530 /* Peripheral Cluster #7 */
531 CLK(tzpc0_ed, "tzpc0", NULL),
532 CLK(mtu1_ed, "mtu1", NULL),
533 CLK(mtu0_ed, "mtu0", NULL),
534 CLK(wdg_ed, "wdg", NULL),
535 CLK(cfgreg_ed, "cfgreg", NULL),
536};
537
538static struct clk_lookup u8500_v1_clks[] = {
539 /* Peripheral Cluster #1 */
Sundar Iyer592b2f22010-12-03 20:35:52 +0530540 CLK(i2c4, "nmk-i2c.4", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100541 CLK(spi3_v1, "spi3", NULL),
542 CLK(msp1_v1, "msp1", NULL),
543
544 /* Peripheral Cluster #2 */
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100545 CLK(gpio1_v1, "gpio.6", NULL),
546 CLK(gpio1_v1, "gpio.7", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100547 CLK(ssitx_v1, "ssitx", NULL),
548 CLK(ssirx_v1, "ssirx", NULL),
549 CLK(spi0_v1, "spi0", NULL),
550 CLK(sdi3_v1, "sdi3", NULL),
551 CLK(sdi1_v1, "sdi1", NULL),
552 CLK(msp2_v1, "msp2", NULL),
553 CLK(sdi4_v1, "sdi4", NULL),
554 CLK(pwl_v1, "pwl", NULL),
555 CLK(spi1_v1, "spi1", NULL),
556 CLK(spi2_v1, "spi2", NULL),
557 CLK(i2c3_v1, "nmk-i2c.3", NULL),
558
559 /* Peripheral Cluster #3 */
560 CLK(ssp1_v1, "ssp1", NULL),
561 CLK(ssp0_v1, "ssp0", NULL),
562
563 /* Peripheral Cluster #5 */
Mian Yousaf Kaukab7f0709e2011-01-21 18:05:40 +0100564 CLK(usb_v1, "musb-ux500.0", "usb"),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100565
566 /* Peripheral Cluster #6 */
567 CLK(mtu1_v1, "mtu1", NULL),
568 CLK(mtu0_v1, "mtu0", NULL),
569 CLK(cfgreg_v1, "cfgreg", NULL),
570 CLK(hash1, "hash1", NULL),
571 CLK(unipro_v1, "unipro", NULL),
572 CLK(rng_v1, "rng", NULL),
573
574 /* PRCMU level clock gating */
575
576 /* Bank 0 */
577 CLK(uniproclk, "uniproclk", NULL),
578 CLK(dsialtclk, "dsialt", NULL),
579
580 /* Bank 1 */
581 CLK(rngclk, "rng", NULL),
582 CLK(uiccclk, "uicc", NULL),
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100583};
584
Vincent Guittot763eef82010-12-03 18:18:39 +0100585#ifdef CONFIG_DEBUG_FS
586/*
587 * debugfs support to trace clock tree hierarchy and attributes with
588 * powerdebug
589 */
590static struct dentry *clk_debugfs_root;
591
592void __init clk_debugfs_add_table(struct clk_lookup *cl, size_t num)
593{
594 while (num--) {
595 /* Check that the clock has not been already registered */
596 if (!(cl->clk->list.prev != cl->clk->list.next))
597 list_add_tail(&cl->clk->list, &clk_list);
598
599 cl++;
600 }
601}
602
603static ssize_t usecount_dbg_read(struct file *file, char __user *buf,
604 size_t size, loff_t *off)
605{
606 struct clk *clk = file->f_dentry->d_inode->i_private;
607 char cusecount[128];
608 unsigned int len;
609
610 len = sprintf(cusecount, "%u\n", clk->enabled);
611 return simple_read_from_buffer(buf, size, off, cusecount, len);
612}
613
614static ssize_t rate_dbg_read(struct file *file, char __user *buf,
615 size_t size, loff_t *off)
616{
617 struct clk *clk = file->f_dentry->d_inode->i_private;
618 char crate[128];
619 unsigned int rate;
620 unsigned int len;
621
622 rate = clk_get_rate(clk);
623 len = sprintf(crate, "%u\n", rate);
624 return simple_read_from_buffer(buf, size, off, crate, len);
625}
626
627static const struct file_operations usecount_fops = {
628 .read = usecount_dbg_read,
629};
630
631static const struct file_operations set_rate_fops = {
632 .read = rate_dbg_read,
633};
634
635static struct dentry *clk_debugfs_register_dir(struct clk *c,
636 struct dentry *p_dentry)
637{
638 struct dentry *d, *clk_d, *child, *child_tmp;
639 char s[255];
640 char *p = s;
641
642 if (c->name == NULL)
643 p += sprintf(p, "BUG");
644 else
645 p += sprintf(p, "%s", c->name);
646
647 clk_d = debugfs_create_dir(s, p_dentry);
648 if (!clk_d)
649 return NULL;
650
651 d = debugfs_create_file("usecount", S_IRUGO,
652 clk_d, c, &usecount_fops);
653 if (!d)
654 goto err_out;
655 d = debugfs_create_file("rate", S_IRUGO,
656 clk_d, c, &set_rate_fops);
657 if (!d)
658 goto err_out;
659 /*
660 * TODO : not currently available in ux500
661 * d = debugfs_create_x32("flags", S_IRUGO, clk_d, (u32 *)&c->flags);
662 * if (!d)
663 * goto err_out;
664 */
665
666 return clk_d;
667
668err_out:
669 d = clk_d;
670 list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
671 debugfs_remove(child);
672 debugfs_remove(clk_d);
673 return NULL;
674}
675
676static void clk_debugfs_remove_dir(struct dentry *cdentry)
677{
678 struct dentry *d, *child, *child_tmp;
679
680 d = cdentry;
681 list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
682 debugfs_remove(child);
683 debugfs_remove(cdentry);
684 return ;
685}
686
687static int clk_debugfs_register_one(struct clk *c)
688{
689 struct clk *pa = c->parent_periph;
690 struct clk *bpa = c->parent_cluster;
691
692 if (!(bpa && !pa)) {
693 c->dent = clk_debugfs_register_dir(c,
694 pa ? pa->dent : clk_debugfs_root);
695 if (!c->dent)
696 return -ENOMEM;
697 }
698
699 if (bpa) {
700 c->dent_bus = clk_debugfs_register_dir(c,
701 bpa->dent_bus ? bpa->dent_bus : bpa->dent);
702 if ((!c->dent_bus) && (c->dent)) {
703 clk_debugfs_remove_dir(c->dent);
704 c->dent = NULL;
705 return -ENOMEM;
706 }
707 }
708 return 0;
709}
710
711static int clk_debugfs_register(struct clk *c)
712{
713 int err;
714 struct clk *pa = c->parent_periph;
715 struct clk *bpa = c->parent_cluster;
716
717 if (pa && (!pa->dent && !pa->dent_bus)) {
718 err = clk_debugfs_register(pa);
719 if (err)
720 return err;
721 }
722
723 if (bpa && (!bpa->dent && !bpa->dent_bus)) {
724 err = clk_debugfs_register(bpa);
725 if (err)
726 return err;
727 }
728
729 if ((!c->dent) && (!c->dent_bus)) {
730 err = clk_debugfs_register_one(c);
731 if (err)
732 return err;
733 }
734 return 0;
735}
736
737static int __init clk_debugfs_init(void)
738{
739 struct clk *c;
740 struct dentry *d;
741 int err;
742
743 d = debugfs_create_dir("clock", NULL);
744 if (!d)
745 return -ENOMEM;
746 clk_debugfs_root = d;
747
748 list_for_each_entry(c, &clk_list, list) {
749 err = clk_debugfs_register(c);
750 if (err)
751 goto err_out;
752 }
753 return 0;
754err_out:
755 debugfs_remove_recursive(clk_debugfs_root);
756 return err;
757}
758
759late_initcall(clk_debugfs_init);
760#endif /* defined(CONFIG_DEBUG_FS) */
761
Linus Walleijba327b12010-05-26 07:38:54 +0100762int __init clk_init(void)
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100763{
Rabin Vincent1df20af2010-03-01 05:07:47 +0100764 if (cpu_is_u8500ed()) {
765 clk_prcmu_ops.enable = clk_prcmu_ed_enable;
766 clk_prcmu_ops.disable = clk_prcmu_ed_disable;
Linus Walleijba327b12010-05-26 07:38:54 +0100767 clk_per6clk.rate = 100000000;
Rabin Vincent591d8dd2010-05-03 08:46:51 +0100768 } else if (cpu_is_u5500()) {
769 /* Clock tree for U5500 not implemented yet */
770 clk_prcc_ops.enable = clk_prcc_ops.disable = NULL;
771 clk_prcmu_ops.enable = clk_prcmu_ops.disable = NULL;
Per Forlinbab263e2010-12-05 12:49:03 +0100772 clk_uartclk.rate = 36360000;
773 clk_sdmmcclk.rate = 99900000;
Rabin Vincent1df20af2010-03-01 05:07:47 +0100774 }
775
776 clkdev_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks));
777 if (cpu_is_u8500ed())
778 clkdev_add_table(u8500_ed_clks, ARRAY_SIZE(u8500_ed_clks));
779 else
780 clkdev_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks));
781
Vincent Guittot763eef82010-12-03 18:18:39 +0100782#ifdef CONFIG_DEBUG_FS
783 clk_debugfs_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks));
784 if (cpu_is_u8500ed())
785 clk_debugfs_add_table(u8500_ed_clks, ARRAY_SIZE(u8500_ed_clks));
786 else
787 clk_debugfs_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks));
788#endif
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100789 return 0;
790}