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

acp-stream.c (5366B)


      1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
      2//
      3// This file is provided under a dual BSD/GPLv2 license. When using or
      4// redistributing this file, you may do so under either license.
      5//
      6// Copyright(c) 2021 Advanced Micro Devices, Inc.
      7//
      8// Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
      9
     10/*
     11 * Hardware interface for generic AMD audio DSP ACP IP
     12 */
     13
     14#include "../ops.h"
     15#include "acp-dsp-offset.h"
     16#include "acp.h"
     17
     18#define PTE_GRP1_OFFSET		0x00000000
     19#define PTE_GRP2_OFFSET		0x00800000
     20#define PTE_GRP3_OFFSET		0x01000000
     21#define PTE_GRP4_OFFSET		0x01800000
     22#define PTE_GRP5_OFFSET		0x02000000
     23#define PTE_GRP6_OFFSET		0x02800000
     24#define PTE_GRP7_OFFSET		0x03000000
     25#define PTE_GRP8_OFFSET		0x03800000
     26
     27int acp_dsp_stream_config(struct snd_sof_dev *sdev, struct acp_dsp_stream *stream)
     28{
     29	unsigned int pte_reg, pte_size, phy_addr_offset, index;
     30	int stream_tag = stream->stream_tag;
     31	u32 low, high, offset, reg_val;
     32	dma_addr_t addr;
     33	int page_idx;
     34
     35	switch (stream_tag) {
     36	case 1:
     37		pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_1;
     38		pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1;
     39		offset = offsetof(struct scratch_reg_conf, grp1_pte);
     40		stream->reg_offset = PTE_GRP1_OFFSET;
     41		break;
     42	case 2:
     43		pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_2;
     44		pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2;
     45		offset = offsetof(struct scratch_reg_conf, grp2_pte);
     46		stream->reg_offset = PTE_GRP2_OFFSET;
     47		break;
     48	case 3:
     49		pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_3;
     50		pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_3;
     51		offset = offsetof(struct scratch_reg_conf, grp3_pte);
     52		stream->reg_offset = PTE_GRP3_OFFSET;
     53		break;
     54	case 4:
     55		pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_4;
     56		pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_4;
     57		offset = offsetof(struct scratch_reg_conf, grp4_pte);
     58		stream->reg_offset = PTE_GRP4_OFFSET;
     59		break;
     60	case 5:
     61		pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_5;
     62		pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5;
     63		offset = offsetof(struct scratch_reg_conf, grp5_pte);
     64		stream->reg_offset = PTE_GRP5_OFFSET;
     65		break;
     66	case 6:
     67		pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_6;
     68		pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_6;
     69		offset = offsetof(struct scratch_reg_conf, grp6_pte);
     70		stream->reg_offset = PTE_GRP6_OFFSET;
     71		break;
     72	case 7:
     73		pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_7;
     74		pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_7;
     75		offset = offsetof(struct scratch_reg_conf, grp7_pte);
     76		stream->reg_offset = PTE_GRP7_OFFSET;
     77		break;
     78	case 8:
     79		pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_8;
     80		pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_8;
     81		offset = offsetof(struct scratch_reg_conf, grp8_pte);
     82		stream->reg_offset = PTE_GRP8_OFFSET;
     83		break;
     84	default:
     85		dev_err(sdev->dev, "Invalid stream tag %d\n", stream_tag);
     86		return -EINVAL;
     87	}
     88
     89	/* write phy_addr in scratch memory */
     90
     91	phy_addr_offset = offsetof(struct scratch_reg_conf, reg_offset);
     92	index = stream_tag - 1;
     93	phy_addr_offset = phy_addr_offset + index * 4;
     94
     95	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 +
     96			  phy_addr_offset, stream->reg_offset);
     97
     98	/* Group Enable */
     99	reg_val = ACP_SRAM_PTE_OFFSET + offset;
    100	snd_sof_dsp_write(sdev, ACP_DSP_BAR, pte_reg, reg_val | BIT(31));
    101	snd_sof_dsp_write(sdev, ACP_DSP_BAR, pte_size, PAGE_SIZE_4K_ENABLE);
    102
    103	for (page_idx = 0; page_idx < stream->num_pages; page_idx++) {
    104		addr = snd_sgbuf_get_addr(stream->dmab, page_idx * PAGE_SIZE);
    105
    106		/* Load the low address of page int ACP SRAM through SRBM */
    107		low = lower_32_bits(addr);
    108		high = upper_32_bits(addr);
    109
    110		snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + offset, low);
    111
    112		high |= BIT(31);
    113		snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + offset + 4, high);
    114		/* Move to next physically contiguous page */
    115		offset += 8;
    116	}
    117
    118	/* Flush ATU Cache after PTE Update */
    119	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACPAXI2AXI_ATU_CTRL, ACP_ATU_CACHE_INVALID);
    120
    121	return 0;
    122}
    123
    124struct acp_dsp_stream *acp_dsp_stream_get(struct snd_sof_dev *sdev, int tag)
    125{
    126	struct acp_dev_data *adata = sdev->pdata->hw_pdata;
    127	struct acp_dsp_stream *stream = adata->stream_buf;
    128	int i;
    129
    130	for (i = 0; i < ACP_MAX_STREAM; i++, stream++) {
    131		if (stream->active)
    132			continue;
    133
    134		/* return stream if tag not specified*/
    135		if (!tag) {
    136			stream->active = 1;
    137			return stream;
    138		}
    139
    140		/* check if this is the requested stream tag */
    141		if (stream->stream_tag == tag) {
    142			stream->active = 1;
    143			return stream;
    144		}
    145	}
    146
    147	dev_err(sdev->dev, "stream %d active or no inactive stream\n", tag);
    148	return NULL;
    149}
    150EXPORT_SYMBOL_NS(acp_dsp_stream_get, SND_SOC_SOF_AMD_COMMON);
    151
    152int acp_dsp_stream_put(struct snd_sof_dev *sdev,
    153		       struct acp_dsp_stream *acp_stream)
    154{
    155	struct acp_dev_data *adata = sdev->pdata->hw_pdata;
    156	struct acp_dsp_stream *stream = adata->stream_buf;
    157	int i;
    158
    159	/* Free an active stream */
    160	for (i = 0; i < ACP_MAX_STREAM; i++, stream++) {
    161		if (stream == acp_stream) {
    162			stream->active = 0;
    163			return 0;
    164		}
    165	}
    166
    167	dev_err(sdev->dev, "Cannot find active stream tag %d\n", acp_stream->stream_tag);
    168	return -EINVAL;
    169}
    170EXPORT_SYMBOL_NS(acp_dsp_stream_put, SND_SOC_SOF_AMD_COMMON);
    171
    172int acp_dsp_stream_init(struct snd_sof_dev *sdev)
    173{
    174	struct acp_dev_data *adata = sdev->pdata->hw_pdata;
    175	int i;
    176
    177	for (i = 0; i < ACP_MAX_STREAM; i++) {
    178		adata->stream_buf[i].sdev = sdev;
    179		adata->stream_buf[i].active = 0;
    180		adata->stream_buf[i].stream_tag = i + 1;
    181	}
    182	return 0;
    183}
    184EXPORT_SYMBOL_NS(acp_dsp_stream_init, SND_SOC_SOF_AMD_COMMON);