aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMagnus Damm <damm@opensource.se>2010-12-03 02:22:31 -0500
committerPaul Mundt <lethal@linux-sh.org>2010-12-03 02:29:15 -0500
commitf6d84f4a7df8057247a3f1723169586af3882436 (patch)
treedf2e040af9efce7a277de6211315875723c5f4ca
parent208c7dc2727ec0fbc678da5e749bcc178c08463d (diff)
ARM: mach-shmobile: AG5 clock framework improvements
This patch improves the state of the AG5 clock framework support. The main clock parent is automatically detected, but most of the clocks are not used by any driver or subsystem at this point. More work is needed for support of multi media hardware such as FSI and/or LCDC/MIPI-DSI. Signed-off-by: Magnus Damm <damm@opensource.se> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r--arch/arm/mach-shmobile/clock-sh73a0.c279
-rw-r--r--arch/arm/mach-shmobile/include/mach/common.h2
2 files changed, 256 insertions, 25 deletions
diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
index 81fd429c3c24..7c8b5179e444 100644
--- a/arch/arm/mach-shmobile/clock-sh73a0.c
+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
@@ -23,37 +23,241 @@
23#include <mach/common.h> 23#include <mach/common.h>
24#include <asm/clkdev.h> 24#include <asm/clkdev.h>
25 25
26#define FRQCRA 0xe6150000
27#define FRQCRB 0xe6150004
28#define FRQCRD 0xe61500e4
29#define VCLKCR1 0xe6150008
30#define VCLKCR2 0xe615000C
31#define VCLKCR3 0xe615001C
32#define ZBCKCR 0xe6150010
33#define FLCKCR 0xe6150014
34#define SD0CKCR 0xe6150074
35#define SD1CKCR 0xe6150078
36#define SD2CKCR 0xe615007C
37#define FSIACKCR 0xe6150018
38#define FSIBCKCR 0xe6150090
39#define SUBCKCR 0xe6150080
40#define SPUACKCR 0xe6150084
41#define SPUVCKCR 0xe6150094
42#define MSUCKCR 0xe6150088
43#define HSICKCR 0xe615008C
44#define MFCK1CR 0xe6150098
45#define MFCK2CR 0xe615009C
46#define DSITCKCR 0xe6150060
47#define DSI0PCKCR 0xe6150064
48#define DSI1PCKCR 0xe6150068
49#define DSI0PHYCR 0xe615006C
50#define DSI1PHYCR 0xe6150070
51#define PLLECR 0xe61500d0
52#define PLL0CR 0xe61500d8
53#define PLL1CR 0xe6150028
54#define PLL2CR 0xe615002c
55#define PLL3CR 0xe61500dc
26#define SMSTPCR0 0xe6150130 56#define SMSTPCR0 0xe6150130
27#define SMSTPCR1 0xe6150134 57#define SMSTPCR1 0xe6150134
28#define SMSTPCR2 0xe6150138 58#define SMSTPCR2 0xe6150138
29#define SMSTPCR3 0xe615013c 59#define SMSTPCR3 0xe615013c
30#define SMSTPCR4 0xe6150140 60#define SMSTPCR4 0xe6150140
31#define SMSTPCR5 0xe6150144 61#define SMSTPCR5 0xe6150144
62#define CKSCR 0xe61500c0
32 63
33/* Fixed 32 KHz root clock from EXTALR pin */ 64/* Fixed 32 KHz root clock from EXTALR pin */
34static struct clk r_clk = { 65static struct clk r_clk = {
35 .rate = 32768, 66 .rate = 32768,
36}; 67};
37 68
38/* Temporarily fixed 48 MHz SUB clock */ 69/*
39static struct clk sub_clk = { 70 * 26MHz default rate for the EXTAL1 root input clock.
40 .rate = 48000000, 71 * If needed, reset this with clk_set_rate() from the platform code.
72 */
73struct clk sh73a0_extal1_clk = {
74 .rate = 26000000,
75};
76
77/*
78 * 48MHz default rate for the EXTAL2 root input clock.
79 * If needed, reset this with clk_set_rate() from the platform code.
80 */
81struct clk sh73a0_extal2_clk = {
82 .rate = 48000000,
83};
84
85/* A fixed divide-by-2 block */
86static unsigned long div2_recalc(struct clk *clk)
87{
88 return clk->parent->rate / 2;
89}
90
91static struct clk_ops div2_clk_ops = {
92 .recalc = div2_recalc,
93};
94
95/* Divide extal1 by two */
96static struct clk extal1_div2_clk = {
97 .ops = &div2_clk_ops,
98 .parent = &sh73a0_extal1_clk,
99};
100
101/* Divide extal2 by two */
102static struct clk extal2_div2_clk = {
103 .ops = &div2_clk_ops,
104 .parent = &sh73a0_extal2_clk,
105};
106
107static struct clk_ops main_clk_ops = {
108 .recalc = followparent_recalc,
109};
110
111/* Main clock */
112static struct clk main_clk = {
113 .ops = &main_clk_ops,
114};
115
116/* PLL0, PLL1, PLL2, PLL3 */
117static unsigned long pll_recalc(struct clk *clk)
118{
119 unsigned long mult = 1;
120
121 if (__raw_readl(PLLECR) & (1 << clk->enable_bit))
122 mult = (((__raw_readl(clk->enable_reg) >> 24) & 0x3f) + 1);
123
124 return clk->parent->rate * mult;
125}
126
127static struct clk_ops pll_clk_ops = {
128 .recalc = pll_recalc,
129};
130
131static struct clk pll0_clk = {
132 .ops = &pll_clk_ops,
133 .flags = CLK_ENABLE_ON_INIT,
134 .parent = &main_clk,
135 .enable_reg = (void __iomem *)PLL0CR,
136 .enable_bit = 0,
41}; 137};
42 138
43/* Temporarily fixed 104 MHz HP clock */ 139static struct clk pll1_clk = {
44static struct clk hp_clk = { 140 .ops = &pll_clk_ops,
45 .rate = 104000000, 141 .flags = CLK_ENABLE_ON_INIT,
142 .parent = &main_clk,
143 .enable_reg = (void __iomem *)PLL1CR,
144 .enable_bit = 1,
145};
146
147static struct clk pll2_clk = {
148 .ops = &pll_clk_ops,
149 .flags = CLK_ENABLE_ON_INIT,
150 .parent = &main_clk,
151 .enable_reg = (void __iomem *)PLL2CR,
152 .enable_bit = 2,
153};
154
155static struct clk pll3_clk = {
156 .ops = &pll_clk_ops,
157 .flags = CLK_ENABLE_ON_INIT,
158 .parent = &main_clk,
159 .enable_reg = (void __iomem *)PLL3CR,
160 .enable_bit = 3,
161};
162
163/* Divide PLL1 by two */
164static struct clk pll1_div2_clk = {
165 .ops = &div2_clk_ops,
166 .parent = &pll1_clk,
46}; 167};
47 168
48static struct clk *main_clks[] = { 169static struct clk *main_clks[] = {
49 &r_clk, 170 &r_clk,
50 &sub_clk, 171 &sh73a0_extal1_clk,
51 &hp_clk, 172 &sh73a0_extal2_clk,
173 &extal1_div2_clk,
174 &extal2_div2_clk,
175 &main_clk,
176 &pll0_clk,
177 &pll1_clk,
178 &pll2_clk,
179 &pll3_clk,
180 &pll1_div2_clk,
181};
182
183static void div4_kick(struct clk *clk)
184{
185 unsigned long value;
186
187 /* set KICK bit in FRQCRB to update hardware setting */
188 value = __raw_readl(FRQCRB);
189 value |= (1 << 31);
190 __raw_writel(value, FRQCRB);
191}
192
193static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
194 24, 0, 36, 48 };
195
196static struct clk_div_mult_table div4_div_mult_table = {
197 .divisors = divisors,
198 .nr_divisors = ARRAY_SIZE(divisors),
199};
200
201static struct clk_div4_table div4_table = {
202 .div_mult_table = &div4_div_mult_table,
203 .kick = div4_kick,
204};
205
206enum { DIV4_I, DIV4_ZG, DIV4_M3, DIV4_B, DIV4_M1, DIV4_M2,
207 DIV4_Z, DIV4_ZTR, DIV4_ZT, DIV4_ZX, DIV4_HP, DIV4_NR };
208
209#define DIV4(_reg, _bit, _mask, _flags) \
210 SH_CLK_DIV4(&pll1_clk, _reg, _bit, _mask, _flags)
211
212static struct clk div4_clks[DIV4_NR] = {
213 [DIV4_I] = DIV4(FRQCRA, 20, 0xfff, CLK_ENABLE_ON_INIT),
214 [DIV4_ZG] = DIV4(FRQCRA, 16, 0xbff, CLK_ENABLE_ON_INIT),
215 [DIV4_M3] = DIV4(FRQCRA, 8, 0xfff, CLK_ENABLE_ON_INIT),
216 [DIV4_B] = DIV4(FRQCRA, 8, 0xfff, CLK_ENABLE_ON_INIT),
217 [DIV4_M1] = DIV4(FRQCRA, 4, 0xfff, 0),
218 [DIV4_M2] = DIV4(FRQCRA, 0, 0xfff, 0),
219 [DIV4_Z] = DIV4(FRQCRB, 24, 0xbff, 0),
220 [DIV4_ZTR] = DIV4(FRQCRB, 20, 0xfff, 0),
221 [DIV4_ZT] = DIV4(FRQCRB, 16, 0xfff, 0),
222 [DIV4_ZX] = DIV4(FRQCRB, 12, 0xfff, 0),
223 [DIV4_HP] = DIV4(FRQCRB, 4, 0xfff, 0),
224};
225
226enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_ZB1,
227 DIV6_FLCTL, DIV6_SDHI0, DIV6_SDHI1, DIV6_SDHI2,
228 DIV6_FSIA, DIV6_FSIB, DIV6_SUB,
229 DIV6_SPUA, DIV6_SPUV, DIV6_MSU,
230 DIV6_HSI, DIV6_MFG1, DIV6_MFG2,
231 DIV6_DSIT, DIV6_DSI0P, DIV6_DSI1P,
232 DIV6_NR };
233
234static struct clk div6_clks[DIV6_NR] = {
235 [DIV6_VCK1] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR1, 0),
236 [DIV6_VCK2] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR2, 0),
237 [DIV6_VCK3] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR3, 0),
238 [DIV6_ZB1] = SH_CLK_DIV6(&pll1_div2_clk, ZBCKCR, 0),
239 [DIV6_FLCTL] = SH_CLK_DIV6(&pll1_div2_clk, FLCKCR, 0),
240 [DIV6_SDHI0] = SH_CLK_DIV6(&pll1_div2_clk, SD0CKCR, 0),
241 [DIV6_SDHI1] = SH_CLK_DIV6(&pll1_div2_clk, SD1CKCR, 0),
242 [DIV6_SDHI2] = SH_CLK_DIV6(&pll1_div2_clk, SD2CKCR, 0),
243 [DIV6_FSIA] = SH_CLK_DIV6(&pll1_div2_clk, FSIACKCR, 0),
244 [DIV6_FSIB] = SH_CLK_DIV6(&pll1_div2_clk, FSIBCKCR, 0),
245 [DIV6_SUB] = SH_CLK_DIV6(&sh73a0_extal2_clk, SUBCKCR, 0),
246 [DIV6_SPUA] = SH_CLK_DIV6(&pll1_div2_clk, SPUACKCR, 0),
247 [DIV6_SPUV] = SH_CLK_DIV6(&pll1_div2_clk, SPUVCKCR, 0),
248 [DIV6_MSU] = SH_CLK_DIV6(&pll1_div2_clk, MSUCKCR, 0),
249 [DIV6_HSI] = SH_CLK_DIV6(&pll1_div2_clk, HSICKCR, 0),
250 [DIV6_MFG1] = SH_CLK_DIV6(&pll1_div2_clk, MFCK1CR, 0),
251 [DIV6_MFG2] = SH_CLK_DIV6(&pll1_div2_clk, MFCK2CR, 0),
252 [DIV6_DSIT] = SH_CLK_DIV6(&pll1_div2_clk, DSITCKCR, 0),
253 [DIV6_DSI0P] = SH_CLK_DIV6(&pll1_div2_clk, DSI0PCKCR, 0),
254 [DIV6_DSI1P] = SH_CLK_DIV6(&pll1_div2_clk, DSI1PCKCR, 0),
52}; 255};
53 256
54enum { MSTP001, 257enum { MSTP001,
55 MSTP116, 258 MSTP116,
56 MSTP219, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, 259 MSTP219,
260 MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
57 MSTP331, MSTP329, MSTP323, 261 MSTP331, MSTP329, MSTP323,
58 MSTP411, MSTP410, MSTP403, 262 MSTP411, MSTP410, MSTP403,
59 MSTP_NR }; 263 MSTP_NR };
@@ -62,27 +266,30 @@ enum { MSTP001,
62 SH_CLK_MSTP32(_parent, _reg, _bit, _flags) 266 SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
63 267
64static struct clk mstp_clks[MSTP_NR] = { 268static struct clk mstp_clks[MSTP_NR] = {
65 [MSTP001] = MSTP(&hp_clk, SMSTPCR0, 1, 0), /* I2C2 */ 269 [MSTP001] = MSTP(&div4_clks[DIV4_HP], SMSTPCR0, 1, 0), /* IIC2 */
66 [MSTP116] = MSTP(&hp_clk, SMSTPCR1, 16, 0), /* I2C0 */ 270 [MSTP116] = MSTP(&div4_clks[DIV4_HP], SMSTPCR1, 16, 0), /* IIC0 */
67 [MSTP219] = MSTP(&sub_clk, SMSTPCR2, 19, 0), /* SCIFA7 */ 271 [MSTP219] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 19, 0), /* SCIFA7 */
68 [MSTP207] = MSTP(&sub_clk, SMSTPCR2, 7, 0), /* SCIFA5 */ 272 [MSTP207] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */
69 [MSTP206] = MSTP(&sub_clk, SMSTPCR2, 6, 0), /* SCIFB */ 273 [MSTP206] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */
70 [MSTP204] = MSTP(&sub_clk, SMSTPCR2, 4, 0), /* SCIFA0 */ 274 [MSTP204] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */
71 [MSTP203] = MSTP(&sub_clk, SMSTPCR2, 3, 0), /* SCIFA1 */ 275 [MSTP203] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 3, 0), /* SCIFA1 */
72 [MSTP202] = MSTP(&sub_clk, SMSTPCR2, 2, 0), /* SCIFA2 */ 276 [MSTP202] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 2, 0), /* SCIFA2 */
73 [MSTP201] = MSTP(&sub_clk, SMSTPCR2, 1, 0), /* SCIFA3 */ 277 [MSTP201] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */
74 [MSTP200] = MSTP(&sub_clk, SMSTPCR2, 0, 0), /* SCIFA4 */ 278 [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */
75 [MSTP331] = MSTP(&sub_clk, SMSTPCR3, 31, 0), /* SCIFA6 */ 279 [MSTP331] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 31, 0), /* SCIFA6 */
76 [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ 280 [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
77 [MSTP323] = MSTP(&hp_clk, SMSTPCR3, 23, 0), /* I2C1 */ 281 [MSTP323] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 23, 0), /* IIC1 */
78 [MSTP411] = MSTP(&hp_clk, SMSTPCR4, 11, 0), /* I2C3 */ 282 [MSTP411] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 11, 0), /* IIC3 */
79 [MSTP410] = MSTP(&hp_clk, SMSTPCR4, 10, 0), /* I2C4 */ 283 [MSTP410] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 10, 0), /* IIC4 */
80 [MSTP403] = MSTP(&r_clk, SMSTPCR4, 0, 0), /* KEYSC0 */
81}; 284};
82 285
286#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
83#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk } 287#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
84 288
85static struct clk_lookup lookups[] = { 289static struct clk_lookup lookups[] = {
290 /* main clocks */
291 CLKDEV_CON_ID("r_clk", &r_clk),
292
86 /* MSTP32 clocks */ 293 /* MSTP32 clocks */
87 CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* I2C2 */ 294 CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* I2C2 */
88 CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* I2C0 */ 295 CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* I2C0 */
@@ -106,10 +313,32 @@ void __init sh73a0_clock_init(void)
106{ 313{
107 int k, ret = 0; 314 int k, ret = 0;
108 315
316 /* detect main clock parent */
317 switch ((__raw_readl(CKSCR) >> 24) & 0x03) {
318 case 0:
319 main_clk.parent = &sh73a0_extal1_clk;
320 break;
321 case 1:
322 main_clk.parent = &extal1_div2_clk;
323 break;
324 case 2:
325 main_clk.parent = &sh73a0_extal2_clk;
326 break;
327 case 3:
328 main_clk.parent = &extal2_div2_clk;
329 break;
330 }
331
109 for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) 332 for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
110 ret = clk_register(main_clks[k]); 333 ret = clk_register(main_clks[k]);
111 334
112 if (!ret) 335 if (!ret)
336 ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
337
338 if (!ret)
339 ret = sh_clk_div6_register(div6_clks, DIV6_NR);
340
341 if (!ret)
113 ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); 342 ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
114 343
115 clkdev_add_table(lookups, ARRAY_SIZE(lookups)); 344 clkdev_add_table(lookups, ARRAY_SIZE(lookups));
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index d8f91a5f692f..15932fd2435e 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -34,5 +34,7 @@ extern void sh73a0_add_early_devices(void);
34extern void sh73a0_add_standard_devices(void); 34extern void sh73a0_add_standard_devices(void);
35extern void sh73a0_clock_init(void); 35extern void sh73a0_clock_init(void);
36extern void sh73a0_pinmux_init(void); 36extern void sh73a0_pinmux_init(void);
37extern struct clk sh73a0_extal1_clk;
38extern struct clk sh73a0_extal2_clk;
37 39
38#endif /* __ARCH_MACH_COMMON_H */ 40#endif /* __ARCH_MACH_COMMON_H */