clk-hsdk-cgu.c 25 KB

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