• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * SH7377 clock framework support
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; either 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 /* 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
52 
53 /* Fixed 32 KHz root clock from EXTALR pin */
54 static struct clk r_clk = {
55 	.rate           = 32768,
56 };
57 
58 /*
59  * 26MHz default rate for the EXTALC1 root input clock.
60  * If needed, reset this with clk_set_rate() from the platform code.
61  */
62 struct clk sh7377_extalc1_clk = {
63 	.rate		= 26666666,
64 };
65 
66 /*
67  * 48MHz default rate for the EXTAL2 root input clock.
68  * If needed, reset this with clk_set_rate() from the platform code.
69  */
70 struct clk sh7377_extal2_clk = {
71 	.rate		= 48000000,
72 };
73 
74 /* A fixed divide-by-2 block */
div2_recalc(struct clk * clk)75 static unsigned long div2_recalc(struct clk *clk)
76 {
77 	return clk->parent->rate / 2;
78 }
79 
80 static struct sh_clk_ops div2_clk_ops = {
81 	.recalc		= div2_recalc,
82 };
83 
84 /* Divide extalc1 by two */
85 static struct clk extalc1_div2_clk = {
86 	.ops		= &div2_clk_ops,
87 	.parent		= &sh7377_extalc1_clk,
88 };
89 
90 /* Divide extal2 by two */
91 static struct clk extal2_div2_clk = {
92 	.ops		= &div2_clk_ops,
93 	.parent		= &sh7377_extal2_clk,
94 };
95 
96 /* Divide extal2 by four */
97 static struct clk extal2_div4_clk = {
98 	.ops		= &div2_clk_ops,
99 	.parent		= &extal2_div2_clk,
100 };
101 
102 /* PLLC1 */
pllc1_recalc(struct clk * clk)103 static unsigned long pllc1_recalc(struct clk *clk)
104 {
105 	unsigned long mult = 1;
106 
107 	if (__raw_readl(PLLC1CR) & (1 << 14))
108 		mult = (((__raw_readl(RTFRQCR) >> 24) & 0x3f) + 1) * 2;
109 
110 	return clk->parent->rate * mult;
111 }
112 
113 static struct sh_clk_ops pllc1_clk_ops = {
114 	.recalc		= pllc1_recalc,
115 };
116 
117 static struct clk pllc1_clk = {
118 	.ops		= &pllc1_clk_ops,
119 	.flags		= CLK_ENABLE_ON_INIT,
120 	.parent		= &extalc1_div2_clk,
121 };
122 
123 /* Divide PLLC1 by two */
124 static struct clk pllc1_div2_clk = {
125 	.ops		= &div2_clk_ops,
126 	.parent		= &pllc1_clk,
127 };
128 
129 /* PLLC2 */
pllc2_recalc(struct clk * clk)130 static unsigned long pllc2_recalc(struct clk *clk)
131 {
132 	unsigned long mult = 1;
133 
134 	if (__raw_readl(PLLC2CR) & (1 << 31))
135 		mult = (((__raw_readl(PLLC2CR) >> 24) & 0x3f) + 1) * 2;
136 
137 	return clk->parent->rate * mult;
138 }
139 
140 static struct sh_clk_ops pllc2_clk_ops = {
141 	.recalc		= pllc2_recalc,
142 };
143 
144 static struct clk pllc2_clk = {
145 	.ops		= &pllc2_clk_ops,
146 	.flags		= CLK_ENABLE_ON_INIT,
147 	.parent		= &extalc1_div2_clk,
148 };
149 
150 static struct clk *main_clks[] = {
151 	&r_clk,
152 	&sh7377_extalc1_clk,
153 	&sh7377_extal2_clk,
154 	&extalc1_div2_clk,
155 	&extal2_div2_clk,
156 	&extal2_div4_clk,
157 	&pllc1_clk,
158 	&pllc1_div2_clk,
159 	&pllc2_clk,
160 };
161 
div4_kick(struct clk * clk)162 static void div4_kick(struct clk *clk)
163 {
164 	unsigned long value;
165 
166 	/* set KICK bit in SYFRQCR to update hardware setting */
167 	value = __raw_readl(SYFRQCR);
168 	value |= (1 << 31);
169 	__raw_writel(value, SYFRQCR);
170 }
171 
172 static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
173 			  24, 32, 36, 48, 0, 72, 96, 0 };
174 
175 static struct clk_div_mult_table div4_div_mult_table = {
176 	.divisors = divisors,
177 	.nr_divisors = ARRAY_SIZE(divisors),
178 };
179 
180 static struct clk_div4_table div4_table = {
181 	.div_mult_table = &div4_div_mult_table,
182 	.kick = div4_kick,
183 };
184 
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 };
188 
189 #define DIV4(_reg, _bit, _mask, _flags) \
190   SH_CLK_DIV4(&pllc1_clk, _reg, _bit, _mask, _flags)
191 
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),
206 };
207 
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,
211        DIV6_NR };
212 
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),
229 };
230 
231 enum { MSTP001,
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,
236        MSTP403,
237        MSTP_NR };
238 
239 #define MSTP(_parent, _reg, _bit, _flags) \
240   SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
241 
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 */
268 };
269 
270 static struct clk_lookup lookups[] = {
271 	/* main clocks */
272 	CLKDEV_CON_ID("r_clk", &r_clk),
273 	CLKDEV_CON_ID("extalc1", &sh7377_extalc1_clk),
274 	CLKDEV_CON_ID("extal2", &sh7377_extal2_clk),
275 	CLKDEV_CON_ID("extalc1_div2_clk", &extalc1_div2_clk),
276 	CLKDEV_CON_ID("extal2_div2_clk", &extal2_div2_clk),
277 	CLKDEV_CON_ID("extal2_div4_clk", &extal2_div4_clk),
278 	CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
279 	CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
280 	CLKDEV_CON_ID("pllc2_clk", &pllc2_clk),
281 
282 	/* DIV4 clocks */
283 	CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
284 	CLKDEV_CON_ID("zg_clk", &div4_clks[DIV4_ZG]),
285 	CLKDEV_CON_ID("b_clk", &div4_clks[DIV4_B]),
286 	CLKDEV_CON_ID("m1_clk", &div4_clks[DIV4_M1]),
287 	CLKDEV_CON_ID("csir_clk", &div4_clks[DIV4_CSIR]),
288 	CLKDEV_CON_ID("ztr_clk", &div4_clks[DIV4_ZTR]),
289 	CLKDEV_CON_ID("zt_clk", &div4_clks[DIV4_ZT]),
290 	CLKDEV_CON_ID("z_clk", &div4_clks[DIV4_Z]),
291 	CLKDEV_CON_ID("hp_clk", &div4_clks[DIV4_HP]),
292 	CLKDEV_CON_ID("zs_clk", &div4_clks[DIV4_ZS]),
293 	CLKDEV_CON_ID("zb_clk", &div4_clks[DIV4_ZB]),
294 	CLKDEV_CON_ID("zb3_clk", &div4_clks[DIV4_ZB3]),
295 	CLKDEV_CON_ID("cp_clk", &div4_clks[DIV4_CP]),
296 
297 	/* DIV6 clocks */
298 	CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]),
299 	CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]),
300 	CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]),
301 	CLKDEV_CON_ID("fmsi_clk", &div6_clks[DIV6_FMSI]),
302 	CLKDEV_CON_ID("fmso_clk", &div6_clks[DIV6_FMSO]),
303 	CLKDEV_CON_ID("fsi_clk", &div6_clks[DIV6_FSI]),
304 	CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]),
305 	CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]),
306 	CLKDEV_CON_ID("msu_clk", &div6_clks[DIV6_MSU]),
307 	CLKDEV_CON_ID("mvi3_clk", &div6_clks[DIV6_MVI3]),
308 	CLKDEV_CON_ID("hdmi_clk", &div6_clks[DIV6_HDMI]),
309 	CLKDEV_CON_ID("mf1_clk", &div6_clks[DIV6_MF1]),
310 	CLKDEV_CON_ID("mf2_clk", &div6_clks[DIV6_MF2]),
311 	CLKDEV_CON_ID("dsit_clk", &div6_clks[DIV6_DSIT]),
312 	CLKDEV_CON_ID("dsip_clk", &div6_clks[DIV6_DSIP]),
313 
314 	/* MSTP32 clocks */
315 	CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */
316 	CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[MSTP131]), /* VEU3 */
317 	CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[MSTP130]), /* VEU2 */
318 	CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks[MSTP129]), /* VEU1 */
319 	CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[MSTP128]), /* VEU0 */
320 	CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */
321 	CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[MSTP106]), /* JPU */
322 	CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[MSTP101]), /* VPU */
323 	CLKDEV_DEV_ID("uio_pdrv_genirq.6", &mstp_clks[MSTP223]), /* SPU2DSP0 */
324 	CLKDEV_DEV_ID("uio_pdrv_genirq.7", &mstp_clks[MSTP223]), /* SPU2DSP1 */
325 	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */
326 	CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP206]), /* SCIFB */
327 	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */
328 	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), /* SCIFA1 */
329 	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */
330 	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */
331 	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
332 	CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */
333 	CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */
334 	CLKDEV_DEV_ID("sh_irda", &mstp_clks[MSTP325]), /* IRDA */
335 	CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */
336 	CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USBHS */
337 	CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP322]), /* USBHS */
338 	CLKDEV_DEV_ID("sh_flctl", &mstp_clks[MSTP315]), /* FLCTL */
339 	CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
340 	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
341 	CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
342 };
343 
sh7377_clock_init(void)344 void __init sh7377_clock_init(void)
345 {
346 	int k, ret = 0;
347 
348 	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
349 		ret = clk_register(main_clks[k]);
350 
351 	if (!ret)
352 		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
353 
354 	if (!ret)
355 		ret = sh_clk_div6_register(div6_clks, DIV6_NR);
356 
357 	if (!ret)
358 		ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
359 
360 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
361 
362 	if (!ret)
363 		shmobile_clk_init();
364 	else
365 		panic("failed to setup sh7377 clocks\n");
366 }
367