mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 20:14:06 +02:00
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:
commit
c35f902cb3
198
Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml
Normal file
198
Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml
Normal 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>;
|
||||
|
||||
/* ... */
|
||||
};
|
||||
};
|
||||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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[] = {
|
||||
|
|
|
|||
|
|
@ -1206,8 +1206,6 @@ static void k3_r5_cluster_rproc_exit(void *data)
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mbox_free_channel(kproc->mbox);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user