remoteproc: qcom: Add support for memory sandbox

Update pil driver with SMMU mapping for allowing authorised
memory access to ADSP firmware, by carveout reserved adsp memory
region from device tree file.

Signed-off-by: Srinivasa Rao Mandadapu <quic_srivasam@quicinc.com>
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
Link: https://lore.kernel.org/r/1664368073-13659-8-git-send-email-quic_srivasam@quicinc.com
This commit is contained in:
Srinivasa Rao Mandadapu 2022-09-28 17:57:53 +05:30 committed by Bjorn Andersson
parent 9ece961916
commit f22eedff28

View file

@ -9,6 +9,7 @@
#include <linux/firmware.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iommu.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
@ -48,6 +49,8 @@
#define LPASS_PWR_ON_REG 0x10
#define LPASS_HALTREQ_REG 0x0
#define SID_MASK_DEFAULT 0xF
#define QDSP6SS_XO_CBCR 0x38
#define QDSP6SS_CORE_CBCR 0x20
#define QDSP6SS_SLEEP_CBCR 0x3c
@ -332,6 +335,47 @@ static int adsp_load(struct rproc *rproc, const struct firmware *fw)
return 0;
}
static void adsp_unmap_carveout(struct rproc *rproc)
{
struct qcom_adsp *adsp = rproc->priv;
if (adsp->has_iommu)
iommu_unmap(rproc->domain, adsp->mem_phys, adsp->mem_size);
}
static int adsp_map_carveout(struct rproc *rproc)
{
struct qcom_adsp *adsp = rproc->priv;
struct of_phandle_args args;
long long sid;
unsigned long iova;
int ret;
if (!adsp->has_iommu)
return 0;
if (!rproc->domain)
return -EINVAL;
ret = of_parse_phandle_with_args(adsp->dev->of_node, "iommus", "#iommu-cells", 0, &args);
if (ret < 0)
return ret;
sid = args.args[0] & SID_MASK_DEFAULT;
/* Add SID configuration for ADSP Firmware to SMMU */
iova = adsp->mem_phys | (sid << 32);
ret = iommu_map(rproc->domain, iova, adsp->mem_phys,
adsp->mem_size, IOMMU_READ | IOMMU_WRITE);
if (ret) {
dev_err(adsp->dev, "Unable to map ADSP Physical Memory\n");
return ret;
}
return 0;
}
static int adsp_start(struct rproc *rproc)
{
struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
@ -342,9 +386,15 @@ static int adsp_start(struct rproc *rproc)
if (ret)
return ret;
ret = adsp_map_carveout(rproc);
if (ret) {
dev_err(adsp->dev, "ADSP smmu mapping failed\n");
goto disable_irqs;
}
ret = clk_prepare_enable(adsp->xo);
if (ret)
goto disable_irqs;
goto adsp_smmu_unmap;
ret = qcom_rproc_pds_enable(adsp, adsp->proxy_pds,
adsp->proxy_pd_count);
@ -400,6 +450,8 @@ static int adsp_start(struct rproc *rproc)
qcom_rproc_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
disable_xo_clk:
clk_disable_unprepare(adsp->xo);
adsp_smmu_unmap:
adsp_unmap_carveout(rproc);
disable_irqs:
qcom_q6v5_unprepare(&adsp->q6v5);
@ -428,6 +480,8 @@ static int adsp_stop(struct rproc *rproc)
if (ret)
dev_err(adsp->dev, "failed to shutdown: %d\n", ret);
adsp_unmap_carveout(rproc);
handover = qcom_q6v5_unprepare(&adsp->q6v5);
if (handover)
qcom_adsp_pil_handover(&adsp->q6v5);