• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/arch/arm/mach-shmobile/
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 <mach/common.h>
24#include <asm/clkdev.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 */
54static 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 */
62struct 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 */
70struct clk sh7377_extal2_clk = {
71	.rate		= 48000000,
72};
73
74/* A fixed divide-by-2 block */
75static unsigned long div2_recalc(struct clk *clk)
76{
77	return clk->parent->rate / 2;
78}
79
80static struct clk_ops div2_clk_ops = {
81	.recalc		= div2_recalc,
82};
83
84/* Divide extalc1 by two */
85static struct clk extalc1_div2_clk = {
86	.ops		= &div2_clk_ops,
87	.parent		= &sh7377_extalc1_clk,
88};
89
90/* Divide extal2 by two */
91static struct clk extal2_div2_clk = {
92	.ops		= &div2_clk_ops,
93	.parent		= &sh7377_extal2_clk,
94};
95
96/* Divide extal2 by four */
97static struct clk extal2_div4_clk = {
98	.ops		= &div2_clk_ops,
99	.parent		= &extal2_div2_clk,
100};
101
102/* PLLC1 */
103static 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
113static struct clk_ops pllc1_clk_ops = {
114	.recalc		= pllc1_recalc,
115};
116
117static 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 */
124static struct clk pllc1_div2_clk = {
125	.ops		= &div2_clk_ops,
126	.parent		= &pllc1_clk,
127};
128
129/* PLLC2 */
130static 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
140static struct clk_ops pllc2_clk_ops = {
141	.recalc		= pllc2_recalc,
142};
143
144static struct clk pllc2_clk = {
145	.ops		= &pllc2_clk_ops,
146	.flags		= CLK_ENABLE_ON_INIT,
147	.parent		= &extalc1_div2_clk,
148};
149
150static 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
162static 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
172static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
173			  24, 32, 36, 48, 0, 72, 96, 0 };
174
175static struct clk_div_mult_table div4_div_mult_table = {
176	.divisors = divisors,
177	.nr_divisors = ARRAY_SIZE(divisors),
178};
179
180static struct clk_div4_table div4_table = {
181	.div_mult_table = &div4_div_mult_table,
182	.kick = div4_kick,
183};
184
185enum { 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
192static 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
208enum { 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
213static 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
231enum { 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
242static 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#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
271#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
272
273static struct clk_lookup lookups[] = {
274	/* main clocks */
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),
284
285	/* DIV4 clocks */
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]),
299
300	/* DIV6 clocks */
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]),
316
317	/* MSTP32 clocks */
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_CON_ID("cmt1", &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 */
345};
346
347void __init sh7377_clock_init(void)
348{
349	int k, ret = 0;
350
351	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
352		ret = clk_register(main_clks[k]);
353
354	if (!ret)
355		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
356
357	if (!ret)
358		ret = sh_clk_div6_register(div6_clks, DIV6_NR);
359
360	if (!ret)
361		ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
362
363	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
364
365	if (!ret)
366		clk_init();
367	else
368		panic("failed to setup sh7377 clocks\n");
369}
370