Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
clock-sh7377.c
Go to the documentation of this file.
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 IOMEM(0xe6150000)
28 #define SYFRQCR IOMEM(0xe6150004)
29 #define CMFRQCR IOMEM(0xe61500E0)
30 #define VCLKCR1 IOMEM(0xe6150008)
31 #define VCLKCR2 IOMEM(0xe615000C)
32 #define VCLKCR3 IOMEM(0xe615001C)
33 #define FMSICKCR IOMEM(0xe6150010)
34 #define FMSOCKCR IOMEM(0xe6150014)
35 #define FSICKCR IOMEM(0xe6150018)
36 #define PLLC1CR IOMEM(0xe6150028)
37 #define PLLC2CR IOMEM(0xe615002C)
38 #define SUBUSBCKCR IOMEM(0xe6150080)
39 #define SPUCKCR IOMEM(0xe6150084)
40 #define MSUCKCR IOMEM(0xe6150088)
41 #define MVI3CKCR IOMEM(0xe6150090)
42 #define HDMICKCR IOMEM(0xe6150094)
43 #define MFCK1CR IOMEM(0xe6150098)
44 #define MFCK2CR IOMEM(0xe615009C)
45 #define DSITCKCR IOMEM(0xe6150060)
46 #define DSIPCKCR IOMEM(0xe6150064)
47 #define SMSTPCR0 IOMEM(0xe6150130)
48 #define SMSTPCR1 IOMEM(0xe6150134)
49 #define SMSTPCR2 IOMEM(0xe6150138)
50 #define SMSTPCR3 IOMEM(0xe615013C)
51 #define SMSTPCR4 IOMEM(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  */
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  */
71  .rate = 48000000,
72 };
73 
74 /* A fixed divide-by-2 block */
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 */
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 */
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,
154  &extalc1_div2_clk,
155  &extal2_div2_clk,
156  &extal2_div4_clk,
157  &pllc1_clk,
158  &pllc1_div2_clk,
159  &pllc2_clk,
160 };
161 
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 
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 
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,
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 
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_mstp_register(mstp_clks, MSTP_NR);
359 
360  clkdev_add_table(lookups, ARRAY_SIZE(lookups));
361 
362  if (!ret)
364  else
365  panic("failed to setup sh7377 clocks\n");
366 }