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 <allen-kh.cheng@mediatek.com> 6 // Tinghan Shen <tinghan.shen@mediatek.com> 7 // 8 // Hardware interface for mt8186 DSP clock 9 10 #include <linux/clk.h> 11 #include <linux/pm_runtime.h> 12 #include <linux/io.h> 13 14 #include "../../sof-audio.h" 15 #include "../../ops.h" 16 #include "../adsp_helper.h" 17 #include "mt8186.h" 18 #include "mt8186-clk.h" 19 20 static const char *adsp_clks[ADSP_CLK_MAX] = { 21 [CLK_TOP_AUDIODSP] = "audiodsp_sel", 22 [CLK_TOP_ADSP_BUS] = "adsp_bus_sel", 23 }; 24 25 int mt8186_adsp_init_clock(struct snd_sof_dev *sdev) 26 { 27 struct adsp_priv *priv = sdev->pdata->hw_pdata; 28 struct device *dev = sdev->dev; 29 int i; 30 31 priv->clk = devm_kcalloc(dev, ADSP_CLK_MAX, sizeof(*priv->clk), GFP_KERNEL); 32 if (!priv->clk) 33 return -ENOMEM; 34 35 for (i = 0; i < ADSP_CLK_MAX; i++) { 36 priv->clk[i] = devm_clk_get(dev, adsp_clks[i]); 37 38 if (IS_ERR(priv->clk[i])) 39 return PTR_ERR(priv->clk[i]); 40 } 41 42 return 0; 43 } 44 45 static int adsp_enable_all_clock(struct snd_sof_dev *sdev) 46 { 47 struct adsp_priv *priv = sdev->pdata->hw_pdata; 48 struct device *dev = sdev->dev; 49 int ret; 50 51 ret = clk_prepare_enable(priv->clk[CLK_TOP_AUDIODSP]); 52 if (ret) { 53 dev_err(dev, "%s clk_prepare_enable(audiodsp) fail %d\n", 54 __func__, ret); 55 return ret; 56 } 57 58 ret = clk_prepare_enable(priv->clk[CLK_TOP_ADSP_BUS]); 59 if (ret) { 60 dev_err(dev, "%s clk_prepare_enable(adsp_bus) fail %d\n", 61 __func__, ret); 62 clk_disable_unprepare(priv->clk[CLK_TOP_AUDIODSP]); 63 return ret; 64 } 65 66 return 0; 67 } 68 69 static void adsp_disable_all_clock(struct snd_sof_dev *sdev) 70 { 71 struct adsp_priv *priv = sdev->pdata->hw_pdata; 72 73 clk_disable_unprepare(priv->clk[CLK_TOP_ADSP_BUS]); 74 clk_disable_unprepare(priv->clk[CLK_TOP_AUDIODSP]); 75 } 76 77 int mt8186_adsp_clock_on(struct snd_sof_dev *sdev) 78 { 79 struct device *dev = sdev->dev; 80 int ret; 81 82 ret = adsp_enable_all_clock(sdev); 83 if (ret) { 84 dev_err(dev, "failed to adsp_enable_clock: %d\n", ret); 85 return ret; 86 } 87 snd_sof_dsp_write(sdev, DSP_REG_BAR, ADSP_CK_EN, 88 UART_EN | DMA_EN | TIMER_EN | COREDBG_EN | CORE_CLK_EN); 89 snd_sof_dsp_write(sdev, DSP_REG_BAR, ADSP_UART_CTRL, 90 UART_BCLK_CG | UART_RSTN); 91 92 return 0; 93 } 94 95 void mt8186_adsp_clock_off(struct snd_sof_dev *sdev) 96 { 97 snd_sof_dsp_write(sdev, DSP_REG_BAR, ADSP_CK_EN, 0); 98 snd_sof_dsp_write(sdev, DSP_REG_BAR, ADSP_UART_CTRL, 0); 99 adsp_disable_all_clock(sdev); 100 } 101 102