q6sstop-qcs404.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/bitops.h>
  6. #include <linux/clk-provider.h>
  7. #include <linux/err.h>
  8. #include <linux/module.h>
  9. #include <linux/platform_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,q6sstopcc-qcs404.h>
  14. #include "clk-regmap.h"
  15. #include "clk-branch.h"
  16. #include "common.h"
  17. #include "reset.h"
  18. static struct clk_branch lcc_ahbfabric_cbc_clk = {
  19. .halt_reg = 0x1b004,
  20. .halt_check = BRANCH_HALT,
  21. .clkr = {
  22. .enable_reg = 0x1b004,
  23. .enable_mask = BIT(0),
  24. .hw.init = &(struct clk_init_data){
  25. .name = "lcc_ahbfabric_cbc_clk",
  26. .ops = &clk_branch2_ops,
  27. },
  28. },
  29. };
  30. static struct clk_branch lcc_q6ss_ahbs_cbc_clk = {
  31. .halt_reg = 0x22000,
  32. .halt_check = BRANCH_VOTED,
  33. .clkr = {
  34. .enable_reg = 0x22000,
  35. .enable_mask = BIT(0),
  36. .hw.init = &(struct clk_init_data){
  37. .name = "lcc_q6ss_ahbs_cbc_clk",
  38. .ops = &clk_branch2_ops,
  39. },
  40. },
  41. };
  42. static struct clk_branch lcc_q6ss_tcm_slave_cbc_clk = {
  43. .halt_reg = 0x1c000,
  44. .halt_check = BRANCH_VOTED,
  45. .clkr = {
  46. .enable_reg = 0x1c000,
  47. .enable_mask = BIT(0),
  48. .hw.init = &(struct clk_init_data){
  49. .name = "lcc_q6ss_tcm_slave_cbc_clk",
  50. .ops = &clk_branch2_ops,
  51. },
  52. },
  53. };
  54. static struct clk_branch lcc_q6ss_ahbm_cbc_clk = {
  55. .halt_reg = 0x22004,
  56. .halt_check = BRANCH_VOTED,
  57. .clkr = {
  58. .enable_reg = 0x22004,
  59. .enable_mask = BIT(0),
  60. .hw.init = &(struct clk_init_data){
  61. .name = "lcc_q6ss_ahbm_cbc_clk",
  62. .ops = &clk_branch2_ops,
  63. },
  64. },
  65. };
  66. static struct clk_branch lcc_q6ss_axim_cbc_clk = {
  67. .halt_reg = 0x1c004,
  68. .halt_check = BRANCH_VOTED,
  69. .clkr = {
  70. .enable_reg = 0x1c004,
  71. .enable_mask = BIT(0),
  72. .hw.init = &(struct clk_init_data){
  73. .name = "lcc_q6ss_axim_cbc_clk",
  74. .ops = &clk_branch2_ops,
  75. },
  76. },
  77. };
  78. static struct clk_branch lcc_q6ss_bcr_sleep_clk = {
  79. .halt_reg = 0x6004,
  80. .halt_check = BRANCH_VOTED,
  81. .clkr = {
  82. .enable_reg = 0x6004,
  83. .enable_mask = BIT(0),
  84. .hw.init = &(struct clk_init_data){
  85. .name = "lcc_q6ss_bcr_sleep_clk",
  86. .ops = &clk_branch2_ops,
  87. },
  88. },
  89. };
  90. /* TCSR clock */
  91. static struct clk_branch tcsr_lcc_csr_cbcr_clk = {
  92. .halt_reg = 0x8008,
  93. .halt_check = BRANCH_VOTED,
  94. .clkr = {
  95. .enable_reg = 0x8008,
  96. .enable_mask = BIT(0),
  97. .hw.init = &(struct clk_init_data){
  98. .name = "tcsr_lcc_csr_cbcr_clk",
  99. .ops = &clk_branch2_ops,
  100. },
  101. },
  102. };
  103. static struct regmap_config q6sstop_regmap_config = {
  104. .reg_bits = 32,
  105. .reg_stride = 4,
  106. .val_bits = 32,
  107. .fast_io = true,
  108. };
  109. static struct clk_regmap *q6sstop_qcs404_clocks[] = {
  110. [LCC_AHBFABRIC_CBC_CLK] = &lcc_ahbfabric_cbc_clk.clkr,
  111. [LCC_Q6SS_AHBS_CBC_CLK] = &lcc_q6ss_ahbs_cbc_clk.clkr,
  112. [LCC_Q6SS_TCM_SLAVE_CBC_CLK] = &lcc_q6ss_tcm_slave_cbc_clk.clkr,
  113. [LCC_Q6SS_AHBM_CBC_CLK] = &lcc_q6ss_ahbm_cbc_clk.clkr,
  114. [LCC_Q6SS_AXIM_CBC_CLK] = &lcc_q6ss_axim_cbc_clk.clkr,
  115. [LCC_Q6SS_BCR_SLEEP_CLK] = &lcc_q6ss_bcr_sleep_clk.clkr,
  116. };
  117. static const struct qcom_reset_map q6sstop_qcs404_resets[] = {
  118. [Q6SSTOP_BCR_RESET] = { 0x6000 },
  119. };
  120. static const struct qcom_cc_desc q6sstop_qcs404_desc = {
  121. .config = &q6sstop_regmap_config,
  122. .clks = q6sstop_qcs404_clocks,
  123. .num_clks = ARRAY_SIZE(q6sstop_qcs404_clocks),
  124. .resets = q6sstop_qcs404_resets,
  125. .num_resets = ARRAY_SIZE(q6sstop_qcs404_resets),
  126. };
  127. static struct clk_regmap *tcsr_qcs404_clocks[] = {
  128. [TCSR_Q6SS_LCC_CBCR_CLK] = &tcsr_lcc_csr_cbcr_clk.clkr,
  129. };
  130. static const struct qcom_cc_desc tcsr_qcs404_desc = {
  131. .config = &q6sstop_regmap_config,
  132. .clks = tcsr_qcs404_clocks,
  133. .num_clks = ARRAY_SIZE(tcsr_qcs404_clocks),
  134. };
  135. static const struct of_device_id q6sstopcc_qcs404_match_table[] = {
  136. { .compatible = "qcom,qcs404-q6sstopcc" },
  137. { }
  138. };
  139. MODULE_DEVICE_TABLE(of, q6sstopcc_qcs404_match_table);
  140. static int q6sstopcc_qcs404_probe(struct platform_device *pdev)
  141. {
  142. const struct qcom_cc_desc *desc;
  143. int ret;
  144. ret = devm_pm_runtime_enable(&pdev->dev);
  145. if (ret)
  146. return ret;
  147. ret = devm_pm_clk_create(&pdev->dev);
  148. if (ret)
  149. return ret;
  150. ret = pm_clk_add(&pdev->dev, NULL);
  151. if (ret < 0) {
  152. dev_err(&pdev->dev, "failed to acquire iface clock\n");
  153. return ret;
  154. }
  155. ret = pm_runtime_resume_and_get(&pdev->dev);
  156. if (ret)
  157. return ret;
  158. q6sstop_regmap_config.name = "q6sstop_tcsr";
  159. desc = &tcsr_qcs404_desc;
  160. ret = qcom_cc_probe_by_index(pdev, 1, desc);
  161. if (ret)
  162. goto err_put_rpm;
  163. q6sstop_regmap_config.name = "q6sstop_cc";
  164. desc = &q6sstop_qcs404_desc;
  165. ret = qcom_cc_probe_by_index(pdev, 0, desc);
  166. if (ret)
  167. goto err_put_rpm;
  168. pm_runtime_put(&pdev->dev);
  169. return 0;
  170. err_put_rpm:
  171. pm_runtime_put_sync(&pdev->dev);
  172. return ret;
  173. }
  174. static const struct dev_pm_ops q6sstopcc_pm_ops = {
  175. SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
  176. };
  177. static struct platform_driver q6sstopcc_qcs404_driver = {
  178. .probe = q6sstopcc_qcs404_probe,
  179. .driver = {
  180. .name = "qcs404-q6sstopcc",
  181. .of_match_table = q6sstopcc_qcs404_match_table,
  182. .pm = &q6sstopcc_pm_ops,
  183. },
  184. };
  185. module_platform_driver(q6sstopcc_qcs404_driver);
  186. MODULE_DESCRIPTION("QTI QCS404 Q6SSTOP Clock Controller Driver");
  187. MODULE_LICENSE("GPL v2");