plldata.c 11 KB

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