clk.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
  4. */
  5. #include <kendryte/clk.h>
  6. #include <asm/io.h>
  7. #include <dt-bindings/clock/k210-sysctl.h>
  8. #include <dt-bindings/mfd/k210-sysctl.h>
  9. #include <dm.h>
  10. #include <log.h>
  11. #include <mapmem.h>
  12. #include <kendryte/bypass.h>
  13. #include <kendryte/pll.h>
  14. /* All methods are delegated to CCF clocks */
  15. static ulong k210_clk_get_rate(struct clk *clk)
  16. {
  17. struct clk *c;
  18. int err = clk_get_by_id(clk->id, &c);
  19. if (err)
  20. return err;
  21. return clk_get_rate(c);
  22. }
  23. static ulong k210_clk_set_rate(struct clk *clk, unsigned long rate)
  24. {
  25. struct clk *c;
  26. int err = clk_get_by_id(clk->id, &c);
  27. if (err)
  28. return err;
  29. return clk_set_rate(c, rate);
  30. }
  31. static int k210_clk_set_parent(struct clk *clk, struct clk *parent)
  32. {
  33. struct clk *c, *p;
  34. int err = clk_get_by_id(clk->id, &c);
  35. if (err)
  36. return err;
  37. err = clk_get_by_id(parent->id, &p);
  38. if (err)
  39. return err;
  40. return clk_set_parent(c, p);
  41. }
  42. static int k210_clk_endisable(struct clk *clk, bool enable)
  43. {
  44. struct clk *c;
  45. int err = clk_get_by_id(clk->id, &c);
  46. if (err)
  47. return err;
  48. return enable ? clk_enable(c) : clk_disable(c);
  49. }
  50. static int k210_clk_enable(struct clk *clk)
  51. {
  52. return k210_clk_endisable(clk, true);
  53. }
  54. static int k210_clk_disable(struct clk *clk)
  55. {
  56. return k210_clk_endisable(clk, false);
  57. }
  58. static const struct clk_ops k210_clk_ops = {
  59. .set_rate = k210_clk_set_rate,
  60. .get_rate = k210_clk_get_rate,
  61. .set_parent = k210_clk_set_parent,
  62. .enable = k210_clk_enable,
  63. .disable = k210_clk_disable,
  64. };
  65. /* Parents for muxed clocks */
  66. static const char * const generic_sels[] = { "in0_half", "pll0_half" };
  67. /* The first clock is in0, which is filled in by k210_clk_probe */
  68. static const char *aclk_sels[] = { NULL, "pll0_half" };
  69. static const char *pll2_sels[] = { NULL, "pll0", "pll1" };
  70. /*
  71. * All parameters for different sub-clocks are collected into parameter arrays.
  72. * These parameters are then initialized by the clock which uses them during
  73. * probe. To save space, ids are automatically generated for each sub-clock by
  74. * using an enum. Instead of storing a parameter struct for each clock, even for
  75. * those clocks which don't use a particular type of sub-clock, we can just
  76. * store the parameters for the clocks which need them.
  77. *
  78. * So why do it like this? Arranging all the sub-clocks together makes it very
  79. * easy to find bugs in the code.
  80. */
  81. #define DIV(id, off, shift, width) DIV_FLAGS(id, off, shift, width, 0)
  82. #define DIV_LIST \
  83. DIV_FLAGS(K210_CLK_ACLK, K210_SYSCTL_SEL0, 1, 2, \
  84. CLK_DIVIDER_POWER_OF_TWO) \
  85. DIV(K210_CLK_APB0, K210_SYSCTL_SEL0, 3, 3) \
  86. DIV(K210_CLK_APB1, K210_SYSCTL_SEL0, 6, 3) \
  87. DIV(K210_CLK_APB2, K210_SYSCTL_SEL0, 9, 3) \
  88. DIV(K210_CLK_SRAM0, K210_SYSCTL_THR0, 0, 4) \
  89. DIV(K210_CLK_SRAM1, K210_SYSCTL_THR0, 4, 4) \
  90. DIV(K210_CLK_AI, K210_SYSCTL_THR0, 8, 4) \
  91. DIV(K210_CLK_DVP, K210_SYSCTL_THR0, 12, 4) \
  92. DIV(K210_CLK_ROM, K210_SYSCTL_THR0, 16, 4) \
  93. DIV(K210_CLK_SPI0, K210_SYSCTL_THR1, 0, 8) \
  94. DIV(K210_CLK_SPI1, K210_SYSCTL_THR1, 8, 8) \
  95. DIV(K210_CLK_SPI2, K210_SYSCTL_THR1, 16, 8) \
  96. DIV(K210_CLK_SPI3, K210_SYSCTL_THR1, 24, 8) \
  97. DIV(K210_CLK_TIMER0, K210_SYSCTL_THR2, 0, 8) \
  98. DIV(K210_CLK_TIMER1, K210_SYSCTL_THR2, 8, 8) \
  99. DIV(K210_CLK_TIMER2, K210_SYSCTL_THR2, 16, 8) \
  100. DIV(K210_CLK_I2S0, K210_SYSCTL_THR3, 0, 16) \
  101. DIV(K210_CLK_I2S1, K210_SYSCTL_THR3, 16, 16) \
  102. DIV(K210_CLK_I2S2, K210_SYSCTL_THR4, 0, 16) \
  103. DIV(K210_CLK_I2S0_M, K210_SYSCTL_THR4, 16, 8) \
  104. DIV(K210_CLK_I2S1_M, K210_SYSCTL_THR4, 24, 8) \
  105. DIV(K210_CLK_I2S2_M, K210_SYSCTL_THR4, 0, 8) \
  106. DIV(K210_CLK_I2C0, K210_SYSCTL_THR5, 8, 8) \
  107. DIV(K210_CLK_I2C1, K210_SYSCTL_THR5, 16, 8) \
  108. DIV(K210_CLK_I2C2, K210_SYSCTL_THR5, 24, 8) \
  109. DIV(K210_CLK_WDT0, K210_SYSCTL_THR6, 0, 8) \
  110. DIV(K210_CLK_WDT1, K210_SYSCTL_THR6, 8, 8)
  111. #define _DIVIFY(id) K210_CLK_DIV_##id
  112. #define DIVIFY(id) _DIVIFY(id)
  113. enum k210_div_ids {
  114. #define DIV_FLAGS(id, ...) DIVIFY(id),
  115. DIV_LIST
  116. #undef DIV_FLAGS
  117. };
  118. struct k210_div_params {
  119. u8 off;
  120. u8 shift;
  121. u8 width;
  122. u8 flags;
  123. };
  124. static const struct k210_div_params k210_divs[] = {
  125. #define DIV_FLAGS(id, _off, _shift, _width, _flags) \
  126. [DIVIFY(id)] = { \
  127. .off = (_off), \
  128. .shift = (_shift), \
  129. .width = (_width), \
  130. .flags = (_flags), \
  131. },
  132. DIV_LIST
  133. #undef DIV_FLAGS
  134. };
  135. #undef DIV
  136. #undef DIV_LIST
  137. #define GATE_LIST \
  138. GATE(K210_CLK_CPU, K210_SYSCTL_EN_CENT, 0) \
  139. GATE(K210_CLK_SRAM0, K210_SYSCTL_EN_CENT, 1) \
  140. GATE(K210_CLK_SRAM1, K210_SYSCTL_EN_CENT, 2) \
  141. GATE(K210_CLK_APB0, K210_SYSCTL_EN_CENT, 3) \
  142. GATE(K210_CLK_APB1, K210_SYSCTL_EN_CENT, 4) \
  143. GATE(K210_CLK_APB2, K210_SYSCTL_EN_CENT, 5) \
  144. GATE(K210_CLK_ROM, K210_SYSCTL_EN_PERI, 0) \
  145. GATE(K210_CLK_DMA, K210_SYSCTL_EN_PERI, 1) \
  146. GATE(K210_CLK_AI, K210_SYSCTL_EN_PERI, 2) \
  147. GATE(K210_CLK_DVP, K210_SYSCTL_EN_PERI, 3) \
  148. GATE(K210_CLK_FFT, K210_SYSCTL_EN_PERI, 4) \
  149. GATE(K210_CLK_GPIO, K210_SYSCTL_EN_PERI, 5) \
  150. GATE(K210_CLK_SPI0, K210_SYSCTL_EN_PERI, 6) \
  151. GATE(K210_CLK_SPI1, K210_SYSCTL_EN_PERI, 7) \
  152. GATE(K210_CLK_SPI2, K210_SYSCTL_EN_PERI, 8) \
  153. GATE(K210_CLK_SPI3, K210_SYSCTL_EN_PERI, 9) \
  154. GATE(K210_CLK_I2S0, K210_SYSCTL_EN_PERI, 10) \
  155. GATE(K210_CLK_I2S1, K210_SYSCTL_EN_PERI, 11) \
  156. GATE(K210_CLK_I2S2, K210_SYSCTL_EN_PERI, 12) \
  157. GATE(K210_CLK_I2C0, K210_SYSCTL_EN_PERI, 13) \
  158. GATE(K210_CLK_I2C1, K210_SYSCTL_EN_PERI, 14) \
  159. GATE(K210_CLK_I2C2, K210_SYSCTL_EN_PERI, 15) \
  160. GATE(K210_CLK_UART1, K210_SYSCTL_EN_PERI, 16) \
  161. GATE(K210_CLK_UART2, K210_SYSCTL_EN_PERI, 17) \
  162. GATE(K210_CLK_UART3, K210_SYSCTL_EN_PERI, 18) \
  163. GATE(K210_CLK_AES, K210_SYSCTL_EN_PERI, 19) \
  164. GATE(K210_CLK_FPIOA, K210_SYSCTL_EN_PERI, 20) \
  165. GATE(K210_CLK_TIMER0, K210_SYSCTL_EN_PERI, 21) \
  166. GATE(K210_CLK_TIMER1, K210_SYSCTL_EN_PERI, 22) \
  167. GATE(K210_CLK_TIMER2, K210_SYSCTL_EN_PERI, 23) \
  168. GATE(K210_CLK_WDT0, K210_SYSCTL_EN_PERI, 24) \
  169. GATE(K210_CLK_WDT1, K210_SYSCTL_EN_PERI, 25) \
  170. GATE(K210_CLK_SHA, K210_SYSCTL_EN_PERI, 26) \
  171. GATE(K210_CLK_OTP, K210_SYSCTL_EN_PERI, 27) \
  172. GATE(K210_CLK_RTC, K210_SYSCTL_EN_PERI, 29)
  173. #define _GATEIFY(id) K210_CLK_GATE_##id
  174. #define GATEIFY(id) _GATEIFY(id)
  175. enum k210_gate_ids {
  176. #define GATE(id, ...) GATEIFY(id),
  177. GATE_LIST
  178. #undef GATE
  179. };
  180. struct k210_gate_params {
  181. u8 off;
  182. u8 bit_idx;
  183. };
  184. static const struct k210_gate_params k210_gates[] = {
  185. #define GATE(id, _off, _idx) \
  186. [GATEIFY(id)] = { \
  187. .off = (_off), \
  188. .bit_idx = (_idx), \
  189. },
  190. GATE_LIST
  191. #undef GATE
  192. };
  193. #undef GATE_LIST
  194. #define MUX(id, reg, shift, width) \
  195. MUX_PARENTS(id, generic_sels, reg, shift, width)
  196. #define MUX_LIST \
  197. MUX_PARENTS(K210_CLK_PLL2, pll2_sels, K210_SYSCTL_PLL2, 26, 2) \
  198. MUX_PARENTS(K210_CLK_ACLK, aclk_sels, K210_SYSCTL_SEL0, 0, 1) \
  199. MUX(K210_CLK_SPI3, K210_SYSCTL_SEL0, 12, 1) \
  200. MUX(K210_CLK_TIMER0, K210_SYSCTL_SEL0, 13, 1) \
  201. MUX(K210_CLK_TIMER1, K210_SYSCTL_SEL0, 14, 1) \
  202. MUX(K210_CLK_TIMER2, K210_SYSCTL_SEL0, 15, 1)
  203. #define _MUXIFY(id) K210_CLK_MUX_##id
  204. #define MUXIFY(id) _MUXIFY(id)
  205. enum k210_mux_ids {
  206. #define MUX_PARENTS(id, ...) MUXIFY(id),
  207. MUX_LIST
  208. #undef MUX_PARENTS
  209. K210_CLK_MUX_NONE,
  210. };
  211. struct k210_mux_params {
  212. const char *const *parent_names;
  213. u8 num_parents;
  214. u8 off;
  215. u8 shift;
  216. u8 width;
  217. };
  218. static const struct k210_mux_params k210_muxes[] = {
  219. #define MUX_PARENTS(id, parents, _off, _shift, _width) \
  220. [MUXIFY(id)] = { \
  221. .parent_names = (const char * const *)(parents), \
  222. .num_parents = ARRAY_SIZE(parents), \
  223. .off = (_off), \
  224. .shift = (_shift), \
  225. .width = (_width), \
  226. },
  227. MUX_LIST
  228. #undef MUX_PARENTS
  229. };
  230. #undef MUX
  231. #undef MUX_LIST
  232. struct k210_pll_params {
  233. u8 off;
  234. u8 lock_off;
  235. u8 shift;
  236. u8 width;
  237. };
  238. static const struct k210_pll_params k210_plls[] = {
  239. #define PLL(_off, _shift, _width) { \
  240. .off = (_off), \
  241. .lock_off = K210_SYSCTL_PLL_LOCK, \
  242. .shift = (_shift), \
  243. .width = (_width), \
  244. }
  245. [0] = PLL(K210_SYSCTL_PLL0, 0, 2),
  246. [1] = PLL(K210_SYSCTL_PLL1, 8, 1),
  247. [2] = PLL(K210_SYSCTL_PLL2, 16, 1),
  248. #undef PLL
  249. };
  250. #define COMP(id) \
  251. COMP_FULL(id, MUXIFY(id), DIVIFY(id), GATEIFY(id))
  252. #define COMP_NOMUX(id) \
  253. COMP_FULL(id, K210_CLK_MUX_NONE, DIVIFY(id), GATEIFY(id))
  254. #define COMP_LIST \
  255. COMP(K210_CLK_SPI3) \
  256. COMP(K210_CLK_TIMER0) \
  257. COMP(K210_CLK_TIMER1) \
  258. COMP(K210_CLK_TIMER2) \
  259. COMP_NOMUX(K210_CLK_SRAM0) \
  260. COMP_NOMUX(K210_CLK_SRAM1) \
  261. COMP_NOMUX(K210_CLK_ROM) \
  262. COMP_NOMUX(K210_CLK_DVP) \
  263. COMP_NOMUX(K210_CLK_APB0) \
  264. COMP_NOMUX(K210_CLK_APB1) \
  265. COMP_NOMUX(K210_CLK_APB2) \
  266. COMP_NOMUX(K210_CLK_AI) \
  267. COMP_NOMUX(K210_CLK_I2S0) \
  268. COMP_NOMUX(K210_CLK_I2S1) \
  269. COMP_NOMUX(K210_CLK_I2S2) \
  270. COMP_NOMUX(K210_CLK_WDT0) \
  271. COMP_NOMUX(K210_CLK_WDT1) \
  272. COMP_NOMUX(K210_CLK_SPI0) \
  273. COMP_NOMUX(K210_CLK_SPI1) \
  274. COMP_NOMUX(K210_CLK_SPI2) \
  275. COMP_NOMUX(K210_CLK_I2C0) \
  276. COMP_NOMUX(K210_CLK_I2C1) \
  277. COMP_NOMUX(K210_CLK_I2C2)
  278. #define _COMPIFY(id) K210_CLK_COMP_##id
  279. #define COMPIFY(id) _COMPIFY(id)
  280. enum k210_comp_ids {
  281. #define COMP_FULL(id, ...) COMPIFY(id),
  282. COMP_LIST
  283. #undef COMP_FULL
  284. };
  285. struct k210_comp_params {
  286. u8 mux;
  287. u8 div;
  288. u8 gate;
  289. };
  290. static const struct k210_comp_params k210_comps[] = {
  291. #define COMP_FULL(id, _mux, _div, _gate) \
  292. [COMPIFY(id)] = { \
  293. .mux = (_mux), \
  294. .div = (_div), \
  295. .gate = (_gate), \
  296. },
  297. COMP_LIST
  298. #undef COMP_FULL
  299. };
  300. #undef COMP
  301. #undef COMP_ID
  302. #undef COMP_NOMUX
  303. #undef COMP_NOMUX_ID
  304. #undef COMP_LIST
  305. static struct clk *k210_bypass_children = {
  306. NULL,
  307. };
  308. /* Helper functions to create sub-clocks */
  309. static struct clk_mux *k210_create_mux(const struct k210_mux_params *params,
  310. void *base)
  311. {
  312. struct clk_mux *mux = kzalloc(sizeof(*mux), GFP_KERNEL);
  313. if (!mux)
  314. return mux;
  315. mux->reg = base + params->off;
  316. mux->mask = BIT(params->width) - 1;
  317. mux->shift = params->shift;
  318. mux->parent_names = params->parent_names;
  319. mux->num_parents = params->num_parents;
  320. return mux;
  321. }
  322. static struct clk_divider *k210_create_div(const struct k210_div_params *params,
  323. void *base)
  324. {
  325. struct clk_divider *div = kzalloc(sizeof(*div), GFP_KERNEL);
  326. if (!div)
  327. return div;
  328. div->reg = base + params->off;
  329. div->shift = params->shift;
  330. div->width = params->width;
  331. div->flags = params->flags;
  332. return div;
  333. }
  334. static struct clk_gate *k210_create_gate(const struct k210_gate_params *params,
  335. void *base)
  336. {
  337. struct clk_gate *gate = kzalloc(sizeof(*gate), GFP_KERNEL);
  338. if (!gate)
  339. return gate;
  340. gate->reg = base + params->off;
  341. gate->bit_idx = params->bit_idx;
  342. return gate;
  343. }
  344. static struct k210_pll *k210_create_pll(const struct k210_pll_params *params,
  345. void *base)
  346. {
  347. struct k210_pll *pll = kzalloc(sizeof(*pll), GFP_KERNEL);
  348. if (!pll)
  349. return pll;
  350. pll->reg = base + params->off;
  351. pll->lock = base + params->lock_off;
  352. pll->shift = params->shift;
  353. pll->width = params->width;
  354. return pll;
  355. }
  356. /* Create all sub-clocks, and then register the composite clock */
  357. static struct clk *k210_register_comp(const struct k210_comp_params *params,
  358. void *base, const char *name,
  359. const char *parent)
  360. {
  361. const char *const *parent_names;
  362. int num_parents;
  363. struct clk *comp;
  364. const struct clk_ops *mux_ops;
  365. struct clk_mux *mux;
  366. struct clk_divider *div;
  367. struct clk_gate *gate;
  368. if (params->mux == K210_CLK_MUX_NONE) {
  369. if (!parent)
  370. return ERR_PTR(-EINVAL);
  371. mux_ops = NULL;
  372. mux = NULL;
  373. parent_names = &parent;
  374. num_parents = 1;
  375. } else {
  376. mux_ops = &clk_mux_ops;
  377. mux = k210_create_mux(&k210_muxes[params->mux], base);
  378. if (!mux)
  379. return ERR_PTR(-ENOMEM);
  380. parent_names = mux->parent_names;
  381. num_parents = mux->num_parents;
  382. }
  383. div = k210_create_div(&k210_divs[params->div], base);
  384. if (!div) {
  385. comp = ERR_PTR(-ENOMEM);
  386. goto cleanup_mux;
  387. }
  388. gate = k210_create_gate(&k210_gates[params->gate], base);
  389. if (!gate) {
  390. comp = ERR_PTR(-ENOMEM);
  391. goto cleanup_div;
  392. }
  393. comp = clk_register_composite(NULL, name, parent_names, num_parents,
  394. &mux->clk, mux_ops,
  395. &div->clk, &clk_divider_ops,
  396. &gate->clk, &clk_gate_ops, 0);
  397. if (IS_ERR(comp))
  398. goto cleanup_gate;
  399. return comp;
  400. cleanup_gate:
  401. free(gate);
  402. cleanup_div:
  403. free(div);
  404. cleanup_mux:
  405. if (mux)
  406. free(mux);
  407. return comp;
  408. }
  409. static bool probed;
  410. static int k210_clk_probe(struct udevice *dev)
  411. {
  412. int ret;
  413. const char *in0;
  414. struct clk *in0_clk, *bypass;
  415. struct clk_mux *mux;
  416. struct clk_divider *div;
  417. struct k210_pll *pll;
  418. void *base;
  419. /*
  420. * Only one instance of this driver allowed. This prevents weird bugs
  421. * when the driver fails part-way through probing. Some clocks will
  422. * already have been registered, and re-probing will register them
  423. * again, creating a bunch of duplicates. Better error-handling/cleanup
  424. * could fix this, but it's Probably Not Worth It (TM).
  425. */
  426. if (probed)
  427. return -ENOTSUPP;
  428. base = dev_read_addr_ptr(dev_get_parent(dev));
  429. if (!base)
  430. return -EINVAL;
  431. in0_clk = kzalloc(sizeof(*in0_clk), GFP_KERNEL);
  432. if (!in0_clk)
  433. return -ENOMEM;
  434. ret = clk_get_by_index(dev, 0, in0_clk);
  435. if (ret)
  436. return ret;
  437. in0 = in0_clk->dev->name;
  438. probed = true;
  439. aclk_sels[0] = in0;
  440. pll2_sels[0] = in0;
  441. /*
  442. * All PLLs have a broken bypass, but pll0 has the CPU downstream, so we
  443. * need to manually reparent it whenever we configure pll0
  444. */
  445. pll = k210_create_pll(&k210_plls[0], base);
  446. if (pll) {
  447. bypass = k210_register_bypass("pll0", in0, &pll->clk,
  448. &k210_pll_ops, in0_clk);
  449. clk_dm(K210_CLK_PLL0, bypass);
  450. } else {
  451. return -ENOMEM;
  452. }
  453. {
  454. const struct k210_pll_params *params = &k210_plls[1];
  455. clk_dm(K210_CLK_PLL1,
  456. k210_register_pll("pll1", in0, base + params->off,
  457. base + params->lock_off, params->shift,
  458. params->width));
  459. }
  460. /* PLL2 is muxed, so set up a composite clock */
  461. mux = k210_create_mux(&k210_muxes[MUXIFY(K210_CLK_PLL2)], base);
  462. pll = k210_create_pll(&k210_plls[2], base);
  463. if (!mux || !pll) {
  464. free(mux);
  465. free(pll);
  466. } else {
  467. clk_dm(K210_CLK_PLL2,
  468. clk_register_composite(NULL, "pll2", pll2_sels,
  469. ARRAY_SIZE(pll2_sels),
  470. &mux->clk, &clk_mux_ops,
  471. &pll->clk, &k210_pll_ops,
  472. &pll->clk, &k210_pll_ops, 0));
  473. }
  474. /* Half-frequency clocks for "even" dividers */
  475. clk_dm(K210_CLK_IN0_H, k210_clk_half("in0_half", in0));
  476. clk_dm(K210_CLK_PLL0_H, k210_clk_half("pll0_half", "pll0"));
  477. clk_dm(K210_CLK_PLL2_H, k210_clk_half("pll2_half", "pll2"));
  478. /* ACLK has no gate */
  479. mux = k210_create_mux(&k210_muxes[MUXIFY(K210_CLK_ACLK)], base);
  480. div = k210_create_div(&k210_divs[DIVIFY(K210_CLK_ACLK)], base);
  481. if (!mux || !div) {
  482. free(mux);
  483. free(div);
  484. } else {
  485. struct clk *aclk =
  486. clk_register_composite(NULL, "aclk", aclk_sels,
  487. ARRAY_SIZE(aclk_sels),
  488. &mux->clk, &clk_mux_ops,
  489. &div->clk, &clk_divider_ops,
  490. NULL, NULL, 0);
  491. clk_dm(K210_CLK_ACLK, aclk);
  492. if (!IS_ERR(aclk)) {
  493. k210_bypass_children = aclk;
  494. k210_bypass_set_children(bypass,
  495. &k210_bypass_children, 1);
  496. }
  497. }
  498. #define REGISTER_COMP(id, name) \
  499. clk_dm(id, \
  500. k210_register_comp(&k210_comps[COMPIFY(id)], base, name, NULL))
  501. REGISTER_COMP(K210_CLK_SPI3, "spi3");
  502. REGISTER_COMP(K210_CLK_TIMER0, "timer0");
  503. REGISTER_COMP(K210_CLK_TIMER1, "timer1");
  504. REGISTER_COMP(K210_CLK_TIMER2, "timer2");
  505. #undef REGISTER_COMP
  506. /* Dividing clocks, no mux */
  507. #define REGISTER_COMP_NOMUX(id, name, parent) \
  508. clk_dm(id, \
  509. k210_register_comp(&k210_comps[COMPIFY(id)], base, name, parent))
  510. REGISTER_COMP_NOMUX(K210_CLK_SRAM0, "sram0", "aclk");
  511. REGISTER_COMP_NOMUX(K210_CLK_SRAM1, "sram1", "aclk");
  512. REGISTER_COMP_NOMUX(K210_CLK_ROM, "rom", "aclk");
  513. REGISTER_COMP_NOMUX(K210_CLK_DVP, "dvp", "aclk");
  514. REGISTER_COMP_NOMUX(K210_CLK_APB0, "apb0", "aclk");
  515. REGISTER_COMP_NOMUX(K210_CLK_APB1, "apb1", "aclk");
  516. REGISTER_COMP_NOMUX(K210_CLK_APB2, "apb2", "aclk");
  517. REGISTER_COMP_NOMUX(K210_CLK_AI, "ai", "pll1");
  518. REGISTER_COMP_NOMUX(K210_CLK_I2S0, "i2s0", "pll2_half");
  519. REGISTER_COMP_NOMUX(K210_CLK_I2S1, "i2s1", "pll2_half");
  520. REGISTER_COMP_NOMUX(K210_CLK_I2S2, "i2s2", "pll2_half");
  521. REGISTER_COMP_NOMUX(K210_CLK_WDT0, "wdt0", "in0_half");
  522. REGISTER_COMP_NOMUX(K210_CLK_WDT1, "wdt1", "in0_half");
  523. REGISTER_COMP_NOMUX(K210_CLK_SPI0, "spi0", "pll0_half");
  524. REGISTER_COMP_NOMUX(K210_CLK_SPI1, "spi1", "pll0_half");
  525. REGISTER_COMP_NOMUX(K210_CLK_SPI2, "spi2", "pll0_half");
  526. REGISTER_COMP_NOMUX(K210_CLK_I2C0, "i2c0", "pll0_half");
  527. REGISTER_COMP_NOMUX(K210_CLK_I2C1, "i2c1", "pll0_half");
  528. REGISTER_COMP_NOMUX(K210_CLK_I2C2, "i2c2", "pll0_half");
  529. #undef REGISTER_COMP_NOMUX
  530. /* Dividing clocks */
  531. #define REGISTER_DIV(id, name, parent) do {\
  532. const struct k210_div_params *params = &k210_divs[DIVIFY(id)]; \
  533. clk_dm(id, \
  534. clk_register_divider(NULL, name, parent, 0, base + params->off, \
  535. params->shift, params->width, 0)); \
  536. } while (false)
  537. REGISTER_DIV(K210_CLK_I2S0_M, "i2s0_m", "pll2_half");
  538. REGISTER_DIV(K210_CLK_I2S1_M, "i2s1_m", "pll2_half");
  539. REGISTER_DIV(K210_CLK_I2S2_M, "i2s2_m", "pll2_half");
  540. #undef REGISTER_DIV
  541. /* Gated clocks */
  542. #define REGISTER_GATE(id, name, parent) do { \
  543. const struct k210_gate_params *params = &k210_gates[GATEIFY(id)]; \
  544. clk_dm(id, \
  545. clk_register_gate(NULL, name, parent, 0, base + params->off, \
  546. params->bit_idx, 0, NULL)); \
  547. } while (false)
  548. REGISTER_GATE(K210_CLK_CPU, "cpu", "aclk");
  549. REGISTER_GATE(K210_CLK_DMA, "dma", "aclk");
  550. REGISTER_GATE(K210_CLK_FFT, "fft", "aclk");
  551. REGISTER_GATE(K210_CLK_GPIO, "gpio", "apb0");
  552. REGISTER_GATE(K210_CLK_UART1, "uart1", "apb0");
  553. REGISTER_GATE(K210_CLK_UART2, "uart2", "apb0");
  554. REGISTER_GATE(K210_CLK_UART3, "uart3", "apb0");
  555. REGISTER_GATE(K210_CLK_FPIOA, "fpioa", "apb0");
  556. REGISTER_GATE(K210_CLK_SHA, "sha", "apb0");
  557. REGISTER_GATE(K210_CLK_AES, "aes", "apb1");
  558. REGISTER_GATE(K210_CLK_OTP, "otp", "apb1");
  559. REGISTER_GATE(K210_CLK_RTC, "rtc", in0);
  560. #undef REGISTER_GATE
  561. return 0;
  562. }
  563. static const struct udevice_id k210_clk_ids[] = {
  564. { .compatible = "kendryte,k210-clk" },
  565. { },
  566. };
  567. U_BOOT_DRIVER(k210_clk) = {
  568. .name = "k210_clk",
  569. .id = UCLASS_CLK,
  570. .of_match = k210_clk_ids,
  571. .ops = &k210_clk_ops,
  572. .probe = k210_clk_probe,
  573. };