lpasscc-sdm845.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/clk-provider.h>
  6. #include <linux/platform_device.h>
  7. #include <linux/module.h>
  8. #include <linux/of_address.h>
  9. #include <linux/regmap.h>
  10. #include <dt-bindings/clock/qcom,lpass-sdm845.h>
  11. #include "clk-regmap.h"
  12. #include "clk-branch.h"
  13. #include "common.h"
  14. static struct clk_branch lpass_q6ss_ahbm_aon_clk = {
  15. .halt_reg = 0x12000,
  16. .halt_check = BRANCH_VOTED,
  17. .clkr = {
  18. .enable_reg = 0x12000,
  19. .enable_mask = BIT(0),
  20. .hw.init = &(struct clk_init_data){
  21. .name = "lpass_q6ss_ahbm_aon_clk",
  22. .ops = &clk_branch2_ops,
  23. },
  24. },
  25. };
  26. static struct clk_branch lpass_q6ss_ahbs_aon_clk = {
  27. .halt_reg = 0x1f000,
  28. .halt_check = BRANCH_VOTED,
  29. .clkr = {
  30. .enable_reg = 0x1f000,
  31. .enable_mask = BIT(0),
  32. .hw.init = &(struct clk_init_data){
  33. .name = "lpass_q6ss_ahbs_aon_clk",
  34. .ops = &clk_branch2_ops,
  35. },
  36. },
  37. };
  38. static struct clk_branch lpass_qdsp6ss_core_clk = {
  39. .halt_reg = 0x20,
  40. /* CLK_OFF would not toggle until LPASS is out of reset */
  41. .halt_check = BRANCH_HALT_SKIP,
  42. .clkr = {
  43. .enable_reg = 0x20,
  44. .enable_mask = BIT(0),
  45. .hw.init = &(struct clk_init_data){
  46. .name = "lpass_qdsp6ss_core_clk",
  47. .ops = &clk_branch2_ops,
  48. },
  49. },
  50. };
  51. static struct clk_branch lpass_qdsp6ss_xo_clk = {
  52. .halt_reg = 0x38,
  53. /* CLK_OFF would not toggle until LPASS is out of reset */
  54. .halt_check = BRANCH_HALT_SKIP,
  55. .clkr = {
  56. .enable_reg = 0x38,
  57. .enable_mask = BIT(0),
  58. .hw.init = &(struct clk_init_data){
  59. .name = "lpass_qdsp6ss_xo_clk",
  60. .ops = &clk_branch2_ops,
  61. },
  62. },
  63. };
  64. static struct clk_branch lpass_qdsp6ss_sleep_clk = {
  65. .halt_reg = 0x3c,
  66. /* CLK_OFF would not toggle until LPASS is out of reset */
  67. .halt_check = BRANCH_HALT_SKIP,
  68. .clkr = {
  69. .enable_reg = 0x3c,
  70. .enable_mask = BIT(0),
  71. .hw.init = &(struct clk_init_data){
  72. .name = "lpass_qdsp6ss_sleep_clk",
  73. .ops = &clk_branch2_ops,
  74. },
  75. },
  76. };
  77. static struct regmap_config lpass_regmap_config = {
  78. .reg_bits = 32,
  79. .reg_stride = 4,
  80. .val_bits = 32,
  81. .fast_io = true,
  82. };
  83. static struct clk_regmap *lpass_cc_sdm845_clocks[] = {
  84. [LPASS_Q6SS_AHBM_AON_CLK] = &lpass_q6ss_ahbm_aon_clk.clkr,
  85. [LPASS_Q6SS_AHBS_AON_CLK] = &lpass_q6ss_ahbs_aon_clk.clkr,
  86. };
  87. static const struct qcom_cc_desc lpass_cc_sdm845_desc = {
  88. .config = &lpass_regmap_config,
  89. .clks = lpass_cc_sdm845_clocks,
  90. .num_clks = ARRAY_SIZE(lpass_cc_sdm845_clocks),
  91. };
  92. static struct clk_regmap *lpass_qdsp6ss_sdm845_clocks[] = {
  93. [LPASS_QDSP6SS_XO_CLK] = &lpass_qdsp6ss_xo_clk.clkr,
  94. [LPASS_QDSP6SS_SLEEP_CLK] = &lpass_qdsp6ss_sleep_clk.clkr,
  95. [LPASS_QDSP6SS_CORE_CLK] = &lpass_qdsp6ss_core_clk.clkr,
  96. };
  97. static const struct qcom_cc_desc lpass_qdsp6ss_sdm845_desc = {
  98. .config = &lpass_regmap_config,
  99. .clks = lpass_qdsp6ss_sdm845_clocks,
  100. .num_clks = ARRAY_SIZE(lpass_qdsp6ss_sdm845_clocks),
  101. };
  102. static int lpass_cc_sdm845_probe(struct platform_device *pdev)
  103. {
  104. const struct qcom_cc_desc *desc;
  105. int ret;
  106. lpass_regmap_config.name = "cc";
  107. desc = &lpass_cc_sdm845_desc;
  108. ret = qcom_cc_probe_by_index(pdev, 0, desc);
  109. if (ret)
  110. return ret;
  111. lpass_regmap_config.name = "qdsp6ss";
  112. desc = &lpass_qdsp6ss_sdm845_desc;
  113. return qcom_cc_probe_by_index(pdev, 1, desc);
  114. }
  115. static const struct of_device_id lpass_cc_sdm845_match_table[] = {
  116. { .compatible = "qcom,sdm845-lpasscc" },
  117. { }
  118. };
  119. MODULE_DEVICE_TABLE(of, lpass_cc_sdm845_match_table);
  120. static struct platform_driver lpass_cc_sdm845_driver = {
  121. .probe = lpass_cc_sdm845_probe,
  122. .driver = {
  123. .name = "sdm845-lpasscc",
  124. .of_match_table = lpass_cc_sdm845_match_table,
  125. },
  126. };
  127. static int __init lpass_cc_sdm845_init(void)
  128. {
  129. return platform_driver_register(&lpass_cc_sdm845_driver);
  130. }
  131. subsys_initcall(lpass_cc_sdm845_init);
  132. static void __exit lpass_cc_sdm845_exit(void)
  133. {
  134. platform_driver_unregister(&lpass_cc_sdm845_driver);
  135. }
  136. module_exit(lpass_cc_sdm845_exit);
  137. MODULE_DESCRIPTION("QTI LPASS_CC SDM845 Driver");
  138. MODULE_LICENSE("GPL v2");