ARM: 6483/1: arm & sh: factorised duplicated clkdev.c
[linux-2.6-block.git] / arch / arm / mach-shmobile / clock-sh7367.c
CommitLineData
c793c1b0 1/*
4f0836b4 2 * SH7367 clock framework support
c793c1b0
MD
3 *
4 * Copyright (C) 2010 Magnus Damm
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19#include <linux/init.h>
c793c1b0 20#include <linux/kernel.h>
4f0836b4 21#include <linux/io.h>
e47bb515 22#include <linux/sh_clk.h>
6d803ba7 23#include <linux/clkdev.h>
4f0836b4 24#include <mach/common.h>
c793c1b0 25
4f0836b4
MD
26/* SH7367 registers */
27#define RTFRQCR 0xe6150000
28#define SYFRQCR 0xe6150004
29#define CMFRQCR 0xe61500E0
30#define VCLKCR1 0xe6150008
31#define VCLKCR2 0xe615000C
32#define VCLKCR3 0xe615001C
33#define SCLKACR 0xe6150010
34#define SCLKBCR 0xe6150014
35#define SUBUSBCKCR 0xe6158080
36#define SPUCKCR 0xe6150084
37#define MSUCKCR 0xe6150088
38#define MVI3CKCR 0xe6150090
39#define VOUCKCR 0xe6150094
40#define MFCK1CR 0xe6150098
41#define MFCK2CR 0xe615009C
42#define PLLC1CR 0xe6150028
43#define PLLC2CR 0xe615002C
44#define RTMSTPCR0 0xe6158030
45#define RTMSTPCR2 0xe6158038
46#define SYMSTPCR0 0xe6158040
47#define SYMSTPCR2 0xe6158048
48#define CMMSTPCR0 0xe615804c
c793c1b0 49
4f0836b4 50/* Fixed 32 KHz root clock from EXTALR pin */
c793c1b0 51static struct clk r_clk = {
4f0836b4 52 .rate = 32768,
c793c1b0
MD
53};
54
4f0836b4
MD
55/*
56 * 26MHz default rate for the EXTALB1 root input clock.
57 * If needed, reset this with clk_set_rate() from the platform code.
58 */
59struct clk sh7367_extalb1_clk = {
60 .rate = 26666666,
3a7b802d
MD
61};
62
4f0836b4
MD
63/*
64 * 48MHz default rate for the EXTAL2 root input clock.
65 * If needed, reset this with clk_set_rate() from the platform code.
66 */
67struct clk sh7367_extal2_clk = {
68 .rate = 48000000,
03fb256d
MD
69};
70
4f0836b4
MD
71/* A fixed divide-by-2 block */
72static unsigned long div2_recalc(struct clk *clk)
73{
74 return clk->parent->rate / 2;
75}
76
77static struct clk_ops div2_clk_ops = {
78 .recalc = div2_recalc,
79};
80
81/* Divide extalb1 by two */
82static struct clk extalb1_div2_clk = {
83 .ops = &div2_clk_ops,
84 .parent = &sh7367_extalb1_clk,
85};
86
87/* Divide extal2 by two */
88static struct clk extal2_div2_clk = {
89 .ops = &div2_clk_ops,
90 .parent = &sh7367_extal2_clk,
91};
92
93/* PLLC1 */
94static unsigned long pllc1_recalc(struct clk *clk)
95{
96 unsigned long mult = 1;
97
98 if (__raw_readl(PLLC1CR) & (1 << 14))
99 mult = (((__raw_readl(RTFRQCR) >> 24) & 0x3f) + 1) * 2;
100
101 return clk->parent->rate * mult;
102}
103
104static struct clk_ops pllc1_clk_ops = {
105 .recalc = pllc1_recalc,
106};
107
108static struct clk pllc1_clk = {
109 .ops = &pllc1_clk_ops,
110 .flags = CLK_ENABLE_ON_INIT,
111 .parent = &extalb1_div2_clk,
112};
113
114/* Divide PLLC1 by two */
115static struct clk pllc1_div2_clk = {
116 .ops = &div2_clk_ops,
117 .parent = &pllc1_clk,
118};
119
120/* PLLC2 */
121static unsigned long pllc2_recalc(struct clk *clk)
122{
123 unsigned long mult = 1;
124
125 if (__raw_readl(PLLC2CR) & (1 << 31))
126 mult = (((__raw_readl(PLLC2CR) >> 24) & 0x3f) + 1) * 2;
127
128 return clk->parent->rate * mult;
129}
130
131static struct clk_ops pllc2_clk_ops = {
132 .recalc = pllc2_recalc,
133};
134
135static struct clk pllc2_clk = {
136 .ops = &pllc2_clk_ops,
137 .flags = CLK_ENABLE_ON_INIT,
138 .parent = &extalb1_div2_clk,
139};
140
141static struct clk *main_clks[] = {
142 &r_clk,
143 &sh7367_extalb1_clk,
144 &sh7367_extal2_clk,
145 &extalb1_div2_clk,
146 &extal2_div2_clk,
147 &pllc1_clk,
148 &pllc1_div2_clk,
149 &pllc2_clk,
150};
151
152static void div4_kick(struct clk *clk)
153{
154 unsigned long value;
155
156 /* set KICK bit in SYFRQCR to update hardware setting */
157 value = __raw_readl(SYFRQCR);
158 value |= (1 << 31);
159 __raw_writel(value, SYFRQCR);
160}
161
162static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
163 24, 32, 36, 48, 0, 72, 0, 0 };
164
165static struct clk_div_mult_table div4_div_mult_table = {
166 .divisors = divisors,
167 .nr_divisors = ARRAY_SIZE(divisors),
168};
169
170static struct clk_div4_table div4_table = {
171 .div_mult_table = &div4_div_mult_table,
172 .kick = div4_kick,
173};
174
175enum { DIV4_I, DIV4_G, DIV4_S, DIV4_B,
176 DIV4_ZX, DIV4_ZT, DIV4_Z, DIV4_ZD, DIV4_HP,
177 DIV4_ZS, DIV4_ZB, DIV4_ZB3, DIV4_CP, DIV4_NR };
178
179#define DIV4(_reg, _bit, _mask, _flags) \
180 SH_CLK_DIV4(&pllc1_clk, _reg, _bit, _mask, _flags)
181
182static struct clk div4_clks[DIV4_NR] = {
183 [DIV4_I] = DIV4(RTFRQCR, 20, 0x6fff, CLK_ENABLE_ON_INIT),
184 [DIV4_G] = DIV4(RTFRQCR, 16, 0x6fff, CLK_ENABLE_ON_INIT),
185 [DIV4_S] = DIV4(RTFRQCR, 12, 0x6fff, CLK_ENABLE_ON_INIT),
186 [DIV4_B] = DIV4(RTFRQCR, 8, 0x6fff, CLK_ENABLE_ON_INIT),
187 [DIV4_ZX] = DIV4(SYFRQCR, 20, 0x6fff, 0),
188 [DIV4_ZT] = DIV4(SYFRQCR, 16, 0x6fff, 0),
189 [DIV4_Z] = DIV4(SYFRQCR, 12, 0x6fff, 0),
190 [DIV4_ZD] = DIV4(SYFRQCR, 8, 0x6fff, 0),
191 [DIV4_HP] = DIV4(SYFRQCR, 4, 0x6fff, 0),
192 [DIV4_ZS] = DIV4(CMFRQCR, 12, 0x6fff, 0),
193 [DIV4_ZB] = DIV4(CMFRQCR, 8, 0x6fff, 0),
194 [DIV4_ZB3] = DIV4(CMFRQCR, 4, 0x6fff, 0),
195 [DIV4_CP] = DIV4(CMFRQCR, 0, 0x6fff, 0),
196};
197
198enum { DIV6_SUB, DIV6_SIUA, DIV6_SIUB, DIV6_MSU, DIV6_SPU,
199 DIV6_MVI3, DIV6_MF1, DIV6_MF2,
200 DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_VOU,
201 DIV6_NR };
202
203static struct clk div6_clks[DIV6_NR] = {
204 [DIV6_SUB] = SH_CLK_DIV6(&sh7367_extal2_clk, SUBUSBCKCR, 0),
205 [DIV6_SIUA] = SH_CLK_DIV6(&pllc1_div2_clk, SCLKACR, 0),
206 [DIV6_SIUB] = SH_CLK_DIV6(&pllc1_div2_clk, SCLKBCR, 0),
207 [DIV6_MSU] = SH_CLK_DIV6(&pllc1_div2_clk, MSUCKCR, 0),
208 [DIV6_SPU] = SH_CLK_DIV6(&pllc1_div2_clk, SPUCKCR, 0),
209 [DIV6_MVI3] = SH_CLK_DIV6(&pllc1_div2_clk, MVI3CKCR, 0),
210 [DIV6_MF1] = SH_CLK_DIV6(&pllc1_div2_clk, MFCK1CR, 0),
211 [DIV6_MF2] = SH_CLK_DIV6(&pllc1_div2_clk, MFCK2CR, 0),
212 [DIV6_VCK1] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR1, 0),
213 [DIV6_VCK2] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR2, 0),
214 [DIV6_VCK3] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR3, 0),
215 [DIV6_VOU] = SH_CLK_DIV6(&pllc1_div2_clk, VOUCKCR, 0),
216};
217
218enum { RTMSTP001,
219 RTMSTP231, RTMSTP230, RTMSTP229, RTMSTP228, RTMSTP226,
220 RTMSTP216, RTMSTP206, RTMSTP205, RTMSTP201,
221 SYMSTP023, SYMSTP007, SYMSTP006, SYMSTP004,
222 SYMSTP003, SYMSTP002, SYMSTP001, SYMSTP000,
223 SYMSTP231, SYMSTP229, SYMSTP225, SYMSTP223, SYMSTP222,
224 SYMSTP215, SYMSTP214, SYMSTP213, SYMSTP211,
225 CMMSTP003,
226 MSTP_NR };
227
228#define MSTP(_parent, _reg, _bit, _flags) \
229 SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
230
231static struct clk mstp_clks[MSTP_NR] = {
232 [RTMSTP001] = MSTP(&div6_clks[DIV6_SUB], RTMSTPCR0, 1, 0), /* IIC2 */
233 [RTMSTP231] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 31, 0), /* VEU3 */
234 [RTMSTP230] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 30, 0), /* VEU2 */
235 [RTMSTP229] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 29, 0), /* VEU1 */
236 [RTMSTP228] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 28, 0), /* VEU0 */
237 [RTMSTP226] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 26, 0), /* VEU2H */
238 [RTMSTP216] = MSTP(&div6_clks[DIV6_SUB], RTMSTPCR2, 16, 0), /* IIC0 */
239 [RTMSTP206] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 6, 0), /* JPU */
240 [RTMSTP205] = MSTP(&div6_clks[DIV6_VOU], RTMSTPCR2, 5, 0), /* VOU */
241 [RTMSTP201] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 1, 0), /* VPU */
242 [SYMSTP023] = MSTP(&div6_clks[DIV6_SPU], SYMSTPCR0, 23, 0), /* SPU1 */
243 [SYMSTP007] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 7, 0), /* SCIFA5 */
244 [SYMSTP006] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 6, 0), /* SCIFB */
245 [SYMSTP004] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 4, 0), /* SCIFA0 */
246 [SYMSTP003] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 3, 0), /* SCIFA1 */
247 [SYMSTP002] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 2, 0), /* SCIFA2 */
248 [SYMSTP001] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 1, 0), /* SCIFA3 */
249 [SYMSTP000] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 0, 0), /* SCIFA4 */
250 [SYMSTP231] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 31, 0), /* SIU */
251 [SYMSTP229] = MSTP(&r_clk, SYMSTPCR2, 29, 0), /* CMT10 */
252 [SYMSTP225] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 25, 0), /* IRDA */
253 [SYMSTP223] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 23, 0), /* IIC1 */
254 [SYMSTP222] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 22, 0), /* USBHS */
255 [SYMSTP215] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 15, 0), /* FLCTL */
256 [SYMSTP214] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 14, 0), /* SDHI0 */
257 [SYMSTP213] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 13, 0), /* SDHI1 */
258 [SYMSTP211] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 11, 0), /* SDHI2 */
259 [CMMSTP003] = MSTP(&r_clk, CMMSTPCR0, 3, 0), /* KEYSC */
260};
261
262#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
263#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
264
c793c1b0 265static struct clk_lookup lookups[] = {
4f0836b4
MD
266 /* main clocks */
267 CLKDEV_CON_ID("r_clk", &r_clk),
268 CLKDEV_CON_ID("extalb1", &sh7367_extalb1_clk),
269 CLKDEV_CON_ID("extal2", &sh7367_extal2_clk),
270 CLKDEV_CON_ID("extalb1_div2_clk", &extalb1_div2_clk),
271 CLKDEV_CON_ID("extal2_div2_clk", &extal2_div2_clk),
272 CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
273 CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
274 CLKDEV_CON_ID("pllc2_clk", &pllc2_clk),
275
276 /* DIV4 clocks */
277 CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
278 CLKDEV_CON_ID("g_clk", &div4_clks[DIV4_G]),
279 CLKDEV_CON_ID("b_clk", &div4_clks[DIV4_B]),
280 CLKDEV_CON_ID("zx_clk", &div4_clks[DIV4_ZX]),
281 CLKDEV_CON_ID("zt_clk", &div4_clks[DIV4_ZT]),
282 CLKDEV_CON_ID("z_clk", &div4_clks[DIV4_Z]),
283 CLKDEV_CON_ID("zd_clk", &div4_clks[DIV4_ZD]),
284 CLKDEV_CON_ID("hp_clk", &div4_clks[DIV4_HP]),
285 CLKDEV_CON_ID("zs_clk", &div4_clks[DIV4_ZS]),
286 CLKDEV_CON_ID("zb_clk", &div4_clks[DIV4_ZB]),
287 CLKDEV_CON_ID("zb3_clk", &div4_clks[DIV4_ZB3]),
288 CLKDEV_CON_ID("cp_clk", &div4_clks[DIV4_CP]),
289
290 /* DIV6 clocks */
291 CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]),
292 CLKDEV_CON_ID("siua_clk", &div6_clks[DIV6_SIUA]),
293 CLKDEV_CON_ID("siub_clk", &div6_clks[DIV6_SIUB]),
294 CLKDEV_CON_ID("msu_clk", &div6_clks[DIV6_MSU]),
295 CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]),
296 CLKDEV_CON_ID("mvi3_clk", &div6_clks[DIV6_MVI3]),
297 CLKDEV_CON_ID("mf1_clk", &div6_clks[DIV6_MF1]),
298 CLKDEV_CON_ID("mf2_clk", &div6_clks[DIV6_MF2]),
299 CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]),
300 CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]),
301 CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]),
302 CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]),
303
304 /* MSTP32 clocks */
305 CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[RTMSTP001]), /* IIC2 */
306 CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[RTMSTP231]), /* VEU3 */
307 CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[RTMSTP230]), /* VEU2 */
308 CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks[RTMSTP229]), /* VEU1 */
309 CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[RTMSTP228]), /* VEU0 */
310 CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[RTMSTP226]), /* VEU2H */
311 CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[RTMSTP216]), /* IIC0 */
312 CLKDEV_DEV_ID("uio_pdrv_genirq.6", &mstp_clks[RTMSTP206]), /* JPU */
313 CLKDEV_DEV_ID("sh-vou", &mstp_clks[RTMSTP205]), /* VOU */
314 CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[RTMSTP201]), /* VPU */
315 CLKDEV_DEV_ID("uio_pdrv_genirq.7", &mstp_clks[SYMSTP023]), /* SPU1 */
316 CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[SYMSTP007]), /* SCIFA5 */
317 CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[SYMSTP006]), /* SCIFB */
318 CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[SYMSTP004]), /* SCIFA0 */
319 CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[SYMSTP003]), /* SCIFA1 */
320 CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[SYMSTP002]), /* SCIFA2 */
321 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[SYMSTP001]), /* SCIFA3 */
322 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[SYMSTP000]), /* SCIFA4 */
323 CLKDEV_DEV_ID("sh_siu", &mstp_clks[SYMSTP231]), /* SIU */
90e09a59 324 CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[SYMSTP229]), /* CMT10 */
4f0836b4
MD
325 CLKDEV_DEV_ID("sh_irda", &mstp_clks[SYMSTP225]), /* IRDA */
326 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[SYMSTP223]), /* IIC1 */
327 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[SYMSTP222]), /* USBHS */
328 CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[SYMSTP222]), /* USBHS */
329 CLKDEV_DEV_ID("sh_flctl", &mstp_clks[SYMSTP215]), /* FLCTL */
330 CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[SYMSTP214]), /* SDHI0 */
331 CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[SYMSTP213]), /* SDHI1 */
332 CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[SYMSTP211]), /* SDHI2 */
333 CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[CMMSTP003]), /* KEYSC */
c793c1b0
MD
334};
335
336void __init sh7367_clock_init(void)
337{
4f0836b4
MD
338 int k, ret = 0;
339
340 for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
341 ret = clk_register(main_clks[k]);
342
343 if (!ret)
344 ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
345
346 if (!ret)
347 ret = sh_clk_div6_register(div6_clks, DIV6_NR);
348
349 if (!ret)
350 ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
351
352 clkdev_add_table(lookups, ARRAY_SIZE(lookups));
c793c1b0 353
4f0836b4
MD
354 if (!ret)
355 clk_init();
356 else
357 panic("failed to setup sh7367 clocks\n");
c793c1b0 358}