clk-core.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. /*
  2. * Marvell EBU clock core handling defined at reset
  3. *
  4. * Copyright (C) 2012 Marvell
  5. *
  6. * Gregory CLEMENT <gregory.clement@free-electrons.com>
  7. * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
  8. *
  9. * This file is licensed under the terms of the GNU General Public
  10. * License version 2. This program is licensed "as is" without any
  11. * warranty of any kind, whether express or implied.
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/clk.h>
  15. #include <linux/clkdev.h>
  16. #include <linux/clk-provider.h>
  17. #include <linux/of_address.h>
  18. #include <linux/io.h>
  19. #include <linux/of.h>
  20. #include "clk-core.h"
  21. struct core_ratio {
  22. int id;
  23. const char *name;
  24. };
  25. struct core_clocks {
  26. u32 (*get_tclk_freq)(void __iomem *sar);
  27. u32 (*get_cpu_freq)(void __iomem *sar);
  28. void (*get_clk_ratio)(void __iomem *sar, int id, int *mult, int *div);
  29. const struct core_ratio *ratios;
  30. int num_ratios;
  31. };
  32. static struct clk_onecell_data clk_data;
  33. static void __init mvebu_clk_core_setup(struct device_node *np,
  34. struct core_clocks *coreclk)
  35. {
  36. const char *tclk_name = "tclk";
  37. const char *cpuclk_name = "cpuclk";
  38. void __iomem *base;
  39. unsigned long rate;
  40. int n;
  41. base = of_iomap(np, 0);
  42. if (WARN_ON(!base))
  43. return;
  44. /*
  45. * Allocate struct for TCLK, cpu clk, and core ratio clocks
  46. */
  47. clk_data.clk_num = 2 + coreclk->num_ratios;
  48. clk_data.clks = kzalloc(clk_data.clk_num * sizeof(struct clk *),
  49. GFP_KERNEL);
  50. if (WARN_ON(!clk_data.clks))
  51. return;
  52. /*
  53. * Register TCLK
  54. */
  55. of_property_read_string_index(np, "clock-output-names", 0,
  56. &tclk_name);
  57. rate = coreclk->get_tclk_freq(base);
  58. clk_data.clks[0] = clk_register_fixed_rate(NULL, tclk_name, NULL,
  59. CLK_IS_ROOT, rate);
  60. WARN_ON(IS_ERR(clk_data.clks[0]));
  61. /*
  62. * Register CPU clock
  63. */
  64. of_property_read_string_index(np, "clock-output-names", 1,
  65. &cpuclk_name);
  66. rate = coreclk->get_cpu_freq(base);
  67. clk_data.clks[1] = clk_register_fixed_rate(NULL, cpuclk_name, NULL,
  68. CLK_IS_ROOT, rate);
  69. WARN_ON(IS_ERR(clk_data.clks[1]));
  70. /*
  71. * Register fixed-factor clocks derived from CPU clock
  72. */
  73. for (n = 0; n < coreclk->num_ratios; n++) {
  74. const char *rclk_name = coreclk->ratios[n].name;
  75. int mult, div;
  76. of_property_read_string_index(np, "clock-output-names",
  77. 2+n, &rclk_name);
  78. coreclk->get_clk_ratio(base, coreclk->ratios[n].id,
  79. &mult, &div);
  80. clk_data.clks[2+n] = clk_register_fixed_factor(NULL, rclk_name,
  81. cpuclk_name, 0, mult, div);
  82. WARN_ON(IS_ERR(clk_data.clks[2+n]));
  83. };
  84. /*
  85. * SAR register isn't needed anymore
  86. */
  87. iounmap(base);
  88. of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
  89. }
  90. #ifdef CONFIG_MACH_ARMADA_370_XP
  91. /*
  92. * Armada 370/XP Sample At Reset is a 64 bit bitfiled split in two
  93. * register of 32 bits
  94. */
  95. #define SARL 0 /* Low part [0:31] */
  96. #define SARL_AXP_PCLK_FREQ_OPT 21
  97. #define SARL_AXP_PCLK_FREQ_OPT_MASK 0x7
  98. #define SARL_A370_PCLK_FREQ_OPT 11
  99. #define SARL_A370_PCLK_FREQ_OPT_MASK 0xF
  100. #define SARL_AXP_FAB_FREQ_OPT 24
  101. #define SARL_AXP_FAB_FREQ_OPT_MASK 0xF
  102. #define SARL_A370_FAB_FREQ_OPT 15
  103. #define SARL_A370_FAB_FREQ_OPT_MASK 0x1F
  104. #define SARL_A370_TCLK_FREQ_OPT 20
  105. #define SARL_A370_TCLK_FREQ_OPT_MASK 0x1
  106. #define SARH 4 /* High part [32:63] */
  107. #define SARH_AXP_PCLK_FREQ_OPT (52-32)
  108. #define SARH_AXP_PCLK_FREQ_OPT_MASK 0x1
  109. #define SARH_AXP_PCLK_FREQ_OPT_SHIFT 3
  110. #define SARH_AXP_FAB_FREQ_OPT (51-32)
  111. #define SARH_AXP_FAB_FREQ_OPT_MASK 0x1
  112. #define SARH_AXP_FAB_FREQ_OPT_SHIFT 4
  113. static const u32 __initconst armada_370_tclk_frequencies[] = {
  114. 16600000,
  115. 20000000,
  116. };
  117. static u32 __init armada_370_get_tclk_freq(void __iomem *sar)
  118. {
  119. u8 tclk_freq_select = 0;
  120. tclk_freq_select = ((readl(sar) >> SARL_A370_TCLK_FREQ_OPT) &
  121. SARL_A370_TCLK_FREQ_OPT_MASK);
  122. return armada_370_tclk_frequencies[tclk_freq_select];
  123. }
  124. static const u32 __initconst armada_370_cpu_frequencies[] = {
  125. 400000000,
  126. 533000000,
  127. 667000000,
  128. 800000000,
  129. 1000000000,
  130. 1067000000,
  131. 1200000000,
  132. };
  133. static u32 __init armada_370_get_cpu_freq(void __iomem *sar)
  134. {
  135. u32 cpu_freq;
  136. u8 cpu_freq_select = 0;
  137. cpu_freq_select = ((readl(sar) >> SARL_A370_PCLK_FREQ_OPT) &
  138. SARL_A370_PCLK_FREQ_OPT_MASK);
  139. if (cpu_freq_select > ARRAY_SIZE(armada_370_cpu_frequencies)) {
  140. pr_err("CPU freq select unsuported %d\n", cpu_freq_select);
  141. cpu_freq = 0;
  142. } else
  143. cpu_freq = armada_370_cpu_frequencies[cpu_freq_select];
  144. return cpu_freq;
  145. }
  146. enum { A370_XP_NBCLK, A370_XP_HCLK, A370_XP_DRAMCLK };
  147. static const struct core_ratio __initconst armada_370_xp_core_ratios[] = {
  148. { .id = A370_XP_NBCLK, .name = "nbclk" },
  149. { .id = A370_XP_HCLK, .name = "hclk" },
  150. { .id = A370_XP_DRAMCLK, .name = "dramclk" },
  151. };
  152. static const int __initconst armada_370_xp_nbclk_ratios[32][2] = {
  153. {0, 1}, {1, 2}, {2, 2}, {2, 2},
  154. {1, 2}, {1, 2}, {1, 1}, {2, 3},
  155. {0, 1}, {1, 2}, {2, 4}, {0, 1},
  156. {1, 2}, {0, 1}, {0, 1}, {2, 2},
  157. {0, 1}, {0, 1}, {0, 1}, {1, 1},
  158. {2, 3}, {0, 1}, {0, 1}, {0, 1},
  159. {0, 1}, {0, 1}, {0, 1}, {1, 1},
  160. {0, 1}, {0, 1}, {0, 1}, {0, 1},
  161. };
  162. static const int __initconst armada_370_xp_hclk_ratios[32][2] = {
  163. {0, 1}, {1, 2}, {2, 6}, {2, 3},
  164. {1, 3}, {1, 4}, {1, 2}, {2, 6},
  165. {0, 1}, {1, 6}, {2, 10}, {0, 1},
  166. {1, 4}, {0, 1}, {0, 1}, {2, 5},
  167. {0, 1}, {0, 1}, {0, 1}, {1, 2},
  168. {2, 6}, {0, 1}, {0, 1}, {0, 1},
  169. {0, 1}, {0, 1}, {0, 1}, {1, 1},
  170. {0, 1}, {0, 1}, {0, 1}, {0, 1},
  171. };
  172. static const int __initconst armada_370_xp_dramclk_ratios[32][2] = {
  173. {0, 1}, {1, 2}, {2, 3}, {2, 3},
  174. {1, 3}, {1, 2}, {1, 2}, {2, 6},
  175. {0, 1}, {1, 3}, {2, 5}, {0, 1},
  176. {1, 4}, {0, 1}, {0, 1}, {2, 5},
  177. {0, 1}, {0, 1}, {0, 1}, {1, 1},
  178. {2, 3}, {0, 1}, {0, 1}, {0, 1},
  179. {0, 1}, {0, 1}, {0, 1}, {1, 1},
  180. {0, 1}, {0, 1}, {0, 1}, {0, 1},
  181. };
  182. static void __init armada_370_xp_get_clk_ratio(u32 opt,
  183. void __iomem *sar, int id, int *mult, int *div)
  184. {
  185. switch (id) {
  186. case A370_XP_NBCLK:
  187. *mult = armada_370_xp_nbclk_ratios[opt][0];
  188. *div = armada_370_xp_nbclk_ratios[opt][1];
  189. break;
  190. case A370_XP_HCLK:
  191. *mult = armada_370_xp_hclk_ratios[opt][0];
  192. *div = armada_370_xp_hclk_ratios[opt][1];
  193. break;
  194. case A370_XP_DRAMCLK:
  195. *mult = armada_370_xp_dramclk_ratios[opt][0];
  196. *div = armada_370_xp_dramclk_ratios[opt][1];
  197. break;
  198. }
  199. }
  200. static void __init armada_370_get_clk_ratio(
  201. void __iomem *sar, int id, int *mult, int *div)
  202. {
  203. u32 opt = ((readl(sar) >> SARL_A370_FAB_FREQ_OPT) &
  204. SARL_A370_FAB_FREQ_OPT_MASK);
  205. armada_370_xp_get_clk_ratio(opt, sar, id, mult, div);
  206. }
  207. static const struct core_clocks armada_370_core_clocks = {
  208. .get_tclk_freq = armada_370_get_tclk_freq,
  209. .get_cpu_freq = armada_370_get_cpu_freq,
  210. .get_clk_ratio = armada_370_get_clk_ratio,
  211. .ratios = armada_370_xp_core_ratios,
  212. .num_ratios = ARRAY_SIZE(armada_370_xp_core_ratios),
  213. };
  214. static const u32 __initconst armada_xp_cpu_frequencies[] = {
  215. 1000000000,
  216. 1066000000,
  217. 1200000000,
  218. 1333000000,
  219. 1500000000,
  220. 1666000000,
  221. 1800000000,
  222. 2000000000,
  223. 667000000,
  224. 0,
  225. 800000000,
  226. 1600000000,
  227. };
  228. /* For Armada XP TCLK frequency is fix: 250MHz */
  229. static u32 __init armada_xp_get_tclk_freq(void __iomem *sar)
  230. {
  231. return 250 * 1000 * 1000;
  232. }
  233. static u32 __init armada_xp_get_cpu_freq(void __iomem *sar)
  234. {
  235. u32 cpu_freq;
  236. u8 cpu_freq_select = 0;
  237. cpu_freq_select = ((readl(sar) >> SARL_AXP_PCLK_FREQ_OPT) &
  238. SARL_AXP_PCLK_FREQ_OPT_MASK);
  239. /*
  240. * The upper bit is not contiguous to the other ones and
  241. * located in the high part of the SAR registers
  242. */
  243. cpu_freq_select |= (((readl(sar+4) >> SARH_AXP_PCLK_FREQ_OPT) &
  244. SARH_AXP_PCLK_FREQ_OPT_MASK)
  245. << SARH_AXP_PCLK_FREQ_OPT_SHIFT);
  246. if (cpu_freq_select > ARRAY_SIZE(armada_xp_cpu_frequencies)) {
  247. pr_err("CPU freq select unsuported: %d\n", cpu_freq_select);
  248. cpu_freq = 0;
  249. } else
  250. cpu_freq = armada_xp_cpu_frequencies[cpu_freq_select];
  251. return cpu_freq;
  252. }
  253. static void __init armada_xp_get_clk_ratio(
  254. void __iomem *sar, int id, int *mult, int *div)
  255. {
  256. u32 opt = ((readl(sar) >> SARL_AXP_FAB_FREQ_OPT) &
  257. SARL_AXP_FAB_FREQ_OPT_MASK);
  258. /*
  259. * The upper bit is not contiguous to the other ones and
  260. * located in the high part of the SAR registers
  261. */
  262. opt |= (((readl(sar+4) >> SARH_AXP_FAB_FREQ_OPT) &
  263. SARH_AXP_FAB_FREQ_OPT_MASK)
  264. << SARH_AXP_FAB_FREQ_OPT_SHIFT);
  265. armada_370_xp_get_clk_ratio(opt, sar, id, mult, div);
  266. }
  267. static const struct core_clocks armada_xp_core_clocks = {
  268. .get_tclk_freq = armada_xp_get_tclk_freq,
  269. .get_cpu_freq = armada_xp_get_cpu_freq,
  270. .get_clk_ratio = armada_xp_get_clk_ratio,
  271. .ratios = armada_370_xp_core_ratios,
  272. .num_ratios = ARRAY_SIZE(armada_370_xp_core_ratios),
  273. };
  274. #endif /* CONFIG_MACH_ARMADA_370_XP */
  275. /*
  276. * Dove PLL sample-at-reset configuration
  277. *
  278. * SAR0[8:5] : CPU frequency
  279. * 5 = 1000 MHz
  280. * 6 = 933 MHz
  281. * 7 = 933 MHz
  282. * 8 = 800 MHz
  283. * 9 = 800 MHz
  284. * 10 = 800 MHz
  285. * 11 = 1067 MHz
  286. * 12 = 667 MHz
  287. * 13 = 533 MHz
  288. * 14 = 400 MHz
  289. * 15 = 333 MHz
  290. * others reserved.
  291. *
  292. * SAR0[11:9] : CPU to L2 Clock divider ratio
  293. * 0 = (1/1) * CPU
  294. * 2 = (1/2) * CPU
  295. * 4 = (1/3) * CPU
  296. * 6 = (1/4) * CPU
  297. * others reserved.
  298. *
  299. * SAR0[15:12] : CPU to DDR DRAM Clock divider ratio
  300. * 0 = (1/1) * CPU
  301. * 2 = (1/2) * CPU
  302. * 3 = (2/5) * CPU
  303. * 4 = (1/3) * CPU
  304. * 6 = (1/4) * CPU
  305. * 8 = (1/5) * CPU
  306. * 10 = (1/6) * CPU
  307. * 12 = (1/7) * CPU
  308. * 14 = (1/8) * CPU
  309. * 15 = (1/10) * CPU
  310. * others reserved.
  311. *
  312. * SAR0[24:23] : TCLK frequency
  313. * 0 = 166 MHz
  314. * 1 = 125 MHz
  315. * others reserved.
  316. */
  317. #ifdef CONFIG_ARCH_DOVE
  318. #define SAR_DOVE_CPU_FREQ 5
  319. #define SAR_DOVE_CPU_FREQ_MASK 0xf
  320. #define SAR_DOVE_L2_RATIO 9
  321. #define SAR_DOVE_L2_RATIO_MASK 0x7
  322. #define SAR_DOVE_DDR_RATIO 12
  323. #define SAR_DOVE_DDR_RATIO_MASK 0xf
  324. #define SAR_DOVE_TCLK_FREQ 23
  325. #define SAR_DOVE_TCLK_FREQ_MASK 0x3
  326. static const u32 __initconst dove_tclk_frequencies[] = {
  327. 166666667,
  328. 125000000,
  329. 0, 0
  330. };
  331. static u32 __init dove_get_tclk_freq(void __iomem *sar)
  332. {
  333. u32 opt = (readl(sar) >> SAR_DOVE_TCLK_FREQ) &
  334. SAR_DOVE_TCLK_FREQ_MASK;
  335. return dove_tclk_frequencies[opt];
  336. }
  337. static const u32 __initconst dove_cpu_frequencies[] = {
  338. 0, 0, 0, 0, 0,
  339. 1000000000,
  340. 933333333, 933333333,
  341. 800000000, 800000000, 800000000,
  342. 1066666667,
  343. 666666667,
  344. 533333333,
  345. 400000000,
  346. 333333333
  347. };
  348. static u32 __init dove_get_cpu_freq(void __iomem *sar)
  349. {
  350. u32 opt = (readl(sar) >> SAR_DOVE_CPU_FREQ) &
  351. SAR_DOVE_CPU_FREQ_MASK;
  352. return dove_cpu_frequencies[opt];
  353. }
  354. enum { DOVE_CPU_TO_L2, DOVE_CPU_TO_DDR };
  355. static const struct core_ratio __initconst dove_core_ratios[] = {
  356. { .id = DOVE_CPU_TO_L2, .name = "l2clk", },
  357. { .id = DOVE_CPU_TO_DDR, .name = "ddrclk", }
  358. };
  359. static const int __initconst dove_cpu_l2_ratios[8][2] = {
  360. { 1, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
  361. { 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 }
  362. };
  363. static const int __initconst dove_cpu_ddr_ratios[16][2] = {
  364. { 1, 1 }, { 0, 1 }, { 1, 2 }, { 2, 5 },
  365. { 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 },
  366. { 1, 5 }, { 0, 1 }, { 1, 6 }, { 0, 1 },
  367. { 1, 7 }, { 0, 1 }, { 1, 8 }, { 1, 10 }
  368. };
  369. static void __init dove_get_clk_ratio(
  370. void __iomem *sar, int id, int *mult, int *div)
  371. {
  372. switch (id) {
  373. case DOVE_CPU_TO_L2:
  374. {
  375. u32 opt = (readl(sar) >> SAR_DOVE_L2_RATIO) &
  376. SAR_DOVE_L2_RATIO_MASK;
  377. *mult = dove_cpu_l2_ratios[opt][0];
  378. *div = dove_cpu_l2_ratios[opt][1];
  379. break;
  380. }
  381. case DOVE_CPU_TO_DDR:
  382. {
  383. u32 opt = (readl(sar) >> SAR_DOVE_DDR_RATIO) &
  384. SAR_DOVE_DDR_RATIO_MASK;
  385. *mult = dove_cpu_ddr_ratios[opt][0];
  386. *div = dove_cpu_ddr_ratios[opt][1];
  387. break;
  388. }
  389. }
  390. }
  391. static const struct core_clocks dove_core_clocks = {
  392. .get_tclk_freq = dove_get_tclk_freq,
  393. .get_cpu_freq = dove_get_cpu_freq,
  394. .get_clk_ratio = dove_get_clk_ratio,
  395. .ratios = dove_core_ratios,
  396. .num_ratios = ARRAY_SIZE(dove_core_ratios),
  397. };
  398. #endif /* CONFIG_ARCH_DOVE */
  399. /*
  400. * Kirkwood PLL sample-at-reset configuration
  401. * (6180 has different SAR layout than other Kirkwood SoCs)
  402. *
  403. * SAR0[4:3,22,1] : CPU frequency (6281,6292,6282)
  404. * 4 = 600 MHz
  405. * 6 = 800 MHz
  406. * 7 = 1000 MHz
  407. * 9 = 1200 MHz
  408. * 12 = 1500 MHz
  409. * 13 = 1600 MHz
  410. * 14 = 1800 MHz
  411. * 15 = 2000 MHz
  412. * others reserved.
  413. *
  414. * SAR0[19,10:9] : CPU to L2 Clock divider ratio (6281,6292,6282)
  415. * 1 = (1/2) * CPU
  416. * 3 = (1/3) * CPU
  417. * 5 = (1/4) * CPU
  418. * others reserved.
  419. *
  420. * SAR0[8:5] : CPU to DDR DRAM Clock divider ratio (6281,6292,6282)
  421. * 2 = (1/2) * CPU
  422. * 4 = (1/3) * CPU
  423. * 6 = (1/4) * CPU
  424. * 7 = (2/9) * CPU
  425. * 8 = (1/5) * CPU
  426. * 9 = (1/6) * CPU
  427. * others reserved.
  428. *
  429. * SAR0[4:2] : Kirkwood 6180 cpu/l2/ddr clock configuration (6180 only)
  430. * 5 = [CPU = 600 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/3) * CPU]
  431. * 6 = [CPU = 800 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/4) * CPU]
  432. * 7 = [CPU = 1000 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/5) * CPU]
  433. * others reserved.
  434. *
  435. * SAR0[21] : TCLK frequency
  436. * 0 = 200 MHz
  437. * 1 = 166 MHz
  438. * others reserved.
  439. */
  440. #ifdef CONFIG_ARCH_KIRKWOOD
  441. #define SAR_KIRKWOOD_CPU_FREQ(x) \
  442. (((x & (1 << 1)) >> 1) | \
  443. ((x & (1 << 22)) >> 21) | \
  444. ((x & (3 << 3)) >> 1))
  445. #define SAR_KIRKWOOD_L2_RATIO(x) \
  446. (((x & (3 << 9)) >> 9) | \
  447. (((x & (1 << 19)) >> 17)))
  448. #define SAR_KIRKWOOD_DDR_RATIO 5
  449. #define SAR_KIRKWOOD_DDR_RATIO_MASK 0xf
  450. #define SAR_MV88F6180_CLK 2
  451. #define SAR_MV88F6180_CLK_MASK 0x7
  452. #define SAR_KIRKWOOD_TCLK_FREQ 21
  453. #define SAR_KIRKWOOD_TCLK_FREQ_MASK 0x1
  454. enum { KIRKWOOD_CPU_TO_L2, KIRKWOOD_CPU_TO_DDR };
  455. static const struct core_ratio __initconst kirkwood_core_ratios[] = {
  456. { .id = KIRKWOOD_CPU_TO_L2, .name = "l2clk", },
  457. { .id = KIRKWOOD_CPU_TO_DDR, .name = "ddrclk", }
  458. };
  459. static u32 __init kirkwood_get_tclk_freq(void __iomem *sar)
  460. {
  461. u32 opt = (readl(sar) >> SAR_KIRKWOOD_TCLK_FREQ) &
  462. SAR_KIRKWOOD_TCLK_FREQ_MASK;
  463. return (opt) ? 166666667 : 200000000;
  464. }
  465. static const u32 __initconst kirkwood_cpu_frequencies[] = {
  466. 0, 0, 0, 0,
  467. 600000000,
  468. 0,
  469. 800000000,
  470. 1000000000,
  471. 0,
  472. 1200000000,
  473. 0, 0,
  474. 1500000000,
  475. 1600000000,
  476. 1800000000,
  477. 2000000000
  478. };
  479. static u32 __init kirkwood_get_cpu_freq(void __iomem *sar)
  480. {
  481. u32 opt = SAR_KIRKWOOD_CPU_FREQ(readl(sar));
  482. return kirkwood_cpu_frequencies[opt];
  483. }
  484. static const int __initconst kirkwood_cpu_l2_ratios[8][2] = {
  485. { 0, 1 }, { 1, 2 }, { 0, 1 }, { 1, 3 },
  486. { 0, 1 }, { 1, 4 }, { 0, 1 }, { 0, 1 }
  487. };
  488. static const int __initconst kirkwood_cpu_ddr_ratios[16][2] = {
  489. { 0, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
  490. { 1, 3 }, { 0, 1 }, { 1, 4 }, { 2, 9 },
  491. { 1, 5 }, { 1, 6 }, { 0, 1 }, { 0, 1 },
  492. { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }
  493. };
  494. static void __init kirkwood_get_clk_ratio(
  495. void __iomem *sar, int id, int *mult, int *div)
  496. {
  497. switch (id) {
  498. case KIRKWOOD_CPU_TO_L2:
  499. {
  500. u32 opt = SAR_KIRKWOOD_L2_RATIO(readl(sar));
  501. *mult = kirkwood_cpu_l2_ratios[opt][0];
  502. *div = kirkwood_cpu_l2_ratios[opt][1];
  503. break;
  504. }
  505. case KIRKWOOD_CPU_TO_DDR:
  506. {
  507. u32 opt = (readl(sar) >> SAR_KIRKWOOD_DDR_RATIO) &
  508. SAR_KIRKWOOD_DDR_RATIO_MASK;
  509. *mult = kirkwood_cpu_ddr_ratios[opt][0];
  510. *div = kirkwood_cpu_ddr_ratios[opt][1];
  511. break;
  512. }
  513. }
  514. }
  515. static const struct core_clocks kirkwood_core_clocks = {
  516. .get_tclk_freq = kirkwood_get_tclk_freq,
  517. .get_cpu_freq = kirkwood_get_cpu_freq,
  518. .get_clk_ratio = kirkwood_get_clk_ratio,
  519. .ratios = kirkwood_core_ratios,
  520. .num_ratios = ARRAY_SIZE(kirkwood_core_ratios),
  521. };
  522. static const u32 __initconst mv88f6180_cpu_frequencies[] = {
  523. 0, 0, 0, 0, 0,
  524. 600000000,
  525. 800000000,
  526. 1000000000
  527. };
  528. static u32 __init mv88f6180_get_cpu_freq(void __iomem *sar)
  529. {
  530. u32 opt = (readl(sar) >> SAR_MV88F6180_CLK) & SAR_MV88F6180_CLK_MASK;
  531. return mv88f6180_cpu_frequencies[opt];
  532. }
  533. static const int __initconst mv88f6180_cpu_ddr_ratios[8][2] = {
  534. { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 },
  535. { 0, 1 }, { 1, 3 }, { 1, 4 }, { 1, 5 }
  536. };
  537. static void __init mv88f6180_get_clk_ratio(
  538. void __iomem *sar, int id, int *mult, int *div)
  539. {
  540. switch (id) {
  541. case KIRKWOOD_CPU_TO_L2:
  542. {
  543. /* mv88f6180 has a fixed 1:2 CPU-to-L2 ratio */
  544. *mult = 1;
  545. *div = 2;
  546. break;
  547. }
  548. case KIRKWOOD_CPU_TO_DDR:
  549. {
  550. u32 opt = (readl(sar) >> SAR_MV88F6180_CLK) &
  551. SAR_MV88F6180_CLK_MASK;
  552. *mult = mv88f6180_cpu_ddr_ratios[opt][0];
  553. *div = mv88f6180_cpu_ddr_ratios[opt][1];
  554. break;
  555. }
  556. }
  557. }
  558. static const struct core_clocks mv88f6180_core_clocks = {
  559. .get_tclk_freq = kirkwood_get_tclk_freq,
  560. .get_cpu_freq = mv88f6180_get_cpu_freq,
  561. .get_clk_ratio = mv88f6180_get_clk_ratio,
  562. .ratios = kirkwood_core_ratios,
  563. .num_ratios = ARRAY_SIZE(kirkwood_core_ratios),
  564. };
  565. #endif /* CONFIG_ARCH_KIRKWOOD */
  566. static const __initdata struct of_device_id clk_core_match[] = {
  567. #ifdef CONFIG_MACH_ARMADA_370_XP
  568. {
  569. .compatible = "marvell,armada-370-core-clock",
  570. .data = &armada_370_core_clocks,
  571. },
  572. {
  573. .compatible = "marvell,armada-xp-core-clock",
  574. .data = &armada_xp_core_clocks,
  575. },
  576. #endif
  577. #ifdef CONFIG_ARCH_DOVE
  578. {
  579. .compatible = "marvell,dove-core-clock",
  580. .data = &dove_core_clocks,
  581. },
  582. #endif
  583. #ifdef CONFIG_ARCH_KIRKWOOD
  584. {
  585. .compatible = "marvell,kirkwood-core-clock",
  586. .data = &kirkwood_core_clocks,
  587. },
  588. {
  589. .compatible = "marvell,mv88f6180-core-clock",
  590. .data = &mv88f6180_core_clocks,
  591. },
  592. #endif
  593. { }
  594. };
  595. void __init mvebu_core_clk_init(void)
  596. {
  597. struct device_node *np;
  598. for_each_matching_node(np, clk_core_match) {
  599. const struct of_device_id *match =
  600. of_match_node(clk_core_match, np);
  601. mvebu_clk_core_setup(np, (struct core_clocks *)match->data);
  602. }
  603. }