blob: e832664d1bd944687c2db0533cec879bb93ee011 [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>
Linus Walleijef7a4742011-06-01 14:44:16 +020017#include <linux/cpufreq.h>
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +010018
Linus Walleijba327b12010-05-26 07:38:54 +010019#include <plat/mtu.h>
Rabin Vincent1df20af2010-03-01 05:07:47 +010020#include <mach/hardware.h>
21#include "clock.h"
22
Vincent Guittot763eef82010-12-03 18:18:39 +010023#ifdef CONFIG_DEBUG_FS
24#include <linux/debugfs.h>
25#include <linux/uaccess.h> /* for copy_from_user */
26static LIST_HEAD(clk_list);
27#endif
28
Rabin Vincent1df20af2010-03-01 05:07:47 +010029#define PRCC_PCKEN 0x00
30#define PRCC_PCKDIS 0x04
31#define PRCC_KCKEN 0x08
32#define PRCC_KCKDIS 0x0C
33
34#define PRCM_YYCLKEN0_MGT_SET 0x510
35#define PRCM_YYCLKEN1_MGT_SET 0x514
36#define PRCM_YYCLKEN0_MGT_CLR 0x518
37#define PRCM_YYCLKEN1_MGT_CLR 0x51C
38#define PRCM_YYCLKEN0_MGT_VAL 0x520
39#define PRCM_YYCLKEN1_MGT_VAL 0x524
40
41#define PRCM_SVAMMDSPCLK_MGT 0x008
42#define PRCM_SIAMMDSPCLK_MGT 0x00C
43#define PRCM_SGACLK_MGT 0x014
44#define PRCM_UARTCLK_MGT 0x018
45#define PRCM_MSP02CLK_MGT 0x01C
46#define PRCM_MSP1CLK_MGT 0x288
47#define PRCM_I2CCLK_MGT 0x020
48#define PRCM_SDMMCCLK_MGT 0x024
49#define PRCM_SLIMCLK_MGT 0x028
50#define PRCM_PER1CLK_MGT 0x02C
51#define PRCM_PER2CLK_MGT 0x030
52#define PRCM_PER3CLK_MGT 0x034
53#define PRCM_PER5CLK_MGT 0x038
54#define PRCM_PER6CLK_MGT 0x03C
55#define PRCM_PER7CLK_MGT 0x040
56#define PRCM_LCDCLK_MGT 0x044
57#define PRCM_BMLCLK_MGT 0x04C
58#define PRCM_HSITXCLK_MGT 0x050
59#define PRCM_HSIRXCLK_MGT 0x054
60#define PRCM_HDMICLK_MGT 0x058
61#define PRCM_APEATCLK_MGT 0x05C
62#define PRCM_APETRACECLK_MGT 0x060
63#define PRCM_MCDECLK_MGT 0x064
64#define PRCM_IPI2CCLK_MGT 0x068
65#define PRCM_DSIALTCLK_MGT 0x06C
66#define PRCM_DMACLK_MGT 0x074
67#define PRCM_B2R2CLK_MGT 0x078
68#define PRCM_TVCLK_MGT 0x07C
Linus Walleijba327b12010-05-26 07:38:54 +010069#define PRCM_TCR 0x1C8
70#define PRCM_TCR_STOPPED (1 << 16)
71#define PRCM_TCR_DOZE_MODE (1 << 17)
Rabin Vincent1df20af2010-03-01 05:07:47 +010072#define PRCM_UNIPROCLK_MGT 0x278
73#define PRCM_SSPCLK_MGT 0x280
74#define PRCM_RNGCLK_MGT 0x284
75#define PRCM_UICCCLK_MGT 0x27C
76
77#define PRCM_MGT_ENABLE (1 << 8)
78
79static DEFINE_SPINLOCK(clocks_lock);
80
81static void __clk_enable(struct clk *clk)
82{
83 if (clk->enabled++ == 0) {
84 if (clk->parent_cluster)
85 __clk_enable(clk->parent_cluster);
86
87 if (clk->parent_periph)
88 __clk_enable(clk->parent_periph);
89
90 if (clk->ops && clk->ops->enable)
91 clk->ops->enable(clk);
92 }
93}
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +010094
95int clk_enable(struct clk *clk)
96{
Rabin Vincent1df20af2010-03-01 05:07:47 +010097 unsigned long flags;
98
99 spin_lock_irqsave(&clocks_lock, flags);
100 __clk_enable(clk);
101 spin_unlock_irqrestore(&clocks_lock, flags);
102
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100103 return 0;
104}
105EXPORT_SYMBOL(clk_enable);
106
Rabin Vincent1df20af2010-03-01 05:07:47 +0100107static void __clk_disable(struct clk *clk)
108{
109 if (--clk->enabled == 0) {
110 if (clk->ops && clk->ops->disable)
111 clk->ops->disable(clk);
112
113 if (clk->parent_periph)
114 __clk_disable(clk->parent_periph);
115
116 if (clk->parent_cluster)
117 __clk_disable(clk->parent_cluster);
118 }
119}
120
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100121void clk_disable(struct clk *clk)
122{
Rabin Vincent1df20af2010-03-01 05:07:47 +0100123 unsigned long flags;
124
125 WARN_ON(!clk->enabled);
126
127 spin_lock_irqsave(&clocks_lock, flags);
128 __clk_disable(clk);
129 spin_unlock_irqrestore(&clocks_lock, flags);
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100130}
131EXPORT_SYMBOL(clk_disable);
132
Linus Walleijba327b12010-05-26 07:38:54 +0100133/*
134 * The MTU has a separate, rather complex muxing setup
135 * with alternative parents (peripheral cluster or
136 * ULP or fixed 32768 Hz) depending on settings
137 */
138static unsigned long clk_mtu_get_rate(struct clk *clk)
139{
Rabin Vincent92389ca2010-12-08 11:07:57 +0530140 void __iomem *addr;
Sundar Iyerf3069542010-12-03 20:35:51 +0530141 u32 tcr;
Linus Walleijba327b12010-05-26 07:38:54 +0100142 int mtu = (int) clk->data;
143 /*
144 * One of these is selected eventually
145 * TODO: Replace the constant with a reference
146 * to the ULP source once this is modeled.
147 */
148 unsigned long clk32k = 32768;
149 unsigned long mturate;
150 unsigned long retclk;
151
Rabin Vincent92389ca2010-12-08 11:07:57 +0530152 if (cpu_is_u5500())
153 addr = __io_address(U5500_PRCMU_BASE);
154 else if (cpu_is_u8500())
155 addr = __io_address(U8500_PRCMU_BASE);
156 else
157 ux500_unknown_soc();
158
Sundar Iyerf3069542010-12-03 20:35:51 +0530159 /*
160 * On a startup, always conifgure the TCR to the doze mode;
161 * bootloaders do it for us. Do this in the kernel too.
162 */
Rabin Vincent92389ca2010-12-08 11:07:57 +0530163 writel(PRCM_TCR_DOZE_MODE, addr + PRCM_TCR);
Sundar Iyerf3069542010-12-03 20:35:51 +0530164
Rabin Vincent92389ca2010-12-08 11:07:57 +0530165 tcr = readl(addr + PRCM_TCR);
Sundar Iyerf3069542010-12-03 20:35:51 +0530166
Linus Walleijba327b12010-05-26 07:38:54 +0100167 /* Get the rate from the parent as a default */
168 if (clk->parent_periph)
169 mturate = clk_get_rate(clk->parent_periph);
170 else if (clk->parent_cluster)
171 mturate = clk_get_rate(clk->parent_cluster);
172 else
173 /* We need to be connected SOMEWHERE */
174 BUG();
175
Linus Walleijba327b12010-05-26 07:38:54 +0100176 /* Return the clock selected for this MTU */
177 if (tcr & (1 << mtu))
178 retclk = clk32k;
179 else
180 retclk = mturate;
181
182 pr_info("MTU%d clock rate: %lu Hz\n", mtu, retclk);
183 return retclk;
184}
185
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100186unsigned long clk_get_rate(struct clk *clk)
187{
Rabin Vincent1df20af2010-03-01 05:07:47 +0100188 unsigned long rate;
189
Linus Walleijba327b12010-05-26 07:38:54 +0100190 /*
191 * If there is a custom getrate callback for this clock,
192 * it will take precedence.
193 */
194 if (clk->get_rate)
195 return clk->get_rate(clk);
196
Rabin Vincent1df20af2010-03-01 05:07:47 +0100197 if (clk->ops && clk->ops->get_rate)
198 return clk->ops->get_rate(clk);
199
200 rate = clk->rate;
201 if (!rate) {
202 if (clk->parent_periph)
203 rate = clk_get_rate(clk->parent_periph);
204 else if (clk->parent_cluster)
205 rate = clk_get_rate(clk->parent_cluster);
206 }
207
208 return rate;
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100209}
210EXPORT_SYMBOL(clk_get_rate);
211
212long clk_round_rate(struct clk *clk, unsigned long rate)
213{
214 /*TODO*/
215 return rate;
216}
217EXPORT_SYMBOL(clk_round_rate);
218
219int clk_set_rate(struct clk *clk, unsigned long rate)
220{
221 clk->rate = rate;
222 return 0;
223}
224EXPORT_SYMBOL(clk_set_rate);
225
Rabin Vincent1df20af2010-03-01 05:07:47 +0100226static void clk_prcmu_enable(struct clk *clk)
227{
228 void __iomem *cg_set_reg = __io_address(U8500_PRCMU_BASE)
229 + PRCM_YYCLKEN0_MGT_SET + clk->prcmu_cg_off;
230
231 writel(1 << clk->prcmu_cg_bit, cg_set_reg);
232}
233
234static void clk_prcmu_disable(struct clk *clk)
235{
236 void __iomem *cg_clr_reg = __io_address(U8500_PRCMU_BASE)
237 + PRCM_YYCLKEN0_MGT_CLR + clk->prcmu_cg_off;
238
239 writel(1 << clk->prcmu_cg_bit, cg_clr_reg);
240}
241
242/* ED doesn't have the combined set/clr registers */
243static void clk_prcmu_ed_enable(struct clk *clk)
244{
245 void __iomem *addr = __io_address(U8500_PRCMU_BASE)
246 + clk->prcmu_cg_mgt;
247
248 writel(readl(addr) | PRCM_MGT_ENABLE, addr);
249}
250
251static void clk_prcmu_ed_disable(struct clk *clk)
252{
253 void __iomem *addr = __io_address(U8500_PRCMU_BASE)
254 + clk->prcmu_cg_mgt;
255
256 writel(readl(addr) & ~PRCM_MGT_ENABLE, addr);
257}
258
259static struct clkops clk_prcmu_ops = {
260 .enable = clk_prcmu_enable,
261 .disable = clk_prcmu_disable,
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100262};
263
Rabin Vincent1df20af2010-03-01 05:07:47 +0100264static unsigned int clkrst_base[] = {
265 [1] = U8500_CLKRST1_BASE,
266 [2] = U8500_CLKRST2_BASE,
267 [3] = U8500_CLKRST3_BASE,
268 [5] = U8500_CLKRST5_BASE,
269 [6] = U8500_CLKRST6_BASE,
270 [7] = U8500_CLKRST7_BASE_ED,
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100271};
272
Rabin Vincent1df20af2010-03-01 05:07:47 +0100273static void clk_prcc_enable(struct clk *clk)
274{
275 void __iomem *addr = __io_address(clkrst_base[clk->cluster]);
276
277 if (clk->prcc_kernel != -1)
278 writel(1 << clk->prcc_kernel, addr + PRCC_KCKEN);
279
280 if (clk->prcc_bus != -1)
281 writel(1 << clk->prcc_bus, addr + PRCC_PCKEN);
282}
283
284static void clk_prcc_disable(struct clk *clk)
285{
286 void __iomem *addr = __io_address(clkrst_base[clk->cluster]);
287
288 if (clk->prcc_bus != -1)
289 writel(1 << clk->prcc_bus, addr + PRCC_PCKDIS);
290
291 if (clk->prcc_kernel != -1)
292 writel(1 << clk->prcc_kernel, addr + PRCC_KCKDIS);
293}
294
295static struct clkops clk_prcc_ops = {
296 .enable = clk_prcc_enable,
297 .disable = clk_prcc_disable,
298};
299
300static struct clk clk_32khz = {
Vincent Guittot763eef82010-12-03 18:18:39 +0100301 .name = "clk_32khz",
Rabin Vincent1df20af2010-03-01 05:07:47 +0100302 .rate = 32000,
303};
304
305/*
306 * PRCMU level clock gating
307 */
308
309/* Bank 0 */
310static DEFINE_PRCMU_CLK(svaclk, 0x0, 2, SVAMMDSPCLK);
311static DEFINE_PRCMU_CLK(siaclk, 0x0, 3, SIAMMDSPCLK);
312static DEFINE_PRCMU_CLK(sgaclk, 0x0, 4, SGACLK);
313static DEFINE_PRCMU_CLK_RATE(uartclk, 0x0, 5, UARTCLK, 38400000);
314static DEFINE_PRCMU_CLK(msp02clk, 0x0, 6, MSP02CLK);
315static DEFINE_PRCMU_CLK(msp1clk, 0x0, 7, MSP1CLK); /* v1 */
316static DEFINE_PRCMU_CLK_RATE(i2cclk, 0x0, 8, I2CCLK, 48000000);
Philippe Langlaisfbdc6d12011-01-27 14:37:07 +0100317static DEFINE_PRCMU_CLK_RATE(sdmmcclk, 0x0, 9, SDMMCCLK, 100000000);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100318static DEFINE_PRCMU_CLK(slimclk, 0x0, 10, SLIMCLK);
319static DEFINE_PRCMU_CLK(per1clk, 0x0, 11, PER1CLK);
320static DEFINE_PRCMU_CLK(per2clk, 0x0, 12, PER2CLK);
321static DEFINE_PRCMU_CLK(per3clk, 0x0, 13, PER3CLK);
322static DEFINE_PRCMU_CLK(per5clk, 0x0, 14, PER5CLK);
323static DEFINE_PRCMU_CLK_RATE(per6clk, 0x0, 15, PER6CLK, 133330000);
324static DEFINE_PRCMU_CLK_RATE(per7clk, 0x0, 16, PER7CLK, 100000000);
325static DEFINE_PRCMU_CLK(lcdclk, 0x0, 17, LCDCLK);
326static DEFINE_PRCMU_CLK(bmlclk, 0x0, 18, BMLCLK);
327static DEFINE_PRCMU_CLK(hsitxclk, 0x0, 19, HSITXCLK);
328static DEFINE_PRCMU_CLK(hsirxclk, 0x0, 20, HSIRXCLK);
329static DEFINE_PRCMU_CLK(hdmiclk, 0x0, 21, HDMICLK);
330static DEFINE_PRCMU_CLK(apeatclk, 0x0, 22, APEATCLK);
331static DEFINE_PRCMU_CLK(apetraceclk, 0x0, 23, APETRACECLK);
332static DEFINE_PRCMU_CLK(mcdeclk, 0x0, 24, MCDECLK);
333static DEFINE_PRCMU_CLK(ipi2clk, 0x0, 25, IPI2CCLK);
334static DEFINE_PRCMU_CLK(dsialtclk, 0x0, 26, DSIALTCLK); /* v1 */
335static DEFINE_PRCMU_CLK(dmaclk, 0x0, 27, DMACLK);
336static DEFINE_PRCMU_CLK(b2r2clk, 0x0, 28, B2R2CLK);
337static DEFINE_PRCMU_CLK(tvclk, 0x0, 29, TVCLK);
338static DEFINE_PRCMU_CLK(uniproclk, 0x0, 30, UNIPROCLK); /* v1 */
339static DEFINE_PRCMU_CLK_RATE(sspclk, 0x0, 31, SSPCLK, 48000000); /* v1 */
340
341/* Bank 1 */
342static DEFINE_PRCMU_CLK(rngclk, 0x4, 0, RNGCLK); /* v1 */
343static DEFINE_PRCMU_CLK(uiccclk, 0x4, 1, UICCCLK); /* v1 */
344
345/*
346 * PRCC level clock gating
347 * Format: per#, clk, PCKEN bit, KCKEN bit, parent
348 */
349
350/* Peripheral Cluster #1 */
Sundar Iyer592b2f22010-12-03 20:35:52 +0530351static DEFINE_PRCC_CLK(1, i2c4, 10, 9, &clk_i2cclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100352static DEFINE_PRCC_CLK(1, gpio0, 9, -1, NULL);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530353static DEFINE_PRCC_CLK(1, slimbus0, 8, 8, &clk_slimclk);
354static DEFINE_PRCC_CLK(1, spi3_ed, 7, 7, NULL);
355static DEFINE_PRCC_CLK(1, spi3_v1, 7, -1, NULL);
356static DEFINE_PRCC_CLK(1, i2c2, 6, 6, &clk_i2cclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100357static DEFINE_PRCC_CLK(1, sdi0, 5, 5, &clk_sdmmcclk);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530358static DEFINE_PRCC_CLK(1, msp1_ed, 4, 4, &clk_msp02clk);
359static DEFINE_PRCC_CLK(1, msp1_v1, 4, 4, &clk_msp1clk);
360static DEFINE_PRCC_CLK(1, msp0, 3, 3, &clk_msp02clk);
361static DEFINE_PRCC_CLK(1, i2c1, 2, 2, &clk_i2cclk);
362static DEFINE_PRCC_CLK(1, uart1, 1, 1, &clk_uartclk);
363static DEFINE_PRCC_CLK(1, uart0, 0, 0, &clk_uartclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100364
365/* Peripheral Cluster #2 */
366
367static DEFINE_PRCC_CLK(2, gpio1_ed, 12, -1, NULL);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530368static DEFINE_PRCC_CLK(2, ssitx_ed, 11, -1, NULL);
369static DEFINE_PRCC_CLK(2, ssirx_ed, 10, -1, NULL);
370static DEFINE_PRCC_CLK(2, spi0_ed, 9, -1, NULL);
371static DEFINE_PRCC_CLK(2, sdi3_ed, 8, 6, &clk_sdmmcclk);
372static DEFINE_PRCC_CLK(2, sdi1_ed, 7, 5, &clk_sdmmcclk);
373static DEFINE_PRCC_CLK(2, msp2_ed, 6, 4, &clk_msp02clk);
374static DEFINE_PRCC_CLK(2, sdi4_ed, 4, 2, &clk_sdmmcclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100375static DEFINE_PRCC_CLK(2, pwl_ed, 3, 1, NULL);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530376static DEFINE_PRCC_CLK(2, spi1_ed, 2, -1, NULL);
377static DEFINE_PRCC_CLK(2, spi2_ed, 1, -1, NULL);
378static DEFINE_PRCC_CLK(2, i2c3_ed, 0, 0, &clk_i2cclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100379
380static DEFINE_PRCC_CLK(2, gpio1_v1, 11, -1, NULL);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530381static DEFINE_PRCC_CLK(2, ssitx_v1, 10, 7, NULL);
382static DEFINE_PRCC_CLK(2, ssirx_v1, 9, 6, NULL);
383static DEFINE_PRCC_CLK(2, spi0_v1, 8, -1, NULL);
384static DEFINE_PRCC_CLK(2, sdi3_v1, 7, 5, &clk_sdmmcclk);
385static DEFINE_PRCC_CLK(2, sdi1_v1, 6, 4, &clk_sdmmcclk);
386static DEFINE_PRCC_CLK(2, msp2_v1, 5, 3, &clk_msp02clk);
387static DEFINE_PRCC_CLK(2, sdi4_v1, 4, 2, &clk_sdmmcclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100388static DEFINE_PRCC_CLK(2, pwl_v1, 3, 1, NULL);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530389static DEFINE_PRCC_CLK(2, spi1_v1, 2, -1, NULL);
390static DEFINE_PRCC_CLK(2, spi2_v1, 1, -1, NULL);
391static DEFINE_PRCC_CLK(2, i2c3_v1, 0, 0, &clk_i2cclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100392
393/* Peripheral Cluster #3 */
Sundar Iyer592b2f22010-12-03 20:35:52 +0530394static DEFINE_PRCC_CLK(3, gpio2, 8, -1, NULL);
395static DEFINE_PRCC_CLK(3, sdi5, 7, 7, &clk_sdmmcclk);
396static DEFINE_PRCC_CLK(3, uart2, 6, 6, &clk_uartclk);
397static DEFINE_PRCC_CLK(3, ske, 5, 5, &clk_32khz);
398static DEFINE_PRCC_CLK(3, sdi2, 4, 4, &clk_sdmmcclk);
399static DEFINE_PRCC_CLK(3, i2c0, 3, 3, &clk_i2cclk);
400static DEFINE_PRCC_CLK(3, ssp1_ed, 2, 2, &clk_i2cclk);
401static DEFINE_PRCC_CLK(3, ssp0_ed, 1, 1, &clk_i2cclk);
402static DEFINE_PRCC_CLK(3, ssp1_v1, 2, 2, &clk_sspclk);
403static DEFINE_PRCC_CLK(3, ssp0_v1, 1, 1, &clk_sspclk);
404static DEFINE_PRCC_CLK(3, fsmc, 0, -1, NULL);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100405
406/* Peripheral Cluster #4 is in the always on domain */
407
408/* Peripheral Cluster #5 */
Sundar Iyer592b2f22010-12-03 20:35:52 +0530409static DEFINE_PRCC_CLK(5, gpio3, 1, -1, NULL);
410static DEFINE_PRCC_CLK(5, usb_ed, 0, 0, &clk_i2cclk);
411static DEFINE_PRCC_CLK(5, usb_v1, 0, 0, NULL);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100412
413/* Peripheral Cluster #6 */
414
Linus Walleijba327b12010-05-26 07:38:54 +0100415/* MTU ID in data */
416static DEFINE_PRCC_CLK_CUSTOM(6, mtu1_v1, 8, -1, NULL, clk_mtu_get_rate, 1);
417static DEFINE_PRCC_CLK_CUSTOM(6, mtu0_v1, 7, -1, NULL, clk_mtu_get_rate, 0);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530418static DEFINE_PRCC_CLK(6, cfgreg_v1, 6, 6, NULL);
419static DEFINE_PRCC_CLK(6, dmc_ed, 6, 6, NULL);
420static DEFINE_PRCC_CLK(6, hash1, 5, -1, NULL);
421static DEFINE_PRCC_CLK(6, unipro_v1, 4, 1, &clk_uniproclk);
422static DEFINE_PRCC_CLK(6, cryp1_ed, 4, -1, NULL);
423static DEFINE_PRCC_CLK(6, pka, 3, -1, NULL);
424static DEFINE_PRCC_CLK(6, hash0, 2, -1, NULL);
425static DEFINE_PRCC_CLK(6, cryp0, 1, -1, NULL);
426static DEFINE_PRCC_CLK(6, rng_ed, 0, 0, &clk_i2cclk);
427static DEFINE_PRCC_CLK(6, rng_v1, 0, 0, &clk_rngclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100428
429/* Peripheral Cluster #7 */
430
Sundar Iyer592b2f22010-12-03 20:35:52 +0530431static DEFINE_PRCC_CLK(7, tzpc0_ed, 4, -1, NULL);
Linus Walleijba327b12010-05-26 07:38:54 +0100432/* MTU ID in data */
433static DEFINE_PRCC_CLK_CUSTOM(7, mtu1_ed, 3, -1, NULL, clk_mtu_get_rate, 1);
434static DEFINE_PRCC_CLK_CUSTOM(7, mtu0_ed, 2, -1, NULL, clk_mtu_get_rate, 0);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530435static DEFINE_PRCC_CLK(7, wdg_ed, 1, -1, NULL);
436static DEFINE_PRCC_CLK(7, cfgreg_ed, 0, -1, NULL);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100437
Vincent Guittot763eef82010-12-03 18:18:39 +0100438static struct clk clk_dummy_apb_pclk = {
439 .name = "apb_pclk",
440};
Russell King3126c7b2010-07-15 11:01:17 +0100441
Rabin Vincent1df20af2010-03-01 05:07:47 +0100442static struct clk_lookup u8500_common_clks[] = {
Russell King3126c7b2010-07-15 11:01:17 +0100443 CLK(dummy_apb_pclk, NULL, "apb_pclk"),
444
Rabin Vincent1df20af2010-03-01 05:07:47 +0100445 /* Peripheral Cluster #1 */
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100446 CLK(gpio0, "gpio.0", NULL),
447 CLK(gpio0, "gpio.1", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100448 CLK(slimbus0, "slimbus0", NULL),
449 CLK(i2c2, "nmk-i2c.2", NULL),
450 CLK(sdi0, "sdi0", NULL),
451 CLK(msp0, "msp0", NULL),
452 CLK(i2c1, "nmk-i2c.1", NULL),
453 CLK(uart1, "uart1", NULL),
454 CLK(uart0, "uart0", NULL),
455
456 /* Peripheral Cluster #3 */
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100457 CLK(gpio2, "gpio.2", NULL),
458 CLK(gpio2, "gpio.3", NULL),
459 CLK(gpio2, "gpio.4", NULL),
460 CLK(gpio2, "gpio.5", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100461 CLK(sdi5, "sdi5", NULL),
462 CLK(uart2, "uart2", NULL),
463 CLK(ske, "ske", NULL),
Sundar Iyer4c61c842010-09-29 19:43:09 -0700464 CLK(ske, "nmk-ske-keypad", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100465 CLK(sdi2, "sdi2", NULL),
466 CLK(i2c0, "nmk-i2c.0", NULL),
467 CLK(fsmc, "fsmc", NULL),
468
469 /* Peripheral Cluster #5 */
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100470 CLK(gpio3, "gpio.8", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100471
472 /* Peripheral Cluster #6 */
473 CLK(hash1, "hash1", NULL),
474 CLK(pka, "pka", NULL),
475 CLK(hash0, "hash0", NULL),
476 CLK(cryp0, "cryp0", NULL),
477
478 /* PRCMU level clock gating */
479
480 /* Bank 0 */
481 CLK(svaclk, "sva", NULL),
482 CLK(siaclk, "sia", NULL),
483 CLK(sgaclk, "sga", NULL),
484 CLK(slimclk, "slim", NULL),
485 CLK(lcdclk, "lcd", NULL),
486 CLK(bmlclk, "bml", NULL),
487 CLK(hsitxclk, "stm-hsi.0", NULL),
488 CLK(hsirxclk, "stm-hsi.1", NULL),
489 CLK(hdmiclk, "hdmi", NULL),
490 CLK(apeatclk, "apeat", NULL),
491 CLK(apetraceclk, "apetrace", NULL),
492 CLK(mcdeclk, "mcde", NULL),
493 CLK(ipi2clk, "ipi2", NULL),
Linus Walleij7b8ddb02010-05-27 15:21:26 -0700494 CLK(dmaclk, "dma40.0", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100495 CLK(b2r2clk, "b2r2", NULL),
496 CLK(tvclk, "tv", NULL),
497};
498
499static struct clk_lookup u8500_ed_clks[] = {
500 /* Peripheral Cluster #1 */
501 CLK(spi3_ed, "spi3", NULL),
502 CLK(msp1_ed, "msp1", NULL),
503
504 /* Peripheral Cluster #2 */
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100505 CLK(gpio1_ed, "gpio.6", NULL),
506 CLK(gpio1_ed, "gpio.7", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100507 CLK(ssitx_ed, "ssitx", NULL),
508 CLK(ssirx_ed, "ssirx", NULL),
509 CLK(spi0_ed, "spi0", NULL),
510 CLK(sdi3_ed, "sdi3", NULL),
511 CLK(sdi1_ed, "sdi1", NULL),
512 CLK(msp2_ed, "msp2", NULL),
513 CLK(sdi4_ed, "sdi4", NULL),
514 CLK(pwl_ed, "pwl", NULL),
515 CLK(spi1_ed, "spi1", NULL),
516 CLK(spi2_ed, "spi2", NULL),
517 CLK(i2c3_ed, "nmk-i2c.3", NULL),
518
519 /* Peripheral Cluster #3 */
520 CLK(ssp1_ed, "ssp1", NULL),
521 CLK(ssp0_ed, "ssp0", NULL),
522
523 /* Peripheral Cluster #5 */
Mian Yousaf Kaukab7f0709e2011-01-21 18:05:40 +0100524 CLK(usb_ed, "musb-ux500.0", "usb"),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100525
526 /* Peripheral Cluster #6 */
527 CLK(dmc_ed, "dmc", NULL),
528 CLK(cryp1_ed, "cryp1", NULL),
529 CLK(rng_ed, "rng", NULL),
530
531 /* Peripheral Cluster #7 */
532 CLK(tzpc0_ed, "tzpc0", NULL),
533 CLK(mtu1_ed, "mtu1", NULL),
534 CLK(mtu0_ed, "mtu0", NULL),
535 CLK(wdg_ed, "wdg", NULL),
536 CLK(cfgreg_ed, "cfgreg", NULL),
537};
538
539static struct clk_lookup u8500_v1_clks[] = {
540 /* Peripheral Cluster #1 */
Sundar Iyer592b2f22010-12-03 20:35:52 +0530541 CLK(i2c4, "nmk-i2c.4", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100542 CLK(spi3_v1, "spi3", NULL),
543 CLK(msp1_v1, "msp1", NULL),
544
545 /* Peripheral Cluster #2 */
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100546 CLK(gpio1_v1, "gpio.6", NULL),
547 CLK(gpio1_v1, "gpio.7", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100548 CLK(ssitx_v1, "ssitx", NULL),
549 CLK(ssirx_v1, "ssirx", NULL),
550 CLK(spi0_v1, "spi0", NULL),
551 CLK(sdi3_v1, "sdi3", NULL),
552 CLK(sdi1_v1, "sdi1", NULL),
553 CLK(msp2_v1, "msp2", NULL),
554 CLK(sdi4_v1, "sdi4", NULL),
555 CLK(pwl_v1, "pwl", NULL),
556 CLK(spi1_v1, "spi1", NULL),
557 CLK(spi2_v1, "spi2", NULL),
558 CLK(i2c3_v1, "nmk-i2c.3", NULL),
559
560 /* Peripheral Cluster #3 */
561 CLK(ssp1_v1, "ssp1", NULL),
562 CLK(ssp0_v1, "ssp0", NULL),
563
564 /* Peripheral Cluster #5 */
Mian Yousaf Kaukab7f0709e2011-01-21 18:05:40 +0100565 CLK(usb_v1, "musb-ux500.0", "usb"),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100566
567 /* Peripheral Cluster #6 */
568 CLK(mtu1_v1, "mtu1", NULL),
569 CLK(mtu0_v1, "mtu0", NULL),
570 CLK(cfgreg_v1, "cfgreg", NULL),
571 CLK(hash1, "hash1", NULL),
572 CLK(unipro_v1, "unipro", NULL),
573 CLK(rng_v1, "rng", NULL),
574
575 /* PRCMU level clock gating */
576
577 /* Bank 0 */
578 CLK(uniproclk, "uniproclk", NULL),
579 CLK(dsialtclk, "dsialt", NULL),
580
581 /* Bank 1 */
582 CLK(rngclk, "rng", NULL),
583 CLK(uiccclk, "uicc", NULL),
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100584};
585
Vincent Guittot763eef82010-12-03 18:18:39 +0100586#ifdef CONFIG_DEBUG_FS
587/*
588 * debugfs support to trace clock tree hierarchy and attributes with
589 * powerdebug
590 */
591static struct dentry *clk_debugfs_root;
592
593void __init clk_debugfs_add_table(struct clk_lookup *cl, size_t num)
594{
595 while (num--) {
596 /* Check that the clock has not been already registered */
597 if (!(cl->clk->list.prev != cl->clk->list.next))
598 list_add_tail(&cl->clk->list, &clk_list);
599
600 cl++;
601 }
602}
603
604static ssize_t usecount_dbg_read(struct file *file, char __user *buf,
605 size_t size, loff_t *off)
606{
607 struct clk *clk = file->f_dentry->d_inode->i_private;
608 char cusecount[128];
609 unsigned int len;
610
611 len = sprintf(cusecount, "%u\n", clk->enabled);
612 return simple_read_from_buffer(buf, size, off, cusecount, len);
613}
614
615static ssize_t rate_dbg_read(struct file *file, char __user *buf,
616 size_t size, loff_t *off)
617{
618 struct clk *clk = file->f_dentry->d_inode->i_private;
619 char crate[128];
620 unsigned int rate;
621 unsigned int len;
622
623 rate = clk_get_rate(clk);
624 len = sprintf(crate, "%u\n", rate);
625 return simple_read_from_buffer(buf, size, off, crate, len);
626}
627
628static const struct file_operations usecount_fops = {
629 .read = usecount_dbg_read,
630};
631
632static const struct file_operations set_rate_fops = {
633 .read = rate_dbg_read,
634};
635
636static struct dentry *clk_debugfs_register_dir(struct clk *c,
637 struct dentry *p_dentry)
638{
Al Viro12520c42011-07-16 12:37:57 -0400639 struct dentry *d, *clk_d;
Al Viroc066b652011-07-16 12:41:29 -0400640 const char *p = c->name;
Vincent Guittot763eef82010-12-03 18:18:39 +0100641
Al Viroc066b652011-07-16 12:41:29 -0400642 if (!p)
643 p = "BUG";
Vincent Guittot763eef82010-12-03 18:18:39 +0100644
Al Viroc066b652011-07-16 12:41:29 -0400645 clk_d = debugfs_create_dir(p, p_dentry);
Vincent Guittot763eef82010-12-03 18:18:39 +0100646 if (!clk_d)
647 return NULL;
648
649 d = debugfs_create_file("usecount", S_IRUGO,
650 clk_d, c, &usecount_fops);
651 if (!d)
652 goto err_out;
653 d = debugfs_create_file("rate", S_IRUGO,
654 clk_d, c, &set_rate_fops);
655 if (!d)
656 goto err_out;
657 /*
658 * TODO : not currently available in ux500
659 * d = debugfs_create_x32("flags", S_IRUGO, clk_d, (u32 *)&c->flags);
660 * if (!d)
661 * goto err_out;
662 */
663
664 return clk_d;
665
666err_out:
Al Viro12520c42011-07-16 12:37:57 -0400667 debugfs_remove_recursive(clk_d);
Vincent Guittot763eef82010-12-03 18:18:39 +0100668 return NULL;
669}
670
Vincent Guittot763eef82010-12-03 18:18:39 +0100671static int clk_debugfs_register_one(struct clk *c)
672{
673 struct clk *pa = c->parent_periph;
674 struct clk *bpa = c->parent_cluster;
675
676 if (!(bpa && !pa)) {
677 c->dent = clk_debugfs_register_dir(c,
678 pa ? pa->dent : clk_debugfs_root);
679 if (!c->dent)
680 return -ENOMEM;
681 }
682
683 if (bpa) {
684 c->dent_bus = clk_debugfs_register_dir(c,
685 bpa->dent_bus ? bpa->dent_bus : bpa->dent);
686 if ((!c->dent_bus) && (c->dent)) {
Al Viro12520c42011-07-16 12:37:57 -0400687 debugfs_remove_recursive(c->dent);
Vincent Guittot763eef82010-12-03 18:18:39 +0100688 c->dent = NULL;
689 return -ENOMEM;
690 }
691 }
692 return 0;
693}
694
695static int clk_debugfs_register(struct clk *c)
696{
697 int err;
698 struct clk *pa = c->parent_periph;
699 struct clk *bpa = c->parent_cluster;
700
701 if (pa && (!pa->dent && !pa->dent_bus)) {
702 err = clk_debugfs_register(pa);
703 if (err)
704 return err;
705 }
706
707 if (bpa && (!bpa->dent && !bpa->dent_bus)) {
708 err = clk_debugfs_register(bpa);
709 if (err)
710 return err;
711 }
712
713 if ((!c->dent) && (!c->dent_bus)) {
714 err = clk_debugfs_register_one(c);
715 if (err)
716 return err;
717 }
718 return 0;
719}
720
721static int __init clk_debugfs_init(void)
722{
723 struct clk *c;
724 struct dentry *d;
725 int err;
726
727 d = debugfs_create_dir("clock", NULL);
728 if (!d)
729 return -ENOMEM;
730 clk_debugfs_root = d;
731
732 list_for_each_entry(c, &clk_list, list) {
733 err = clk_debugfs_register(c);
734 if (err)
735 goto err_out;
736 }
737 return 0;
738err_out:
739 debugfs_remove_recursive(clk_debugfs_root);
740 return err;
741}
742
743late_initcall(clk_debugfs_init);
744#endif /* defined(CONFIG_DEBUG_FS) */
745
Linus Walleijef7a4742011-06-01 14:44:16 +0200746unsigned long clk_smp_twd_rate = 400000000;
747
748unsigned long clk_smp_twd_get_rate(struct clk *clk)
749{
750 return clk_smp_twd_rate;
751}
752
753static struct clk clk_smp_twd = {
754 .get_rate = clk_smp_twd_get_rate,
755 .name = "smp_twd",
756};
757
758static struct clk_lookup clk_smp_twd_lookup = {
759 .dev_id = "smp_twd",
760 .clk = &clk_smp_twd,
761};
762
763#ifdef CONFIG_CPU_FREQ
764
765static int clk_twd_cpufreq_transition(struct notifier_block *nb,
766 unsigned long state, void *data)
767{
768 struct cpufreq_freqs *f = data;
769
770 if (state == CPUFREQ_PRECHANGE) {
771 /* Save frequency in simple Hz */
772 clk_smp_twd_rate = f->new * 1000;
773 }
774
775 return NOTIFY_OK;
776}
777
778static struct notifier_block clk_twd_cpufreq_nb = {
779 .notifier_call = clk_twd_cpufreq_transition,
780};
781
782static int clk_init_smp_twd_cpufreq(void)
783{
784 return cpufreq_register_notifier(&clk_twd_cpufreq_nb,
785 CPUFREQ_TRANSITION_NOTIFIER);
786}
787late_initcall(clk_init_smp_twd_cpufreq);
788
789#endif
790
Linus Walleijba327b12010-05-26 07:38:54 +0100791int __init clk_init(void)
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100792{
Rabin Vincent1df20af2010-03-01 05:07:47 +0100793 if (cpu_is_u8500ed()) {
794 clk_prcmu_ops.enable = clk_prcmu_ed_enable;
795 clk_prcmu_ops.disable = clk_prcmu_ed_disable;
Linus Walleijba327b12010-05-26 07:38:54 +0100796 clk_per6clk.rate = 100000000;
Rabin Vincent591d8dd2010-05-03 08:46:51 +0100797 } else if (cpu_is_u5500()) {
798 /* Clock tree for U5500 not implemented yet */
799 clk_prcc_ops.enable = clk_prcc_ops.disable = NULL;
800 clk_prcmu_ops.enable = clk_prcmu_ops.disable = NULL;
Per Forlinbab263e2010-12-05 12:49:03 +0100801 clk_uartclk.rate = 36360000;
802 clk_sdmmcclk.rate = 99900000;
Rabin Vincent1df20af2010-03-01 05:07:47 +0100803 }
804
805 clkdev_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks));
806 if (cpu_is_u8500ed())
807 clkdev_add_table(u8500_ed_clks, ARRAY_SIZE(u8500_ed_clks));
808 else
809 clkdev_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks));
810
Linus Walleijef7a4742011-06-01 14:44:16 +0200811 clkdev_add(&clk_smp_twd_lookup);
812
Vincent Guittot763eef82010-12-03 18:18:39 +0100813#ifdef CONFIG_DEBUG_FS
814 clk_debugfs_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks));
815 if (cpu_is_u8500ed())
816 clk_debugfs_add_table(u8500_ed_clks, ARRAY_SIZE(u8500_ed_clks));
817 else
818 clk_debugfs_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks));
819#endif
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100820 return 0;
821}