2 * SH7377 clock framework support
4 * Copyright (C) 2010 Magnus Damm
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; either version 2 of the License
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <linux/init.h>
20 #include <linux/kernel.h>
22 #include <linux/sh_clk.h>
23 #include <linux/clkdev.h>
24 #include <mach/common.h>
26 /* SH7377 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 FMSICKCR 0xe6150010
34 #define FMSOCKCR 0xe6150014
35 #define FSICKCR 0xe6150018
36 #define PLLC1CR 0xe6150028
37 #define PLLC2CR 0xe615002C
38 #define SUBUSBCKCR 0xe6150080
39 #define SPUCKCR 0xe6150084
40 #define MSUCKCR 0xe6150088
41 #define MVI3CKCR 0xe6150090
42 #define HDMICKCR 0xe6150094
43 #define MFCK1CR 0xe6150098
44 #define MFCK2CR 0xe615009C
45 #define DSITCKCR 0xe6150060
46 #define DSIPCKCR 0xe6150064
47 #define SMSTPCR0 0xe6150130
48 #define SMSTPCR1 0xe6150134
49 #define SMSTPCR2 0xe6150138
50 #define SMSTPCR3 0xe615013C
51 #define SMSTPCR4 0xe6150140
53 /* Fixed 32 KHz root clock from EXTALR pin */
54 static struct clk r_clk
= {
59 * 26MHz default rate for the EXTALC1 root input clock.
60 * If needed, reset this with clk_set_rate() from the platform code.
62 struct clk sh7377_extalc1_clk
= {
67 * 48MHz default rate for the EXTAL2 root input clock.
68 * If needed, reset this with clk_set_rate() from the platform code.
70 struct clk sh7377_extal2_clk
= {
74 /* A fixed divide-by-2 block */
75 static unsigned long div2_recalc(struct clk
*clk
)
77 return clk
->parent
->rate
/ 2;
80 static struct clk_ops div2_clk_ops
= {
81 .recalc
= div2_recalc
,
84 /* Divide extalc1 by two */
85 static struct clk extalc1_div2_clk
= {
87 .parent
= &sh7377_extalc1_clk
,
90 /* Divide extal2 by two */
91 static struct clk extal2_div2_clk
= {
93 .parent
= &sh7377_extal2_clk
,
96 /* Divide extal2 by four */
97 static struct clk extal2_div4_clk
= {
99 .parent
= &extal2_div2_clk
,
103 static unsigned long pllc1_recalc(struct clk
*clk
)
105 unsigned long mult
= 1;
107 if (__raw_readl(PLLC1CR
) & (1 << 14))
108 mult
= (((__raw_readl(RTFRQCR
) >> 24) & 0x3f) + 1) * 2;
110 return clk
->parent
->rate
* mult
;
113 static struct clk_ops pllc1_clk_ops
= {
114 .recalc
= pllc1_recalc
,
117 static struct clk pllc1_clk
= {
118 .ops
= &pllc1_clk_ops
,
119 .flags
= CLK_ENABLE_ON_INIT
,
120 .parent
= &extalc1_div2_clk
,
123 /* Divide PLLC1 by two */
124 static struct clk pllc1_div2_clk
= {
125 .ops
= &div2_clk_ops
,
126 .parent
= &pllc1_clk
,
130 static unsigned long pllc2_recalc(struct clk
*clk
)
132 unsigned long mult
= 1;
134 if (__raw_readl(PLLC2CR
) & (1 << 31))
135 mult
= (((__raw_readl(PLLC2CR
) >> 24) & 0x3f) + 1) * 2;
137 return clk
->parent
->rate
* mult
;
140 static struct clk_ops pllc2_clk_ops
= {
141 .recalc
= pllc2_recalc
,
144 static struct clk pllc2_clk
= {
145 .ops
= &pllc2_clk_ops
,
146 .flags
= CLK_ENABLE_ON_INIT
,
147 .parent
= &extalc1_div2_clk
,
150 static struct clk
*main_clks
[] = {
162 static void div4_kick(struct clk
*clk
)
166 /* set KICK bit in SYFRQCR to update hardware setting */
167 value
= __raw_readl(SYFRQCR
);
169 __raw_writel(value
, SYFRQCR
);
172 static int divisors
[] = { 2, 3, 4, 6, 8, 12, 16, 18,
173 24, 32, 36, 48, 0, 72, 96, 0 };
175 static struct clk_div_mult_table div4_div_mult_table
= {
176 .divisors
= divisors
,
177 .nr_divisors
= ARRAY_SIZE(divisors
),
180 static struct clk_div4_table div4_table
= {
181 .div_mult_table
= &div4_div_mult_table
,
185 enum { DIV4_I
, DIV4_ZG
, DIV4_B
, DIV4_M1
, DIV4_CSIR
,
186 DIV4_ZTR
, DIV4_ZT
, DIV4_Z
, DIV4_HP
,
187 DIV4_ZS
, DIV4_ZB
, DIV4_ZB3
, DIV4_CP
, DIV4_NR
};
189 #define DIV4(_reg, _bit, _mask, _flags) \
190 SH_CLK_DIV4(&pllc1_clk, _reg, _bit, _mask, _flags)
192 static struct clk div4_clks
[DIV4_NR
] = {
193 [DIV4_I
] = DIV4(RTFRQCR
, 20, 0x6fff, CLK_ENABLE_ON_INIT
),
194 [DIV4_ZG
] = DIV4(RTFRQCR
, 16, 0x6fff, CLK_ENABLE_ON_INIT
),
195 [DIV4_B
] = DIV4(RTFRQCR
, 8, 0x6fff, CLK_ENABLE_ON_INIT
),
196 [DIV4_M1
] = DIV4(RTFRQCR
, 4, 0x6fff, CLK_ENABLE_ON_INIT
),
197 [DIV4_CSIR
] = DIV4(RTFRQCR
, 0, 0x6fff, 0),
198 [DIV4_ZTR
] = DIV4(SYFRQCR
, 20, 0x6fff, 0),
199 [DIV4_ZT
] = DIV4(SYFRQCR
, 16, 0x6fff, 0),
200 [DIV4_Z
] = DIV4(SYFRQCR
, 12, 0x6fff, 0),
201 [DIV4_HP
] = DIV4(SYFRQCR
, 4, 0x6fff, 0),
202 [DIV4_ZS
] = DIV4(CMFRQCR
, 12, 0x6fff, 0),
203 [DIV4_ZB
] = DIV4(CMFRQCR
, 8, 0x6fff, 0),
204 [DIV4_ZB3
] = DIV4(CMFRQCR
, 4, 0x6fff, 0),
205 [DIV4_CP
] = DIV4(CMFRQCR
, 0, 0x6fff, 0),
208 enum { DIV6_VCK1
, DIV6_VCK2
, DIV6_VCK3
, DIV6_FMSI
, DIV6_FMSO
,
209 DIV6_FSI
, DIV6_SUB
, DIV6_SPU
, DIV6_MSU
, DIV6_MVI3
, DIV6_HDMI
,
210 DIV6_MF1
, DIV6_MF2
, DIV6_DSIT
, DIV6_DSIP
,
213 static struct clk div6_clks
[] = {
214 [DIV6_VCK1
] = SH_CLK_DIV6(&pllc1_div2_clk
, VCLKCR1
, 0),
215 [DIV6_VCK2
] = SH_CLK_DIV6(&pllc1_div2_clk
, VCLKCR2
, 0),
216 [DIV6_VCK3
] = SH_CLK_DIV6(&pllc1_div2_clk
, VCLKCR3
, 0),
217 [DIV6_FMSI
] = SH_CLK_DIV6(&pllc1_div2_clk
, FMSICKCR
, 0),
218 [DIV6_FMSO
] = SH_CLK_DIV6(&pllc1_div2_clk
, FMSOCKCR
, 0),
219 [DIV6_FSI
] = SH_CLK_DIV6(&pllc1_div2_clk
, FSICKCR
, 0),
220 [DIV6_SUB
] = SH_CLK_DIV6(&sh7377_extal2_clk
, SUBUSBCKCR
, 0),
221 [DIV6_SPU
] = SH_CLK_DIV6(&pllc1_div2_clk
, SPUCKCR
, 0),
222 [DIV6_MSU
] = SH_CLK_DIV6(&pllc1_div2_clk
, MSUCKCR
, 0),
223 [DIV6_MVI3
] = SH_CLK_DIV6(&pllc1_div2_clk
, MVI3CKCR
, 0),
224 [DIV6_HDMI
] = SH_CLK_DIV6(&pllc1_div2_clk
, HDMICKCR
, 0),
225 [DIV6_MF1
] = SH_CLK_DIV6(&pllc1_div2_clk
, MFCK1CR
, 0),
226 [DIV6_MF2
] = SH_CLK_DIV6(&pllc1_div2_clk
, MFCK2CR
, 0),
227 [DIV6_DSIT
] = SH_CLK_DIV6(&pllc1_div2_clk
, DSITCKCR
, 0),
228 [DIV6_DSIP
] = SH_CLK_DIV6(&pllc1_div2_clk
, DSIPCKCR
, 0),
232 MSTP131
, MSTP130
, MSTP129
, MSTP128
, MSTP116
, MSTP106
, MSTP101
,
233 MSTP223
, MSTP207
, MSTP206
, MSTP204
, MSTP203
, MSTP202
, MSTP201
, MSTP200
,
234 MSTP331
, MSTP329
, MSTP325
, MSTP323
, MSTP322
,
235 MSTP315
, MSTP314
, MSTP313
,
239 #define MSTP(_parent, _reg, _bit, _flags) \
240 SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
242 static struct clk mstp_clks
[] = {
243 [MSTP001
] = MSTP(&div6_clks
[DIV6_SUB
], SMSTPCR0
, 1, 0), /* IIC2 */
244 [MSTP131
] = MSTP(&div4_clks
[DIV4_B
], SMSTPCR1
, 31, 0), /* VEU3 */
245 [MSTP130
] = MSTP(&div4_clks
[DIV4_B
], SMSTPCR1
, 30, 0), /* VEU2 */
246 [MSTP129
] = MSTP(&div4_clks
[DIV4_B
], SMSTPCR1
, 29, 0), /* VEU1 */
247 [MSTP128
] = MSTP(&div4_clks
[DIV4_B
], SMSTPCR1
, 28, 0), /* VEU0 */
248 [MSTP116
] = MSTP(&div6_clks
[DIV6_SUB
], SMSTPCR1
, 16, 0), /* IIC0 */
249 [MSTP106
] = MSTP(&div4_clks
[DIV4_B
], SMSTPCR1
, 6, 0), /* JPU */
250 [MSTP101
] = MSTP(&div4_clks
[DIV4_M1
], SMSTPCR1
, 1, 0), /* VPU */
251 [MSTP223
] = MSTP(&div6_clks
[DIV6_SPU
], SMSTPCR2
, 23, 0), /* SPU2 */
252 [MSTP207
] = MSTP(&div6_clks
[DIV6_SUB
], SMSTPCR2
, 7, 0), /* SCIFA5 */
253 [MSTP206
] = MSTP(&div6_clks
[DIV6_SUB
], SMSTPCR2
, 6, 0), /* SCIFB */
254 [MSTP204
] = MSTP(&div6_clks
[DIV6_SUB
], SMSTPCR2
, 4, 0), /* SCIFA0 */
255 [MSTP203
] = MSTP(&div6_clks
[DIV6_SUB
], SMSTPCR2
, 3, 0), /* SCIFA1 */
256 [MSTP202
] = MSTP(&div6_clks
[DIV6_SUB
], SMSTPCR2
, 2, 0), /* SCIFA2 */
257 [MSTP201
] = MSTP(&div6_clks
[DIV6_SUB
], SMSTPCR2
, 1, 0), /* SCIFA3 */
258 [MSTP200
] = MSTP(&div6_clks
[DIV6_SUB
], SMSTPCR2
, 0, 0), /* SCIFA4 */
259 [MSTP331
] = MSTP(&div6_clks
[DIV6_SUB
], SMSTPCR3
, 31, 0), /* SCIFA6 */
260 [MSTP329
] = MSTP(&r_clk
, SMSTPCR3
, 29, 0), /* CMT10 */
261 [MSTP325
] = MSTP(&div6_clks
[DIV6_SUB
], SMSTPCR3
, 25, 0), /* IRDA */
262 [MSTP323
] = MSTP(&div6_clks
[DIV6_SUB
], SMSTPCR3
, 23, 0), /* IIC1 */
263 [MSTP322
] = MSTP(&div6_clks
[DIV6_SUB
], SMSTPCR3
, 22, 0), /* USB0 */
264 [MSTP315
] = MSTP(&div4_clks
[DIV4_HP
], SMSTPCR3
, 15, 0), /* FLCTL */
265 [MSTP314
] = MSTP(&div4_clks
[DIV4_HP
], SMSTPCR3
, 14, 0), /* SDHI0 */
266 [MSTP313
] = MSTP(&div4_clks
[DIV4_HP
], SMSTPCR3
, 13, 0), /* SDHI1 */
267 [MSTP403
] = MSTP(&r_clk
, SMSTPCR4
, 3, 0), /* KEYSC */
270 #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
271 #define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
273 static struct clk_lookup lookups
[] = {
275 CLKDEV_CON_ID("r_clk", &r_clk
),
276 CLKDEV_CON_ID("extalc1", &sh7377_extalc1_clk
),
277 CLKDEV_CON_ID("extal2", &sh7377_extal2_clk
),
278 CLKDEV_CON_ID("extalc1_div2_clk", &extalc1_div2_clk
),
279 CLKDEV_CON_ID("extal2_div2_clk", &extal2_div2_clk
),
280 CLKDEV_CON_ID("extal2_div4_clk", &extal2_div4_clk
),
281 CLKDEV_CON_ID("pllc1_clk", &pllc1_clk
),
282 CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk
),
283 CLKDEV_CON_ID("pllc2_clk", &pllc2_clk
),
286 CLKDEV_CON_ID("i_clk", &div4_clks
[DIV4_I
]),
287 CLKDEV_CON_ID("zg_clk", &div4_clks
[DIV4_ZG
]),
288 CLKDEV_CON_ID("b_clk", &div4_clks
[DIV4_B
]),
289 CLKDEV_CON_ID("m1_clk", &div4_clks
[DIV4_M1
]),
290 CLKDEV_CON_ID("csir_clk", &div4_clks
[DIV4_CSIR
]),
291 CLKDEV_CON_ID("ztr_clk", &div4_clks
[DIV4_ZTR
]),
292 CLKDEV_CON_ID("zt_clk", &div4_clks
[DIV4_ZT
]),
293 CLKDEV_CON_ID("z_clk", &div4_clks
[DIV4_Z
]),
294 CLKDEV_CON_ID("hp_clk", &div4_clks
[DIV4_HP
]),
295 CLKDEV_CON_ID("zs_clk", &div4_clks
[DIV4_ZS
]),
296 CLKDEV_CON_ID("zb_clk", &div4_clks
[DIV4_ZB
]),
297 CLKDEV_CON_ID("zb3_clk", &div4_clks
[DIV4_ZB3
]),
298 CLKDEV_CON_ID("cp_clk", &div4_clks
[DIV4_CP
]),
301 CLKDEV_CON_ID("vck1_clk", &div6_clks
[DIV6_VCK1
]),
302 CLKDEV_CON_ID("vck2_clk", &div6_clks
[DIV6_VCK2
]),
303 CLKDEV_CON_ID("vck3_clk", &div6_clks
[DIV6_VCK3
]),
304 CLKDEV_CON_ID("fmsi_clk", &div6_clks
[DIV6_FMSI
]),
305 CLKDEV_CON_ID("fmso_clk", &div6_clks
[DIV6_FMSO
]),
306 CLKDEV_CON_ID("fsi_clk", &div6_clks
[DIV6_FSI
]),
307 CLKDEV_CON_ID("sub_clk", &div6_clks
[DIV6_SUB
]),
308 CLKDEV_CON_ID("spu_clk", &div6_clks
[DIV6_SPU
]),
309 CLKDEV_CON_ID("msu_clk", &div6_clks
[DIV6_MSU
]),
310 CLKDEV_CON_ID("mvi3_clk", &div6_clks
[DIV6_MVI3
]),
311 CLKDEV_CON_ID("hdmi_clk", &div6_clks
[DIV6_HDMI
]),
312 CLKDEV_CON_ID("mf1_clk", &div6_clks
[DIV6_MF1
]),
313 CLKDEV_CON_ID("mf2_clk", &div6_clks
[DIV6_MF2
]),
314 CLKDEV_CON_ID("dsit_clk", &div6_clks
[DIV6_DSIT
]),
315 CLKDEV_CON_ID("dsip_clk", &div6_clks
[DIV6_DSIP
]),
318 CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks
[MSTP001
]), /* IIC2 */
319 CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks
[MSTP131
]), /* VEU3 */
320 CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks
[MSTP130
]), /* VEU2 */
321 CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks
[MSTP129
]), /* VEU1 */
322 CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks
[MSTP128
]), /* VEU0 */
323 CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks
[MSTP116
]), /* IIC0 */
324 CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks
[MSTP106
]), /* JPU */
325 CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks
[MSTP101
]), /* VPU */
326 CLKDEV_DEV_ID("uio_pdrv_genirq.6", &mstp_clks
[MSTP223
]), /* SPU2DSP0 */
327 CLKDEV_DEV_ID("uio_pdrv_genirq.7", &mstp_clks
[MSTP223
]), /* SPU2DSP1 */
328 CLKDEV_DEV_ID("sh-sci.5", &mstp_clks
[MSTP207
]), /* SCIFA5 */
329 CLKDEV_DEV_ID("sh-sci.7", &mstp_clks
[MSTP206
]), /* SCIFB */
330 CLKDEV_DEV_ID("sh-sci.0", &mstp_clks
[MSTP204
]), /* SCIFA0 */
331 CLKDEV_DEV_ID("sh-sci.1", &mstp_clks
[MSTP203
]), /* SCIFA1 */
332 CLKDEV_DEV_ID("sh-sci.2", &mstp_clks
[MSTP202
]), /* SCIFA2 */
333 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks
[MSTP201
]), /* SCIFA3 */
334 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks
[MSTP200
]), /* SCIFA4 */
335 CLKDEV_DEV_ID("sh-sci.6", &mstp_clks
[MSTP331
]), /* SCIFA6 */
336 CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks
[MSTP329
]), /* CMT10 */
337 CLKDEV_DEV_ID("sh_irda", &mstp_clks
[MSTP325
]), /* IRDA */
338 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks
[MSTP323
]), /* IIC1 */
339 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks
[MSTP322
]), /* USBHS */
340 CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks
[MSTP322
]), /* USBHS */
341 CLKDEV_DEV_ID("sh_flctl", &mstp_clks
[MSTP315
]), /* FLCTL */
342 CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks
[MSTP314
]), /* SDHI0 */
343 CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks
[MSTP313
]), /* SDHI1 */
344 CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks
[MSTP403
]), /* KEYSC */
347 void __init
sh7377_clock_init(void)
351 for (k
= 0; !ret
&& (k
< ARRAY_SIZE(main_clks
)); k
++)
352 ret
= clk_register(main_clks
[k
]);
355 ret
= sh_clk_div4_register(div4_clks
, DIV4_NR
, &div4_table
);
358 ret
= sh_clk_div6_register(div6_clks
, DIV6_NR
);
361 ret
= sh_clk_mstp32_register(mstp_clks
, MSTP_NR
);
363 clkdev_add_table(lookups
, ARRAY_SIZE(lookups
));
368 panic("failed to setup sh7377 clocks\n");