mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-06-21 15:43:21 +02:00
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:
@@ -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)
|
||||
|
||||
+1
-268
@@ -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;
|
||||
|
||||
|
||||
@@ -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 */
|
||||
Reference in New Issue
Block a user