Unverified Commit f063eba3 authored by Ajit Kumar Pandey's avatar Ajit Kumar Pandey Committed by Mark Brown
Browse files

ASoC: SOF: amd: Add support for SOF firmware authentication



Add callback to notify PSP after loading firmware on DSP. PSP will
validate the loaded firmware and set qualifier bit to run firmware
on secured AMD systems.

Signed-off-by: default avatarJulian Schroeder <Julian.Schroeder@amd.com>
Signed-off-by: default avatarAjit Kumar Pandey <AjitKumar.Pandey@amd.com>
Reviewed-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: default avatarCurtis Malainey <curtis@malainey.com>
Signed-off-by: default avatarDaniel Baluta <daniel.baluta@nxp.com>
Link: https://lore.kernel.org/r/20211117093734.17407-14-daniel.baluta@oss.nxp.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 4627421f
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -54,6 +54,9 @@
#define ACP_PGFSM_STATUS			0x1420

/* Registers from ACP_INTR block */
#define ACP_EXTERNAL_INTR_ENB			0x1800
#define ACP_EXTERNAL_INTR_CNTL			0x1804
#define ACP_EXTERNAL_INTR_STAT			0x1808
#define ACP_DSP_SW_INTR_CNTL			0x1814
#define ACP_DSP_SW_INTR_STAT                    0x1818
#define ACP_SW_INTR_TRIG                        0x181C
@@ -68,6 +71,7 @@
#define ACP_SHA_DMA_CMD_STS			0x1CC0
#define ACP_SHA_DMA_ERR_STATUS			0x1CC4
#define ACP_SHA_TRANSFER_BYTE_CNT		0x1CC8
#define ACP_SHA_PSP_ACK                         0x1C74

#define ACP_SCRATCH_REG_0			0x10000

+65 −1
Original line number Diff line number Diff line
@@ -20,6 +20,22 @@
#include "acp.h"
#include "acp-dsp-offset.h"

static int smn_write(struct pci_dev *dev, u32 smn_addr, u32 data)
{
	pci_write_config_dword(dev, 0x60, smn_addr);
	pci_write_config_dword(dev, 0x64, data);

	return 0;
}

static int smn_read(struct pci_dev *dev, u32 smn_addr, u32 *data)
{
	pci_write_config_dword(dev, 0x60, smn_addr);
	pci_read_config_dword(dev, 0x64, data);

	return 0;
}

static void configure_acp_groupregisters(struct acp_dev_data *adata)
{
	struct snd_sof_dev *sdev = adata->dev;
@@ -135,6 +151,25 @@ int configure_and_run_dma(struct acp_dev_data *adata, unsigned int src_addr,
	return ret;
}

static int psp_fw_validate(struct acp_dev_data *adata)
{
	struct snd_sof_dev *sdev = adata->dev;
	int timeout;
	u32 data;

	smn_write(adata->smn_dev, MP0_C2PMSG_26_REG, MBOX_ACP_SHA_DMA_COMMAND);

	for (timeout = ACP_PSP_TIMEOUT_COUNTER; timeout > 0; timeout--) {
		msleep(20);
		smn_read(adata->smn_dev, MP0_C2PMSG_26_REG, &data);
		if (data & MBOX_READY_MASK)
			return 0;
	}

	dev_err(sdev->dev, "FW validation timedout: status %x\n", data & MBOX_STATUS_MASK);
	return -ETIMEDOUT;
}

int configure_and_run_sha_dma(struct acp_dev_data *adata, void *image_addr,
			      unsigned int start_addr, unsigned int dest_addr,
			      unsigned int image_length)
@@ -174,7 +209,9 @@ int configure_and_run_sha_dma(struct acp_dev_data *adata, void *image_addr,
		return ret;
	}

	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SHA_DSP_FW_QUALIFIER, DSP_FW_RUN_ENABLE);
	ret = psp_fw_validate(adata);
	if (ret)
		return ret;

	fw_qualifier = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SHA_DSP_FW_QUALIFIER);
	if (!(fw_qualifier & DSP_FW_RUN_ENABLE)) {
@@ -238,6 +275,13 @@ static irqreturn_t acp_irq_thread(int irq, void *context)
	struct snd_sof_dev *sdev = context;
	unsigned int val;

	val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_EXTERNAL_INTR_STAT);
	if (val & ACP_SHA_STAT) {
		/* Clear SHA interrupt raised by PSP */
		snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_EXTERNAL_INTR_STAT, val);
		return IRQ_HANDLED;
	}

	val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_DSP_SW_INTR_STAT);
	if (val & ACP_DSP_TO_HOST_IRQ) {
		sof_ops(sdev)->irq_thread(irq, sdev);
@@ -326,6 +370,7 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev)
{
	struct pci_dev *pci = to_pci_dev(sdev->dev);
	struct acp_dev_data *adata;
	const struct sof_amd_acp_desc *chip;
	unsigned int addr;
	int ret;

@@ -346,18 +391,32 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev)

	sdev->pdata->hw_pdata = adata;

	chip = get_chip_info(sdev->pdata);
	if (!chip) {
		dev_err(sdev->dev, "no such device supported, chip id:%x\n", pci->device);
		return -EIO;
	}

	adata->smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, chip->host_bridge_id, NULL);
	if (!adata->smn_dev) {
		dev_err(sdev->dev, "Failed to get host bridge device\n");
		return -ENODEV;
	}

	sdev->ipc_irq = pci->irq;
	ret = request_threaded_irq(sdev->ipc_irq, acp_irq_handler, acp_irq_thread,
				   IRQF_SHARED, "AudioDSP", sdev);
	if (ret < 0) {
		dev_err(sdev->dev, "failed to register IRQ %d\n",
			sdev->ipc_irq);
		pci_dev_put(adata->smn_dev);
		return ret;
	}

	ret = acp_init(sdev);
	if (ret < 0) {
		free_irq(sdev->ipc_irq, sdev);
		pci_dev_put(adata->smn_dev);
		return ret;
	}

@@ -371,6 +430,11 @@ EXPORT_SYMBOL_NS(amd_sof_acp_probe, SND_SOC_SOF_AMD_COMMON);

int amd_sof_acp_remove(struct snd_sof_dev *sdev)
{
	struct acp_dev_data *adata = sdev->pdata->hw_pdata;

	if (adata->smn_dev)
		pci_dev_put(adata->smn_dev);

	if (sdev->ipc_irq)
		free_irq(sdev->ipc_irq, sdev);

+21 −0
Original line number Diff line number Diff line
@@ -52,6 +52,15 @@

#define ACP_DSP_TO_HOST_IRQ			0x04

#define HOST_BRIDGE_CZN				0x1630
#define ACP_SHA_STAT				0x8000
#define ACP_PSP_TIMEOUT_COUNTER			5
#define ACP_EXT_INTR_ERROR_STAT			0x20000000
#define MP0_C2PMSG_26_REG			0x03810570
#define MBOX_ACP_SHA_DMA_COMMAND		0x330000
#define MBOX_READY_MASK				0x80000000
#define MBOX_STATUS_MASK			0xFFFF

struct  acp_atu_grp_pte {
	u32 low;
	u32 high;
@@ -140,6 +149,7 @@ struct acp_dev_data {
	struct dma_descriptor dscr_info[ACP_MAX_DESC];
	struct acp_dsp_stream stream_buf[ACP_MAX_STREAM];
	struct acp_dsp_stream *dtrace_stream;
	struct pci_dev *smn_dev;
};

void memcpy_to_scratch(struct snd_sof_dev *sdev, u32 offset, unsigned int *src, size_t bytes);
@@ -202,4 +212,15 @@ int snd_amd_acp_find_config(struct pci_dev *pci);
/* Trace */
int acp_sof_trace_init(struct snd_sof_dev *sdev, u32 *stream_tag);
int acp_sof_trace_release(struct snd_sof_dev *sdev);

struct sof_amd_acp_desc {
	unsigned int host_bridge_id;
};

static inline const struct sof_amd_acp_desc *get_chip_info(struct snd_sof_pdata *pdata)
{
	const struct sof_dev_desc *desc = pdata->desc;

	return desc->chip_info;
}
#endif
+5 −0
Original line number Diff line number Diff line
@@ -43,12 +43,17 @@ static const struct resource renoir_res[] = {
	},
};

static const struct sof_amd_acp_desc renoir_chip_info = {
	.host_bridge_id = HOST_BRIDGE_CZN,
};

static const struct sof_dev_desc renoir_desc = {
	.machines		= snd_soc_acpi_amd_sof_machines,
	.resindex_lpe_base	= 0,
	.resindex_pcicfg_base	= -1,
	.resindex_imr_base	= -1,
	.irqindex_host_ipc	= -1,
	.chip_info		= &renoir_chip_info,
	.default_fw_path	= "amd/sof",
	.default_tplg_path	= "amd/sof-tplg",
	.default_fw_filename	= "sof-rn.ri",