diff options
-rw-r--r-- | arch/sh/Kconfig | 2 | ||||
-rw-r--r-- | arch/sh/boards/board-sh7785lcr.c | 22 | ||||
-rw-r--r-- | arch/sh/include/asm/clock.h | 2 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4a/clock-sh7785.c | 203 |
4 files changed, 125 insertions, 104 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index d7990cd2f8d4..df764c56b050 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
@@ -514,7 +514,7 @@ config SH_PCLK_FREQ | |||
514 | platforms lacking an RTC. | 514 | platforms lacking an RTC. |
515 | 515 | ||
516 | config SH_CLK_CPG_LEGACY | 516 | config SH_CLK_CPG_LEGACY |
517 | def_bool y | 517 | def_bool y if !CPU_SUBTYPE_SH7785 |
518 | 518 | ||
519 | config SH_CLK_MD | 519 | config SH_CLK_MD |
520 | int "CPU Mode Pin Setting" | 520 | int "CPU Mode Pin Setting" |
diff --git a/arch/sh/boards/board-sh7785lcr.c b/arch/sh/boards/board-sh7785lcr.c index 6f94f17adc46..33b194b0454d 100644 --- a/arch/sh/boards/board-sh7785lcr.c +++ b/arch/sh/boards/board-sh7785lcr.c | |||
@@ -2,12 +2,12 @@ | |||
2 | * Renesas Technology Corp. R0P7785LC0011RL Support. | 2 | * Renesas Technology Corp. R0P7785LC0011RL Support. |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Yoshihiro Shimoda | 4 | * Copyright (C) 2008 Yoshihiro Shimoda |
5 | * Copyright (C) 2009 Paul Mundt | ||
5 | * | 6 | * |
6 | * This file is subject to the terms and conditions of the GNU General Public | 7 | * This file is subject to the terms and conditions of the GNU General Public |
7 | * License. See the file "COPYING" in the main directory of this archive | 8 | * License. See the file "COPYING" in the main directory of this archive |
8 | * for more details. | 9 | * for more details. |
9 | */ | 10 | */ |
10 | |||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
13 | #include <linux/sm501.h> | 13 | #include <linux/sm501.h> |
@@ -19,8 +19,11 @@ | |||
19 | #include <linux/i2c-pca-platform.h> | 19 | #include <linux/i2c-pca-platform.h> |
20 | #include <linux/i2c-algo-pca.h> | 20 | #include <linux/i2c-algo-pca.h> |
21 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
22 | #include <asm/heartbeat.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/errno.h> | ||
23 | #include <mach/sh7785lcr.h> | 24 | #include <mach/sh7785lcr.h> |
25 | #include <asm/heartbeat.h> | ||
26 | #include <asm/clock.h> | ||
24 | 27 | ||
25 | /* | 28 | /* |
26 | * NOTE: This board has 2 physical memory maps. | 29 | * NOTE: This board has 2 physical memory maps. |
@@ -273,6 +276,20 @@ void __init init_sh7785lcr_IRQ(void) | |||
273 | plat_irq_setup_pins(IRQ_MODE_IRQ3210); | 276 | plat_irq_setup_pins(IRQ_MODE_IRQ3210); |
274 | } | 277 | } |
275 | 278 | ||
279 | static int sh7785lcr_clk_init(void) | ||
280 | { | ||
281 | struct clk *clk; | ||
282 | int ret; | ||
283 | |||
284 | clk = clk_get(NULL, "extal"); | ||
285 | if (!clk || IS_ERR(clk)) | ||
286 | return PTR_ERR(clk); | ||
287 | ret = clk_set_rate(clk, 33333333); | ||
288 | clk_put(clk); | ||
289 | |||
290 | return ret; | ||
291 | } | ||
292 | |||
276 | static void sh7785lcr_power_off(void) | 293 | static void sh7785lcr_power_off(void) |
277 | { | 294 | { |
278 | unsigned char *p; | 295 | unsigned char *p; |
@@ -309,6 +326,7 @@ static void __init sh7785lcr_setup(char **cmdline_p) | |||
309 | static struct sh_machine_vector mv_sh7785lcr __initmv = { | 326 | static struct sh_machine_vector mv_sh7785lcr __initmv = { |
310 | .mv_name = "SH7785LCR", | 327 | .mv_name = "SH7785LCR", |
311 | .mv_setup = sh7785lcr_setup, | 328 | .mv_setup = sh7785lcr_setup, |
329 | .mv_clk_init = sh7785lcr_clk_init, | ||
312 | .mv_init_irq = init_sh7785lcr_IRQ, | 330 | .mv_init_irq = init_sh7785lcr_IRQ, |
313 | }; | 331 | }; |
314 | 332 | ||
diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h index c27e844db0de..40cf3c07d7e6 100644 --- a/arch/sh/include/asm/clock.h +++ b/arch/sh/include/asm/clock.h | |||
@@ -34,7 +34,9 @@ struct clk { | |||
34 | 34 | ||
35 | unsigned long rate; | 35 | unsigned long rate; |
36 | unsigned long flags; | 36 | unsigned long flags; |
37 | |||
37 | unsigned long arch_flags; | 38 | unsigned long arch_flags; |
39 | void *priv; | ||
38 | }; | 40 | }; |
39 | 41 | ||
40 | struct clk_lookup { | 42 | struct clk_lookup { |
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c index bf5a0dacf8e5..87584dc81926 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SH7785 support for the clock framework | 4 | * SH7785 support for the clock framework |
5 | * | 5 | * |
6 | * Copyright (C) 2007 Paul Mundt | 6 | * Copyright (C) 2007 - 2009 Paul Mundt |
7 | * | 7 | * |
8 | * This file is subject to the terms and conditions of the GNU General Public | 8 | * This file is subject to the terms and conditions of the GNU General Public |
9 | * License. See the file "COPYING" in the main directory of this archive | 9 | * License. See the file "COPYING" in the main directory of this archive |
@@ -11,145 +11,146 @@ | |||
11 | */ | 11 | */ |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/clk.h> | ||
15 | #include <linux/io.h> | ||
14 | #include <asm/clock.h> | 16 | #include <asm/clock.h> |
15 | #include <asm/freq.h> | 17 | #include <asm/freq.h> |
16 | #include <asm/io.h> | ||
17 | |||
18 | static int ifc_divisors[] = { 1, 2, 4, 6 }; | ||
19 | static int ufc_divisors[] = { 1, 1, 4, 6 }; | ||
20 | static int sfc_divisors[] = { 1, 1, 4, 6 }; | ||
21 | static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18, | ||
22 | 24, 32, 36, 48, 1, 1, 1, 1 }; | ||
23 | static int mfc_divisors[] = { 1, 1, 4, 6 }; | ||
24 | static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 18, | ||
25 | 24, 32, 36, 48, 1, 1, 1, 1 }; | ||
26 | |||
27 | static void master_clk_init(struct clk *clk) | ||
28 | { | ||
29 | clk->rate *= pfc_divisors[ctrl_inl(FRQMR1) & 0x000f]; | ||
30 | } | ||
31 | 18 | ||
32 | static struct clk_ops sh7785_master_clk_ops = { | 19 | static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18, |
33 | .init = master_clk_init, | 20 | 24, 32, 36, 48 }; |
21 | struct clk_priv { | ||
22 | unsigned int shift; | ||
34 | }; | 23 | }; |
35 | 24 | ||
36 | static unsigned long module_clk_recalc(struct clk *clk) | 25 | #define FRQMR_CLK_DATA(_name, _shift) \ |
37 | { | 26 | static struct clk_priv _name##_data = { .shift = _shift, } |
38 | int idx = (ctrl_inl(FRQMR1) & 0x000f); | ||
39 | return clk->parent->rate / pfc_divisors[idx]; | ||
40 | } | ||
41 | 27 | ||
42 | static struct clk_ops sh7785_module_clk_ops = { | 28 | FRQMR_CLK_DATA(pfc, 0); |
43 | .recalc = module_clk_recalc, | 29 | FRQMR_CLK_DATA(s3fc, 4); |
44 | }; | 30 | FRQMR_CLK_DATA(s2fc, 8); |
31 | FRQMR_CLK_DATA(mfc, 12); | ||
32 | FRQMR_CLK_DATA(bfc, 16); | ||
33 | FRQMR_CLK_DATA(sfc, 20); | ||
34 | FRQMR_CLK_DATA(ufc, 24); | ||
35 | FRQMR_CLK_DATA(ifc, 28); | ||
45 | 36 | ||
46 | static unsigned long bus_clk_recalc(struct clk *clk) | 37 | static unsigned long frqmr_clk_recalc(struct clk *clk) |
47 | { | 38 | { |
48 | int idx = ((ctrl_inl(FRQMR1) >> 16) & 0x000f); | 39 | struct clk_priv *data = clk->priv; |
49 | return clk->parent->rate / bfc_divisors[idx]; | 40 | unsigned int idx; |
50 | } | ||
51 | 41 | ||
52 | static struct clk_ops sh7785_bus_clk_ops = { | 42 | idx = (__raw_readl(FRQMR1) >> data->shift) & 0x000f; |
53 | .recalc = bus_clk_recalc, | ||
54 | }; | ||
55 | 43 | ||
56 | static unsigned long cpu_clk_recalc(struct clk *clk) | 44 | /* |
57 | { | 45 | * XXX: PLL1 multiplier is locked for the default clock mode, |
58 | int idx = ((ctrl_inl(FRQMR1) >> 28) & 0x0003); | 46 | * when mode pin detection and configuration support is added, |
59 | return clk->parent->rate / ifc_divisors[idx]; | 47 | * select the multiplier dynamically. |
48 | */ | ||
49 | return clk->parent->rate * 36 / div2[idx]; | ||
60 | } | 50 | } |
61 | 51 | ||
62 | static struct clk_ops sh7785_cpu_clk_ops = { | 52 | static struct clk_ops frqmr_clk_ops = { |
63 | .recalc = cpu_clk_recalc, | 53 | .recalc = frqmr_clk_recalc, |
64 | }; | 54 | }; |
65 | 55 | ||
66 | static struct clk_ops *sh7785_clk_ops[] = { | 56 | /* |
67 | &sh7785_master_clk_ops, | 57 | * Default rate for the root input clock, reset this with clk_set_rate() |
68 | &sh7785_module_clk_ops, | 58 | * from the platform code. |
69 | &sh7785_bus_clk_ops, | 59 | */ |
70 | &sh7785_cpu_clk_ops, | 60 | static struct clk extal_clk = { |
61 | .name = "extal", | ||
62 | .id = -1, | ||
63 | .rate = 33333333, | ||
71 | }; | 64 | }; |
72 | 65 | ||
73 | void __init arch_init_clk_ops(struct clk_ops **ops, int idx) | 66 | static struct clk cpu_clk = { |
74 | { | 67 | .name = "cpu_clk", /* Ick */ |
75 | if (idx < ARRAY_SIZE(sh7785_clk_ops)) | 68 | .id = -1, |
76 | *ops = sh7785_clk_ops[idx]; | 69 | .ops = &frqmr_clk_ops, |
77 | } | 70 | .parent = &extal_clk, |
78 | 71 | .flags = CLK_ENABLE_ON_INIT, | |
79 | static unsigned long shyway_clk_recalc(struct clk *clk) | 72 | .priv = &ifc_data, |
80 | { | ||
81 | int idx = ((ctrl_inl(FRQMR1) >> 20) & 0x0003); | ||
82 | return clk->parent->rate / sfc_divisors[idx]; | ||
83 | } | ||
84 | |||
85 | static struct clk_ops sh7785_shyway_clk_ops = { | ||
86 | .recalc = shyway_clk_recalc, | ||
87 | }; | 73 | }; |
88 | 74 | ||
89 | static struct clk sh7785_shyway_clk = { | 75 | static struct clk shyway_clk = { |
90 | .name = "shyway_clk", | 76 | .name = "shyway_clk", /* SHck */ |
77 | .id = -1, | ||
78 | .ops = &frqmr_clk_ops, | ||
79 | .parent = &extal_clk, | ||
91 | .flags = CLK_ENABLE_ON_INIT, | 80 | .flags = CLK_ENABLE_ON_INIT, |
92 | .ops = &sh7785_shyway_clk_ops, | 81 | .priv = &sfc_data, |
93 | }; | 82 | }; |
94 | 83 | ||
95 | static unsigned long ddr_clk_recalc(struct clk *clk) | 84 | static struct clk peripheral_clk = { |
96 | { | 85 | .name = "peripheral_clk", /* Pck */ |
97 | int idx = ((ctrl_inl(FRQMR1) >> 12) & 0x0003); | 86 | .id = -1, |
98 | return clk->parent->rate / mfc_divisors[idx]; | 87 | .ops = &frqmr_clk_ops, |
99 | } | 88 | .parent = &extal_clk, |
89 | .flags = CLK_ENABLE_ON_INIT, | ||
90 | .priv = &pfc_data, | ||
91 | }; | ||
100 | 92 | ||
101 | static struct clk_ops sh7785_ddr_clk_ops = { | 93 | static struct clk ddr_clk = { |
102 | .recalc = ddr_clk_recalc, | 94 | .name = "ddr_clk", /* DDRck */ |
95 | .id = -1, | ||
96 | .ops = &frqmr_clk_ops, | ||
97 | .parent = &extal_clk, | ||
98 | .flags = CLK_ENABLE_ON_INIT, | ||
99 | .priv = &mfc_data, | ||
103 | }; | 100 | }; |
104 | 101 | ||
105 | static struct clk sh7785_ddr_clk = { | 102 | static struct clk bus_clk = { |
106 | .name = "ddr_clk", | 103 | .name = "bus_clk", /* Bck */ |
104 | .id = -1, | ||
105 | .ops = &frqmr_clk_ops, | ||
106 | .parent = &extal_clk, | ||
107 | .flags = CLK_ENABLE_ON_INIT, | 107 | .flags = CLK_ENABLE_ON_INIT, |
108 | .ops = &sh7785_ddr_clk_ops, | 108 | .priv = &bfc_data, |
109 | }; | 109 | }; |
110 | 110 | ||
111 | static unsigned long ram_clk_recalc(struct clk *clk) | 111 | static struct clk ga_clk = { |
112 | { | 112 | .name = "ga_clk", /* GAck */ |
113 | int idx = ((ctrl_inl(FRQMR1) >> 24) & 0x0003); | 113 | .id = -1, |
114 | return clk->parent->rate / ufc_divisors[idx]; | 114 | .ops = &frqmr_clk_ops, |
115 | } | 115 | .parent = &extal_clk, |
116 | .priv = &s2fc_data, | ||
117 | }; | ||
116 | 118 | ||
117 | static struct clk_ops sh7785_ram_clk_ops = { | 119 | static struct clk du_clk = { |
118 | .recalc = ram_clk_recalc, | 120 | .name = "du_clk", /* DUck */ |
121 | .id = -1, | ||
122 | .ops = &frqmr_clk_ops, | ||
123 | .parent = &extal_clk, | ||
124 | .priv = &s3fc_data, | ||
119 | }; | 125 | }; |
120 | 126 | ||
121 | static struct clk sh7785_ram_clk = { | 127 | static struct clk umem_clk = { |
122 | .name = "ram_clk", | 128 | .name = "umem_clk", /* uck */ |
129 | .id = -1, | ||
130 | .ops = &frqmr_clk_ops, | ||
131 | .parent = &extal_clk, | ||
123 | .flags = CLK_ENABLE_ON_INIT, | 132 | .flags = CLK_ENABLE_ON_INIT, |
124 | .ops = &sh7785_ram_clk_ops, | 133 | .priv = &ufc_data, |
125 | }; | 134 | }; |
126 | 135 | ||
127 | /* | 136 | static struct clk *clks[] = { |
128 | * Additional SH7785-specific on-chip clocks that aren't already part of the | 137 | &extal_clk, |
129 | * clock framework | 138 | &cpu_clk, |
130 | */ | 139 | ­way_clk, |
131 | static struct clk *sh7785_onchip_clocks[] = { | 140 | &peripheral_clk, |
132 | &sh7785_shyway_clk, | 141 | &ddr_clk, |
133 | &sh7785_ddr_clk, | 142 | &bus_clk, |
134 | &sh7785_ram_clk, | 143 | &ga_clk, |
144 | &du_clk, | ||
145 | &umem_clk, | ||
135 | }; | 146 | }; |
136 | 147 | ||
137 | int __init arch_clk_init(void) | 148 | int __init arch_clk_init(void) |
138 | { | 149 | { |
139 | struct clk *clk; | ||
140 | int i, ret = 0; | 150 | int i, ret = 0; |
141 | 151 | ||
142 | cpg_clk_init(); | 152 | for (i = 0; i < ARRAY_SIZE(clks); i++) |
143 | 153 | ret |= clk_register(clks[i]); | |
144 | clk = clk_get(NULL, "master_clk"); | ||
145 | for (i = 0; i < ARRAY_SIZE(sh7785_onchip_clocks); i++) { | ||
146 | struct clk *clkp = sh7785_onchip_clocks[i]; | ||
147 | |||
148 | clkp->parent = clk; | ||
149 | ret |= clk_register(clkp); | ||
150 | } | ||
151 | |||
152 | clk_put(clk); | ||
153 | 154 | ||
154 | return ret; | 155 | return ret; |
155 | } | 156 | } |