plldata.c 12 KB

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