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

cnl-sst-dsp.c (6408B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * cnl-sst-dsp.c - CNL SST library generic function
      4 *
      5 * Copyright (C) 2016-17, Intel Corporation.
      6 * Author: Guneshwor Singh <guneshwor.o.singh@intel.com>
      7 *
      8 * Modified from:
      9 *	SKL SST library generic function
     10 *	Copyright (C) 2014-15, Intel Corporation.
     11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     12 *
     13 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     14 */
     15#include <linux/device.h>
     16#include "../common/sst-dsp.h"
     17#include "../common/sst-ipc.h"
     18#include "../common/sst-dsp-priv.h"
     19#include "cnl-sst-dsp.h"
     20
     21/* various timeout values */
     22#define CNL_DSP_PU_TO		50
     23#define CNL_DSP_PD_TO		50
     24#define CNL_DSP_RESET_TO	50
     25
     26static int
     27cnl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
     28{
     29	/* update bits */
     30	sst_dsp_shim_update_bits_unlocked(ctx,
     31			CNL_ADSP_REG_ADSPCS, CNL_ADSPCS_CRST(core_mask),
     32			CNL_ADSPCS_CRST(core_mask));
     33
     34	/* poll with timeout to check if operation successful */
     35	return sst_dsp_register_poll(ctx,
     36			CNL_ADSP_REG_ADSPCS,
     37			CNL_ADSPCS_CRST(core_mask),
     38			CNL_ADSPCS_CRST(core_mask),
     39			CNL_DSP_RESET_TO,
     40			"Set reset");
     41}
     42
     43static int
     44cnl_dsp_core_unset_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
     45{
     46	/* update bits */
     47	sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
     48					CNL_ADSPCS_CRST(core_mask), 0);
     49
     50	/* poll with timeout to check if operation successful */
     51	return sst_dsp_register_poll(ctx,
     52			CNL_ADSP_REG_ADSPCS,
     53			CNL_ADSPCS_CRST(core_mask),
     54			0,
     55			CNL_DSP_RESET_TO,
     56			"Unset reset");
     57}
     58
     59static bool is_cnl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask)
     60{
     61	int val;
     62	bool is_enable;
     63
     64	val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPCS);
     65
     66	is_enable = (val & CNL_ADSPCS_CPA(core_mask)) &&
     67			(val & CNL_ADSPCS_SPA(core_mask)) &&
     68			!(val & CNL_ADSPCS_CRST(core_mask)) &&
     69			!(val & CNL_ADSPCS_CSTALL(core_mask));
     70
     71	dev_dbg(ctx->dev, "DSP core(s) enabled? %d: core_mask %#x\n",
     72		is_enable, core_mask);
     73
     74	return is_enable;
     75}
     76
     77static int cnl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask)
     78{
     79	/* stall core */
     80	sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
     81			CNL_ADSPCS_CSTALL(core_mask),
     82			CNL_ADSPCS_CSTALL(core_mask));
     83
     84	/* set reset state */
     85	return cnl_dsp_core_set_reset_state(ctx, core_mask);
     86}
     87
     88static int cnl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask)
     89{
     90	int ret;
     91
     92	/* unset reset state */
     93	ret = cnl_dsp_core_unset_reset_state(ctx, core_mask);
     94	if (ret < 0)
     95		return ret;
     96
     97	/* run core */
     98	sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
     99				CNL_ADSPCS_CSTALL(core_mask), 0);
    100
    101	if (!is_cnl_dsp_core_enable(ctx, core_mask)) {
    102		cnl_dsp_reset_core(ctx, core_mask);
    103		dev_err(ctx->dev, "DSP core mask %#x enable failed\n",
    104			core_mask);
    105		ret = -EIO;
    106	}
    107
    108	return ret;
    109}
    110
    111static int cnl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask)
    112{
    113	/* update bits */
    114	sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
    115					  CNL_ADSPCS_SPA(core_mask),
    116					  CNL_ADSPCS_SPA(core_mask));
    117
    118	/* poll with timeout to check if operation successful */
    119	return sst_dsp_register_poll(ctx, CNL_ADSP_REG_ADSPCS,
    120				    CNL_ADSPCS_CPA(core_mask),
    121				    CNL_ADSPCS_CPA(core_mask),
    122				    CNL_DSP_PU_TO,
    123				    "Power up");
    124}
    125
    126static int cnl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask)
    127{
    128	/* update bits */
    129	sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
    130					CNL_ADSPCS_SPA(core_mask), 0);
    131
    132	/* poll with timeout to check if operation successful */
    133	return sst_dsp_register_poll(ctx,
    134			CNL_ADSP_REG_ADSPCS,
    135			CNL_ADSPCS_CPA(core_mask),
    136			0,
    137			CNL_DSP_PD_TO,
    138			"Power down");
    139}
    140
    141int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask)
    142{
    143	int ret;
    144
    145	/* power up */
    146	ret = cnl_dsp_core_power_up(ctx, core_mask);
    147	if (ret < 0) {
    148		dev_dbg(ctx->dev, "DSP core mask %#x power up failed",
    149			core_mask);
    150		return ret;
    151	}
    152
    153	return cnl_dsp_start_core(ctx, core_mask);
    154}
    155
    156int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask)
    157{
    158	int ret;
    159
    160	ret = cnl_dsp_reset_core(ctx, core_mask);
    161	if (ret < 0) {
    162		dev_err(ctx->dev, "DSP core mask %#x reset failed\n",
    163			core_mask);
    164		return ret;
    165	}
    166
    167	/* power down core*/
    168	ret = cnl_dsp_core_power_down(ctx, core_mask);
    169	if (ret < 0) {
    170		dev_err(ctx->dev, "DSP core mask %#x power down failed\n",
    171			core_mask);
    172		return ret;
    173	}
    174
    175	if (is_cnl_dsp_core_enable(ctx, core_mask)) {
    176		dev_err(ctx->dev, "DSP core mask %#x disable failed\n",
    177			core_mask);
    178		ret = -EIO;
    179	}
    180
    181	return ret;
    182}
    183
    184irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id)
    185{
    186	struct sst_dsp *ctx = dev_id;
    187	u32 val;
    188	irqreturn_t ret = IRQ_NONE;
    189
    190	spin_lock(&ctx->spinlock);
    191
    192	val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS);
    193	ctx->intr_status = val;
    194
    195	if (val == 0xffffffff) {
    196		spin_unlock(&ctx->spinlock);
    197		return IRQ_NONE;
    198	}
    199
    200	if (val & CNL_ADSPIS_IPC) {
    201		cnl_ipc_int_disable(ctx);
    202		ret = IRQ_WAKE_THREAD;
    203	}
    204
    205	spin_unlock(&ctx->spinlock);
    206
    207	return ret;
    208}
    209
    210void cnl_dsp_free(struct sst_dsp *dsp)
    211{
    212	cnl_ipc_int_disable(dsp);
    213
    214	free_irq(dsp->irq, dsp);
    215	cnl_ipc_op_int_disable(dsp);
    216	cnl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK);
    217}
    218EXPORT_SYMBOL_GPL(cnl_dsp_free);
    219
    220void cnl_ipc_int_enable(struct sst_dsp *ctx)
    221{
    222	sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_ADSPIC,
    223				 CNL_ADSPIC_IPC, CNL_ADSPIC_IPC);
    224}
    225
    226void cnl_ipc_int_disable(struct sst_dsp *ctx)
    227{
    228	sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPIC,
    229					  CNL_ADSPIC_IPC, 0);
    230}
    231
    232void cnl_ipc_op_int_enable(struct sst_dsp *ctx)
    233{
    234	/* enable IPC DONE interrupt */
    235	sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
    236				 CNL_ADSP_REG_HIPCCTL_DONE,
    237				 CNL_ADSP_REG_HIPCCTL_DONE);
    238
    239	/* enable IPC BUSY interrupt */
    240	sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
    241				 CNL_ADSP_REG_HIPCCTL_BUSY,
    242				 CNL_ADSP_REG_HIPCCTL_BUSY);
    243}
    244
    245void cnl_ipc_op_int_disable(struct sst_dsp *ctx)
    246{
    247	/* disable IPC DONE interrupt */
    248	sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
    249				 CNL_ADSP_REG_HIPCCTL_DONE, 0);
    250
    251	/* disable IPC BUSY interrupt */
    252	sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
    253				 CNL_ADSP_REG_HIPCCTL_BUSY, 0);
    254}
    255
    256bool cnl_ipc_int_status(struct sst_dsp *ctx)
    257{
    258	return sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS) &
    259							CNL_ADSPIS_IPC;
    260}
    261
    262void cnl_ipc_free(struct sst_generic_ipc *ipc)
    263{
    264	cnl_ipc_op_int_disable(ipc->dsp);
    265	sst_ipc_fini(ipc);
    266}