lkml.org 
[lkml]   [2021]   [Nov]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 13/21] ASoC: SOF: amd: Add support for SOF firmware authentication
    Date
    From: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>

    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: Julian Schroeder <Julian.Schroeder@amd.com>
    Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
    Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
    Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
    Reviewed-by: Curtis Malainey <curtis@malainey.com>
    Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
    ---
    sound/soc/sof/amd/acp-dsp-offset.h | 4 ++
    sound/soc/sof/amd/acp.c | 66 +++++++++++++++++++++++++++++-
    sound/soc/sof/amd/acp.h | 21 ++++++++++
    sound/soc/sof/amd/pci-rn.c | 5 +++
    4 files changed, 95 insertions(+), 1 deletion(-)

    diff --git a/sound/soc/sof/amd/acp-dsp-offset.h b/sound/soc/sof/amd/acp-dsp-offset.h
    index 1d11e9d69dce..63f13c111b24 100644
    --- a/sound/soc/sof/amd/acp-dsp-offset.h
    +++ b/sound/soc/sof/amd/acp-dsp-offset.h
    @@ -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

    diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c
    index 74ede28aa8d8..4c5550e8d364 100644
    --- a/sound/soc/sof/amd/acp.c
    +++ b/sound/soc/sof/amd/acp.c
    @@ -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);

    diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h
    index fd923f72a01a..a2f8e4219066 100644
    --- a/sound/soc/sof/amd/acp.h
    +++ b/sound/soc/sof/amd/acp.h
    @@ -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
    diff --git a/sound/soc/sof/amd/pci-rn.c b/sound/soc/sof/amd/pci-rn.c
    index 3c379a5ef231..392ffbdf6417 100644
    --- a/sound/soc/sof/amd/pci-rn.c
    +++ b/sound/soc/sof/amd/pci-rn.c
    @@ -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",
    --
    2.27.0
    \
     
     \ /
      Last update: 2021-11-17 10:39    [W:6.339 / U:0.048 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site