diff options
| -rw-r--r-- | Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml | 198 | ||||
| -rw-r--r-- | drivers/remoteproc/da8xx_remoteproc.c | 57 | ||||
| -rw-r--r-- | drivers/remoteproc/imx_dsp_rproc.c | 45 | ||||
| -rw-r--r-- | drivers/remoteproc/imx_rproc.c | 449 | ||||
| -rw-r--r-- | drivers/remoteproc/imx_rproc.h | 7 | ||||
| -rw-r--r-- | drivers/remoteproc/keystone_remoteproc.c | 95 | ||||
| -rw-r--r-- | drivers/remoteproc/pru_rproc.c | 3 | ||||
| -rw-r--r-- | drivers/remoteproc/qcom_q6v5.c | 8 | ||||
| -rw-r--r-- | drivers/remoteproc/qcom_q6v5_mss.c | 11 | ||||
| -rw-r--r-- | drivers/remoteproc/qcom_q6v5_pas.c | 32 | ||||
| -rw-r--r-- | drivers/remoteproc/ti_k3_common.c | 21 | ||||
| -rw-r--r-- | drivers/remoteproc/ti_k3_dsp_remoteproc.c | 2 | ||||
| -rw-r--r-- | drivers/remoteproc/ti_k3_r5_remoteproc.c | 2 | ||||
| -rw-r--r-- | drivers/remoteproc/wkup_m3_rproc.c | 69 |
14 files changed, 635 insertions, 364 deletions
diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml new file mode 100644 index 000000000000..c47d97004b33 --- /dev/null +++ b/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml @@ -0,0 +1,198 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/remoteproc/qcom,milos-pas.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Milos SoC Peripheral Authentication Service + +maintainers: + - Luca Weiss <luca.weiss@fairphone.com> + +description: + Qualcomm Milos SoC Peripheral Authentication Service loads and boots firmware + on the Qualcomm DSP Hexagon cores. + +properties: + compatible: + enum: + - qcom,milos-adsp-pas + - qcom,milos-cdsp-pas + - qcom,milos-mpss-pas + - qcom,milos-wpss-pas + + reg: + maxItems: 1 + + clocks: + items: + - description: XO clock + + clock-names: + items: + - const: xo + + interrupts: + minItems: 6 + maxItems: 6 + + interrupt-names: + minItems: 6 + maxItems: 6 + + qcom,qmp: + $ref: /schemas/types.yaml#/definitions/phandle + description: Reference to the AOSS side-channel message RAM. + + smd-edge: false + + firmware-name: + minItems: 1 + items: + - description: Firmware name of the Hexagon core + - description: Firmware name of the Hexagon Devicetree + + memory-region: + minItems: 1 + items: + - description: Memory region for core Firmware authentication + - description: Memory region for Devicetree Firmware authentication + +required: + - compatible + - reg + - memory-region + +allOf: + - $ref: /schemas/remoteproc/qcom,pas-common.yaml# + - if: + properties: + compatible: + enum: + - qcom,milos-adsp-pas + - qcom,milos-cdsp-pas + then: + properties: + memory-region: + minItems: 2 + firmware-name: + minItems: 2 + else: + properties: + memory-region: + maxItems: 1 + firmware-name: + maxItems: 1 + + - if: + properties: + compatible: + contains: + enum: + - qcom,milos-adsp-pas + then: + properties: + power-domains: + items: + - description: LCX power domain + - description: LMX power domain + power-domain-names: + items: + - const: lcx + - const: lmx + + - if: + properties: + compatible: + enum: + - qcom,milos-cdsp-pas + - qcom,milos-wpss-pas + then: + properties: + power-domains: + items: + - description: CX power domain + - description: MX power domain + power-domain-names: + items: + - const: cx + - const: mx + + - if: + properties: + compatible: + enum: + - qcom,milos-mpss-pas + then: + properties: + power-domains: + items: + - description: CX power domain + - description: MSS power domain + power-domain-names: + items: + - const: cx + - const: mss + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/clock/qcom,rpmh.h> + #include <dt-bindings/interconnect/qcom,icc.h> + #include <dt-bindings/interconnect/qcom,milos-rpmh.h> + #include <dt-bindings/interrupt-controller/irq.h> + #include <dt-bindings/mailbox/qcom-ipcc.h> + #include <dt-bindings/power/qcom,rpmhpd.h> + + remoteproc@3000000 { + compatible = "qcom,milos-adsp-pas"; + reg = <0x03000000 0x10000>; + + interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 3 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 7 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "shutdown-ack"; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + power-domains = <&rpmhpd RPMHPD_LCX>, + <&rpmhpd RPMHPD_LMX>; + power-domain-names = "lcx", + "lmx"; + + interconnects = <&lpass_ag_noc MASTER_LPASS_PROC QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + + memory-region = <&adspslpi_mem>, <&q6_adsp_dtb_mem>; + + firmware-name = "qcom/milos/vendor/device/adsp.mbn", + "qcom/milos/vendor/device/adsp_dtb.mbn"; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&smp2p_adsp_out 0>; + qcom,smem-state-names = "stop"; + + glink-edge { + interrupts-extended = <&ipcc IPCC_CLIENT_LPASS + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_CLIENT_LPASS + IPCC_MPROC_SIGNAL_GLINK_QMP>; + + label = "lpass"; + qcom,remote-pid = <2>; + + /* ... */ + }; + }; diff --git a/drivers/remoteproc/da8xx_remoteproc.c b/drivers/remoteproc/da8xx_remoteproc.c index 93031f0867d1..e418a2bf5d2e 100644 --- a/drivers/remoteproc/da8xx_remoteproc.c +++ b/drivers/remoteproc/da8xx_remoteproc.c @@ -233,6 +233,13 @@ static int da8xx_rproc_get_internal_memories(struct platform_device *pdev, return 0; } +static void da8xx_rproc_mem_release(void *data) +{ + struct device *dev = data; + + of_reserved_mem_device_release(dev); +} + static int da8xx_rproc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -274,14 +281,13 @@ static int da8xx_rproc_probe(struct platform_device *pdev) ret = of_reserved_mem_device_init(dev); if (ret) return dev_err_probe(dev, ret, "device does not have specific CMA pool\n"); + devm_add_action_or_reset(&pdev->dev, da8xx_rproc_mem_release, &pdev->dev); } - rproc = rproc_alloc(dev, "dsp", &da8xx_rproc_ops, da8xx_fw_name, - sizeof(*drproc)); - if (!rproc) { - ret = -ENOMEM; - goto free_mem; - } + rproc = devm_rproc_alloc(dev, "dsp", &da8xx_rproc_ops, da8xx_fw_name, + sizeof(*drproc)); + if (!rproc) + return -ENOMEM; /* error recovery is not supported at present */ rproc->recovery_disabled = true; @@ -294,9 +300,7 @@ static int da8xx_rproc_probe(struct platform_device *pdev) ret = da8xx_rproc_get_internal_memories(pdev, drproc); if (ret) - goto free_rproc; - - platform_set_drvdata(pdev, rproc); + return ret; /* everything the ISR needs is now setup, so hook it up */ ret = devm_request_threaded_irq(dev, irq, da8xx_rproc_callback, @@ -304,7 +308,7 @@ static int da8xx_rproc_probe(struct platform_device *pdev) rproc); if (ret) { dev_err(dev, "devm_request_threaded_irq error: %d\n", ret); - goto free_rproc; + return ret; } /* @@ -314,7 +318,7 @@ static int da8xx_rproc_probe(struct platform_device *pdev) */ ret = reset_control_assert(dsp_reset); if (ret) - goto free_rproc; + return ret; drproc->chipsig = chipsig; drproc->bootreg = bootreg; @@ -322,39 +326,13 @@ static int da8xx_rproc_probe(struct platform_device *pdev) drproc->irq_data = irq_data; drproc->irq = irq; - ret = rproc_add(rproc); + ret = devm_rproc_add(dev, rproc); if (ret) { dev_err(dev, "rproc_add failed: %d\n", ret); - goto free_rproc; + return ret; } return 0; - -free_rproc: - rproc_free(rproc); -free_mem: - if (dev->of_node) - of_reserved_mem_device_release(dev); - return ret; -} - -static void da8xx_rproc_remove(struct platform_device *pdev) -{ - struct rproc *rproc = platform_get_drvdata(pdev); - struct da8xx_rproc *drproc = rproc->priv; - struct device *dev = &pdev->dev; - - /* - * The devm subsystem might end up releasing things before - * freeing the irq, thus allowing an interrupt to sneak in while - * the device is being removed. This should prevent that. - */ - disable_irq(drproc->irq); - - rproc_del(rproc); - rproc_free(rproc); - if (dev->of_node) - of_reserved_mem_device_release(dev); } static const struct of_device_id davinci_rproc_of_match[] __maybe_unused = { @@ -365,7 +343,6 @@ MODULE_DEVICE_TABLE(of, davinci_rproc_of_match); static struct platform_driver da8xx_rproc_driver = { .probe = da8xx_rproc_probe, - .remove = da8xx_rproc_remove, .driver = { .name = "davinci-rproc", .of_match_table = of_match_ptr(davinci_rproc_of_match), diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index 5ee622bf5352..6e78a01755c7 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -774,7 +774,6 @@ static int imx_dsp_rproc_prepare(struct rproc *rproc) { struct imx_dsp_rproc *priv = rproc->priv; struct device *dev = rproc->dev.parent; - struct rproc_mem_entry *carveout; int ret; ret = imx_dsp_rproc_add_carveout(priv); @@ -785,15 +784,6 @@ static int imx_dsp_rproc_prepare(struct rproc *rproc) pm_runtime_get_sync(dev); - /* - * Clear buffers after pm rumtime for internal ocram is not - * accessible if power and clock are not enabled. - */ - list_for_each_entry(carveout, &rproc->carveouts, node) { - if (carveout->va) - memset(carveout->va, 0, carveout->len); - } - return 0; } @@ -1022,13 +1012,39 @@ static int imx_dsp_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw return 0; } +static int imx_dsp_rproc_load(struct rproc *rproc, const struct firmware *fw) +{ + struct imx_dsp_rproc *priv = rproc->priv; + const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; + struct rproc_mem_entry *carveout; + int ret; + + /* Reset DSP if needed */ + if (dsp_dcfg->reset) + dsp_dcfg->reset(priv); + /* + * Clear buffers after pm rumtime for internal ocram is not + * accessible if power and clock are not enabled. + */ + list_for_each_entry(carveout, &rproc->carveouts, node) { + if (carveout->va) + memset(carveout->va, 0, carveout->len); + } + + ret = imx_dsp_rproc_elf_load_segments(rproc, fw); + if (ret) + return ret; + + return 0; +} + static const struct rproc_ops imx_dsp_rproc_ops = { .prepare = imx_dsp_rproc_prepare, .unprepare = imx_dsp_rproc_unprepare, .start = imx_dsp_rproc_start, .stop = imx_dsp_rproc_stop, .kick = imx_dsp_rproc_kick, - .load = imx_dsp_rproc_elf_load_segments, + .load = imx_dsp_rproc_load, .parse_fw = imx_dsp_rproc_parse_fw, .handle_rsc = imx_dsp_rproc_handle_rsc, .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table, @@ -1189,6 +1205,8 @@ static int imx_dsp_rproc_probe(struct platform_device *pdev) goto err_detach_domains; } + rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_XTENSA); + pm_runtime_enable(dev); return 0; @@ -1214,7 +1232,6 @@ static int imx_dsp_runtime_resume(struct device *dev) { struct rproc *rproc = dev_get_drvdata(dev); struct imx_dsp_rproc *priv = rproc->priv; - const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; int ret; /* @@ -1235,10 +1252,6 @@ static int imx_dsp_runtime_resume(struct device *dev) return ret; } - /* Reset DSP if needed */ - if (dsp_dcfg->reset) - dsp_dcfg->reset(priv); - return 0; } diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index a6eef0080ca9..bb25221a4a89 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -285,161 +285,101 @@ static const struct imx_rproc_att imx_rproc_att_imx6sx[] = { { 0x80000000, 0x80000000, 0x60000000, 0 }, }; -static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn_mmio = { - .src_reg = IMX7D_SRC_SCR, - .src_mask = IMX7D_M4_RST_MASK, - .src_start = IMX7D_M4_START, - .src_stop = IMX8M_M7_STOP, - .gpr_reg = IMX8M_GPR22, - .gpr_wait = IMX8M_GPR22_CM7_CPUWAIT, - .att = imx_rproc_att_imx8mn, - .att_size = ARRAY_SIZE(imx_rproc_att_imx8mn), - .method = IMX_RPROC_MMIO, -}; - -static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn = { - .att = imx_rproc_att_imx8mn, - .att_size = ARRAY_SIZE(imx_rproc_att_imx8mn), - .method = IMX_RPROC_SMC, -}; - -static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = { - .src_reg = IMX7D_SRC_SCR, - .src_mask = IMX7D_M4_RST_MASK, - .src_start = IMX7D_M4_START, - .src_stop = IMX7D_M4_STOP, - .att = imx_rproc_att_imx8mq, - .att_size = ARRAY_SIZE(imx_rproc_att_imx8mq), - .method = IMX_RPROC_MMIO, -}; +static int imx_rproc_arm_smc_start(struct rproc *rproc) +{ + struct arm_smccc_res res; -static const struct imx_rproc_dcfg imx_rproc_cfg_imx8qm = { - .att = imx_rproc_att_imx8qm, - .att_size = ARRAY_SIZE(imx_rproc_att_imx8qm), - .method = IMX_RPROC_SCU_API, -}; + arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_START, 0, 0, 0, 0, 0, 0, &res); -static const struct imx_rproc_dcfg imx_rproc_cfg_imx8qxp = { - .att = imx_rproc_att_imx8qxp, - .att_size = ARRAY_SIZE(imx_rproc_att_imx8qxp), - .method = IMX_RPROC_SCU_API, -}; + return res.a0; +} -static const struct imx_rproc_dcfg imx_rproc_cfg_imx8ulp = { - .att = imx_rproc_att_imx8ulp, - .att_size = ARRAY_SIZE(imx_rproc_att_imx8ulp), - .method = IMX_RPROC_NONE, -}; +static int imx_rproc_mmio_start(struct rproc *rproc) +{ + struct imx_rproc *priv = rproc->priv; + const struct imx_rproc_dcfg *dcfg = priv->dcfg; -static const struct imx_rproc_dcfg imx_rproc_cfg_imx7ulp = { - .att = imx_rproc_att_imx7ulp, - .att_size = ARRAY_SIZE(imx_rproc_att_imx7ulp), - .method = IMX_RPROC_NONE, - .flags = IMX_RPROC_NEED_SYSTEM_OFF, -}; + if (priv->gpr) + return regmap_clear_bits(priv->gpr, dcfg->gpr_reg, dcfg->gpr_wait); -static const struct imx_rproc_dcfg imx_rproc_cfg_imx7d = { - .src_reg = IMX7D_SRC_SCR, - .src_mask = IMX7D_M4_RST_MASK, - .src_start = IMX7D_M4_START, - .src_stop = IMX7D_M4_STOP, - .att = imx_rproc_att_imx7d, - .att_size = ARRAY_SIZE(imx_rproc_att_imx7d), - .method = IMX_RPROC_MMIO, -}; + return regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, dcfg->src_start); +} -static const struct imx_rproc_dcfg imx_rproc_cfg_imx6sx = { - .src_reg = IMX6SX_SRC_SCR, - .src_mask = IMX6SX_M4_RST_MASK, - .src_start = IMX6SX_M4_START, - .src_stop = IMX6SX_M4_STOP, - .att = imx_rproc_att_imx6sx, - .att_size = ARRAY_SIZE(imx_rproc_att_imx6sx), - .method = IMX_RPROC_MMIO, -}; +static int imx_rproc_scu_api_start(struct rproc *rproc) +{ + struct imx_rproc *priv = rproc->priv; -static const struct imx_rproc_dcfg imx_rproc_cfg_imx93 = { - .att = imx_rproc_att_imx93, - .att_size = ARRAY_SIZE(imx_rproc_att_imx93), - .method = IMX_RPROC_SMC, -}; + return imx_sc_pm_cpu_start(priv->ipc_handle, priv->rsrc_id, true, priv->entry); +} static int imx_rproc_start(struct rproc *rproc) { struct imx_rproc *priv = rproc->priv; const struct imx_rproc_dcfg *dcfg = priv->dcfg; struct device *dev = priv->dev; - struct arm_smccc_res res; int ret; ret = imx_rproc_xtr_mbox_init(rproc, true); if (ret) return ret; - switch (dcfg->method) { - case IMX_RPROC_MMIO: - if (priv->gpr) { - ret = regmap_clear_bits(priv->gpr, dcfg->gpr_reg, - dcfg->gpr_wait); - } else { - ret = regmap_update_bits(priv->regmap, dcfg->src_reg, - dcfg->src_mask, - dcfg->src_start); - } - break; - case IMX_RPROC_SMC: - arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_START, 0, 0, 0, 0, 0, 0, &res); - ret = res.a0; - break; - case IMX_RPROC_SCU_API: - ret = imx_sc_pm_cpu_start(priv->ipc_handle, priv->rsrc_id, true, priv->entry); - break; - default: + if (!dcfg->ops || !dcfg->ops->start) return -EOPNOTSUPP; - } + ret = dcfg->ops->start(rproc); if (ret) dev_err(dev, "Failed to enable remote core!\n"); return ret; } -static int imx_rproc_stop(struct rproc *rproc) +static int imx_rproc_arm_smc_stop(struct rproc *rproc) { struct imx_rproc *priv = rproc->priv; - const struct imx_rproc_dcfg *dcfg = priv->dcfg; - struct device *dev = priv->dev; struct arm_smccc_res res; + + arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STOP, 0, 0, 0, 0, 0, 0, &res); + if (res.a1) + dev_info(priv->dev, "Not in wfi, force stopped\n"); + + return res.a0; +} + +static int imx_rproc_mmio_stop(struct rproc *rproc) +{ + struct imx_rproc *priv = rproc->priv; + const struct imx_rproc_dcfg *dcfg = priv->dcfg; int ret; - switch (dcfg->method) { - case IMX_RPROC_MMIO: - if (priv->gpr) { - ret = regmap_set_bits(priv->gpr, dcfg->gpr_reg, - dcfg->gpr_wait); - if (ret) { - dev_err(priv->dev, - "Failed to quiescence M4 platform!\n"); - return ret; - } + if (priv->gpr) { + ret = regmap_set_bits(priv->gpr, dcfg->gpr_reg, dcfg->gpr_wait); + if (ret) { + dev_err(priv->dev, "Failed to quiescence M4 platform!\n"); + return ret; } + } + + return regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, dcfg->src_stop); +} + +static int imx_rproc_scu_api_stop(struct rproc *rproc) +{ + struct imx_rproc *priv = rproc->priv; + + return imx_sc_pm_cpu_start(priv->ipc_handle, priv->rsrc_id, false, priv->entry); +} + +static int imx_rproc_stop(struct rproc *rproc) +{ + struct imx_rproc *priv = rproc->priv; + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + struct device *dev = priv->dev; + int ret; - ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, - dcfg->src_stop); - break; - case IMX_RPROC_SMC: - arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STOP, 0, 0, 0, 0, 0, 0, &res); - ret = res.a0; - if (res.a1) - dev_info(dev, "Not in wfi, force stopped\n"); - break; - case IMX_RPROC_SCU_API: - ret = imx_sc_pm_cpu_start(priv->ipc_handle, priv->rsrc_id, false, priv->entry); - break; - default: + if (!dcfg->ops || !dcfg->ops->stop) return -EOPNOTSUPP; - } + ret = dcfg->ops->stop(rproc); if (ret) dev_err(dev, "Failed to stop remote core\n"); else @@ -922,84 +862,27 @@ static int imx_rproc_attach_pd(struct imx_rproc *priv) return 0; } -static int imx_rproc_detect_mode(struct imx_rproc *priv) +static int imx_rproc_arm_smc_detect_mode(struct rproc *rproc) { - struct regmap_config config = { .name = "imx-rproc" }; - const struct imx_rproc_dcfg *dcfg = priv->dcfg; - struct device *dev = priv->dev; - struct regmap *regmap; + struct imx_rproc *priv = rproc->priv; struct arm_smccc_res res; - int ret; - u32 val; - u8 pt; - switch (dcfg->method) { - case IMX_RPROC_NONE: + arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STARTED, 0, 0, 0, 0, 0, 0, &res); + if (res.a0) priv->rproc->state = RPROC_DETACHED; - return 0; - case IMX_RPROC_SMC: - arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STARTED, 0, 0, 0, 0, 0, 0, &res); - if (res.a0) - priv->rproc->state = RPROC_DETACHED; - return 0; - case IMX_RPROC_SCU_API: - ret = imx_scu_get_handle(&priv->ipc_handle); - if (ret) - return ret; - ret = of_property_read_u32(dev->of_node, "fsl,resource-id", &priv->rsrc_id); - if (ret) { - dev_err(dev, "No fsl,resource-id property\n"); - return ret; - } - - if (priv->rsrc_id == IMX_SC_R_M4_1_PID0) - priv->core_index = 1; - else - priv->core_index = 0; - /* - * If Mcore resource is not owned by Acore partition, It is kicked by ROM, - * and Linux could only do IPC with Mcore and nothing else. - */ - if (imx_sc_rm_is_resource_owned(priv->ipc_handle, priv->rsrc_id)) { - if (of_property_read_u32(dev->of_node, "fsl,entry-address", &priv->entry)) - return -EINVAL; - - return imx_rproc_attach_pd(priv); - } - - priv->rproc->state = RPROC_DETACHED; - priv->rproc->recovery_disabled = false; - rproc_set_feature(priv->rproc, RPROC_FEAT_ATTACH_ON_RECOVERY); - - /* Get partition id and enable irq in SCFW */ - ret = imx_sc_rm_get_resource_owner(priv->ipc_handle, priv->rsrc_id, &pt); - if (ret) { - dev_err(dev, "not able to get resource owner\n"); - return ret; - } - - priv->rproc_pt = pt; - priv->rproc_nb.notifier_call = imx_rproc_partition_notify; - - ret = imx_scu_irq_register_notifier(&priv->rproc_nb); - if (ret) { - dev_err(dev, "register scu notifier failed, %d\n", ret); - return ret; - } - - ret = imx_scu_irq_group_enable(IMX_SC_IRQ_GROUP_REBOOTED, BIT(priv->rproc_pt), - true); - if (ret) { - imx_scu_irq_unregister_notifier(&priv->rproc_nb); - dev_err(dev, "Enable irq failed, %d\n", ret); - return ret; - } + return 0; +} - return 0; - default: - break; - } +static int imx_rproc_mmio_detect_mode(struct rproc *rproc) +{ + const struct regmap_config config = { .name = "imx-rproc" }; + struct imx_rproc *priv = rproc->priv; + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + struct device *dev = priv->dev; + struct regmap *regmap; + u32 val; + int ret; priv->gpr = syscon_regmap_lookup_by_phandle(dev->of_node, "fsl,iomuxc-gpr"); if (IS_ERR(priv->gpr)) @@ -1039,6 +922,85 @@ static int imx_rproc_detect_mode(struct imx_rproc *priv) return 0; } +static int imx_rproc_scu_api_detect_mode(struct rproc *rproc) +{ + struct imx_rproc *priv = rproc->priv; + struct device *dev = priv->dev; + int ret; + u8 pt; + + ret = imx_scu_get_handle(&priv->ipc_handle); + if (ret) + return ret; + ret = of_property_read_u32(dev->of_node, "fsl,resource-id", &priv->rsrc_id); + if (ret) { + dev_err(dev, "No fsl,resource-id property\n"); + return ret; + } + + if (priv->rsrc_id == IMX_SC_R_M4_1_PID0) + priv->core_index = 1; + else + priv->core_index = 0; + + /* + * If Mcore resource is not owned by Acore partition, It is kicked by ROM, + * and Linux could only do IPC with Mcore and nothing else. + */ + if (imx_sc_rm_is_resource_owned(priv->ipc_handle, priv->rsrc_id)) { + if (of_property_read_u32(dev->of_node, "fsl,entry-address", &priv->entry)) + return -EINVAL; + + return imx_rproc_attach_pd(priv); + } + + priv->rproc->state = RPROC_DETACHED; + priv->rproc->recovery_disabled = false; + rproc_set_feature(priv->rproc, RPROC_FEAT_ATTACH_ON_RECOVERY); + + /* Get partition id and enable irq in SCFW */ + ret = imx_sc_rm_get_resource_owner(priv->ipc_handle, priv->rsrc_id, &pt); + if (ret) { + dev_err(dev, "not able to get resource owner\n"); + return ret; + } + + priv->rproc_pt = pt; + priv->rproc_nb.notifier_call = imx_rproc_partition_notify; + + ret = imx_scu_irq_register_notifier(&priv->rproc_nb); + if (ret) { + dev_err(dev, "register scu notifier failed, %d\n", ret); + return ret; + } + + ret = imx_scu_irq_group_enable(IMX_SC_IRQ_GROUP_REBOOTED, BIT(priv->rproc_pt), + true); + if (ret) { + imx_scu_irq_unregister_notifier(&priv->rproc_nb); + dev_err(dev, "Enable irq failed, %d\n", ret); + return ret; + } + + return 0; +} + +static int imx_rproc_detect_mode(struct imx_rproc *priv) +{ + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + + /* + * To i.MX{7,8} ULP, Linux is under control of RTOS, no need + * dcfg->ops or dcfg->ops->detect_mode, it is state RPROC_DETACHED. + */ + if (!dcfg->ops || !dcfg->ops->detect_mode) { + priv->rproc->state = RPROC_DETACHED; + return 0; + } + + return dcfg->ops->detect_mode(priv->rproc); +} + static int imx_rproc_clk_enable(struct imx_rproc *priv) { const struct imx_rproc_dcfg *dcfg = priv->dcfg; @@ -1207,6 +1169,111 @@ static void imx_rproc_remove(struct platform_device *pdev) destroy_workqueue(priv->workqueue); } +static const struct imx_rproc_plat_ops imx_rproc_ops_arm_smc = { + .start = imx_rproc_arm_smc_start, + .stop = imx_rproc_arm_smc_stop, + .detect_mode = imx_rproc_arm_smc_detect_mode, +}; + +static const struct imx_rproc_plat_ops imx_rproc_ops_mmio = { + .start = imx_rproc_mmio_start, + .stop = imx_rproc_mmio_stop, + .detect_mode = imx_rproc_mmio_detect_mode, +}; + +static const struct imx_rproc_plat_ops imx_rproc_ops_scu_api = { + .start = imx_rproc_scu_api_start, + .stop = imx_rproc_scu_api_stop, + .detect_mode = imx_rproc_scu_api_detect_mode, +}; + +static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn_mmio = { + .src_reg = IMX7D_SRC_SCR, + .src_mask = IMX7D_M4_RST_MASK, + .src_start = IMX7D_M4_START, + .src_stop = IMX8M_M7_STOP, + .gpr_reg = IMX8M_GPR22, + .gpr_wait = IMX8M_GPR22_CM7_CPUWAIT, + .att = imx_rproc_att_imx8mn, + .att_size = ARRAY_SIZE(imx_rproc_att_imx8mn), + .method = IMX_RPROC_MMIO, + .ops = &imx_rproc_ops_mmio, +}; + +static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn = { + .att = imx_rproc_att_imx8mn, + .att_size = ARRAY_SIZE(imx_rproc_att_imx8mn), + .method = IMX_RPROC_SMC, + .ops = &imx_rproc_ops_arm_smc, +}; + +static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = { + .src_reg = IMX7D_SRC_SCR, + .src_mask = IMX7D_M4_RST_MASK, + .src_start = IMX7D_M4_START, + .src_stop = IMX7D_M4_STOP, + .att = imx_rproc_att_imx8mq, + .att_size = ARRAY_SIZE(imx_rproc_att_imx8mq), + .method = IMX_RPROC_MMIO, + .ops = &imx_rproc_ops_mmio, +}; + +static const struct imx_rproc_dcfg imx_rproc_cfg_imx8qm = { + .att = imx_rproc_att_imx8qm, + .att_size = ARRAY_SIZE(imx_rproc_att_imx8qm), + .method = IMX_RPROC_SCU_API, + .ops = &imx_rproc_ops_scu_api, +}; + +static const struct imx_rproc_dcfg imx_rproc_cfg_imx8qxp = { + .att = imx_rproc_att_imx8qxp, + .att_size = ARRAY_SIZE(imx_rproc_att_imx8qxp), + .method = IMX_RPROC_SCU_API, + .ops = &imx_rproc_ops_scu_api, +}; + +static const struct imx_rproc_dcfg imx_rproc_cfg_imx8ulp = { + .att = imx_rproc_att_imx8ulp, + .att_size = ARRAY_SIZE(imx_rproc_att_imx8ulp), + .method = IMX_RPROC_NONE, +}; + +static const struct imx_rproc_dcfg imx_rproc_cfg_imx7ulp = { + .att = imx_rproc_att_imx7ulp, + .att_size = ARRAY_SIZE(imx_rproc_att_imx7ulp), + .method = IMX_RPROC_NONE, + .flags = IMX_RPROC_NEED_SYSTEM_OFF, +}; + +static const struct imx_rproc_dcfg imx_rproc_cfg_imx7d = { + .src_reg = IMX7D_SRC_SCR, + .src_mask = IMX7D_M4_RST_MASK, + .src_start = IMX7D_M4_START, + .src_stop = IMX7D_M4_STOP, + .att = imx_rproc_att_imx7d, + .att_size = ARRAY_SIZE(imx_rproc_att_imx7d), + .method = IMX_RPROC_MMIO, + .ops = &imx_rproc_ops_mmio, +}; + +static const struct imx_rproc_dcfg imx_rproc_cfg_imx6sx = { + .src_reg = IMX6SX_SRC_SCR, + .src_mask = IMX6SX_M4_RST_MASK, + .src_start = IMX6SX_M4_START, + .src_stop = IMX6SX_M4_STOP, + .att = imx_rproc_att_imx6sx, + .att_size = ARRAY_SIZE(imx_rproc_att_imx6sx), + .method = IMX_RPROC_MMIO, + .ops = &imx_rproc_ops_mmio, +}; + +static const struct imx_rproc_dcfg imx_rproc_cfg_imx93 = { + .att = imx_rproc_att_imx93, + .att_size = ARRAY_SIZE(imx_rproc_att_imx93), + .method = IMX_RPROC_SMC, + .ops = &imx_rproc_ops_arm_smc, +}; + static const struct of_device_id imx_rproc_of_match[] = { { .compatible = "fsl,imx7ulp-cm4", .data = &imx_rproc_cfg_imx7ulp }, { .compatible = "fsl,imx7d-cm4", .data = &imx_rproc_cfg_imx7d }, diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h index cfd38d37e146..3a9adaaf048b 100644 --- a/drivers/remoteproc/imx_rproc.h +++ b/drivers/remoteproc/imx_rproc.h @@ -31,6 +31,12 @@ enum imx_rproc_method { /* dcfg flags */ #define IMX_RPROC_NEED_SYSTEM_OFF BIT(0) +struct imx_rproc_plat_ops { + int (*start)(struct rproc *rproc); + int (*stop)(struct rproc *rproc); + int (*detect_mode)(struct rproc *rproc); +}; + struct imx_rproc_dcfg { u32 src_reg; u32 src_mask; @@ -42,6 +48,7 @@ struct imx_rproc_dcfg { size_t att_size; enum imx_rproc_method method; u32 flags; + const struct imx_rproc_plat_ops *ops; }; #endif /* _IMX_RPROC_H */ diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c index 7b41b4547fa8..4d6550b48567 100644 --- a/drivers/remoteproc/keystone_remoteproc.c +++ b/drivers/remoteproc/keystone_remoteproc.c @@ -349,6 +349,20 @@ static int keystone_rproc_of_get_dev_syscon(struct platform_device *pdev, return 0; } +static void keystone_rproc_mem_release(void *data) +{ + struct device *dev = data; + + of_reserved_mem_device_release(dev); +} + +static void keystone_rproc_pm_runtime_put(void *data) +{ + struct device *dev = data; + + pm_runtime_put_sync(dev); +} + static int keystone_rproc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -394,80 +408,58 @@ static int keystone_rproc_probe(struct platform_device *pdev) return PTR_ERR(ksproc->reset); /* enable clock for accessing DSP internal memories */ - pm_runtime_enable(dev); + ret = devm_pm_runtime_enable(dev); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to enable runtime PM\n"); + ret = pm_runtime_resume_and_get(dev); - if (ret < 0) { - dev_err(dev, "failed to enable clock, status = %d\n", ret); - goto disable_rpm; - } + if (ret < 0) + return dev_err_probe(dev, ret, "failed to enable clock\n"); + + ret = devm_add_action_or_reset(dev, keystone_rproc_pm_ |
