• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/arm/mach-shmobile/
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 <mach/common.h>
24#include <asm/clkdev.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 */
51static 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 */
59struct 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 */
67struct clk sh7367_extal2_clk = {
68	.rate		= 48000000,
69};
70
71/* A fixed divide-by-2 block */
72static unsigned long div2_recalc(struct clk *clk)
73{
74	return clk->parent->rate / 2;
75}
76
77static struct clk_ops div2_clk_ops = {
78	.recalc		= div2_recalc,
79};
80
81/* Divide extalb1 by two */
82static struct clk extalb1_div2_clk = {
83	.ops		= &div2_clk_ops,
84	.parent		= &sh7367_extalb1_clk,
85};
86
87/* Divide extal2 by two */
88static struct clk extal2_div2_clk = {
89	.ops		= &div2_clk_ops,
90	.parent		= &sh7367_extal2_clk,
91};
92
93/* PLLC1 */
94static 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
104static struct clk_ops pllc1_clk_ops = {
105	.recalc		= pllc1_recalc,
106};
107
108static 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 */
115static struct clk pllc1_div2_clk = {
116	.ops		= &div2_clk_ops,
117	.parent		= &pllc1_clk,
118};
119
120/* PLLC2 */
121static 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
131static struct clk_ops pllc2_clk_ops = {
132	.recalc		= pllc2_recalc,
133};
134
135static struct clk pllc2_clk = {
136	.ops		= &pllc2_clk_ops,
137	.flags		= CLK_ENABLE_ON_INIT,
138	.parent		= &extalb1_div2_clk,
139};
140
141static 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
152static 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
162static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
163			  24, 32, 36, 48, 0, 72, 0, 0 };
164
165static struct clk_div_mult_table div4_div_mult_table = {
166	.divisors = divisors,
167	.nr_divisors = ARRAY_SIZE(divisors),
168};
169
170static struct clk_div4_table div4_table = {
171	.div_mult_table = &div4_div_mult_table,
172	.kick = div4_kick,
173};
174
175enum { 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
182static 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
198enum { 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
203static 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
218enum { 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
231static 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#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
263#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
264
265static struct clk_lookup lookups[] = {
266	/* main clocks */
267	CLKDEV_CON_ID("r_clk", &r_clk),
268	CLKDEV_CON_ID("extalb1", &sh7367_extalb1_clk),
269	CLKDEV_CON_ID("extal2", &sh7367_extal2_clk),
270	CLKDEV_CON_ID("extalb1_div2_clk", &extalb1_div2_clk),
271	CLKDEV_CON_ID("extal2_div2_clk", &extal2_div2_clk),
272	CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
273	CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
274	CLKDEV_CON_ID("pllc2_clk", &pllc2_clk),
275
276	/* DIV4 clocks */
277	CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
278	CLKDEV_CON_ID("g_clk", &div4_clks[DIV4_G]),
279	CLKDEV_CON_ID("b_clk", &div4_clks[DIV4_B]),
280	CLKDEV_CON_ID("zx_clk", &div4_clks[DIV4_ZX]),
281	CLKDEV_CON_ID("zt_clk", &div4_clks[DIV4_ZT]),
282	CLKDEV_CON_ID("z_clk", &div4_clks[DIV4_Z]),
283	CLKDEV_CON_ID("zd_clk", &div4_clks[DIV4_ZD]),
284	CLKDEV_CON_ID("hp_clk", &div4_clks[DIV4_HP]),
285	CLKDEV_CON_ID("zs_clk", &div4_clks[DIV4_ZS]),
286	CLKDEV_CON_ID("zb_clk", &div4_clks[DIV4_ZB]),
287	CLKDEV_CON_ID("zb3_clk", &div4_clks[DIV4_ZB3]),
288	CLKDEV_CON_ID("cp_clk", &div4_clks[DIV4_CP]),
289
290	/* DIV6 clocks */
291	CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]),
292	CLKDEV_CON_ID("siua_clk", &div6_clks[DIV6_SIUA]),
293	CLKDEV_CON_ID("siub_clk", &div6_clks[DIV6_SIUB]),
294	CLKDEV_CON_ID("msu_clk", &div6_clks[DIV6_MSU]),
295	CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]),
296	CLKDEV_CON_ID("mvi3_clk", &div6_clks[DIV6_MVI3]),
297	CLKDEV_CON_ID("mf1_clk", &div6_clks[DIV6_MF1]),
298	CLKDEV_CON_ID("mf2_clk", &div6_clks[DIV6_MF2]),
299	CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]),
300	CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]),
301	CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]),
302	CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]),
303
304	/* MSTP32 clocks */
305	CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[RTMSTP001]), /* IIC2 */
306	CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[RTMSTP231]), /* VEU3 */
307	CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[RTMSTP230]), /* VEU2 */
308	CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks[RTMSTP229]), /* VEU1 */
309	CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[RTMSTP228]), /* VEU0 */
310	CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[RTMSTP226]), /* VEU2H */
311	CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[RTMSTP216]), /* IIC0 */
312	CLKDEV_DEV_ID("uio_pdrv_genirq.6", &mstp_clks[RTMSTP206]), /* JPU */
313	CLKDEV_DEV_ID("sh-vou", &mstp_clks[RTMSTP205]), /* VOU */
314	CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[RTMSTP201]), /* VPU */
315	CLKDEV_DEV_ID("uio_pdrv_genirq.7", &mstp_clks[SYMSTP023]), /* SPU1 */
316	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[SYMSTP007]), /* SCIFA5 */
317	CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[SYMSTP006]), /* SCIFB */
318	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[SYMSTP004]), /* SCIFA0 */
319	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[SYMSTP003]), /* SCIFA1 */
320	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[SYMSTP002]), /* SCIFA2 */
321	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[SYMSTP001]), /* SCIFA3 */
322	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[SYMSTP000]), /* SCIFA4 */
323	CLKDEV_DEV_ID("sh_siu", &mstp_clks[SYMSTP231]), /* SIU */
324	CLKDEV_CON_ID("cmt1", &mstp_clks[SYMSTP229]), /* CMT10 */
325	CLKDEV_DEV_ID("sh_irda", &mstp_clks[SYMSTP225]), /* IRDA */
326	CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[SYMSTP223]), /* IIC1 */
327	CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[SYMSTP222]), /* USBHS */
328	CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[SYMSTP222]), /* USBHS */
329	CLKDEV_DEV_ID("sh_flctl", &mstp_clks[SYMSTP215]), /* FLCTL */
330	CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[SYMSTP214]), /* SDHI0 */
331	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[SYMSTP213]), /* SDHI1 */
332	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[SYMSTP211]), /* SDHI2 */
333	CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[CMMSTP003]), /* KEYSC */
334};
335
336void __init sh7367_clock_init(void)
337{
338	int k, ret = 0;
339
340	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
341		ret = clk_register(main_clks[k]);
342
343	if (!ret)
344		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
345
346	if (!ret)
347		ret = sh_clk_div6_register(div6_clks, DIV6_NR);
348
349	if (!ret)
350		ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
351
352	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
353
354	if (!ret)
355		clk_init();
356	else
357		panic("failed to setup sh7367 clocks\n");
358}
359