qcom_wcnss_iris.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Qualcomm Wireless Connectivity Subsystem Iris driver
  4. *
  5. * Copyright (C) 2016 Linaro Ltd
  6. * Copyright (C) 2014 Sony Mobile Communications AB
  7. * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  8. */
  9. #include <linux/clk.h>
  10. #include <linux/kernel.h>
  11. #include <linux/module.h>
  12. #include <linux/of_device.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/regulator/consumer.h>
  15. #include "qcom_wcnss.h"
  16. struct qcom_iris {
  17. struct device *dev;
  18. struct clk *xo_clk;
  19. struct regulator_bulk_data *vregs;
  20. size_t num_vregs;
  21. };
  22. struct iris_data {
  23. const struct wcnss_vreg_info *vregs;
  24. size_t num_vregs;
  25. bool use_48mhz_xo;
  26. };
  27. static const struct iris_data wcn3620_data = {
  28. .vregs = (struct wcnss_vreg_info[]) {
  29. { "vddxo", 1800000, 1800000, 10000 },
  30. { "vddrfa", 1300000, 1300000, 100000 },
  31. { "vddpa", 3300000, 3300000, 515000 },
  32. { "vdddig", 1800000, 1800000, 10000 },
  33. },
  34. .num_vregs = 4,
  35. .use_48mhz_xo = false,
  36. };
  37. static const struct iris_data wcn3660_data = {
  38. .vregs = (struct wcnss_vreg_info[]) {
  39. { "vddxo", 1800000, 1800000, 10000 },
  40. { "vddrfa", 1300000, 1300000, 100000 },
  41. { "vddpa", 2900000, 3000000, 515000 },
  42. { "vdddig", 1200000, 1225000, 10000 },
  43. },
  44. .num_vregs = 4,
  45. .use_48mhz_xo = true,
  46. };
  47. static const struct iris_data wcn3680_data = {
  48. .vregs = (struct wcnss_vreg_info[]) {
  49. { "vddxo", 1800000, 1800000, 10000 },
  50. { "vddrfa", 1300000, 1300000, 100000 },
  51. { "vddpa", 3300000, 3300000, 515000 },
  52. { "vdddig", 1800000, 1800000, 10000 },
  53. },
  54. .num_vregs = 4,
  55. .use_48mhz_xo = true,
  56. };
  57. int qcom_iris_enable(struct qcom_iris *iris)
  58. {
  59. int ret;
  60. ret = regulator_bulk_enable(iris->num_vregs, iris->vregs);
  61. if (ret)
  62. return ret;
  63. ret = clk_prepare_enable(iris->xo_clk);
  64. if (ret) {
  65. dev_err(iris->dev, "failed to enable xo clk\n");
  66. goto disable_regulators;
  67. }
  68. return 0;
  69. disable_regulators:
  70. regulator_bulk_disable(iris->num_vregs, iris->vregs);
  71. return ret;
  72. }
  73. void qcom_iris_disable(struct qcom_iris *iris)
  74. {
  75. clk_disable_unprepare(iris->xo_clk);
  76. regulator_bulk_disable(iris->num_vregs, iris->vregs);
  77. }
  78. static int qcom_iris_probe(struct platform_device *pdev)
  79. {
  80. const struct iris_data *data;
  81. struct qcom_wcnss *wcnss;
  82. struct qcom_iris *iris;
  83. int ret;
  84. int i;
  85. iris = devm_kzalloc(&pdev->dev, sizeof(struct qcom_iris), GFP_KERNEL);
  86. if (!iris)
  87. return -ENOMEM;
  88. data = of_device_get_match_data(&pdev->dev);
  89. wcnss = dev_get_drvdata(pdev->dev.parent);
  90. iris->xo_clk = devm_clk_get(&pdev->dev, "xo");
  91. if (IS_ERR(iris->xo_clk)) {
  92. if (PTR_ERR(iris->xo_clk) != -EPROBE_DEFER)
  93. dev_err(&pdev->dev, "failed to acquire xo clk\n");
  94. return PTR_ERR(iris->xo_clk);
  95. }
  96. iris->num_vregs = data->num_vregs;
  97. iris->vregs = devm_kcalloc(&pdev->dev,
  98. iris->num_vregs,
  99. sizeof(struct regulator_bulk_data),
  100. GFP_KERNEL);
  101. if (!iris->vregs)
  102. return -ENOMEM;
  103. for (i = 0; i < iris->num_vregs; i++)
  104. iris->vregs[i].supply = data->vregs[i].name;
  105. ret = devm_regulator_bulk_get(&pdev->dev, iris->num_vregs, iris->vregs);
  106. if (ret) {
  107. dev_err(&pdev->dev, "failed to get regulators\n");
  108. return ret;
  109. }
  110. for (i = 0; i < iris->num_vregs; i++) {
  111. if (data->vregs[i].max_voltage)
  112. regulator_set_voltage(iris->vregs[i].consumer,
  113. data->vregs[i].min_voltage,
  114. data->vregs[i].max_voltage);
  115. if (data->vregs[i].load_uA)
  116. regulator_set_load(iris->vregs[i].consumer,
  117. data->vregs[i].load_uA);
  118. }
  119. qcom_wcnss_assign_iris(wcnss, iris, data->use_48mhz_xo);
  120. return 0;
  121. }
  122. static int qcom_iris_remove(struct platform_device *pdev)
  123. {
  124. struct qcom_wcnss *wcnss = dev_get_drvdata(pdev->dev.parent);
  125. qcom_wcnss_assign_iris(wcnss, NULL, false);
  126. return 0;
  127. }
  128. static const struct of_device_id iris_of_match[] = {
  129. { .compatible = "qcom,wcn3620", .data = &wcn3620_data },
  130. { .compatible = "qcom,wcn3660", .data = &wcn3660_data },
  131. { .compatible = "qcom,wcn3680", .data = &wcn3680_data },
  132. {}
  133. };
  134. MODULE_DEVICE_TABLE(of, iris_of_match);
  135. struct platform_driver qcom_iris_driver = {
  136. .probe = qcom_iris_probe,
  137. .remove = qcom_iris_remove,
  138. .driver = {
  139. .name = "qcom-iris",
  140. .of_match_table = iris_of_match,
  141. },
  142. };