lpassaudiocc-sc7280.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2021, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/clk-provider.h>
  6. #include <linux/err.h>
  7. #include <linux/kernel.h>
  8. #include <linux/module.h>
  9. #include <linux/of_device.h>
  10. #include <linux/pm_clock.h>
  11. #include <linux/pm_runtime.h>
  12. #include <linux/regmap.h>
  13. #include <dt-bindings/clock/qcom,lpass-sc7280.h>
  14. #include <dt-bindings/clock/qcom,lpassaudiocc-sc7280.h>
  15. #include "clk-alpha-pll.h"
  16. #include "clk-branch.h"
  17. #include "clk-rcg.h"
  18. #include "clk-regmap.h"
  19. #include "clk-regmap-divider.h"
  20. #include "clk-regmap-mux.h"
  21. #include "common.h"
  22. #include "gdsc.h"
  23. #include "reset.h"
  24. enum {
  25. P_BI_TCXO,
  26. P_LPASS_AON_CC_PLL_OUT_EVEN,
  27. P_LPASS_AON_CC_PLL_OUT_MAIN,
  28. P_LPASS_AON_CC_PLL_OUT_MAIN_CDIV_DIV_CLK_SRC,
  29. P_LPASS_AON_CC_PLL_OUT_ODD,
  30. P_LPASS_AUDIO_CC_PLL_OUT_AUX,
  31. P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC,
  32. P_LPASS_AUDIO_CC_PLL_MAIN_DIV_CLK,
  33. };
  34. static const struct pll_vco zonda_vco[] = {
  35. { 595200000UL, 3600000000UL, 0 },
  36. };
  37. static struct clk_branch lpass_q6ss_ahbm_clk = {
  38. .halt_reg = 0x901c,
  39. .halt_check = BRANCH_HALT,
  40. .clkr = {
  41. .enable_reg = 0x901c,
  42. .enable_mask = BIT(0),
  43. .hw.init = &(struct clk_init_data){
  44. .name = "lpass_q6ss_ahbm_clk",
  45. .ops = &clk_branch2_ops,
  46. },
  47. },
  48. };
  49. static struct clk_branch lpass_q6ss_ahbs_clk = {
  50. .halt_reg = 0x9020,
  51. .halt_check = BRANCH_HALT_VOTED,
  52. .clkr = {
  53. .enable_reg = 0x9020,
  54. .enable_mask = BIT(0),
  55. .hw.init = &(struct clk_init_data){
  56. .name = "lpass_q6ss_ahbs_clk",
  57. .ops = &clk_branch2_ops,
  58. },
  59. },
  60. };
  61. /* 1128.96MHz configuration */
  62. static const struct alpha_pll_config lpass_audio_cc_pll_config = {
  63. .l = 0x3a,
  64. .alpha = 0xcccc,
  65. .config_ctl_val = 0x08200920,
  66. .config_ctl_hi_val = 0x05002001,
  67. .config_ctl_hi1_val = 0x00000000,
  68. .user_ctl_val = 0x03000101,
  69. };
  70. static struct clk_alpha_pll lpass_audio_cc_pll = {
  71. .offset = 0x0,
  72. .vco_table = zonda_vco,
  73. .num_vco = ARRAY_SIZE(zonda_vco),
  74. .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_ZONDA],
  75. .clkr = {
  76. .hw.init = &(const struct clk_init_data){
  77. .name = "lpass_audio_cc_pll",
  78. .parent_data = &(const struct clk_parent_data){
  79. .index = 0,
  80. },
  81. .num_parents = 1,
  82. .ops = &clk_alpha_pll_zonda_ops,
  83. },
  84. },
  85. };
  86. static const struct clk_div_table post_div_table_lpass_audio_cc_pll_out_aux2[] = {
  87. { 0x1, 2 },
  88. { }
  89. };
  90. static struct clk_alpha_pll_postdiv lpass_audio_cc_pll_out_aux2 = {
  91. .offset = 0x0,
  92. .post_div_shift = 8,
  93. .post_div_table = post_div_table_lpass_audio_cc_pll_out_aux2,
  94. .num_post_div = ARRAY_SIZE(post_div_table_lpass_audio_cc_pll_out_aux2),
  95. .width = 2,
  96. .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_ZONDA],
  97. .clkr.hw.init = &(const struct clk_init_data){
  98. .name = "lpass_audio_cc_pll_out_aux2",
  99. .parent_hws = (const struct clk_hw*[]){
  100. &lpass_audio_cc_pll.clkr.hw,
  101. },
  102. .num_parents = 1,
  103. .ops = &clk_alpha_pll_postdiv_zonda_ops,
  104. },
  105. };
  106. static const struct pll_vco lucid_vco[] = {
  107. { 249600000, 2000000000, 0 },
  108. };
  109. /* 614.4 MHz configuration */
  110. static const struct alpha_pll_config lpass_aon_cc_pll_config = {
  111. .l = 0x20,
  112. .alpha = 0x0,
  113. .config_ctl_val = 0x20485699,
  114. .config_ctl_hi_val = 0x00002261,
  115. .config_ctl_hi1_val = 0x329A299C,
  116. .user_ctl_val = 0x00005100,
  117. .user_ctl_hi_val = 0x00000805,
  118. .user_ctl_hi1_val = 0x00000000,
  119. };
  120. static struct clk_alpha_pll lpass_aon_cc_pll = {
  121. .offset = 0x0,
  122. .vco_table = lucid_vco,
  123. .num_vco = ARRAY_SIZE(lucid_vco),
  124. .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
  125. .clkr = {
  126. .hw.init = &(const struct clk_init_data){
  127. .name = "lpass_aon_cc_pll",
  128. .parent_data = &(const struct clk_parent_data){
  129. .index = 0,
  130. },
  131. .num_parents = 1,
  132. .ops = &clk_alpha_pll_lucid_ops,
  133. },
  134. },
  135. };
  136. static const struct clk_div_table post_div_table_lpass_aon_cc_pll_out_even[] = {
  137. { 0x1, 2 },
  138. { }
  139. };
  140. static struct clk_alpha_pll_postdiv lpass_aon_cc_pll_out_even = {
  141. .offset = 0x0,
  142. .post_div_shift = 8,
  143. .post_div_table = post_div_table_lpass_aon_cc_pll_out_even,
  144. .num_post_div = ARRAY_SIZE(post_div_table_lpass_aon_cc_pll_out_even),
  145. .width = 4,
  146. .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
  147. .clkr.hw.init = &(const struct clk_init_data){
  148. .name = "lpass_aon_cc_pll_out_even",
  149. .parent_hws = (const struct clk_hw*[]){
  150. &lpass_aon_cc_pll.clkr.hw,
  151. },
  152. .num_parents = 1,
  153. .ops = &clk_alpha_pll_postdiv_lucid_ops,
  154. },
  155. };
  156. static const struct clk_div_table post_div_table_lpass_aon_cc_pll_out_odd[] = {
  157. { 0x5, 5 },
  158. { }
  159. };
  160. static struct clk_alpha_pll_postdiv lpass_aon_cc_pll_out_odd = {
  161. .offset = 0x0,
  162. .post_div_shift = 12,
  163. .post_div_table = post_div_table_lpass_aon_cc_pll_out_odd,
  164. .num_post_div = ARRAY_SIZE(post_div_table_lpass_aon_cc_pll_out_odd),
  165. .width = 4,
  166. .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
  167. .clkr.hw.init = &(const struct clk_init_data){
  168. .name = "lpass_aon_cc_pll_out_odd",
  169. .parent_hws = (const struct clk_hw*[]){
  170. &lpass_aon_cc_pll.clkr.hw,
  171. },
  172. .num_parents = 1,
  173. .ops = &clk_alpha_pll_postdiv_lucid_ops,
  174. },
  175. };
  176. static const struct parent_map lpass_audio_cc_parent_map_0[] = {
  177. { P_BI_TCXO, 0 },
  178. { P_LPASS_AUDIO_CC_PLL_OUT_AUX, 3 },
  179. { P_LPASS_AON_CC_PLL_OUT_ODD, 5 },
  180. { P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 6 },
  181. };
  182. static struct clk_regmap_div lpass_audio_cc_pll_out_aux2_div_clk_src;
  183. static struct clk_regmap_div lpass_audio_cc_pll_out_main_div_clk_src;
  184. static const struct clk_parent_data lpass_audio_cc_parent_data_0[] = {
  185. { .index = 0 },
  186. { .hw = &lpass_audio_cc_pll.clkr.hw },
  187. { .hw = &lpass_aon_cc_pll_out_odd.clkr.hw },
  188. { .hw = &lpass_audio_cc_pll_out_aux2_div_clk_src.clkr.hw },
  189. };
  190. static const struct parent_map lpass_aon_cc_parent_map_0[] = {
  191. { P_BI_TCXO, 0 },
  192. { P_LPASS_AON_CC_PLL_OUT_EVEN, 4 },
  193. };
  194. static const struct clk_parent_data lpass_aon_cc_parent_data_0[] = {
  195. { .index = 0 },
  196. { .hw = &lpass_aon_cc_pll_out_even.clkr.hw },
  197. };
  198. static const struct parent_map lpass_aon_cc_parent_map_1[] = {
  199. { P_BI_TCXO, 0 },
  200. { P_LPASS_AON_CC_PLL_OUT_ODD, 1 },
  201. { P_LPASS_AUDIO_CC_PLL_MAIN_DIV_CLK, 6 },
  202. };
  203. static const struct clk_parent_data lpass_aon_cc_parent_data_1[] = {
  204. { .index = 0 },
  205. { .hw = &lpass_aon_cc_pll_out_odd.clkr.hw },
  206. { .hw = &lpass_audio_cc_pll_out_main_div_clk_src.clkr.hw },
  207. };
  208. static const struct freq_tbl ftbl_lpass_aon_cc_main_rcg_clk_src[] = {
  209. F(38400000, P_LPASS_AON_CC_PLL_OUT_EVEN, 8, 0, 0),
  210. F(76800000, P_LPASS_AON_CC_PLL_OUT_EVEN, 4, 0, 0),
  211. F(153600000, P_LPASS_AON_CC_PLL_OUT_EVEN, 2, 0, 0),
  212. { }
  213. };
  214. static struct clk_rcg2 lpass_aon_cc_main_rcg_clk_src = {
  215. .cmd_rcgr = 0x1000,
  216. .mnd_width = 0,
  217. .hid_width = 5,
  218. .parent_map = lpass_aon_cc_parent_map_0,
  219. .freq_tbl = ftbl_lpass_aon_cc_main_rcg_clk_src,
  220. .clkr.hw.init = &(const struct clk_init_data){
  221. .name = "lpass_aon_cc_main_rcg_clk_src",
  222. .parent_data = lpass_aon_cc_parent_data_0,
  223. .num_parents = ARRAY_SIZE(lpass_aon_cc_parent_data_0),
  224. .flags = CLK_OPS_PARENT_ENABLE,
  225. .ops = &clk_rcg2_shared_ops,
  226. },
  227. };
  228. static const struct freq_tbl ftbl_lpass_aon_cc_tx_mclk_rcg_clk_src[] = {
  229. F(19200000, P_BI_TCXO, 1, 0, 0),
  230. F(24576000, P_LPASS_AON_CC_PLL_OUT_ODD, 5, 0, 0),
  231. { }
  232. };
  233. static struct clk_rcg2 lpass_aon_cc_tx_mclk_rcg_clk_src = {
  234. .cmd_rcgr = 0x13004,
  235. .mnd_width = 0,
  236. .hid_width = 5,
  237. .parent_map = lpass_aon_cc_parent_map_1,
  238. .freq_tbl = ftbl_lpass_aon_cc_tx_mclk_rcg_clk_src,
  239. .clkr.hw.init = &(const struct clk_init_data){
  240. .name = "lpass_aon_cc_tx_mclk_rcg_clk_src",
  241. .parent_data = lpass_aon_cc_parent_data_1,
  242. .num_parents = ARRAY_SIZE(lpass_aon_cc_parent_data_1),
  243. .ops = &clk_rcg2_ops,
  244. },
  245. };
  246. static struct clk_regmap_div lpass_audio_cc_pll_out_aux2_div_clk_src = {
  247. .reg = 0x48,
  248. .shift = 0,
  249. .width = 4,
  250. .clkr.hw.init = &(const struct clk_init_data) {
  251. .name = "lpass_audio_cc_pll_out_aux2_div_clk_src",
  252. .parent_hws = (const struct clk_hw*[]){
  253. &lpass_audio_cc_pll_out_aux2.clkr.hw,
  254. },
  255. .num_parents = 1,
  256. .flags = CLK_SET_RATE_PARENT,
  257. .ops = &clk_regmap_div_ro_ops,
  258. },
  259. };
  260. static struct clk_regmap_div lpass_audio_cc_pll_out_main_div_clk_src = {
  261. .reg = 0x3c,
  262. .shift = 0,
  263. .width = 4,
  264. .clkr.hw.init = &(const struct clk_init_data) {
  265. .name = "lpass_audio_cc_pll_out_main_div_clk_src",
  266. .parent_hws = (const struct clk_hw*[]){
  267. &lpass_audio_cc_pll.clkr.hw,
  268. },
  269. .num_parents = 1,
  270. .flags = CLK_SET_RATE_PARENT,
  271. .ops = &clk_regmap_div_ro_ops,
  272. },
  273. };
  274. static struct clk_regmap_div lpass_aon_cc_cdiv_tx_mclk_div_clk_src = {
  275. .reg = 0x13010,
  276. .shift = 0,
  277. .width = 4,
  278. .clkr.hw.init = &(const struct clk_init_data) {
  279. .name = "lpass_aon_cc_cdiv_tx_mclk_div_clk_src",
  280. .parent_hws = (const struct clk_hw*[]){
  281. &lpass_aon_cc_tx_mclk_rcg_clk_src.clkr.hw,
  282. },
  283. .num_parents = 1,
  284. .flags = CLK_SET_RATE_PARENT,
  285. .ops = &clk_regmap_div_ro_ops,
  286. },
  287. };
  288. static struct clk_regmap_div lpass_aon_cc_pll_out_main_cdiv_div_clk_src = {
  289. .reg = 0x80,
  290. .shift = 0,
  291. .width = 4,
  292. .clkr.hw.init = &(const struct clk_init_data) {
  293. .name = "lpass_aon_cc_pll_out_main_cdiv_div_clk_src",
  294. .parent_hws = (const struct clk_hw*[]){
  295. &lpass_aon_cc_pll.clkr.hw,
  296. },
  297. .num_parents = 1,
  298. .flags = CLK_SET_RATE_PARENT,
  299. .ops = &clk_regmap_div_ro_ops,
  300. },
  301. };
  302. static const struct freq_tbl ftbl_lpass_audio_cc_ext_mclk0_clk_src[] = {
  303. F(256000, P_LPASS_AON_CC_PLL_OUT_ODD, 15, 1, 32),
  304. F(352800, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 32),
  305. F(512000, P_LPASS_AON_CC_PLL_OUT_ODD, 15, 1, 16),
  306. F(705600, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 16),
  307. F(768000, P_LPASS_AON_CC_PLL_OUT_ODD, 10, 1, 16),
  308. F(1024000, P_LPASS_AON_CC_PLL_OUT_ODD, 15, 1, 8),
  309. F(1411200, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 8),
  310. F(1536000, P_LPASS_AON_CC_PLL_OUT_ODD, 10, 1, 8),
  311. F(2048000, P_LPASS_AON_CC_PLL_OUT_ODD, 15, 1, 4),
  312. F(2822400, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 4),
  313. F(3072000, P_LPASS_AON_CC_PLL_OUT_ODD, 10, 1, 4),
  314. F(4096000, P_LPASS_AON_CC_PLL_OUT_ODD, 15, 1, 2),
  315. F(5644800, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 2),
  316. F(6144000, P_LPASS_AON_CC_PLL_OUT_ODD, 10, 1, 2),
  317. F(8192000, P_LPASS_AON_CC_PLL_OUT_ODD, 15, 0, 0),
  318. F(9600000, P_BI_TCXO, 2, 0, 0),
  319. F(11289600, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 0, 0),
  320. F(12288000, P_LPASS_AON_CC_PLL_OUT_ODD, 10, 0, 0),
  321. F(19200000, P_BI_TCXO, 1, 0, 0),
  322. F(22579200, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 5, 0, 0),
  323. F(24576000, P_LPASS_AON_CC_PLL_OUT_ODD, 5, 0, 0),
  324. { }
  325. };
  326. static struct clk_rcg2 lpass_audio_cc_ext_mclk0_clk_src = {
  327. .cmd_rcgr = 0x20004,
  328. .mnd_width = 8,
  329. .hid_width = 5,
  330. .parent_map = lpass_audio_cc_parent_map_0,
  331. .freq_tbl = ftbl_lpass_audio_cc_ext_mclk0_clk_src,
  332. .clkr.hw.init = &(const struct clk_init_data){
  333. .name = "lpass_audio_cc_ext_mclk0_clk_src",
  334. .parent_data = lpass_audio_cc_parent_data_0,
  335. .num_parents = ARRAY_SIZE(lpass_audio_cc_parent_data_0),
  336. .ops = &clk_rcg2_ops,
  337. },
  338. };
  339. static struct clk_rcg2 lpass_audio_cc_ext_mclk1_clk_src = {
  340. .cmd_rcgr = 0x21004,
  341. .mnd_width = 8,
  342. .hid_width = 5,
  343. .parent_map = lpass_audio_cc_parent_map_0,
  344. .freq_tbl = ftbl_lpass_audio_cc_ext_mclk0_clk_src,
  345. .clkr.hw.init = &(const struct clk_init_data){
  346. .name = "lpass_audio_cc_ext_mclk1_clk_src",
  347. .parent_data = lpass_audio_cc_parent_data_0,
  348. .num_parents = ARRAY_SIZE(lpass_audio_cc_parent_data_0),
  349. .ops = &clk_rcg2_ops,
  350. },
  351. };
  352. static struct clk_rcg2 lpass_audio_cc_rx_mclk_clk_src = {
  353. .cmd_rcgr = 0x24004,
  354. .mnd_width = 8,
  355. .hid_width = 5,
  356. .parent_map = lpass_audio_cc_parent_map_0,
  357. .freq_tbl = ftbl_lpass_audio_cc_ext_mclk0_clk_src,
  358. .clkr.hw.init = &(const struct clk_init_data){
  359. .name = "lpass_audio_cc_rx_mclk_clk_src",
  360. .parent_data = lpass_audio_cc_parent_data_0,
  361. .num_parents = ARRAY_SIZE(lpass_audio_cc_parent_data_0),
  362. .ops = &clk_rcg2_ops,
  363. },
  364. };
  365. static struct clk_regmap_div lpass_audio_cc_cdiv_rx_mclk_div_clk_src = {
  366. .reg = 0x240d0,
  367. .shift = 0,
  368. .width = 4,
  369. .clkr.hw.init = &(const struct clk_init_data) {
  370. .name = "lpass_audio_cc_cdiv_rx_mclk_div_clk_src",
  371. .parent_hws = (const struct clk_hw*[]){
  372. &lpass_audio_cc_rx_mclk_clk_src.clkr.hw,
  373. },
  374. .num_parents = 1,
  375. .flags = CLK_SET_RATE_PARENT,
  376. .ops = &clk_regmap_div_ro_ops,
  377. },
  378. };
  379. static struct clk_branch lpass_aon_cc_audio_hm_h_clk;
  380. static struct clk_branch lpass_audio_cc_codec_mem0_clk = {
  381. .halt_reg = 0x1e004,
  382. .halt_check = BRANCH_HALT,
  383. .clkr = {
  384. .enable_reg = 0x1e004,
  385. .enable_mask = BIT(0),
  386. .hw.init = &(const struct clk_init_data){
  387. .name = "lpass_audio_cc_codec_mem0_clk",
  388. .parent_hws = (const struct clk_hw*[]){
  389. &lpass_aon_cc_audio_hm_h_clk.clkr.hw,
  390. },
  391. .num_parents = 1,
  392. .flags = CLK_SET_RATE_PARENT,
  393. .ops = &clk_branch2_ops,
  394. },
  395. },
  396. };
  397. static struct clk_branch lpass_audio_cc_codec_mem1_clk = {
  398. .halt_reg = 0x1e008,
  399. .halt_check = BRANCH_HALT,
  400. .clkr = {
  401. .enable_reg = 0x1e008,
  402. .enable_mask = BIT(0),
  403. .hw.init = &(const struct clk_init_data){
  404. .name = "lpass_audio_cc_codec_mem1_clk",
  405. .parent_hws = (const struct clk_hw*[]){
  406. &lpass_aon_cc_audio_hm_h_clk.clkr.hw,
  407. },
  408. .num_parents = 1,
  409. .flags = CLK_SET_RATE_PARENT,
  410. .ops = &clk_branch2_ops,
  411. },
  412. },
  413. };
  414. static struct clk_branch lpass_audio_cc_codec_mem2_clk = {
  415. .halt_reg = 0x1e00c,
  416. .halt_check = BRANCH_HALT,
  417. .clkr = {
  418. .enable_reg = 0x1e00c,
  419. .enable_mask = BIT(0),
  420. .hw.init = &(const struct clk_init_data){
  421. .name = "lpass_audio_cc_codec_mem2_clk",
  422. .parent_hws = (const struct clk_hw*[]){
  423. &lpass_aon_cc_audio_hm_h_clk.clkr.hw,
  424. },
  425. .num_parents = 1,
  426. .flags = CLK_SET_RATE_PARENT,
  427. .ops = &clk_branch2_ops,
  428. },
  429. },
  430. };
  431. static struct clk_branch lpass_audio_cc_codec_mem_clk = {
  432. .halt_reg = 0x1e000,
  433. .halt_check = BRANCH_HALT,
  434. .clkr = {
  435. .enable_reg = 0x1e000,
  436. .enable_mask = BIT(0),
  437. .hw.init = &(const struct clk_init_data){
  438. .name = "lpass_audio_cc_codec_mem_clk",
  439. .parent_hws = (const struct clk_hw*[]){
  440. &lpass_aon_cc_audio_hm_h_clk.clkr.hw,
  441. },
  442. .num_parents = 1,
  443. .flags = CLK_SET_RATE_PARENT,
  444. .ops = &clk_branch2_ops,
  445. },
  446. },
  447. };
  448. static struct clk_branch lpass_audio_cc_ext_mclk0_clk = {
  449. .halt_reg = 0x20018,
  450. .halt_check = BRANCH_HALT,
  451. .clkr = {
  452. .enable_reg = 0x20018,
  453. .enable_mask = BIT(0),
  454. .hw.init = &(const struct clk_init_data){
  455. .name = "lpass_audio_cc_ext_mclk0_clk",
  456. .parent_hws = (const struct clk_hw*[]){
  457. &lpass_audio_cc_ext_mclk0_clk_src.clkr.hw,
  458. },
  459. .num_parents = 1,
  460. .flags = CLK_SET_RATE_PARENT,
  461. .ops = &clk_branch2_ops,
  462. },
  463. },
  464. };
  465. static struct clk_branch lpass_audio_cc_ext_mclk1_clk = {
  466. .halt_reg = 0x21018,
  467. .halt_check = BRANCH_HALT,
  468. .clkr = {
  469. .enable_reg = 0x21018,
  470. .enable_mask = BIT(0),
  471. .hw.init = &(const struct clk_init_data){
  472. .name = "lpass_audio_cc_ext_mclk1_clk",
  473. .parent_hws = (const struct clk_hw*[]){
  474. &lpass_audio_cc_ext_mclk1_clk_src.clkr.hw,
  475. },
  476. .num_parents = 1,
  477. .flags = CLK_SET_RATE_PARENT,
  478. .ops = &clk_branch2_ops,
  479. },
  480. },
  481. };
  482. static struct clk_branch lpass_audio_cc_rx_mclk_2x_clk = {
  483. .halt_reg = 0x240cc,
  484. .halt_check = BRANCH_HALT,
  485. .clkr = {
  486. .enable_reg = 0x240cc,
  487. .enable_mask = BIT(0),
  488. .hw.init = &(const struct clk_init_data){
  489. .name = "lpass_audio_cc_rx_mclk_2x_clk",
  490. .parent_hws = (const struct clk_hw*[]){
  491. &lpass_audio_cc_rx_mclk_clk_src.clkr.hw,
  492. },
  493. .num_parents = 1,
  494. .flags = CLK_SET_RATE_PARENT,
  495. .ops = &clk_branch2_ops,
  496. },
  497. },
  498. };
  499. static struct clk_branch lpass_audio_cc_rx_mclk_clk = {
  500. .halt_reg = 0x240d4,
  501. .halt_check = BRANCH_HALT,
  502. .clkr = {
  503. .enable_reg = 0x240d4,
  504. .enable_mask = BIT(0),
  505. .hw.init = &(const struct clk_init_data){
  506. .name = "lpass_audio_cc_rx_mclk_clk",
  507. .parent_hws = (const struct clk_hw*[]){
  508. &lpass_audio_cc_cdiv_rx_mclk_div_clk_src.clkr.hw,
  509. },
  510. .num_parents = 1,
  511. .flags = CLK_SET_RATE_PARENT,
  512. .ops = &clk_branch2_ops,
  513. },
  514. },
  515. };
  516. static struct clk_branch lpass_aon_cc_audio_hm_h_clk = {
  517. .halt_reg = 0x9014,
  518. .halt_check = BRANCH_HALT,
  519. .clkr = {
  520. .enable_reg = 0x9014,
  521. .enable_mask = BIT(0),
  522. .hw.init = &(const struct clk_init_data){
  523. .name = "lpass_aon_cc_audio_hm_h_clk",
  524. .parent_hws = (const struct clk_hw*[]){
  525. &lpass_aon_cc_main_rcg_clk_src.clkr.hw,
  526. },
  527. .num_parents = 1,
  528. .flags = CLK_SET_RATE_PARENT,
  529. .ops = &clk_branch2_aon_ops,
  530. },
  531. },
  532. };
  533. static struct clk_branch lpass_aon_cc_va_mem0_clk = {
  534. .halt_reg = 0x9028,
  535. .halt_check = BRANCH_HALT,
  536. .clkr = {
  537. .enable_reg = 0x9028,
  538. .enable_mask = BIT(0),
  539. .hw.init = &(const struct clk_init_data){
  540. .name = "lpass_aon_cc_va_mem0_clk",
  541. .parent_hws = (const struct clk_hw*[]){
  542. &lpass_aon_cc_main_rcg_clk_src.clkr.hw,
  543. },
  544. .num_parents = 1,
  545. .flags = CLK_SET_RATE_PARENT,
  546. .ops = &clk_branch2_ops,
  547. },
  548. },
  549. };
  550. static struct clk_branch lpass_aon_cc_tx_mclk_2x_clk = {
  551. .halt_reg = 0x1300c,
  552. .halt_check = BRANCH_HALT,
  553. .clkr = {
  554. .enable_reg = 0x1300c,
  555. .enable_mask = BIT(0),
  556. .hw.init = &(const struct clk_init_data){
  557. .name = "lpass_aon_cc_tx_mclk_2x_clk",
  558. .parent_hws = (const struct clk_hw*[]){
  559. &lpass_aon_cc_tx_mclk_rcg_clk_src.clkr.hw,
  560. },
  561. .num_parents = 1,
  562. .flags = CLK_SET_RATE_PARENT,
  563. .ops = &clk_branch2_ops,
  564. },
  565. },
  566. };
  567. static struct clk_branch lpass_aon_cc_tx_mclk_clk = {
  568. .halt_reg = 0x13014,
  569. .halt_check = BRANCH_HALT,
  570. .clkr = {
  571. .enable_reg = 0x13014,
  572. .enable_mask = BIT(0),
  573. .hw.init = &(const struct clk_init_data){
  574. .name = "lpass_aon_cc_tx_mclk_clk",
  575. .parent_hws = (const struct clk_hw*[]){
  576. &lpass_aon_cc_cdiv_tx_mclk_div_clk_src.clkr.hw,
  577. },
  578. .num_parents = 1,
  579. .flags = CLK_SET_RATE_PARENT,
  580. .ops = &clk_branch2_ops,
  581. },
  582. },
  583. };
  584. static struct gdsc lpass_aon_cc_lpass_audio_hm_gdsc = {
  585. .gdscr = 0x9090,
  586. .pd = {
  587. .name = "lpass_aon_cc_lpass_audio_hm_gdsc",
  588. },
  589. .pwrsts = PWRSTS_OFF_ON,
  590. .flags = RETAIN_FF_ENABLE,
  591. };
  592. static struct clk_regmap *lpass_cc_sc7280_clocks[] = {
  593. [LPASS_Q6SS_AHBM_CLK] = &lpass_q6ss_ahbm_clk.clkr,
  594. [LPASS_Q6SS_AHBS_CLK] = &lpass_q6ss_ahbs_clk.clkr,
  595. };
  596. static struct clk_regmap *lpass_aon_cc_sc7280_clocks[] = {
  597. [LPASS_AON_CC_AUDIO_HM_H_CLK] = &lpass_aon_cc_audio_hm_h_clk.clkr,
  598. [LPASS_AON_CC_VA_MEM0_CLK] = &lpass_aon_cc_va_mem0_clk.clkr,
  599. [LPASS_AON_CC_CDIV_TX_MCLK_DIV_CLK_SRC] = &lpass_aon_cc_cdiv_tx_mclk_div_clk_src.clkr,
  600. [LPASS_AON_CC_MAIN_RCG_CLK_SRC] = &lpass_aon_cc_main_rcg_clk_src.clkr,
  601. [LPASS_AON_CC_PLL] = &lpass_aon_cc_pll.clkr,
  602. [LPASS_AON_CC_PLL_OUT_EVEN] = &lpass_aon_cc_pll_out_even.clkr,
  603. [LPASS_AON_CC_PLL_OUT_MAIN_CDIV_DIV_CLK_SRC] =
  604. &lpass_aon_cc_pll_out_main_cdiv_div_clk_src.clkr,
  605. [LPASS_AON_CC_PLL_OUT_ODD] = &lpass_aon_cc_pll_out_odd.clkr,
  606. [LPASS_AON_CC_TX_MCLK_2X_CLK] = &lpass_aon_cc_tx_mclk_2x_clk.clkr,
  607. [LPASS_AON_CC_TX_MCLK_CLK] = &lpass_aon_cc_tx_mclk_clk.clkr,
  608. [LPASS_AON_CC_TX_MCLK_RCG_CLK_SRC] = &lpass_aon_cc_tx_mclk_rcg_clk_src.clkr,
  609. };
  610. static struct gdsc *lpass_aon_cc_sc7280_gdscs[] = {
  611. [LPASS_AON_CC_LPASS_AUDIO_HM_GDSC] = &lpass_aon_cc_lpass_audio_hm_gdsc,
  612. };
  613. static struct clk_regmap *lpass_audio_cc_sc7280_clocks[] = {
  614. [LPASS_AUDIO_CC_CDIV_RX_MCLK_DIV_CLK_SRC] = &lpass_audio_cc_cdiv_rx_mclk_div_clk_src.clkr,
  615. [LPASS_AUDIO_CC_CODEC_MEM0_CLK] = &lpass_audio_cc_codec_mem0_clk.clkr,
  616. [LPASS_AUDIO_CC_CODEC_MEM1_CLK] = &lpass_audio_cc_codec_mem1_clk.clkr,
  617. [LPASS_AUDIO_CC_CODEC_MEM2_CLK] = &lpass_audio_cc_codec_mem2_clk.clkr,
  618. [LPASS_AUDIO_CC_CODEC_MEM_CLK] = &lpass_audio_cc_codec_mem_clk.clkr,
  619. [LPASS_AUDIO_CC_EXT_MCLK0_CLK] = &lpass_audio_cc_ext_mclk0_clk.clkr,
  620. [LPASS_AUDIO_CC_EXT_MCLK0_CLK_SRC] = &lpass_audio_cc_ext_mclk0_clk_src.clkr,
  621. [LPASS_AUDIO_CC_EXT_MCLK1_CLK] = &lpass_audio_cc_ext_mclk1_clk.clkr,
  622. [LPASS_AUDIO_CC_EXT_MCLK1_CLK_SRC] = &lpass_audio_cc_ext_mclk1_clk_src.clkr,
  623. [LPASS_AUDIO_CC_PLL] = &lpass_audio_cc_pll.clkr,
  624. [LPASS_AUDIO_CC_PLL_OUT_AUX2] = &lpass_audio_cc_pll_out_aux2.clkr,
  625. [LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC] = &lpass_audio_cc_pll_out_aux2_div_clk_src.clkr,
  626. [LPASS_AUDIO_CC_PLL_OUT_MAIN_DIV_CLK_SRC] = &lpass_audio_cc_pll_out_main_div_clk_src.clkr,
  627. [LPASS_AUDIO_CC_RX_MCLK_2X_CLK] = &lpass_audio_cc_rx_mclk_2x_clk.clkr,
  628. [LPASS_AUDIO_CC_RX_MCLK_CLK] = &lpass_audio_cc_rx_mclk_clk.clkr,
  629. [LPASS_AUDIO_CC_RX_MCLK_CLK_SRC] = &lpass_audio_cc_rx_mclk_clk_src.clkr,
  630. };
  631. static struct regmap_config lpass_audio_cc_sc7280_regmap_config = {
  632. .reg_bits = 32,
  633. .reg_stride = 4,
  634. .val_bits = 32,
  635. .fast_io = true,
  636. };
  637. static const struct qcom_cc_desc lpass_cc_sc7280_desc = {
  638. .config = &lpass_audio_cc_sc7280_regmap_config,
  639. .clks = lpass_cc_sc7280_clocks,
  640. .num_clks = ARRAY_SIZE(lpass_cc_sc7280_clocks),
  641. .gdscs = lpass_aon_cc_sc7280_gdscs,
  642. .num_gdscs = ARRAY_SIZE(lpass_aon_cc_sc7280_gdscs),
  643. };
  644. static const struct qcom_cc_desc lpass_audio_cc_sc7280_desc = {
  645. .config = &lpass_audio_cc_sc7280_regmap_config,
  646. .clks = lpass_audio_cc_sc7280_clocks,
  647. .num_clks = ARRAY_SIZE(lpass_audio_cc_sc7280_clocks),
  648. };
  649. static const struct qcom_reset_map lpass_audio_cc_sc7280_resets[] = {
  650. [LPASS_AUDIO_SWR_RX_CGCR] = { 0xa0, 1 },
  651. [LPASS_AUDIO_SWR_TX_CGCR] = { 0xa8, 1 },
  652. [LPASS_AUDIO_SWR_WSA_CGCR] = { 0xb0, 1 },
  653. };
  654. static const struct qcom_cc_desc lpass_audio_cc_reset_sc7280_desc = {
  655. .config = &lpass_audio_cc_sc7280_regmap_config,
  656. .resets = lpass_audio_cc_sc7280_resets,
  657. .num_resets = ARRAY_SIZE(lpass_audio_cc_sc7280_resets),
  658. };
  659. static const struct of_device_id lpass_audio_cc_sc7280_match_table[] = {
  660. { .compatible = "qcom,sc7280-lpassaudiocc" },
  661. { }
  662. };
  663. MODULE_DEVICE_TABLE(of, lpass_audio_cc_sc7280_match_table);
  664. static int lpass_audio_setup_runtime_pm(struct platform_device *pdev)
  665. {
  666. int ret;
  667. pm_runtime_use_autosuspend(&pdev->dev);
  668. pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
  669. ret = devm_pm_runtime_enable(&pdev->dev);
  670. if (ret)
  671. return ret;
  672. ret = devm_pm_clk_create(&pdev->dev);
  673. if (ret)
  674. return ret;
  675. ret = pm_clk_add(&pdev->dev, "iface");
  676. if (ret < 0)
  677. dev_err(&pdev->dev, "failed to acquire iface clock\n");
  678. return pm_runtime_resume_and_get(&pdev->dev);
  679. }
  680. static int lpass_audio_cc_sc7280_probe(struct platform_device *pdev)
  681. {
  682. const struct qcom_cc_desc *desc;
  683. struct regmap *regmap;
  684. int ret;
  685. ret = lpass_audio_setup_runtime_pm(pdev);
  686. if (ret)
  687. return ret;
  688. lpass_audio_cc_sc7280_regmap_config.name = "lpassaudio_cc";
  689. lpass_audio_cc_sc7280_regmap_config.max_register = 0x2f000;
  690. desc = &lpass_audio_cc_sc7280_desc;
  691. regmap = qcom_cc_map(pdev, desc);
  692. if (IS_ERR(regmap)) {
  693. ret = PTR_ERR(regmap);
  694. goto exit;
  695. }
  696. clk_zonda_pll_configure(&lpass_audio_cc_pll, regmap, &lpass_audio_cc_pll_config);
  697. /* PLL settings */
  698. regmap_write(regmap, 0x4, 0x3b);
  699. regmap_write(regmap, 0x8, 0xff05);
  700. ret = qcom_cc_really_probe(pdev, &lpass_audio_cc_sc7280_desc, regmap);
  701. if (ret) {
  702. dev_err(&pdev->dev, "Failed to register LPASS AUDIO CC clocks\n");
  703. goto exit;
  704. }
  705. ret = qcom_cc_probe_by_index(pdev, 1, &lpass_audio_cc_reset_sc7280_desc);
  706. if (ret) {
  707. dev_err(&pdev->dev, "Failed to register LPASS AUDIO CC Resets\n");
  708. goto exit;
  709. }
  710. pm_runtime_mark_last_busy(&pdev->dev);
  711. exit:
  712. pm_runtime_put_autosuspend(&pdev->dev);
  713. return ret;
  714. }
  715. static const struct dev_pm_ops lpass_audio_cc_pm_ops = {
  716. SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
  717. };
  718. static struct platform_driver lpass_audio_cc_sc7280_driver = {
  719. .probe = lpass_audio_cc_sc7280_probe,
  720. .driver = {
  721. .name = "lpass_audio_cc-sc7280",
  722. .of_match_table = lpass_audio_cc_sc7280_match_table,
  723. .pm = &lpass_audio_cc_pm_ops,
  724. },
  725. };
  726. static const struct qcom_cc_desc lpass_aon_cc_sc7280_desc = {
  727. .config = &lpass_audio_cc_sc7280_regmap_config,
  728. .clks = lpass_aon_cc_sc7280_clocks,
  729. .num_clks = ARRAY_SIZE(lpass_aon_cc_sc7280_clocks),
  730. .gdscs = lpass_aon_cc_sc7280_gdscs,
  731. .num_gdscs = ARRAY_SIZE(lpass_aon_cc_sc7280_gdscs),
  732. };
  733. static const struct of_device_id lpass_aon_cc_sc7280_match_table[] = {
  734. { .compatible = "qcom,sc7280-lpassaoncc" },
  735. { }
  736. };
  737. MODULE_DEVICE_TABLE(of, lpass_aon_cc_sc7280_match_table);
  738. static int lpass_aon_cc_sc7280_probe(struct platform_device *pdev)
  739. {
  740. const struct qcom_cc_desc *desc;
  741. struct regmap *regmap;
  742. int ret;
  743. ret = lpass_audio_setup_runtime_pm(pdev);
  744. if (ret)
  745. return ret;
  746. if (of_property_read_bool(pdev->dev.of_node, "qcom,adsp-pil-mode")) {
  747. lpass_audio_cc_sc7280_regmap_config.name = "cc";
  748. desc = &lpass_cc_sc7280_desc;
  749. ret = qcom_cc_probe(pdev, desc);
  750. goto exit;
  751. }
  752. lpass_audio_cc_sc7280_regmap_config.name = "lpasscc_aon";
  753. lpass_audio_cc_sc7280_regmap_config.max_register = 0xa0008;
  754. desc = &lpass_aon_cc_sc7280_desc;
  755. regmap = qcom_cc_map(pdev, desc);
  756. if (IS_ERR(regmap)) {
  757. ret = PTR_ERR(regmap);
  758. goto exit;
  759. }
  760. clk_lucid_pll_configure(&lpass_aon_cc_pll, regmap, &lpass_aon_cc_pll_config);
  761. ret = qcom_cc_really_probe(pdev, &lpass_aon_cc_sc7280_desc, regmap);
  762. if (ret) {
  763. dev_err(&pdev->dev, "Failed to register LPASS AON CC clocks\n");
  764. goto exit;
  765. }
  766. pm_runtime_mark_last_busy(&pdev->dev);
  767. exit:
  768. pm_runtime_put_autosuspend(&pdev->dev);
  769. return ret;
  770. }
  771. static struct platform_driver lpass_aon_cc_sc7280_driver = {
  772. .probe = lpass_aon_cc_sc7280_probe,
  773. .driver = {
  774. .name = "lpass_aon_cc-sc7280",
  775. .of_match_table = lpass_aon_cc_sc7280_match_table,
  776. .pm = &lpass_audio_cc_pm_ops,
  777. },
  778. };
  779. static int __init lpass_audio_cc_sc7280_init(void)
  780. {
  781. int ret;
  782. ret = platform_driver_register(&lpass_aon_cc_sc7280_driver);
  783. if (ret)
  784. return ret;
  785. return platform_driver_register(&lpass_audio_cc_sc7280_driver);
  786. }
  787. subsys_initcall(lpass_audio_cc_sc7280_init);
  788. static void __exit lpass_audio_cc_sc7280_exit(void)
  789. {
  790. platform_driver_unregister(&lpass_audio_cc_sc7280_driver);
  791. platform_driver_unregister(&lpass_aon_cc_sc7280_driver);
  792. }
  793. module_exit(lpass_audio_cc_sc7280_exit);
  794. MODULE_DESCRIPTION("QTI LPASS_AUDIO_CC SC7280 Driver");
  795. MODULE_LICENSE("GPL v2");