clk-sg2042-clkgen.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Sophgo SG2042 Clock Generator Driver
  4. *
  5. * Copyright (C) 2024 Sophgo Technology Inc.
  6. * Copyright (C) 2024 Chen Wang <unicorn_wang@outlook.com>
  7. */
  8. #include <linux/array_size.h>
  9. #include <linux/bits.h>
  10. #include <linux/clk.h>
  11. #include <linux/clk-provider.h>
  12. #include <linux/io.h>
  13. #include <linux/platform_device.h>
  14. #include <asm/div64.h>
  15. #include <dt-bindings/clock/sophgo,sg2042-clkgen.h>
  16. #include "clk-sg2042.h"
  17. /* Registers defined in SYS_CTRL */
  18. #define R_PLL_BEGIN 0xC0
  19. #define R_PLL_STAT (0xC0 - R_PLL_BEGIN)
  20. #define R_PLL_CLKEN_CONTROL (0xC4 - R_PLL_BEGIN)
  21. #define R_MPLL_CONTROL (0xE8 - R_PLL_BEGIN)
  22. #define R_FPLL_CONTROL (0xF4 - R_PLL_BEGIN)
  23. #define R_DPLL0_CONTROL (0xF8 - R_PLL_BEGIN)
  24. #define R_DPLL1_CONTROL (0xFC - R_PLL_BEGIN)
  25. /* Registers defined in CLOCK */
  26. #define R_CLKENREG0 0x00
  27. #define R_CLKENREG1 0x04
  28. #define R_CLKSELREG0 0x20
  29. #define R_CLKDIVREG0 0x40
  30. #define R_CLKDIVREG1 0x44
  31. #define R_CLKDIVREG2 0x48
  32. #define R_CLKDIVREG3 0x4C
  33. #define R_CLKDIVREG4 0x50
  34. #define R_CLKDIVREG5 0x54
  35. #define R_CLKDIVREG6 0x58
  36. #define R_CLKDIVREG7 0x5C
  37. #define R_CLKDIVREG8 0x60
  38. #define R_CLKDIVREG9 0x64
  39. #define R_CLKDIVREG10 0x68
  40. #define R_CLKDIVREG11 0x6C
  41. #define R_CLKDIVREG12 0x70
  42. #define R_CLKDIVREG13 0x74
  43. #define R_CLKDIVREG14 0x78
  44. #define R_CLKDIVREG15 0x7C
  45. #define R_CLKDIVREG16 0x80
  46. #define R_CLKDIVREG17 0x84
  47. #define R_CLKDIVREG18 0x88
  48. #define R_CLKDIVREG19 0x8C
  49. #define R_CLKDIVREG20 0x90
  50. #define R_CLKDIVREG21 0x94
  51. #define R_CLKDIVREG22 0x98
  52. #define R_CLKDIVREG23 0x9C
  53. #define R_CLKDIVREG24 0xA0
  54. #define R_CLKDIVREG25 0xA4
  55. #define R_CLKDIVREG26 0xA8
  56. #define R_CLKDIVREG27 0xAC
  57. #define R_CLKDIVREG28 0xB0
  58. #define R_CLKDIVREG29 0xB4
  59. #define R_CLKDIVREG30 0xB8
  60. /* All following shift value are the same for all DIV registers */
  61. #define SHIFT_DIV_RESET_CTRL 0
  62. #define SHIFT_DIV_FACTOR_SEL 3
  63. #define SHIFT_DIV_FACTOR 16
  64. /**
  65. * struct sg2042_divider_clock - Divider clock
  66. * @hw: clk_hw for initialization
  67. * @id: used to map clk_onecell_data
  68. * @reg: used for readl/writel.
  69. * **NOTE**: DIV registers are ALL in CLOCK!
  70. * @lock: spinlock to protect register access, modification of
  71. * frequency can only be served one at the time
  72. * @offset_ctrl: offset of divider control registers
  73. * @shift: shift of "Clock Divider Factor" in divider control register
  74. * @width: width of "Clock Divider Factor" in divider control register
  75. * @div_flags: private flags for this clock, not for framework-specific
  76. * @initval: In the divider control register, we can configure whether
  77. * to use the value of "Clock Divider Factor" or just use
  78. * the initial value pre-configured by IC. BIT[3] controls
  79. * this and by default (value is 0), means initial value
  80. * is used.
  81. * **NOTE** that we cannot read the initial value (default
  82. * value when poweron) and default value of "Clock Divider
  83. * Factor" is zero, which I think is a hardware design flaw
  84. * and should be sync-ed with the initial value. So in
  85. * software we have to add a configuration item (initval)
  86. * to manually configure this value and use it when BIT[3]
  87. * is zero.
  88. */
  89. struct sg2042_divider_clock {
  90. struct clk_hw hw;
  91. unsigned int id;
  92. void __iomem *reg;
  93. /* protect register access */
  94. spinlock_t *lock;
  95. u32 offset_ctrl;
  96. u8 shift;
  97. u8 width;
  98. u8 div_flags;
  99. u32 initval;
  100. };
  101. #define to_sg2042_clk_divider(_hw) \
  102. container_of(_hw, struct sg2042_divider_clock, hw)
  103. /**
  104. * struct sg2042_gate_clock - Gate clock
  105. * @hw: clk_hw for initialization
  106. * @id: used to map clk_onecell_data
  107. * @offset_enable: offset of gate enable registers
  108. * @bit_idx: which bit in the register controls gating of this clock
  109. */
  110. struct sg2042_gate_clock {
  111. struct clk_hw hw;
  112. unsigned int id;
  113. u32 offset_enable;
  114. u8 bit_idx;
  115. };
  116. /**
  117. * struct sg2042_mux_clock - Mux clock
  118. * @hw: clk_hw for initialization
  119. * @id: used to map clk_onecell_data
  120. * @offset_select: offset of mux selection registers
  121. * **NOTE**: MUX registers are ALL in CLOCK!
  122. * @shift: shift of "Clock Select" in mux selection register
  123. * @width: width of "Clock Select" in mux selection register
  124. * @clk_nb: used for notification
  125. * @original_index: set by notifier callback
  126. */
  127. struct sg2042_mux_clock {
  128. struct clk_hw hw;
  129. unsigned int id;
  130. u32 offset_select;
  131. u8 shift;
  132. u8 width;
  133. struct notifier_block clk_nb;
  134. u8 original_index;
  135. };
  136. #define to_sg2042_mux_nb(_nb) container_of(_nb, struct sg2042_mux_clock, clk_nb)
  137. static unsigned long sg2042_clk_divider_recalc_rate(struct clk_hw *hw,
  138. unsigned long parent_rate)
  139. {
  140. struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw);
  141. unsigned long ret_rate;
  142. u32 val;
  143. if (!(readl(divider->reg) & BIT(SHIFT_DIV_FACTOR_SEL))) {
  144. val = divider->initval;
  145. } else {
  146. val = readl(divider->reg) >> divider->shift;
  147. val &= clk_div_mask(divider->width);
  148. }
  149. ret_rate = divider_recalc_rate(hw, parent_rate, val, NULL,
  150. divider->div_flags, divider->width);
  151. pr_debug("--> %s: divider_recalc_rate: ret_rate = %ld\n",
  152. clk_hw_get_name(hw), ret_rate);
  153. return ret_rate;
  154. }
  155. static long sg2042_clk_divider_round_rate(struct clk_hw *hw,
  156. unsigned long rate,
  157. unsigned long *prate)
  158. {
  159. struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw);
  160. unsigned long ret_rate;
  161. u32 bestdiv;
  162. /* if read only, just return current value */
  163. if (divider->div_flags & CLK_DIVIDER_READ_ONLY) {
  164. if (!(readl(divider->reg) & BIT(SHIFT_DIV_FACTOR_SEL))) {
  165. bestdiv = divider->initval;
  166. } else {
  167. bestdiv = readl(divider->reg) >> divider->shift;
  168. bestdiv &= clk_div_mask(divider->width);
  169. }
  170. ret_rate = DIV_ROUND_UP_ULL((u64)*prate, bestdiv);
  171. } else {
  172. ret_rate = divider_round_rate(hw, rate, prate, NULL,
  173. divider->width, divider->div_flags);
  174. }
  175. pr_debug("--> %s: divider_round_rate: val = %ld\n",
  176. clk_hw_get_name(hw), ret_rate);
  177. return ret_rate;
  178. }
  179. static int sg2042_clk_divider_set_rate(struct clk_hw *hw,
  180. unsigned long rate,
  181. unsigned long parent_rate)
  182. {
  183. struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw);
  184. unsigned long flags = 0;
  185. u32 val, val2, value;
  186. value = divider_get_val(rate, parent_rate, NULL,
  187. divider->width, divider->div_flags);
  188. if (divider->lock)
  189. spin_lock_irqsave(divider->lock, flags);
  190. else
  191. __acquire(divider->lock);
  192. /*
  193. * The sequence of clock frequency modification is:
  194. * Assert to reset divider.
  195. * Modify the value of Clock Divide Factor (and High Wide if needed).
  196. * De-assert to restore divided clock with new frequency.
  197. */
  198. val = readl(divider->reg);
  199. /* assert */
  200. val &= ~BIT(SHIFT_DIV_RESET_CTRL);
  201. writel(val, divider->reg);
  202. if (divider->div_flags & CLK_DIVIDER_HIWORD_MASK) {
  203. val = clk_div_mask(divider->width) << (divider->shift + 16);
  204. } else {
  205. val = readl(divider->reg);
  206. val &= ~(clk_div_mask(divider->width) << divider->shift);
  207. }
  208. val |= value << divider->shift;
  209. val |= BIT(SHIFT_DIV_FACTOR_SEL);
  210. writel(val, divider->reg);
  211. val2 = val;
  212. /* de-assert */
  213. val |= BIT(SHIFT_DIV_RESET_CTRL);
  214. writel(val, divider->reg);
  215. if (divider->lock)
  216. spin_unlock_irqrestore(divider->lock, flags);
  217. else
  218. __release(divider->lock);
  219. pr_debug("--> %s: divider_set_rate: register val = 0x%x\n",
  220. clk_hw_get_name(hw), val2);
  221. return 0;
  222. }
  223. static const struct clk_ops sg2042_clk_divider_ops = {
  224. .recalc_rate = sg2042_clk_divider_recalc_rate,
  225. .round_rate = sg2042_clk_divider_round_rate,
  226. .set_rate = sg2042_clk_divider_set_rate,
  227. };
  228. static const struct clk_ops sg2042_clk_divider_ro_ops = {
  229. .recalc_rate = sg2042_clk_divider_recalc_rate,
  230. .round_rate = sg2042_clk_divider_round_rate,
  231. };
  232. /*
  233. * Clock initialization macro naming rules:
  234. * FW: use CLK_HW_INIT_FW_NAME
  235. * HW: use CLK_HW_INIT_HW
  236. * HWS: use CLK_HW_INIT_HWS
  237. * RO: means Read-Only
  238. */
  239. #define SG2042_DIV_FW(_id, _name, _parent, \
  240. _r_ctrl, _shift, _width, \
  241. _div_flag, _initval) { \
  242. .id = _id, \
  243. .hw.init = CLK_HW_INIT_FW_NAME( \
  244. _name, \
  245. _parent, \
  246. &sg2042_clk_divider_ops, \
  247. 0), \
  248. .offset_ctrl = _r_ctrl, \
  249. .shift = _shift, \
  250. .width = _width, \
  251. .div_flags = _div_flag, \
  252. .initval = _initval, \
  253. }
  254. #define SG2042_DIV_FW_RO(_id, _name, _parent, \
  255. _r_ctrl, _shift, _width, \
  256. _div_flag, _initval) { \
  257. .id = _id, \
  258. .hw.init = CLK_HW_INIT_FW_NAME( \
  259. _name, \
  260. _parent, \
  261. &sg2042_clk_divider_ro_ops, \
  262. 0), \
  263. .offset_ctrl = _r_ctrl, \
  264. .shift = _shift, \
  265. .width = _width, \
  266. .div_flags = (_div_flag) | CLK_DIVIDER_READ_ONLY, \
  267. .initval = _initval, \
  268. }
  269. #define SG2042_DIV_HW(_id, _name, _parent, \
  270. _r_ctrl, _shift, _width, \
  271. _div_flag, _initval) { \
  272. .id = _id, \
  273. .hw.init = CLK_HW_INIT_HW( \
  274. _name, \
  275. _parent, \
  276. &sg2042_clk_divider_ops, \
  277. 0), \
  278. .offset_ctrl = _r_ctrl, \
  279. .shift = _shift, \
  280. .width = _width, \
  281. .div_flags = _div_flag, \
  282. .initval = _initval, \
  283. }
  284. #define SG2042_DIV_HW_RO(_id, _name, _parent, \
  285. _r_ctrl, _shift, _width, \
  286. _div_flag, _initval) { \
  287. .id = _id, \
  288. .hw.init = CLK_HW_INIT_HW( \
  289. _name, \
  290. _parent, \
  291. &sg2042_clk_divider_ro_ops, \
  292. 0), \
  293. .offset_ctrl = _r_ctrl, \
  294. .shift = _shift, \
  295. .width = _width, \
  296. .div_flags = (_div_flag) | CLK_DIVIDER_READ_ONLY, \
  297. .initval = _initval, \
  298. }
  299. #define SG2042_DIV_HWS(_id, _name, _parent, \
  300. _r_ctrl, _shift, _width, \
  301. _div_flag, _initval) { \
  302. .id = _id, \
  303. .hw.init = CLK_HW_INIT_HWS( \
  304. _name, \
  305. _parent, \
  306. &sg2042_clk_divider_ops, \
  307. 0), \
  308. .offset_ctrl = _r_ctrl, \
  309. .shift = _shift, \
  310. .width = _width, \
  311. .div_flags = _div_flag, \
  312. .initval = _initval, \
  313. }
  314. #define SG2042_DIV_HWS_RO(_id, _name, _parent, \
  315. _r_ctrl, _shift, _width, \
  316. _div_flag, _initval) { \
  317. .id = _id, \
  318. .hw.init = CLK_HW_INIT_HWS( \
  319. _name, \
  320. _parent, \
  321. &sg2042_clk_divider_ro_ops, \
  322. 0), \
  323. .offset_ctrl = _r_ctrl, \
  324. .shift = _shift, \
  325. .width = _width, \
  326. .div_flags = (_div_flag) | CLK_DIVIDER_READ_ONLY, \
  327. .initval = _initval, \
  328. }
  329. #define SG2042_GATE_HWS(_id, _name, _parent, _flags, \
  330. _r_enable, _bit_idx) { \
  331. .id = _id, \
  332. .hw.init = CLK_HW_INIT_HWS( \
  333. _name, \
  334. _parent, \
  335. NULL, \
  336. _flags), \
  337. .offset_enable = _r_enable, \
  338. .bit_idx = _bit_idx, \
  339. }
  340. #define SG2042_GATE_HW(_id, _name, _parent, _flags, \
  341. _r_enable, _bit_idx) { \
  342. .id = _id, \
  343. .hw.init = CLK_HW_INIT_HW( \
  344. _name, \
  345. _parent, \
  346. NULL, \
  347. _flags), \
  348. .offset_enable = _r_enable, \
  349. .bit_idx = _bit_idx, \
  350. }
  351. #define SG2042_GATE_FW(_id, _name, _parent, _flags, \
  352. _r_enable, _bit_idx) { \
  353. .id = _id, \
  354. .hw.init = CLK_HW_INIT_FW_NAME( \
  355. _name, \
  356. _parent, \
  357. NULL, \
  358. _flags), \
  359. .offset_enable = _r_enable, \
  360. .bit_idx = _bit_idx, \
  361. }
  362. #define SG2042_MUX(_id, _name, _parents, _flags, _r_select, _shift, _width) { \
  363. .id = _id, \
  364. .hw.init = CLK_HW_INIT_PARENTS_HW( \
  365. _name, \
  366. _parents, \
  367. NULL, \
  368. _flags), \
  369. .offset_select = _r_select, \
  370. .shift = _shift, \
  371. .width = _width, \
  372. }
  373. /*
  374. * Clock items in the array are sorted according to the clock-tree diagram,
  375. * from top to bottom, from upstream to downstream. Read TRM for details.
  376. */
  377. /* updated during probe/registration */
  378. static const struct clk_hw *clk_gate_ddr01_div0[] = { NULL };
  379. static const struct clk_hw *clk_gate_ddr01_div1[] = { NULL };
  380. static const struct clk_hw *clk_gate_ddr23_div0[] = { NULL };
  381. static const struct clk_hw *clk_gate_ddr23_div1[] = { NULL };
  382. static const struct clk_hw *clk_gate_rp_cpu_normal_div0[] = { NULL };
  383. static const struct clk_hw *clk_gate_rp_cpu_normal_div1[] = { NULL };
  384. static const struct clk_hw *clk_gate_axi_ddr_div0[] = { NULL };
  385. static const struct clk_hw *clk_gate_axi_ddr_div1[] = { NULL };
  386. static const struct sg2042_gate_clock sg2042_gate_clks_level_1[] = {
  387. SG2042_GATE_FW(GATE_CLK_DDR01_DIV0, "clk_gate_ddr01_div0", "dpll0",
  388. CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
  389. R_CLKDIVREG27, 4),
  390. SG2042_GATE_FW(GATE_CLK_DDR01_DIV1, "clk_gate_ddr01_div1", "fpll",
  391. CLK_IS_CRITICAL,
  392. R_CLKDIVREG28, 4),
  393. SG2042_GATE_FW(GATE_CLK_DDR23_DIV0, "clk_gate_ddr23_div0", "dpll1",
  394. CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
  395. R_CLKDIVREG29, 4),
  396. SG2042_GATE_FW(GATE_CLK_DDR23_DIV1, "clk_gate_ddr23_div1", "fpll",
  397. CLK_IS_CRITICAL,
  398. R_CLKDIVREG30, 4),
  399. SG2042_GATE_FW(GATE_CLK_RP_CPU_NORMAL_DIV0,
  400. "clk_gate_rp_cpu_normal_div0", "mpll",
  401. CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
  402. R_CLKDIVREG0, 4),
  403. SG2042_GATE_FW(GATE_CLK_RP_CPU_NORMAL_DIV1,
  404. "clk_gate_rp_cpu_normal_div1", "fpll",
  405. CLK_IS_CRITICAL,
  406. R_CLKDIVREG1, 4),
  407. SG2042_GATE_FW(GATE_CLK_AXI_DDR_DIV0, "clk_gate_axi_ddr_div0", "mpll",
  408. CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
  409. R_CLKDIVREG25, 4),
  410. SG2042_GATE_FW(GATE_CLK_AXI_DDR_DIV1, "clk_gate_axi_ddr_div1", "fpll",
  411. CLK_IS_CRITICAL,
  412. R_CLKDIVREG26, 4),
  413. };
  414. #define DEF_DIVFLAG (CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO)
  415. static struct sg2042_divider_clock sg2042_div_clks_level_1[] = {
  416. SG2042_DIV_HWS_RO(DIV_CLK_DPLL0_DDR01_0,
  417. "clk_div_ddr01_0", clk_gate_ddr01_div0,
  418. R_CLKDIVREG27, 16, 5, DEF_DIVFLAG, 1),
  419. SG2042_DIV_HWS_RO(DIV_CLK_FPLL_DDR01_1,
  420. "clk_div_ddr01_1", clk_gate_ddr01_div1,
  421. R_CLKDIVREG28, 16, 5, DEF_DIVFLAG, 1),
  422. SG2042_DIV_HWS_RO(DIV_CLK_DPLL1_DDR23_0,
  423. "clk_div_ddr23_0", clk_gate_ddr23_div0,
  424. R_CLKDIVREG29, 16, 5, DEF_DIVFLAG, 1),
  425. SG2042_DIV_HWS_RO(DIV_CLK_FPLL_DDR23_1,
  426. "clk_div_ddr23_1", clk_gate_ddr23_div1,
  427. R_CLKDIVREG30, 16, 5, DEF_DIVFLAG, 1),
  428. SG2042_DIV_HWS(DIV_CLK_MPLL_RP_CPU_NORMAL_0,
  429. "clk_div_rp_cpu_normal_0", clk_gate_rp_cpu_normal_div0,
  430. R_CLKDIVREG0, 16, 5, DEF_DIVFLAG, 1),
  431. SG2042_DIV_HWS(DIV_CLK_FPLL_RP_CPU_NORMAL_1,
  432. "clk_div_rp_cpu_normal_1", clk_gate_rp_cpu_normal_div1,
  433. R_CLKDIVREG1, 16, 5, DEF_DIVFLAG, 1),
  434. SG2042_DIV_HWS(DIV_CLK_MPLL_AXI_DDR_0,
  435. "clk_div_axi_ddr_0", clk_gate_axi_ddr_div0,
  436. R_CLKDIVREG25, 16, 5, DEF_DIVFLAG, 2),
  437. SG2042_DIV_HWS(DIV_CLK_FPLL_AXI_DDR_1,
  438. "clk_div_axi_ddr_1", clk_gate_axi_ddr_div1,
  439. R_CLKDIVREG26, 16, 5, DEF_DIVFLAG, 1),
  440. };
  441. /*
  442. * Note: regarding names for mux clock, "0/1" or "div0/div1" means the
  443. * first/second parent input source, not the register value.
  444. * For example:
  445. * "clk_div_ddr01_0" is the name of Clock divider 0 control of DDR01, and
  446. * "clk_gate_ddr01_div0" is the gate clock in front of the "clk_div_ddr01_0",
  447. * they are both controlled by register CLKDIVREG27;
  448. * "clk_div_ddr01_1" is the name of Clock divider 1 control of DDR01, and
  449. * "clk_gate_ddr01_div1" is the gate clock in front of the "clk_div_ddr01_1",
  450. * they are both controlled by register CLKDIVREG28;
  451. * While for register value of mux selection, use Clock Select for DDR01’s clock
  452. * as example, see CLKSELREG0, bit[2].
  453. * 1: Select in_dpll0_clk as clock source, correspondng to the parent input
  454. * source from "clk_div_ddr01_0".
  455. * 0: Select in_fpll_clk as clock source, corresponding to the parent input
  456. * source from "clk_div_ddr01_1".
  457. * So we need a table to define the array of register values corresponding to
  458. * the parent index and tell CCF about this when registering mux clock.
  459. */
  460. static const u32 sg2042_mux_table[] = {1, 0};
  461. /* Aliases just for easy reading */
  462. #define clk_div_ddr01_0 (&sg2042_div_clks_level_1[0].hw)
  463. #define clk_div_ddr01_1 (&sg2042_div_clks_level_1[1].hw)
  464. #define clk_div_ddr23_0 (&sg2042_div_clks_level_1[2].hw)
  465. #define clk_div_ddr23_1 (&sg2042_div_clks_level_1[3].hw)
  466. #define clk_div_rp_cpu_normal_0 (&sg2042_div_clks_level_1[4].hw)
  467. #define clk_div_rp_cpu_normal_1 (&sg2042_div_clks_level_1[5].hw)
  468. #define clk_div_axi_ddr_0 (&sg2042_div_clks_level_1[6].hw)
  469. #define clk_div_axi_ddr_1 (&sg2042_div_clks_level_1[7].hw)
  470. static const struct clk_hw *clk_mux_ddr01_p[] = {
  471. clk_div_ddr01_0,
  472. clk_div_ddr01_1,
  473. };
  474. static const struct clk_hw *clk_mux_ddr23_p[] = {
  475. clk_div_ddr23_0,
  476. clk_div_ddr23_1,
  477. };
  478. static const struct clk_hw *clk_mux_rp_cpu_normal_p[] = {
  479. clk_div_rp_cpu_normal_0,
  480. clk_div_rp_cpu_normal_1,
  481. };
  482. static const struct clk_hw *clk_mux_axi_ddr_p[] = {
  483. clk_div_axi_ddr_0,
  484. clk_div_axi_ddr_1,
  485. };
  486. /* Mux clocks to be updated during probe/registration */
  487. static const struct clk_hw *clk_mux_ddr01[] = { NULL };
  488. static const struct clk_hw *clk_mux_ddr23[] = { NULL };
  489. static const struct clk_hw *clk_mux_rp_cpu_normal[] = { NULL };
  490. static const struct clk_hw *clk_mux_axi_ddr[] = { NULL };
  491. static struct sg2042_mux_clock sg2042_mux_clks[] = {
  492. SG2042_MUX(MUX_CLK_DDR01, "clk_mux_ddr01", clk_mux_ddr01_p,
  493. CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT | CLK_MUX_READ_ONLY,
  494. R_CLKSELREG0, 2, 1),
  495. SG2042_MUX(MUX_CLK_DDR23, "clk_mux_ddr23", clk_mux_ddr23_p,
  496. CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT | CLK_MUX_READ_ONLY,
  497. R_CLKSELREG0, 3, 1),
  498. SG2042_MUX(MUX_CLK_RP_CPU_NORMAL, "clk_mux_rp_cpu_normal", clk_mux_rp_cpu_normal_p,
  499. CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
  500. R_CLKSELREG0, 0, 1),
  501. SG2042_MUX(MUX_CLK_AXI_DDR, "clk_mux_axi_ddr", clk_mux_axi_ddr_p,
  502. CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
  503. R_CLKSELREG0, 1, 1),
  504. };
  505. /* Aliases just for easy reading */
  506. #define clk_div_top_rp_cmn_div2 (&sg2042_div_clks_level_2[0].hw)
  507. #define clk_div_50m_a53 (&sg2042_div_clks_level_2[1].hw)
  508. #define clk_div_timer1 (&sg2042_div_clks_level_2[2].hw)
  509. #define clk_div_timer2 (&sg2042_div_clks_level_2[3].hw)
  510. #define clk_div_timer3 (&sg2042_div_clks_level_2[4].hw)
  511. #define clk_div_timer4 (&sg2042_div_clks_level_2[5].hw)
  512. #define clk_div_timer5 (&sg2042_div_clks_level_2[6].hw)
  513. #define clk_div_timer6 (&sg2042_div_clks_level_2[7].hw)
  514. #define clk_div_timer7 (&sg2042_div_clks_level_2[8].hw)
  515. #define clk_div_timer8 (&sg2042_div_clks_level_2[9].hw)
  516. #define clk_div_uart_500m (&sg2042_div_clks_level_2[10].hw)
  517. #define clk_div_ahb_lpc (&sg2042_div_clks_level_2[11].hw)
  518. #define clk_div_efuse (&sg2042_div_clks_level_2[12].hw)
  519. #define clk_div_tx_eth0 (&sg2042_div_clks_level_2[13].hw)
  520. #define clk_div_ptp_ref_i_eth0 (&sg2042_div_clks_level_2[14].hw)
  521. #define clk_div_ref_eth0 (&sg2042_div_clks_level_2[15].hw)
  522. #define clk_div_emmc (&sg2042_div_clks_level_2[16].hw)
  523. #define clk_div_sd (&sg2042_div_clks_level_2[17].hw)
  524. #define clk_div_top_axi0 (&sg2042_div_clks_level_2[18].hw)
  525. #define clk_div_100k_emmc (&sg2042_div_clks_level_2[19].hw)
  526. #define clk_div_100k_sd (&sg2042_div_clks_level_2[20].hw)
  527. #define clk_div_gpio_db (&sg2042_div_clks_level_2[21].hw)
  528. #define clk_div_top_axi_hsperi (&sg2042_div_clks_level_2[22].hw)
  529. static struct sg2042_divider_clock sg2042_div_clks_level_2[] = {
  530. SG2042_DIV_HWS(DIV_CLK_FPLL_TOP_RP_CMN_DIV2,
  531. "clk_div_top_rp_cmn_div2", clk_mux_rp_cpu_normal,
  532. R_CLKDIVREG3, 16, 16, DEF_DIVFLAG, 2),
  533. SG2042_DIV_FW(DIV_CLK_FPLL_50M_A53, "clk_div_50m_a53", "fpll",
  534. R_CLKDIVREG2, 16, 8, DEF_DIVFLAG, 20),
  535. /* downstream of div_50m_a53 */
  536. SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER1, "clk_div_timer1", clk_div_50m_a53,
  537. R_CLKDIVREG6, 16, 16, DEF_DIVFLAG, 1),
  538. SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER2, "clk_div_timer2", clk_div_50m_a53,
  539. R_CLKDIVREG7, 16, 16, DEF_DIVFLAG, 1),
  540. SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER3, "clk_div_timer3", clk_div_50m_a53,
  541. R_CLKDIVREG8, 16, 16, DEF_DIVFLAG, 1),
  542. SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER4, "clk_div_timer4", clk_div_50m_a53,
  543. R_CLKDIVREG9, 16, 16, DEF_DIVFLAG, 1),
  544. SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER5, "clk_div_timer5", clk_div_50m_a53,
  545. R_CLKDIVREG10, 16, 16, DEF_DIVFLAG, 1),
  546. SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER6, "clk_div_timer6", clk_div_50m_a53,
  547. R_CLKDIVREG11, 16, 16, DEF_DIVFLAG, 1),
  548. SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER7, "clk_div_timer7", clk_div_50m_a53,
  549. R_CLKDIVREG12, 16, 16, DEF_DIVFLAG, 1),
  550. SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER8, "clk_div_timer8", clk_div_50m_a53,
  551. R_CLKDIVREG13, 16, 16, DEF_DIVFLAG, 1),
  552. /*
  553. * Set clk_div_uart_500m as RO, because the width of CLKDIVREG4 is too
  554. * narrow for us to produce 115200. Use UART internal divider directly.
  555. */
  556. SG2042_DIV_FW_RO(DIV_CLK_FPLL_UART_500M, "clk_div_uart_500m", "fpll",
  557. R_CLKDIVREG4, 16, 7, DEF_DIVFLAG, 2),
  558. SG2042_DIV_FW(DIV_CLK_FPLL_AHB_LPC, "clk_div_ahb_lpc", "fpll",
  559. R_CLKDIVREG5, 16, 16, DEF_DIVFLAG, 5),
  560. SG2042_DIV_FW(DIV_CLK_FPLL_EFUSE, "clk_div_efuse", "fpll",
  561. R_CLKDIVREG14, 16, 7, DEF_DIVFLAG, 40),
  562. SG2042_DIV_FW(DIV_CLK_FPLL_TX_ETH0, "clk_div_tx_eth0", "fpll",
  563. R_CLKDIVREG16, 16, 11, DEF_DIVFLAG, 8),
  564. SG2042_DIV_FW(DIV_CLK_FPLL_PTP_REF_I_ETH0,
  565. "clk_div_ptp_ref_i_eth0", "fpll",
  566. R_CLKDIVREG17, 16, 8, DEF_DIVFLAG, 20),
  567. SG2042_DIV_FW(DIV_CLK_FPLL_REF_ETH0, "clk_div_ref_eth0", "fpll",
  568. R_CLKDIVREG18, 16, 8, DEF_DIVFLAG, 40),
  569. SG2042_DIV_FW(DIV_CLK_FPLL_EMMC, "clk_div_emmc", "fpll",
  570. R_CLKDIVREG19, 16, 5, DEF_DIVFLAG, 10),
  571. SG2042_DIV_FW(DIV_CLK_FPLL_SD, "clk_div_sd", "fpll",
  572. R_CLKDIVREG21, 16, 5, DEF_DIVFLAG, 10),
  573. SG2042_DIV_FW(DIV_CLK_FPLL_TOP_AXI0, "clk_div_top_axi0", "fpll",
  574. R_CLKDIVREG23, 16, 5, DEF_DIVFLAG, 10),
  575. /* downstream of div_top_axi0 */
  576. SG2042_DIV_HW(DIV_CLK_FPLL_100K_EMMC, "clk_div_100k_emmc", clk_div_top_axi0,
  577. R_CLKDIVREG20, 16, 16, DEF_DIVFLAG, 1000),
  578. SG2042_DIV_HW(DIV_CLK_FPLL_100K_SD, "clk_div_100k_sd", clk_div_top_axi0,
  579. R_CLKDIVREG22, 16, 16, DEF_DIVFLAG, 1000),
  580. SG2042_DIV_HW(DIV_CLK_FPLL_GPIO_DB, "clk_div_gpio_db", clk_div_top_axi0,
  581. R_CLKDIVREG15, 16, 16, DEF_DIVFLAG, 1000),
  582. SG2042_DIV_FW(DIV_CLK_FPLL_TOP_AXI_HSPERI,
  583. "clk_div_top_axi_hsperi", "fpll",
  584. R_CLKDIVREG24, 16, 5, DEF_DIVFLAG, 4),
  585. };
  586. /* Gate clocks to be updated during probe/registration */
  587. static const struct clk_hw *clk_gate_rp_cpu_normal[] = { NULL };
  588. static const struct clk_hw *clk_gate_top_rp_cmn_div2[] = { NULL };
  589. static const struct sg2042_gate_clock sg2042_gate_clks_level_2[] = {
  590. SG2042_GATE_HWS(GATE_CLK_DDR01, "clk_gate_ddr01", clk_mux_ddr01,
  591. CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
  592. R_CLKENREG1, 14),
  593. SG2042_GATE_HWS(GATE_CLK_DDR23, "clk_gate_ddr23", clk_mux_ddr23,
  594. CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
  595. R_CLKENREG1, 15),
  596. SG2042_GATE_HWS(GATE_CLK_RP_CPU_NORMAL,
  597. "clk_gate_rp_cpu_normal", clk_mux_rp_cpu_normal,
  598. CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
  599. R_CLKENREG0, 0),
  600. SG2042_GATE_HWS(GATE_CLK_AXI_DDR, "clk_gate_axi_ddr", clk_mux_axi_ddr,
  601. CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
  602. R_CLKENREG1, 13),
  603. /* upon are gate clocks directly downstream of muxes */
  604. /* downstream of clk_div_top_rp_cmn_div2 */
  605. SG2042_GATE_HW(GATE_CLK_TOP_RP_CMN_DIV2,
  606. "clk_gate_top_rp_cmn_div2", clk_div_top_rp_cmn_div2,
  607. CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 2),
  608. SG2042_GATE_HWS(GATE_CLK_HSDMA, "clk_gate_hsdma", clk_gate_top_rp_cmn_div2,
  609. CLK_SET_RATE_PARENT, R_CLKENREG1, 10),
  610. /*
  611. * downstream of clk_gate_rp_cpu_normal
  612. *
  613. * FIXME: there should be one 1/2 DIV between clk_gate_rp_cpu_normal
  614. * and clk_gate_axi_pcie0/clk_gate_axi_pcie1.
  615. * But the 1/2 DIV is fixed and no configurable register exported, so
  616. * when reading from these two clocks, the rate value are still the
  617. * same as that of clk_gate_rp_cpu_normal, it's not correct.
  618. * This just affects the value read.
  619. */
  620. SG2042_GATE_HWS(GATE_CLK_AXI_PCIE0,
  621. "clk_gate_axi_pcie0", clk_gate_rp_cpu_normal,
  622. CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG1, 8),
  623. SG2042_GATE_HWS(GATE_CLK_AXI_PCIE1,
  624. "clk_gate_axi_pcie1", clk_gate_rp_cpu_normal,
  625. CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG1, 9),
  626. /* downstream of div_50m_a53 */
  627. SG2042_GATE_HW(GATE_CLK_A53_50M, "clk_gate_a53_50m", clk_div_50m_a53,
  628. CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 1),
  629. SG2042_GATE_HW(GATE_CLK_TIMER1, "clk_gate_timer1", clk_div_timer1,
  630. CLK_SET_RATE_PARENT, R_CLKENREG0, 12),
  631. SG2042_GATE_HW(GATE_CLK_TIMER2, "clk_gate_timer2", clk_div_timer2,
  632. CLK_SET_RATE_PARENT, R_CLKENREG0, 13),
  633. SG2042_GATE_HW(GATE_CLK_TIMER3, "clk_gate_timer3", clk_div_timer3,
  634. CLK_SET_RATE_PARENT, R_CLKENREG0, 14),
  635. SG2042_GATE_HW(GATE_CLK_TIMER4, "clk_gate_timer4", clk_div_timer4,
  636. CLK_SET_RATE_PARENT, R_CLKENREG0, 15),
  637. SG2042_GATE_HW(GATE_CLK_TIMER5, "clk_gate_timer5", clk_div_timer5,
  638. CLK_SET_RATE_PARENT, R_CLKENREG0, 16),
  639. SG2042_GATE_HW(GATE_CLK_TIMER6, "clk_gate_timer6", clk_div_timer6,
  640. CLK_SET_RATE_PARENT, R_CLKENREG0, 17),
  641. SG2042_GATE_HW(GATE_CLK_TIMER7, "clk_gate_timer7", clk_div_timer7,
  642. CLK_SET_RATE_PARENT, R_CLKENREG0, 18),
  643. SG2042_GATE_HW(GATE_CLK_TIMER8, "clk_gate_timer8", clk_div_timer8,
  644. CLK_SET_RATE_PARENT, R_CLKENREG0, 19),
  645. /* gate clocks downstream from div clocks one-to-one */
  646. SG2042_GATE_HW(GATE_CLK_UART_500M, "clk_gate_uart_500m", clk_div_uart_500m,
  647. CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 4),
  648. SG2042_GATE_HW(GATE_CLK_AHB_LPC, "clk_gate_ahb_lpc", clk_div_ahb_lpc,
  649. CLK_SET_RATE_PARENT, R_CLKENREG0, 7),
  650. SG2042_GATE_HW(GATE_CLK_EFUSE, "clk_gate_efuse", clk_div_efuse,
  651. CLK_SET_RATE_PARENT, R_CLKENREG0, 20),
  652. SG2042_GATE_HW(GATE_CLK_TX_ETH0, "clk_gate_tx_eth0", clk_div_tx_eth0,
  653. CLK_SET_RATE_PARENT, R_CLKENREG0, 30),
  654. SG2042_GATE_HW(GATE_CLK_PTP_REF_I_ETH0,
  655. "clk_gate_ptp_ref_i_eth0", clk_div_ptp_ref_i_eth0,
  656. CLK_SET_RATE_PARENT, R_CLKENREG1, 0),
  657. SG2042_GATE_HW(GATE_CLK_REF_ETH0, "clk_gate_ref_eth0", clk_div_ref_eth0,
  658. CLK_SET_RATE_PARENT, R_CLKENREG1, 1),
  659. SG2042_GATE_HW(GATE_CLK_EMMC_100M, "clk_gate_emmc", clk_div_emmc,
  660. CLK_SET_RATE_PARENT, R_CLKENREG1, 3),
  661. SG2042_GATE_HW(GATE_CLK_SD_100M, "clk_gate_sd", clk_div_sd,
  662. CLK_SET_RATE_PARENT, R_CLKENREG1, 6),
  663. /* downstream of clk_div_top_axi0 */
  664. SG2042_GATE_HW(GATE_CLK_AHB_ROM, "clk_gate_ahb_rom", clk_div_top_axi0,
  665. 0, R_CLKENREG0, 8),
  666. SG2042_GATE_HW(GATE_CLK_AHB_SF, "clk_gate_ahb_sf", clk_div_top_axi0,
  667. 0, R_CLKENREG0, 9),
  668. SG2042_GATE_HW(GATE_CLK_AXI_SRAM, "clk_gate_axi_sram", clk_div_top_axi0,
  669. CLK_IGNORE_UNUSED, R_CLKENREG0, 10),
  670. SG2042_GATE_HW(GATE_CLK_APB_TIMER, "clk_gate_apb_timer", clk_div_top_axi0,
  671. CLK_IGNORE_UNUSED, R_CLKENREG0, 11),
  672. SG2042_GATE_HW(GATE_CLK_APB_EFUSE, "clk_gate_apb_efuse", clk_div_top_axi0,
  673. 0, R_CLKENREG0, 21),
  674. SG2042_GATE_HW(GATE_CLK_APB_GPIO, "clk_gate_apb_gpio", clk_div_top_axi0,
  675. 0, R_CLKENREG0, 22),
  676. SG2042_GATE_HW(GATE_CLK_APB_GPIO_INTR,
  677. "clk_gate_apb_gpio_intr", clk_div_top_axi0,
  678. CLK_IS_CRITICAL, R_CLKENREG0, 23),
  679. SG2042_GATE_HW(GATE_CLK_APB_I2C, "clk_gate_apb_i2c", clk_div_top_axi0,
  680. 0, R_CLKENREG0, 26),
  681. SG2042_GATE_HW(GATE_CLK_APB_WDT, "clk_gate_apb_wdt", clk_div_top_axi0,
  682. 0, R_CLKENREG0, 27),
  683. SG2042_GATE_HW(GATE_CLK_APB_PWM, "clk_gate_apb_pwm", clk_div_top_axi0,
  684. 0, R_CLKENREG0, 28),
  685. SG2042_GATE_HW(GATE_CLK_APB_RTC, "clk_gate_apb_rtc", clk_div_top_axi0,
  686. 0, R_CLKENREG0, 29),
  687. SG2042_GATE_HW(GATE_CLK_TOP_AXI0, "clk_gate_top_axi0", clk_div_top_axi0,
  688. CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
  689. R_CLKENREG1, 11),
  690. /* downstream of DIV clocks which are sourced from clk_div_top_axi0 */
  691. SG2042_GATE_HW(GATE_CLK_GPIO_DB, "clk_gate_gpio_db", clk_div_gpio_db,
  692. CLK_SET_RATE_PARENT, R_CLKENREG0, 24),
  693. SG2042_GATE_HW(GATE_CLK_100K_EMMC, "clk_gate_100k_emmc", clk_div_100k_emmc,
  694. CLK_SET_RATE_PARENT, R_CLKENREG1, 4),
  695. SG2042_GATE_HW(GATE_CLK_100K_SD, "clk_gate_100k_sd", clk_div_100k_sd,
  696. CLK_SET_RATE_PARENT, R_CLKENREG1, 7),
  697. /* downstream of clk_div_top_axi_hsperi */
  698. SG2042_GATE_HW(GATE_CLK_SYSDMA_AXI,
  699. "clk_gate_sysdma_axi", clk_div_top_axi_hsperi,
  700. CLK_SET_RATE_PARENT, R_CLKENREG0, 3),
  701. SG2042_GATE_HW(GATE_CLK_APB_UART,
  702. "clk_gate_apb_uart", clk_div_top_axi_hsperi,
  703. CLK_SET_RATE_PARENT, R_CLKENREG0, 5),
  704. SG2042_GATE_HW(GATE_CLK_AXI_DBG_I2C,
  705. "clk_gate_axi_dbg_i2c", clk_div_top_axi_hsperi,
  706. CLK_SET_RATE_PARENT, R_CLKENREG0, 6),
  707. SG2042_GATE_HW(GATE_CLK_APB_SPI,
  708. "clk_gate_apb_spi", clk_div_top_axi_hsperi,
  709. CLK_SET_RATE_PARENT, R_CLKENREG0, 25),
  710. SG2042_GATE_HW(GATE_CLK_AXI_ETH0,
  711. "clk_gate_axi_eth0", clk_div_top_axi_hsperi,
  712. CLK_SET_RATE_PARENT, R_CLKENREG0, 31),
  713. SG2042_GATE_HW(GATE_CLK_AXI_EMMC,
  714. "clk_gate_axi_emmc", clk_div_top_axi_hsperi,
  715. CLK_SET_RATE_PARENT, R_CLKENREG1, 2),
  716. SG2042_GATE_HW(GATE_CLK_AXI_SD,
  717. "clk_gate_axi_sd", clk_div_top_axi_hsperi,
  718. CLK_SET_RATE_PARENT, R_CLKENREG1, 5),
  719. SG2042_GATE_HW(GATE_CLK_TOP_AXI_HSPERI,
  720. "clk_gate_top_axi_hsperi", clk_div_top_axi_hsperi,
  721. CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
  722. R_CLKENREG1, 12),
  723. };
  724. static DEFINE_SPINLOCK(sg2042_clk_lock);
  725. static int sg2042_clk_register_divs(struct device *dev,
  726. struct sg2042_clk_data *clk_data,
  727. struct sg2042_divider_clock div_clks[],
  728. int num_div_clks)
  729. {
  730. struct sg2042_divider_clock *div;
  731. struct clk_hw *hw;
  732. int i, ret = 0;
  733. for (i = 0; i < num_div_clks; i++) {
  734. div = &div_clks[i];
  735. if (div->div_flags & CLK_DIVIDER_HIWORD_MASK) {
  736. if (div->width + div->shift > 16) {
  737. pr_warn("divider value exceeds LOWORD field\n");
  738. ret = -EINVAL;
  739. break;
  740. }
  741. }
  742. div->reg = clk_data->iobase + div->offset_ctrl;
  743. div->lock = &sg2042_clk_lock;
  744. hw = &div->hw;
  745. ret = devm_clk_hw_register(dev, hw);
  746. if (ret) {
  747. pr_err("failed to register clock %s\n", div->hw.init->name);
  748. break;
  749. }
  750. clk_data->onecell_data.hws[div->id] = hw;
  751. }
  752. return ret;
  753. }
  754. static int sg2042_clk_register_gates(struct device *dev,
  755. struct sg2042_clk_data *clk_data,
  756. const struct sg2042_gate_clock gate_clks[],
  757. int num_gate_clks)
  758. {
  759. const struct sg2042_gate_clock *gate;
  760. struct clk_hw *hw;
  761. int i, ret = 0;
  762. for (i = 0; i < num_gate_clks; i++) {
  763. gate = &gate_clks[i];
  764. hw = __devm_clk_hw_register_gate
  765. (dev,
  766. NULL,
  767. gate->hw.init->name,
  768. NULL,
  769. gate->hw.init->parent_hws[0],
  770. NULL,
  771. gate->hw.init->flags,
  772. clk_data->iobase + gate->offset_enable,
  773. gate->bit_idx,
  774. 0,
  775. &sg2042_clk_lock);
  776. if (IS_ERR(hw)) {
  777. pr_err("failed to register clock %s\n", gate->hw.init->name);
  778. ret = PTR_ERR(hw);
  779. break;
  780. }
  781. clk_data->onecell_data.hws[gate->id] = hw;
  782. /* Updated some clocks which take the role of parent */
  783. switch (gate->id) {
  784. case GATE_CLK_RP_CPU_NORMAL:
  785. *clk_gate_rp_cpu_normal = hw;
  786. break;
  787. case GATE_CLK_TOP_RP_CMN_DIV2:
  788. *clk_gate_top_rp_cmn_div2 = hw;
  789. break;
  790. }
  791. }
  792. return ret;
  793. }
  794. static int sg2042_clk_register_gates_fw(struct device *dev,
  795. struct sg2042_clk_data *clk_data,
  796. const struct sg2042_gate_clock gate_clks[],
  797. int num_gate_clks)
  798. {
  799. const struct sg2042_gate_clock *gate;
  800. struct clk_hw *hw;
  801. int i, ret = 0;
  802. for (i = 0; i < num_gate_clks; i++) {
  803. gate = &gate_clks[i];
  804. hw = devm_clk_hw_register_gate_parent_data
  805. (dev,
  806. gate->hw.init->name,
  807. gate->hw.init->parent_data,
  808. gate->hw.init->flags,
  809. clk_data->iobase + gate->offset_enable,
  810. gate->bit_idx,
  811. 0,
  812. &sg2042_clk_lock);
  813. if (IS_ERR(hw)) {
  814. pr_err("failed to register clock %s\n", gate->hw.init->name);
  815. ret = PTR_ERR(hw);
  816. break;
  817. }
  818. clk_data->onecell_data.hws[gate->id] = hw;
  819. /* Updated some clocks which take the role of parent */
  820. switch (gate->id) {
  821. case GATE_CLK_DDR01_DIV0:
  822. *clk_gate_ddr01_div0 = hw;
  823. break;
  824. case GATE_CLK_DDR01_DIV1:
  825. *clk_gate_ddr01_div1 = hw;
  826. break;
  827. case GATE_CLK_DDR23_DIV0:
  828. *clk_gate_ddr23_div0 = hw;
  829. break;
  830. case GATE_CLK_DDR23_DIV1:
  831. *clk_gate_ddr23_div1 = hw;
  832. break;
  833. case GATE_CLK_RP_CPU_NORMAL_DIV0:
  834. *clk_gate_rp_cpu_normal_div0 = hw;
  835. break;
  836. case GATE_CLK_RP_CPU_NORMAL_DIV1:
  837. *clk_gate_rp_cpu_normal_div1 = hw;
  838. break;
  839. case GATE_CLK_AXI_DDR_DIV0:
  840. *clk_gate_axi_ddr_div0 = hw;
  841. break;
  842. case GATE_CLK_AXI_DDR_DIV1:
  843. *clk_gate_axi_ddr_div1 = hw;
  844. break;
  845. }
  846. }
  847. return ret;
  848. }
  849. static int sg2042_mux_notifier_cb(struct notifier_block *nb,
  850. unsigned long event,
  851. void *data)
  852. {
  853. struct sg2042_mux_clock *mux = to_sg2042_mux_nb(nb);
  854. const struct clk_ops *ops = &clk_mux_ops;
  855. struct clk_notifier_data *ndata = data;
  856. struct clk_hw *hw;
  857. int ret = 0;
  858. hw = __clk_get_hw(ndata->clk);
  859. /* To switch to fpll before changing rate and restore after that */
  860. if (event == PRE_RATE_CHANGE) {
  861. mux->original_index = ops->get_parent(hw);
  862. /*
  863. * "1" is the array index of the second parent input source of
  864. * mux. For SG2042, it's fpll for all mux clocks.
  865. * "0" is the array index of the frist parent input source of
  866. * mux, For SG2042, it's mpll.
  867. * FIXME, any good idea to avoid magic number?
  868. */
  869. if (mux->original_index == 0)
  870. ret = ops->set_parent(hw, 1);
  871. } else if (event == POST_RATE_CHANGE) {
  872. ret = ops->set_parent(hw, mux->original_index);
  873. }
  874. return notifier_from_errno(ret);
  875. }
  876. static int sg2042_clk_register_muxs(struct device *dev,
  877. struct sg2042_clk_data *clk_data,
  878. struct sg2042_mux_clock mux_clks[],
  879. int num_mux_clks)
  880. {
  881. struct sg2042_mux_clock *mux;
  882. struct clk_hw *hw;
  883. int i, ret = 0;
  884. for (i = 0; i < num_mux_clks; i++) {
  885. mux = &mux_clks[i];
  886. hw = __devm_clk_hw_register_mux
  887. (dev,
  888. NULL,
  889. mux->hw.init->name,
  890. mux->hw.init->num_parents,
  891. NULL,
  892. mux->hw.init->parent_hws,
  893. NULL,
  894. mux->hw.init->flags,
  895. clk_data->iobase + mux->offset_select,
  896. mux->shift,
  897. BIT(mux->width) - 1,
  898. 0,
  899. sg2042_mux_table,
  900. &sg2042_clk_lock);
  901. if (IS_ERR(hw)) {
  902. pr_err("failed to register clock %s\n", mux->hw.init->name);
  903. ret = PTR_ERR(hw);
  904. break;
  905. }
  906. clk_data->onecell_data.hws[mux->id] = hw;
  907. /* Updated some clocks which takes the role of parent */
  908. switch (mux->id) {
  909. case MUX_CLK_DDR01:
  910. *clk_mux_ddr01 = hw;
  911. break;
  912. case MUX_CLK_DDR23:
  913. *clk_mux_ddr23 = hw;
  914. break;
  915. case MUX_CLK_RP_CPU_NORMAL:
  916. *clk_mux_rp_cpu_normal = hw;
  917. break;
  918. case MUX_CLK_AXI_DDR:
  919. *clk_mux_axi_ddr = hw;
  920. break;
  921. }
  922. /*
  923. * FIXME: Theoretically, we should set parent for the
  924. * mux, but seems hardware has done this for us with
  925. * default value, so we don't set parent again here.
  926. */
  927. if (!(mux->hw.init->flags & CLK_MUX_READ_ONLY)) {
  928. mux->clk_nb.notifier_call = sg2042_mux_notifier_cb;
  929. ret = devm_clk_notifier_register(dev, hw->clk, &mux->clk_nb);
  930. if (ret) {
  931. pr_err("failed to register clock notifier for %s\n",
  932. mux->hw.init->name);
  933. break;
  934. }
  935. }
  936. }
  937. return ret;
  938. }
  939. static int sg2042_init_clkdata(struct platform_device *pdev,
  940. int num_clks,
  941. struct sg2042_clk_data **pp_clk_data)
  942. {
  943. struct sg2042_clk_data *clk_data = NULL;
  944. clk_data = devm_kzalloc(&pdev->dev,
  945. struct_size(clk_data, onecell_data.hws, num_clks),
  946. GFP_KERNEL);
  947. if (!clk_data)
  948. return -ENOMEM;
  949. clk_data->iobase = devm_platform_ioremap_resource(pdev, 0);
  950. if (WARN_ON(IS_ERR(clk_data->iobase)))
  951. return PTR_ERR(clk_data->iobase);
  952. clk_data->onecell_data.num = num_clks;
  953. *pp_clk_data = clk_data;
  954. return 0;
  955. }
  956. static int sg2042_clkgen_probe(struct platform_device *pdev)
  957. {
  958. struct sg2042_clk_data *clk_data = NULL;
  959. int num_clks;
  960. int ret;
  961. num_clks = ARRAY_SIZE(sg2042_div_clks_level_1) +
  962. ARRAY_SIZE(sg2042_div_clks_level_2) +
  963. ARRAY_SIZE(sg2042_gate_clks_level_1) +
  964. ARRAY_SIZE(sg2042_gate_clks_level_2) +
  965. ARRAY_SIZE(sg2042_mux_clks);
  966. ret = sg2042_init_clkdata(pdev, num_clks, &clk_data);
  967. if (ret)
  968. goto error_out;
  969. /* level-1 gates */
  970. ret = sg2042_clk_register_gates_fw(&pdev->dev, clk_data,
  971. sg2042_gate_clks_level_1,
  972. ARRAY_SIZE(sg2042_gate_clks_level_1));
  973. if (ret)
  974. goto error_out;
  975. /* level-1 div */
  976. ret = sg2042_clk_register_divs(&pdev->dev, clk_data, sg2042_div_clks_level_1,
  977. ARRAY_SIZE(sg2042_div_clks_level_1));
  978. if (ret)
  979. goto error_out;
  980. /* mux */
  981. ret = sg2042_clk_register_muxs(&pdev->dev, clk_data, sg2042_mux_clks,
  982. ARRAY_SIZE(sg2042_mux_clks));
  983. if (ret)
  984. goto error_out;
  985. /* level 2 div */
  986. ret = sg2042_clk_register_divs(&pdev->dev, clk_data, sg2042_div_clks_level_2,
  987. ARRAY_SIZE(sg2042_div_clks_level_2));
  988. if (ret)
  989. goto error_out;
  990. /* level 2 gate */
  991. ret = sg2042_clk_register_gates(&pdev->dev, clk_data, sg2042_gate_clks_level_2,
  992. ARRAY_SIZE(sg2042_gate_clks_level_2));
  993. if (ret)
  994. goto error_out;
  995. return devm_of_clk_add_hw_provider(&pdev->dev,
  996. of_clk_hw_onecell_get,
  997. &clk_data->onecell_data);
  998. error_out:
  999. pr_err("%s failed error number %d\n", __func__, ret);
  1000. return ret;
  1001. }
  1002. static const struct of_device_id sg2042_clkgen_match[] = {
  1003. { .compatible = "sophgo,sg2042-clkgen" },
  1004. { /* sentinel */ }
  1005. };
  1006. MODULE_DEVICE_TABLE(of, sg2042_clkgen_match);
  1007. static struct platform_driver sg2042_clkgen_driver = {
  1008. .probe = sg2042_clkgen_probe,
  1009. .driver = {
  1010. .name = "clk-sophgo-sg2042-clkgen",
  1011. .of_match_table = sg2042_clkgen_match,
  1012. .suppress_bind_attrs = true,
  1013. },
  1014. };
  1015. module_platform_driver(sg2042_clkgen_driver);
  1016. MODULE_AUTHOR("Chen Wang");
  1017. MODULE_DESCRIPTION("Sophgo SG2042 clock generator driver");
  1018. MODULE_LICENSE("GPL");