• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Port on Texas Instruments TMS320C6x architecture
3  *
4  *  Copyright (C) 2011 Texas Instruments Incorporated
5  *  Author: Mark Salter <msalter@redhat.com>
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  */
11 #include <linux/kernel.h>
12 #include <linux/delay.h>
13 #include <linux/errno.h>
14 #include <linux/string.h>
15 #include <linux/ioport.h>
16 #include <linux/clkdev.h>
17 #include <linux/of.h>
18 #include <linux/of_address.h>
19 
20 #include <asm/clock.h>
21 #include <asm/setup.h>
22 #include <asm/irq.h>
23 
24 /*
25  * Common SoC clock support.
26  */
27 
28 /* Default input for PLL1 */
29 struct clk clkin1 = {
30 	.name = "clkin1",
31 	.node = LIST_HEAD_INIT(clkin1.node),
32 	.children = LIST_HEAD_INIT(clkin1.children),
33 	.childnode = LIST_HEAD_INIT(clkin1.childnode),
34 };
35 
36 struct pll_data c6x_soc_pll1 = {
37 	.num	   = 1,
38 	.sysclks   = {
39 		{
40 			.name = "pll1",
41 			.parent = &clkin1,
42 			.pll_data = &c6x_soc_pll1,
43 			.flags = CLK_PLL,
44 		},
45 		{
46 			.name = "pll1_sysclk1",
47 			.parent = &c6x_soc_pll1.sysclks[0],
48 			.flags = CLK_PLL,
49 		},
50 		{
51 			.name = "pll1_sysclk2",
52 			.parent = &c6x_soc_pll1.sysclks[0],
53 			.flags = CLK_PLL,
54 		},
55 		{
56 			.name = "pll1_sysclk3",
57 			.parent = &c6x_soc_pll1.sysclks[0],
58 			.flags = CLK_PLL,
59 		},
60 		{
61 			.name = "pll1_sysclk4",
62 			.parent = &c6x_soc_pll1.sysclks[0],
63 			.flags = CLK_PLL,
64 		},
65 		{
66 			.name = "pll1_sysclk5",
67 			.parent = &c6x_soc_pll1.sysclks[0],
68 			.flags = CLK_PLL,
69 		},
70 		{
71 			.name = "pll1_sysclk6",
72 			.parent = &c6x_soc_pll1.sysclks[0],
73 			.flags = CLK_PLL,
74 		},
75 		{
76 			.name = "pll1_sysclk7",
77 			.parent = &c6x_soc_pll1.sysclks[0],
78 			.flags = CLK_PLL,
79 		},
80 		{
81 			.name = "pll1_sysclk8",
82 			.parent = &c6x_soc_pll1.sysclks[0],
83 			.flags = CLK_PLL,
84 		},
85 		{
86 			.name = "pll1_sysclk9",
87 			.parent = &c6x_soc_pll1.sysclks[0],
88 			.flags = CLK_PLL,
89 		},
90 		{
91 			.name = "pll1_sysclk10",
92 			.parent = &c6x_soc_pll1.sysclks[0],
93 			.flags = CLK_PLL,
94 		},
95 		{
96 			.name = "pll1_sysclk11",
97 			.parent = &c6x_soc_pll1.sysclks[0],
98 			.flags = CLK_PLL,
99 		},
100 		{
101 			.name = "pll1_sysclk12",
102 			.parent = &c6x_soc_pll1.sysclks[0],
103 			.flags = CLK_PLL,
104 		},
105 		{
106 			.name = "pll1_sysclk13",
107 			.parent = &c6x_soc_pll1.sysclks[0],
108 			.flags = CLK_PLL,
109 		},
110 		{
111 			.name = "pll1_sysclk14",
112 			.parent = &c6x_soc_pll1.sysclks[0],
113 			.flags = CLK_PLL,
114 		},
115 		{
116 			.name = "pll1_sysclk15",
117 			.parent = &c6x_soc_pll1.sysclks[0],
118 			.flags = CLK_PLL,
119 		},
120 		{
121 			.name = "pll1_sysclk16",
122 			.parent = &c6x_soc_pll1.sysclks[0],
123 			.flags = CLK_PLL,
124 		},
125 	},
126 };
127 
128 /* CPU core clock */
129 struct clk c6x_core_clk = {
130 	.name = "core",
131 };
132 
133 /* miscellaneous IO clocks */
134 struct clk c6x_i2c_clk = {
135 	.name = "i2c",
136 };
137 
138 struct clk c6x_watchdog_clk = {
139 	.name = "watchdog",
140 };
141 
142 struct clk c6x_mcbsp1_clk = {
143 	.name = "mcbsp1",
144 };
145 
146 struct clk c6x_mcbsp2_clk = {
147 	.name = "mcbsp2",
148 };
149 
150 struct clk c6x_mdio_clk = {
151 	.name = "mdio",
152 };
153 
154 
155 #ifdef CONFIG_SOC_TMS320C6455
156 static struct clk_lookup c6455_clks[] = {
157 	CLK(NULL, "pll1", &c6x_soc_pll1.sysclks[0]),
158 	CLK(NULL, "pll1_sysclk2", &c6x_soc_pll1.sysclks[2]),
159 	CLK(NULL, "pll1_sysclk3", &c6x_soc_pll1.sysclks[3]),
160 	CLK(NULL, "pll1_sysclk4", &c6x_soc_pll1.sysclks[4]),
161 	CLK(NULL, "pll1_sysclk5", &c6x_soc_pll1.sysclks[5]),
162 	CLK(NULL, "core", &c6x_core_clk),
163 	CLK("i2c_davinci.1", NULL, &c6x_i2c_clk),
164 	CLK("watchdog", NULL, &c6x_watchdog_clk),
165 	CLK("2c81800.mdio", NULL, &c6x_mdio_clk),
166 	CLK("", NULL, NULL)
167 };
168 
169 
c6455_setup_clocks(struct device_node * node)170 static void __init c6455_setup_clocks(struct device_node *node)
171 {
172 	struct pll_data *pll = &c6x_soc_pll1;
173 	struct clk *sysclks = pll->sysclks;
174 
175 	pll->flags = PLL_HAS_PRE | PLL_HAS_MUL;
176 
177 	sysclks[2].flags |= FIXED_DIV_PLL;
178 	sysclks[2].div = 3;
179 	sysclks[3].flags |= FIXED_DIV_PLL;
180 	sysclks[3].div = 6;
181 	sysclks[4].div = PLLDIV4;
182 	sysclks[5].div = PLLDIV5;
183 
184 	c6x_core_clk.parent = &sysclks[0];
185 	c6x_i2c_clk.parent = &sysclks[3];
186 	c6x_watchdog_clk.parent = &sysclks[3];
187 	c6x_mdio_clk.parent = &sysclks[3];
188 
189 	c6x_clks_init(c6455_clks);
190 }
191 #endif /* CONFIG_SOC_TMS320C6455 */
192 
193 #ifdef CONFIG_SOC_TMS320C6457
194 static struct clk_lookup c6457_clks[] = {
195 	CLK(NULL, "pll1", &c6x_soc_pll1.sysclks[0]),
196 	CLK(NULL, "pll1_sysclk1", &c6x_soc_pll1.sysclks[1]),
197 	CLK(NULL, "pll1_sysclk2", &c6x_soc_pll1.sysclks[2]),
198 	CLK(NULL, "pll1_sysclk3", &c6x_soc_pll1.sysclks[3]),
199 	CLK(NULL, "pll1_sysclk4", &c6x_soc_pll1.sysclks[4]),
200 	CLK(NULL, "pll1_sysclk5", &c6x_soc_pll1.sysclks[5]),
201 	CLK(NULL, "core", &c6x_core_clk),
202 	CLK("i2c_davinci.1", NULL, &c6x_i2c_clk),
203 	CLK("watchdog", NULL, &c6x_watchdog_clk),
204 	CLK("2c81800.mdio", NULL, &c6x_mdio_clk),
205 	CLK("", NULL, NULL)
206 };
207 
c6457_setup_clocks(struct device_node * node)208 static void __init c6457_setup_clocks(struct device_node *node)
209 {
210 	struct pll_data *pll = &c6x_soc_pll1;
211 	struct clk *sysclks = pll->sysclks;
212 
213 	pll->flags = PLL_HAS_MUL | PLL_HAS_POST;
214 
215 	sysclks[1].flags |= FIXED_DIV_PLL;
216 	sysclks[1].div = 1;
217 	sysclks[2].flags |= FIXED_DIV_PLL;
218 	sysclks[2].div = 3;
219 	sysclks[3].flags |= FIXED_DIV_PLL;
220 	sysclks[3].div = 6;
221 	sysclks[4].div = PLLDIV4;
222 	sysclks[5].div = PLLDIV5;
223 
224 	c6x_core_clk.parent = &sysclks[1];
225 	c6x_i2c_clk.parent = &sysclks[3];
226 	c6x_watchdog_clk.parent = &sysclks[5];
227 	c6x_mdio_clk.parent = &sysclks[5];
228 
229 	c6x_clks_init(c6457_clks);
230 }
231 #endif /* CONFIG_SOC_TMS320C6455 */
232 
233 #ifdef CONFIG_SOC_TMS320C6472
234 static struct clk_lookup c6472_clks[] = {
235 	CLK(NULL, "pll1", &c6x_soc_pll1.sysclks[0]),
236 	CLK(NULL, "pll1_sysclk1", &c6x_soc_pll1.sysclks[1]),
237 	CLK(NULL, "pll1_sysclk2", &c6x_soc_pll1.sysclks[2]),
238 	CLK(NULL, "pll1_sysclk3", &c6x_soc_pll1.sysclks[3]),
239 	CLK(NULL, "pll1_sysclk4", &c6x_soc_pll1.sysclks[4]),
240 	CLK(NULL, "pll1_sysclk5", &c6x_soc_pll1.sysclks[5]),
241 	CLK(NULL, "pll1_sysclk6", &c6x_soc_pll1.sysclks[6]),
242 	CLK(NULL, "pll1_sysclk7", &c6x_soc_pll1.sysclks[7]),
243 	CLK(NULL, "pll1_sysclk8", &c6x_soc_pll1.sysclks[8]),
244 	CLK(NULL, "pll1_sysclk9", &c6x_soc_pll1.sysclks[9]),
245 	CLK(NULL, "pll1_sysclk10", &c6x_soc_pll1.sysclks[10]),
246 	CLK(NULL, "core", &c6x_core_clk),
247 	CLK("i2c_davinci.1", NULL, &c6x_i2c_clk),
248 	CLK("watchdog", NULL, &c6x_watchdog_clk),
249 	CLK("2c81800.mdio", NULL, &c6x_mdio_clk),
250 	CLK("", NULL, NULL)
251 };
252 
253 /* assumptions used for delay loop calculations */
254 #define MIN_CLKIN1_KHz 15625
255 #define MAX_CORE_KHz   700000
256 #define MIN_PLLOUT_KHz MIN_CLKIN1_KHz
257 
c6472_setup_clocks(struct device_node * node)258 static void __init c6472_setup_clocks(struct device_node *node)
259 {
260 	struct pll_data *pll = &c6x_soc_pll1;
261 	struct clk *sysclks = pll->sysclks;
262 	int i;
263 
264 	pll->flags = PLL_HAS_MUL;
265 
266 	for (i = 1; i <= 6; i++) {
267 		sysclks[i].flags |= FIXED_DIV_PLL;
268 		sysclks[i].div = 1;
269 	}
270 
271 	sysclks[7].flags |= FIXED_DIV_PLL;
272 	sysclks[7].div = 3;
273 	sysclks[8].flags |= FIXED_DIV_PLL;
274 	sysclks[8].div = 6;
275 	sysclks[9].flags |= FIXED_DIV_PLL;
276 	sysclks[9].div = 2;
277 	sysclks[10].div = PLLDIV10;
278 
279 	c6x_core_clk.parent = &sysclks[get_coreid() + 1];
280 	c6x_i2c_clk.parent = &sysclks[8];
281 	c6x_watchdog_clk.parent = &sysclks[8];
282 	c6x_mdio_clk.parent = &sysclks[5];
283 
284 	c6x_clks_init(c6472_clks);
285 }
286 #endif /* CONFIG_SOC_TMS320C6472 */
287 
288 
289 #ifdef CONFIG_SOC_TMS320C6474
290 static struct clk_lookup c6474_clks[] = {
291 	CLK(NULL, "pll1", &c6x_soc_pll1.sysclks[0]),
292 	CLK(NULL, "pll1_sysclk7", &c6x_soc_pll1.sysclks[7]),
293 	CLK(NULL, "pll1_sysclk9", &c6x_soc_pll1.sysclks[9]),
294 	CLK(NULL, "pll1_sysclk10", &c6x_soc_pll1.sysclks[10]),
295 	CLK(NULL, "pll1_sysclk11", &c6x_soc_pll1.sysclks[11]),
296 	CLK(NULL, "pll1_sysclk12", &c6x_soc_pll1.sysclks[12]),
297 	CLK(NULL, "pll1_sysclk13", &c6x_soc_pll1.sysclks[13]),
298 	CLK(NULL, "core", &c6x_core_clk),
299 	CLK("i2c_davinci.1", NULL, &c6x_i2c_clk),
300 	CLK("mcbsp.1", NULL, &c6x_mcbsp1_clk),
301 	CLK("mcbsp.2", NULL, &c6x_mcbsp2_clk),
302 	CLK("watchdog", NULL, &c6x_watchdog_clk),
303 	CLK("2c81800.mdio", NULL, &c6x_mdio_clk),
304 	CLK("", NULL, NULL)
305 };
306 
c6474_setup_clocks(struct device_node * node)307 static void __init c6474_setup_clocks(struct device_node *node)
308 {
309 	struct pll_data *pll = &c6x_soc_pll1;
310 	struct clk *sysclks = pll->sysclks;
311 
312 	pll->flags = PLL_HAS_MUL;
313 
314 	sysclks[7].flags |= FIXED_DIV_PLL;
315 	sysclks[7].div = 1;
316 	sysclks[9].flags |= FIXED_DIV_PLL;
317 	sysclks[9].div = 3;
318 	sysclks[10].flags |= FIXED_DIV_PLL;
319 	sysclks[10].div = 6;
320 
321 	sysclks[11].div = PLLDIV11;
322 
323 	sysclks[12].flags |= FIXED_DIV_PLL;
324 	sysclks[12].div = 2;
325 
326 	sysclks[13].div = PLLDIV13;
327 
328 	c6x_core_clk.parent = &sysclks[7];
329 	c6x_i2c_clk.parent = &sysclks[10];
330 	c6x_watchdog_clk.parent = &sysclks[10];
331 	c6x_mcbsp1_clk.parent = &sysclks[10];
332 	c6x_mcbsp2_clk.parent = &sysclks[10];
333 
334 	c6x_clks_init(c6474_clks);
335 }
336 #endif /* CONFIG_SOC_TMS320C6474 */
337 
338 #ifdef CONFIG_SOC_TMS320C6678
339 static struct clk_lookup c6678_clks[] = {
340 	CLK(NULL, "pll1", &c6x_soc_pll1.sysclks[0]),
341 	CLK(NULL, "pll1_refclk", &c6x_soc_pll1.sysclks[1]),
342 	CLK(NULL, "pll1_sysclk2", &c6x_soc_pll1.sysclks[2]),
343 	CLK(NULL, "pll1_sysclk3", &c6x_soc_pll1.sysclks[3]),
344 	CLK(NULL, "pll1_sysclk4", &c6x_soc_pll1.sysclks[4]),
345 	CLK(NULL, "pll1_sysclk5", &c6x_soc_pll1.sysclks[5]),
346 	CLK(NULL, "pll1_sysclk6", &c6x_soc_pll1.sysclks[6]),
347 	CLK(NULL, "pll1_sysclk7", &c6x_soc_pll1.sysclks[7]),
348 	CLK(NULL, "pll1_sysclk8", &c6x_soc_pll1.sysclks[8]),
349 	CLK(NULL, "pll1_sysclk9", &c6x_soc_pll1.sysclks[9]),
350 	CLK(NULL, "pll1_sysclk10", &c6x_soc_pll1.sysclks[10]),
351 	CLK(NULL, "pll1_sysclk11", &c6x_soc_pll1.sysclks[11]),
352 	CLK(NULL, "core", &c6x_core_clk),
353 	CLK("", NULL, NULL)
354 };
355 
c6678_setup_clocks(struct device_node * node)356 static void __init c6678_setup_clocks(struct device_node *node)
357 {
358 	struct pll_data *pll = &c6x_soc_pll1;
359 	struct clk *sysclks = pll->sysclks;
360 
361 	pll->flags = PLL_HAS_MUL;
362 
363 	sysclks[1].flags |= FIXED_DIV_PLL;
364 	sysclks[1].div = 1;
365 
366 	sysclks[2].div = PLLDIV2;
367 
368 	sysclks[3].flags |= FIXED_DIV_PLL;
369 	sysclks[3].div = 2;
370 
371 	sysclks[4].flags |= FIXED_DIV_PLL;
372 	sysclks[4].div = 3;
373 
374 	sysclks[5].div = PLLDIV5;
375 
376 	sysclks[6].flags |= FIXED_DIV_PLL;
377 	sysclks[6].div = 64;
378 
379 	sysclks[7].flags |= FIXED_DIV_PLL;
380 	sysclks[7].div = 6;
381 
382 	sysclks[8].div = PLLDIV8;
383 
384 	sysclks[9].flags |= FIXED_DIV_PLL;
385 	sysclks[9].div = 12;
386 
387 	sysclks[10].flags |= FIXED_DIV_PLL;
388 	sysclks[10].div = 3;
389 
390 	sysclks[11].flags |= FIXED_DIV_PLL;
391 	sysclks[11].div = 6;
392 
393 	c6x_core_clk.parent = &sysclks[0];
394 	c6x_i2c_clk.parent = &sysclks[7];
395 
396 	c6x_clks_init(c6678_clks);
397 }
398 #endif /* CONFIG_SOC_TMS320C6678 */
399 
400 static struct of_device_id c6x_clkc_match[] __initdata = {
401 #ifdef CONFIG_SOC_TMS320C6455
402 	{ .compatible = "ti,c6455-pll", .data = c6455_setup_clocks },
403 #endif
404 #ifdef CONFIG_SOC_TMS320C6457
405 	{ .compatible = "ti,c6457-pll", .data = c6457_setup_clocks },
406 #endif
407 #ifdef CONFIG_SOC_TMS320C6472
408 	{ .compatible = "ti,c6472-pll", .data = c6472_setup_clocks },
409 #endif
410 #ifdef CONFIG_SOC_TMS320C6474
411 	{ .compatible = "ti,c6474-pll", .data = c6474_setup_clocks },
412 #endif
413 #ifdef CONFIG_SOC_TMS320C6678
414 	{ .compatible = "ti,c6678-pll", .data = c6678_setup_clocks },
415 #endif
416 	{ .compatible = "ti,c64x+pll" },
417 	{}
418 };
419 
c64x_setup_clocks(void)420 void __init c64x_setup_clocks(void)
421 {
422 	void (*__setup_clocks)(struct device_node *np);
423 	struct pll_data *pll = &c6x_soc_pll1;
424 	struct device_node *node;
425 	const struct of_device_id *id;
426 	int err;
427 	u32 val;
428 
429 	node = of_find_matching_node(NULL, c6x_clkc_match);
430 	if (!node)
431 		return;
432 
433 	pll->base = of_iomap(node, 0);
434 	if (!pll->base)
435 		goto out;
436 
437 	err = of_property_read_u32(node, "clock-frequency", &val);
438 	if (err || val == 0) {
439 		pr_err("%s: no clock-frequency found! Using %dMHz\n",
440 		       node->full_name, (int)val / 1000000);
441 		val = 25000000;
442 	}
443 	clkin1.rate = val;
444 
445 	err = of_property_read_u32(node, "ti,c64x+pll-bypass-delay", &val);
446 	if (err)
447 		val = 5000;
448 	pll->bypass_delay = val;
449 
450 	err = of_property_read_u32(node, "ti,c64x+pll-reset-delay", &val);
451 	if (err)
452 		val = 30000;
453 	pll->reset_delay = val;
454 
455 	err = of_property_read_u32(node, "ti,c64x+pll-lock-delay", &val);
456 	if (err)
457 		val = 30000;
458 	pll->lock_delay = val;
459 
460 	/* id->data is a pointer to SoC-specific setup */
461 	id = of_match_node(c6x_clkc_match, node);
462 	if (id && id->data) {
463 		__setup_clocks = id->data;
464 		__setup_clocks(node);
465 	}
466 
467 out:
468 	of_node_put(node);
469 }
470