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