clk-bcm281xx.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2013 Broadcom Corporation.
  4. */
  5. /*
  6. *
  7. * bcm281xx-specific clock tables
  8. *
  9. */
  10. #include <common.h>
  11. #include <asm/io.h>
  12. #include <linux/errno.h>
  13. #include <asm/arch/sysmap.h>
  14. #include <asm/kona-common/clk.h>
  15. #include "clk-core.h"
  16. #define CLOCK_1K 1000
  17. #define CLOCK_1M (CLOCK_1K * 1000)
  18. /* declare a reference clock */
  19. #define DECLARE_REF_CLK(clk_name, clk_parent, clk_rate, clk_div) \
  20. static struct refclk clk_name = { \
  21. .clk = { \
  22. .name = #clk_name, \
  23. .parent = clk_parent, \
  24. .rate = clk_rate, \
  25. .div = clk_div, \
  26. .ops = &ref_clk_ops, \
  27. }, \
  28. }
  29. /*
  30. * Reference clocks
  31. */
  32. /* Declare a list of reference clocks */
  33. DECLARE_REF_CLK(ref_crystal, 0, 26 * CLOCK_1M, 1);
  34. DECLARE_REF_CLK(var_96m, 0, 96 * CLOCK_1M, 1);
  35. DECLARE_REF_CLK(ref_96m, 0, 96 * CLOCK_1M, 1);
  36. DECLARE_REF_CLK(ref_312m, 0, 312 * CLOCK_1M, 0);
  37. DECLARE_REF_CLK(ref_104m, &ref_312m.clk, 104 * CLOCK_1M, 3);
  38. DECLARE_REF_CLK(ref_52m, &ref_104m.clk, 52 * CLOCK_1M, 2);
  39. DECLARE_REF_CLK(ref_13m, &ref_52m.clk, 13 * CLOCK_1M, 4);
  40. DECLARE_REF_CLK(var_312m, 0, 312 * CLOCK_1M, 0);
  41. DECLARE_REF_CLK(var_104m, &var_312m.clk, 104 * CLOCK_1M, 3);
  42. DECLARE_REF_CLK(var_52m, &var_104m.clk, 52 * CLOCK_1M, 2);
  43. DECLARE_REF_CLK(var_13m, &var_52m.clk, 13 * CLOCK_1M, 4);
  44. struct refclk_lkup {
  45. struct refclk *procclk;
  46. const char *name;
  47. };
  48. /* Lookup table for string to clk tranlation */
  49. #define MKSTR(x) {&x, #x}
  50. static struct refclk_lkup refclk_str_tbl[] = {
  51. MKSTR(ref_crystal), MKSTR(var_96m), MKSTR(ref_96m),
  52. MKSTR(ref_312m), MKSTR(ref_104m), MKSTR(ref_52m),
  53. MKSTR(ref_13m), MKSTR(var_312m), MKSTR(var_104m),
  54. MKSTR(var_52m), MKSTR(var_13m),
  55. };
  56. int refclk_entries = sizeof(refclk_str_tbl)/sizeof(refclk_str_tbl[0]);
  57. /* convert ref clock string to clock structure pointer */
  58. struct refclk *refclk_str_to_clk(const char *name)
  59. {
  60. int i;
  61. struct refclk_lkup *tblp = refclk_str_tbl;
  62. for (i = 0; i < refclk_entries; i++, tblp++) {
  63. if (!(strcmp(name, tblp->name)))
  64. return tblp->procclk;
  65. }
  66. return NULL;
  67. }
  68. /* frequency tables indexed by freq_id */
  69. unsigned long master_axi_freq_tbl[8] = {
  70. 26 * CLOCK_1M,
  71. 52 * CLOCK_1M,
  72. 104 * CLOCK_1M,
  73. 156 * CLOCK_1M,
  74. 156 * CLOCK_1M,
  75. 208 * CLOCK_1M,
  76. 312 * CLOCK_1M,
  77. 312 * CLOCK_1M
  78. };
  79. unsigned long master_ahb_freq_tbl[8] = {
  80. 26 * CLOCK_1M,
  81. 52 * CLOCK_1M,
  82. 52 * CLOCK_1M,
  83. 52 * CLOCK_1M,
  84. 78 * CLOCK_1M,
  85. 104 * CLOCK_1M,
  86. 104 * CLOCK_1M,
  87. 156 * CLOCK_1M
  88. };
  89. unsigned long slave_axi_freq_tbl[8] = {
  90. 26 * CLOCK_1M,
  91. 52 * CLOCK_1M,
  92. 78 * CLOCK_1M,
  93. 104 * CLOCK_1M,
  94. 156 * CLOCK_1M,
  95. 156 * CLOCK_1M
  96. };
  97. unsigned long slave_apb_freq_tbl[8] = {
  98. 26 * CLOCK_1M,
  99. 26 * CLOCK_1M,
  100. 39 * CLOCK_1M,
  101. 52 * CLOCK_1M,
  102. 52 * CLOCK_1M,
  103. 78 * CLOCK_1M
  104. };
  105. unsigned long esub_freq_tbl[8] = {
  106. 78 * CLOCK_1M,
  107. 156 * CLOCK_1M,
  108. 156 * CLOCK_1M,
  109. 156 * CLOCK_1M,
  110. 208 * CLOCK_1M,
  111. 208 * CLOCK_1M,
  112. 208 * CLOCK_1M
  113. };
  114. static struct bus_clk_data bsc1_apb_data = {
  115. .gate = HW_SW_GATE_AUTO(0x0458, 16, 0, 1),
  116. };
  117. static struct bus_clk_data bsc2_apb_data = {
  118. .gate = HW_SW_GATE_AUTO(0x045c, 16, 0, 1),
  119. };
  120. static struct bus_clk_data bsc3_apb_data = {
  121. .gate = HW_SW_GATE_AUTO(0x0484, 16, 0, 1),
  122. };
  123. /* * Master CCU clocks */
  124. static struct peri_clk_data sdio1_data = {
  125. .gate = HW_SW_GATE(0x0358, 18, 2, 3),
  126. .clocks = CLOCKS("ref_crystal",
  127. "var_52m",
  128. "ref_52m",
  129. "var_96m",
  130. "ref_96m"),
  131. .sel = SELECTOR(0x0a28, 0, 3),
  132. .div = DIVIDER(0x0a28, 4, 14),
  133. .trig = TRIGGER(0x0afc, 9),
  134. };
  135. static struct peri_clk_data sdio2_data = {
  136. .gate = HW_SW_GATE(0x035c, 18, 2, 3),
  137. .clocks = CLOCKS("ref_crystal",
  138. "var_52m",
  139. "ref_52m",
  140. "var_96m",
  141. "ref_96m"),
  142. .sel = SELECTOR(0x0a2c, 0, 3),
  143. .div = DIVIDER(0x0a2c, 4, 14),
  144. .trig = TRIGGER(0x0afc, 10),
  145. };
  146. static struct peri_clk_data sdio3_data = {
  147. .gate = HW_SW_GATE(0x0364, 18, 2, 3),
  148. .clocks = CLOCKS("ref_crystal",
  149. "var_52m",
  150. "ref_52m",
  151. "var_96m",
  152. "ref_96m"),
  153. .sel = SELECTOR(0x0a34, 0, 3),
  154. .div = DIVIDER(0x0a34, 4, 14),
  155. .trig = TRIGGER(0x0afc, 12),
  156. };
  157. static struct peri_clk_data sdio4_data = {
  158. .gate = HW_SW_GATE(0x0360, 18, 2, 3),
  159. .clocks = CLOCKS("ref_crystal",
  160. "var_52m",
  161. "ref_52m",
  162. "var_96m",
  163. "ref_96m"),
  164. .sel = SELECTOR(0x0a30, 0, 3),
  165. .div = DIVIDER(0x0a30, 4, 14),
  166. .trig = TRIGGER(0x0afc, 11),
  167. };
  168. static struct peri_clk_data sdio1_sleep_data = {
  169. .clocks = CLOCKS("ref_32k"),
  170. .gate = SW_ONLY_GATE(0x0358, 20, 4),
  171. };
  172. static struct peri_clk_data sdio2_sleep_data = {
  173. .clocks = CLOCKS("ref_32k"),
  174. .gate = SW_ONLY_GATE(0x035c, 20, 4),
  175. };
  176. static struct peri_clk_data sdio3_sleep_data = {
  177. .clocks = CLOCKS("ref_32k"),
  178. .gate = SW_ONLY_GATE(0x0364, 20, 4),
  179. };
  180. static struct peri_clk_data sdio4_sleep_data = {
  181. .clocks = CLOCKS("ref_32k"),
  182. .gate = SW_ONLY_GATE(0x0360, 20, 4),
  183. };
  184. static struct bus_clk_data usb_otg_ahb_data = {
  185. .gate = HW_SW_GATE_AUTO(0x0348, 16, 0, 1),
  186. };
  187. static struct bus_clk_data sdio1_ahb_data = {
  188. .gate = HW_SW_GATE_AUTO(0x0358, 16, 0, 1),
  189. };
  190. static struct bus_clk_data sdio2_ahb_data = {
  191. .gate = HW_SW_GATE_AUTO(0x035c, 16, 0, 1),
  192. };
  193. static struct bus_clk_data sdio3_ahb_data = {
  194. .gate = HW_SW_GATE_AUTO(0x0364, 16, 0, 1),
  195. };
  196. static struct bus_clk_data sdio4_ahb_data = {
  197. .gate = HW_SW_GATE_AUTO(0x0360, 16, 0, 1),
  198. };
  199. /* * Slave CCU clocks */
  200. static struct peri_clk_data bsc1_data = {
  201. .gate = HW_SW_GATE(0x0458, 18, 2, 3),
  202. .clocks = CLOCKS("ref_crystal",
  203. "var_104m",
  204. "ref_104m",
  205. "var_13m",
  206. "ref_13m"),
  207. .sel = SELECTOR(0x0a64, 0, 3),
  208. .trig = TRIGGER(0x0afc, 23),
  209. };
  210. static struct peri_clk_data bsc2_data = {
  211. .gate = HW_SW_GATE(0x045c, 18, 2, 3),
  212. .clocks = CLOCKS("ref_crystal",
  213. "var_104m",
  214. "ref_104m",
  215. "var_13m",
  216. "ref_13m"),
  217. .sel = SELECTOR(0x0a68, 0, 3),
  218. .trig = TRIGGER(0x0afc, 24),
  219. };
  220. static struct peri_clk_data bsc3_data = {
  221. .gate = HW_SW_GATE(0x0484, 18, 2, 3),
  222. .clocks = CLOCKS("ref_crystal",
  223. "var_104m",
  224. "ref_104m",
  225. "var_13m",
  226. "ref_13m"),
  227. .sel = SELECTOR(0x0a84, 0, 3),
  228. .trig = TRIGGER(0x0b00, 2),
  229. };
  230. /*
  231. * CCU clocks
  232. */
  233. static struct ccu_clock kpm_ccu_clk = {
  234. .clk = {
  235. .name = "kpm_ccu_clk",
  236. .ops = &ccu_clk_ops,
  237. .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
  238. },
  239. .num_policy_masks = 1,
  240. .policy_freq_offset = 0x00000008,
  241. .freq_bit_shift = 8,
  242. .policy_ctl_offset = 0x0000000c,
  243. .policy0_mask_offset = 0x00000010,
  244. .policy1_mask_offset = 0x00000014,
  245. .policy2_mask_offset = 0x00000018,
  246. .policy3_mask_offset = 0x0000001c,
  247. .lvm_en_offset = 0x00000034,
  248. .freq_id = 2,
  249. .freq_tbl = master_axi_freq_tbl,
  250. };
  251. static struct ccu_clock kps_ccu_clk = {
  252. .clk = {
  253. .name = "kps_ccu_clk",
  254. .ops = &ccu_clk_ops,
  255. .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
  256. },
  257. .num_policy_masks = 2,
  258. .policy_freq_offset = 0x00000008,
  259. .freq_bit_shift = 8,
  260. .policy_ctl_offset = 0x0000000c,
  261. .policy0_mask_offset = 0x00000010,
  262. .policy1_mask_offset = 0x00000014,
  263. .policy2_mask_offset = 0x00000018,
  264. .policy3_mask_offset = 0x0000001c,
  265. .policy0_mask2_offset = 0x00000048,
  266. .policy1_mask2_offset = 0x0000004c,
  267. .policy2_mask2_offset = 0x00000050,
  268. .policy3_mask2_offset = 0x00000054,
  269. .lvm_en_offset = 0x00000034,
  270. .freq_id = 2,
  271. .freq_tbl = slave_axi_freq_tbl,
  272. };
  273. #ifdef CONFIG_BCM_SF2_ETH
  274. static struct ccu_clock esub_ccu_clk = {
  275. .clk = {
  276. .name = "esub_ccu_clk",
  277. .ops = &ccu_clk_ops,
  278. .ccu_clk_mgr_base = ESUB_CLK_BASE_ADDR,
  279. },
  280. .num_policy_masks = 1,
  281. .policy_freq_offset = 0x00000008,
  282. .freq_bit_shift = 8,
  283. .policy_ctl_offset = 0x0000000c,
  284. .policy0_mask_offset = 0x00000010,
  285. .policy1_mask_offset = 0x00000014,
  286. .policy2_mask_offset = 0x00000018,
  287. .policy3_mask_offset = 0x0000001c,
  288. .lvm_en_offset = 0x00000034,
  289. .freq_id = 2,
  290. .freq_tbl = esub_freq_tbl,
  291. };
  292. #endif
  293. /*
  294. * Bus clocks
  295. */
  296. /* KPM bus clocks */
  297. static struct bus_clock usb_otg_ahb_clk = {
  298. .clk = {
  299. .name = "usb_otg_ahb_clk",
  300. .parent = &kpm_ccu_clk.clk,
  301. .ops = &bus_clk_ops,
  302. .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
  303. },
  304. .freq_tbl = master_ahb_freq_tbl,
  305. .data = &usb_otg_ahb_data,
  306. };
  307. static struct bus_clock sdio1_ahb_clk = {
  308. .clk = {
  309. .name = "sdio1_ahb_clk",
  310. .parent = &kpm_ccu_clk.clk,
  311. .ops = &bus_clk_ops,
  312. .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
  313. },
  314. .freq_tbl = master_ahb_freq_tbl,
  315. .data = &sdio1_ahb_data,
  316. };
  317. static struct bus_clock sdio2_ahb_clk = {
  318. .clk = {
  319. .name = "sdio2_ahb_clk",
  320. .parent = &kpm_ccu_clk.clk,
  321. .ops = &bus_clk_ops,
  322. .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
  323. },
  324. .freq_tbl = master_ahb_freq_tbl,
  325. .data = &sdio2_ahb_data,
  326. };
  327. static struct bus_clock sdio3_ahb_clk = {
  328. .clk = {
  329. .name = "sdio3_ahb_clk",
  330. .parent = &kpm_ccu_clk.clk,
  331. .ops = &bus_clk_ops,
  332. .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
  333. },
  334. .freq_tbl = master_ahb_freq_tbl,
  335. .data = &sdio3_ahb_data,
  336. };
  337. static struct bus_clock sdio4_ahb_clk = {
  338. .clk = {
  339. .name = "sdio4_ahb_clk",
  340. .parent = &kpm_ccu_clk.clk,
  341. .ops = &bus_clk_ops,
  342. .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
  343. },
  344. .freq_tbl = master_ahb_freq_tbl,
  345. .data = &sdio4_ahb_data,
  346. };
  347. static struct bus_clock bsc1_apb_clk = {
  348. .clk = {
  349. .name = "bsc1_apb_clk",
  350. .parent = &kps_ccu_clk.clk,
  351. .ops = &bus_clk_ops,
  352. .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
  353. },
  354. .freq_tbl = slave_apb_freq_tbl,
  355. .data = &bsc1_apb_data,
  356. };
  357. static struct bus_clock bsc2_apb_clk = {
  358. .clk = {
  359. .name = "bsc2_apb_clk",
  360. .parent = &kps_ccu_clk.clk,
  361. .ops = &bus_clk_ops,
  362. .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
  363. },
  364. .freq_tbl = slave_apb_freq_tbl,
  365. .data = &bsc2_apb_data,
  366. };
  367. static struct bus_clock bsc3_apb_clk = {
  368. .clk = {
  369. .name = "bsc3_apb_clk",
  370. .parent = &kps_ccu_clk.clk,
  371. .ops = &bus_clk_ops,
  372. .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
  373. },
  374. .freq_tbl = slave_apb_freq_tbl,
  375. .data = &bsc3_apb_data,
  376. };
  377. /* KPM peripheral */
  378. static struct peri_clock sdio1_clk = {
  379. .clk = {
  380. .name = "sdio1_clk",
  381. .parent = &ref_52m.clk,
  382. .ops = &peri_clk_ops,
  383. .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
  384. },
  385. .data = &sdio1_data,
  386. };
  387. static struct peri_clock sdio2_clk = {
  388. .clk = {
  389. .name = "sdio2_clk",
  390. .parent = &ref_52m.clk,
  391. .ops = &peri_clk_ops,
  392. .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
  393. },
  394. .data = &sdio2_data,
  395. };
  396. static struct peri_clock sdio3_clk = {
  397. .clk = {
  398. .name = "sdio3_clk",
  399. .parent = &ref_52m.clk,
  400. .ops = &peri_clk_ops,
  401. .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
  402. },
  403. .data = &sdio3_data,
  404. };
  405. static struct peri_clock sdio4_clk = {
  406. .clk = {
  407. .name = "sdio4_clk",
  408. .parent = &ref_52m.clk,
  409. .ops = &peri_clk_ops,
  410. .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
  411. },
  412. .data = &sdio4_data,
  413. };
  414. static struct peri_clock sdio1_sleep_clk = {
  415. .clk = {
  416. .name = "sdio1_sleep_clk",
  417. .parent = &kpm_ccu_clk.clk,
  418. .ops = &bus_clk_ops,
  419. .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
  420. },
  421. .data = &sdio1_sleep_data,
  422. };
  423. static struct peri_clock sdio2_sleep_clk = {
  424. .clk = {
  425. .name = "sdio2_sleep_clk",
  426. .parent = &kpm_ccu_clk.clk,
  427. .ops = &bus_clk_ops,
  428. .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
  429. },
  430. .data = &sdio2_sleep_data,
  431. };
  432. static struct peri_clock sdio3_sleep_clk = {
  433. .clk = {
  434. .name = "sdio3_sleep_clk",
  435. .parent = &kpm_ccu_clk.clk,
  436. .ops = &bus_clk_ops,
  437. .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
  438. },
  439. .data = &sdio3_sleep_data,
  440. };
  441. static struct peri_clock sdio4_sleep_clk = {
  442. .clk = {
  443. .name = "sdio4_sleep_clk",
  444. .parent = &kpm_ccu_clk.clk,
  445. .ops = &bus_clk_ops,
  446. .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
  447. },
  448. .data = &sdio4_sleep_data,
  449. };
  450. /* KPS peripheral clock */
  451. static struct peri_clock bsc1_clk = {
  452. .clk = {
  453. .name = "bsc1_clk",
  454. .parent = &ref_13m.clk,
  455. .rate = 13 * CLOCK_1M,
  456. .div = 1,
  457. .ops = &peri_clk_ops,
  458. .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
  459. },
  460. .data = &bsc1_data,
  461. };
  462. static struct peri_clock bsc2_clk = {
  463. .clk = {
  464. .name = "bsc2_clk",
  465. .parent = &ref_13m.clk,
  466. .rate = 13 * CLOCK_1M,
  467. .div = 1,
  468. .ops = &peri_clk_ops,
  469. .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
  470. },
  471. .data = &bsc2_data,
  472. };
  473. static struct peri_clock bsc3_clk = {
  474. .clk = {
  475. .name = "bsc3_clk",
  476. .parent = &ref_13m.clk,
  477. .rate = 13 * CLOCK_1M,
  478. .div = 1,
  479. .ops = &peri_clk_ops,
  480. .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
  481. },
  482. .data = &bsc3_data,
  483. };
  484. /* public table for registering clocks */
  485. struct clk_lookup arch_clk_tbl[] = {
  486. /* Peripheral clocks */
  487. CLK_LK(sdio1),
  488. CLK_LK(sdio2),
  489. CLK_LK(sdio3),
  490. CLK_LK(sdio4),
  491. CLK_LK(sdio1_sleep),
  492. CLK_LK(sdio2_sleep),
  493. CLK_LK(sdio3_sleep),
  494. CLK_LK(sdio4_sleep),
  495. CLK_LK(bsc1),
  496. CLK_LK(bsc2),
  497. CLK_LK(bsc3),
  498. /* Bus clocks */
  499. CLK_LK(usb_otg_ahb),
  500. CLK_LK(sdio1_ahb),
  501. CLK_LK(sdio2_ahb),
  502. CLK_LK(sdio3_ahb),
  503. CLK_LK(sdio4_ahb),
  504. CLK_LK(bsc1_apb),
  505. CLK_LK(bsc2_apb),
  506. CLK_LK(bsc3_apb),
  507. #ifdef CONFIG_BCM_SF2_ETH
  508. CLK_LK(esub_ccu),
  509. #endif
  510. };
  511. /* public array size */
  512. unsigned int arch_clk_tbl_array_size = ARRAY_SIZE(arch_clk_tbl);