cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mt8195-clk.c (3986B)


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