1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <linux/init.h>
20#include <linux/kernel.h>
21#include <linux/io.h>
22#include <linux/sh_clk.h>
23#include <linux/clkdev.h>
24#include <mach/common.h>
25
26
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
49
50
51static struct clk r_clk = {
52 .rate = 32768,
53};
54
55
56
57
58
59struct clk sh7367_extalb1_clk = {
60 .rate = 26666666,
61};
62
63
64
65
66
67struct clk sh7367_extal2_clk = {
68 .rate = 48000000,
69};
70
71
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
82static struct clk extalb1_div2_clk = {
83 .ops = &div2_clk_ops,
84 .parent = &sh7367_extalb1_clk,
85};
86
87
88static struct clk extal2_div2_clk = {
89 .ops = &div2_clk_ops,
90 .parent = &sh7367_extal2_clk,
91};
92
93
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
115static struct clk pllc1_div2_clk = {
116 .ops = &div2_clk_ops,
117 .parent = &pllc1_clk,
118};
119
120
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
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),
233 [RTMSTP231] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 31, 0),
234 [RTMSTP230] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 30, 0),
235 [RTMSTP229] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 29, 0),
236 [RTMSTP228] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 28, 0),
237 [RTMSTP226] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 26, 0),
238 [RTMSTP216] = MSTP(&div6_clks[DIV6_SUB], RTMSTPCR2, 16, 0),
239 [RTMSTP206] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 6, 0),
240 [RTMSTP205] = MSTP(&div6_clks[DIV6_VOU], RTMSTPCR2, 5, 0),
241 [RTMSTP201] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 1, 0),
242 [SYMSTP023] = MSTP(&div6_clks[DIV6_SPU], SYMSTPCR0, 23, 0),
243 [SYMSTP007] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 7, 0),
244 [SYMSTP006] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 6, 0),
245 [SYMSTP004] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 4, 0),
246 [SYMSTP003] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 3, 0),
247 [SYMSTP002] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 2, 0),
248 [SYMSTP001] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 1, 0),
249 [SYMSTP000] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 0, 0),
250 [SYMSTP231] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 31, 0),
251 [SYMSTP229] = MSTP(&r_clk, SYMSTPCR2, 29, 0),
252 [SYMSTP225] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 25, 0),
253 [SYMSTP223] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 23, 0),
254 [SYMSTP222] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 22, 0),
255 [SYMSTP215] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 15, 0),
256 [SYMSTP214] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 14, 0),
257 [SYMSTP213] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 13, 0),
258 [SYMSTP211] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 11, 0),
259 [CMMSTP003] = MSTP(&r_clk, CMMSTPCR0, 3, 0),
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
265static struct clk_lookup lookups[] = {
266
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
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
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
305 CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[RTMSTP001]),
306 CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[RTMSTP231]),
307 CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[RTMSTP230]),
308 CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks[RTMSTP229]),
309 CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[RTMSTP228]),
310 CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[RTMSTP226]),
311 CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[RTMSTP216]),
312 CLKDEV_DEV_ID("uio_pdrv_genirq.6", &mstp_clks[RTMSTP206]),
313 CLKDEV_DEV_ID("sh-vou", &mstp_clks[RTMSTP205]),
314 CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[RTMSTP201]),
315 CLKDEV_DEV_ID("uio_pdrv_genirq.7", &mstp_clks[SYMSTP023]),
316 CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[SYMSTP007]),
317 CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[SYMSTP006]),
318 CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[SYMSTP004]),
319 CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[SYMSTP003]),
320 CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[SYMSTP002]),
321 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[SYMSTP001]),
322 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[SYMSTP000]),
323 CLKDEV_DEV_ID("sh_siu", &mstp_clks[SYMSTP231]),
324 CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[SYMSTP229]),
325 CLKDEV_DEV_ID("sh_irda", &mstp_clks[SYMSTP225]),
326 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[SYMSTP223]),
327 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[SYMSTP222]),
328 CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[SYMSTP222]),
329 CLKDEV_DEV_ID("sh_flctl", &mstp_clks[SYMSTP215]),
330 CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[SYMSTP214]),
331 CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[SYMSTP213]),
332 CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[SYMSTP211]),
333 CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[CMMSTP003]),
334};
335
336void __init sh7367_clock_init(void)
337{
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));
353
354 if (!ret)
355 clk_init();
356 else
357 panic("failed to setup sh7367 clocks\n");
358}
359