smd-rpm.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * RPM over SMD communication wrapper for interconnects
  4. *
  5. * Copyright (C) 2019 Linaro Ltd
  6. * Author: Georgi Djakov <georgi.djakov@linaro.org>
  7. */
  8. #include <linux/interconnect-provider.h>
  9. #include <linux/module.h>
  10. #include <linux/platform_device.h>
  11. #include <linux/soc/qcom/smd-rpm.h>
  12. #include "icc-rpm.h"
  13. #define RPM_KEY_BW 0x00007762
  14. #define QCOM_RPM_SMD_KEY_RATE 0x007a484b
  15. static struct qcom_smd_rpm *icc_smd_rpm;
  16. struct icc_rpm_smd_req {
  17. __le32 key;
  18. __le32 nbytes;
  19. __le32 value;
  20. };
  21. bool qcom_icc_rpm_smd_available(void)
  22. {
  23. return !!icc_smd_rpm;
  24. }
  25. EXPORT_SYMBOL_GPL(qcom_icc_rpm_smd_available);
  26. int qcom_icc_rpm_smd_send(int ctx, int rsc_type, int id, u32 val)
  27. {
  28. struct icc_rpm_smd_req req = {
  29. .key = cpu_to_le32(RPM_KEY_BW),
  30. .nbytes = cpu_to_le32(sizeof(u32)),
  31. .value = cpu_to_le32(val),
  32. };
  33. return qcom_rpm_smd_write(icc_smd_rpm, ctx, rsc_type, id, &req,
  34. sizeof(req));
  35. }
  36. EXPORT_SYMBOL_GPL(qcom_icc_rpm_smd_send);
  37. int qcom_icc_rpm_set_bus_rate(const struct rpm_clk_resource *clk, int ctx, u32 rate)
  38. {
  39. struct clk_smd_rpm_req req = {
  40. .key = cpu_to_le32(QCOM_RPM_SMD_KEY_RATE),
  41. .nbytes = cpu_to_le32(sizeof(u32)),
  42. };
  43. /* Branch clocks are only on/off */
  44. if (clk->branch)
  45. rate = !!rate;
  46. req.value = cpu_to_le32(rate);
  47. return qcom_rpm_smd_write(icc_smd_rpm,
  48. ctx,
  49. clk->resource_type,
  50. clk->clock_id,
  51. &req, sizeof(req));
  52. }
  53. EXPORT_SYMBOL_GPL(qcom_icc_rpm_set_bus_rate);
  54. static void qcom_icc_rpm_smd_remove(struct platform_device *pdev)
  55. {
  56. icc_smd_rpm = NULL;
  57. }
  58. static int qcom_icc_rpm_smd_probe(struct platform_device *pdev)
  59. {
  60. icc_smd_rpm = dev_get_drvdata(pdev->dev.parent);
  61. if (!icc_smd_rpm) {
  62. dev_err(&pdev->dev, "unable to retrieve handle to RPM\n");
  63. return -ENODEV;
  64. }
  65. return 0;
  66. }
  67. static struct platform_driver qcom_interconnect_rpm_smd_driver = {
  68. .driver = {
  69. .name = "icc_smd_rpm",
  70. },
  71. .probe = qcom_icc_rpm_smd_probe,
  72. .remove_new = qcom_icc_rpm_smd_remove,
  73. };
  74. module_platform_driver(qcom_interconnect_rpm_smd_driver);
  75. MODULE_AUTHOR("Georgi Djakov <georgi.djakov@linaro.org>");
  76. MODULE_DESCRIPTION("Qualcomm SMD RPM interconnect proxy driver");
  77. MODULE_LICENSE("GPL v2");
  78. MODULE_ALIAS("platform:icc_smd_rpm");