mt8186-clk.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
  2. //
  3. // Copyright(c) 2022 Mediatek Corporation. All rights reserved.
  4. //
  5. // Author: Allen-KH Cheng <[email protected]>
  6. // Tinghan Shen <[email protected]>
  7. //
  8. // Hardware interface for mt8186 DSP clock
  9. #include <linux/clk.h>
  10. #include <linux/pm_runtime.h>
  11. #include <linux/io.h>
  12. #include "../../sof-audio.h"
  13. #include "../../ops.h"
  14. #include "../adsp_helper.h"
  15. #include "mt8186.h"
  16. #include "mt8186-clk.h"
  17. static const char *adsp_clks[ADSP_CLK_MAX] = {
  18. [CLK_TOP_AUDIODSP] = "audiodsp",
  19. [CLK_TOP_ADSP_BUS] = "adsp_bus",
  20. };
  21. int mt8186_adsp_init_clock(struct snd_sof_dev *sdev)
  22. {
  23. struct adsp_priv *priv = sdev->pdata->hw_pdata;
  24. struct device *dev = sdev->dev;
  25. int i;
  26. priv->clk = devm_kcalloc(dev, ADSP_CLK_MAX, sizeof(*priv->clk), GFP_KERNEL);
  27. if (!priv->clk)
  28. return -ENOMEM;
  29. for (i = 0; i < ADSP_CLK_MAX; i++) {
  30. priv->clk[i] = devm_clk_get(dev, adsp_clks[i]);
  31. if (IS_ERR(priv->clk[i]))
  32. return PTR_ERR(priv->clk[i]);
  33. }
  34. return 0;
  35. }
  36. static int adsp_enable_all_clock(struct snd_sof_dev *sdev)
  37. {
  38. struct adsp_priv *priv = sdev->pdata->hw_pdata;
  39. struct device *dev = sdev->dev;
  40. int ret;
  41. ret = clk_prepare_enable(priv->clk[CLK_TOP_AUDIODSP]);
  42. if (ret) {
  43. dev_err(dev, "%s clk_prepare_enable(audiodsp) fail %d\n",
  44. __func__, ret);
  45. return ret;
  46. }
  47. ret = clk_prepare_enable(priv->clk[CLK_TOP_ADSP_BUS]);
  48. if (ret) {
  49. dev_err(dev, "%s clk_prepare_enable(adsp_bus) fail %d\n",
  50. __func__, ret);
  51. clk_disable_unprepare(priv->clk[CLK_TOP_AUDIODSP]);
  52. return ret;
  53. }
  54. return 0;
  55. }
  56. static void adsp_disable_all_clock(struct snd_sof_dev *sdev)
  57. {
  58. struct adsp_priv *priv = sdev->pdata->hw_pdata;
  59. clk_disable_unprepare(priv->clk[CLK_TOP_ADSP_BUS]);
  60. clk_disable_unprepare(priv->clk[CLK_TOP_AUDIODSP]);
  61. }
  62. int mt8186_adsp_clock_on(struct snd_sof_dev *sdev)
  63. {
  64. struct device *dev = sdev->dev;
  65. int ret;
  66. ret = adsp_enable_all_clock(sdev);
  67. if (ret) {
  68. dev_err(dev, "failed to adsp_enable_clock: %d\n", ret);
  69. return ret;
  70. }
  71. snd_sof_dsp_write(sdev, DSP_REG_BAR, ADSP_CK_EN,
  72. UART_EN | DMA_EN | TIMER_EN | COREDBG_EN | CORE_CLK_EN);
  73. snd_sof_dsp_write(sdev, DSP_REG_BAR, ADSP_UART_CTRL,
  74. UART_BCLK_CG | UART_RSTN);
  75. return 0;
  76. }
  77. void mt8186_adsp_clock_off(struct snd_sof_dev *sdev)
  78. {
  79. snd_sof_dsp_write(sdev, DSP_REG_BAR, ADSP_CK_EN, 0);
  80. snd_sof_dsp_write(sdev, DSP_REG_BAR, ADSP_UART_CTRL, 0);
  81. adsp_disable_all_clock(sdev);
  82. }