• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * SH7367 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; 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>
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 /* 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
49 
50 /* Fixed 32 KHz root clock from EXTALR pin */
51 static struct clk r_clk = {
52 	.rate           = 32768,
53 };
54 
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  */
59 struct clk sh7367_extalb1_clk = {
60 	.rate		= 26666666,
61 };
62 
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  */
67 struct clk sh7367_extal2_clk = {
68 	.rate		= 48000000,
69 };
70 
71 /* A fixed divide-by-2 block */
div2_recalc(struct clk * clk)72 static unsigned long div2_recalc(struct clk *clk)
73 {
74 	return clk->parent->rate / 2;
75 }
76 
77 static struct sh_clk_ops div2_clk_ops = {
78 	.recalc		= div2_recalc,
79 };
80 
81 /* Divide extalb1 by two */
82 static struct clk extalb1_div2_clk = {
83 	.ops		= &div2_clk_ops,
84 	.parent		= &sh7367_extalb1_clk,
85 };
86 
87 /* Divide extal2 by two */
88 static struct clk extal2_div2_clk = {
89 	.ops		= &div2_clk_ops,
90 	.parent		= &sh7367_extal2_clk,
91 };
92 
93 /* PLLC1 */
pllc1_recalc(struct clk * clk)94 static 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 
104 static struct sh_clk_ops pllc1_clk_ops = {
105 	.recalc		= pllc1_recalc,
106 };
107 
108 static 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 */
115 static struct clk pllc1_div2_clk = {
116 	.ops		= &div2_clk_ops,
117 	.parent		= &pllc1_clk,
118 };
119 
120 /* PLLC2 */
pllc2_recalc(struct clk * clk)121 static 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 
131 static struct sh_clk_ops pllc2_clk_ops = {
132 	.recalc		= pllc2_recalc,
133 };
134 
135 static struct clk pllc2_clk = {
136 	.ops		= &pllc2_clk_ops,
137 	.flags		= CLK_ENABLE_ON_INIT,
138 	.parent		= &extalb1_div2_clk,
139 };
140 
141 static 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 
div4_kick(struct clk * clk)152 static 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 
162 static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
163 			  24, 32, 36, 48, 0, 72, 0, 0 };
164 
165 static struct clk_div_mult_table div4_div_mult_table = {
166 	.divisors = divisors,
167 	.nr_divisors = ARRAY_SIZE(divisors),
168 };
169 
170 static struct clk_div4_table div4_table = {
171 	.div_mult_table = &div4_div_mult_table,
172 	.kick = div4_kick,
173 };
174 
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 };
178 
179 #define DIV4(_reg, _bit, _mask, _flags) \
180   SH_CLK_DIV4(&pllc1_clk, _reg, _bit, _mask, _flags)
181 
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),
196 };
197 
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,
201        DIV6_NR };
202 
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),
216 };
217 
218 enum { 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 
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 */
260 };
261 
262 static struct clk_lookup lookups[] = {
263 	/* main clocks */
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),
272 
273 	/* DIV4 clocks */
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]),
286 
287 	/* DIV6 clocks */
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]),
300 
301 	/* MSTP32 clocks */
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 */
331 };
332 
sh7367_clock_init(void)333 void __init sh7367_clock_init(void)
334 {
335 	int k, ret = 0;
336 
337 	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
338 		ret = clk_register(main_clks[k]);
339 
340 	if (!ret)
341 		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
342 
343 	if (!ret)
344 		ret = sh_clk_div6_register(div6_clks, DIV6_NR);
345 
346 	if (!ret)
347 		ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
348 
349 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
350 
351 	if (!ret)
352 		shmobile_clk_init();
353 	else
354 		panic("failed to setup sh7367 clocks\n");
355 }
356