remoteproc updates for v6.18

Enable coredump support for the i.MX HiFi core remoteproc, and clean up
 the i.MX remoteproc driver.
 
 Introduce remoteprocs on the Qualcomm Milos platform. Gracefully shut own
 the ADSP remoteproc when bootloader has loaded the "Lite" firmware on X
 Elite. Improve the resource handover procedure to avoid possibly duplicate
 handling.
 
 Transition the TI DA8xx, TI Keystone, and TI Wakeup M3 remoteproc
 drivers to handle resources using devres.
 -----BEGIN PGP SIGNATURE-----
 
 iQJJBAABCgAzFiEEBd4DzF816k8JZtUlCx85Pw2ZrcUFAmjehA8VHGFuZGVyc3Nv
 bkBrZXJuZWwub3JnAAoJEAsfOT8Nma3F8HoP/A9eBjE7wBguQ/3YkAPKe8Idrfrb
 kxl5weM1zVoIz4Hz/DLfv2LkKtxw/sELmQyk/iiO5N6jte5xsgfCQj1wbH4l9GvC
 tguRwbh1IKfsynJEAKj0fuUU0OpIwsFubuJCsmaHhlsZJruqg5SwHLlHT03CTeKp
 PeIDUOyyfHeOimMrwvwhwORzhxve3NKdrPks1xzurTZhHgsnIZe31UPfJEN+YPEm
 9OVmahSQhVoA5O7kr1KLKHjGZ7lV7KMCtYxJc9X1wbNMvfxY//D+mlRVPNAZSpVq
 gwXMPXLukqCQcLXNwUCTvjZwv8QnzKs1XKUvchYRp/8IkRy02zvi2UKoqQY1IfIv
 g58BVjCWnD/nbl+soCQ6iu7S8bEy3ruw6cnIYULDQOhCgSax5snAa1aq93H/XPZK
 3/YI5OhaQtc1iv4YH9BUg+HLNu/KDWxfU9jfXXa7BAQb9KQgJU9cBy3pofT+jkSI
 Z3t5lmfw/HIDvMagKLwnM/VY9lL5K1YUjlFV2iJ1rHDJSwckpI9mkFBig3zfFSNR
 Ezc2ifbY6D58Vox+E/r2CgOLPq0s9k8ionXJ+TxJ/Od8h2mvtqRIXexd3x+5c0hN
 mLaL6f5rfdmZS3V1Rg/NYRtuFeVe+flBnP0rLmZ2XrbHRU4TTyn+vGp00tSihsbo
 0eH98EUK56CpoWjg
 =UVU4
 -----END PGP SIGNATURE-----

Merge tag 'rproc-v6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux

Pull remoteproc updates from Bjorn Andersson:

 - Enable coredump support for the i.MX HiFi core remoteproc, and clean
   up the i.MX remoteproc driver.

 - Introduce remoteprocs on the Qualcomm Milos platform. Gracefully shut
   own the ADSP remoteproc when bootloader has loaded the "Lite"
   firmware on X Elite. Improve the resource handover procedure to avoid
   possibly duplicate handling.

 - Transition the TI DA8xx, TI Keystone, and TI Wakeup M3 remoteproc
   drivers to handle resources using devres.

* tag 'rproc-v6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux: (29 commits)
  remoteproc: pru: Fix potential NULL pointer dereference in pru_rproc_set_ctable()
  remoteproc: qcom: pas: Drop redundant assignment to ret
  remoteproc: qcom: pas: Shutdown lite ADSP DTB on X1E
  remoteproc: qcom: q6v5: Avoid handling handover twice
  remoteproc: qcom: q6v5: Avoid disabling handover IRQ twice
  remoteproc: qcom: pas: Add Milos remoteproc support
  dt-bindings: remoteproc: qcom,milos-pas: Document remoteprocs
  remoteproc: qcom_q6v5_mss: support loading MBN file on msm8974
  remoteproc: imx_rproc: Clean up after ops introduction
  remoteproc: imx_rproc: Simplify IMX_RPROC_SMC switch case
  remoteproc: imx_rproc: Simplify IMX_RPROC_SCU_API switch case
  remoteproc: imx_rproc: Simplify IMX_RPROC_MMIO switch case
  remoteproc: imx_rproc: Move imx_rproc_dcfg closer to imx_rproc_of_match
  remoteproc: imx_rproc: Introduce start/stop/detect_mode ops for imx_rproc_dcfg
  remoteproc: k3: Correctly release some resources allocated in k3_rproc_request_mbox()
  remoteproc: wkup_m3: Use devm_rproc_add() helper
  remoteproc: wkup_m3: Use devm_rproc_alloc() helper
  remoteproc: wkup_m3: Use devm action to call PM runtime put sync
  remoteproc: wkup_m3: Use devm_pm_runtime_enable() helper
  remoteproc: keystone: Use devm_rproc_add() helper
  ...
This commit is contained in:
Linus Torvalds 2025-10-04 15:45:17 -07:00
commit c35f902cb3
14 changed files with 636 additions and 365 deletions

View File

@ -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>;
/* ... */
};
};

View File

@ -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),

View File

@ -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;
}

View File

@ -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 int imx_rproc_arm_smc_start(struct rproc *rproc)
{
struct arm_smccc_res res;
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,
};
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_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,
};
return res.a0;
}
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,
};
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_imx8qxp = {
.att = imx_rproc_att_imx8qxp,
.att_size = ARRAY_SIZE(imx_rproc_att_imx8qxp),
.method = IMX_RPROC_SCU_API,
};
if (priv->gpr)
return regmap_clear_bits(priv->gpr, dcfg->gpr_reg, dcfg->gpr_wait);
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,
};
return regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, dcfg->src_start);
}
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 int imx_rproc_scu_api_start(struct rproc *rproc)
{
struct imx_rproc *priv = rproc->priv;
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,
};
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 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_arm_smc_stop(struct rproc *rproc)
{
struct imx_rproc *priv = rproc->priv;
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;
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;
struct arm_smccc_res res;
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;
}
}
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" };
struct imx_rproc *priv = rproc->priv;
struct arm_smccc_res res;
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;
}
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;
struct arm_smccc_res res;
int ret;
u32 val;
u8 pt;
switch (dcfg->method) {
case IMX_RPROC_NONE:
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;
default:
break;
}
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 },

View File

@ -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 */

View File

@ -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_runtime_put, dev);
if (ret)
return dev_err_probe(dev, ret, "failed to add disable pm devm action\n");
ret = keystone_rproc_of_get_memories(pdev, ksproc);
if (ret)
goto disable_clk;
return ret;
ksproc->irq_ring = platform_get_irq_byname(pdev, "vring");
if (ksproc->irq_ring < 0) {
ret = ksproc->irq_ring;
goto disable_clk;
}
if (ksproc->irq_ring < 0)
return ksproc->irq_ring;
ksproc->irq_fault = platform_get_irq_byname(pdev, "exception");
if (ksproc->irq_fault < 0) {
ret = ksproc->irq_fault;
goto disable_clk;
}
if (ksproc->irq_fault < 0)
return ksproc->irq_fault;
ksproc->kick_gpio = gpiod_get(dev, "kick", GPIOD_ASIS);
ksproc->kick_gpio = devm_gpiod_get(dev, "kick", GPIOD_ASIS);
ret = PTR_ERR_OR_ZERO(ksproc->kick_gpio);
if (ret) {
dev_err(dev, "failed to get gpio for virtio kicks, status = %d\n",
ret);
goto disable_clk;
}
if (ret)
return dev_err_probe(dev, ret, "failed to get gpio for virtio kicks\n");
if (of_reserved_mem_device_init(dev))
ret = of_reserved_mem_device_init(dev);
if (ret) {
dev_warn(dev, "device does not have specific CMA pool\n");
} else {
ret = devm_add_action_or_reset(dev, keystone_rproc_mem_release, dev);
if (ret)
return ret;
}
/* ensure the DSP is in reset before loading firmware */
ret = reset_control_status(ksproc->reset);
if (ret < 0) {
dev_err(dev, "failed to get reset status, status = %d\n", ret);
goto release_mem;
return dev_err_probe(dev, ret, "failed to get reset status\n");
} else if (ret == 0) {
WARN(1, "device is not in reset\n");
keystone_rproc_dsp_reset(ksproc);
}
ret = rproc_add(rproc);
if (ret) {
dev_err(dev, "failed to add register device with remoteproc core, status = %d\n",
ret);
goto release_mem;
}
platform_set_drvdata(pdev, ksproc);
ret = devm_rproc_add(dev, rproc);
if (ret)
return dev_err_probe(dev, ret, "failed to register device with remoteproc core\n");
return 0;
release_mem:
of_reserved_mem_device_release(dev);
gpiod_put(ksproc->kick_gpio);
disable_clk:
pm_runtime_put_sync(dev);
disable_rpm:
pm_runtime_disable(dev);
return ret;
}
static void keystone_rproc_remove(struct platform_device *pdev)
{
struct keystone_rproc *ksproc = platform_get_drvdata(pdev);
rproc_del(ksproc->rproc);
gpiod_put(ksproc->kick_gpio);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
of_reserved_mem_device_release(&pdev->dev);
}
static const struct of_device_id keystone_rproc_of_match[] = {
@ -481,7 +473,6 @@ MODULE_DEVICE_TABLE(of, keystone_rproc_of_match);
static struct platform_driver keystone_rproc_driver = {
.probe = keystone_rproc_probe,
.remove = keystone_rproc_remove,
.driver = {
.name = "keystone-rproc",
.of_match_table = keystone_rproc_of_match,

View File

@ -340,7 +340,7 @@ EXPORT_SYMBOL_GPL(pru_rproc_put);
*/
int pru_rproc_set_ctable(struct rproc *rproc, enum pru_ctable_idx c, u32 addr)
{
struct pru_rproc *pru = rproc->priv;
struct pru_rproc *pru;
unsigned int reg;
u32 mask, set;
u16 idx;
@ -352,6 +352,7 @@ int pru_rproc_set_ctable(struct rproc *rproc, enum pru_ctable_idx c, u32 addr)
if (!rproc->dev.parent || !is_pru_rproc(rproc->dev.parent))
return -ENODEV;
pru = rproc->priv;
/* pointer is 16 bit and index is 8-bit so mask out the rest */
idx_mask = (c >= PRU_C28) ? 0xFFFF : 0xFF;

View File

@ -156,9 +156,6 @@ int qcom_q6v5_wait_for_start(struct qcom_q6v5 *q6v5, int timeout)
int ret;
ret = wait_for_completion_timeout(&q6v5->start_done, timeout);
if (!ret)
disable_irq(q6v5->handover_irq);
return !ret ? -ETIMEDOUT : 0;
}
EXPORT_SYMBOL_GPL(qcom_q6v5_wait_for_start);
@ -167,6 +164,11 @@ static irqreturn_t q6v5_handover_interrupt(int irq, void *data)
{
struct qcom_q6v5 *q6v5 = data;
if (q6v5->handover_issued) {
dev_err(q6v5->dev, "Handover signaled, but it already happened\n");
return IRQ_HANDLED;
}
if (q6v5->handover)
q6v5->handover(q6v5);

View File

@ -498,6 +498,8 @@ static void q6v5_debug_policy_load(struct q6v5 *qproc, void *mba_region)
release_firmware(dp_fw);
}
#define MSM8974_B00_OFFSET 0x1000
static int q6v5_load(struct rproc *rproc, const struct firmware *fw)
{
struct q6v5 *qproc = rproc->priv;
@ -516,7 +518,14 @@ static int q6v5_load(struct rproc *rproc, const struct firmware *fw)
return -EBUSY;
}
memcpy(mba_region, fw->data, fw->size);
if ((qproc->version == MSS_MSM8974 ||
qproc->version == MSS_MSM8226 ||
qproc->version == MSS_MSM8926) &&
fw->size > MSM8974_B00_OFFSET &&
!memcmp(fw->data, ELFMAG, SELFMAG))
memcpy(mba_region, fw->data + MSM8974_B00_OFFSET, fw->size - MSM8974_B00_OFFSET);
else
memcpy(mba_region, fw->data, fw->size);
q6v5_debug_policy_load(qproc, mba_region);
memunmap(mba_region);

View File

@ -42,6 +42,7 @@ struct qcom_pas_data {
int pas_id;
int dtb_pas_id;
int lite_pas_id;
int lite_dtb_pas_id;
unsigned int minidump_id;
bool auto_boot;
bool decrypt_shutdown;
@ -80,6 +81,7 @@ struct qcom_pas {
int pas_id;
int dtb_pas_id;
int lite_pas_id;
int lite_dtb_pas_id;
unsigned int minidump_id;
int crash_reason_smem;
unsigned int smem_host_id;
@ -225,7 +227,9 @@ static int qcom_pas_load(struct rproc *rproc, const struct firmware *fw)
pas->firmware = fw;
if (pas->lite_pas_id)
ret = qcom_scm_pas_shutdown(pas->lite_pas_id);
qcom_scm_pas_shutdown(pas->lite_pas_id);
if (pas->lite_dtb_pas_id)
qcom_scm_pas_shutdown(pas->lite_dtb_pas_id);
if (pas->dtb_pas_id) {
ret = request_firmware(&pas->dtb_firmware, pas->dtb_firmware_name, pas->dev);
@ -721,6 +725,7 @@ static int qcom_pas_probe(struct platform_device *pdev)
pas->minidump_id = desc->minidump_id;
pas->pas_id = desc->pas_id;
pas->lite_pas_id = desc->lite_pas_id;
pas->lite_dtb_pas_id = desc->lite_dtb_pas_id;
pas->info_name = desc->sysmon_name;
pas->smem_host_id = desc->smem_host_id;
pas->decrypt_shutdown = desc->decrypt_shutdown;
@ -1084,6 +1089,7 @@ static const struct qcom_pas_data x1e80100_adsp_resource = {
.pas_id = 1,
.dtb_pas_id = 0x24,
.lite_pas_id = 0x1f,
.lite_dtb_pas_id = 0x29,
.minidump_id = 5,
.auto_boot = true,
.proxy_pd_names = (char*[]){
@ -1255,6 +1261,26 @@ static const struct qcom_pas_data sdx55_mpss_resource = {
.ssctl_id = 0x22,
};
static const struct qcom_pas_data milos_cdsp_resource = {
.crash_reason_smem = 601,
.firmware_name = "cdsp.mbn",
.dtb_firmware_name = "cdsp_dtb.mbn",
.pas_id = 18,
.dtb_pas_id = 0x25,
.minidump_id = 7,
.auto_boot = true,
.proxy_pd_names = (char*[]){
"cx",
"mx",
NULL
},
.load_state = "cdsp",
.ssr_name = "cdsp",
.sysmon_name = "cdsp",
.ssctl_id = 0x17,
.smem_host_id = 5,
};
static const struct qcom_pas_data sm8450_mpss_resource = {
.crash_reason_smem = 421,
.firmware_name = "modem.mdt",
@ -1429,6 +1455,10 @@ static const struct qcom_pas_data sm8750_mpss_resource = {
};
static const struct of_device_id qcom_pas_of_match[] = {
{ .compatible = "qcom,milos-adsp-pas", .data = &sm8550_adsp_resource},
{ .compatible = "qcom,milos-cdsp-pas", .data = &milos_cdsp_resource},
{ .compatible = "qcom,milos-mpss-pas", .data = &sm8450_mpss_resource},
{ .compatible = "qcom,milos-wpss-pas", .data = &sc7280_wpss_resource},
{ .compatible = "qcom,msm8226-adsp-pil", .data = &msm8996_adsp_resource},
{ .compatible = "qcom,msm8953-adsp-pil", .data = &msm8996_adsp_resource},
{ .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init},

View File

@ -155,6 +155,13 @@ int k3_rproc_release(struct k3_rproc *kproc)
}
EXPORT_SYMBOL_GPL(k3_rproc_release);
static void k3_rproc_free_channel(void *data)
{
struct k3_rproc *kproc = data;
mbox_free_channel(kproc->mbox);
}
int k3_rproc_request_mbox(struct rproc *rproc)
{
struct k3_rproc *kproc = rproc->priv;
@ -173,19 +180,9 @@ int k3_rproc_request_mbox(struct rproc *rproc)
return dev_err_probe(dev, PTR_ERR(kproc->mbox),
"mbox_request_channel failed\n");
/*
* Ping the remote processor, this is only for sanity-sake for now;
* there is no functional effect whatsoever.
*
* Note that the reply will _not_ arrive immediately: this message
* will wait in the mailbox fifo until the remote processor is booted.
*/
ret = mbox_send_message(kproc->mbox, (void *)RP_MBOX_ECHO_REQUEST);
if (ret < 0) {
dev_err(dev, "mbox_send_message failed (%pe)\n", ERR_PTR(ret));
mbox_free_channel(kproc->mbox);
ret = devm_add_action_or_reset(dev, k3_rproc_free_channel, kproc);
if (ret)
return ret;
}
return 0;
}

View File

@ -175,8 +175,6 @@ static void k3_dsp_rproc_remove(struct platform_device *pdev)
if (ret)
dev_err(dev, "failed to detach proc (%pe)\n", ERR_PTR(ret));
}
mbox_free_channel(kproc->mbox);
}
static const struct k3_rproc_mem_data c66_mems[] = {

View File

@ -1206,8 +1206,6 @@ static void k3_r5_cluster_rproc_exit(void *data)
return;
}
}
mbox_free_channel(kproc->mbox);
}
}

View File

@ -125,6 +125,13 @@ static const struct of_device_id wkup_m3_rproc_of_match[] = {
};
MODULE_DEVICE_TABLE(of, wkup_m3_rproc_of_match);
static void wkup_m3_rproc_pm_runtime_put(void *data)
{
struct device *dev = data;
pm_runtime_put_sync(dev);
}
static int wkup_m3_rproc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@ -148,19 +155,20 @@ static int wkup_m3_rproc_probe(struct platform_device *pdev)
return -ENODEV;
}
pm_runtime_enable(&pdev->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_get_sync(&pdev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
goto err;
}
if (ret < 0)
return dev_err_probe(dev, ret, "pm_runtime_get_sync() failed\n");
ret = devm_add_action_or_reset(dev, wkup_m3_rproc_pm_runtime_put, dev);
if (ret)
return dev_err_probe(dev, ret, "failed to add disable pm devm action\n");
rproc = rproc_alloc(dev, "wkup_m3", &wkup_m3_rproc_ops,
fw_name, sizeof(*wkupm3));
if (!rproc) {
ret = -ENOMEM;
goto err;
}
rproc = devm_rproc_alloc(dev, "wkup_m3", &wkup_m3_rproc_ops,
fw_name, sizeof(*wkupm3));
if (!rproc)
return -ENOMEM;
rproc->auto_boot = false;
rproc->sysfs_read_only = true;
@ -175,9 +183,7 @@ static int wkup_m3_rproc_probe(struct platform_device *pdev)
if (!wkupm3->rsts) {
if (!(pdata && pdata->deassert_reset && pdata->assert_reset &&
pdata->reset_name)) {
dev_err(dev, "Platform data missing!\n");
ret = -ENODEV;
goto err_put_rproc;
return dev_err_probe(dev, -ENODEV, "Platform data missing!\n");
}
}
@ -185,12 +191,9 @@ static int wkup_m3_rproc_probe(struct platform_device *pdev)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
mem_names[i]);
wkupm3->mem[i].cpu_addr = devm_ioremap_resource(dev, res);
if (IS_ERR(wkupm3->mem[i].cpu_addr)) {
dev_err(&pdev->dev, "devm_ioremap_resource failed for resource %d\n",
i);
ret = PTR_ERR(wkupm3->mem[i].cpu_addr);
goto err_put_rproc;
}
if (IS_ERR(wkupm3->mem[i].cpu_addr))
return dev_err_probe(dev, PTR_ERR(wkupm3->mem[i].cpu_addr),
"devm_ioremap_resource failed for resource %d\n", i);
wkupm3->mem[i].bus_addr = res->start;
wkupm3->mem[i].size = resource_size(res);
addrp = of_get_address(dev->of_node, i, &size, NULL);
@ -207,30 +210,11 @@ static int wkup_m3_rproc_probe(struct platform_device *pdev)
dev_set_drvdata(dev, rproc);
ret = rproc_add(rproc);
if (ret) {
dev_err(dev, "rproc_add failed\n");
goto err_put_rproc;
}
ret = devm_rproc_add(dev, rproc);
if (ret)
return dev_err_probe(dev, ret, "rproc_add failed\n");
return 0;
err_put_rproc:
rproc_free(rproc);
err:
pm_runtime_put_noidle(dev);
pm_runtime_disable(dev);
return ret;
}
static void wkup_m3_rproc_remove(struct platform_device *pdev)
{
struct rproc *rproc = platform_get_drvdata(pdev);
rproc_del(rproc);
rproc_free(rproc);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
}
#ifdef CONFIG_PM
@ -251,7 +235,6 @@ static const struct dev_pm_ops wkup_m3_rproc_pm_ops = {
static struct platform_driver wkup_m3_rproc_driver = {
.probe = wkup_m3_rproc_probe,
.remove = wkup_m3_rproc_remove,
.driver = {
.name = "wkup_m3_rproc",
.of_match_table = wkup_m3_rproc_of_match,