2 * SH7367 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; 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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 /* 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
50 /* Fixed 32 KHz root clock from EXTALR pin */
51 static struct clk r_clk
= {
56 * 26MHz default rate for the EXTALB1 root input clock.
57 * If needed, reset this with clk_set_rate() from the platform code.
59 struct clk sh7367_extalb1_clk
= {
64 * 48MHz default rate for the EXTAL2 root input clock.
65 * If needed, reset this with clk_set_rate() from the platform code.
67 struct clk sh7367_extal2_clk
= {
71 /* A fixed divide-by-2 block */
72 static unsigned long div2_recalc(struct clk
*clk
)
74 return clk
->parent
->rate
/ 2;
77 static struct clk_ops div2_clk_ops
= {
78 .recalc
= div2_recalc
,
81 /* Divide extalb1 by two */
82 static struct clk extalb1_div2_clk
= {
84 .parent
= &sh7367_extalb1_clk
,
87 /* Divide extal2 by two */
88 static struct clk extal2_div2_clk
= {
90 .parent
= &sh7367_extal2_clk
,
94 static unsigned long pllc1_recalc(struct clk
*clk
)
96 unsigned long mult
= 1;
98 if (__raw_readl(PLLC1CR
) & (1 << 14))
99 mult
= (((__raw_readl(RTFRQCR
) >> 24) & 0x3f) + 1) * 2;
101 return clk
->parent
->rate
* mult
;
104 static struct clk_ops pllc1_clk_ops
= {
105 .recalc
= pllc1_recalc
,
108 static struct clk pllc1_clk
= {
109 .ops
= &pllc1_clk_ops
,
110 .flags
= CLK_ENABLE_ON_INIT
,
111 .parent
= &extalb1_div2_clk
,
114 /* Divide PLLC1 by two */
115 static struct clk pllc1_div2_clk
= {
116 .ops
= &div2_clk_ops
,
117 .parent
= &pllc1_clk
,
121 static unsigned long pllc2_recalc(struct clk
*clk
)
123 unsigned long mult
= 1;
125 if (__raw_readl(PLLC2CR
) & (1 << 31))
126 mult
= (((__raw_readl(PLLC2CR
) >> 24) & 0x3f) + 1) * 2;
128 return clk
->parent
->rate
* mult
;
131 static struct clk_ops pllc2_clk_ops
= {
132 .recalc
= pllc2_recalc
,
135 static struct clk pllc2_clk
= {
136 .ops
= &pllc2_clk_ops
,
137 .flags
= CLK_ENABLE_ON_INIT
,
138 .parent
= &extalb1_div2_clk
,
141 static struct clk
*main_clks
[] = {
152 static void div4_kick(struct clk
*clk
)
156 /* set KICK bit in SYFRQCR to update hardware setting */
157 value
= __raw_readl(SYFRQCR
);
159 __raw_writel(value
, SYFRQCR
);
162 static int divisors
[] = { 2, 3, 4, 6, 8, 12, 16, 18,
163 24, 32, 36, 48, 0, 72, 0, 0 };
165 static struct clk_div_mult_table div4_div_mult_table
= {
166 .divisors
= divisors
,
167 .nr_divisors
= ARRAY_SIZE(divisors
),
170 static struct clk_div4_table div4_table
= {
171 .div_mult_table
= &div4_div_mult_table
,
175 enum { 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
};
179 #define DIV4(_reg, _bit, _mask, _flags) \
180 SH_CLK_DIV4(&pllc1_clk, _reg, _bit, _mask, _flags)
182 static 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),
198 enum { 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
,
203 static 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),
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
,
228 #define MSTP(_parent, _reg, _bit, _flags) \
229 SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
231 static 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 */
262 static struct clk_lookup lookups
[] = {
264 CLKDEV_CON_ID("r_clk", &r_clk
),
265 CLKDEV_CON_ID("extalb1", &sh7367_extalb1_clk
),
266 CLKDEV_CON_ID("extal2", &sh7367_extal2_clk
),
267 CLKDEV_CON_ID("extalb1_div2_clk", &extalb1_div2_clk
),
268 CLKDEV_CON_ID("extal2_div2_clk", &extal2_div2_clk
),
269 CLKDEV_CON_ID("pllc1_clk", &pllc1_clk
),
270 CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk
),
271 CLKDEV_CON_ID("pllc2_clk", &pllc2_clk
),
274 CLKDEV_CON_ID("i_clk", &div4_clks
[DIV4_I
]),
275 CLKDEV_CON_ID("g_clk", &div4_clks
[DIV4_G
]),
276 CLKDEV_CON_ID("b_clk", &div4_clks
[DIV4_B
]),
277 CLKDEV_CON_ID("zx_clk", &div4_clks
[DIV4_ZX
]),
278 CLKDEV_CON_ID("zt_clk", &div4_clks
[DIV4_ZT
]),
279 CLKDEV_CON_ID("z_clk", &div4_clks
[DIV4_Z
]),
280 CLKDEV_CON_ID("zd_clk", &div4_clks
[DIV4_ZD
]),
281 CLKDEV_CON_ID("hp_clk", &div4_clks
[DIV4_HP
]),
282 CLKDEV_CON_ID("zs_clk", &div4_clks
[DIV4_ZS
]),
283 CLKDEV_CON_ID("zb_clk", &div4_clks
[DIV4_ZB
]),
284 CLKDEV_CON_ID("zb3_clk", &div4_clks
[DIV4_ZB3
]),
285 CLKDEV_CON_ID("cp_clk", &div4_clks
[DIV4_CP
]),
288 CLKDEV_CON_ID("sub_clk", &div6_clks
[DIV6_SUB
]),
289 CLKDEV_CON_ID("siua_clk", &div6_clks
[DIV6_SIUA
]),
290 CLKDEV_CON_ID("siub_clk", &div6_clks
[DIV6_SIUB
]),
291 CLKDEV_CON_ID("msu_clk", &div6_clks
[DIV6_MSU
]),
292 CLKDEV_CON_ID("spu_clk", &div6_clks
[DIV6_SPU
]),
293 CLKDEV_CON_ID("mvi3_clk", &div6_clks
[DIV6_MVI3
]),
294 CLKDEV_CON_ID("mf1_clk", &div6_clks
[DIV6_MF1
]),
295 CLKDEV_CON_ID("mf2_clk", &div6_clks
[DIV6_MF2
]),
296 CLKDEV_CON_ID("vck1_clk", &div6_clks
[DIV6_VCK1
]),
297 CLKDEV_CON_ID("vck2_clk", &div6_clks
[DIV6_VCK2
]),
298 CLKDEV_CON_ID("vck3_clk", &div6_clks
[DIV6_VCK3
]),
299 CLKDEV_CON_ID("vou_clk", &div6_clks
[DIV6_VOU
]),
302 CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks
[RTMSTP001
]), /* IIC2 */
303 CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks
[RTMSTP231
]), /* VEU3 */
304 CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks
[RTMSTP230
]), /* VEU2 */
305 CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks
[RTMSTP229
]), /* VEU1 */
306 CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks
[RTMSTP228
]), /* VEU0 */
307 CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks
[RTMSTP226
]), /* VEU2H */
308 CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks
[RTMSTP216
]), /* IIC0 */
309 CLKDEV_DEV_ID("uio_pdrv_genirq.6", &mstp_clks
[RTMSTP206
]), /* JPU */
310 CLKDEV_DEV_ID("sh-vou", &mstp_clks
[RTMSTP205
]), /* VOU */
311 CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks
[RTMSTP201
]), /* VPU */
312 CLKDEV_DEV_ID("uio_pdrv_genirq.7", &mstp_clks
[SYMSTP023
]), /* SPU1 */
313 CLKDEV_DEV_ID("sh-sci.5", &mstp_clks
[SYMSTP007
]), /* SCIFA5 */
314 CLKDEV_DEV_ID("sh-sci.6", &mstp_clks
[SYMSTP006
]), /* SCIFB */
315 CLKDEV_DEV_ID("sh-sci.0", &mstp_clks
[SYMSTP004
]), /* SCIFA0 */
316 CLKDEV_DEV_ID("sh-sci.1", &mstp_clks
[SYMSTP003
]), /* SCIFA1 */
317 CLKDEV_DEV_ID("sh-sci.2", &mstp_clks
[SYMSTP002
]), /* SCIFA2 */
318 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks
[SYMSTP001
]), /* SCIFA3 */
319 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks
[SYMSTP000
]), /* SCIFA4 */
320 CLKDEV_DEV_ID("sh_siu", &mstp_clks
[SYMSTP231
]), /* SIU */
321 CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks
[SYMSTP229
]), /* CMT10 */
322 CLKDEV_DEV_ID("sh_irda", &mstp_clks
[SYMSTP225
]), /* IRDA */
323 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks
[SYMSTP223
]), /* IIC1 */
324 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks
[SYMSTP222
]), /* USBHS */
325 CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks
[SYMSTP222
]), /* USBHS */
326 CLKDEV_DEV_ID("sh_flctl", &mstp_clks
[SYMSTP215
]), /* FLCTL */
327 CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks
[SYMSTP214
]), /* SDHI0 */
328 CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks
[SYMSTP213
]), /* SDHI1 */
329 CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks
[SYMSTP211
]), /* SDHI2 */
330 CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks
[CMMSTP003
]), /* KEYSC */
333 void __init
sh7367_clock_init(void)
337 for (k
= 0; !ret
&& (k
< ARRAY_SIZE(main_clks
)); k
++)
338 ret
= clk_register(main_clks
[k
]);
341 ret
= sh_clk_div4_register(div4_clks
, DIV4_NR
, &div4_table
);
344 ret
= sh_clk_div6_register(div6_clks
, DIV6_NR
);
347 ret
= sh_clk_mstp32_register(mstp_clks
, MSTP_NR
);
349 clkdev_add_table(lookups
, ARRAY_SIZE(lookups
));
354 panic("failed to setup sh7367 clocks\n");