brintos

brintos / linux-shallow public Read only

0
0
Text · 4.0 KiB · 7cffcad Raw
165 lines · c
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)2//3// Copyright(c) 2021 Mediatek Corporation. All rights reserved.4//5// Author: YC Hung <yc.hung@mediatek.com>6//7// Hardware interface for mt8195 DSP clock8 9#include <linux/clk.h>10#include <linux/io.h>11#include "mt8195.h"12#include "mt8195-clk.h"13#include "../adsp_helper.h"14#include "../../sof-audio.h"15 16static const char *adsp_clks[ADSP_CLK_MAX] = {17	[CLK_TOP_ADSP] = "adsp_sel",18	[CLK_TOP_CLK26M] = "clk26m_ck",19	[CLK_TOP_AUDIO_LOCAL_BUS] = "audio_local_bus",20	[CLK_TOP_MAINPLL_D7_D2] = "mainpll_d7_d2",21	[CLK_SCP_ADSP_AUDIODSP] = "scp_adsp_audiodsp",22	[CLK_TOP_AUDIO_H] = "audio_h",23};24 25int mt8195_adsp_init_clock(struct snd_sof_dev *sdev)26{27	struct device *dev = sdev->dev;28	struct adsp_priv *priv = sdev->pdata->hw_pdata;29	int i;30 31	priv->clk = devm_kcalloc(dev, ADSP_CLK_MAX, sizeof(*priv->clk), GFP_KERNEL);32 33	if (!priv->clk)34		return -ENOMEM;35 36	for (i = 0; i < ADSP_CLK_MAX; i++) {37		priv->clk[i] = devm_clk_get(dev, adsp_clks[i]);38		if (IS_ERR(priv->clk[i]))39			return PTR_ERR(priv->clk[i]);40	}41 42	return 0;43}44 45static int adsp_enable_all_clock(struct snd_sof_dev *sdev)46{47	struct device *dev = sdev->dev;48	struct adsp_priv *priv = sdev->pdata->hw_pdata;49	int ret;50 51	ret = clk_prepare_enable(priv->clk[CLK_TOP_MAINPLL_D7_D2]);52	if (ret) {53		dev_err(dev, "%s clk_prepare_enable(mainpll_d7_d2) fail %d\n",54			__func__, ret);55		return ret;56	}57 58	ret = clk_prepare_enable(priv->clk[CLK_TOP_ADSP]);59	if (ret) {60		dev_err(dev, "%s clk_prepare_enable(adsp_sel) fail %d\n",61			__func__, ret);62		goto disable_mainpll_d7_d2_clk;63	}64 65	ret = clk_prepare_enable(priv->clk[CLK_TOP_AUDIO_LOCAL_BUS]);66	if (ret) {67		dev_err(dev, "%s clk_prepare_enable(audio_local_bus) fail %d\n",68			__func__, ret);69		goto disable_dsp_sel_clk;70	}71 72	ret = clk_prepare_enable(priv->clk[CLK_SCP_ADSP_AUDIODSP]);73	if (ret) {74		dev_err(dev, "%s clk_prepare_enable(scp_adsp_audiodsp) fail %d\n",75			__func__, ret);76		goto disable_audio_local_bus_clk;77	}78 79	ret = clk_prepare_enable(priv->clk[CLK_TOP_AUDIO_H]);80	if (ret) {81		dev_err(dev, "%s clk_prepare_enable(audio_h) fail %d\n",82			__func__, ret);83		goto disable_scp_adsp_audiodsp_clk;84	}85 86	return 0;87 88disable_scp_adsp_audiodsp_clk:89	clk_disable_unprepare(priv->clk[CLK_SCP_ADSP_AUDIODSP]);90disable_audio_local_bus_clk:91	clk_disable_unprepare(priv->clk[CLK_TOP_AUDIO_LOCAL_BUS]);92disable_dsp_sel_clk:93	clk_disable_unprepare(priv->clk[CLK_TOP_ADSP]);94disable_mainpll_d7_d2_clk:95	clk_disable_unprepare(priv->clk[CLK_TOP_MAINPLL_D7_D2]);96 97	return ret;98}99 100static void adsp_disable_all_clock(struct snd_sof_dev *sdev)101{102	struct adsp_priv *priv = sdev->pdata->hw_pdata;103 104	clk_disable_unprepare(priv->clk[CLK_TOP_AUDIO_H]);105	clk_disable_unprepare(priv->clk[CLK_SCP_ADSP_AUDIODSP]);106	clk_disable_unprepare(priv->clk[CLK_TOP_AUDIO_LOCAL_BUS]);107	clk_disable_unprepare(priv->clk[CLK_TOP_ADSP]);108	clk_disable_unprepare(priv->clk[CLK_TOP_MAINPLL_D7_D2]);109}110 111static int adsp_default_clk_init(struct snd_sof_dev *sdev, bool enable)112{113	struct device *dev = sdev->dev;114	struct adsp_priv *priv = sdev->pdata->hw_pdata;115	int ret;116 117	dev_dbg(dev, "%s: %s\n", __func__, enable ? "on" : "off");118 119	if (enable) {120		ret = clk_set_parent(priv->clk[CLK_TOP_ADSP],121				     priv->clk[CLK_TOP_CLK26M]);122		if (ret) {123			dev_err(dev, "failed to set dsp_sel to clk26m: %d\n", ret);124			return ret;125		}126 127		ret = clk_set_parent(priv->clk[CLK_TOP_AUDIO_LOCAL_BUS],128				     priv->clk[CLK_TOP_MAINPLL_D7_D2]);129		if (ret) {130			dev_err(dev, "set audio_local_bus failed %d\n", ret);131			return ret;132		}133 134		ret = clk_set_parent(priv->clk[CLK_TOP_AUDIO_H],135				     priv->clk[CLK_TOP_CLK26M]);136		if (ret) {137			dev_err(dev, "set audio_h_sel failed %d\n", ret);138			return ret;139		}140 141		ret = adsp_enable_all_clock(sdev);142		if (ret) {143			dev_err(dev, "failed to adsp_enable_clock: %d\n", ret);144			return ret;145		}146	} else {147		adsp_disable_all_clock(sdev);148	}149 150	return 0;151}152 153int adsp_clock_on(struct snd_sof_dev *sdev)154{155	/* Open ADSP clock */156	return adsp_default_clk_init(sdev, 1);157}158 159int adsp_clock_off(struct snd_sof_dev *sdev)160{161	/* Close ADSP clock */162	return adsp_default_clk_init(sdev, 0);163}164 165