digital-cdc-rsc-mgr.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include <linux/clk.h>
  7. #include <linux/clk-provider.h>
  8. #include <linux/ratelimit.h>
  9. #include <dsp/digital-cdc-rsc-mgr.h>
  10. #include <linux/dev_printk.h>
  11. struct mutex hw_vote_lock;
  12. static bool is_init_done;
  13. /**
  14. * digital_cdc_rsc_mgr_hw_vote_enable - Enables hw vote in DSP
  15. *
  16. * @vote_handle: vote handle for which voting needs to be done
  17. * @dev: indicate which device votes
  18. *
  19. * Returns 0 on success or -EINVAL/error code on failure
  20. */
  21. int digital_cdc_rsc_mgr_hw_vote_enable(struct clk *vote_handle, struct device *dev)
  22. {
  23. int ret = 0;
  24. if (!is_init_done || vote_handle == NULL) {
  25. pr_err_ratelimited("%s: init failed or vote handle NULL\n",
  26. __func__);
  27. return -EINVAL;
  28. }
  29. mutex_lock(&hw_vote_lock);
  30. ret = clk_prepare_enable(vote_handle);
  31. mutex_unlock(&hw_vote_lock);
  32. dev_dbg(dev, "%s: return %d\n", __func__, ret);
  33. return ret;
  34. }
  35. EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_enable);
  36. /**
  37. * digital_cdc_rsc_mgr_hw_vote_disable - Disables hw vote in DSP
  38. *
  39. * @vote_handle: vote handle for which voting needs to be disabled
  40. * @dev: indicate which device unvotes
  41. *
  42. */
  43. void digital_cdc_rsc_mgr_hw_vote_disable(struct clk *vote_handle, struct device *dev)
  44. {
  45. if (!is_init_done || vote_handle == NULL) {
  46. pr_err_ratelimited("%s: init failed or vote handle NULL\n",
  47. __func__);
  48. return;
  49. }
  50. mutex_lock(&hw_vote_lock);
  51. clk_disable_unprepare(vote_handle);
  52. mutex_unlock(&hw_vote_lock);
  53. dev_dbg(dev, "%s: leave\n", __func__);
  54. }
  55. EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_disable);
  56. /**
  57. * digital_cdc_rsc_mgr_hw_vote_reset - Resets hw vote count
  58. *
  59. */
  60. void digital_cdc_rsc_mgr_hw_vote_reset(struct clk* vote_handle)
  61. {
  62. int count = 0;
  63. if (!is_init_done || vote_handle == NULL) {
  64. pr_err_ratelimited("%s: init failed or vote handle NULL\n",
  65. __func__);
  66. return;
  67. }
  68. mutex_lock(&hw_vote_lock);
  69. while (__clk_is_enabled(vote_handle)) {
  70. clk_disable_unprepare(vote_handle);
  71. count++;
  72. }
  73. pr_debug("%s: Vote count after SSR: %d\n", __func__, count);
  74. while (count--)
  75. clk_prepare_enable(vote_handle);
  76. mutex_unlock(&hw_vote_lock);
  77. }
  78. EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_reset);
  79. void digital_cdc_rsc_mgr_init(void)
  80. {
  81. mutex_init(&hw_vote_lock);
  82. is_init_done = true;
  83. }
  84. void digital_cdc_rsc_mgr_exit(void)
  85. {
  86. mutex_destroy(&hw_vote_lock);
  87. is_init_done = false;
  88. }