mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
remoteproc updates for v7.2
Add i.MX94 support to the i.MX remoteproc driver, covering the Cortex-M7 and Cortex-M33 Sync cores. This also fixes programming of non-zero System Manager CPU/LMM reset vectors. Move the remoteproc resource table definitions to a separate header, so they can be used by clients that do not otherwise depend on remoteproc. Switch the firmware resource handling over to the common iterator. Update the Xilinx R5F remoteproc driver to check the remote core state before attaching, drop a binding header dependency, and add firmware-name based auto boot support. Add Qualcomm Hawi ADSP/CDSP bindings, together with Shikra RPM bindings and CDSP, LPAICP, and MPSS PAS support. Fix a Qualcomm minidump leak, clean up PAS and WCSS reset handling, and make the user-visible Qualcomm naming consistent. Remove a duplicate STM32_RPROC Kconfig dependency and make i.MX remoteproc instances use the device node name so multiple processors can be distinguished in sysfs. -----BEGIN PGP SIGNATURE----- iQJCBAABCgAsFiEEBd4DzF816k8JZtUlCx85Pw2ZrcUFAmo2pWgOHGJqb3JuQGty eW8uc2UACgkQCx85Pw2ZrcUxqA//XXAZHUD0Hz7Qag+z38N5qSCk/U/Qg38lvRWB lNDZ2g7KqmwdJbzJr5wzG8hoTO84hs3/nRAzV+KnwOIJ5M4EyH0AF9aqXjaqvyC7 V10OYSt5eQQZPBCZ87D7lABVxeuXtc07ETcecx3/zLZSdPqHUa25E1V86EwqYNl1 50wXTjbzhqdCOxKHxxhBhLq1GdPZE4shfzkTATfhAOTInRHwsfUS2u08Wh31kcuX eGG3vAIWQKbLGtM+ZLy/GCNhT58pBtHixnMjCJOmv2c8HzPoQmkSZbf+/8L6fOYY 48XbRJG1PdlraWVpEXzjJBLO+jULJmAtqlptMXX30V/qAnxoLWyU22Vw86hcj5XU Cxb/O1YconxtAbzQvCcB94oSpGM5DXXyHiUk+Cwizv3q+SHaMIdTA51Atpf/ly5k /di1FqOKzVHYbFDYYxttXmXrpUVIRfFDMkONoZgLZiE1cRZXrbwHrqZFaBz7lvw/ m/tu1+VX3jGaVJpyA5uAflxVW29r+VCNZ2RLKDC0vLnnRAut5oMbWUtLJlXhD9Ad wvgMkNMXPCsSyuUQ3gBLqHP8TdBMQav5dNGy0LcLuRDLN82I+h/GfxFOqowArKdh iVNnogPUJhscsSdnyspqBMDZ+fexYw6jIknt3ALet+6MWJ2gxt7k4j8y3CoRL6GB 5okVSqM= =6cLo -----END PGP SIGNATURE----- Merge tag 'rproc-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux Pull remoteproc updates from Bjorn Andersson: - Add i.MX94 support to the i.MX remoteproc driver, covering the Cortex-M7 and Cortex-M33 Sync cores. This also fixes programming of non-zero System Manager CPU/LMM reset vectors. - Move the remoteproc resource table definitions to a separate header, so they can be used by clients that do not otherwise depend on remoteproc. Switch the firmware resource handling over to the common iterator. - Update the Xilinx R5F remoteproc driver to check the remote core state before attaching, drop a binding header dependency, and add firmware-name based auto boot support. - Add Qualcomm Hawi ADSP/CDSP bindings, together with Shikra RPM bindings and CDSP, LPAICP, and MPSS PAS support. Fix a Qualcomm minidump leak, clean up PAS and WCSS reset handling, and make the user-visible Qualcomm naming consistent. - Remove a duplicate STM32_RPROC Kconfig dependency and make i.MX remoteproc instances use the device node name so multiple processors can be distinguished in sysfs. * tag 'rproc-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux: remoteproc: qcom: pas: Drop start/stop completion from struct qcom_pas remoteproc: qcom: pas: Add Shikra remoteproc support dt-bindings: remoteproc: qcom,shikra-pas: Document Shikra PAS remoteprocs dt-bindings: remoteproc: Add Shikra RPM processor compatible remoteproc: qcom: Unify user-visible "Qualcomm" name remoteproc: qcom: Fix leak when custom dump_segments addition fails remoteproc: qcom_q6v5_wcss: drop redundant wcss_q6_bcr_reset dt-bindings: remoteproc: qcom,sm8550-pas: Add Hawi CDSP compatible dt-bindings: remoteproc: qcom,sm8550-pas: Add Hawi ADSP compatible remoteproc: xlnx: Enable auto boot feature dt-bindings: remoteproc: xlnx: Add firmware-name property remoteproc: xlnx: Remove binding header dependency remoteproc: imx_rproc: Use device node name as processor name remoteproc: use rsc_table_for_each_entry() in rproc_handle_resources() remoteproc: Move resource table data structure to its own header remoteproc: xlnx: Check remote core state remoteproc: imx_rproc: Add support for i.MX94 remoteproc: imx_rproc: Program non-zero SM CPU/LMM reset vector dt-bindings: remoteproc: imx-rproc: Support i.MX94 remoteproc: Dead code cleanup in Kconfig for STM32_RPROC
This commit is contained in:
commit
9d0d4d12e4
|
|
@ -28,6 +28,9 @@ properties:
|
|||
- fsl,imx8qxp-cm4
|
||||
- fsl,imx8ulp-cm33
|
||||
- fsl,imx93-cm33
|
||||
- fsl,imx94-cm33s
|
||||
- fsl,imx94-cm70
|
||||
- fsl,imx94-cm71
|
||||
- fsl,imx95-cm7
|
||||
|
||||
clocks:
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ properties:
|
|||
- qcom,qcm2290-rpm-proc
|
||||
- qcom,qcs404-rpm-proc
|
||||
- qcom,sdm660-rpm-proc
|
||||
- qcom,shikra-rpm-proc
|
||||
- qcom,sm6115-rpm-proc
|
||||
- qcom,sm6125-rpm-proc
|
||||
- qcom,sm6375-rpm-proc
|
||||
|
|
|
|||
|
|
@ -0,0 +1,167 @@
|
|||
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/remoteproc/qcom,shikra-pas.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Shikra SoC Peripheral Authentication Service
|
||||
|
||||
maintainers:
|
||||
- Bibek Kumar Patro <bibek.patro@oss.qualcomm.com>
|
||||
- Komal Bajaj <komal.bajaj@oss.qualcomm.com>
|
||||
|
||||
description:
|
||||
Qualcomm Shikra SoC Peripheral Authentication Service loads and boots
|
||||
firmware on the Qualcomm DSP Hexagon cores.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,shikra-cdsp-pas
|
||||
- qcom,shikra-lpaicp-pas
|
||||
- qcom,shikra-mpss-pas
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: XO clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: xo
|
||||
|
||||
memory-region:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
smd-edge: false
|
||||
|
||||
firmware-name:
|
||||
minItems: 1
|
||||
items:
|
||||
- description: Firmware name of the Hexagon core
|
||||
- description: Firmware name of the Hexagon Devicetree
|
||||
|
||||
glink-edge:
|
||||
$ref: /schemas/remoteproc/qcom,glink-edge.yaml#
|
||||
description:
|
||||
Qualcomm G-Link subnode which represents communication edge, channels
|
||||
and devices related to the remoteproc core.
|
||||
unevaluatedProperties: false
|
||||
|
||||
qcom,smem-states:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
description: States used by the AP to signal the Hexagon core
|
||||
items:
|
||||
- description: Stop the remote processor
|
||||
items:
|
||||
- description: Phandle to the Shared Memory Point 2 Point device
|
||||
handling the communication with a remote processor
|
||||
- description: Single bit index to toggle in the value sent to
|
||||
the remote processor
|
||||
maximum: 32
|
||||
|
||||
qcom,smem-state-names:
|
||||
description: The names of the state bits used for SMP2P output
|
||||
items:
|
||||
- const: stop
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- memory-region
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/remoteproc/qcom,pas-common.yaml#
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,shikra-cdsp-pas
|
||||
- qcom,shikra-mpss-pas
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
minItems: 6
|
||||
interrupt-names:
|
||||
minItems: 6
|
||||
memory-region:
|
||||
maxItems: 1
|
||||
firmware-name:
|
||||
maxItems: 1
|
||||
power-domains:
|
||||
items:
|
||||
- description: CX power domain
|
||||
power-domain-names:
|
||||
items:
|
||||
- const: cx
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,shikra-lpaicp-pas
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
maxItems: 5
|
||||
interrupt-names:
|
||||
maxItems: 5
|
||||
memory-region:
|
||||
minItems: 2
|
||||
firmware-name:
|
||||
minItems: 2
|
||||
power-domains: false
|
||||
power-domain-names: false
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,rpmcc.h>
|
||||
#include <dt-bindings/interconnect/qcom,icc.h>
|
||||
#include <dt-bindings/interconnect/qcom,rpm-icc.h>
|
||||
#include <dt-bindings/interconnect/qcom,shikra.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/power/qcom-rpmpd.h>
|
||||
|
||||
remoteproc@b300000 {
|
||||
compatible = "qcom,shikra-cdsp-pas";
|
||||
reg = <0x0b300000 0x100000>;
|
||||
|
||||
interrupts-extended = <&intc GIC_SPI 265 IRQ_TYPE_EDGE_RISING>,
|
||||
<&cdsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
|
||||
<&cdsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>,
|
||||
<&cdsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>,
|
||||
<&cdsp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>,
|
||||
<&cdsp_smp2p_in 7 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "wdog", "fatal", "ready",
|
||||
"handover", "stop-ack", "shutdown-ack";
|
||||
|
||||
clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>;
|
||||
clock-names = "xo";
|
||||
|
||||
interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG
|
||||
&mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>;
|
||||
|
||||
power-domains = <&rpmpd RPMHPD_CX>;
|
||||
power-domain-names = "cx";
|
||||
|
||||
memory-region = <&cdsp_mem>;
|
||||
|
||||
qcom,smem-states = <&cdsp_smp2p_out 0>;
|
||||
qcom,smem-state-names = "stop";
|
||||
|
||||
firmware-name = "qcom/shikra/cdsp.mbn";
|
||||
|
||||
glink-edge {
|
||||
interrupts = <GIC_SPI 261 IRQ_TYPE_EDGE_RISING>;
|
||||
mboxes = <&apcs_glb 4>;
|
||||
qcom,remote-pid = <5>;
|
||||
label = "cdsp";
|
||||
};
|
||||
};
|
||||
|
|
@ -30,12 +30,14 @@ properties:
|
|||
- items:
|
||||
- enum:
|
||||
- qcom,glymur-adsp-pas
|
||||
- qcom,hawi-adsp-pas
|
||||
- qcom,kaanapali-adsp-pas
|
||||
- qcom,sm8750-adsp-pas
|
||||
- const: qcom,sm8550-adsp-pas
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,glymur-cdsp-pas
|
||||
- qcom,hawi-cdsp-pas
|
||||
- qcom,kaanapali-cdsp-pas
|
||||
- const: qcom,sm8550-cdsp-pas
|
||||
- items:
|
||||
|
|
@ -104,6 +106,8 @@ allOf:
|
|||
enum:
|
||||
- qcom,glymur-adsp-pas
|
||||
- qcom,glymur-cdsp-pas
|
||||
- qcom,hawi-adsp-pas
|
||||
- qcom,hawi-cdsp-pas
|
||||
- qcom,kaanapali-adsp-pas
|
||||
- qcom,kaanapali-cdsp-pas
|
||||
- qcom,sm8750-adsp-pas
|
||||
|
|
|
|||
|
|
@ -128,6 +128,10 @@ patternProperties:
|
|||
- description: vring1
|
||||
additionalItems: true
|
||||
|
||||
firmware-name:
|
||||
maxItems: 1
|
||||
description: default firmware to load
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
|||
|
|
@ -1450,6 +1450,34 @@ int zynqmp_pm_get_node_status(const u32 node, u32 *const status,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_get_node_status);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_get_rpu_node_status - PM call to request a RPU node's current power state
|
||||
* @node: ID of the RPU component or sub-system in question
|
||||
* @status: Current operating state of the requested RPU node.
|
||||
* @requirements: Current requirements asserted on the RPU node.
|
||||
* @usage: Usage information, used for RPU slave nodes only:
|
||||
* PM_USAGE_NO_MASTER - No master is currently using
|
||||
* the node
|
||||
* PM_USAGE_CURRENT_MASTER - Only requesting master is
|
||||
* currently using the node
|
||||
* PM_USAGE_OTHER_MASTER - Only other masters are
|
||||
* currently using the node
|
||||
* PM_USAGE_BOTH_MASTERS - Both the current and at least
|
||||
* one other master is currently
|
||||
* using the node
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
int zynqmp_pm_get_rpu_node_status(const u32 node, u32 *const status,
|
||||
u32 *const requirements, u32 *const usage)
|
||||
{
|
||||
if (zynqmp_pm_feature(PM_GET_NODE_STATUS) < PM_API_VERSION_2)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return zynqmp_pm_get_node_status(node, status, requirements, usage);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_get_rpu_node_status);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_force_pwrdwn - PM call to request for another PU or subsystem to
|
||||
* be powered down forcefully
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ config QCOM_Q6V5_COMMON
|
|||
depends on QCOM_SMEM
|
||||
|
||||
config QCOM_Q6V5_ADSP
|
||||
tristate "Qualcomm Technology Inc ADSP Peripheral Image Loader"
|
||||
tristate "Qualcomm ADSP Peripheral Image Loader"
|
||||
depends on OF && ARCH_QCOM
|
||||
depends on QCOM_SMEM
|
||||
depends on RPMSG_QCOM_SMD || RPMSG_QCOM_SMD=n
|
||||
|
|
@ -316,7 +316,6 @@ config ST_SLIM_REMOTEPROC
|
|||
config STM32_RPROC
|
||||
tristate "STM32 remoteproc support"
|
||||
depends on ARCH_STM32 || COMPILE_TEST
|
||||
depends on REMOTEPROC
|
||||
select MAILBOX
|
||||
help
|
||||
Say y here to support STM32 MCU processors via the
|
||||
|
|
|
|||
|
|
@ -145,6 +145,41 @@ static const struct imx_rproc_att imx_rproc_att_imx95_m7[] = {
|
|||
{ 0x80000000, 0x80000000, 0x50000000, 0 },
|
||||
};
|
||||
|
||||
static const struct imx_rproc_att imx_rproc_att_imx94_m70[] = {
|
||||
/* dev addr , sys addr , size , flags */
|
||||
/* TCM CODE NON-SECURE */
|
||||
{ 0x00000000, 0x203C0000, 0x00040000, ATT_OWN | ATT_IOMEM },
|
||||
/* TCM SYS NON-SECURE*/
|
||||
{ 0x20000000, 0x20400000, 0x00040000, ATT_OWN | ATT_IOMEM },
|
||||
|
||||
/* DDR */
|
||||
{ 0x80000000, 0x80000000, 0x10000000, 0 },
|
||||
};
|
||||
|
||||
static const struct imx_rproc_att imx_rproc_att_imx94_m71[] = {
|
||||
/* dev addr , sys addr , size , flags */
|
||||
/* TCM CODE NON-SECURE */
|
||||
{ 0x00000000, 0x202C0000, 0x00040000, ATT_OWN | ATT_IOMEM },
|
||||
/* TCM SYS NON-SECURE*/
|
||||
{ 0x20000000, 0x20300000, 0x00040000, ATT_OWN | ATT_IOMEM },
|
||||
|
||||
/* DDR */
|
||||
{ 0x80000000, 0x80000000, 0x10000000, 0 },
|
||||
};
|
||||
|
||||
static const struct imx_rproc_att imx_rproc_att_imx94_m33s[] = {
|
||||
/* dev addr , sys addr , size , flags */
|
||||
/* TCM CODE NON-SECURE */
|
||||
{ 0x0FFC0000, 0x209C0000, 0x00040000, ATT_OWN | ATT_IOMEM },
|
||||
/* TCM SYS NON-SECURE */
|
||||
{ 0x20000000, 0x20A00000, 0x00040000, ATT_OWN | ATT_IOMEM },
|
||||
/* M33S OCRAM NON-SECURE */
|
||||
{ 0x20800000, 0x20800000, 0x180000, ATT_OWN | ATT_IOMEM },
|
||||
|
||||
/* DDR */
|
||||
{ 0x80000000, 0x80000000, 0x10000000, 0 },
|
||||
};
|
||||
|
||||
static const struct imx_rproc_att imx_rproc_att_imx93[] = {
|
||||
/* dev addr , sys addr , size , flags */
|
||||
/* TCM CODE NON-SECURE */
|
||||
|
|
@ -339,13 +374,32 @@ static int imx_rproc_scu_api_start(struct rproc *rproc)
|
|||
return imx_sc_pm_cpu_start(priv->ipc_handle, priv->rsrc_id, true, priv->entry);
|
||||
}
|
||||
|
||||
static u64 imx_rproc_sm_get_reset_vector(struct rproc *rproc)
|
||||
{
|
||||
struct imx_rproc *priv = rproc->priv;
|
||||
u32 reset_vector_mask = priv->dcfg->reset_vector_mask ?: GENMASK(31, 0);
|
||||
|
||||
/*
|
||||
* The hardware fetches the first two words from reset_vectors
|
||||
* (hardware reset address) and populates SP and PC using the first
|
||||
* two words. Execution proceeds from PC. The ELF entry point does
|
||||
* not always match the hardware reset address.
|
||||
* To derive the correct hardware reset address, the lower address
|
||||
* bits must be masked off before programming the reset vector.
|
||||
*/
|
||||
return rproc->bootaddr & reset_vector_mask;
|
||||
}
|
||||
|
||||
static int imx_rproc_sm_cpu_start(struct rproc *rproc)
|
||||
{
|
||||
struct imx_rproc *priv = rproc->priv;
|
||||
const struct imx_rproc_dcfg *dcfg = priv->dcfg;
|
||||
u64 reset_vector;
|
||||
int ret;
|
||||
|
||||
ret = scmi_imx_cpu_reset_vector_set(dcfg->cpuid, 0, true, false, false);
|
||||
reset_vector = imx_rproc_sm_get_reset_vector(rproc);
|
||||
|
||||
ret = scmi_imx_cpu_reset_vector_set(dcfg->cpuid, reset_vector, true, false, false);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "Failed to set reset vector cpuid(%u): %d\n", dcfg->cpuid, ret);
|
||||
return ret;
|
||||
|
|
@ -359,13 +413,16 @@ static int imx_rproc_sm_lmm_start(struct rproc *rproc)
|
|||
struct imx_rproc *priv = rproc->priv;
|
||||
const struct imx_rproc_dcfg *dcfg = priv->dcfg;
|
||||
struct device *dev = priv->dev;
|
||||
u64 reset_vector;
|
||||
int ret;
|
||||
|
||||
reset_vector = imx_rproc_sm_get_reset_vector(rproc);
|
||||
|
||||
/*
|
||||
* If the remoteproc core can't start the M7, it will already be
|
||||
* handled in imx_rproc_sm_lmm_prepare().
|
||||
*/
|
||||
ret = scmi_imx_lmm_reset_vector_set(dcfg->lmid, dcfg->cpuid, 0, 0);
|
||||
ret = scmi_imx_lmm_reset_vector_set(dcfg->lmid, dcfg->cpuid, 0, reset_vector);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to set reset vector lmid(%u), cpuid(%u): %d\n",
|
||||
dcfg->lmid, dcfg->cpuid, ret);
|
||||
|
|
@ -1230,8 +1287,7 @@ static int imx_rproc_probe(struct platform_device *pdev)
|
|||
const struct imx_rproc_dcfg *dcfg;
|
||||
int ret;
|
||||
|
||||
/* set some other name then imx */
|
||||
rproc = devm_rproc_alloc(dev, "imx-rproc", &imx_rproc_ops,
|
||||
rproc = devm_rproc_alloc(dev, np->name, &imx_rproc_ops,
|
||||
NULL, sizeof(*priv));
|
||||
if (!rproc)
|
||||
return -ENOMEM;
|
||||
|
|
@ -1455,6 +1511,33 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx93 = {
|
|||
.flags = IMX_RPROC_NEED_CLKS,
|
||||
};
|
||||
|
||||
static const struct imx_rproc_dcfg imx_rproc_cfg_imx94_m70 = {
|
||||
.att = imx_rproc_att_imx94_m70,
|
||||
.att_size = ARRAY_SIZE(imx_rproc_att_imx94_m70),
|
||||
.ops = &imx_rproc_ops_sm_lmm,
|
||||
.cpuid = 1,
|
||||
.lmid = 2,
|
||||
.reset_vector_mask = GENMASK_U32(31, 16),
|
||||
};
|
||||
|
||||
static const struct imx_rproc_dcfg imx_rproc_cfg_imx94_m71 = {
|
||||
.att = imx_rproc_att_imx94_m71,
|
||||
.att_size = ARRAY_SIZE(imx_rproc_att_imx94_m71),
|
||||
.ops = &imx_rproc_ops_sm_lmm,
|
||||
.cpuid = 7,
|
||||
.lmid = 3,
|
||||
.reset_vector_mask = GENMASK_U32(31, 16),
|
||||
};
|
||||
|
||||
static const struct imx_rproc_dcfg imx_rproc_cfg_imx94_m33s = {
|
||||
.att = imx_rproc_att_imx94_m33s,
|
||||
.att_size = ARRAY_SIZE(imx_rproc_att_imx94_m33s),
|
||||
.ops = &imx_rproc_ops_sm_lmm,
|
||||
.cpuid = 8,
|
||||
.lmid = 1,
|
||||
.reset_vector_mask = GENMASK_U32(31, 16),
|
||||
};
|
||||
|
||||
static const struct imx_rproc_dcfg imx_rproc_cfg_imx95_m7 = {
|
||||
.att = imx_rproc_att_imx95_m7,
|
||||
.att_size = ARRAY_SIZE(imx_rproc_att_imx95_m7),
|
||||
|
|
@ -1462,6 +1545,7 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx95_m7 = {
|
|||
/* Must align with System Manager Firmware */
|
||||
.cpuid = 1, /* Use 1 as cpu id for M7 core */
|
||||
.lmid = 1, /* Use 1 as Logical Machine ID where M7 resides */
|
||||
.reset_vector_mask = GENMASK_U32(31, 16),
|
||||
};
|
||||
|
||||
static const struct of_device_id imx_rproc_of_match[] = {
|
||||
|
|
@ -1478,6 +1562,9 @@ static const struct of_device_id imx_rproc_of_match[] = {
|
|||
{ .compatible = "fsl,imx8qm-cm4", .data = &imx_rproc_cfg_imx8qm },
|
||||
{ .compatible = "fsl,imx8ulp-cm33", .data = &imx_rproc_cfg_imx8ulp },
|
||||
{ .compatible = "fsl,imx93-cm33", .data = &imx_rproc_cfg_imx93 },
|
||||
{ .compatible = "fsl,imx94-cm70", .data = &imx_rproc_cfg_imx94_m70 },
|
||||
{ .compatible = "fsl,imx94-cm71", .data = &imx_rproc_cfg_imx94_m71 },
|
||||
{ .compatible = "fsl,imx94-cm33s", .data = &imx_rproc_cfg_imx94_m33s },
|
||||
{ .compatible = "fsl,imx95-cm7", .data = &imx_rproc_cfg_imx95_m7 },
|
||||
{},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ struct imx_rproc_dcfg {
|
|||
/* For System Manager(SM) based SoCs */
|
||||
u32 cpuid; /* ID of the remote core */
|
||||
u32 lmid; /* ID of the Logcial Machine */
|
||||
/* reset_vector = elf_entry_addr & reset_vector_mask */
|
||||
u32 reset_vector_mask;
|
||||
};
|
||||
|
||||
#endif /* _IMX_RPROC_H */
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ static int qcom_add_minidump_segments(struct rproc *rproc, struct minidump_subsy
|
|||
struct minidump_region __iomem *ptr;
|
||||
struct minidump_region region;
|
||||
int seg_cnt, i;
|
||||
int ret = 0;
|
||||
dma_addr_t da;
|
||||
size_t size;
|
||||
char *name;
|
||||
|
|
@ -129,17 +130,22 @@ static int qcom_add_minidump_segments(struct rproc *rproc, struct minidump_subsy
|
|||
if (le32_to_cpu(region.valid) == MINIDUMP_REGION_VALID) {
|
||||
name = kstrndup(region.name, MAX_REGION_NAME_LENGTH - 1, GFP_KERNEL);
|
||||
if (!name) {
|
||||
iounmap(ptr);
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
da = le64_to_cpu(region.address);
|
||||
size = le64_to_cpu(region.size);
|
||||
rproc_coredump_add_custom_segment(rproc, da, size, rproc_dumpfn_t, name);
|
||||
ret = rproc_coredump_add_custom_segment(rproc, da, size, rproc_dumpfn_t,
|
||||
name);
|
||||
if (ret) {
|
||||
kfree(name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iounmap(ptr);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
|
||||
|
|
|
|||
|
|
@ -92,9 +92,6 @@ struct qcom_pas {
|
|||
const struct firmware *firmware;
|
||||
const struct firmware *dtb_firmware;
|
||||
|
||||
struct completion start_done;
|
||||
struct completion stop_done;
|
||||
|
||||
phys_addr_t mem_phys;
|
||||
phys_addr_t dtb_mem_phys;
|
||||
phys_addr_t mem_reloc;
|
||||
|
|
@ -1457,6 +1454,51 @@ static const struct qcom_pas_data sc7280_wpss_resource = {
|
|||
.ssctl_id = 0x19,
|
||||
};
|
||||
|
||||
static const struct qcom_pas_data shikra_cdsp_resource = {
|
||||
.crash_reason_smem = 601,
|
||||
.firmware_name = "cdsp.mbn",
|
||||
.pas_id = 18,
|
||||
.minidump_id = 7,
|
||||
.auto_boot = true,
|
||||
.proxy_pd_names = (char *[]){
|
||||
"cx",
|
||||
NULL
|
||||
},
|
||||
.load_state = "cdsp",
|
||||
.ssr_name = "cdsp",
|
||||
.sysmon_name = "cdsp",
|
||||
.ssctl_id = 0x17,
|
||||
.smem_host_id = 5,
|
||||
};
|
||||
|
||||
static const struct qcom_pas_data shikra_lpaicp_resource = {
|
||||
.crash_reason_smem = 682,
|
||||
.firmware_name = "lpaicp.mbn",
|
||||
.dtb_firmware_name = "lpaicp_dtb.mbn",
|
||||
.pas_id = 0x56,
|
||||
.dtb_pas_id = 0x57,
|
||||
.minidump_id = 0,
|
||||
.auto_boot = true,
|
||||
.ssr_name = "lpaicp",
|
||||
.sysmon_name = "lpaicp",
|
||||
};
|
||||
|
||||
static const struct qcom_pas_data shikra_mpss_resource = {
|
||||
.crash_reason_smem = 421,
|
||||
.firmware_name = "qdsp6sw.mbn",
|
||||
.pas_id = 4,
|
||||
.minidump_id = 3,
|
||||
.auto_boot = false,
|
||||
.proxy_pd_names = (char *[]){
|
||||
"cx",
|
||||
NULL
|
||||
},
|
||||
.load_state = "modem",
|
||||
.ssr_name = "mpss",
|
||||
.sysmon_name = "modem",
|
||||
.ssctl_id = 0x12,
|
||||
};
|
||||
|
||||
static const struct qcom_pas_data sm8650_cdsp_resource = {
|
||||
.crash_reason_smem = 601,
|
||||
.firmware_name = "cdsp.mdt",
|
||||
|
|
@ -1571,6 +1613,9 @@ static const struct of_device_id qcom_pas_of_match[] = {
|
|||
{ .compatible = "qcom,sdm845-slpi-pas", .data = &sdm845_slpi_resource_init },
|
||||
{ .compatible = "qcom,sdx55-mpss-pas", .data = &sdx55_mpss_resource },
|
||||
{ .compatible = "qcom,sdx75-mpss-pas", .data = &sm8650_mpss_resource },
|
||||
{ .compatible = "qcom,shikra-cdsp-pas", .data = &shikra_cdsp_resource },
|
||||
{ .compatible = "qcom,shikra-lpaicp-pas", .data = &shikra_lpaicp_resource },
|
||||
{ .compatible = "qcom,shikra-mpss-pas", .data = &shikra_mpss_resource },
|
||||
{ .compatible = "qcom,sm6115-adsp-pas", .data = &adsp_resource_init },
|
||||
{ .compatible = "qcom,sm6115-cdsp-pas", .data = &cdsp_resource_init },
|
||||
{ .compatible = "qcom,sm6115-mpss-pas", .data = &sc8180x_mpss_resource },
|
||||
|
|
|
|||
|
|
@ -96,7 +96,6 @@ struct wcss_data {
|
|||
unsigned int crash_reason_smem;
|
||||
u32 version;
|
||||
bool aon_reset_required;
|
||||
bool wcss_q6_reset_required;
|
||||
const char *ssr_name;
|
||||
const char *sysmon_name;
|
||||
int ssctl_id;
|
||||
|
|
@ -134,7 +133,6 @@ struct q6v5_wcss {
|
|||
struct reset_control *wcss_aon_reset;
|
||||
struct reset_control *wcss_reset;
|
||||
struct reset_control *wcss_q6_reset;
|
||||
struct reset_control *wcss_q6_bcr_reset;
|
||||
|
||||
struct qcom_q6v5 q6v5;
|
||||
|
||||
|
|
@ -309,7 +307,7 @@ static int q6v5_wcss_qcs404_power_on(struct q6v5_wcss *wcss)
|
|||
return ret;
|
||||
|
||||
/* Remove reset to the WCNSS QDSP6SS */
|
||||
reset_control_deassert(wcss->wcss_q6_bcr_reset);
|
||||
reset_control_deassert(wcss->wcss_q6_reset);
|
||||
|
||||
/* Enable Q6SSTOP_AHBFABRIC_CBCR clock */
|
||||
ret = clk_prepare_enable(wcss->ahbfabric_cbcr_clk);
|
||||
|
|
@ -803,19 +801,10 @@ static int q6v5_wcss_init_reset(struct q6v5_wcss *wcss,
|
|||
return PTR_ERR(wcss->wcss_reset);
|
||||
}
|
||||
|
||||
if (desc->wcss_q6_reset_required) {
|
||||
wcss->wcss_q6_reset = devm_reset_control_get_exclusive(dev, "wcss_q6_reset");
|
||||
if (IS_ERR(wcss->wcss_q6_reset)) {
|
||||
dev_err(wcss->dev, "unable to acquire wcss_q6_reset\n");
|
||||
return PTR_ERR(wcss->wcss_q6_reset);
|
||||
}
|
||||
}
|
||||
|
||||
wcss->wcss_q6_bcr_reset = devm_reset_control_get_optional_exclusive(dev,
|
||||
"wcss_q6_bcr_reset");
|
||||
if (IS_ERR(wcss->wcss_q6_bcr_reset)) {
|
||||
dev_err(wcss->dev, "unable to acquire wcss_q6_bcr_reset\n");
|
||||
return PTR_ERR(wcss->wcss_q6_bcr_reset);
|
||||
wcss->wcss_q6_reset = devm_reset_control_get_exclusive(dev, "wcss_q6_reset");
|
||||
if (IS_ERR(wcss->wcss_q6_reset)) {
|
||||
dev_err(wcss->dev, "unable to acquire wcss_q6_reset\n");
|
||||
return PTR_ERR(wcss->wcss_q6_reset);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1062,7 +1051,6 @@ static const struct wcss_data wcss_ipq8074_res_init = {
|
|||
.firmware_name = "IPQ8074/q6_fw.mdt",
|
||||
.crash_reason_smem = WCSS_CRASH_REASON,
|
||||
.aon_reset_required = true,
|
||||
.wcss_q6_reset_required = true,
|
||||
.ops = &q6v5_wcss_ipq8074_ops,
|
||||
.requires_force_stop = true,
|
||||
};
|
||||
|
|
@ -1072,7 +1060,6 @@ static const struct wcss_data wcss_qcs404_res_init = {
|
|||
.firmware_name = "wcnss.mdt",
|
||||
.version = WCSS_QCS404,
|
||||
.aon_reset_required = false,
|
||||
.wcss_q6_reset_required = false,
|
||||
.ssr_name = "mpss",
|
||||
.sysmon_name = "wcnss",
|
||||
.ssctl_id = 0x12,
|
||||
|
|
|
|||
|
|
@ -1011,60 +1011,55 @@ static rproc_handle_resource_t rproc_loading_handlers[RSC_LAST] = {
|
|||
[RSC_VDEV] = rproc_handle_vdev,
|
||||
};
|
||||
|
||||
struct rproc_rsc_cb_data {
|
||||
struct rproc *rproc;
|
||||
rproc_handle_resource_t *handlers;
|
||||
};
|
||||
|
||||
static int rproc_handle_rsc_entry(u32 type, void *rsc, int offset,
|
||||
int avail, void *data)
|
||||
{
|
||||
struct rproc_rsc_cb_data *d = data;
|
||||
struct rproc *rproc = d->rproc;
|
||||
struct device *dev = &rproc->dev;
|
||||
rproc_handle_resource_t handler;
|
||||
int ret;
|
||||
|
||||
dev_dbg(dev, "rsc: type %d\n", type);
|
||||
|
||||
if (type >= RSC_VENDOR_START && type <= RSC_VENDOR_END) {
|
||||
ret = rproc_handle_rsc(rproc, type, rsc, offset, avail);
|
||||
if (ret == RSC_HANDLED)
|
||||
return 0;
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
dev_warn(dev, "unsupported vendor resource %d\n", type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (type >= RSC_LAST) {
|
||||
dev_warn(dev, "unsupported resource %d\n", type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
handler = d->handlers[type];
|
||||
if (!handler)
|
||||
return 0;
|
||||
|
||||
return handler(rproc, rsc, offset, avail);
|
||||
}
|
||||
|
||||
/* handle firmware resource entries before booting the remote processor */
|
||||
static int rproc_handle_resources(struct rproc *rproc,
|
||||
rproc_handle_resource_t handlers[RSC_LAST])
|
||||
{
|
||||
struct device *dev = &rproc->dev;
|
||||
rproc_handle_resource_t handler;
|
||||
int ret = 0, i;
|
||||
struct rproc_rsc_cb_data d = { .rproc = rproc, .handlers = handlers };
|
||||
|
||||
if (!rproc->table_ptr)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < rproc->table_ptr->num; i++) {
|
||||
int offset = rproc->table_ptr->offset[i];
|
||||
struct fw_rsc_hdr *hdr = (void *)rproc->table_ptr + offset;
|
||||
int avail = rproc->table_sz - offset - sizeof(*hdr);
|
||||
void *rsc = (void *)hdr + sizeof(*hdr);
|
||||
|
||||
/* make sure table isn't truncated */
|
||||
if (avail < 0) {
|
||||
dev_err(dev, "rsc table is truncated\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "rsc: type %d\n", hdr->type);
|
||||
|
||||
if (hdr->type >= RSC_VENDOR_START &&
|
||||
hdr->type <= RSC_VENDOR_END) {
|
||||
ret = rproc_handle_rsc(rproc, hdr->type, rsc,
|
||||
offset + sizeof(*hdr), avail);
|
||||
if (ret == RSC_HANDLED)
|
||||
continue;
|
||||
else if (ret < 0)
|
||||
break;
|
||||
|
||||
dev_warn(dev, "unsupported vendor resource %d\n",
|
||||
hdr->type);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hdr->type >= RSC_LAST) {
|
||||
dev_warn(dev, "unsupported resource %d\n", hdr->type);
|
||||
continue;
|
||||
}
|
||||
|
||||
handler = handlers[hdr->type];
|
||||
if (!handler)
|
||||
continue;
|
||||
|
||||
ret = handler(rproc, rsc, offset + sizeof(*hdr), avail);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return rsc_table_for_each_entry(rproc->table_ptr, rproc->table_sz,
|
||||
&rproc->dev, rproc_handle_rsc_entry, &d);
|
||||
}
|
||||
|
||||
static int rproc_prepare_subdevices(struct rproc *rproc)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <dt-bindings/power/xlnx-zynqmp-power.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/firmware/xlnx-zynqmp.h>
|
||||
#include <linux/kernel.h>
|
||||
|
|
@ -19,6 +18,11 @@
|
|||
|
||||
#include "remoteproc_internal.h"
|
||||
|
||||
#define PD_R5_0_ATCM 15
|
||||
#define PD_R5_0_BTCM 16
|
||||
#define PD_R5_1_ATCM 17
|
||||
#define PD_R5_1_BTCM 18
|
||||
|
||||
/* IPI buffer MAX length */
|
||||
#define IPI_BUF_LEN_MAX 32U
|
||||
|
||||
|
|
@ -899,17 +903,18 @@ static const struct rproc_ops zynqmp_r5_rproc_ops = {
|
|||
};
|
||||
|
||||
/**
|
||||
* zynqmp_r5_add_rproc_core() - Add core data to framework.
|
||||
* Allocate and add struct rproc object for each r5f core
|
||||
* zynqmp_r5_alloc_rproc_core() - alloc rproc core data structure
|
||||
* Allocate struct rproc object for each r5f core
|
||||
* This is called for each individual r5f core
|
||||
*
|
||||
* @cdev: Device node of each r5 core
|
||||
*
|
||||
* Return: zynqmp_r5_core object for success else error code pointer
|
||||
*/
|
||||
static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
|
||||
static struct zynqmp_r5_core *zynqmp_r5_alloc_rproc_core(struct device *cdev)
|
||||
{
|
||||
struct zynqmp_r5_core *r5_core;
|
||||
const char *fw_name = NULL;
|
||||
struct rproc *r5_rproc;
|
||||
int ret;
|
||||
|
||||
|
|
@ -918,10 +923,15 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
|
|||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
ret = rproc_of_parse_firmware(cdev, 0, &fw_name);
|
||||
if (ret < 0 && ret != -EINVAL)
|
||||
return ERR_PTR(dev_err_probe(cdev, ret,
|
||||
"failed to parse firmware-name\n"));
|
||||
|
||||
/* Allocate remoteproc instance */
|
||||
r5_rproc = rproc_alloc(cdev, dev_name(cdev),
|
||||
&zynqmp_r5_rproc_ops,
|
||||
NULL, sizeof(struct zynqmp_r5_core));
|
||||
fw_name, sizeof(struct zynqmp_r5_core));
|
||||
if (!r5_rproc) {
|
||||
dev_err(cdev, "failed to allocate memory for rproc instance\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
|
@ -932,6 +942,11 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
|
|||
r5_rproc->recovery_disabled = true;
|
||||
r5_rproc->has_iommu = false;
|
||||
r5_rproc->auto_boot = false;
|
||||
|
||||
/* attempt to boot automatically if the firmware-name is provided */
|
||||
if (fw_name)
|
||||
r5_rproc->auto_boot = true;
|
||||
|
||||
r5_core = r5_rproc->priv;
|
||||
r5_core->dev = cdev;
|
||||
r5_core->np = dev_of_node(cdev);
|
||||
|
|
@ -941,23 +956,6 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
|
|||
goto free_rproc;
|
||||
}
|
||||
|
||||
/* Add R5 remoteproc core */
|
||||
ret = rproc_add(r5_rproc);
|
||||
if (ret) {
|
||||
dev_err(cdev, "failed to add r5 remoteproc\n");
|
||||
goto free_rproc;
|
||||
}
|
||||
|
||||
/*
|
||||
* If firmware is already available in the memory then move rproc state
|
||||
* to DETACHED. Firmware can be preloaded via debugger or by any other
|
||||
* agent (processors) in the system.
|
||||
* If firmware isn't available in the memory and resource table isn't
|
||||
* found, then rproc state remains OFFLINE.
|
||||
*/
|
||||
if (!zynqmp_r5_get_rsc_table_va(r5_core))
|
||||
r5_rproc->state = RPROC_DETACHED;
|
||||
|
||||
r5_core->rproc = r5_rproc;
|
||||
return r5_core;
|
||||
|
||||
|
|
@ -1210,6 +1208,7 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
|
|||
{
|
||||
struct device *dev = cluster->dev;
|
||||
struct zynqmp_r5_core *r5_core;
|
||||
u32 req, usage, status;
|
||||
int ret = -EINVAL, i;
|
||||
|
||||
r5_core = cluster->r5_cores[0];
|
||||
|
|
@ -1255,6 +1254,42 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
|
|||
ret = zynqmp_r5_get_sram_banks(r5_core);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* It is possible that firmware is loaded into the memory, but
|
||||
* RPU (remote) is not running. In such case, RPU state will be
|
||||
* moved to RPROC_DETACHED wrongfully. To avoid it first make
|
||||
* sure RPU is power-on and out of reset before parsing for the
|
||||
* resource table.
|
||||
*/
|
||||
ret = zynqmp_pm_get_rpu_node_status(r5_core->pm_domain_id,
|
||||
&status, &req, &usage);
|
||||
if (ret) {
|
||||
dev_warn(r5_core->dev,
|
||||
"failed to get rpu node status, err %d\n", ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If RPU state is power on and out of reset i.e. running, then
|
||||
* assign RPROC_DETACHED state. If the RPU is not out of reset
|
||||
* then do not attempt to attach to the remote processor.
|
||||
*/
|
||||
if (status == PM_NODE_RUNNING) {
|
||||
/*
|
||||
* Not all the firmware that is running on the remote
|
||||
* core is expected to have the resource table. The
|
||||
* firmware might not use RPMsg at all, and in that case
|
||||
* resource table becomes irrelevant. However, we still
|
||||
* need to make sure that running core is not reported
|
||||
* as offline. so do not decide remote core state based
|
||||
* on the resource table availability
|
||||
*/
|
||||
if (zynqmp_r5_get_rsc_table_va(r5_core))
|
||||
dev_dbg(r5_core->dev, "rsc tbl not found\n");
|
||||
r5_core->rproc->state = RPROC_DETACHED;
|
||||
r5_core->rproc->auto_boot = true;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1278,7 +1313,7 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
|
|||
enum rpu_oper_mode fw_reg_val;
|
||||
struct device **child_devs;
|
||||
enum rpu_tcm_comb tcm_mode;
|
||||
int core_count, ret, i;
|
||||
int core_count, ret, i, j;
|
||||
struct mbox_info *ipi;
|
||||
|
||||
ret = of_property_read_u32(dev_node, "xlnx,cluster-mode", &cluster_mode);
|
||||
|
|
@ -1364,7 +1399,7 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
|
|||
child_devs[i] = &child_pdev->dev;
|
||||
|
||||
/* create and add remoteproc instance of type struct rproc */
|
||||
r5_cores[i] = zynqmp_r5_add_rproc_core(&child_pdev->dev);
|
||||
r5_cores[i] = zynqmp_r5_alloc_rproc_core(&child_pdev->dev);
|
||||
if (IS_ERR(r5_cores[i])) {
|
||||
ret = PTR_ERR(r5_cores[i]);
|
||||
r5_cores[i] = NULL;
|
||||
|
|
@ -1409,16 +1444,31 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
|
|||
goto release_r5_cores;
|
||||
}
|
||||
|
||||
for (j = 0; j < cluster->core_count; j++) {
|
||||
/* Add R5 remoteproc core */
|
||||
ret = rproc_add(r5_cores[j]->rproc);
|
||||
if (ret) {
|
||||
dev_err_probe(r5_cores[j]->dev, ret,
|
||||
"failed to add remoteproc\n");
|
||||
goto delete_r5_cores;
|
||||
}
|
||||
}
|
||||
|
||||
kfree(child_devs);
|
||||
return 0;
|
||||
|
||||
delete_r5_cores:
|
||||
i = core_count - 1;
|
||||
/* delete previous added rproc */
|
||||
while (--j >= 0)
|
||||
rproc_del(r5_cores[j]->rproc);
|
||||
|
||||
release_r5_cores:
|
||||
while (i >= 0) {
|
||||
put_device(child_devs[i]);
|
||||
if (r5_cores[i]) {
|
||||
zynqmp_r5_free_mbox(r5_cores[i]->ipi);
|
||||
of_reserved_mem_device_release(r5_cores[i]->dev);
|
||||
rproc_del(r5_cores[i]->rproc);
|
||||
rproc_free(r5_cores[i]->rproc);
|
||||
}
|
||||
i--;
|
||||
|
|
|
|||
|
|
@ -542,6 +542,18 @@ enum pm_gem_config_type {
|
|||
GEM_CONFIG_FIXED = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum pm_node_status - Device node status provided by xilpm fw
|
||||
* @PM_NODE_UNUSED: Device is not used
|
||||
* @PM_NODE_RUNNING: Device is power-on and out of reset
|
||||
* @PM_NODE_HALT: Device is power-on but in the reset state
|
||||
*/
|
||||
enum pm_node_status {
|
||||
PM_NODE_UNUSED = 0,
|
||||
PM_NODE_RUNNING = 1,
|
||||
PM_NODE_HALT = 12,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct zynqmp_pm_query_data - PM query data
|
||||
* @qid: query ID
|
||||
|
|
@ -630,6 +642,8 @@ int zynqmp_pm_set_rpu_mode(u32 node_id, enum rpu_oper_mode rpu_mode);
|
|||
int zynqmp_pm_set_tcm_config(u32 node_id, enum rpu_tcm_comb tcm_mode);
|
||||
int zynqmp_pm_get_node_status(const u32 node, u32 *const status,
|
||||
u32 *const requirements, u32 *const usage);
|
||||
int zynqmp_pm_get_rpu_node_status(const u32 node, u32 *const status,
|
||||
u32 *const requirements, u32 *const usage);
|
||||
int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value);
|
||||
int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config,
|
||||
u32 value);
|
||||
|
|
@ -939,6 +953,13 @@ static inline int zynqmp_pm_get_node_status(const u32 node, u32 *const status,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int zynqmp_pm_get_rpu_node_status(const u32 node, u32 *const status,
|
||||
u32 *const requirements,
|
||||
u32 *const usage)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int zynqmp_pm_set_sd_config(u32 node,
|
||||
enum pm_sd_config_type config,
|
||||
u32 value)
|
||||
|
|
|
|||
|
|
@ -42,274 +42,7 @@
|
|||
#include <linux/completion.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
/**
|
||||
* struct resource_table - firmware resource table header
|
||||
* @ver: version number
|
||||
* @num: number of resource entries
|
||||
* @reserved: reserved (must be zero)
|
||||
* @offset: array of offsets pointing at the various resource entries
|
||||
*
|
||||
* A resource table is essentially a list of system resources required
|
||||
* by the remote processor. It may also include configuration entries.
|
||||
* If needed, the remote processor firmware should contain this table
|
||||
* as a dedicated ".resource_table" ELF section.
|
||||
*
|
||||
* Some resources entries are mere announcements, where the host is informed
|
||||
* of specific remoteproc configuration. Other entries require the host to
|
||||
* do something (e.g. allocate a system resource). Sometimes a negotiation
|
||||
* is expected, where the firmware requests a resource, and once allocated,
|
||||
* the host should provide back its details (e.g. address of an allocated
|
||||
* memory region).
|
||||
*
|
||||
* The header of the resource table, as expressed by this structure,
|
||||
* contains a version number (should we need to change this format in the
|
||||
* future), the number of available resource entries, and their offsets
|
||||
* in the table.
|
||||
*
|
||||
* Immediately following this header are the resource entries themselves,
|
||||
* each of which begins with a resource entry header (as described below).
|
||||
*/
|
||||
struct resource_table {
|
||||
u32 ver;
|
||||
u32 num;
|
||||
u32 reserved[2];
|
||||
u32 offset[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct fw_rsc_hdr - firmware resource entry header
|
||||
* @type: resource type
|
||||
* @data: resource data
|
||||
*
|
||||
* Every resource entry begins with a 'struct fw_rsc_hdr' header providing
|
||||
* its @type. The content of the entry itself will immediately follow
|
||||
* this header, and it should be parsed according to the resource type.
|
||||
*/
|
||||
struct fw_rsc_hdr {
|
||||
u32 type;
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* enum fw_resource_type - types of resource entries
|
||||
*
|
||||
* @RSC_CARVEOUT: request for allocation of a physically contiguous
|
||||
* memory region.
|
||||
* @RSC_DEVMEM: request to iommu_map a memory-based peripheral.
|
||||
* @RSC_TRACE: announces the availability of a trace buffer into which
|
||||
* the remote processor will be writing logs.
|
||||
* @RSC_VDEV: declare support for a virtio device, and serve as its
|
||||
* virtio header.
|
||||
* @RSC_LAST: just keep this one at the end of standard resources
|
||||
* @RSC_VENDOR_START: start of the vendor specific resource types range
|
||||
* @RSC_VENDOR_END: end of the vendor specific resource types range
|
||||
*
|
||||
* For more details regarding a specific resource type, please see its
|
||||
* dedicated structure below.
|
||||
*
|
||||
* Please note that these values are used as indices to the rproc_handle_rsc
|
||||
* lookup table, so please keep them sane. Moreover, @RSC_LAST is used to
|
||||
* check the validity of an index before the lookup table is accessed, so
|
||||
* please update it as needed.
|
||||
*/
|
||||
enum fw_resource_type {
|
||||
RSC_CARVEOUT = 0,
|
||||
RSC_DEVMEM = 1,
|
||||
RSC_TRACE = 2,
|
||||
RSC_VDEV = 3,
|
||||
RSC_LAST = 4,
|
||||
RSC_VENDOR_START = 128,
|
||||
RSC_VENDOR_END = 512,
|
||||
};
|
||||
|
||||
#define FW_RSC_ADDR_ANY (-1)
|
||||
|
||||
/**
|
||||
* struct fw_rsc_carveout - physically contiguous memory request
|
||||
* @da: device address
|
||||
* @pa: physical address
|
||||
* @len: length (in bytes)
|
||||
* @flags: iommu protection flags
|
||||
* @reserved: reserved (must be zero)
|
||||
* @name: human-readable name of the requested memory region
|
||||
*
|
||||
* This resource entry requests the host to allocate a physically contiguous
|
||||
* memory region.
|
||||
*
|
||||
* These request entries should precede other firmware resource entries,
|
||||
* as other entries might request placing other data objects inside
|
||||
* these memory regions (e.g. data/code segments, trace resource entries, ...).
|
||||
*
|
||||
* Allocating memory this way helps utilizing the reserved physical memory
|
||||
* (e.g. CMA) more efficiently, and also minimizes the number of TLB entries
|
||||
* needed to map it (in case @rproc is using an IOMMU). Reducing the TLB
|
||||
* pressure is important; it may have a substantial impact on performance.
|
||||
*
|
||||
* If the firmware is compiled with static addresses, then @da should specify
|
||||
* the expected device address of this memory region. If @da is set to
|
||||
* FW_RSC_ADDR_ANY, then the host will dynamically allocate it, and then
|
||||
* overwrite @da with the dynamically allocated address.
|
||||
*
|
||||
* We will always use @da to negotiate the device addresses, even if it
|
||||
* isn't using an iommu. In that case, though, it will obviously contain
|
||||
* physical addresses.
|
||||
*
|
||||
* Some remote processors needs to know the allocated physical address
|
||||
* even if they do use an iommu. This is needed, e.g., if they control
|
||||
* hardware accelerators which access the physical memory directly (this
|
||||
* is the case with OMAP4 for instance). In that case, the host will
|
||||
* overwrite @pa with the dynamically allocated physical address.
|
||||
* Generally we don't want to expose physical addresses if we don't have to
|
||||
* (remote processors are generally _not_ trusted), so we might want to
|
||||
* change this to happen _only_ when explicitly required by the hardware.
|
||||
*
|
||||
* @flags is used to provide IOMMU protection flags, and @name should
|
||||
* (optionally) contain a human readable name of this carveout region
|
||||
* (mainly for debugging purposes).
|
||||
*/
|
||||
struct fw_rsc_carveout {
|
||||
u32 da;
|
||||
u32 pa;
|
||||
u32 len;
|
||||
u32 flags;
|
||||
u32 reserved;
|
||||
u8 name[32];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct fw_rsc_devmem - iommu mapping request
|
||||
* @da: device address
|
||||
* @pa: physical address
|
||||
* @len: length (in bytes)
|
||||
* @flags: iommu protection flags
|
||||
* @reserved: reserved (must be zero)
|
||||
* @name: human-readable name of the requested region to be mapped
|
||||
*
|
||||
* This resource entry requests the host to iommu map a physically contiguous
|
||||
* memory region. This is needed in case the remote processor requires
|
||||
* access to certain memory-based peripherals; _never_ use it to access
|
||||
* regular memory.
|
||||
*
|
||||
* This is obviously only needed if the remote processor is accessing memory
|
||||
* via an iommu.
|
||||
*
|
||||
* @da should specify the required device address, @pa should specify
|
||||
* the physical address we want to map, @len should specify the size of
|
||||
* the mapping and @flags is the IOMMU protection flags. As always, @name may
|
||||
* (optionally) contain a human readable name of this mapping (mainly for
|
||||
* debugging purposes).
|
||||
*
|
||||
* Note: at this point we just "trust" those devmem entries to contain valid
|
||||
* physical addresses, but this isn't safe and will be changed: eventually we
|
||||
* want remoteproc implementations to provide us ranges of physical addresses
|
||||
* the firmware is allowed to request, and not allow firmwares to request
|
||||
* access to physical addresses that are outside those ranges.
|
||||
*/
|
||||
struct fw_rsc_devmem {
|
||||
u32 da;
|
||||
u32 pa;
|
||||
u32 len;
|
||||
u32 flags;
|
||||
u32 reserved;
|
||||
u8 name[32];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct fw_rsc_trace - trace buffer declaration
|
||||
* @da: device address
|
||||
* @len: length (in bytes)
|
||||
* @reserved: reserved (must be zero)
|
||||
* @name: human-readable name of the trace buffer
|
||||
*
|
||||
* This resource entry provides the host information about a trace buffer
|
||||
* into which the remote processor will write log messages.
|
||||
*
|
||||
* @da specifies the device address of the buffer, @len specifies
|
||||
* its size, and @name may contain a human readable name of the trace buffer.
|
||||
*
|
||||
* After booting the remote processor, the trace buffers are exposed to the
|
||||
* user via debugfs entries (called trace0, trace1, etc..).
|
||||
*/
|
||||
struct fw_rsc_trace {
|
||||
u32 da;
|
||||
u32 len;
|
||||
u32 reserved;
|
||||
u8 name[32];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct fw_rsc_vdev_vring - vring descriptor entry
|
||||
* @da: device address
|
||||
* @align: the alignment between the consumer and producer parts of the vring
|
||||
* @num: num of buffers supported by this vring (must be power of two)
|
||||
* @notifyid: a unique rproc-wide notify index for this vring. This notify
|
||||
* index is used when kicking a remote processor, to let it know that this
|
||||
* vring is triggered.
|
||||
* @pa: physical address
|
||||
*
|
||||
* This descriptor is not a resource entry by itself; it is part of the
|
||||
* vdev resource type (see below).
|
||||
*
|
||||
* Note that @da should either contain the device address where
|
||||
* the remote processor is expecting the vring, or indicate that
|
||||
* dynamically allocation of the vring's device address is supported.
|
||||
*/
|
||||
struct fw_rsc_vdev_vring {
|
||||
u32 da;
|
||||
u32 align;
|
||||
u32 num;
|
||||
u32 notifyid;
|
||||
u32 pa;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct fw_rsc_vdev - virtio device header
|
||||
* @id: virtio device id (as in virtio_ids.h)
|
||||
* @notifyid: a unique rproc-wide notify index for this vdev. This notify
|
||||
* index is used when kicking a remote processor, to let it know that the
|
||||
* status/features of this vdev have changes.
|
||||
* @dfeatures: specifies the virtio device features supported by the firmware
|
||||
* @gfeatures: a place holder used by the host to write back the
|
||||
* negotiated features that are supported by both sides.
|
||||
* @config_len: the size of the virtio config space of this vdev. The config
|
||||
* space lies in the resource table immediate after this vdev header.
|
||||
* @status: a place holder where the host will indicate its virtio progress.
|
||||
* @num_of_vrings: indicates how many vrings are described in this vdev header
|
||||
* @reserved: reserved (must be zero)
|
||||
* @vring: an array of @num_of_vrings entries of 'struct fw_rsc_vdev_vring'.
|
||||
*
|
||||
* This resource is a virtio device header: it provides information about
|
||||
* the vdev, and is then used by the host and its peer remote processors
|
||||
* to negotiate and share certain virtio properties.
|
||||
*
|
||||
* By providing this resource entry, the firmware essentially asks remoteproc
|
||||
* to statically allocate a vdev upon registration of the rproc (dynamic vdev
|
||||
* allocation is not yet supported).
|
||||
*
|
||||
* Note:
|
||||
* 1. unlike virtualization systems, the term 'host' here means
|
||||
* the Linux side which is running remoteproc to control the remote
|
||||
* processors. We use the name 'gfeatures' to comply with virtio's terms,
|
||||
* though there isn't really any virtualized guest OS here: it's the host
|
||||
* which is responsible for negotiating the final features.
|
||||
* Yeah, it's a bit confusing.
|
||||
*
|
||||
* 2. immediately following this structure is the virtio config space for
|
||||
* this vdev (which is specific to the vdev; for more info, read the virtio
|
||||
* spec). The size of the config space is specified by @config_len.
|
||||
*/
|
||||
struct fw_rsc_vdev {
|
||||
u32 id;
|
||||
u32 notifyid;
|
||||
u32 dfeatures;
|
||||
u32 gfeatures;
|
||||
u32 config_len;
|
||||
u8 status;
|
||||
u8 num_of_vrings;
|
||||
u8 reserved[2];
|
||||
struct fw_rsc_vdev_vring vring[];
|
||||
} __packed;
|
||||
#include <linux/rsc_table.h>
|
||||
|
||||
struct rproc;
|
||||
|
||||
|
|
|
|||
359
include/linux/rsc_table.h
Normal file
359
include/linux/rsc_table.h
Normal file
|
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
* Resource table and its types data structure
|
||||
*
|
||||
* Copyright(c) 2011 Texas Instruments, Inc.
|
||||
* Copyright(c) 2011 Google, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Texas Instruments nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef RSC_TABLE_H
|
||||
#define RSC_TABLE_H
|
||||
|
||||
/**
|
||||
* struct resource_table - firmware resource table header
|
||||
* @ver: version number
|
||||
* @num: number of resource entries
|
||||
* @reserved: reserved (must be zero)
|
||||
* @offset: array of offsets pointing at the various resource entries
|
||||
*
|
||||
* A resource table is essentially a list of system resources required
|
||||
* by the remote processor. It may also include configuration entries.
|
||||
* If needed, the remote processor firmware should contain this table
|
||||
* as a dedicated ".resource_table" ELF section.
|
||||
*
|
||||
* Some resources entries are mere announcements, where the host is informed
|
||||
* of specific remoteproc configuration. Other entries require the host to
|
||||
* do something (e.g. allocate a system resource). Sometimes a negotiation
|
||||
* is expected, where the firmware requests a resource, and once allocated,
|
||||
* the host should provide back its details (e.g. address of an allocated
|
||||
* memory region).
|
||||
*
|
||||
* The header of the resource table, as expressed by this structure,
|
||||
* contains a version number (should we need to change this format in the
|
||||
* future), the number of available resource entries, and their offsets
|
||||
* in the table.
|
||||
*
|
||||
* Immediately following this header are the resource entries themselves,
|
||||
* each of which begins with a resource entry header (as described below).
|
||||
*/
|
||||
struct resource_table {
|
||||
u32 ver;
|
||||
u32 num;
|
||||
u32 reserved[2];
|
||||
u32 offset[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct fw_rsc_hdr - firmware resource entry header
|
||||
* @type: resource type
|
||||
* @data: resource data
|
||||
*
|
||||
* Every resource entry begins with a 'struct fw_rsc_hdr' header providing
|
||||
* its @type. The content of the entry itself will immediately follow
|
||||
* this header, and it should be parsed according to the resource type.
|
||||
*/
|
||||
struct fw_rsc_hdr {
|
||||
u32 type;
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* enum fw_resource_type - types of resource entries
|
||||
*
|
||||
* @RSC_CARVEOUT: request for allocation of a physically contiguous
|
||||
* memory region.
|
||||
* @RSC_DEVMEM: request to iommu_map a memory-based peripheral.
|
||||
* @RSC_TRACE: announces the availability of a trace buffer into which
|
||||
* the remote processor will be writing logs.
|
||||
* @RSC_VDEV: declare support for a virtio device, and serve as its
|
||||
* virtio header.
|
||||
* @RSC_LAST: just keep this one at the end of standard resources
|
||||
* @RSC_VENDOR_START: start of the vendor specific resource types range
|
||||
* @RSC_VENDOR_END: end of the vendor specific resource types range
|
||||
*
|
||||
* For more details regarding a specific resource type, please see its
|
||||
* dedicated structure below.
|
||||
*
|
||||
* Please note that these values are used as indices to the rproc_handle_rsc
|
||||
* lookup table, so please keep them sane. Moreover, @RSC_LAST is used to
|
||||
* check the validity of an index before the lookup table is accessed, so
|
||||
* please update it as needed.
|
||||
*/
|
||||
enum fw_resource_type {
|
||||
RSC_CARVEOUT = 0,
|
||||
RSC_DEVMEM = 1,
|
||||
RSC_TRACE = 2,
|
||||
RSC_VDEV = 3,
|
||||
RSC_LAST = 4,
|
||||
RSC_VENDOR_START = 128,
|
||||
RSC_VENDOR_END = 512,
|
||||
};
|
||||
|
||||
#define FW_RSC_ADDR_ANY (-1)
|
||||
|
||||
/**
|
||||
* struct fw_rsc_carveout - physically contiguous memory request
|
||||
* @da: device address
|
||||
* @pa: physical address
|
||||
* @len: length (in bytes)
|
||||
* @flags: iommu protection flags
|
||||
* @reserved: reserved (must be zero)
|
||||
* @name: human-readable name of the requested memory region
|
||||
*
|
||||
* This resource entry requests the host to allocate a physically contiguous
|
||||
* memory region.
|
||||
*
|
||||
* These request entries should precede other firmware resource entries,
|
||||
* as other entries might request placing other data objects inside
|
||||
* these memory regions (e.g. data/code segments, trace resource entries, ...).
|
||||
*
|
||||
* Allocating memory this way helps utilizing the reserved physical memory
|
||||
* (e.g. CMA) more efficiently, and also minimizes the number of TLB entries
|
||||
* needed to map it (in case @rproc is using an IOMMU). Reducing the TLB
|
||||
* pressure is important; it may have a substantial impact on performance.
|
||||
*
|
||||
* If the firmware is compiled with static addresses, then @da should specify
|
||||
* the expected device address of this memory region. If @da is set to
|
||||
* FW_RSC_ADDR_ANY, then the host will dynamically allocate it, and then
|
||||
* overwrite @da with the dynamically allocated address.
|
||||
*
|
||||
* We will always use @da to negotiate the device addresses, even if it
|
||||
* isn't using an iommu. In that case, though, it will obviously contain
|
||||
* physical addresses.
|
||||
*
|
||||
* Some remote processors needs to know the allocated physical address
|
||||
* even if they do use an iommu. This is needed, e.g., if they control
|
||||
* hardware accelerators which access the physical memory directly (this
|
||||
* is the case with OMAP4 for instance). In that case, the host will
|
||||
* overwrite @pa with the dynamically allocated physical address.
|
||||
* Generally we don't want to expose physical addresses if we don't have to
|
||||
* (remote processors are generally _not_ trusted), so we might want to
|
||||
* change this to happen _only_ when explicitly required by the hardware.
|
||||
*
|
||||
* @flags is used to provide IOMMU protection flags, and @name should
|
||||
* (optionally) contain a human readable name of this carveout region
|
||||
* (mainly for debugging purposes).
|
||||
*/
|
||||
struct fw_rsc_carveout {
|
||||
u32 da;
|
||||
u32 pa;
|
||||
u32 len;
|
||||
u32 flags;
|
||||
u32 reserved;
|
||||
u8 name[32];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct fw_rsc_devmem - iommu mapping request
|
||||
* @da: device address
|
||||
* @pa: physical address
|
||||
* @len: length (in bytes)
|
||||
* @flags: iommu protection flags
|
||||
* @reserved: reserved (must be zero)
|
||||
* @name: human-readable name of the requested region to be mapped
|
||||
*
|
||||
* This resource entry requests the host to iommu map a physically contiguous
|
||||
* memory region. This is needed in case the remote processor requires
|
||||
* access to certain memory-based peripherals; _never_ use it to access
|
||||
* regular memory.
|
||||
*
|
||||
* This is obviously only needed if the remote processor is accessing memory
|
||||
* via an iommu.
|
||||
*
|
||||
* @da should specify the required device address, @pa should specify
|
||||
* the physical address we want to map, @len should specify the size of
|
||||
* the mapping and @flags is the IOMMU protection flags. As always, @name may
|
||||
* (optionally) contain a human readable name of this mapping (mainly for
|
||||
* debugging purposes).
|
||||
*
|
||||
* Note: at this point we just "trust" those devmem entries to contain valid
|
||||
* physical addresses, but this isn't safe and will be changed: eventually we
|
||||
* want remoteproc implementations to provide us ranges of physical addresses
|
||||
* the firmware is allowed to request, and not allow firmwares to request
|
||||
* access to physical addresses that are outside those ranges.
|
||||
*/
|
||||
struct fw_rsc_devmem {
|
||||
u32 da;
|
||||
u32 pa;
|
||||
u32 len;
|
||||
u32 flags;
|
||||
u32 reserved;
|
||||
u8 name[32];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct fw_rsc_trace - trace buffer declaration
|
||||
* @da: device address
|
||||
* @len: length (in bytes)
|
||||
* @reserved: reserved (must be zero)
|
||||
* @name: human-readable name of the trace buffer
|
||||
*
|
||||
* This resource entry provides the host information about a trace buffer
|
||||
* into which the remote processor will write log messages.
|
||||
*
|
||||
* @da specifies the device address of the buffer, @len specifies
|
||||
* its size, and @name may contain a human readable name of the trace buffer.
|
||||
*
|
||||
* After booting the remote processor, the trace buffers are exposed to the
|
||||
* user via debugfs entries (called trace0, trace1, etc..).
|
||||
*/
|
||||
struct fw_rsc_trace {
|
||||
u32 da;
|
||||
u32 len;
|
||||
u32 reserved;
|
||||
u8 name[32];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct fw_rsc_vdev_vring - vring descriptor entry
|
||||
* @da: device address
|
||||
* @align: the alignment between the consumer and producer parts of the vring
|
||||
* @num: num of buffers supported by this vring (must be power of two)
|
||||
* @notifyid: a unique rproc-wide notify index for this vring. This notify
|
||||
* index is used when kicking a remote processor, to let it know that this
|
||||
* vring is triggered.
|
||||
* @pa: physical address
|
||||
*
|
||||
* This descriptor is not a resource entry by itself; it is part of the
|
||||
* vdev resource type (see below).
|
||||
*
|
||||
* Note that @da should either contain the device address where
|
||||
* the remote processor is expecting the vring, or indicate that
|
||||
* dynamically allocation of the vring's device address is supported.
|
||||
*/
|
||||
struct fw_rsc_vdev_vring {
|
||||
u32 da;
|
||||
u32 align;
|
||||
u32 num;
|
||||
u32 notifyid;
|
||||
u32 pa;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct fw_rsc_vdev - virtio device header
|
||||
* @id: virtio device id (as in virtio_ids.h)
|
||||
* @notifyid: a unique rproc-wide notify index for this vdev. This notify
|
||||
* index is used when kicking a remote processor, to let it know that the
|
||||
* status/features of this vdev have changes.
|
||||
* @dfeatures: specifies the virtio device features supported by the firmware
|
||||
* @gfeatures: a place holder used by the host to write back the
|
||||
* negotiated features that are supported by both sides.
|
||||
* @config_len: the size of the virtio config space of this vdev. The config
|
||||
* space lies in the resource table immediate after this vdev header.
|
||||
* @status: a place holder where the host will indicate its virtio progress.
|
||||
* @num_of_vrings: indicates how many vrings are described in this vdev header
|
||||
* @reserved: reserved (must be zero)
|
||||
* @vring: an array of @num_of_vrings entries of 'struct fw_rsc_vdev_vring'.
|
||||
*
|
||||
* This resource is a virtio device header: it provides information about
|
||||
* the vdev, and is then used by the host and its peer remote processors
|
||||
* to negotiate and share certain virtio properties.
|
||||
*
|
||||
* By providing this resource entry, the firmware essentially asks remoteproc
|
||||
* to statically allocate a vdev upon registration of the rproc (dynamic vdev
|
||||
* allocation is not yet supported).
|
||||
*
|
||||
* Note:
|
||||
* 1. unlike virtualization systems, the term 'host' here means
|
||||
* the Linux side which is running remoteproc to control the remote
|
||||
* processors. We use the name 'gfeatures' to comply with virtio's terms,
|
||||
* though there isn't really any virtualized guest OS here: it's the host
|
||||
* which is responsible for negotiating the final features.
|
||||
* Yeah, it's a bit confusing.
|
||||
*
|
||||
* 2. immediately following this structure is the virtio config space for
|
||||
* this vdev (which is specific to the vdev; for more info, read the virtio
|
||||
* spec). The size of the config space is specified by @config_len.
|
||||
*/
|
||||
struct fw_rsc_vdev {
|
||||
u32 id;
|
||||
u32 notifyid;
|
||||
u32 dfeatures;
|
||||
u32 gfeatures;
|
||||
u32 config_len;
|
||||
u8 status;
|
||||
u8 num_of_vrings;
|
||||
u8 reserved[2];
|
||||
struct fw_rsc_vdev_vring vring[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* rsc_table_for_each_entry() - iterate over all entries in a resource table
|
||||
* @table: pointer to the resource table
|
||||
* @table_sz: total size of the table buffer in bytes
|
||||
* @dev: device used for error logging
|
||||
* @cb: callback invoked for each entry:
|
||||
* @type - value from enum fw_resource_type
|
||||
* @rsc - pointer to the entry payload (past struct fw_rsc_hdr)
|
||||
* @offset - byte offset of the payload within the table; callers
|
||||
* that write back into the table (e.g. to record a
|
||||
* dynamically allocated address) use this to locate the
|
||||
* entry for later update
|
||||
* @avail - bytes available in the payload
|
||||
* @data - caller-supplied private pointer
|
||||
* Return 0 to continue iteration, non-zero to stop.
|
||||
* @data: private pointer forwarded to @cb on every call
|
||||
*
|
||||
* Iterates over every resource entry in @table, performing the standard
|
||||
* truncation check, and invokes @cb for each one. Iteration stops on the
|
||||
* first non-zero return from @cb or on a malformed table.
|
||||
*
|
||||
* Returns 0 after a complete iteration, -EINVAL if the table is truncated,
|
||||
* or the first non-zero value returned by @cb.
|
||||
*/
|
||||
static inline int rsc_table_for_each_entry(struct resource_table *table,
|
||||
size_t table_sz,
|
||||
struct device *dev,
|
||||
int (*cb)(u32 type, void *rsc,
|
||||
int offset, int avail,
|
||||
void *data),
|
||||
void *data) {
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < table->num; i++) {
|
||||
int offset = table->offset[i];
|
||||
struct fw_rsc_hdr *hdr = (void *)table + offset;
|
||||
int avail = table_sz - offset - sizeof(*hdr);
|
||||
int rsc_offset = offset + sizeof(*hdr);
|
||||
void *rsc = (void *)hdr + sizeof(*hdr);
|
||||
|
||||
if (avail < 0) {
|
||||
dev_err(dev, "rsc table is truncated\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = cb(hdr->type, rsc, rsc_offset, avail, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* RSC_TABLE_H */
|
||||
Loading…
Reference in New Issue
Block a user