clk_zynqmp.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * ZynqMP clock driver
  4. *
  5. * Copyright (C) 2016 Xilinx, Inc.
  6. */
  7. #include <common.h>
  8. #include <log.h>
  9. #include <malloc.h>
  10. #include <dm/device_compat.h>
  11. #include <linux/bitops.h>
  12. #include <clk-uclass.h>
  13. #include <clk.h>
  14. #include <asm/arch/sys_proto.h>
  15. #include <dm.h>
  16. #include <linux/err.h>
  17. static const resource_size_t zynqmp_crf_apb_clkc_base = 0xfd1a0020;
  18. static const resource_size_t zynqmp_crl_apb_clkc_base = 0xff5e0020;
  19. /* Full power domain clocks */
  20. #define CRF_APB_APLL_CTRL (zynqmp_crf_apb_clkc_base + 0x00)
  21. #define CRF_APB_DPLL_CTRL (zynqmp_crf_apb_clkc_base + 0x0c)
  22. #define CRF_APB_VPLL_CTRL (zynqmp_crf_apb_clkc_base + 0x18)
  23. #define CRF_APB_PLL_STATUS (zynqmp_crf_apb_clkc_base + 0x24)
  24. #define CRF_APB_APLL_TO_LPD_CTRL (zynqmp_crf_apb_clkc_base + 0x28)
  25. #define CRF_APB_DPLL_TO_LPD_CTRL (zynqmp_crf_apb_clkc_base + 0x2c)
  26. #define CRF_APB_VPLL_TO_LPD_CTRL (zynqmp_crf_apb_clkc_base + 0x30)
  27. /* Peripheral clocks */
  28. #define CRF_APB_ACPU_CTRL (zynqmp_crf_apb_clkc_base + 0x40)
  29. #define CRF_APB_DBG_TRACE_CTRL (zynqmp_crf_apb_clkc_base + 0x44)
  30. #define CRF_APB_DBG_FPD_CTRL (zynqmp_crf_apb_clkc_base + 0x48)
  31. #define CRF_APB_DP_VIDEO_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x50)
  32. #define CRF_APB_DP_AUDIO_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x54)
  33. #define CRF_APB_DP_STC_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x5c)
  34. #define CRF_APB_DDR_CTRL (zynqmp_crf_apb_clkc_base + 0x60)
  35. #define CRF_APB_GPU_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x64)
  36. #define CRF_APB_SATA_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x80)
  37. #define CRF_APB_PCIE_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x94)
  38. #define CRF_APB_GDMA_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x98)
  39. #define CRF_APB_DPDMA_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x9c)
  40. #define CRF_APB_TOPSW_MAIN_CTRL (zynqmp_crf_apb_clkc_base + 0xa0)
  41. #define CRF_APB_TOPSW_LSBUS_CTRL (zynqmp_crf_apb_clkc_base + 0xa4)
  42. #define CRF_APB_GTGREF0_REF_CTRL (zynqmp_crf_apb_clkc_base + 0xa8)
  43. #define CRF_APB_DBG_TSTMP_CTRL (zynqmp_crf_apb_clkc_base + 0xd8)
  44. /* Low power domain clocks */
  45. #define CRL_APB_IOPLL_CTRL (zynqmp_crl_apb_clkc_base + 0x00)
  46. #define CRL_APB_RPLL_CTRL (zynqmp_crl_apb_clkc_base + 0x10)
  47. #define CRL_APB_PLL_STATUS (zynqmp_crl_apb_clkc_base + 0x20)
  48. #define CRL_APB_IOPLL_TO_FPD_CTRL (zynqmp_crl_apb_clkc_base + 0x24)
  49. #define CRL_APB_RPLL_TO_FPD_CTRL (zynqmp_crl_apb_clkc_base + 0x28)
  50. /* Peripheral clocks */
  51. #define CRL_APB_USB3_DUAL_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x2c)
  52. #define CRL_APB_GEM0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x30)
  53. #define CRL_APB_GEM1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x34)
  54. #define CRL_APB_GEM2_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x38)
  55. #define CRL_APB_GEM3_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x3c)
  56. #define CRL_APB_USB0_BUS_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x40)
  57. #define CRL_APB_USB1_BUS_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x44)
  58. #define CRL_APB_QSPI_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x48)
  59. #define CRL_APB_SDIO0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x4c)
  60. #define CRL_APB_SDIO1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x50)
  61. #define CRL_APB_UART0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x54)
  62. #define CRL_APB_UART1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x58)
  63. #define CRL_APB_SPI0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x5c)
  64. #define CRL_APB_SPI1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x60)
  65. #define CRL_APB_CAN0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x64)
  66. #define CRL_APB_CAN1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x68)
  67. #define CRL_APB_CPU_R5_CTRL (zynqmp_crl_apb_clkc_base + 0x70)
  68. #define CRL_APB_IOU_SWITCH_CTRL (zynqmp_crl_apb_clkc_base + 0x7c)
  69. #define CRL_APB_CSU_PLL_CTRL (zynqmp_crl_apb_clkc_base + 0x80)
  70. #define CRL_APB_PCAP_CTRL (zynqmp_crl_apb_clkc_base + 0x84)
  71. #define CRL_APB_LPD_SWITCH_CTRL (zynqmp_crl_apb_clkc_base + 0x88)
  72. #define CRL_APB_LPD_LSBUS_CTRL (zynqmp_crl_apb_clkc_base + 0x8c)
  73. #define CRL_APB_DBG_LPD_CTRL (zynqmp_crl_apb_clkc_base + 0x90)
  74. #define CRL_APB_NAND_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x94)
  75. #define CRL_APB_ADMA_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x98)
  76. #define CRL_APB_PL0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xa0)
  77. #define CRL_APB_PL1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xa4)
  78. #define CRL_APB_PL2_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xa8)
  79. #define CRL_APB_PL3_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xac)
  80. #define CRL_APB_PL0_THR_CNT (zynqmp_crl_apb_clkc_base + 0xb4)
  81. #define CRL_APB_PL1_THR_CNT (zynqmp_crl_apb_clkc_base + 0xbc)
  82. #define CRL_APB_PL2_THR_CNT (zynqmp_crl_apb_clkc_base + 0xc4)
  83. #define CRL_APB_PL3_THR_CNT (zynqmp_crl_apb_clkc_base + 0xdc)
  84. #define CRL_APB_GEM_TSU_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xe0)
  85. #define CRL_APB_DLL_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xe4)
  86. #define CRL_APB_AMS_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xe8)
  87. #define CRL_APB_I2C0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x100)
  88. #define CRL_APB_I2C1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x104)
  89. #define CRL_APB_TIMESTAMP_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x108)
  90. #define ZYNQ_CLK_MAXDIV 0x3f
  91. #define CLK_CTRL_DIV1_SHIFT 16
  92. #define CLK_CTRL_DIV1_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT)
  93. #define CLK_CTRL_DIV0_SHIFT 8
  94. #define CLK_CTRL_DIV0_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT)
  95. #define CLK_CTRL_SRCSEL_MASK 0x7
  96. #define PLLCTRL_FBDIV_MASK 0x7f00
  97. #define PLLCTRL_FBDIV_SHIFT 8
  98. #define PLLCTRL_RESET_MASK 1
  99. #define PLLCTRL_RESET_SHIFT 0
  100. #define PLLCTRL_BYPASS_MASK 0x8
  101. #define PLLCTRL_BYPASS_SHFT 3
  102. #define PLLCTRL_POST_SRC_SHFT 24
  103. #define PLLCTRL_POST_SRC_MASK (0x7 << PLLCTRL_POST_SRC_SHFT)
  104. #define PLLCTRL_PRE_SRC_SHFT 20
  105. #define PLLCTRL_PRE_SRC_MASK (0x7 << PLLCTRL_PRE_SRC_SHFT)
  106. #define NUM_MIO_PINS 77
  107. enum zynqmp_clk {
  108. iopll, rpll,
  109. apll, dpll, vpll,
  110. iopll_to_fpd, rpll_to_fpd, apll_to_lpd, dpll_to_lpd, vpll_to_lpd,
  111. acpu, acpu_half,
  112. dbg_fpd, dbg_lpd, dbg_trace, dbg_tstmp,
  113. dp_video_ref, dp_audio_ref,
  114. dp_stc_ref, gdma_ref, dpdma_ref,
  115. ddr_ref, sata_ref, pcie_ref,
  116. gpu_ref, gpu_pp0_ref, gpu_pp1_ref,
  117. topsw_main, topsw_lsbus,
  118. gtgref0_ref,
  119. lpd_switch, lpd_lsbus,
  120. usb0_bus_ref, usb1_bus_ref, usb3_dual_ref, usb0, usb1,
  121. cpu_r5, cpu_r5_core,
  122. csu_spb, csu_pll, pcap,
  123. iou_switch,
  124. gem_tsu_ref, gem_tsu,
  125. gem0_ref, gem1_ref, gem2_ref, gem3_ref,
  126. gem0_tx, gem1_tx, gem2_tx, gem3_tx,
  127. qspi_ref,
  128. sdio0_ref, sdio1_ref,
  129. uart0_ref, uart1_ref,
  130. spi0_ref, spi1_ref,
  131. nand_ref,
  132. i2c0_ref, i2c1_ref, can0_ref, can1_ref, can0, can1,
  133. dll_ref,
  134. adma_ref,
  135. timestamp_ref,
  136. ams_ref,
  137. pl0, pl1, pl2, pl3,
  138. wdt,
  139. clk_max,
  140. };
  141. static const char * const clk_names[clk_max] = {
  142. "iopll", "rpll", "apll", "dpll",
  143. "vpll", "iopll_to_fpd", "rpll_to_fpd",
  144. "apll_to_lpd", "dpll_to_lpd", "vpll_to_lpd",
  145. "acpu", "acpu_half", "dbg_fpd", "dbg_lpd",
  146. "dbg_trace", "dbg_tstmp", "dp_video_ref",
  147. "dp_audio_ref", "dp_stc_ref", "gdma_ref",
  148. "dpdma_ref", "ddr_ref", "sata_ref", "pcie_ref",
  149. "gpu_ref", "gpu_pp0_ref", "gpu_pp1_ref",
  150. "topsw_main", "topsw_lsbus", "gtgref0_ref",
  151. "lpd_switch", "lpd_lsbus", "usb0_bus_ref",
  152. "usb1_bus_ref", "usb3_dual_ref", "usb0",
  153. "usb1", "cpu_r5", "cpu_r5_core", "csu_spb",
  154. "csu_pll", "pcap", "iou_switch", "gem_tsu_ref",
  155. "gem_tsu", "gem0_ref", "gem1_ref", "gem2_ref",
  156. "gem3_ref", "gem0_tx", "gem1_tx", "gem2_tx",
  157. "gem3_tx", "qspi_ref", "sdio0_ref", "sdio1_ref",
  158. "uart0_ref", "uart1_ref", "spi0_ref",
  159. "spi1_ref", "nand_ref", "i2c0_ref", "i2c1_ref",
  160. "can0_ref", "can1_ref", "can0", "can1",
  161. "dll_ref", "adma_ref", "timestamp_ref",
  162. "ams_ref", "pl0", "pl1", "pl2", "pl3", "wdt"
  163. };
  164. static const u32 pll_src[][4] = {
  165. {apll, 0xff, dpll, vpll}, /* acpu */
  166. {dpll, vpll, 0xff, 0xff}, /* ddr_ref */
  167. {rpll, iopll, 0xff, 0xff}, /* dll_ref */
  168. {iopll, 0xff, rpll, dpll_to_lpd}, /* gem_tsu_ref */
  169. {iopll, 0xff, rpll, dpll}, /* peripheral */
  170. {apll, 0xff, iopll_to_fpd, dpll}, /* wdt */
  171. {iopll_to_fpd, 0xff, dpll, apll}, /* dbg_fpd */
  172. {iopll, 0xff, rpll, dpll_to_lpd}, /* timestamp_ref */
  173. {iopll_to_fpd, 0xff, apll, dpll}, /* sata_ref */
  174. {iopll_to_fpd, 0xff, rpll_to_fpd, dpll},/* pcie_ref */
  175. {iopll_to_fpd, 0xff, vpll, dpll}, /* gpu_ref */
  176. {apll, 0xff, vpll, dpll}, /* topsw_main_ref */
  177. {rpll, 0xff, iopll, dpll_to_lpd}, /* cpu_r5_ref */
  178. };
  179. enum zynqmp_clk_pll_src {
  180. ACPU_CLK_SRC = 0,
  181. DDR_CLK_SRC,
  182. DLL_CLK_SRC,
  183. GEM_TSU_CLK_SRC,
  184. PERI_CLK_SRC,
  185. WDT_CLK_SRC,
  186. DBG_FPD_CLK_SRC,
  187. TIMESTAMP_CLK_SRC,
  188. SATA_CLK_SRC,
  189. PCIE_CLK_SRC,
  190. GPU_CLK_SRC,
  191. TOPSW_MAIN_CLK_SRC,
  192. CPU_R5_CLK_SRC
  193. };
  194. struct zynqmp_clk_priv {
  195. unsigned long ps_clk_freq;
  196. unsigned long video_clk;
  197. unsigned long pss_alt_ref_clk;
  198. unsigned long gt_crx_ref_clk;
  199. unsigned long aux_ref_clk;
  200. };
  201. static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
  202. {
  203. switch (id) {
  204. case iopll:
  205. return CRL_APB_IOPLL_CTRL;
  206. case rpll:
  207. return CRL_APB_RPLL_CTRL;
  208. case apll:
  209. return CRF_APB_APLL_CTRL;
  210. case dpll:
  211. return CRF_APB_DPLL_CTRL;
  212. case vpll:
  213. return CRF_APB_VPLL_CTRL;
  214. case acpu:
  215. return CRF_APB_ACPU_CTRL;
  216. case dbg_fpd:
  217. return CRF_APB_DBG_FPD_CTRL;
  218. case dbg_trace:
  219. return CRF_APB_DBG_TRACE_CTRL;
  220. case dbg_tstmp:
  221. return CRF_APB_DBG_TSTMP_CTRL;
  222. case gpu_ref ... gpu_pp1_ref:
  223. return CRF_APB_GPU_REF_CTRL;
  224. case ddr_ref:
  225. return CRF_APB_DDR_CTRL;
  226. case sata_ref:
  227. return CRF_APB_SATA_REF_CTRL;
  228. case pcie_ref:
  229. return CRF_APB_PCIE_REF_CTRL;
  230. case gdma_ref:
  231. return CRF_APB_GDMA_REF_CTRL;
  232. case dpdma_ref:
  233. return CRF_APB_DPDMA_REF_CTRL;
  234. case topsw_main:
  235. return CRF_APB_TOPSW_MAIN_CTRL;
  236. case topsw_lsbus:
  237. return CRF_APB_TOPSW_LSBUS_CTRL;
  238. case lpd_switch:
  239. return CRL_APB_LPD_SWITCH_CTRL;
  240. case lpd_lsbus:
  241. return CRL_APB_LPD_LSBUS_CTRL;
  242. case qspi_ref:
  243. return CRL_APB_QSPI_REF_CTRL;
  244. case usb3_dual_ref:
  245. return CRL_APB_USB3_DUAL_REF_CTRL;
  246. case gem_tsu_ref:
  247. return CRL_APB_GEM_TSU_REF_CTRL;
  248. case gem0_ref:
  249. return CRL_APB_GEM0_REF_CTRL;
  250. case gem1_ref:
  251. return CRL_APB_GEM1_REF_CTRL;
  252. case gem2_ref:
  253. return CRL_APB_GEM2_REF_CTRL;
  254. case gem3_ref:
  255. return CRL_APB_GEM3_REF_CTRL;
  256. case usb0_bus_ref:
  257. return CRL_APB_USB0_BUS_REF_CTRL;
  258. case usb1_bus_ref:
  259. return CRL_APB_USB1_BUS_REF_CTRL;
  260. case cpu_r5:
  261. return CRL_APB_CPU_R5_CTRL;
  262. case uart0_ref:
  263. return CRL_APB_UART0_REF_CTRL;
  264. case uart1_ref:
  265. return CRL_APB_UART1_REF_CTRL;
  266. case sdio0_ref:
  267. return CRL_APB_SDIO0_REF_CTRL;
  268. case sdio1_ref:
  269. return CRL_APB_SDIO1_REF_CTRL;
  270. case spi0_ref:
  271. return CRL_APB_SPI0_REF_CTRL;
  272. case spi1_ref:
  273. return CRL_APB_SPI1_REF_CTRL;
  274. case nand_ref:
  275. return CRL_APB_NAND_REF_CTRL;
  276. case i2c0_ref:
  277. return CRL_APB_I2C0_REF_CTRL;
  278. case i2c1_ref:
  279. return CRL_APB_I2C1_REF_CTRL;
  280. case can0_ref:
  281. return CRL_APB_CAN0_REF_CTRL;
  282. case can1_ref:
  283. return CRL_APB_CAN1_REF_CTRL;
  284. case dll_ref:
  285. return CRL_APB_DLL_REF_CTRL;
  286. case adma_ref:
  287. return CRL_APB_ADMA_REF_CTRL;
  288. case timestamp_ref:
  289. return CRL_APB_TIMESTAMP_REF_CTRL;
  290. case ams_ref:
  291. return CRL_APB_AMS_REF_CTRL;
  292. case pl0:
  293. return CRL_APB_PL0_REF_CTRL;
  294. case pl1:
  295. return CRL_APB_PL1_REF_CTRL;
  296. case pl2:
  297. return CRL_APB_PL2_REF_CTRL;
  298. case pl3:
  299. return CRL_APB_PL3_REF_CTRL;
  300. case wdt:
  301. return CRF_APB_TOPSW_LSBUS_CTRL;
  302. case iopll_to_fpd:
  303. return CRL_APB_IOPLL_TO_FPD_CTRL;
  304. default:
  305. debug("Invalid clk id%d\n", id);
  306. }
  307. return 0;
  308. }
  309. static ulong zynqmp_clk_get_pll_src(ulong clk_ctrl,
  310. struct zynqmp_clk_priv *priv,
  311. bool is_pre_src)
  312. {
  313. u32 src_sel;
  314. if (is_pre_src)
  315. src_sel = (clk_ctrl & PLLCTRL_PRE_SRC_MASK) >>
  316. PLLCTRL_PRE_SRC_SHFT;
  317. else
  318. src_sel = (clk_ctrl & PLLCTRL_POST_SRC_MASK) >>
  319. PLLCTRL_POST_SRC_SHFT;
  320. switch (src_sel) {
  321. case 4:
  322. return priv->video_clk;
  323. case 5:
  324. return priv->pss_alt_ref_clk;
  325. case 6:
  326. return priv->aux_ref_clk;
  327. case 7:
  328. return priv->gt_crx_ref_clk;
  329. case 0 ... 3:
  330. default:
  331. return priv->ps_clk_freq;
  332. }
  333. }
  334. static ulong zynqmp_clk_get_pll_rate(struct zynqmp_clk_priv *priv,
  335. enum zynqmp_clk id)
  336. {
  337. u32 clk_ctrl, reset, mul;
  338. ulong freq;
  339. int ret;
  340. ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
  341. if (ret) {
  342. printf("%s mio read fail\n", __func__);
  343. return -EIO;
  344. }
  345. if (clk_ctrl & PLLCTRL_BYPASS_MASK)
  346. freq = zynqmp_clk_get_pll_src(clk_ctrl, priv, 0);
  347. else
  348. freq = zynqmp_clk_get_pll_src(clk_ctrl, priv, 1);
  349. reset = (clk_ctrl & PLLCTRL_RESET_MASK) >> PLLCTRL_RESET_SHIFT;
  350. if (reset && !(clk_ctrl & PLLCTRL_BYPASS_MASK))
  351. return 0;
  352. mul = (clk_ctrl & PLLCTRL_FBDIV_MASK) >> PLLCTRL_FBDIV_SHIFT;
  353. freq *= mul;
  354. if (clk_ctrl & (1 << 16))
  355. freq /= 2;
  356. return freq;
  357. }
  358. static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
  359. enum zynqmp_clk id)
  360. {
  361. u32 clk_ctrl, div, srcsel;
  362. enum zynqmp_clk pll;
  363. int ret;
  364. unsigned long pllrate;
  365. ret = zynqmp_mmio_read(CRF_APB_ACPU_CTRL, &clk_ctrl);
  366. if (ret) {
  367. printf("%s mio read fail\n", __func__);
  368. return -EIO;
  369. }
  370. div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
  371. srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
  372. pll = pll_src[ACPU_CLK_SRC][srcsel];
  373. pllrate = zynqmp_clk_get_pll_rate(priv, pll);
  374. if (IS_ERR_VALUE(pllrate))
  375. return pllrate;
  376. return DIV_ROUND_CLOSEST(pllrate, div);
  377. }
  378. static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
  379. {
  380. u32 clk_ctrl, div, srcsel;
  381. enum zynqmp_clk pll;
  382. int ret;
  383. ulong pllrate;
  384. ret = zynqmp_mmio_read(CRF_APB_DDR_CTRL, &clk_ctrl);
  385. if (ret) {
  386. printf("%s mio read fail\n", __func__);
  387. return -EIO;
  388. }
  389. div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
  390. srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
  391. pll = pll_src[DDR_CLK_SRC][srcsel];
  392. pllrate = zynqmp_clk_get_pll_rate(priv, pll);
  393. if (IS_ERR_VALUE(pllrate))
  394. return pllrate;
  395. return DIV_ROUND_CLOSEST(pllrate, div);
  396. }
  397. static ulong zynqmp_clk_get_dll_rate(struct zynqmp_clk_priv *priv)
  398. {
  399. u32 clk_ctrl, srcsel;
  400. enum zynqmp_clk pll;
  401. ulong pllrate;
  402. int ret;
  403. ret = zynqmp_mmio_read(CRL_APB_DLL_REF_CTRL, &clk_ctrl);
  404. if (ret) {
  405. printf("%s mio read fail\n", __func__);
  406. return -EIO;
  407. }
  408. srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
  409. pll = pll_src[DLL_CLK_SRC][srcsel];
  410. pllrate = zynqmp_clk_get_pll_rate(priv, pll);
  411. if (IS_ERR_VALUE(pllrate))
  412. return pllrate;
  413. return pllrate;
  414. }
  415. static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
  416. enum zynqmp_clk id, bool two_divs)
  417. {
  418. enum zynqmp_clk pll;
  419. u32 clk_ctrl, div0, srcsel;
  420. u32 div1 = 1;
  421. int ret;
  422. ulong pllrate;
  423. ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
  424. if (ret) {
  425. printf("%s mio read fail\n", __func__);
  426. return -EIO;
  427. }
  428. div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
  429. if (!div0)
  430. div0 = 1;
  431. if (two_divs) {
  432. div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
  433. if (!div1)
  434. div1 = 1;
  435. }
  436. srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
  437. if (id == gem_tsu_ref)
  438. pll = pll_src[GEM_TSU_CLK_SRC][srcsel];
  439. else
  440. pll = pll_src[PERI_CLK_SRC][srcsel];
  441. pllrate = zynqmp_clk_get_pll_rate(priv, pll);
  442. if (IS_ERR_VALUE(pllrate))
  443. return pllrate;
  444. return
  445. DIV_ROUND_CLOSEST(
  446. DIV_ROUND_CLOSEST(pllrate, div0), div1);
  447. }
  448. static ulong zynqmp_clk_get_crf_crl_rate(struct zynqmp_clk_priv *priv,
  449. enum zynqmp_clk id, bool two_divs)
  450. {
  451. enum zynqmp_clk pll;
  452. u32 clk_ctrl, div0, srcsel;
  453. u32 div1 = 1;
  454. int ret;
  455. ulong pllrate;
  456. ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
  457. if (ret) {
  458. printf("%d %s mio read fail\n", __LINE__, __func__);
  459. return -EIO;
  460. }
  461. div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
  462. if (!div0)
  463. div0 = 1;
  464. srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
  465. switch (id) {
  466. case wdt:
  467. case dbg_trace:
  468. case topsw_lsbus:
  469. pll = pll_src[WDT_CLK_SRC][srcsel];
  470. break;
  471. case dbg_fpd:
  472. case dbg_tstmp:
  473. pll = pll_src[DBG_FPD_CLK_SRC][srcsel];
  474. break;
  475. case timestamp_ref:
  476. pll = pll_src[TIMESTAMP_CLK_SRC][srcsel];
  477. break;
  478. case sata_ref:
  479. pll = pll_src[SATA_CLK_SRC][srcsel];
  480. break;
  481. case pcie_ref:
  482. pll = pll_src[PCIE_CLK_SRC][srcsel];
  483. break;
  484. case gpu_ref ... gpu_pp1_ref:
  485. pll = pll_src[GPU_CLK_SRC][srcsel];
  486. break;
  487. case gdma_ref:
  488. case dpdma_ref:
  489. case topsw_main:
  490. pll = pll_src[TOPSW_MAIN_CLK_SRC][srcsel];
  491. break;
  492. case cpu_r5:
  493. case ams_ref:
  494. case adma_ref:
  495. case lpd_lsbus:
  496. case lpd_switch:
  497. pll = pll_src[CPU_R5_CLK_SRC][srcsel];
  498. break;
  499. default:
  500. return -ENXIO;
  501. }
  502. if (two_divs) {
  503. ret = zynqmp_mmio_read(zynqmp_clk_get_register(pll), &clk_ctrl);
  504. if (ret) {
  505. printf("%d %s mio read fail\n", __LINE__, __func__);
  506. return -EIO;
  507. }
  508. div1 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
  509. if (!div1)
  510. div1 = 1;
  511. }
  512. if (pll == iopll_to_fpd)
  513. pll = iopll;
  514. pllrate = zynqmp_clk_get_pll_rate(priv, pll);
  515. if (IS_ERR_VALUE(pllrate))
  516. return pllrate;
  517. return
  518. DIV_ROUND_CLOSEST(
  519. DIV_ROUND_CLOSEST(pllrate, div0), div1);
  520. }
  521. static unsigned long zynqmp_clk_calc_peripheral_two_divs(ulong rate,
  522. ulong pll_rate,
  523. u32 *div0, u32 *div1)
  524. {
  525. long new_err, best_err = (long)(~0UL >> 1);
  526. ulong new_rate, best_rate = 0;
  527. u32 d0, d1;
  528. for (d0 = 1; d0 <= ZYNQ_CLK_MAXDIV; d0++) {
  529. for (d1 = 1; d1 <= ZYNQ_CLK_MAXDIV >> 1; d1++) {
  530. new_rate = DIV_ROUND_CLOSEST(
  531. DIV_ROUND_CLOSEST(pll_rate, d0), d1);
  532. new_err = abs(new_rate - rate);
  533. if (new_err < best_err) {
  534. *div0 = d0;
  535. *div1 = d1;
  536. best_err = new_err;
  537. best_rate = new_rate;
  538. }
  539. }
  540. }
  541. return best_rate;
  542. }
  543. static ulong zynqmp_clk_set_peripheral_rate(struct zynqmp_clk_priv *priv,
  544. enum zynqmp_clk id, ulong rate,
  545. bool two_divs)
  546. {
  547. enum zynqmp_clk pll;
  548. u32 clk_ctrl, div0 = 0, div1 = 0;
  549. ulong pll_rate, new_rate;
  550. u32 reg, srcsel;
  551. int ret;
  552. u32 mask;
  553. reg = zynqmp_clk_get_register(id);
  554. ret = zynqmp_mmio_read(reg, &clk_ctrl);
  555. if (ret) {
  556. printf("%s mio read fail\n", __func__);
  557. return -EIO;
  558. }
  559. srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
  560. pll = pll_src[PERI_CLK_SRC][srcsel];
  561. pll_rate = zynqmp_clk_get_pll_rate(priv, pll);
  562. if (IS_ERR_VALUE(pll_rate))
  563. return pll_rate;
  564. clk_ctrl &= ~CLK_CTRL_DIV0_MASK;
  565. if (two_divs) {
  566. clk_ctrl &= ~CLK_CTRL_DIV1_MASK;
  567. new_rate = zynqmp_clk_calc_peripheral_two_divs(rate, pll_rate,
  568. &div0, &div1);
  569. clk_ctrl |= div1 << CLK_CTRL_DIV1_SHIFT;
  570. } else {
  571. div0 = DIV_ROUND_CLOSEST(pll_rate, rate);
  572. if (div0 > ZYNQ_CLK_MAXDIV)
  573. div0 = ZYNQ_CLK_MAXDIV;
  574. new_rate = DIV_ROUND_CLOSEST(rate, div0);
  575. }
  576. clk_ctrl |= div0 << CLK_CTRL_DIV0_SHIFT;
  577. mask = (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT) |
  578. (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT);
  579. ret = zynqmp_mmio_write(reg, mask, clk_ctrl);
  580. if (ret) {
  581. printf("%s mio write fail\n", __func__);
  582. return -EIO;
  583. }
  584. return new_rate;
  585. }
  586. static ulong zynqmp_clk_get_rate(struct clk *clk)
  587. {
  588. struct zynqmp_clk_priv *priv = dev_get_priv(clk->dev);
  589. enum zynqmp_clk id = clk->id;
  590. bool two_divs = false;
  591. switch (id) {
  592. case iopll ... vpll:
  593. return zynqmp_clk_get_pll_rate(priv, id);
  594. case acpu:
  595. return zynqmp_clk_get_cpu_rate(priv, id);
  596. case ddr_ref:
  597. return zynqmp_clk_get_ddr_rate(priv);
  598. case dll_ref:
  599. return zynqmp_clk_get_dll_rate(priv);
  600. case gem_tsu_ref:
  601. case pl0 ... pl3:
  602. case gem0_ref ... gem3_ref:
  603. case qspi_ref ... can1_ref:
  604. case usb0_bus_ref ... usb3_dual_ref:
  605. two_divs = true;
  606. return zynqmp_clk_get_peripheral_rate(priv, id, two_divs);
  607. case wdt:
  608. case topsw_lsbus:
  609. case sata_ref ... gpu_pp1_ref:
  610. two_divs = true;
  611. case cpu_r5:
  612. case dbg_fpd:
  613. case ams_ref:
  614. case adma_ref:
  615. case lpd_lsbus:
  616. case dbg_trace:
  617. case dbg_tstmp:
  618. case lpd_switch:
  619. case topsw_main:
  620. case timestamp_ref:
  621. case gdma_ref ... dpdma_ref:
  622. return zynqmp_clk_get_crf_crl_rate(priv, id, two_divs);
  623. default:
  624. return -ENXIO;
  625. }
  626. }
  627. static ulong zynqmp_clk_set_rate(struct clk *clk, ulong rate)
  628. {
  629. struct zynqmp_clk_priv *priv = dev_get_priv(clk->dev);
  630. enum zynqmp_clk id = clk->id;
  631. bool two_divs = true;
  632. switch (id) {
  633. case gem0_ref ... gem3_ref:
  634. case qspi_ref ... can1_ref:
  635. return zynqmp_clk_set_peripheral_rate(priv, id,
  636. rate, two_divs);
  637. default:
  638. return -ENXIO;
  639. }
  640. }
  641. int soc_clk_dump(void)
  642. {
  643. struct udevice *dev;
  644. int i, ret;
  645. ret = uclass_get_device_by_driver(UCLASS_CLK,
  646. DM_DRIVER_GET(zynqmp_clk), &dev);
  647. if (ret)
  648. return ret;
  649. printf("clk\t\tfrequency\n");
  650. for (i = 0; i < clk_max; i++) {
  651. const char *name = clk_names[i];
  652. if (name) {
  653. struct clk clk;
  654. unsigned long rate;
  655. clk.id = i;
  656. ret = clk_request(dev, &clk);
  657. if (ret < 0)
  658. return ret;
  659. rate = clk_get_rate(&clk);
  660. clk_free(&clk);
  661. if ((rate == (unsigned long)-ENOSYS) ||
  662. (rate == (unsigned long)-ENXIO) ||
  663. (rate == (unsigned long)-EIO))
  664. printf("%10s%20s\n", name, "unknown");
  665. else
  666. printf("%10s%20lu\n", name, rate);
  667. }
  668. }
  669. return 0;
  670. }
  671. static int zynqmp_get_freq_by_name(char *name, struct udevice *dev, ulong *freq)
  672. {
  673. struct clk clk;
  674. int ret;
  675. ret = clk_get_by_name(dev, name, &clk);
  676. if (ret < 0) {
  677. dev_err(dev, "failed to get %s\n", name);
  678. return ret;
  679. }
  680. *freq = clk_get_rate(&clk);
  681. if (IS_ERR_VALUE(*freq)) {
  682. dev_err(dev, "failed to get rate %s\n", name);
  683. return -EINVAL;
  684. }
  685. return 0;
  686. }
  687. static int zynqmp_clk_probe(struct udevice *dev)
  688. {
  689. int ret;
  690. struct zynqmp_clk_priv *priv = dev_get_priv(dev);
  691. debug("%s\n", __func__);
  692. ret = zynqmp_get_freq_by_name("pss_ref_clk", dev, &priv->ps_clk_freq);
  693. if (ret < 0)
  694. return -EINVAL;
  695. ret = zynqmp_get_freq_by_name("video_clk", dev, &priv->video_clk);
  696. if (ret < 0)
  697. return -EINVAL;
  698. ret = zynqmp_get_freq_by_name("pss_alt_ref_clk", dev,
  699. &priv->pss_alt_ref_clk);
  700. if (ret < 0)
  701. return -EINVAL;
  702. ret = zynqmp_get_freq_by_name("aux_ref_clk", dev, &priv->aux_ref_clk);
  703. if (ret < 0)
  704. return -EINVAL;
  705. ret = zynqmp_get_freq_by_name("gt_crx_ref_clk", dev,
  706. &priv->gt_crx_ref_clk);
  707. if (ret < 0)
  708. return -EINVAL;
  709. return 0;
  710. }
  711. static int zynqmp_clk_enable(struct clk *clk)
  712. {
  713. enum zynqmp_clk id = clk->id;
  714. u32 reg, clk_ctrl, clkact_shift, mask;
  715. int ret;
  716. reg = zynqmp_clk_get_register(id);
  717. debug("%s, clk_id:%x, clk_base:0x%x\n", __func__, id, reg);
  718. switch (id) {
  719. case usb0_bus_ref ... usb1:
  720. clkact_shift = 25;
  721. mask = 0x1;
  722. break;
  723. case gem0_ref ... gem3_ref:
  724. clkact_shift = 25;
  725. mask = 0x3;
  726. break;
  727. case qspi_ref ... can1_ref:
  728. case lpd_lsbus:
  729. clkact_shift = 24;
  730. mask = 0x1;
  731. break;
  732. default:
  733. return -ENXIO;
  734. }
  735. ret = zynqmp_mmio_read(reg, &clk_ctrl);
  736. if (ret) {
  737. printf("%s mio read fail\n", __func__);
  738. return -EIO;
  739. }
  740. clk_ctrl |= (mask << clkact_shift);
  741. ret = zynqmp_mmio_write(reg, mask << clkact_shift, clk_ctrl);
  742. if (ret) {
  743. printf("%s mio write fail\n", __func__);
  744. return -EIO;
  745. }
  746. return ret;
  747. }
  748. static struct clk_ops zynqmp_clk_ops = {
  749. .set_rate = zynqmp_clk_set_rate,
  750. .get_rate = zynqmp_clk_get_rate,
  751. .enable = zynqmp_clk_enable,
  752. };
  753. static const struct udevice_id zynqmp_clk_ids[] = {
  754. { .compatible = "xlnx,zynqmp-clk" },
  755. { }
  756. };
  757. U_BOOT_DRIVER(zynqmp_clk) = {
  758. .name = "zynqmp_clk",
  759. .id = UCLASS_CLK,
  760. .of_match = zynqmp_clk_ids,
  761. .probe = zynqmp_clk_probe,
  762. .ops = &zynqmp_clk_ops,
  763. .priv_auto = sizeof(struct zynqmp_clk_priv),
  764. };