clk-hsdk-cgu.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. /*
  2. * Synopsys HSDK SDP CGU clock driver
  3. *
  4. * Copyright (C) 2017 Synopsys
  5. * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
  6. *
  7. * This file is licensed under the terms of the GNU General Public
  8. * License version 2. This program is licensed "as is" without any
  9. * warranty of any kind, whether express or implied.
  10. */
  11. #include <common.h>
  12. #include <clk-uclass.h>
  13. #include <div64.h>
  14. #include <dm.h>
  15. #include <log.h>
  16. #include <linux/bitops.h>
  17. #include <linux/bug.h>
  18. #include <linux/delay.h>
  19. #include <linux/io.h>
  20. #include <asm/arcregs.h>
  21. #include <dt-bindings/clock/snps,hsdk-cgu.h>
  22. /*
  23. * Synopsys ARC HSDK clock tree.
  24. *
  25. * ------------------
  26. * | 33.33 MHz xtal |
  27. * ------------------
  28. * |
  29. * | -----------
  30. * |-->| ARC PLL |
  31. * | -----------
  32. * | |
  33. * | |-->|CGU_ARC_IDIV|----------->
  34. * | |-->|CREG_CORE_IF_DIV|------->
  35. * |
  36. * | --------------
  37. * |-->| SYSTEM PLL |
  38. * | --------------
  39. * | |
  40. * | |-->|CGU_SYS_IDIV_APB|------->
  41. * | |-->|CGU_SYS_IDIV_AXI|------->
  42. * | |-->|CGU_SYS_IDIV_*|--------->
  43. * | |-->|CGU_SYS_IDIV_EBI_REF|--->
  44. * |
  45. * | --------------
  46. * |-->| TUNNEL PLL |
  47. * | --------------
  48. * | |
  49. * | |-->|CGU_TUN_IDIV_TUN|----------->
  50. * | |-->|CGU_TUN_IDIV_ROM|----------->
  51. * | |-->|CGU_TUN_IDIV_PWM|----------->
  52. * |
  53. * | -----------
  54. * |-->| DDR PLL |
  55. * -----------
  56. * |
  57. * |---------------------------->
  58. *
  59. * ------------------
  60. * | 27.00 MHz xtal |
  61. * ------------------
  62. * |
  63. * | ------------
  64. * |-->| HDMI PLL |
  65. * ------------
  66. * |
  67. * |-->|CGU_HDMI_IDIV_APB|------>
  68. */
  69. #define CGU_ARC_IDIV 0x080
  70. #define CGU_TUN_IDIV_TUN 0x380
  71. #define CGU_TUN_IDIV_ROM 0x390
  72. #define CGU_TUN_IDIV_PWM 0x3A0
  73. #define CGU_TUN_IDIV_TIMER 0x3B0
  74. #define CGU_HDMI_IDIV_APB 0x480
  75. #define CGU_SYS_IDIV_APB 0x180
  76. #define CGU_SYS_IDIV_AXI 0x190
  77. #define CGU_SYS_IDIV_ETH 0x1A0
  78. #define CGU_SYS_IDIV_USB 0x1B0
  79. #define CGU_SYS_IDIV_SDIO 0x1C0
  80. #define CGU_SYS_IDIV_HDMI 0x1D0
  81. #define CGU_SYS_IDIV_GFX_CORE 0x1E0
  82. #define CGU_SYS_IDIV_GFX_DMA 0x1F0
  83. #define CGU_SYS_IDIV_GFX_CFG 0x200
  84. #define CGU_SYS_IDIV_DMAC_CORE 0x210
  85. #define CGU_SYS_IDIV_DMAC_CFG 0x220
  86. #define CGU_SYS_IDIV_SDIO_REF 0x230
  87. #define CGU_SYS_IDIV_SPI_REF 0x240
  88. #define CGU_SYS_IDIV_I2C_REF 0x250
  89. #define CGU_SYS_IDIV_UART_REF 0x260
  90. #define CGU_SYS_IDIV_EBI_REF 0x270
  91. #define CGU_IDIV_MASK 0xFF /* All idiv have 8 significant bits */
  92. #define CGU_ARC_PLL 0x0
  93. #define CGU_SYS_PLL 0x10
  94. #define CGU_DDR_PLL 0x20
  95. #define CGU_TUN_PLL 0x30
  96. #define CGU_HDMI_PLL 0x40
  97. #define CGU_PLL_CTRL 0x000 /* ARC PLL control register */
  98. #define CGU_PLL_STATUS 0x004 /* ARC PLL status register */
  99. #define CGU_PLL_FMEAS 0x008 /* ARC PLL frequency measurement register */
  100. #define CGU_PLL_MON 0x00C /* ARC PLL monitor register */
  101. #define CGU_PLL_CTRL_ODIV_SHIFT 2
  102. #define CGU_PLL_CTRL_IDIV_SHIFT 4
  103. #define CGU_PLL_CTRL_FBDIV_SHIFT 9
  104. #define CGU_PLL_CTRL_BAND_SHIFT 20
  105. #define CGU_PLL_CTRL_ODIV_MASK GENMASK(3, CGU_PLL_CTRL_ODIV_SHIFT)
  106. #define CGU_PLL_CTRL_IDIV_MASK GENMASK(8, CGU_PLL_CTRL_IDIV_SHIFT)
  107. #define CGU_PLL_CTRL_FBDIV_MASK GENMASK(15, CGU_PLL_CTRL_FBDIV_SHIFT)
  108. #define CGU_PLL_CTRL_PD BIT(0)
  109. #define CGU_PLL_CTRL_BYPASS BIT(1)
  110. #define CGU_PLL_STATUS_LOCK BIT(0)
  111. #define CGU_PLL_STATUS_ERR BIT(1)
  112. #define HSDK_PLL_MAX_LOCK_TIME 100 /* 100 us */
  113. #define CREG_CORE_IF_DIV 0x000 /* ARC CORE interface divider */
  114. #define CORE_IF_CLK_THRESHOLD_HZ 500000000
  115. #define CREG_CORE_IF_CLK_DIV_1 0x0
  116. #define CREG_CORE_IF_CLK_DIV_2 0x1
  117. #define MIN_PLL_RATE 100000000 /* 100 MHz */
  118. #define PARENT_RATE_33 33333333 /* fixed clock - xtal */
  119. #define PARENT_RATE_27 27000000 /* fixed clock - xtal */
  120. #define CGU_MAX_CLOCKS 27
  121. #define MAX_FREQ_VARIATIONS 6
  122. struct hsdk_idiv_cfg {
  123. const u32 oft;
  124. const u8 val[MAX_FREQ_VARIATIONS];
  125. };
  126. struct hsdk_div_full_cfg {
  127. const u32 clk_rate[MAX_FREQ_VARIATIONS];
  128. const u32 pll_rate[MAX_FREQ_VARIATIONS];
  129. const struct hsdk_idiv_cfg idiv[];
  130. };
  131. static const struct hsdk_div_full_cfg hsdk_4xd_tun_clk_cfg = {
  132. { 25000000, 50000000, 75000000, 100000000, 125000000, 150000000 },
  133. { 600000000, 600000000, 600000000, 600000000, 750000000, 600000000 }, {
  134. { CGU_TUN_IDIV_TUN, { 24, 12, 8, 6, 6, 4 } },
  135. { CGU_TUN_IDIV_ROM, { 4, 4, 4, 4, 5, 4 } },
  136. { CGU_TUN_IDIV_PWM, { 8, 8, 8, 8, 10, 8 } },
  137. { CGU_TUN_IDIV_TIMER, { 12, 12, 12, 12, 15, 12 } },
  138. { /* last one */ }
  139. }
  140. };
  141. static const struct hsdk_div_full_cfg hsdk_tun_clk_cfg = {
  142. { 25000000, 50000000, 75000000, 100000000, 125000000, 150000000 },
  143. { 600000000, 600000000, 600000000, 600000000, 750000000, 600000000 }, {
  144. { CGU_TUN_IDIV_TUN, { 24, 12, 8, 6, 6, 4 } },
  145. { CGU_TUN_IDIV_ROM, { 4, 4, 4, 4, 5, 4 } },
  146. { CGU_TUN_IDIV_PWM, { 8, 8, 8, 8, 10, 8 } },
  147. { /* last one */ }
  148. }
  149. };
  150. static const struct hsdk_div_full_cfg axi_clk_cfg = {
  151. { 200000000, 400000000, 600000000, 800000000 },
  152. { 800000000, 800000000, 600000000, 800000000 }, {
  153. { CGU_SYS_IDIV_APB, { 4, 4, 3, 4 } }, /* APB */
  154. { CGU_SYS_IDIV_AXI, { 4, 2, 1, 1 } }, /* AXI */
  155. { CGU_SYS_IDIV_ETH, { 2, 2, 2, 2 } }, /* ETH */
  156. { CGU_SYS_IDIV_USB, { 2, 2, 2, 2 } }, /* USB */
  157. { CGU_SYS_IDIV_SDIO, { 2, 2, 2, 2 } }, /* SDIO */
  158. { CGU_SYS_IDIV_HDMI, { 2, 2, 2, 2 } }, /* HDMI */
  159. { CGU_SYS_IDIV_GFX_CORE, { 1, 1, 1, 1 } }, /* GPU-CORE */
  160. { CGU_SYS_IDIV_GFX_DMA, { 2, 2, 2, 2 } }, /* GPU-DMA */
  161. { CGU_SYS_IDIV_GFX_CFG, { 4, 4, 3, 4 } }, /* GPU-CFG */
  162. { CGU_SYS_IDIV_DMAC_CORE,{ 2, 2, 2, 2 } }, /* DMAC-CORE */
  163. { CGU_SYS_IDIV_DMAC_CFG, { 4, 4, 3, 4 } }, /* DMAC-CFG */
  164. { CGU_SYS_IDIV_SDIO_REF, { 8, 8, 6, 8 } }, /* SDIO-REF */
  165. { CGU_SYS_IDIV_SPI_REF, { 24, 24, 18, 24 } }, /* SPI-REF */
  166. { CGU_SYS_IDIV_I2C_REF, { 4, 4, 3, 4 } }, /* I2C-REF */
  167. { CGU_SYS_IDIV_UART_REF, { 24, 24, 18, 24 } }, /* UART-REF */
  168. { CGU_SYS_IDIV_EBI_REF, { 16, 16, 12, 16 } }, /* EBI-REF */
  169. { /* last one */ }
  170. }
  171. };
  172. struct hsdk_pll_cfg {
  173. const u32 rate;
  174. const u8 idiv;
  175. const u8 fbdiv;
  176. const u8 odiv;
  177. const u8 band;
  178. };
  179. static const struct hsdk_pll_cfg asdt_pll_cfg[] = {
  180. { 100000000, 0, 11, 3, 0 },
  181. { 125000000, 0, 14, 3, 0 },
  182. { 133000000, 0, 15, 3, 0 },
  183. { 150000000, 0, 17, 3, 0 },
  184. { 200000000, 1, 47, 3, 0 },
  185. { 233000000, 1, 27, 2, 0 },
  186. { 300000000, 1, 35, 2, 0 },
  187. { 333000000, 1, 39, 2, 0 },
  188. { 400000000, 1, 47, 2, 0 },
  189. { 500000000, 0, 14, 1, 0 },
  190. { 600000000, 0, 17, 1, 0 },
  191. { 700000000, 0, 20, 1, 0 },
  192. { 750000000, 1, 44, 1, 0 },
  193. { 800000000, 0, 23, 1, 0 },
  194. { 900000000, 1, 26, 0, 0 },
  195. { 1000000000, 1, 29, 0, 0 },
  196. { 1100000000, 1, 32, 0, 0 },
  197. { 1200000000, 1, 35, 0, 0 },
  198. { 1300000000, 1, 38, 0, 0 },
  199. { 1400000000, 1, 41, 0, 0 },
  200. { 1500000000, 1, 44, 0, 0 },
  201. { 1600000000, 1, 47, 0, 0 },
  202. {}
  203. };
  204. static const struct hsdk_pll_cfg hdmi_pll_cfg[] = {
  205. { 297000000, 0, 21, 2, 0 },
  206. { 540000000, 0, 19, 1, 0 },
  207. { 594000000, 0, 21, 1, 0 },
  208. {}
  209. };
  210. struct hsdk_cgu_domain {
  211. /* PLLs registers */
  212. void __iomem *pll_regs;
  213. /* PLLs special registers */
  214. void __iomem *spec_regs;
  215. /* PLLs devdata */
  216. const struct hsdk_pll_devdata *pll;
  217. /* Dividers registers */
  218. void __iomem *idiv_regs;
  219. };
  220. struct hsdk_cgu_clk {
  221. const struct cgu_clk_map *map;
  222. /* CGU block register */
  223. void __iomem *cgu_regs;
  224. /* CREG block register */
  225. void __iomem *creg_regs;
  226. /* The domain we are working with */
  227. struct hsdk_cgu_domain curr_domain;
  228. };
  229. struct hsdk_pll_devdata {
  230. const u32 parent_rate;
  231. const struct hsdk_pll_cfg *const pll_cfg;
  232. const int (*const update_rate)(struct hsdk_cgu_clk *clk,
  233. unsigned long rate,
  234. const struct hsdk_pll_cfg *cfg);
  235. };
  236. static int hsdk_pll_core_update_rate(struct hsdk_cgu_clk *, unsigned long,
  237. const struct hsdk_pll_cfg *);
  238. static int hsdk_pll_comm_update_rate(struct hsdk_cgu_clk *, unsigned long,
  239. const struct hsdk_pll_cfg *);
  240. static const struct hsdk_pll_devdata core_pll_dat = {
  241. .parent_rate = PARENT_RATE_33,
  242. .pll_cfg = asdt_pll_cfg,
  243. .update_rate = hsdk_pll_core_update_rate,
  244. };
  245. static const struct hsdk_pll_devdata sdt_pll_dat = {
  246. .parent_rate = PARENT_RATE_33,
  247. .pll_cfg = asdt_pll_cfg,
  248. .update_rate = hsdk_pll_comm_update_rate,
  249. };
  250. static const struct hsdk_pll_devdata hdmi_pll_dat = {
  251. .parent_rate = PARENT_RATE_27,
  252. .pll_cfg = hdmi_pll_cfg,
  253. .update_rate = hsdk_pll_comm_update_rate,
  254. };
  255. static ulong idiv_set(struct clk *, ulong);
  256. static ulong cpu_clk_set(struct clk *, ulong);
  257. static ulong axi_clk_set(struct clk *, ulong);
  258. static ulong tun_hsdk_set(struct clk *, ulong);
  259. static ulong tun_h4xd_set(struct clk *, ulong);
  260. static ulong idiv_get(struct clk *);
  261. static int idiv_off(struct clk *);
  262. static ulong pll_set(struct clk *, ulong);
  263. static ulong pll_get(struct clk *);
  264. struct cgu_clk_map {
  265. const u32 cgu_pll_oft;
  266. const u32 cgu_div_oft;
  267. const struct hsdk_pll_devdata *const pll_devdata;
  268. const ulong (*const get_rate)(struct clk *clk);
  269. const ulong (*const set_rate)(struct clk *clk, ulong rate);
  270. const int (*const disable)(struct clk *clk);
  271. };
  272. static const struct cgu_clk_map hsdk_clk_map[] = {
  273. [CLK_ARC_PLL] = { CGU_ARC_PLL, 0, &core_pll_dat, pll_get, pll_set, NULL },
  274. [CLK_ARC] = { CGU_ARC_PLL, CGU_ARC_IDIV, &core_pll_dat, idiv_get, cpu_clk_set, idiv_off },
  275. [CLK_DDR_PLL] = { CGU_DDR_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL },
  276. [CLK_SYS_PLL] = { CGU_SYS_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL },
  277. [CLK_SYS_APB] = { CGU_SYS_PLL, CGU_SYS_IDIV_APB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  278. [CLK_SYS_AXI] = { CGU_SYS_PLL, CGU_SYS_IDIV_AXI, &sdt_pll_dat, idiv_get, axi_clk_set, idiv_off },
  279. [CLK_SYS_ETH] = { CGU_SYS_PLL, CGU_SYS_IDIV_ETH, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  280. [CLK_SYS_USB] = { CGU_SYS_PLL, CGU_SYS_IDIV_USB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  281. [CLK_SYS_SDIO] = { CGU_SYS_PLL, CGU_SYS_IDIV_SDIO, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  282. [CLK_SYS_HDMI] = { CGU_SYS_PLL, CGU_SYS_IDIV_HDMI, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  283. [CLK_SYS_GFX_CORE] = { CGU_SYS_PLL, CGU_SYS_IDIV_GFX_CORE, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  284. [CLK_SYS_GFX_DMA] = { CGU_SYS_PLL, CGU_SYS_IDIV_GFX_DMA, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  285. [CLK_SYS_GFX_CFG] = { CGU_SYS_PLL, CGU_SYS_IDIV_GFX_CFG, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  286. [CLK_SYS_DMAC_CORE] = { CGU_SYS_PLL, CGU_SYS_IDIV_DMAC_CORE, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  287. [CLK_SYS_DMAC_CFG] = { CGU_SYS_PLL, CGU_SYS_IDIV_DMAC_CFG, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  288. [CLK_SYS_SDIO_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_SDIO_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  289. [CLK_SYS_SPI_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_SPI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  290. [CLK_SYS_I2C_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_I2C_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  291. [CLK_SYS_UART_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_UART_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  292. [CLK_SYS_EBI_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_EBI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  293. [CLK_TUN_PLL] = { CGU_TUN_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL },
  294. [CLK_TUN_TUN] = { CGU_TUN_PLL, CGU_TUN_IDIV_TUN, &sdt_pll_dat, idiv_get, tun_hsdk_set, idiv_off },
  295. [CLK_TUN_ROM] = { CGU_TUN_PLL, CGU_TUN_IDIV_ROM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  296. [CLK_TUN_PWM] = { CGU_TUN_PLL, CGU_TUN_IDIV_PWM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  297. [CLK_TUN_TIMER] = { /* missing in HSDK */ },
  298. [CLK_HDMI_PLL] = { CGU_HDMI_PLL, 0, &hdmi_pll_dat, pll_get, pll_set, NULL },
  299. [CLK_HDMI] = { CGU_HDMI_PLL, CGU_HDMI_IDIV_APB, &hdmi_pll_dat, idiv_get, idiv_set, idiv_off }
  300. };
  301. static const struct cgu_clk_map hsdk_4xd_clk_map[] = {
  302. [CLK_ARC_PLL] = { CGU_ARC_PLL, 0, &core_pll_dat, pll_get, pll_set, NULL },
  303. [CLK_ARC] = { CGU_ARC_PLL, CGU_ARC_IDIV, &core_pll_dat, idiv_get, cpu_clk_set, idiv_off },
  304. [CLK_DDR_PLL] = { CGU_DDR_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL },
  305. [CLK_SYS_PLL] = { CGU_SYS_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL },
  306. [CLK_SYS_APB] = { CGU_SYS_PLL, CGU_SYS_IDIV_APB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  307. [CLK_SYS_AXI] = { CGU_SYS_PLL, CGU_SYS_IDIV_AXI, &sdt_pll_dat, idiv_get, axi_clk_set, idiv_off },
  308. [CLK_SYS_ETH] = { CGU_SYS_PLL, CGU_SYS_IDIV_ETH, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  309. [CLK_SYS_USB] = { CGU_SYS_PLL, CGU_SYS_IDIV_USB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  310. [CLK_SYS_SDIO] = { CGU_SYS_PLL, CGU_SYS_IDIV_SDIO, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  311. [CLK_SYS_HDMI] = { CGU_SYS_PLL, CGU_SYS_IDIV_HDMI, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  312. [CLK_SYS_GFX_CORE] = { CGU_SYS_PLL, CGU_SYS_IDIV_GFX_CORE, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  313. [CLK_SYS_GFX_DMA] = { /* missing in HSDK-4xD */ },
  314. [CLK_SYS_GFX_CFG] = { /* missing in HSDK-4xD */ },
  315. [CLK_SYS_DMAC_CORE] = { CGU_SYS_PLL, CGU_SYS_IDIV_DMAC_CORE, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  316. [CLK_SYS_DMAC_CFG] = { CGU_SYS_PLL, CGU_SYS_IDIV_DMAC_CFG, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  317. [CLK_SYS_SDIO_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_SDIO_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  318. [CLK_SYS_SPI_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_SPI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  319. [CLK_SYS_I2C_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_I2C_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  320. [CLK_SYS_UART_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_UART_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  321. [CLK_SYS_EBI_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_EBI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  322. [CLK_TUN_PLL] = { CGU_TUN_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL },
  323. [CLK_TUN_TUN] = { CGU_TUN_PLL, CGU_TUN_IDIV_TUN, &sdt_pll_dat, idiv_get, tun_h4xd_set, idiv_off },
  324. [CLK_TUN_ROM] = { CGU_TUN_PLL, CGU_TUN_IDIV_ROM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  325. [CLK_TUN_PWM] = { CGU_TUN_PLL, CGU_TUN_IDIV_PWM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  326. [CLK_TUN_TIMER] = { CGU_TUN_PLL, CGU_TUN_IDIV_TIMER, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
  327. [CLK_HDMI_PLL] = { CGU_HDMI_PLL, 0, &hdmi_pll_dat, pll_get, pll_set, NULL },
  328. [CLK_HDMI] = { CGU_HDMI_PLL, CGU_HDMI_IDIV_APB, &hdmi_pll_dat, idiv_get, idiv_set, idiv_off }
  329. };
  330. static inline void hsdk_idiv_write(struct hsdk_cgu_clk *clk, u32 val)
  331. {
  332. iowrite32(val, clk->curr_domain.idiv_regs);
  333. }
  334. static inline u32 hsdk_idiv_read(struct hsdk_cgu_clk *clk)
  335. {
  336. return ioread32(clk->curr_domain.idiv_regs);
  337. }
  338. static inline void hsdk_pll_write(struct hsdk_cgu_clk *clk, u32 reg, u32 val)
  339. {
  340. iowrite32(val, clk->curr_domain.pll_regs + reg);
  341. }
  342. static inline u32 hsdk_pll_read(struct hsdk_cgu_clk *clk, u32 reg)
  343. {
  344. return ioread32(clk->curr_domain.pll_regs + reg);
  345. }
  346. static inline void hsdk_pll_spcwrite(struct hsdk_cgu_clk *clk, u32 reg, u32 val)
  347. {
  348. iowrite32(val, clk->curr_domain.spec_regs + reg);
  349. }
  350. static inline u32 hsdk_pll_spcread(struct hsdk_cgu_clk *clk, u32 reg)
  351. {
  352. return ioread32(clk->curr_domain.spec_regs + reg);
  353. }
  354. static inline void hsdk_pll_set_cfg(struct hsdk_cgu_clk *clk,
  355. const struct hsdk_pll_cfg *cfg)
  356. {
  357. u32 val = 0;
  358. /* Powerdown and Bypass bits should be cleared */
  359. val |= (u32)cfg->idiv << CGU_PLL_CTRL_IDIV_SHIFT;
  360. val |= (u32)cfg->fbdiv << CGU_PLL_CTRL_FBDIV_SHIFT;
  361. val |= (u32)cfg->odiv << CGU_PLL_CTRL_ODIV_SHIFT;
  362. val |= (u32)cfg->band << CGU_PLL_CTRL_BAND_SHIFT;
  363. pr_debug("write configurarion: %#x\n", val);
  364. hsdk_pll_write(clk, CGU_PLL_CTRL, val);
  365. }
  366. static inline bool hsdk_pll_is_locked(struct hsdk_cgu_clk *clk)
  367. {
  368. return !!(hsdk_pll_read(clk, CGU_PLL_STATUS) & CGU_PLL_STATUS_LOCK);
  369. }
  370. static inline bool hsdk_pll_is_err(struct hsdk_cgu_clk *clk)
  371. {
  372. return !!(hsdk_pll_read(clk, CGU_PLL_STATUS) & CGU_PLL_STATUS_ERR);
  373. }
  374. static ulong pll_get(struct clk *sclk)
  375. {
  376. u32 val;
  377. u64 rate;
  378. u32 idiv, fbdiv, odiv;
  379. struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
  380. u32 parent_rate = clk->curr_domain.pll->parent_rate;
  381. val = hsdk_pll_read(clk, CGU_PLL_CTRL);
  382. pr_debug("current configurarion: %#x\n", val);
  383. /* Check if PLL is bypassed */
  384. if (val & CGU_PLL_CTRL_BYPASS)
  385. return parent_rate;
  386. /* Check if PLL is disabled */
  387. if (val & CGU_PLL_CTRL_PD)
  388. return 0;
  389. /* input divider = reg.idiv + 1 */
  390. idiv = 1 + ((val & CGU_PLL_CTRL_IDIV_MASK) >> CGU_PLL_CTRL_IDIV_SHIFT);
  391. /* fb divider = 2*(reg.fbdiv + 1) */
  392. fbdiv = 2 * (1 + ((val & CGU_PLL_CTRL_FBDIV_MASK) >> CGU_PLL_CTRL_FBDIV_SHIFT));
  393. /* output divider = 2^(reg.odiv) */
  394. odiv = 1 << ((val & CGU_PLL_CTRL_ODIV_MASK) >> CGU_PLL_CTRL_ODIV_SHIFT);
  395. rate = (u64)parent_rate * fbdiv;
  396. do_div(rate, idiv * odiv);
  397. return rate;
  398. }
  399. static unsigned long hsdk_pll_round_rate(struct clk *sclk, unsigned long rate)
  400. {
  401. int i;
  402. unsigned long best_rate;
  403. struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
  404. const struct hsdk_pll_cfg *pll_cfg = clk->curr_domain.pll->pll_cfg;
  405. if (pll_cfg[0].rate == 0)
  406. return -EINVAL;
  407. best_rate = pll_cfg[0].rate;
  408. for (i = 1; pll_cfg[i].rate != 0; i++) {
  409. if (abs(rate - pll_cfg[i].rate) < abs(rate - best_rate))
  410. best_rate = pll_cfg[i].rate;
  411. }
  412. pr_debug("chosen best rate: %lu\n", best_rate);
  413. return best_rate;
  414. }
  415. static int hsdk_pll_comm_update_rate(struct hsdk_cgu_clk *clk,
  416. unsigned long rate,
  417. const struct hsdk_pll_cfg *cfg)
  418. {
  419. hsdk_pll_set_cfg(clk, cfg);
  420. /*
  421. * Wait until CGU relocks and check error status.
  422. * If after timeout CGU is unlocked yet return error.
  423. */
  424. udelay(HSDK_PLL_MAX_LOCK_TIME);
  425. if (!hsdk_pll_is_locked(clk))
  426. return -ETIMEDOUT;
  427. if (hsdk_pll_is_err(clk))
  428. return -EINVAL;
  429. return 0;
  430. }
  431. static int hsdk_pll_core_update_rate(struct hsdk_cgu_clk *clk,
  432. unsigned long rate,
  433. const struct hsdk_pll_cfg *cfg)
  434. {
  435. /*
  436. * When core clock exceeds 500MHz, the divider for the interface
  437. * clock must be programmed to div-by-2.
  438. */
  439. if (rate > CORE_IF_CLK_THRESHOLD_HZ)
  440. hsdk_pll_spcwrite(clk, CREG_CORE_IF_DIV, CREG_CORE_IF_CLK_DIV_2);
  441. hsdk_pll_set_cfg(clk, cfg);
  442. /*
  443. * Wait until CGU relocks and check error status.
  444. * If after timeout CGU is unlocked yet return error.
  445. */
  446. udelay(HSDK_PLL_MAX_LOCK_TIME);
  447. if (!hsdk_pll_is_locked(clk))
  448. return -ETIMEDOUT;
  449. if (hsdk_pll_is_err(clk))
  450. return -EINVAL;
  451. /*
  452. * Program divider to div-by-1 if we succesfuly set core clock below
  453. * 500MHz threshold.
  454. */
  455. if (rate <= CORE_IF_CLK_THRESHOLD_HZ)
  456. hsdk_pll_spcwrite(clk, CREG_CORE_IF_DIV, CREG_CORE_IF_CLK_DIV_1);
  457. return 0;
  458. }
  459. static ulong pll_set(struct clk *sclk, ulong rate)
  460. {
  461. int i;
  462. unsigned long best_rate;
  463. struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
  464. const struct hsdk_pll_devdata *pll = clk->curr_domain.pll;
  465. const struct hsdk_pll_cfg *pll_cfg = pll->pll_cfg;
  466. best_rate = hsdk_pll_round_rate(sclk, rate);
  467. for (i = 0; pll_cfg[i].rate != 0; i++)
  468. if (pll_cfg[i].rate == best_rate)
  469. return pll->update_rate(clk, best_rate, &pll_cfg[i]);
  470. pr_err("invalid rate=%ld Hz, parent_rate=%d Hz\n", best_rate,
  471. pll->parent_rate);
  472. return -EINVAL;
  473. }
  474. static int idiv_off(struct clk *sclk)
  475. {
  476. struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
  477. hsdk_idiv_write(clk, 0);
  478. return 0;
  479. }
  480. static ulong idiv_get(struct clk *sclk)
  481. {
  482. struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
  483. ulong parent_rate = pll_get(sclk);
  484. u32 div_factor = hsdk_idiv_read(clk);
  485. div_factor &= CGU_IDIV_MASK;
  486. pr_debug("current configurarion: %#x (%d)\n", div_factor, div_factor);
  487. if (div_factor == 0)
  488. return 0;
  489. return parent_rate / div_factor;
  490. }
  491. /* Special behavior: wen we set this clock we set both idiv and pll */
  492. static ulong cpu_clk_set(struct clk *sclk, ulong rate)
  493. {
  494. ulong ret;
  495. ret = pll_set(sclk, rate);
  496. idiv_set(sclk, rate);
  497. return ret;
  498. }
  499. /*
  500. * Special behavior:
  501. * when we set these clocks we set both PLL and all idiv dividers related to
  502. * this PLL domain.
  503. */
  504. static ulong common_div_clk_set(struct clk *sclk, ulong rate,
  505. const struct hsdk_div_full_cfg *cfg)
  506. {
  507. struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
  508. ulong pll_rate;
  509. int i, freq_idx = -1;
  510. ulong ret = 0;
  511. pll_rate = pll_get(sclk);
  512. for (i = 0; i < MAX_FREQ_VARIATIONS; i++) {
  513. /* unused freq variations are filled with 0 */
  514. if (!cfg->clk_rate[i])
  515. break;
  516. if (cfg->clk_rate[i] == rate) {
  517. freq_idx = i;
  518. break;
  519. }
  520. }
  521. if (freq_idx < 0) {
  522. pr_err("clk: invalid rate=%ld Hz\n", rate);
  523. return -EINVAL;
  524. }
  525. /* configure PLL before dividers */
  526. if (cfg->pll_rate[freq_idx] < pll_rate)
  527. ret = pll_set(sclk, cfg->pll_rate[freq_idx]);
  528. /* configure SYS dividers */
  529. for (i = 0; cfg->idiv[i].oft != 0; i++) {
  530. clk->curr_domain.idiv_regs = clk->cgu_regs + cfg->idiv[i].oft;
  531. hsdk_idiv_write(clk, cfg->idiv[i].val[freq_idx]);
  532. }
  533. /* configure PLL after dividers */
  534. if (cfg->pll_rate[freq_idx] >= pll_rate)
  535. ret = pll_set(sclk, cfg->pll_rate[freq_idx]);
  536. return ret;
  537. }
  538. static ulong axi_clk_set(struct clk *sclk, ulong rate)
  539. {
  540. return common_div_clk_set(sclk, rate, &axi_clk_cfg);
  541. }
  542. static ulong tun_hsdk_set(struct clk *sclk, ulong rate)
  543. {
  544. return common_div_clk_set(sclk, rate, &hsdk_tun_clk_cfg);
  545. }
  546. static ulong tun_h4xd_set(struct clk *sclk, ulong rate)
  547. {
  548. return common_div_clk_set(sclk, rate, &hsdk_4xd_tun_clk_cfg);
  549. }
  550. static ulong idiv_set(struct clk *sclk, ulong rate)
  551. {
  552. struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
  553. ulong parent_rate = pll_get(sclk);
  554. u32 div_factor;
  555. div_factor = parent_rate / rate;
  556. if (abs(rate - parent_rate / (div_factor + 1)) <=
  557. abs(rate - parent_rate / div_factor)) {
  558. div_factor += 1;
  559. }
  560. if (div_factor & ~CGU_IDIV_MASK) {
  561. pr_err("invalid rate=%ld Hz, parent_rate=%ld Hz, div=%d: max divider valie is%d\n",
  562. rate, parent_rate, div_factor, CGU_IDIV_MASK);
  563. div_factor = CGU_IDIV_MASK;
  564. }
  565. if (div_factor == 0) {
  566. pr_err("invalid rate=%ld Hz, parent_rate=%ld Hz, div=%d: min divider valie is 1\n",
  567. rate, parent_rate, div_factor);
  568. div_factor = 1;
  569. }
  570. hsdk_idiv_write(clk, div_factor);
  571. return 0;
  572. }
  573. static int hsdk_prepare_clock_tree_branch(struct clk *sclk)
  574. {
  575. struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
  576. if (sclk->id >= CGU_MAX_CLOCKS)
  577. return -EINVAL;
  578. /* clocks missing in current map have their entry zeroed */
  579. if (!clk->map[sclk->id].pll_devdata)
  580. return -EINVAL;
  581. clk->curr_domain.pll = clk->map[sclk->id].pll_devdata;
  582. clk->curr_domain.pll_regs = clk->cgu_regs + clk->map[sclk->id].cgu_pll_oft;
  583. clk->curr_domain.spec_regs = clk->creg_regs;
  584. clk->curr_domain.idiv_regs = clk->cgu_regs + clk->map[sclk->id].cgu_div_oft;
  585. return 0;
  586. }
  587. static ulong hsdk_cgu_get_rate(struct clk *sclk)
  588. {
  589. struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
  590. if (hsdk_prepare_clock_tree_branch(sclk))
  591. return -EINVAL;
  592. return clk->map[sclk->id].get_rate(sclk);
  593. }
  594. static ulong hsdk_cgu_set_rate(struct clk *sclk, ulong rate)
  595. {
  596. struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
  597. if (hsdk_prepare_clock_tree_branch(sclk))
  598. return -EINVAL;
  599. if (clk->map[sclk->id].set_rate)
  600. return clk->map[sclk->id].set_rate(sclk, rate);
  601. return -EINVAL;
  602. }
  603. static int hsdk_cgu_disable(struct clk *sclk)
  604. {
  605. struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
  606. if (hsdk_prepare_clock_tree_branch(sclk))
  607. return -EINVAL;
  608. if (clk->map[sclk->id].disable)
  609. return clk->map[sclk->id].disable(sclk);
  610. return -EINVAL;
  611. }
  612. static const struct clk_ops hsdk_cgu_ops = {
  613. .set_rate = hsdk_cgu_set_rate,
  614. .get_rate = hsdk_cgu_get_rate,
  615. .disable = hsdk_cgu_disable,
  616. };
  617. static int hsdk_cgu_clk_probe(struct udevice *dev)
  618. {
  619. struct hsdk_cgu_clk *hsdk_clk = dev_get_priv(dev);
  620. BUILD_BUG_ON(ARRAY_SIZE(hsdk_clk_map) != CGU_MAX_CLOCKS);
  621. BUILD_BUG_ON(ARRAY_SIZE(hsdk_4xd_clk_map) != CGU_MAX_CLOCKS);
  622. /* Choose which clock map to use in runtime */
  623. if ((read_aux_reg(ARC_AUX_IDENTITY) & 0xFF) == 0x52)
  624. hsdk_clk->map = hsdk_clk_map;
  625. else
  626. hsdk_clk->map = hsdk_4xd_clk_map;
  627. hsdk_clk->cgu_regs = (void __iomem *)devfdt_get_addr_index(dev, 0);
  628. if (!hsdk_clk->cgu_regs)
  629. return -EINVAL;
  630. hsdk_clk->creg_regs = (void __iomem *)devfdt_get_addr_index(dev, 1);
  631. if (!hsdk_clk->creg_regs)
  632. return -EINVAL;
  633. return 0;
  634. }
  635. static const struct udevice_id hsdk_cgu_clk_id[] = {
  636. { .compatible = "snps,hsdk-cgu-clock" },
  637. { }
  638. };
  639. U_BOOT_DRIVER(hsdk_cgu_clk) = {
  640. .name = "hsdk-cgu-clk",
  641. .id = UCLASS_CLK,
  642. .of_match = hsdk_cgu_clk_id,
  643. .probe = hsdk_cgu_clk_probe,
  644. .priv_auto = sizeof(struct hsdk_cgu_clk),
  645. .ops = &hsdk_cgu_ops,
  646. };