blob: 063f3dbd45a97abaa0154d13056e8f72b0dcf59a [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
Arnd Bergmann815aceb2012-05-14 16:29:32 +0200152 if (cpu_is_u8500_family())
Rabin Vincent92389ca2010-12-08 11:07:57 +0530153 addr = __io_address(U8500_PRCMU_BASE);
154 else
155 ux500_unknown_soc();
156
Sundar Iyerf3069542010-12-03 20:35:51 +0530157 /*
158 * On a startup, always conifgure the TCR to the doze mode;
159 * bootloaders do it for us. Do this in the kernel too.
160 */
Rabin Vincent92389ca2010-12-08 11:07:57 +0530161 writel(PRCM_TCR_DOZE_MODE, addr + PRCM_TCR);
Sundar Iyerf3069542010-12-03 20:35:51 +0530162
Rabin Vincent92389ca2010-12-08 11:07:57 +0530163 tcr = readl(addr + PRCM_TCR);
Sundar Iyerf3069542010-12-03 20:35:51 +0530164
Linus Walleijba327b12010-05-26 07:38:54 +0100165 /* Get the rate from the parent as a default */
166 if (clk->parent_periph)
167 mturate = clk_get_rate(clk->parent_periph);
168 else if (clk->parent_cluster)
169 mturate = clk_get_rate(clk->parent_cluster);
170 else
171 /* We need to be connected SOMEWHERE */
172 BUG();
173
Linus Walleijba327b12010-05-26 07:38:54 +0100174 /* Return the clock selected for this MTU */
175 if (tcr & (1 << mtu))
176 retclk = clk32k;
177 else
178 retclk = mturate;
179
180 pr_info("MTU%d clock rate: %lu Hz\n", mtu, retclk);
181 return retclk;
182}
183
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100184unsigned long clk_get_rate(struct clk *clk)
185{
Rabin Vincent1df20af2010-03-01 05:07:47 +0100186 unsigned long rate;
187
Linus Walleijba327b12010-05-26 07:38:54 +0100188 /*
189 * If there is a custom getrate callback for this clock,
190 * it will take precedence.
191 */
192 if (clk->get_rate)
193 return clk->get_rate(clk);
194
Rabin Vincent1df20af2010-03-01 05:07:47 +0100195 if (clk->ops && clk->ops->get_rate)
196 return clk->ops->get_rate(clk);
197
198 rate = clk->rate;
199 if (!rate) {
200 if (clk->parent_periph)
201 rate = clk_get_rate(clk->parent_periph);
202 else if (clk->parent_cluster)
203 rate = clk_get_rate(clk->parent_cluster);
204 }
205
206 return rate;
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100207}
208EXPORT_SYMBOL(clk_get_rate);
209
210long clk_round_rate(struct clk *clk, unsigned long rate)
211{
212 /*TODO*/
213 return rate;
214}
215EXPORT_SYMBOL(clk_round_rate);
216
217int clk_set_rate(struct clk *clk, unsigned long rate)
218{
219 clk->rate = rate;
220 return 0;
221}
222EXPORT_SYMBOL(clk_set_rate);
223
Ola Lilja25cb3b42012-01-30 15:18:14 +0100224int clk_set_parent(struct clk *clk, struct clk *parent)
225{
226 /*TODO*/
227 return -ENOSYS;
228}
229EXPORT_SYMBOL(clk_set_parent);
230
Rabin Vincent1df20af2010-03-01 05:07:47 +0100231static void clk_prcmu_enable(struct clk *clk)
232{
233 void __iomem *cg_set_reg = __io_address(U8500_PRCMU_BASE)
234 + PRCM_YYCLKEN0_MGT_SET + clk->prcmu_cg_off;
235
236 writel(1 << clk->prcmu_cg_bit, cg_set_reg);
237}
238
239static void clk_prcmu_disable(struct clk *clk)
240{
241 void __iomem *cg_clr_reg = __io_address(U8500_PRCMU_BASE)
242 + PRCM_YYCLKEN0_MGT_CLR + clk->prcmu_cg_off;
243
244 writel(1 << clk->prcmu_cg_bit, cg_clr_reg);
245}
246
Rabin Vincent1df20af2010-03-01 05:07:47 +0100247static struct clkops clk_prcmu_ops = {
248 .enable = clk_prcmu_enable,
249 .disable = clk_prcmu_disable,
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100250};
251
Rabin Vincent1df20af2010-03-01 05:07:47 +0100252static unsigned int clkrst_base[] = {
253 [1] = U8500_CLKRST1_BASE,
254 [2] = U8500_CLKRST2_BASE,
255 [3] = U8500_CLKRST3_BASE,
256 [5] = U8500_CLKRST5_BASE,
257 [6] = U8500_CLKRST6_BASE,
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100258};
259
Rabin Vincent1df20af2010-03-01 05:07:47 +0100260static void clk_prcc_enable(struct clk *clk)
261{
262 void __iomem *addr = __io_address(clkrst_base[clk->cluster]);
263
264 if (clk->prcc_kernel != -1)
265 writel(1 << clk->prcc_kernel, addr + PRCC_KCKEN);
266
267 if (clk->prcc_bus != -1)
268 writel(1 << clk->prcc_bus, addr + PRCC_PCKEN);
269}
270
271static void clk_prcc_disable(struct clk *clk)
272{
273 void __iomem *addr = __io_address(clkrst_base[clk->cluster]);
274
275 if (clk->prcc_bus != -1)
276 writel(1 << clk->prcc_bus, addr + PRCC_PCKDIS);
277
278 if (clk->prcc_kernel != -1)
279 writel(1 << clk->prcc_kernel, addr + PRCC_KCKDIS);
280}
281
282static struct clkops clk_prcc_ops = {
283 .enable = clk_prcc_enable,
284 .disable = clk_prcc_disable,
285};
286
287static struct clk clk_32khz = {
Vincent Guittot763eef82010-12-03 18:18:39 +0100288 .name = "clk_32khz",
Rabin Vincent1df20af2010-03-01 05:07:47 +0100289 .rate = 32000,
290};
291
292/*
293 * PRCMU level clock gating
294 */
295
296/* Bank 0 */
297static DEFINE_PRCMU_CLK(svaclk, 0x0, 2, SVAMMDSPCLK);
298static DEFINE_PRCMU_CLK(siaclk, 0x0, 3, SIAMMDSPCLK);
299static DEFINE_PRCMU_CLK(sgaclk, 0x0, 4, SGACLK);
300static DEFINE_PRCMU_CLK_RATE(uartclk, 0x0, 5, UARTCLK, 38400000);
301static DEFINE_PRCMU_CLK(msp02clk, 0x0, 6, MSP02CLK);
302static DEFINE_PRCMU_CLK(msp1clk, 0x0, 7, MSP1CLK); /* v1 */
303static DEFINE_PRCMU_CLK_RATE(i2cclk, 0x0, 8, I2CCLK, 48000000);
Philippe Langlaisfbdc6d12011-01-27 14:37:07 +0100304static DEFINE_PRCMU_CLK_RATE(sdmmcclk, 0x0, 9, SDMMCCLK, 100000000);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100305static DEFINE_PRCMU_CLK(slimclk, 0x0, 10, SLIMCLK);
306static DEFINE_PRCMU_CLK(per1clk, 0x0, 11, PER1CLK);
307static DEFINE_PRCMU_CLK(per2clk, 0x0, 12, PER2CLK);
308static DEFINE_PRCMU_CLK(per3clk, 0x0, 13, PER3CLK);
309static DEFINE_PRCMU_CLK(per5clk, 0x0, 14, PER5CLK);
310static DEFINE_PRCMU_CLK_RATE(per6clk, 0x0, 15, PER6CLK, 133330000);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100311static DEFINE_PRCMU_CLK(lcdclk, 0x0, 17, LCDCLK);
312static DEFINE_PRCMU_CLK(bmlclk, 0x0, 18, BMLCLK);
313static DEFINE_PRCMU_CLK(hsitxclk, 0x0, 19, HSITXCLK);
314static DEFINE_PRCMU_CLK(hsirxclk, 0x0, 20, HSIRXCLK);
315static DEFINE_PRCMU_CLK(hdmiclk, 0x0, 21, HDMICLK);
316static DEFINE_PRCMU_CLK(apeatclk, 0x0, 22, APEATCLK);
317static DEFINE_PRCMU_CLK(apetraceclk, 0x0, 23, APETRACECLK);
318static DEFINE_PRCMU_CLK(mcdeclk, 0x0, 24, MCDECLK);
319static DEFINE_PRCMU_CLK(ipi2clk, 0x0, 25, IPI2CCLK);
320static DEFINE_PRCMU_CLK(dsialtclk, 0x0, 26, DSIALTCLK); /* v1 */
321static DEFINE_PRCMU_CLK(dmaclk, 0x0, 27, DMACLK);
322static DEFINE_PRCMU_CLK(b2r2clk, 0x0, 28, B2R2CLK);
323static DEFINE_PRCMU_CLK(tvclk, 0x0, 29, TVCLK);
324static DEFINE_PRCMU_CLK(uniproclk, 0x0, 30, UNIPROCLK); /* v1 */
325static DEFINE_PRCMU_CLK_RATE(sspclk, 0x0, 31, SSPCLK, 48000000); /* v1 */
326
327/* Bank 1 */
328static DEFINE_PRCMU_CLK(rngclk, 0x4, 0, RNGCLK); /* v1 */
329static DEFINE_PRCMU_CLK(uiccclk, 0x4, 1, UICCCLK); /* v1 */
330
331/*
332 * PRCC level clock gating
333 * Format: per#, clk, PCKEN bit, KCKEN bit, parent
334 */
335
336/* Peripheral Cluster #1 */
Sundar Iyer592b2f22010-12-03 20:35:52 +0530337static DEFINE_PRCC_CLK(1, i2c4, 10, 9, &clk_i2cclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100338static DEFINE_PRCC_CLK(1, gpio0, 9, -1, NULL);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530339static DEFINE_PRCC_CLK(1, slimbus0, 8, 8, &clk_slimclk);
Linus Walleijc15def12011-12-15 13:38:40 +0100340static DEFINE_PRCC_CLK(1, spi3, 7, -1, NULL);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530341static DEFINE_PRCC_CLK(1, i2c2, 6, 6, &clk_i2cclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100342static DEFINE_PRCC_CLK(1, sdi0, 5, 5, &clk_sdmmcclk);
Linus Walleijc15def12011-12-15 13:38:40 +0100343static DEFINE_PRCC_CLK(1, msp1, 4, 4, &clk_msp1clk);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530344static DEFINE_PRCC_CLK(1, msp0, 3, 3, &clk_msp02clk);
345static DEFINE_PRCC_CLK(1, i2c1, 2, 2, &clk_i2cclk);
346static DEFINE_PRCC_CLK(1, uart1, 1, 1, &clk_uartclk);
347static DEFINE_PRCC_CLK(1, uart0, 0, 0, &clk_uartclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100348
349/* Peripheral Cluster #2 */
Linus Walleijc15def12011-12-15 13:38:40 +0100350static DEFINE_PRCC_CLK(2, gpio1, 11, -1, NULL);
351static DEFINE_PRCC_CLK(2, ssitx, 10, 7, NULL);
352static DEFINE_PRCC_CLK(2, ssirx, 9, 6, NULL);
353static DEFINE_PRCC_CLK(2, spi0, 8, -1, NULL);
354static DEFINE_PRCC_CLK(2, sdi3, 7, 5, &clk_sdmmcclk);
355static DEFINE_PRCC_CLK(2, sdi1, 6, 4, &clk_sdmmcclk);
356static DEFINE_PRCC_CLK(2, msp2, 5, 3, &clk_msp02clk);
357static DEFINE_PRCC_CLK(2, sdi4, 4, 2, &clk_sdmmcclk);
358static DEFINE_PRCC_CLK(2, pwl, 3, 1, NULL);
359static DEFINE_PRCC_CLK(2, spi1, 2, -1, NULL);
360static DEFINE_PRCC_CLK(2, spi2, 1, -1, NULL);
361static DEFINE_PRCC_CLK(2, i2c3, 0, 0, &clk_i2cclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100362
363/* Peripheral Cluster #3 */
Sundar Iyer592b2f22010-12-03 20:35:52 +0530364static DEFINE_PRCC_CLK(3, gpio2, 8, -1, NULL);
365static DEFINE_PRCC_CLK(3, sdi5, 7, 7, &clk_sdmmcclk);
366static DEFINE_PRCC_CLK(3, uart2, 6, 6, &clk_uartclk);
367static DEFINE_PRCC_CLK(3, ske, 5, 5, &clk_32khz);
368static DEFINE_PRCC_CLK(3, sdi2, 4, 4, &clk_sdmmcclk);
369static DEFINE_PRCC_CLK(3, i2c0, 3, 3, &clk_i2cclk);
Linus Walleijc15def12011-12-15 13:38:40 +0100370static DEFINE_PRCC_CLK(3, ssp1, 2, 2, &clk_sspclk);
371static DEFINE_PRCC_CLK(3, ssp0, 1, 1, &clk_sspclk);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530372static DEFINE_PRCC_CLK(3, fsmc, 0, -1, NULL);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100373
374/* Peripheral Cluster #4 is in the always on domain */
375
376/* Peripheral Cluster #5 */
Sundar Iyer592b2f22010-12-03 20:35:52 +0530377static DEFINE_PRCC_CLK(5, gpio3, 1, -1, NULL);
Linus Walleijc15def12011-12-15 13:38:40 +0100378static DEFINE_PRCC_CLK(5, usb, 0, 0, NULL);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100379
380/* Peripheral Cluster #6 */
381
Linus Walleijba327b12010-05-26 07:38:54 +0100382/* MTU ID in data */
Linus Walleijc15def12011-12-15 13:38:40 +0100383static DEFINE_PRCC_CLK_CUSTOM(6, mtu1, 8, -1, NULL, clk_mtu_get_rate, 1);
384static DEFINE_PRCC_CLK_CUSTOM(6, mtu0, 7, -1, NULL, clk_mtu_get_rate, 0);
385static DEFINE_PRCC_CLK(6, cfgreg, 6, 6, NULL);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530386static DEFINE_PRCC_CLK(6, hash1, 5, -1, NULL);
Linus Walleijc15def12011-12-15 13:38:40 +0100387static DEFINE_PRCC_CLK(6, unipro, 4, 1, &clk_uniproclk);
Sundar Iyer592b2f22010-12-03 20:35:52 +0530388static DEFINE_PRCC_CLK(6, pka, 3, -1, NULL);
389static DEFINE_PRCC_CLK(6, hash0, 2, -1, NULL);
390static DEFINE_PRCC_CLK(6, cryp0, 1, -1, NULL);
Linus Walleijc15def12011-12-15 13:38:40 +0100391static DEFINE_PRCC_CLK(6, rng, 0, 0, &clk_rngclk);
Rabin Vincent1df20af2010-03-01 05:07:47 +0100392
Vincent Guittot763eef82010-12-03 18:18:39 +0100393static struct clk clk_dummy_apb_pclk = {
394 .name = "apb_pclk",
395};
Russell King3126c7b2010-07-15 11:01:17 +0100396
Linus Walleijc15def12011-12-15 13:38:40 +0100397static struct clk_lookup u8500_clks[] = {
Russell King3126c7b2010-07-15 11:01:17 +0100398 CLK(dummy_apb_pclk, NULL, "apb_pclk"),
399
Rabin Vincent1df20af2010-03-01 05:07:47 +0100400 /* Peripheral Cluster #1 */
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100401 CLK(gpio0, "gpio.0", NULL),
402 CLK(gpio0, "gpio.1", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100403 CLK(slimbus0, "slimbus0", NULL),
404 CLK(i2c2, "nmk-i2c.2", NULL),
405 CLK(sdi0, "sdi0", NULL),
406 CLK(msp0, "msp0", NULL),
407 CLK(i2c1, "nmk-i2c.1", NULL),
408 CLK(uart1, "uart1", NULL),
409 CLK(uart0, "uart0", NULL),
410
411 /* Peripheral Cluster #3 */
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100412 CLK(gpio2, "gpio.2", NULL),
413 CLK(gpio2, "gpio.3", NULL),
414 CLK(gpio2, "gpio.4", NULL),
415 CLK(gpio2, "gpio.5", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100416 CLK(sdi5, "sdi5", NULL),
417 CLK(uart2, "uart2", NULL),
418 CLK(ske, "ske", NULL),
Sundar Iyer4c61c842010-09-29 19:43:09 -0700419 CLK(ske, "nmk-ske-keypad", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100420 CLK(sdi2, "sdi2", NULL),
421 CLK(i2c0, "nmk-i2c.0", NULL),
422 CLK(fsmc, "fsmc", NULL),
423
424 /* Peripheral Cluster #5 */
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100425 CLK(gpio3, "gpio.8", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100426
427 /* Peripheral Cluster #6 */
428 CLK(hash1, "hash1", NULL),
429 CLK(pka, "pka", NULL),
430 CLK(hash0, "hash0", NULL),
431 CLK(cryp0, "cryp0", NULL),
432
433 /* PRCMU level clock gating */
434
435 /* Bank 0 */
436 CLK(svaclk, "sva", NULL),
437 CLK(siaclk, "sia", NULL),
438 CLK(sgaclk, "sga", NULL),
439 CLK(slimclk, "slim", NULL),
440 CLK(lcdclk, "lcd", NULL),
441 CLK(bmlclk, "bml", NULL),
442 CLK(hsitxclk, "stm-hsi.0", NULL),
443 CLK(hsirxclk, "stm-hsi.1", NULL),
444 CLK(hdmiclk, "hdmi", NULL),
445 CLK(apeatclk, "apeat", NULL),
446 CLK(apetraceclk, "apetrace", NULL),
447 CLK(mcdeclk, "mcde", NULL),
448 CLK(ipi2clk, "ipi2", NULL),
Linus Walleij7b8ddb02010-05-27 15:21:26 -0700449 CLK(dmaclk, "dma40.0", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100450 CLK(b2r2clk, "b2r2", NULL),
451 CLK(tvclk, "tv", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100452
Rabin Vincent1df20af2010-03-01 05:07:47 +0100453 /* Peripheral Cluster #1 */
Sundar Iyer592b2f22010-12-03 20:35:52 +0530454 CLK(i2c4, "nmk-i2c.4", NULL),
Linus Walleijc15def12011-12-15 13:38:40 +0100455 CLK(spi3, "spi3", NULL),
456 CLK(msp1, "msp1", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100457
458 /* Peripheral Cluster #2 */
Linus Walleijc15def12011-12-15 13:38:40 +0100459 CLK(gpio1, "gpio.6", NULL),
460 CLK(gpio1, "gpio.7", NULL),
461 CLK(ssitx, "ssitx", NULL),
462 CLK(ssirx, "ssirx", NULL),
463 CLK(spi0, "spi0", NULL),
464 CLK(sdi3, "sdi3", NULL),
465 CLK(sdi1, "sdi1", NULL),
466 CLK(msp2, "msp2", NULL),
467 CLK(sdi4, "sdi4", NULL),
468 CLK(pwl, "pwl", NULL),
469 CLK(spi1, "spi1", NULL),
470 CLK(spi2, "spi2", NULL),
471 CLK(i2c3, "nmk-i2c.3", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100472
473 /* Peripheral Cluster #3 */
Linus Walleijc15def12011-12-15 13:38:40 +0100474 CLK(ssp1, "ssp1", NULL),
475 CLK(ssp0, "ssp0", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100476
477 /* Peripheral Cluster #5 */
Linus Walleijc15def12011-12-15 13:38:40 +0100478 CLK(usb, "musb-ux500.0", "usb"),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100479
480 /* Peripheral Cluster #6 */
Linus Walleijc15def12011-12-15 13:38:40 +0100481 CLK(mtu1, "mtu1", NULL),
482 CLK(mtu0, "mtu0", NULL),
483 CLK(cfgreg, "cfgreg", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100484 CLK(hash1, "hash1", NULL),
Linus Walleijc15def12011-12-15 13:38:40 +0100485 CLK(unipro, "unipro", NULL),
486 CLK(rng, "rng", NULL),
Rabin Vincent1df20af2010-03-01 05:07:47 +0100487
488 /* PRCMU level clock gating */
489
490 /* Bank 0 */
491 CLK(uniproclk, "uniproclk", NULL),
492 CLK(dsialtclk, "dsialt", NULL),
493
494 /* Bank 1 */
495 CLK(rngclk, "rng", NULL),
496 CLK(uiccclk, "uicc", NULL),
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100497};
498
Vincent Guittot763eef82010-12-03 18:18:39 +0100499#ifdef CONFIG_DEBUG_FS
500/*
501 * debugfs support to trace clock tree hierarchy and attributes with
502 * powerdebug
503 */
504static struct dentry *clk_debugfs_root;
505
506void __init clk_debugfs_add_table(struct clk_lookup *cl, size_t num)
507{
508 while (num--) {
509 /* Check that the clock has not been already registered */
510 if (!(cl->clk->list.prev != cl->clk->list.next))
511 list_add_tail(&cl->clk->list, &clk_list);
512
513 cl++;
514 }
515}
516
517static ssize_t usecount_dbg_read(struct file *file, char __user *buf,
518 size_t size, loff_t *off)
519{
520 struct clk *clk = file->f_dentry->d_inode->i_private;
521 char cusecount[128];
522 unsigned int len;
523
524 len = sprintf(cusecount, "%u\n", clk->enabled);
525 return simple_read_from_buffer(buf, size, off, cusecount, len);
526}
527
528static ssize_t rate_dbg_read(struct file *file, char __user *buf,
529 size_t size, loff_t *off)
530{
531 struct clk *clk = file->f_dentry->d_inode->i_private;
532 char crate[128];
533 unsigned int rate;
534 unsigned int len;
535
536 rate = clk_get_rate(clk);
537 len = sprintf(crate, "%u\n", rate);
538 return simple_read_from_buffer(buf, size, off, crate, len);
539}
540
541static const struct file_operations usecount_fops = {
542 .read = usecount_dbg_read,
543};
544
545static const struct file_operations set_rate_fops = {
546 .read = rate_dbg_read,
547};
548
549static struct dentry *clk_debugfs_register_dir(struct clk *c,
550 struct dentry *p_dentry)
551{
Al Viro12520c42011-07-16 12:37:57 -0400552 struct dentry *d, *clk_d;
Al Viroc066b652011-07-16 12:41:29 -0400553 const char *p = c->name;
Vincent Guittot763eef82010-12-03 18:18:39 +0100554
Al Viroc066b652011-07-16 12:41:29 -0400555 if (!p)
556 p = "BUG";
Vincent Guittot763eef82010-12-03 18:18:39 +0100557
Al Viroc066b652011-07-16 12:41:29 -0400558 clk_d = debugfs_create_dir(p, p_dentry);
Vincent Guittot763eef82010-12-03 18:18:39 +0100559 if (!clk_d)
560 return NULL;
561
562 d = debugfs_create_file("usecount", S_IRUGO,
563 clk_d, c, &usecount_fops);
564 if (!d)
565 goto err_out;
566 d = debugfs_create_file("rate", S_IRUGO,
567 clk_d, c, &set_rate_fops);
568 if (!d)
569 goto err_out;
570 /*
571 * TODO : not currently available in ux500
572 * d = debugfs_create_x32("flags", S_IRUGO, clk_d, (u32 *)&c->flags);
573 * if (!d)
574 * goto err_out;
575 */
576
577 return clk_d;
578
579err_out:
Al Viro12520c42011-07-16 12:37:57 -0400580 debugfs_remove_recursive(clk_d);
Vincent Guittot763eef82010-12-03 18:18:39 +0100581 return NULL;
582}
583
Vincent Guittot763eef82010-12-03 18:18:39 +0100584static int clk_debugfs_register_one(struct clk *c)
585{
586 struct clk *pa = c->parent_periph;
587 struct clk *bpa = c->parent_cluster;
588
589 if (!(bpa && !pa)) {
590 c->dent = clk_debugfs_register_dir(c,
591 pa ? pa->dent : clk_debugfs_root);
592 if (!c->dent)
593 return -ENOMEM;
594 }
595
596 if (bpa) {
597 c->dent_bus = clk_debugfs_register_dir(c,
598 bpa->dent_bus ? bpa->dent_bus : bpa->dent);
599 if ((!c->dent_bus) && (c->dent)) {
Al Viro12520c42011-07-16 12:37:57 -0400600 debugfs_remove_recursive(c->dent);
Vincent Guittot763eef82010-12-03 18:18:39 +0100601 c->dent = NULL;
602 return -ENOMEM;
603 }
604 }
605 return 0;
606}
607
608static int clk_debugfs_register(struct clk *c)
609{
610 int err;
611 struct clk *pa = c->parent_periph;
612 struct clk *bpa = c->parent_cluster;
613
614 if (pa && (!pa->dent && !pa->dent_bus)) {
615 err = clk_debugfs_register(pa);
616 if (err)
617 return err;
618 }
619
620 if (bpa && (!bpa->dent && !bpa->dent_bus)) {
621 err = clk_debugfs_register(bpa);
622 if (err)
623 return err;
624 }
625
626 if ((!c->dent) && (!c->dent_bus)) {
627 err = clk_debugfs_register_one(c);
628 if (err)
629 return err;
630 }
631 return 0;
632}
633
634static int __init clk_debugfs_init(void)
635{
636 struct clk *c;
637 struct dentry *d;
638 int err;
639
640 d = debugfs_create_dir("clock", NULL);
641 if (!d)
642 return -ENOMEM;
643 clk_debugfs_root = d;
644
645 list_for_each_entry(c, &clk_list, list) {
646 err = clk_debugfs_register(c);
647 if (err)
648 goto err_out;
649 }
650 return 0;
651err_out:
652 debugfs_remove_recursive(clk_debugfs_root);
653 return err;
654}
655
656late_initcall(clk_debugfs_init);
657#endif /* defined(CONFIG_DEBUG_FS) */
658
Linus Walleij10958432011-12-19 00:28:50 +0100659unsigned long clk_smp_twd_rate = 500000000;
Linus Walleijef7a4742011-06-01 14:44:16 +0200660
661unsigned long clk_smp_twd_get_rate(struct clk *clk)
662{
663 return clk_smp_twd_rate;
664}
665
666static struct clk clk_smp_twd = {
667 .get_rate = clk_smp_twd_get_rate,
668 .name = "smp_twd",
669};
670
671static struct clk_lookup clk_smp_twd_lookup = {
672 .dev_id = "smp_twd",
673 .clk = &clk_smp_twd,
674};
675
676#ifdef CONFIG_CPU_FREQ
677
678static int clk_twd_cpufreq_transition(struct notifier_block *nb,
679 unsigned long state, void *data)
680{
681 struct cpufreq_freqs *f = data;
682
683 if (state == CPUFREQ_PRECHANGE) {
684 /* Save frequency in simple Hz */
Linus Walleij10958432011-12-19 00:28:50 +0100685 clk_smp_twd_rate = (f->new * 1000) / 2;
Linus Walleijef7a4742011-06-01 14:44:16 +0200686 }
687
688 return NOTIFY_OK;
689}
690
691static struct notifier_block clk_twd_cpufreq_nb = {
692 .notifier_call = clk_twd_cpufreq_transition,
693};
694
695static int clk_init_smp_twd_cpufreq(void)
696{
697 return cpufreq_register_notifier(&clk_twd_cpufreq_nb,
698 CPUFREQ_TRANSITION_NOTIFIER);
699}
700late_initcall(clk_init_smp_twd_cpufreq);
701
702#endif
703
Linus Walleijba327b12010-05-26 07:38:54 +0100704int __init clk_init(void)
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100705{
Linus Walleijc15def12011-12-15 13:38:40 +0100706 clkdev_add_table(u8500_clks, ARRAY_SIZE(u8500_clks));
Linus Walleijef7a4742011-06-01 14:44:16 +0200707 clkdev_add(&clk_smp_twd_lookup);
708
Vincent Guittot763eef82010-12-03 18:18:39 +0100709#ifdef CONFIG_DEBUG_FS
Linus Walleijc15def12011-12-15 13:38:40 +0100710 clk_debugfs_add_table(u8500_clks, ARRAY_SIZE(u8500_clks));
Vincent Guittot763eef82010-12-03 18:18:39 +0100711#endif
Srinidhi Kasagarc6b503c2009-11-28 08:15:01 +0100712 return 0;
713}