dsi_pll_8996.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
  4. */
  5. #define pr_fmt(fmt) "%s: " fmt, __func__
  6. #include <linux/kernel.h>
  7. #include <linux/err.h>
  8. #include <linux/delay.h>
  9. #include <linux/clk/msm-clk-provider.h>
  10. #include <linux/clk/msm-clk.h>
  11. #include <linux/workqueue.h>
  12. #include <linux/clk/msm-clock-generic.h>
  13. #include <dt-bindings/clock/msm-clocks-8996.h>
  14. #include "pll_drv.h"
  15. #include "dsi_pll.h"
  16. #include "dsi_pll_8996.h"
  17. #define VCO_DELAY_USEC 1
  18. static struct dsi_pll_db pll_db[DSI_PLL_NUM];
  19. static const struct clk_ops n2_clk_src_ops;
  20. static const struct clk_ops shadow_n2_clk_src_ops;
  21. static const struct clk_ops byte_clk_src_ops;
  22. static const struct clk_ops post_n1_div_clk_src_ops;
  23. static const struct clk_ops shadow_post_n1_div_clk_src_ops;
  24. static const struct clk_ops clk_ops_gen_mux_dsi;
  25. /* Op structures */
  26. static const struct clk_ops clk_ops_dsi_vco = {
  27. .set_rate = pll_vco_set_rate_8996,
  28. .round_rate = pll_vco_round_rate_8996,
  29. .handoff = pll_vco_handoff_8996,
  30. .prepare = pll_vco_prepare_8996,
  31. .unprepare = pll_vco_unprepare_8996,
  32. };
  33. static struct clk_div_ops post_n1_div_ops = {
  34. .set_div = post_n1_div_set_div,
  35. .get_div = post_n1_div_get_div,
  36. };
  37. static struct clk_div_ops n2_div_ops = { /* hr_oclk3 */
  38. .set_div = n2_div_set_div,
  39. .get_div = n2_div_get_div,
  40. };
  41. static struct clk_mux_ops mdss_byte_mux_ops = {
  42. .set_mux_sel = set_mdss_byte_mux_sel_8996,
  43. .get_mux_sel = get_mdss_byte_mux_sel_8996,
  44. };
  45. static struct clk_mux_ops mdss_pixel_mux_ops = {
  46. .set_mux_sel = set_mdss_pixel_mux_sel_8996,
  47. .get_mux_sel = get_mdss_pixel_mux_sel_8996,
  48. };
  49. /* Shadow ops for dynamic refresh */
  50. static const struct clk_ops clk_ops_shadow_dsi_vco = {
  51. .set_rate = shadow_pll_vco_set_rate_8996,
  52. .round_rate = pll_vco_round_rate_8996,
  53. .handoff = shadow_pll_vco_handoff_8996,
  54. };
  55. static struct clk_div_ops shadow_post_n1_div_ops = {
  56. .set_div = post_n1_div_set_div,
  57. };
  58. static struct clk_div_ops shadow_n2_div_ops = {
  59. .set_div = shadow_n2_div_set_div,
  60. };
  61. static struct dsi_pll_vco_clk dsi0pll_vco_clk = {
  62. .ref_clk_rate = 19200000UL,
  63. .min_rate = 1300000000UL,
  64. .max_rate = 2600000000UL,
  65. .pll_en_seq_cnt = 1,
  66. .pll_enable_seqs[0] = dsi_pll_enable_seq_8996,
  67. .c = {
  68. .dbg_name = "dsi0pll_vco_clk_8996",
  69. .ops = &clk_ops_dsi_vco,
  70. CLK_INIT(dsi0pll_vco_clk.c),
  71. },
  72. };
  73. static struct dsi_pll_vco_clk dsi0pll_shadow_vco_clk = {
  74. .ref_clk_rate = 19200000u,
  75. .min_rate = 1300000000u,
  76. .max_rate = 2600000000u,
  77. .c = {
  78. .dbg_name = "dsi0pll_shadow_vco_clk",
  79. .ops = &clk_ops_shadow_dsi_vco,
  80. CLK_INIT(dsi0pll_shadow_vco_clk.c),
  81. },
  82. };
  83. static struct dsi_pll_vco_clk dsi1pll_vco_clk = {
  84. .ref_clk_rate = 19200000UL,
  85. .min_rate = 1300000000UL,
  86. .max_rate = 2600000000UL,
  87. .pll_en_seq_cnt = 1,
  88. .pll_enable_seqs[0] = dsi_pll_enable_seq_8996,
  89. .c = {
  90. .dbg_name = "dsi1pll_vco_clk_8996",
  91. .ops = &clk_ops_dsi_vco,
  92. CLK_INIT(dsi1pll_vco_clk.c),
  93. },
  94. };
  95. static struct dsi_pll_vco_clk dsi1pll_shadow_vco_clk = {
  96. .ref_clk_rate = 19200000u,
  97. .min_rate = 1300000000u,
  98. .max_rate = 2600000000u,
  99. .pll_en_seq_cnt = 1,
  100. .pll_enable_seqs[0] = dsi_pll_enable_seq_8996,
  101. .c = {
  102. .dbg_name = "dsi1pll_shadow_vco_clk",
  103. .ops = &clk_ops_shadow_dsi_vco,
  104. CLK_INIT(dsi1pll_shadow_vco_clk.c),
  105. },
  106. };
  107. static struct div_clk dsi0pll_post_n1_div_clk = {
  108. .data = {
  109. .max_div = 15,
  110. .min_div = 1,
  111. },
  112. .ops = &post_n1_div_ops,
  113. .c = {
  114. .parent = &dsi0pll_vco_clk.c,
  115. .dbg_name = "dsi0pll_post_n1_div_clk",
  116. .ops = &post_n1_div_clk_src_ops,
  117. .flags = CLKFLAG_NO_RATE_CACHE,
  118. CLK_INIT(dsi0pll_post_n1_div_clk.c),
  119. },
  120. };
  121. static struct div_clk dsi0pll_shadow_post_n1_div_clk = {
  122. .data = {
  123. .max_div = 15,
  124. .min_div = 1,
  125. },
  126. .ops = &shadow_post_n1_div_ops,
  127. .c = {
  128. .parent = &dsi0pll_shadow_vco_clk.c,
  129. .dbg_name = "dsi0pll_shadow_post_n1_div_clk",
  130. .ops = &shadow_post_n1_div_clk_src_ops,
  131. .flags = CLKFLAG_NO_RATE_CACHE,
  132. CLK_INIT(dsi0pll_shadow_post_n1_div_clk.c),
  133. },
  134. };
  135. static struct div_clk dsi1pll_post_n1_div_clk = {
  136. .data = {
  137. .max_div = 15,
  138. .min_div = 1,
  139. },
  140. .ops = &post_n1_div_ops,
  141. .c = {
  142. .parent = &dsi1pll_vco_clk.c,
  143. .dbg_name = "dsi1pll_post_n1_div_clk",
  144. .ops = &post_n1_div_clk_src_ops,
  145. .flags = CLKFLAG_NO_RATE_CACHE,
  146. CLK_INIT(dsi1pll_post_n1_div_clk.c),
  147. },
  148. };
  149. static struct div_clk dsi1pll_shadow_post_n1_div_clk = {
  150. .data = {
  151. .max_div = 15,
  152. .min_div = 1,
  153. },
  154. .ops = &shadow_post_n1_div_ops,
  155. .c = {
  156. .parent = &dsi1pll_shadow_vco_clk.c,
  157. .dbg_name = "dsi1pll_shadow_post_n1_div_clk",
  158. .ops = &shadow_post_n1_div_clk_src_ops,
  159. .flags = CLKFLAG_NO_RATE_CACHE,
  160. CLK_INIT(dsi1pll_shadow_post_n1_div_clk.c),
  161. },
  162. };
  163. static struct div_clk dsi0pll_n2_div_clk = {
  164. .data = {
  165. .max_div = 15,
  166. .min_div = 1,
  167. },
  168. .ops = &n2_div_ops,
  169. .c = {
  170. .parent = &dsi0pll_post_n1_div_clk.c,
  171. .dbg_name = "dsi0pll_n2_div_clk",
  172. .ops = &n2_clk_src_ops,
  173. .flags = CLKFLAG_NO_RATE_CACHE,
  174. CLK_INIT(dsi0pll_n2_div_clk.c),
  175. },
  176. };
  177. static struct div_clk dsi0pll_shadow_n2_div_clk = {
  178. .data = {
  179. .max_div = 15,
  180. .min_div = 1,
  181. },
  182. .ops = &shadow_n2_div_ops,
  183. .c = {
  184. .parent = &dsi0pll_shadow_post_n1_div_clk.c,
  185. .dbg_name = "dsi0pll_shadow_n2_div_clk",
  186. .ops = &shadow_n2_clk_src_ops,
  187. .flags = CLKFLAG_NO_RATE_CACHE,
  188. CLK_INIT(dsi0pll_shadow_n2_div_clk.c),
  189. },
  190. };
  191. static struct div_clk dsi1pll_n2_div_clk = {
  192. .data = {
  193. .max_div = 15,
  194. .min_div = 1,
  195. },
  196. .ops = &n2_div_ops,
  197. .c = {
  198. .parent = &dsi1pll_post_n1_div_clk.c,
  199. .dbg_name = "dsi1pll_n2_div_clk",
  200. .ops = &n2_clk_src_ops,
  201. .flags = CLKFLAG_NO_RATE_CACHE,
  202. CLK_INIT(dsi1pll_n2_div_clk.c),
  203. },
  204. };
  205. static struct div_clk dsi1pll_shadow_n2_div_clk = {
  206. .data = {
  207. .max_div = 15,
  208. .min_div = 1,
  209. },
  210. .ops = &shadow_n2_div_ops,
  211. .c = {
  212. .parent = &dsi1pll_shadow_post_n1_div_clk.c,
  213. .dbg_name = "dsi1pll_shadow_n2_div_clk",
  214. .ops = &shadow_n2_clk_src_ops,
  215. .flags = CLKFLAG_NO_RATE_CACHE,
  216. CLK_INIT(dsi1pll_shadow_n2_div_clk.c),
  217. },
  218. };
  219. static struct div_clk dsi0pll_pixel_clk_src = {
  220. .data = {
  221. .div = 2,
  222. .min_div = 2,
  223. .max_div = 2,
  224. },
  225. .c = {
  226. .parent = &dsi0pll_n2_div_clk.c,
  227. .dbg_name = "dsi0pll_pixel_clk_src",
  228. .ops = &clk_ops_div,
  229. .flags = CLKFLAG_NO_RATE_CACHE,
  230. CLK_INIT(dsi0pll_pixel_clk_src.c),
  231. },
  232. };
  233. static struct div_clk dsi0pll_shadow_pixel_clk_src = {
  234. .data = {
  235. .div = 2,
  236. .min_div = 2,
  237. .max_div = 2,
  238. },
  239. .c = {
  240. .parent = &dsi0pll_shadow_n2_div_clk.c,
  241. .dbg_name = "dsi0pll_shadow_pixel_clk_src",
  242. .ops = &clk_ops_div,
  243. .flags = CLKFLAG_NO_RATE_CACHE,
  244. CLK_INIT(dsi0pll_shadow_pixel_clk_src.c),
  245. },
  246. };
  247. static struct div_clk dsi1pll_pixel_clk_src = {
  248. .data = {
  249. .div = 2,
  250. .min_div = 2,
  251. .max_div = 2,
  252. },
  253. .c = {
  254. .parent = &dsi1pll_n2_div_clk.c,
  255. .dbg_name = "dsi1pll_pixel_clk_src",
  256. .ops = &clk_ops_div,
  257. .flags = CLKFLAG_NO_RATE_CACHE,
  258. CLK_INIT(dsi1pll_pixel_clk_src.c),
  259. },
  260. };
  261. static struct div_clk dsi1pll_shadow_pixel_clk_src = {
  262. .data = {
  263. .div = 2,
  264. .min_div = 2,
  265. .max_div = 2,
  266. },
  267. .c = {
  268. .parent = &dsi1pll_shadow_n2_div_clk.c,
  269. .dbg_name = "dsi1pll_shadow_pixel_clk_src",
  270. .ops = &clk_ops_div,
  271. .flags = CLKFLAG_NO_RATE_CACHE,
  272. CLK_INIT(dsi1pll_shadow_pixel_clk_src.c),
  273. },
  274. };
  275. static struct mux_clk dsi0pll_pixel_clk_mux = {
  276. .num_parents = 2,
  277. .parents = (struct clk_src[]) {
  278. {&dsi0pll_pixel_clk_src.c, 0},
  279. {&dsi0pll_shadow_pixel_clk_src.c, 1},
  280. },
  281. .ops = &mdss_pixel_mux_ops,
  282. .c = {
  283. .parent = &dsi0pll_pixel_clk_src.c,
  284. .dbg_name = "dsi0pll_pixel_clk_mux",
  285. .ops = &clk_ops_gen_mux_dsi,
  286. .flags = CLKFLAG_NO_RATE_CACHE,
  287. CLK_INIT(dsi0pll_pixel_clk_mux.c),
  288. }
  289. };
  290. static struct mux_clk dsi1pll_pixel_clk_mux = {
  291. .num_parents = 2,
  292. .parents = (struct clk_src[]) {
  293. {&dsi1pll_pixel_clk_src.c, 0},
  294. {&dsi1pll_shadow_pixel_clk_src.c, 1},
  295. },
  296. .ops = &mdss_pixel_mux_ops,
  297. .c = {
  298. .parent = &dsi1pll_pixel_clk_src.c,
  299. .dbg_name = "dsi1pll_pixel_clk_mux",
  300. .ops = &clk_ops_gen_mux_dsi,
  301. .flags = CLKFLAG_NO_RATE_CACHE,
  302. CLK_INIT(dsi1pll_pixel_clk_mux.c),
  303. }
  304. };
  305. static struct div_clk dsi0pll_byte_clk_src = {
  306. .data = {
  307. .div = 8,
  308. .min_div = 8,
  309. .max_div = 8,
  310. },
  311. .c = {
  312. .parent = &dsi0pll_post_n1_div_clk.c,
  313. .dbg_name = "dsi0pll_byte_clk_src",
  314. .ops = &clk_ops_div,
  315. CLK_INIT(dsi0pll_byte_clk_src.c),
  316. },
  317. };
  318. static struct div_clk dsi0pll_shadow_byte_clk_src = {
  319. .data = {
  320. .div = 8,
  321. .min_div = 8,
  322. .max_div = 8,
  323. },
  324. .c = {
  325. .parent = &dsi0pll_shadow_post_n1_div_clk.c,
  326. .dbg_name = "dsi0pll_shadow_byte_clk_src",
  327. .ops = &clk_ops_div,
  328. CLK_INIT(dsi0pll_shadow_byte_clk_src.c),
  329. },
  330. };
  331. static struct div_clk dsi1pll_byte_clk_src = {
  332. .data = {
  333. .div = 8,
  334. .min_div = 8,
  335. .max_div = 8,
  336. },
  337. .c = {
  338. .parent = &dsi1pll_post_n1_div_clk.c,
  339. .dbg_name = "dsi1pll_byte_clk_src",
  340. .ops = &clk_ops_div,
  341. CLK_INIT(dsi1pll_byte_clk_src.c),
  342. },
  343. };
  344. static struct div_clk dsi1pll_shadow_byte_clk_src = {
  345. .data = {
  346. .div = 8,
  347. .min_div = 8,
  348. .max_div = 8,
  349. },
  350. .c = {
  351. .parent = &dsi1pll_shadow_post_n1_div_clk.c,
  352. .dbg_name = "dsi1pll_shadow_byte_clk_src",
  353. .ops = &clk_ops_div,
  354. CLK_INIT(dsi1pll_shadow_byte_clk_src.c),
  355. },
  356. };
  357. static struct mux_clk dsi0pll_byte_clk_mux = {
  358. .num_parents = 2,
  359. .parents = (struct clk_src[]) {
  360. {&dsi0pll_byte_clk_src.c, 0},
  361. {&dsi0pll_shadow_byte_clk_src.c, 1},
  362. },
  363. .ops = &mdss_byte_mux_ops,
  364. .c = {
  365. .parent = &dsi0pll_byte_clk_src.c,
  366. .dbg_name = "dsi0pll_byte_clk_mux",
  367. .ops = &clk_ops_gen_mux_dsi,
  368. .flags = CLKFLAG_NO_RATE_CACHE,
  369. CLK_INIT(dsi0pll_byte_clk_mux.c),
  370. }
  371. };
  372. static struct mux_clk dsi1pll_byte_clk_mux = {
  373. .num_parents = 2,
  374. .parents = (struct clk_src[]) {
  375. {&dsi1pll_byte_clk_src.c, 0},
  376. {&dsi1pll_shadow_byte_clk_src.c, 1},
  377. },
  378. .ops = &mdss_byte_mux_ops,
  379. .c = {
  380. .parent = &dsi1pll_byte_clk_src.c,
  381. .dbg_name = "dsi1pll_byte_clk_mux",
  382. .ops = &clk_ops_gen_mux_dsi,
  383. .flags = CLKFLAG_NO_RATE_CACHE,
  384. CLK_INIT(dsi1pll_byte_clk_mux.c),
  385. }
  386. };
  387. static struct clk_lookup mdss_dsi_pllcc_8996[] = {
  388. CLK_LIST(dsi0pll_byte_clk_mux),
  389. CLK_LIST(dsi0pll_byte_clk_src),
  390. CLK_LIST(dsi0pll_pixel_clk_mux),
  391. CLK_LIST(dsi0pll_pixel_clk_src),
  392. CLK_LIST(dsi0pll_n2_div_clk),
  393. CLK_LIST(dsi0pll_post_n1_div_clk),
  394. CLK_LIST(dsi0pll_vco_clk),
  395. CLK_LIST(dsi0pll_shadow_byte_clk_src),
  396. CLK_LIST(dsi0pll_shadow_pixel_clk_src),
  397. CLK_LIST(dsi0pll_shadow_n2_div_clk),
  398. CLK_LIST(dsi0pll_shadow_post_n1_div_clk),
  399. CLK_LIST(dsi0pll_shadow_vco_clk),
  400. };
  401. static struct clk_lookup mdss_dsi_pllcc_8996_1[] = {
  402. CLK_LIST(dsi1pll_byte_clk_mux),
  403. CLK_LIST(dsi1pll_byte_clk_src),
  404. CLK_LIST(dsi1pll_pixel_clk_mux),
  405. CLK_LIST(dsi1pll_pixel_clk_src),
  406. CLK_LIST(dsi1pll_n2_div_clk),
  407. CLK_LIST(dsi1pll_post_n1_div_clk),
  408. CLK_LIST(dsi1pll_vco_clk),
  409. CLK_LIST(dsi1pll_shadow_byte_clk_src),
  410. CLK_LIST(dsi1pll_shadow_pixel_clk_src),
  411. CLK_LIST(dsi1pll_shadow_n2_div_clk),
  412. CLK_LIST(dsi1pll_shadow_post_n1_div_clk),
  413. CLK_LIST(dsi1pll_shadow_vco_clk),
  414. };
  415. int dsi_pll_clock_register_8996(struct platform_device *pdev,
  416. struct mdss_pll_resources *pll_res)
  417. {
  418. int rc = 0, ndx;
  419. int const ssc_freq_default = 31500; /* default h/w recommended value */
  420. int const ssc_ppm_default = 5000; /* default h/w recommended value */
  421. struct dsi_pll_db *pdb;
  422. if (pll_res->index >= DSI_PLL_NUM) {
  423. pr_err("pll ndx=%d is NOT supported\n", pll_res->index);
  424. return -EINVAL;
  425. }
  426. ndx = pll_res->index;
  427. pdb = &pll_db[ndx];
  428. pll_res->priv = pdb;
  429. pdb->pll = pll_res;
  430. ndx++;
  431. ndx %= DSI_PLL_NUM;
  432. pdb->next = &pll_db[ndx];
  433. /* Set clock source operations */
  434. /* hr_oclk3, pixel */
  435. n2_clk_src_ops = clk_ops_slave_div;
  436. n2_clk_src_ops.prepare = mdss_pll_div_prepare;
  437. shadow_n2_clk_src_ops = clk_ops_slave_div;
  438. /* hr_ockl2, byte, vco pll */
  439. post_n1_div_clk_src_ops = clk_ops_div;
  440. post_n1_div_clk_src_ops.prepare = mdss_pll_div_prepare;
  441. shadow_post_n1_div_clk_src_ops = clk_ops_div;
  442. byte_clk_src_ops = clk_ops_div;
  443. byte_clk_src_ops.prepare = mdss_pll_div_prepare;
  444. clk_ops_gen_mux_dsi = clk_ops_gen_mux;
  445. clk_ops_gen_mux_dsi.round_rate = parent_round_rate;
  446. clk_ops_gen_mux_dsi.set_rate = parent_set_rate;
  447. if (pll_res->ssc_en) {
  448. if (!pll_res->ssc_freq)
  449. pll_res->ssc_freq = ssc_freq_default;
  450. if (!pll_res->ssc_ppm)
  451. pll_res->ssc_ppm = ssc_ppm_default;
  452. }
  453. /* Set client data to mux, div and vco clocks. */
  454. if (pll_res->index == DSI_PLL_1) {
  455. dsi1pll_byte_clk_src.priv = pll_res;
  456. dsi1pll_pixel_clk_src.priv = pll_res;
  457. dsi1pll_post_n1_div_clk.priv = pll_res;
  458. dsi1pll_n2_div_clk.priv = pll_res;
  459. dsi1pll_vco_clk.priv = pll_res;
  460. dsi1pll_shadow_byte_clk_src.priv = pll_res;
  461. dsi1pll_shadow_pixel_clk_src.priv = pll_res;
  462. dsi1pll_shadow_post_n1_div_clk.priv = pll_res;
  463. dsi1pll_shadow_n2_div_clk.priv = pll_res;
  464. dsi1pll_shadow_vco_clk.priv = pll_res;
  465. pll_res->vco_delay = VCO_DELAY_USEC;
  466. rc = of_msm_clock_register(pdev->dev.of_node,
  467. mdss_dsi_pllcc_8996_1,
  468. ARRAY_SIZE(mdss_dsi_pllcc_8996_1));
  469. } else {
  470. dsi0pll_byte_clk_src.priv = pll_res;
  471. dsi0pll_pixel_clk_src.priv = pll_res;
  472. dsi0pll_post_n1_div_clk.priv = pll_res;
  473. dsi0pll_n2_div_clk.priv = pll_res;
  474. dsi0pll_vco_clk.priv = pll_res;
  475. dsi0pll_shadow_byte_clk_src.priv = pll_res;
  476. dsi0pll_shadow_pixel_clk_src.priv = pll_res;
  477. dsi0pll_shadow_post_n1_div_clk.priv = pll_res;
  478. dsi0pll_shadow_n2_div_clk.priv = pll_res;
  479. dsi0pll_shadow_vco_clk.priv = pll_res;
  480. pll_res->vco_delay = VCO_DELAY_USEC;
  481. rc = of_msm_clock_register(pdev->dev.of_node,
  482. mdss_dsi_pllcc_8996,
  483. ARRAY_SIZE(mdss_dsi_pllcc_8996));
  484. }
  485. if (!rc) {
  486. pr_info("Registered DSI PLL ndx=%d clocks successfully\n",
  487. pll_res->index);
  488. }
  489. return rc;
  490. }