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

skl-sst-dsp.c (11038B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * skl-sst-dsp.c - SKL SST library generic function
      4 *
      5 * Copyright (C) 2014-15, Intel Corporation.
      6 * Author:Rafal Redzimski <rafal.f.redzimski@intel.com>
      7 *	Jeeja KP <jeeja.kp@intel.com>
      8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      9 */
     10#include <sound/pcm.h>
     11
     12#include "../common/sst-dsp.h"
     13#include "../common/sst-ipc.h"
     14#include "../common/sst-dsp-priv.h"
     15#include "skl.h"
     16
     17/* various timeout values */
     18#define SKL_DSP_PU_TO		50
     19#define SKL_DSP_PD_TO		50
     20#define SKL_DSP_RESET_TO	50
     21
     22void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state)
     23{
     24	mutex_lock(&ctx->mutex);
     25	ctx->sst_state = state;
     26	mutex_unlock(&ctx->mutex);
     27}
     28
     29/*
     30 * Initialize core power state and usage count. To be called after
     31 * successful first boot. Hence core 0 will be running and other cores
     32 * will be reset
     33 */
     34void skl_dsp_init_core_state(struct sst_dsp *ctx)
     35{
     36	struct skl_dev *skl = ctx->thread_context;
     37	int i;
     38
     39	skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING;
     40	skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1;
     41
     42	for (i = SKL_DSP_CORE0_ID + 1; i < skl->cores.count; i++) {
     43		skl->cores.state[i] = SKL_DSP_RESET;
     44		skl->cores.usage_count[i] = 0;
     45	}
     46}
     47
     48/* Get the mask for all enabled cores */
     49unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx)
     50{
     51	struct skl_dev *skl = ctx->thread_context;
     52	unsigned int core_mask, en_cores_mask;
     53	u32 val;
     54
     55	core_mask = SKL_DSP_CORES_MASK(skl->cores.count);
     56
     57	val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
     58
     59	/* Cores having CPA bit set */
     60	en_cores_mask = (val & SKL_ADSPCS_CPA_MASK(core_mask)) >>
     61			SKL_ADSPCS_CPA_SHIFT;
     62
     63	/* And cores having CRST bit cleared */
     64	en_cores_mask &= (~val & SKL_ADSPCS_CRST_MASK(core_mask)) >>
     65			SKL_ADSPCS_CRST_SHIFT;
     66
     67	/* And cores having CSTALL bit cleared */
     68	en_cores_mask &= (~val & SKL_ADSPCS_CSTALL_MASK(core_mask)) >>
     69			SKL_ADSPCS_CSTALL_SHIFT;
     70	en_cores_mask &= core_mask;
     71
     72	dev_dbg(ctx->dev, "DSP enabled cores mask = %x\n", en_cores_mask);
     73
     74	return en_cores_mask;
     75}
     76
     77static int
     78skl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
     79{
     80	int ret;
     81
     82	/* update bits */
     83	sst_dsp_shim_update_bits_unlocked(ctx,
     84			SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK(core_mask),
     85			SKL_ADSPCS_CRST_MASK(core_mask));
     86
     87	/* poll with timeout to check if operation successful */
     88	ret = sst_dsp_register_poll(ctx,
     89			SKL_ADSP_REG_ADSPCS,
     90			SKL_ADSPCS_CRST_MASK(core_mask),
     91			SKL_ADSPCS_CRST_MASK(core_mask),
     92			SKL_DSP_RESET_TO,
     93			"Set reset");
     94	if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
     95				SKL_ADSPCS_CRST_MASK(core_mask)) !=
     96				SKL_ADSPCS_CRST_MASK(core_mask)) {
     97		dev_err(ctx->dev, "Set reset state failed: core_mask %x\n",
     98							core_mask);
     99		ret = -EIO;
    100	}
    101
    102	return ret;
    103}
    104
    105int skl_dsp_core_unset_reset_state(
    106		struct sst_dsp *ctx, unsigned int core_mask)
    107{
    108	int ret;
    109
    110	dev_dbg(ctx->dev, "In %s\n", __func__);
    111
    112	/* update bits */
    113	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
    114				SKL_ADSPCS_CRST_MASK(core_mask), 0);
    115
    116	/* poll with timeout to check if operation successful */
    117	ret = sst_dsp_register_poll(ctx,
    118			SKL_ADSP_REG_ADSPCS,
    119			SKL_ADSPCS_CRST_MASK(core_mask),
    120			0,
    121			SKL_DSP_RESET_TO,
    122			"Unset reset");
    123
    124	if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
    125				SKL_ADSPCS_CRST_MASK(core_mask)) != 0) {
    126		dev_err(ctx->dev, "Unset reset state failed: core_mask %x\n",
    127				core_mask);
    128		ret = -EIO;
    129	}
    130
    131	return ret;
    132}
    133
    134static bool
    135is_skl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask)
    136{
    137	int val;
    138	bool is_enable;
    139
    140	val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
    141
    142	is_enable = ((val & SKL_ADSPCS_CPA_MASK(core_mask)) &&
    143			(val & SKL_ADSPCS_SPA_MASK(core_mask)) &&
    144			!(val & SKL_ADSPCS_CRST_MASK(core_mask)) &&
    145			!(val & SKL_ADSPCS_CSTALL_MASK(core_mask)));
    146
    147	dev_dbg(ctx->dev, "DSP core(s) enabled? %d : core_mask %x\n",
    148						is_enable, core_mask);
    149
    150	return is_enable;
    151}
    152
    153static int skl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask)
    154{
    155	/* stall core */
    156	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
    157			SKL_ADSPCS_CSTALL_MASK(core_mask),
    158			SKL_ADSPCS_CSTALL_MASK(core_mask));
    159
    160	/* set reset state */
    161	return skl_dsp_core_set_reset_state(ctx, core_mask);
    162}
    163
    164int skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask)
    165{
    166	int ret;
    167
    168	/* unset reset state */
    169	ret = skl_dsp_core_unset_reset_state(ctx, core_mask);
    170	if (ret < 0)
    171		return ret;
    172
    173	/* run core */
    174	dev_dbg(ctx->dev, "unstall/run core: core_mask = %x\n", core_mask);
    175	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
    176			SKL_ADSPCS_CSTALL_MASK(core_mask), 0);
    177
    178	if (!is_skl_dsp_core_enable(ctx, core_mask)) {
    179		skl_dsp_reset_core(ctx, core_mask);
    180		dev_err(ctx->dev, "DSP start core failed: core_mask %x\n",
    181							core_mask);
    182		ret = -EIO;
    183	}
    184
    185	return ret;
    186}
    187
    188int skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask)
    189{
    190	int ret;
    191
    192	/* update bits */
    193	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
    194			SKL_ADSPCS_SPA_MASK(core_mask),
    195			SKL_ADSPCS_SPA_MASK(core_mask));
    196
    197	/* poll with timeout to check if operation successful */
    198	ret = sst_dsp_register_poll(ctx,
    199			SKL_ADSP_REG_ADSPCS,
    200			SKL_ADSPCS_CPA_MASK(core_mask),
    201			SKL_ADSPCS_CPA_MASK(core_mask),
    202			SKL_DSP_PU_TO,
    203			"Power up");
    204
    205	if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
    206			SKL_ADSPCS_CPA_MASK(core_mask)) !=
    207			SKL_ADSPCS_CPA_MASK(core_mask)) {
    208		dev_err(ctx->dev, "DSP core power up failed: core_mask %x\n",
    209				core_mask);
    210		ret = -EIO;
    211	}
    212
    213	return ret;
    214}
    215
    216int skl_dsp_core_power_down(struct sst_dsp  *ctx, unsigned int core_mask)
    217{
    218	/* update bits */
    219	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
    220				SKL_ADSPCS_SPA_MASK(core_mask), 0);
    221
    222	/* poll with timeout to check if operation successful */
    223	return sst_dsp_register_poll(ctx,
    224			SKL_ADSP_REG_ADSPCS,
    225			SKL_ADSPCS_CPA_MASK(core_mask),
    226			0,
    227			SKL_DSP_PD_TO,
    228			"Power down");
    229}
    230
    231int skl_dsp_enable_core(struct sst_dsp  *ctx, unsigned int core_mask)
    232{
    233	int ret;
    234
    235	/* power up */
    236	ret = skl_dsp_core_power_up(ctx, core_mask);
    237	if (ret < 0) {
    238		dev_err(ctx->dev, "dsp core power up failed: core_mask %x\n",
    239							core_mask);
    240		return ret;
    241	}
    242
    243	return skl_dsp_start_core(ctx, core_mask);
    244}
    245
    246int skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask)
    247{
    248	int ret;
    249
    250	ret = skl_dsp_reset_core(ctx, core_mask);
    251	if (ret < 0) {
    252		dev_err(ctx->dev, "dsp core reset failed: core_mask %x\n",
    253							core_mask);
    254		return ret;
    255	}
    256
    257	/* power down core*/
    258	ret = skl_dsp_core_power_down(ctx, core_mask);
    259	if (ret < 0) {
    260		dev_err(ctx->dev, "dsp core power down fail mask %x: %d\n",
    261							core_mask, ret);
    262		return ret;
    263	}
    264
    265	if (is_skl_dsp_core_enable(ctx, core_mask)) {
    266		dev_err(ctx->dev, "dsp core disable fail mask %x: %d\n",
    267							core_mask, ret);
    268		ret = -EIO;
    269	}
    270
    271	return ret;
    272}
    273
    274int skl_dsp_boot(struct sst_dsp *ctx)
    275{
    276	int ret;
    277
    278	if (is_skl_dsp_core_enable(ctx, SKL_DSP_CORE0_MASK)) {
    279		ret = skl_dsp_reset_core(ctx, SKL_DSP_CORE0_MASK);
    280		if (ret < 0) {
    281			dev_err(ctx->dev, "dsp core0 reset fail: %d\n", ret);
    282			return ret;
    283		}
    284
    285		ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK);
    286		if (ret < 0) {
    287			dev_err(ctx->dev, "dsp core0 start fail: %d\n", ret);
    288			return ret;
    289		}
    290	} else {
    291		ret = skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
    292		if (ret < 0) {
    293			dev_err(ctx->dev, "dsp core0 disable fail: %d\n", ret);
    294			return ret;
    295		}
    296		ret = skl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK);
    297	}
    298
    299	return ret;
    300}
    301
    302irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id)
    303{
    304	struct sst_dsp *ctx = dev_id;
    305	u32 val;
    306	irqreturn_t result = IRQ_NONE;
    307
    308	spin_lock(&ctx->spinlock);
    309
    310	val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPIS);
    311	ctx->intr_status = val;
    312
    313	if (val == 0xffffffff) {
    314		spin_unlock(&ctx->spinlock);
    315		return IRQ_NONE;
    316	}
    317
    318	if (val & SKL_ADSPIS_IPC) {
    319		skl_ipc_int_disable(ctx);
    320		result = IRQ_WAKE_THREAD;
    321	}
    322
    323	if (val & SKL_ADSPIS_CL_DMA) {
    324		skl_cldma_int_disable(ctx);
    325		result = IRQ_WAKE_THREAD;
    326	}
    327
    328	spin_unlock(&ctx->spinlock);
    329
    330	return result;
    331}
    332/*
    333 * skl_dsp_get_core/skl_dsp_put_core will be called inside DAPM context
    334 * within the dapm mutex. Hence no separate lock is used.
    335 */
    336int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id)
    337{
    338	struct skl_dev *skl = ctx->thread_context;
    339	int ret = 0;
    340
    341	if (core_id >= skl->cores.count) {
    342		dev_err(ctx->dev, "invalid core id: %d\n", core_id);
    343		return -EINVAL;
    344	}
    345
    346	skl->cores.usage_count[core_id]++;
    347
    348	if (skl->cores.state[core_id] == SKL_DSP_RESET) {
    349		ret = ctx->fw_ops.set_state_D0(ctx, core_id);
    350		if (ret < 0) {
    351			dev_err(ctx->dev, "unable to get core%d\n", core_id);
    352			goto out;
    353		}
    354	}
    355
    356out:
    357	dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n",
    358			core_id, skl->cores.state[core_id],
    359			skl->cores.usage_count[core_id]);
    360
    361	return ret;
    362}
    363EXPORT_SYMBOL_GPL(skl_dsp_get_core);
    364
    365int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id)
    366{
    367	struct skl_dev *skl = ctx->thread_context;
    368	int ret = 0;
    369
    370	if (core_id >= skl->cores.count) {
    371		dev_err(ctx->dev, "invalid core id: %d\n", core_id);
    372		return -EINVAL;
    373	}
    374
    375	if ((--skl->cores.usage_count[core_id] == 0) &&
    376		(skl->cores.state[core_id] != SKL_DSP_RESET)) {
    377		ret = ctx->fw_ops.set_state_D3(ctx, core_id);
    378		if (ret < 0) {
    379			dev_err(ctx->dev, "unable to put core %d: %d\n",
    380					core_id, ret);
    381			skl->cores.usage_count[core_id]++;
    382		}
    383	}
    384
    385	dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n",
    386			core_id, skl->cores.state[core_id],
    387			skl->cores.usage_count[core_id]);
    388
    389	return ret;
    390}
    391EXPORT_SYMBOL_GPL(skl_dsp_put_core);
    392
    393int skl_dsp_wake(struct sst_dsp *ctx)
    394{
    395	return skl_dsp_get_core(ctx, SKL_DSP_CORE0_ID);
    396}
    397EXPORT_SYMBOL_GPL(skl_dsp_wake);
    398
    399int skl_dsp_sleep(struct sst_dsp *ctx)
    400{
    401	return skl_dsp_put_core(ctx, SKL_DSP_CORE0_ID);
    402}
    403EXPORT_SYMBOL_GPL(skl_dsp_sleep);
    404
    405struct sst_dsp *skl_dsp_ctx_init(struct device *dev,
    406		struct sst_dsp_device *sst_dev, int irq)
    407{
    408	int ret;
    409	struct sst_dsp *sst;
    410
    411	sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL);
    412	if (sst == NULL)
    413		return NULL;
    414
    415	spin_lock_init(&sst->spinlock);
    416	mutex_init(&sst->mutex);
    417	sst->dev = dev;
    418	sst->sst_dev = sst_dev;
    419	sst->irq = irq;
    420	sst->ops = sst_dev->ops;
    421	sst->thread_context = sst_dev->thread_context;
    422
    423	/* Initialise SST Audio DSP */
    424	if (sst->ops->init) {
    425		ret = sst->ops->init(sst);
    426		if (ret < 0)
    427			return NULL;
    428	}
    429
    430	return sst;
    431}
    432
    433int skl_dsp_acquire_irq(struct sst_dsp *sst)
    434{
    435	struct sst_dsp_device *sst_dev = sst->sst_dev;
    436	int ret;
    437
    438	/* Register the ISR */
    439	ret = request_threaded_irq(sst->irq, sst->ops->irq_handler,
    440		sst_dev->thread, IRQF_SHARED, "AudioDSP", sst);
    441	if (ret)
    442		dev_err(sst->dev, "unable to grab threaded IRQ %d, disabling device\n",
    443			       sst->irq);
    444
    445	return ret;
    446}
    447
    448void skl_dsp_free(struct sst_dsp *dsp)
    449{
    450	skl_ipc_int_disable(dsp);
    451
    452	free_irq(dsp->irq, dsp);
    453	skl_ipc_op_int_disable(dsp);
    454	skl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK);
    455}
    456EXPORT_SYMBOL_GPL(skl_dsp_free);
    457
    458bool is_skl_dsp_running(struct sst_dsp *ctx)
    459{
    460	return (ctx->sst_state == SKL_DSP_RUNNING);
    461}
    462EXPORT_SYMBOL_GPL(is_skl_dsp_running);