blob: ec35f0aa5665a99d23f11c73ec552ab6e83f3aca [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
Ola Lilja25cb3b42012-01-30 15:18:14 +0100226int clk_set_parent(struct clk *clk, struct clk *parent)
227{
228 /*TODO*/
229 return -ENOSYS;
230}
231EXPORT_SYMBOL(clk_set_parent);
232
Rabin Vincent1df20af2010-03-01 05:07:47 +0100233static void clk_prcmu_enable(struct clk *clk)
234{
235 void __iomem *cg_set_reg = __io_address(U8500_PRCMU_BASE)
236 + PRCM_YYCLKEN0_MGT_SET + clk->prcmu_cg_off;
237
238 writel(1 << clk->prcmu_cg_bit, cg_set_reg);
239}
240
241static void clk_prcmu_disable(struct clk *clk)
242{
243 void __iomem *cg_clr_reg = __io_address(U8500_PRCMU_BASE)
244 + PRCM_YYCLKEN0_MGT_CLR + clk->prcmu_cg_off;
245
246 writel(1 << clk->prcmu_cg_bit, cg_clr_reg);
247}
248
Rabin Vincent1df20af2010-03-01 05:07:47 +0100249static struct clkops clk_prcmu_ops = {
250 .enable = clk_prcmu_enable,
251 .disable = clk_prcmu_disable,
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100252};
253
Rabin Vincent1df20af2010-03-01 05:07:47 +0100254static unsigned int clkrst_base[] = {
255 [1] = U8500_CLKRST1_BASE,
256 [2] = U8500_CLKRST2_BASE,
257 [3] = U8500_CLKRST3_BASE,
258 [5] = U8500_CLKRST5_BASE,
259 [6] = U8500_CLKRST6_BASE,
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100260};
261
Rabin Vincent1df20af2010-03-01 05:07:47 +0100262static void clk_prcc_enable(struct clk *clk)
263{
264 void __iomem *addr = __io_address(clkrst_base[clk->cluster]);
265
266 if (clk->prcc_kernel != -1)
267 writel(1 << clk->prcc_kernel, addr + PRCC_KCKEN);
268
269 if (clk->prcc_bus != -1)
270 writel(1 << clk->prcc_bus, addr + PRCC_PCKEN);
271}
272
273static void clk_prcc_disable(struct clk *clk)
274{
275 void __iomem *addr = __io_address(clkrst_base[clk->cluster]);
276
277 if (clk->prcc_bus != -1)
278 writel(1 << clk->prcc_bus, addr + PRCC_PCKDIS);
279
280 if (clk->prcc_kernel != -1)
281 writel(1 << clk->prcc_kernel, addr + PRCC_KCKDIS);
282}
283
284static struct clkops clk_prcc_ops = {
285 .enable = clk_prcc_enable,
286 .disable = clk_prcc_disable,
287};
288
289static struct clk clk_32khz = {
Vincent Guittot763eef82010-12-03 18:18:39 +0100290 .name = "clk_32khz",
Rabin Vincent1df20af2010-03-01 05:07:47 +0100291 .rate = 32000,
292};
293
294/*
295 * PRCMU level clock gating
296 */
297
298/* Bank 0 */
299static DEFINE_PRCMU_CLK(svaclk, 0x0, 2, SVAMMDSPCLK);
300static DEFINE_PRCMU_CLK(siaclk, 0x0, 3, SIAMMDSPCLK);
301static DEFINE_PRCMU_CLK(sgaclk, 0x0, 4, SGACLK);
302static DEFINE_PRCMU_CLK_RATE(uartclk, 0x0, 5, UARTCLK, 38400000);
303static DEFINE_PRCMU_CLK(msp02clk, 0x0, 6, MSP02CLK);
304static DEFINE_PRCMU_CLK(msp1clk, 0x0, 7, MSP1CLK); /* v1 */
305static DEFINE_PRCMU_CLK_RATE(i2cclk, 0x0, 8, I2CCLK, 48000000);
Philippe Langlaisfbdc6d12011-01-27 14:37:07 +0100306static DEFINE_PRCMU_CLK_RATE(sdmmcclk, 0x0, 9, SDMMCCLK, 100000000);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100307static DEFINE_PRCMU_CLK(slimclk, 0x0, 10, SLIMCLK);
308static DEFINE_PRCMU_CLK(per1clk, 0x0, 11, PER1CLK);
309static DEFINE_PRCMU_CLK(per2clk, 0x0, 12, PER2CLK);
310static DEFINE_PRCMU_CLK(per3clk, 0x0, 13, PER3CLK);
311static DEFINE_PRCMU_CLK(per5clk, 0x0, 14, PER5CLK);
312static DEFINE_PRCMU_CLK_RATE(per6clk, 0x0, 15, PER6CLK, 133330000);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100313static DEFINE_PRCMU_CLK(lcdclk, 0x0, 17, LCDCLK);
314static DEFINE_PRCMU_CLK(bmlclk, 0x0, 18, BMLCLK);
315static DEFINE_PRCMU_CLK(hsitxclk, 0x0, 19, HSITXCLK);
316static DEFINE_PRCMU_CLK(hsirxclk, 0x0, 20, HSIRXCLK);
317static DEFINE_PRCMU_CLK(hdmiclk, 0x0, 21, HDMICLK);
318static DEFINE_PRCMU_CLK(apeatclk, 0x0, 22, APEATCLK);
319static DEFINE_PRCMU_CLK(apetraceclk, 0x0, 23, APETRACECLK);
320static DEFINE_PRCMU_CLK(mcdeclk, 0x0, 24, MCDECLK);
321static DEFINE_PRCMU_CLK(ipi2clk, 0x0, 25, IPI2CCLK);
322static DEFINE_PRCMU_CLK(dsialtclk, 0x0, 26, DSIALTCLK); /* v1 */
323static DEFINE_PRCMU_CLK(dmaclk, 0x0, 27, DMACLK);
324static DEFINE_PRCMU_CLK(b2r2clk, 0x0, 28, B2R2CLK);
325static DEFINE_PRCMU_CLK(tvclk, 0x0, 29, TVCLK);
326static DEFINE_PRCMU_CLK(uniproclk, 0x0, 30, UNIPROCLK); /* v1 */
327static DEFINE_PRCMU_CLK_RATE(sspclk, 0x0, 31, SSPCLK, 48000000); /* v1 */
328
329/* Bank 1 */
330static DEFINE_PRCMU_CLK(rngclk, 0x4, 0, RNGCLK); /* v1 */
331static DEFINE_PRCMU_CLK(uiccclk, 0x4, 1, UICCCLK); /* v1 */
332
333/*
334 * PRCC level clock gating
335 * Format: per#, clk, PCKEN bit, KCKEN bit, parent
336 */
337
338/* Peripheral Cluster #1 */
Sundar Iyer592b2f22010-12-03 20:35:52 +0530339static DEFINE_PRCC_CLK(1, i2c4, 10, 9, &clk_i2cclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100340static DEFINE_PRCC_CLK(1, gpio0, 9, -1, NULL);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530341static DEFINE_PRCC_CLK(1, slimbus0, 8, 8, &clk_slimclk);
Linus Walleijc15def12011-12-15 13:38:40 +0100342static DEFINE_PRCC_CLK(1, spi3, 7, -1, NULL);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530343static DEFINE_PRCC_CLK(1, i2c2, 6, 6, &clk_i2cclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100344static DEFINE_PRCC_CLK(1, sdi0, 5, 5, &clk_sdmmcclk);
Linus Walleijc15def12011-12-15 13:38:40 +0100345static DEFINE_PRCC_CLK(1, msp1, 4, 4, &clk_msp1clk);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530346static DEFINE_PRCC_CLK(1, msp0, 3, 3, &clk_msp02clk);
347static DEFINE_PRCC_CLK(1, i2c1, 2, 2, &clk_i2cclk);
348static DEFINE_PRCC_CLK(1, uart1, 1, 1, &clk_uartclk);
349static DEFINE_PRCC_CLK(1, uart0, 0, 0, &clk_uartclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100350
351/* Peripheral Cluster #2 */
Linus Walleijc15def12011-12-15 13:38:40 +0100352static DEFINE_PRCC_CLK(2, gpio1, 11, -1, NULL);
353static DEFINE_PRCC_CLK(2, ssitx, 10, 7, NULL);
354static DEFINE_PRCC_CLK(2, ssirx, 9, 6, NULL);
355static DEFINE_PRCC_CLK(2, spi0, 8, -1, NULL);
356static DEFINE_PRCC_CLK(2, sdi3, 7, 5, &clk_sdmmcclk);
357static DEFINE_PRCC_CLK(2, sdi1, 6, 4, &clk_sdmmcclk);
358static DEFINE_PRCC_CLK(2, msp2, 5, 3, &clk_msp02clk);
359static DEFINE_PRCC_CLK(2, sdi4, 4, 2, &clk_sdmmcclk);
360static DEFINE_PRCC_CLK(2, pwl, 3, 1, NULL);
361static DEFINE_PRCC_CLK(2, spi1, 2, -1, NULL);
362static DEFINE_PRCC_CLK(2, spi2, 1, -1, NULL);
363static DEFINE_PRCC_CLK(2, i2c3, 0, 0, &clk_i2cclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100364
365/* Peripheral Cluster #3 */
Sundar Iyer592b2f22010-12-03 20:35:52 +0530366static DEFINE_PRCC_CLK(3, gpio2, 8, -1, NULL);
367static DEFINE_PRCC_CLK(3, sdi5, 7, 7, &clk_sdmmcclk);
368static DEFINE_PRCC_CLK(3, uart2, 6, 6, &clk_uartclk);
369static DEFINE_PRCC_CLK(3, ske, 5, 5, &clk_32khz);
370static DEFINE_PRCC_CLK(3, sdi2, 4, 4, &clk_sdmmcclk);
371static DEFINE_PRCC_CLK(3, i2c0, 3, 3, &clk_i2cclk);
Linus Walleijc15def12011-12-15 13:38:40 +0100372static DEFINE_PRCC_CLK(3, ssp1, 2, 2, &clk_sspclk);
373static DEFINE_PRCC_CLK(3, ssp0, 1, 1, &clk_sspclk);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530374static DEFINE_PRCC_CLK(3, fsmc, 0, -1, NULL);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100375
376/* Peripheral Cluster #4 is in the always on domain */
377
378/* Peripheral Cluster #5 */
Sundar Iyer592b2f22010-12-03 20:35:52 +0530379static DEFINE_PRCC_CLK(5, gpio3, 1, -1, NULL);
Linus Walleijc15def12011-12-15 13:38:40 +0100380static DEFINE_PRCC_CLK(5, usb, 0, 0, NULL);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100381
382/* Peripheral Cluster #6 */
383
Linus Walleijba327b12010-05-26 07:38:54 +0100384/* MTU ID in data */
Linus Walleijc15def12011-12-15 13:38:40 +0100385static DEFINE_PRCC_CLK_CUSTOM(6, mtu1, 8, -1, NULL, clk_mtu_get_rate, 1);
386static DEFINE_PRCC_CLK_CUSTOM(6, mtu0, 7, -1, NULL, clk_mtu_get_rate, 0);
387static DEFINE_PRCC_CLK(6, cfgreg, 6, 6, NULL);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530388static DEFINE_PRCC_CLK(6, hash1, 5, -1, NULL);
Linus Walleijc15def12011-12-15 13:38:40 +0100389static DEFINE_PRCC_CLK(6, unipro, 4, 1, &clk_uniproclk);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530390static DEFINE_PRCC_CLK(6, pka, 3, -1, NULL);
391static DEFINE_PRCC_CLK(6, hash0, 2, -1, NULL);
392static DEFINE_PRCC_CLK(6, cryp0, 1, -1, NULL);
Linus Walleijc15def12011-12-15 13:38:40 +0100393static DEFINE_PRCC_CLK(6, rng, 0, 0, &clk_rngclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100394
Vincent Guittot763eef82010-12-03 18:18:39 +0100395static struct clk clk_dummy_apb_pclk = {
396 .name = "apb_pclk",
397};
Russell King3126c7b2010-07-15 11:01:17 +0100398
Linus Walleijc15def12011-12-15 13:38:40 +0100399static struct clk_lookup u8500_clks[] = {
Russell King3126c7b2010-07-15 11:01:17 +0100400 CLK(dummy_apb_pclk, NULL, "apb_pclk"),
401
Rabin Vincent1df20af2010-03-01 05:07:47 +0100402 /* Peripheral Cluster #1 */
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100403 CLK(gpio0, "gpio.0", NULL),
404 CLK(gpio0, "gpio.1", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100405 CLK(slimbus0, "slimbus0", NULL),
406 CLK(i2c2, "nmk-i2c.2", NULL),
407 CLK(sdi0, "sdi0", NULL),
408 CLK(msp0, "msp0", NULL),
409 CLK(i2c1, "nmk-i2c.1", NULL),
410 CLK(uart1, "uart1", NULL),
411 CLK(uart0, "uart0", NULL),
412
413 /* Peripheral Cluster #3 */
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100414 CLK(gpio2, "gpio.2", NULL),
415 CLK(gpio2, "gpio.3", NULL),
416 CLK(gpio2, "gpio.4", NULL),
417 CLK(gpio2, "gpio.5", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100418 CLK(sdi5, "sdi5", NULL),
419 CLK(uart2, "uart2", NULL),
420 CLK(ske, "ske", NULL),
Sundar Iyer4c61c842010-09-29 19:43:09 -0700421 CLK(ske, "nmk-ske-keypad", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100422 CLK(sdi2, "sdi2", NULL),
423 CLK(i2c0, "nmk-i2c.0", NULL),
424 CLK(fsmc, "fsmc", NULL),
425
426 /* Peripheral Cluster #5 */
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100427 CLK(gpio3, "gpio.8", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100428
429 /* Peripheral Cluster #6 */
430 CLK(hash1, "hash1", NULL),
431 CLK(pka, "pka", NULL),
432 CLK(hash0, "hash0", NULL),
433 CLK(cryp0, "cryp0", NULL),
434
435 /* PRCMU level clock gating */
436
437 /* Bank 0 */
438 CLK(svaclk, "sva", NULL),
439 CLK(siaclk, "sia", NULL),
440 CLK(sgaclk, "sga", NULL),
441 CLK(slimclk, "slim", NULL),
442 CLK(lcdclk, "lcd", NULL),
443 CLK(bmlclk, "bml", NULL),
444 CLK(hsitxclk, "stm-hsi.0", NULL),
445 CLK(hsirxclk, "stm-hsi.1", NULL),
446 CLK(hdmiclk, "hdmi", NULL),
447 CLK(apeatclk, "apeat", NULL),
448 CLK(apetraceclk, "apetrace", NULL),
449 CLK(mcdeclk, "mcde", NULL),
450 CLK(ipi2clk, "ipi2", NULL),
Linus Walleij7b8ddb02010-05-27 15:21:26 -0700451 CLK(dmaclk, "dma40.0", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100452 CLK(b2r2clk, "b2r2", NULL),
453 CLK(tvclk, "tv", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100454
Rabin Vincent1df20af2010-03-01 05:07:47 +0100455 /* Peripheral Cluster #1 */
Sundar Iyer592b2f22010-12-03 20:35:52 +0530456 CLK(i2c4, "nmk-i2c.4", NULL),
Linus Walleijc15def12011-12-15 13:38:40 +0100457 CLK(spi3, "spi3", NULL),
458 CLK(msp1, "msp1", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100459
460 /* Peripheral Cluster #2 */
Linus Walleijc15def12011-12-15 13:38:40 +0100461 CLK(gpio1, "gpio.6", NULL),
462 CLK(gpio1, "gpio.7", NULL),
463 CLK(ssitx, "ssitx", NULL),
464 CLK(ssirx, "ssirx", NULL),
465 CLK(spi0, "spi0", NULL),
466 CLK(sdi3, "sdi3", NULL),
467 CLK(sdi1, "sdi1", NULL),
468 CLK(msp2, "msp2", NULL),
469 CLK(sdi4, "sdi4", NULL),
470 CLK(pwl, "pwl", NULL),
471 CLK(spi1, "spi1", NULL),
472 CLK(spi2, "spi2", NULL),
473 CLK(i2c3, "nmk-i2c.3", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100474
475 /* Peripheral Cluster #3 */
Linus Walleijc15def12011-12-15 13:38:40 +0100476 CLK(ssp1, "ssp1", NULL),
477 CLK(ssp0, "ssp0", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100478
479 /* Peripheral Cluster #5 */
Linus Walleijc15def12011-12-15 13:38:40 +0100480 CLK(usb, "musb-ux500.0", "usb"),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100481
482 /* Peripheral Cluster #6 */
Linus Walleijc15def12011-12-15 13:38:40 +0100483 CLK(mtu1, "mtu1", NULL),
484 CLK(mtu0, "mtu0", NULL),
485 CLK(cfgreg, "cfgreg", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100486 CLK(hash1, "hash1", NULL),
Linus Walleijc15def12011-12-15 13:38:40 +0100487 CLK(unipro, "unipro", NULL),
488 CLK(rng, "rng", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100489
490 /* PRCMU level clock gating */
491
492 /* Bank 0 */
493 CLK(uniproclk, "uniproclk", NULL),
494 CLK(dsialtclk, "dsialt", NULL),
495
496 /* Bank 1 */
497 CLK(rngclk, "rng", NULL),
498 CLK(uiccclk, "uicc", NULL),
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100499};
500
Vincent Guittot763eef82010-12-03 18:18:39 +0100501#ifdef CONFIG_DEBUG_FS
502/*
503 * debugfs support to trace clock tree hierarchy and attributes with
504 * powerdebug
505 */
506static struct dentry *clk_debugfs_root;
507
508void __init clk_debugfs_add_table(struct clk_lookup *cl, size_t num)
509{
510 while (num--) {
511 /* Check that the clock has not been already registered */
512 if (!(cl->clk->list.prev != cl->clk->list.next))
513 list_add_tail(&cl->clk->list, &clk_list);
514
515 cl++;
516 }
517}
518
519static ssize_t usecount_dbg_read(struct file *file, char __user *buf,
520 size_t size, loff_t *off)
521{
522 struct clk *clk = file->f_dentry->d_inode->i_private;
523 char cusecount[128];
524 unsigned int len;
525
526 len = sprintf(cusecount, "%u\n", clk->enabled);
527 return simple_read_from_buffer(buf, size, off, cusecount, len);
528}
529
530static ssize_t rate_dbg_read(struct file *file, char __user *buf,
531 size_t size, loff_t *off)
532{
533 struct clk *clk = file->f_dentry->d_inode->i_private;
534 char crate[128];
535 unsigned int rate;
536 unsigned int len;
537
538 rate = clk_get_rate(clk);
539 len = sprintf(crate, "%u\n", rate);
540 return simple_read_from_buffer(buf, size, off, crate, len);
541}
542
543static const struct file_operations usecount_fops = {
544 .read = usecount_dbg_read,
545};
546
547static const struct file_operations set_rate_fops = {
548 .read = rate_dbg_read,
549};
550
551static struct dentry *clk_debugfs_register_dir(struct clk *c,
552 struct dentry *p_dentry)
553{
Al Viro12520c42011-07-16 12:37:57 -0400554 struct dentry *d, *clk_d;
Al Viroc066b652011-07-16 12:41:29 -0400555 const char *p = c->name;
Vincent Guittot763eef82010-12-03 18:18:39 +0100556
Al Viroc066b652011-07-16 12:41:29 -0400557 if (!p)
558 p = "BUG";
Vincent Guittot763eef82010-12-03 18:18:39 +0100559
Al Viroc066b652011-07-16 12:41:29 -0400560 clk_d = debugfs_create_dir(p, p_dentry);
Vincent Guittot763eef82010-12-03 18:18:39 +0100561 if (!clk_d)
562 return NULL;
563
564 d = debugfs_create_file("usecount", S_IRUGO,
565 clk_d, c, &usecount_fops);
566 if (!d)
567 goto err_out;
568 d = debugfs_create_file("rate", S_IRUGO,
569 clk_d, c, &set_rate_fops);
570 if (!d)
571 goto err_out;
572 /*
573 * TODO : not currently available in ux500
574 * d = debugfs_create_x32("flags", S_IRUGO, clk_d, (u32 *)&c->flags);
575 * if (!d)
576 * goto err_out;
577 */
578
579 return clk_d;
580
581err_out:
Al Viro12520c42011-07-16 12:37:57 -0400582 debugfs_remove_recursive(clk_d);
Vincent Guittot763eef82010-12-03 18:18:39 +0100583 return NULL;
584}
585
Vincent Guittot763eef82010-12-03 18:18:39 +0100586static int clk_debugfs_register_one(struct clk *c)
587{
588 struct clk *pa = c->parent_periph;
589 struct clk *bpa = c->parent_cluster;
590
591 if (!(bpa && !pa)) {
592 c->dent = clk_debugfs_register_dir(c,
593 pa ? pa->dent : clk_debugfs_root);
594 if (!c->dent)
595 return -ENOMEM;
596 }
597
598 if (bpa) {
599 c->dent_bus = clk_debugfs_register_dir(c,
600 bpa->dent_bus ? bpa->dent_bus : bpa->dent);
601 if ((!c->dent_bus) && (c->dent)) {
Al Viro12520c42011-07-16 12:37:57 -0400602 debugfs_remove_recursive(c->dent);
Vincent Guittot763eef82010-12-03 18:18:39 +0100603 c->dent = NULL;
604 return -ENOMEM;
605 }
606 }
607 return 0;
608}
609
610static int clk_debugfs_register(struct clk *c)
611{
612 int err;
613 struct clk *pa = c->parent_periph;
614 struct clk *bpa = c->parent_cluster;
615
616 if (pa && (!pa->dent && !pa->dent_bus)) {
617 err = clk_debugfs_register(pa);
618 if (err)
619 return err;
620 }
621
622 if (bpa && (!bpa->dent && !bpa->dent_bus)) {
623 err = clk_debugfs_register(bpa);
624 if (err)
625 return err;
626 }
627
628 if ((!c->dent) && (!c->dent_bus)) {
629 err = clk_debugfs_register_one(c);
630 if (err)
631 return err;
632 }
633 return 0;
634}
635
636static int __init clk_debugfs_init(void)
637{
638 struct clk *c;
639 struct dentry *d;
640 int err;
641
642 d = debugfs_create_dir("clock", NULL);
643 if (!d)
644 return -ENOMEM;
645 clk_debugfs_root = d;
646
647 list_for_each_entry(c, &clk_list, list) {
648 err = clk_debugfs_register(c);
649 if (err)
650 goto err_out;
651 }
652 return 0;
653err_out:
654 debugfs_remove_recursive(clk_debugfs_root);
655 return err;
656}
657
658late_initcall(clk_debugfs_init);
659#endif /* defined(CONFIG_DEBUG_FS) */
660
Linus Walleij10958432011-12-19 00:28:50 +0100661unsigned long clk_smp_twd_rate = 500000000;
Linus Walleijef7a4742011-06-01 14:44:16 +0200662
663unsigned long clk_smp_twd_get_rate(struct clk *clk)
664{
665 return clk_smp_twd_rate;
666}
667
668static struct clk clk_smp_twd = {
669 .get_rate = clk_smp_twd_get_rate,
670 .name = "smp_twd",
671};
672
673static struct clk_lookup clk_smp_twd_lookup = {
674 .dev_id = "smp_twd",
675 .clk = &clk_smp_twd,
676};
677
678#ifdef CONFIG_CPU_FREQ
679
680static int clk_twd_cpufreq_transition(struct notifier_block *nb,
681 unsigned long state, void *data)
682{
683 struct cpufreq_freqs *f = data;
684
685 if (state == CPUFREQ_PRECHANGE) {
686 /* Save frequency in simple Hz */
Linus Walleij10958432011-12-19 00:28:50 +0100687 clk_smp_twd_rate = (f->new * 1000) / 2;
Linus Walleijef7a4742011-06-01 14:44:16 +0200688 }
689
690 return NOTIFY_OK;
691}
692
693static struct notifier_block clk_twd_cpufreq_nb = {
694 .notifier_call = clk_twd_cpufreq_transition,
695};
696
697static int clk_init_smp_twd_cpufreq(void)
698{
699 return cpufreq_register_notifier(&clk_twd_cpufreq_nb,
700 CPUFREQ_TRANSITION_NOTIFIER);
701}
702late_initcall(clk_init_smp_twd_cpufreq);
703
704#endif
705
Linus Walleijba327b12010-05-26 07:38:54 +0100706int __init clk_init(void)
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100707{
Linus Walleijc15def12011-12-15 13:38:40 +0100708 if (cpu_is_u5500()) {
Rabin Vincent591d8dd2010-05-03 08:46:51 +0100709 /* Clock tree for U5500 not implemented yet */
710 clk_prcc_ops.enable = clk_prcc_ops.disable = NULL;
711 clk_prcmu_ops.enable = clk_prcmu_ops.disable = NULL;
Per Forlinbab263e2010-12-05 12:49:03 +0100712 clk_uartclk.rate = 36360000;
713 clk_sdmmcclk.rate = 99900000;
Rabin Vincent1df20af2010-03-01 05:07:47 +0100714 }
715
Linus Walleijc15def12011-12-15 13:38:40 +0100716 clkdev_add_table(u8500_clks, ARRAY_SIZE(u8500_clks));
Linus Walleijef7a4742011-06-01 14:44:16 +0200717 clkdev_add(&clk_smp_twd_lookup);
718
Vincent Guittot763eef82010-12-03 18:18:39 +0100719#ifdef CONFIG_DEBUG_FS
Linus Walleijc15def12011-12-15 13:38:40 +0100720 clk_debugfs_add_table(u8500_clks, ARRAY_SIZE(u8500_clks));
Vincent Guittot763eef82010-12-03 18:18:39 +0100721#endif
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100722 return 0;
723}