]>
Commit | Line | Data |
---|---|---|
55ba99eb KM |
1 | /* |
2 | * arch/sh/kernel/cpu/sh4a/clock-sh7786.c | |
3 | * | |
4 | * SH7786 support for the clock framework | |
5 | * | |
43a1839c | 6 | * Copyright (C) 2010 Paul Mundt |
55ba99eb KM |
7 | * |
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 | |
10 | * for more details. | |
11 | */ | |
12 | #include <linux/init.h> | |
13 | #include <linux/kernel.h> | |
43a1839c PM |
14 | #include <linux/clk.h> |
15 | #include <linux/io.h> | |
e21d2aa7 PM |
16 | #include <linux/clk.h> |
17 | #include <asm/clkdev.h> | |
55ba99eb KM |
18 | #include <asm/clock.h> |
19 | #include <asm/freq.h> | |
55ba99eb | 20 | |
43a1839c PM |
21 | /* |
22 | * Default rate for the root input clock, reset this with clk_set_rate() | |
23 | * from the platform code. | |
24 | */ | |
25 | static struct clk extal_clk = { | |
26 | .name = "extal", | |
27 | .id = -1, | |
28 | .rate = 33333333, | |
55ba99eb KM |
29 | }; |
30 | ||
43a1839c | 31 | static unsigned long pll_recalc(struct clk *clk) |
55ba99eb | 32 | { |
43a1839c | 33 | int multiplier; |
55ba99eb | 34 | |
43a1839c PM |
35 | /* |
36 | * Clock modes 0, 1, and 2 use an x64 multiplier against PLL1, | |
37 | * while modes 3, 4, and 5 use an x32. | |
38 | */ | |
39 | multiplier = (sh_mv.mv_mode_pins() & 0xf) < 3 ? 64 : 32; | |
55ba99eb | 40 | |
43a1839c | 41 | return clk->parent->rate * multiplier; |
55ba99eb KM |
42 | } |
43 | ||
43a1839c PM |
44 | static struct clk_ops pll_clk_ops = { |
45 | .recalc = pll_recalc, | |
55ba99eb KM |
46 | }; |
47 | ||
43a1839c PM |
48 | static struct clk pll_clk = { |
49 | .name = "pll_clk", | |
50 | .id = -1, | |
51 | .ops = &pll_clk_ops, | |
52 | .parent = &extal_clk, | |
53 | .flags = CLK_ENABLE_ON_INIT, | |
55ba99eb KM |
54 | }; |
55 | ||
43a1839c PM |
56 | static struct clk *clks[] = { |
57 | &extal_clk, | |
58 | &pll_clk, | |
55ba99eb KM |
59 | }; |
60 | ||
43a1839c PM |
61 | static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18, |
62 | 24, 32, 36, 48 }; | |
55ba99eb | 63 | |
0a5f337e | 64 | static struct clk_div_mult_table div4_div_mult_table = { |
43a1839c PM |
65 | .divisors = div2, |
66 | .nr_divisors = ARRAY_SIZE(div2), | |
55ba99eb KM |
67 | }; |
68 | ||
0a5f337e MD |
69 | static struct clk_div4_table div4_table = { |
70 | .div_mult_table = &div4_div_mult_table, | |
71 | }; | |
72 | ||
43a1839c | 73 | enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_DU, DIV4_P, DIV4_NR }; |
55ba99eb | 74 | |
43a1839c PM |
75 | #define DIV4(_str, _bit, _mask, _flags) \ |
76 | SH_CLK_DIV4(_str, &pll_clk, FRQMR1, _bit, _mask, _flags) | |
55ba99eb | 77 | |
43a1839c PM |
78 | struct clk div4_clks[DIV4_NR] = { |
79 | [DIV4_P] = DIV4("peripheral_clk", 0, 0x0b40, 0), | |
80 | [DIV4_DU] = DIV4("du_clk", 4, 0x0010, 0), | |
81 | [DIV4_DDR] = DIV4("ddr_clk", 12, 0x0002, CLK_ENABLE_ON_INIT), | |
82 | [DIV4_B] = DIV4("bus_clk", 16, 0x0360, CLK_ENABLE_ON_INIT), | |
83 | [DIV4_SH] = DIV4("shyway_clk", 20, 0x0002, CLK_ENABLE_ON_INIT), | |
84 | [DIV4_I] = DIV4("cpu_clk", 28, 0x0006, CLK_ENABLE_ON_INIT), | |
55ba99eb KM |
85 | }; |
86 | ||
43a1839c PM |
87 | #define MSTPCR0 0xffc40030 |
88 | #define MSTPCR1 0xffc40034 | |
89 | ||
8bc23d95 MD |
90 | enum { MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, |
91 | MSTP023, MSTP022, MSTP021, MSTP020, MSTP017, MSTP016, | |
92 | MSTP015, MSTP014, MSTP011, MSTP010, MSTP009, MSTP008, | |
93 | MSTP005, MSTP004, MSTP002, | |
94 | MSTP112, MSTP110, MSTP109, MSTP108, | |
95 | MSTP105, MSTP104, MSTP103, MSTP102, | |
96 | MSTP_NR }; | |
97 | ||
98 | static struct clk mstp_clks[MSTP_NR] = { | |
43a1839c | 99 | /* MSTPCR0 */ |
8bc23d95 MD |
100 | [MSTP029] = SH_CLK_MSTP32("sci_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0), |
101 | [MSTP028] = SH_CLK_MSTP32("sci_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0), | |
102 | [MSTP027] = SH_CLK_MSTP32("sci_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0), | |
103 | [MSTP026] = SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0), | |
104 | [MSTP025] = SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0), | |
105 | [MSTP024] = SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0), | |
106 | [MSTP023] = SH_CLK_MSTP32("ssi_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 23, 0), | |
107 | [MSTP022] = SH_CLK_MSTP32("ssi_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 22, 0), | |
108 | [MSTP021] = SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0), | |
109 | [MSTP020] = SH_CLK_MSTP32("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0), | |
110 | [MSTP017] = SH_CLK_MSTP32("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0), | |
111 | [MSTP016] = SH_CLK_MSTP32("hac_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 16, 0), | |
112 | [MSTP015] = SH_CLK_MSTP32("i2c_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 15, 0), | |
113 | [MSTP014] = SH_CLK_MSTP32("i2c_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 14, 0), | |
114 | [MSTP011] = SH_CLK_MSTP32("tmu9_11_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 11, 0), | |
115 | [MSTP010] = SH_CLK_MSTP32("tmu678_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 10, 0), | |
116 | [MSTP009] = SH_CLK_MSTP32("tmu345_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 9, 0), | |
117 | [MSTP008] = SH_CLK_MSTP32("tmu012_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 8, 0), | |
118 | [MSTP005] = SH_CLK_MSTP32("sdif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 5, 0), | |
119 | [MSTP004] = SH_CLK_MSTP32("sdif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 4, 0), | |
120 | [MSTP002] = SH_CLK_MSTP32("hspi_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 2, 0), | |
43a1839c PM |
121 | |
122 | /* MSTPCR1 */ | |
8bc23d95 MD |
123 | [MSTP112] = SH_CLK_MSTP32("usb_fck", -1, NULL, MSTPCR1, 12, 0), |
124 | [MSTP110] = SH_CLK_MSTP32("pcie_fck", 2, NULL, MSTPCR1, 10, 0), | |
125 | [MSTP109] = SH_CLK_MSTP32("pcie_fck", 1, NULL, MSTPCR1, 9, 0), | |
126 | [MSTP108] = SH_CLK_MSTP32("pcie_fck", 0, NULL, MSTPCR1, 8, 0), | |
127 | [MSTP105] = SH_CLK_MSTP32("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0), | |
128 | [MSTP104] = SH_CLK_MSTP32("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0), | |
129 | [MSTP103] = SH_CLK_MSTP32("du_fck", -1, NULL, MSTPCR1, 3, 0), | |
130 | [MSTP102] = SH_CLK_MSTP32("ether_fck", -1, NULL, MSTPCR1, 2, 0), | |
55ba99eb KM |
131 | }; |
132 | ||
d8ef3ccc MD |
133 | #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } |
134 | ||
e21d2aa7 | 135 | static struct clk_lookup lookups[] = { |
d8ef3ccc MD |
136 | /* MSTP32 clocks */ |
137 | { | |
138 | /* SCIF5 */ | |
139 | .dev_id = "sh-sci.5", | |
140 | .con_id = "sci_fck", | |
141 | .clk = &mstp_clks[MSTP029], | |
142 | }, { | |
143 | /* SCIF4 */ | |
144 | .dev_id = "sh-sci.4", | |
145 | .con_id = "sci_fck", | |
146 | .clk = &mstp_clks[MSTP028], | |
147 | }, { | |
148 | /* SCIF3 */ | |
149 | .dev_id = "sh-sci.3", | |
150 | .con_id = "sci_fck", | |
151 | .clk = &mstp_clks[MSTP027], | |
152 | }, { | |
153 | /* SCIF2 */ | |
154 | .dev_id = "sh-sci.2", | |
155 | .con_id = "sci_fck", | |
156 | .clk = &mstp_clks[MSTP026], | |
157 | }, { | |
158 | /* SCIF1 */ | |
159 | .dev_id = "sh-sci.1", | |
160 | .con_id = "sci_fck", | |
161 | .clk = &mstp_clks[MSTP025], | |
162 | }, { | |
163 | /* SCIF0 */ | |
164 | .dev_id = "sh-sci.0", | |
165 | .con_id = "sci_fck", | |
166 | .clk = &mstp_clks[MSTP024], | |
167 | }, | |
168 | CLKDEV_CON_ID("ssi3_fck", &mstp_clks[MSTP023]), | |
169 | CLKDEV_CON_ID("ssi2_fck", &mstp_clks[MSTP022]), | |
170 | CLKDEV_CON_ID("ssi1_fck", &mstp_clks[MSTP021]), | |
171 | CLKDEV_CON_ID("ssi0_fck", &mstp_clks[MSTP020]), | |
172 | CLKDEV_CON_ID("hac1_fck", &mstp_clks[MSTP017]), | |
173 | CLKDEV_CON_ID("hac0_fck", &mstp_clks[MSTP016]), | |
174 | CLKDEV_CON_ID("i2c1_fck", &mstp_clks[MSTP015]), | |
175 | CLKDEV_CON_ID("i2c0_fck", &mstp_clks[MSTP014]), | |
e21d2aa7 PM |
176 | { |
177 | /* TMU0 */ | |
178 | .dev_id = "sh_tmu.0", | |
179 | .con_id = "tmu_fck", | |
8bc23d95 | 180 | .clk = &mstp_clks[MSTP008], |
e21d2aa7 PM |
181 | }, { |
182 | /* TMU1 */ | |
183 | .dev_id = "sh_tmu.1", | |
184 | .con_id = "tmu_fck", | |
8bc23d95 | 185 | .clk = &mstp_clks[MSTP008], |
e21d2aa7 PM |
186 | }, { |
187 | /* TMU2 */ | |
188 | .dev_id = "sh_tmu.2", | |
189 | .con_id = "tmu_fck", | |
8bc23d95 | 190 | .clk = &mstp_clks[MSTP008], |
e21d2aa7 PM |
191 | }, { |
192 | /* TMU3 */ | |
193 | .dev_id = "sh_tmu.3", | |
194 | .con_id = "tmu_fck", | |
8bc23d95 | 195 | .clk = &mstp_clks[MSTP009], |
e21d2aa7 PM |
196 | }, { |
197 | /* TMU4 */ | |
198 | .dev_id = "sh_tmu.4", | |
199 | .con_id = "tmu_fck", | |
8bc23d95 | 200 | .clk = &mstp_clks[MSTP009], |
e21d2aa7 PM |
201 | }, { |
202 | /* TMU5 */ | |
203 | .dev_id = "sh_tmu.5", | |
204 | .con_id = "tmu_fck", | |
8bc23d95 | 205 | .clk = &mstp_clks[MSTP009], |
e21d2aa7 PM |
206 | }, { |
207 | /* TMU6 */ | |
208 | .dev_id = "sh_tmu.6", | |
209 | .con_id = "tmu_fck", | |
8bc23d95 | 210 | .clk = &mstp_clks[MSTP010], |
e21d2aa7 PM |
211 | }, { |
212 | /* TMU7 */ | |
213 | .dev_id = "sh_tmu.7", | |
214 | .con_id = "tmu_fck", | |
8bc23d95 | 215 | .clk = &mstp_clks[MSTP010], |
e21d2aa7 PM |
216 | }, { |
217 | /* TMU8 */ | |
218 | .dev_id = "sh_tmu.8", | |
219 | .con_id = "tmu_fck", | |
8bc23d95 | 220 | .clk = &mstp_clks[MSTP010], |
e21d2aa7 PM |
221 | }, { |
222 | /* TMU9 */ | |
223 | .dev_id = "sh_tmu.9", | |
224 | .con_id = "tmu_fck", | |
8bc23d95 | 225 | .clk = &mstp_clks[MSTP011], |
e21d2aa7 PM |
226 | }, { |
227 | /* TMU10 */ | |
228 | .dev_id = "sh_tmu.10", | |
229 | .con_id = "tmu_fck", | |
8bc23d95 | 230 | .clk = &mstp_clks[MSTP011], |
e21d2aa7 PM |
231 | }, { |
232 | /* TMU11 */ | |
233 | .dev_id = "sh_tmu.11", | |
234 | .con_id = "tmu_fck", | |
8bc23d95 | 235 | .clk = &mstp_clks[MSTP011], |
d8ef3ccc MD |
236 | }, |
237 | CLKDEV_CON_ID("sdif1_fck", &mstp_clks[MSTP005]), | |
238 | CLKDEV_CON_ID("sdif0_fck", &mstp_clks[MSTP004]), | |
239 | CLKDEV_CON_ID("hspi_fck", &mstp_clks[MSTP002]), | |
240 | CLKDEV_CON_ID("usb_fck", &mstp_clks[MSTP112]), | |
241 | CLKDEV_CON_ID("pcie2_fck", &mstp_clks[MSTP110]), | |
242 | CLKDEV_CON_ID("pcie1_fck", &mstp_clks[MSTP109]), | |
243 | CLKDEV_CON_ID("pcie0_fck", &mstp_clks[MSTP108]), | |
244 | CLKDEV_CON_ID("dmac_11_6_fck", &mstp_clks[MSTP105]), | |
245 | CLKDEV_CON_ID("dmac_5_0_fck", &mstp_clks[MSTP104]), | |
246 | CLKDEV_CON_ID("du_fck", &mstp_clks[MSTP103]), | |
247 | CLKDEV_CON_ID("ether_fck", &mstp_clks[MSTP102]), | |
e21d2aa7 PM |
248 | }; |
249 | ||
9fe5ee0e | 250 | int __init arch_clk_init(void) |
55ba99eb | 251 | { |
f5c84cf5 | 252 | int i, ret = 0; |
55ba99eb | 253 | |
43a1839c PM |
254 | for (i = 0; i < ARRAY_SIZE(clks); i++) |
255 | ret |= clk_register(clks[i]); | |
e21d2aa7 PM |
256 | for (i = 0; i < ARRAY_SIZE(lookups); i++) |
257 | clkdev_add(&lookups[i]); | |
55ba99eb | 258 | |
43a1839c PM |
259 | if (!ret) |
260 | ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks), | |
261 | &div4_table); | |
262 | if (!ret) | |
8bc23d95 | 263 | ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); |
55ba99eb | 264 | |
f5c84cf5 | 265 | return ret; |
55ba99eb | 266 | } |