Required properties:
- compatible Should be "mediatek,mt8183-scp"
-- reg Should contain the address ranges for the two memory
- regions, SRAM and CFG.
-- reg-names Contains the corresponding names for the two memory
- regions. These should be named "sram" & "cfg".
+- reg Should contain the address ranges for memory regions:
+ SRAM, CFG, and L1TCM.
+- reg-names Contains the corresponding names for the memory regions:
+ "sram", "cfg", and "l1tcm".
- clocks Clock for co-processor (See: ../clock/clock-bindings.txt)
- clock-names Contains the corresponding name for the clock. This
should be named "main".
"qcom,sm8250-adsp-pas"
"qcom,sm8250-cdsp-pas"
"qcom,sm8250-slpi-pas"
+ "qcom,sm8350-adsp-pas"
+ "qcom,sm8350-cdsp-pas"
+ "qcom,sm8350-slpi-pas"
+ "qcom,sm8350-mpss-pas"
- interrupts-extended:
Usage: required
qcom,sm8250-adsp-pas:
qcom,sm8250-cdsp-pas:
qcom,sm8250-slpi-pas:
+ qcom,sm8350-adsp-pas:
+ qcom,sm8350-cdsp-pas:
+ qcom,sm8350-slpi-pas:
must be "wdog", "fatal", "ready", "handover", "stop-ack"
qcom,qcs404-wcss-pas:
qcom,sc7180-mpss-pas:
qcom,sm8150-mpss-pas:
+ qcom,sm8350-mpss-pas:
must be "wdog", "fatal", "ready", "handover", "stop-ack",
"shutdown-ack"
qcom,sm8150-adsp-pas:
qcom,sm8150-cdsp-pas:
qcom,sm8250-cdsp-pas:
+ qcom,sm8350-cdsp-pas:
must be "cx", "load_state"
qcom,sc7180-mpss-pas:
qcom,sm8150-mpss-pas:
+ qcom,sm8350-mpss-pas:
must be "cx", "load_state", "mss"
qcom,sm8250-adsp-pas:
+ qcom,sm8350-adsp-pas:
qcom,sm8150-slpi-pas:
qcom,sm8250-slpi-pas:
+ qcom,sm8350-slpi-pas:
must be "lcx", "lmx", "load_state"
- memory-region:
Definition: must be one of:
"qcom,wcn3620",
"qcom,wcn3660",
+ "qcom,wcn3660b",
"qcom,wcn3680"
- clocks:
depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
depends on QCOM_SYSMON || QCOM_SYSMON=n
+ depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n
select MFD_SYSCON
select QCOM_PIL_INFO
select QCOM_MDT_LOADER
select QCOM_RPROC_COMMON
help
Say y here to support the Peripheral Image Loader
- for the Qualcomm Technology Inc. ADSP remote processors.
+ for the non-TrustZone part of Qualcomm Technology Inc. ADSP and CDSP
+ remote processors. The TrustZone part is handled by QCOM_Q6V5_PAS
+ driver.
config QCOM_Q6V5_MSS
tristate "Qualcomm Hexagon V5 self-authenticating modem subsystem support"
depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
depends on QCOM_SYSMON || QCOM_SYSMON=n
+ depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n
select MFD_SYSCON
select QCOM_MDT_LOADER
select QCOM_PIL_INFO
select QCOM_SCM
help
Say y here to support the Qualcomm self-authenticating modem
- subsystem based on Hexagon V5.
+ subsystem based on Hexagon V5. The TrustZone based system is
+ handled by QCOM_Q6V5_PAS driver.
config QCOM_Q6V5_PAS
tristate "Qualcomm Hexagon v5 Peripheral Authentication Service support"
depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
depends on QCOM_SYSMON || QCOM_SYSMON=n
+ depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n
select MFD_SYSCON
select QCOM_PIL_INFO
select QCOM_MDT_LOADER
help
Say y here to support the TrustZone based Peripheral Image Loader
for the Qualcomm Hexagon v5 based remote processors. This is commonly
- used to control subsystems such as ADSP, Compute and Sensor.
+ used to control subsystems such as ADSP (Audio DSP),
+ CDSP (Compute DSP), MPSS (Modem Peripheral SubSystem), and
+ SLPI (Sensor Low Power Island).
config QCOM_Q6V5_WCSS
tristate "Qualcomm Hexagon based WCSS Peripheral Image Loader"
depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
depends on QCOM_SYSMON || QCOM_SYSMON=n
+ depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n
select MFD_SYSCON
select QCOM_MDT_LOADER
select QCOM_PIL_INFO
select QCOM_SCM
help
Say y here to support the Qualcomm Peripheral Image Loader for the
- Hexagon V5 based WCSS remote processors.
+ Hexagon V5 based WCSS remote processors on e.g. IPQ8074. This is
+ a non-TrustZone wireless subsystem.
config QCOM_SYSMON
tristate "Qualcomm sysmon driver"
depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
depends on QCOM_SMEM
depends on QCOM_SYSMON || QCOM_SYSMON=n
+ depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n
select QCOM_MDT_LOADER
select QCOM_PIL_INFO
select QCOM_RPROC_COMMON
select QCOM_SCM
help
- Say y here to support the Peripheral Image Loader for the Qualcomm
- Wireless Connectivity Subsystem.
+ Say y here to support the Peripheral Image Loader for loading WCNSS
+ firmware and boot the core on e.g. MSM8974, MSM8916. The firmware is
+ verified and booted with the help of the Peripheral Authentication
+ System (PAS) in TrustZone.
config ST_REMOTEPROC
tristate "ST remoteproc support"
#define AUX_CTRL_NMI BIT(1)
#define AUX_CTRL_SW_RESET BIT(0)
+static bool auto_boot;
+module_param(auto_boot, bool, 0400);
+MODULE_PARM_DESC(auto_boot,
+ "Auto-boot the remote processor [default=false]");
+
struct vpu_mem_map {
const char *name;
unsigned int da;
if (!rproc)
return -ENOMEM;
+ rproc->auto_boot = auto_boot;
+
vpu = rproc->priv;
vpu->dev = &pdev->dev;
platform_set_drvdata(pdev, vpu);
#define MT8192_CORE0_SW_RSTN_CLR 0x10000
#define MT8192_CORE0_SW_RSTN_SET 0x10004
+#define MT8192_CORE0_MEM_ATT_PREDEF 0x10008
+#define MT8192_CORE0_WDT_IRQ 0x10030
#define MT8192_CORE0_WDT_CFG 0x10034
#define SCP_FW_VER_LEN 32
void (*scp_reset_assert)(struct mtk_scp *scp);
void (*scp_reset_deassert)(struct mtk_scp *scp);
void (*scp_stop)(struct mtk_scp *scp);
+ void *(*scp_da_to_va)(struct mtk_scp *scp, u64 da, size_t len);
u32 host_to_scp_reg;
u32 host_to_scp_int_bit;
void __iomem *reg_base;
void __iomem *sram_base;
size_t sram_size;
+ phys_addr_t sram_phys;
+ void __iomem *l1tcm_base;
+ size_t l1tcm_size;
+ phys_addr_t l1tcm_phys;
const struct mtk_scp_of_data *data;
scp_to_host = readl(scp->reg_base + MT8192_SCP2APMCU_IPC_SET);
- if (scp_to_host & MT8192_SCP_IPC_INT_BIT)
+ if (scp_to_host & MT8192_SCP_IPC_INT_BIT) {
scp_ipi_handler(scp);
- else
- scp_wdt_handler(scp, scp_to_host);
- /*
- * SCP won't send another interrupt until we clear
- * MT8192_SCP2APMCU_IPC.
- */
- writel(MT8192_SCP_IPC_INT_BIT,
- scp->reg_base + MT8192_SCP2APMCU_IPC_CLR);
+ /*
+ * SCP won't send another interrupt until we clear
+ * MT8192_SCP2APMCU_IPC.
+ */
+ writel(MT8192_SCP_IPC_INT_BIT,
+ scp->reg_base + MT8192_SCP2APMCU_IPC_CLR);
+ } else {
+ scp_wdt_handler(scp, scp_to_host);
+ writel(1, scp->reg_base + MT8192_CORE0_WDT_IRQ);
+ }
}
static irqreturn_t scp_irq_handler(int irq, void *priv)
mt8192_power_on_sram(scp->reg_base + MT8192_L1TCM_SRAM_PDN);
mt8192_power_on_sram(scp->reg_base + MT8192_CPU0_SRAM_PD);
+ /* enable MPU for all memory regions */
+ writel(0xff, scp->reg_base + MT8192_CORE0_MEM_ATT_PREDEF);
+
return 0;
}
return ret;
}
-static void *scp_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *mt8183_scp_da_to_va(struct mtk_scp *scp, u64 da, size_t len)
{
- struct mtk_scp *scp = (struct mtk_scp *)rproc->priv;
int offset;
if (da < scp->sram_size) {
return NULL;
}
+static void *mt8192_scp_da_to_va(struct mtk_scp *scp, u64 da, size_t len)
+{
+ int offset;
+
+ if (da >= scp->sram_phys &&
+ (da + len) <= scp->sram_phys + scp->sram_size) {
+ offset = da - scp->sram_phys;
+ return (void __force *)scp->sram_base + offset;
+ }
+
+ /* optional memory region */
+ if (scp->l1tcm_size &&
+ da >= scp->l1tcm_phys &&
+ (da + len) <= scp->l1tcm_phys + scp->l1tcm_size) {
+ offset = da - scp->l1tcm_phys;
+ return (void __force *)scp->l1tcm_base + offset;
+ }
+
+ /* optional memory region */
+ if (scp->dram_size &&
+ da >= scp->dma_addr &&
+ (da + len) <= scp->dma_addr + scp->dram_size) {
+ offset = da - scp->dma_addr;
+ return scp->cpu_addr + offset;
+ }
+
+ return NULL;
+}
+
+static void *scp_da_to_va(struct rproc *rproc, u64 da, size_t len)
+{
+ struct mtk_scp *scp = (struct mtk_scp *)rproc->priv;
+
+ return scp->data->scp_da_to_va(scp, da, len);
+}
+
static void mt8183_scp_stop(struct mtk_scp *scp)
{
/* Disable SCP watchdog */
goto free_rproc;
}
scp->sram_size = resource_size(res);
+ scp->sram_phys = res->start;
+
+ /* l1tcm is an optional memory region */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "l1tcm");
+ scp->l1tcm_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR((__force void *)scp->l1tcm_base)) {
+ ret = PTR_ERR((__force void *)scp->l1tcm_base);
+ if (ret != -EINVAL) {
+ dev_err(dev, "Failed to map l1tcm memory\n");
+ goto free_rproc;
+ }
+ } else {
+ scp->l1tcm_size = resource_size(res);
+ scp->l1tcm_phys = res->start;
+ }
mutex_init(&scp->send_lock);
for (i = 0; i < SCP_IPI_MAX; i++)
mutex_init(&scp->ipi_desc[i].lock);
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
- scp->reg_base = devm_ioremap_resource(dev, res);
+ scp->reg_base = devm_platform_ioremap_resource_byname(pdev, "cfg");
if (IS_ERR((__force void *)scp->reg_base)) {
dev_err(dev, "Failed to parse and map cfg memory\n");
ret = PTR_ERR((__force void *)scp->reg_base);
.scp_reset_assert = mt8183_scp_reset_assert,
.scp_reset_deassert = mt8183_scp_reset_deassert,
.scp_stop = mt8183_scp_stop,
+ .scp_da_to_va = mt8183_scp_da_to_va,
.host_to_scp_reg = MT8183_HOST_TO_SCP,
.host_to_scp_int_bit = MT8183_HOST_IPC_INT_BIT,
.ipi_buf_offset = 0x7bdb0,
.scp_reset_assert = mt8192_scp_reset_assert,
.scp_reset_deassert = mt8192_scp_reset_deassert,
.scp_stop = mt8192_scp_stop,
+ .scp_da_to_va = mt8192_scp_da_to_va,
.host_to_scp_reg = MT8192_GIPC_IN_SET,
.host_to_scp_int_bit = MT8192_HOST_IPC_INT_BIT,
};
.ssctl_id = 0x14,
};
+static const struct adsp_data sm8350_adsp_resource = {
+ .crash_reason_smem = 423,
+ .firmware_name = "adsp.mdt",
+ .pas_id = 1,
+ .has_aggre2_clk = false,
+ .auto_boot = true,
+ .active_pd_names = (char*[]){
+ "load_state",
+ NULL
+ },
+ .proxy_pd_names = (char*[]){
+ "lcx",
+ "lmx",
+ NULL
+ },
+ .ssr_name = "lpass",
+ .sysmon_name = "adsp",
+ .ssctl_id = 0x14,
+};
+
static const struct adsp_data msm8998_adsp_resource = {
.crash_reason_smem = 423,
.firmware_name = "adsp.mdt",
.ssctl_id = 0x17,
};
+static const struct adsp_data sm8350_cdsp_resource = {
+ .crash_reason_smem = 601,
+ .firmware_name = "cdsp.mdt",
+ .pas_id = 18,
+ .has_aggre2_clk = false,
+ .auto_boot = true,
+ .active_pd_names = (char*[]){
+ "load_state",
+ NULL
+ },
+ .proxy_pd_names = (char*[]){
+ "cx",
+ NULL
+ },
+ .ssr_name = "cdsp",
+ .sysmon_name = "cdsp",
+ .ssctl_id = 0x17,
+};
+
static const struct adsp_data mpss_resource_init = {
.crash_reason_smem = 421,
.firmware_name = "modem.mdt",
.ssctl_id = 0x16,
};
+static const struct adsp_data sm8350_slpi_resource = {
+ .crash_reason_smem = 424,
+ .firmware_name = "slpi.mdt",
+ .pas_id = 12,
+ .has_aggre2_clk = false,
+ .auto_boot = true,
+ .active_pd_names = (char*[]){
+ "load_state",
+ NULL
+ },
+ .proxy_pd_names = (char*[]){
+ "lcx",
+ "lmx",
+ NULL
+ },
+ .ssr_name = "dsps",
+ .sysmon_name = "slpi",
+ .ssctl_id = 0x16,
+};
+
static const struct adsp_data msm8998_slpi_resource = {
.crash_reason_smem = 424,
.firmware_name = "slpi.mdt",
{ .compatible = "qcom,sm8250-adsp-pas", .data = &sm8250_adsp_resource},
{ .compatible = "qcom,sm8250-cdsp-pas", .data = &sm8250_cdsp_resource},
{ .compatible = "qcom,sm8250-slpi-pas", .data = &sm8250_slpi_resource},
+ { .compatible = "qcom,sm8350-adsp-pas", .data = &sm8350_adsp_resource},
+ { .compatible = "qcom,sm8350-cdsp-pas", .data = &sm8350_cdsp_resource},
+ { .compatible = "qcom,sm8350-slpi-pas", .data = &sm8350_slpi_resource},
+ { .compatible = "qcom,sm8350-mpss-pas", .data = &mpss_resource_init},
{ },
};
MODULE_DEVICE_TABLE(of, adsp_of_match);
if (IS_ERR(mmio)) {
ret = PTR_ERR(mmio);
goto free_rproc;
- };
+ }
ret = wcnss_alloc_memory_region(wcnss);
if (ret)
static const struct of_device_id iris_of_match[] = {
{ .compatible = "qcom,wcn3620", .data = &wcn3620_data },
{ .compatible = "qcom,wcn3660", .data = &wcn3660_data },
+ { .compatible = "qcom,wcn3660b", .data = &wcn3680_data },
{ .compatible = "qcom,wcn3680", .data = &wcn3680_data },
{}
};
goto out;
}
- kfree(rproc->firmware);
+ kfree_const(rproc->firmware);
rproc->firmware = p;
out:
ddata->mb[i].chan = mbox_request_channel_byname(cl, name);
if (IS_ERR(ddata->mb[i].chan)) {
- if (PTR_ERR(ddata->mb[i].chan) == -EPROBE_DEFER)
+ if (PTR_ERR(ddata->mb[i].chan) == -EPROBE_DEFER) {
+ dev_err_probe(dev->parent,
+ PTR_ERR(ddata->mb[i].chan),
+ "failed to request mailbox %s\n",
+ name);
goto err_probe;
+ }
dev_warn(dev, "cannot get %s mbox\n", name);
ddata->mb[i].chan = NULL;
}
irq = platform_get_irq(pdev, 0);
if (irq == -EPROBE_DEFER)
- return -EPROBE_DEFER;
+ return dev_err_probe(dev, irq, "failed to get interrupt\n");
if (irq > 0) {
err = devm_request_irq(dev, irq, stm32_rproc_wdg, 0,
dev_name(dev), pdev);
- if (err) {
- dev_err(dev, "failed to request wdg irq\n");
- return err;
- }
+ if (err)
+ return dev_err_probe(dev, err,
+ "failed to request wdg irq\n");
ddata->wdg_irq = irq;
}
ddata->rst = devm_reset_control_get_by_index(dev, 0);
- if (IS_ERR(ddata->rst)) {
- dev_err(dev, "failed to get mcu reset\n");
- return PTR_ERR(ddata->rst);
- }
+ if (IS_ERR(ddata->rst))
+ return dev_err_probe(dev, PTR_ERR(ddata->rst),
+ "failed to get mcu_reset\n");
/*
* if platform is secured the hold boot bit must be written by