2024-04-08 20:54:22

by Tanmay Shah

[permalink] [raw]
Subject: [PATCH v14 0/4] add zynqmp TCM bindings

Tightly-Coupled Memories(TCMs) are low-latency memory that provides
predictable instruction execution and predictable data load/store
timing. Each Cortex-R5F processor contains exclusive two 64 KB memory
banks on the ATCM and BTCM ports, for a total of 128 KB of memory.
In lockstep mode, both 128KB memory is accessible to the cluster.

As per ZynqMP Ultrascale+ Technical Reference Manual UG1085, following
is address space of TCM memory. The bindings in this patch series
introduces properties to accommodate following address space with
address translation between Linux and Cortex-R5 views.

| | | |
| --- | --- | --- |
| *Mode* | *R5 View* | *Linux view* | Notes |
| *Split Mode* | *start addr*| *start addr* | |
| R5_0 ATCM (64 KB) | 0x0000_0000 | 0xFFE0_0000 | |
| R5_0 BTCM (64 KB) | 0x0002_0000 | 0xFFE2_0000 | |
| R5_1 ATCM (64 KB) | 0x0000_0000 | 0xFFE9_0000 | alias of 0xFFE1_0000 |
| R5_1 BTCM (64 KB) | 0x0002_0000 | 0xFFEB_0000 | alias of 0xFFE3_0000 |
| ___ | ___ | ___ | |
| *Lockstep Mode* | | | |
| R5_0 ATCM (128 KB) | 0x0000_0000 | 0xFFE0_0000 | |
| R5_0 BTCM (128 KB) | 0x0002_0000 | 0xFFE2_0000 | |

References:
UG1085 TCM address space:
https://docs.xilinx.com/r/en-US/ug1085-zynq-ultrascale-trm/Tightly-Coupled-Memory-Address-Map

---

prerequisite-patch-link: https://lore.kernel.org/all/[email protected]/
Base Branch: 6.9.rc2

Changes in v14:
- Add xlnx,tcm-mode property and use it for TCM configuration
- Add Versal and Versal-NET platform support
- Maintain backward compatibility for ZynqMP platform and use hardcode
TCM addresses

Changes in v13:
- Have power-domains property for lockstep case instead of
keeping it flexible.
- Add "items:" list in power-domains property

Changes in v12:
- add "reg", "reg-names" and "power-domains" in pattern properties
- add "reg" and "reg-names" in required list
- keep "power-domains" in required list as it was before the change

Changes in v11:
- Fix yamllint warning and reduce indentation as needed
- Remove redundant initialization of the variable
- Return correct error code if memory allocation failed

Changs in v10:
- Add new patch (1/4) to series that changes hardcode TCM addresses in
lockstep mode and removes separate handling of TCM in lockstep and
split mode
- modify number of "reg", "reg-names" and "power-domains" entries
based on cluster mode
- Add extra optional atcm and btcm in "reg" property for lockstep mode
- Add "reg-names" for extra optional atcm and btcm for lockstep mode
- Drop previous Ack as bindings has new change
- Add individual tcm regions via "reg" and "reg-names" for lockstep mode
- Add each tcm's power-domains in lockstep mode
- Drop previous Ack as new change in dts patchset
- Remove redundant changes in driver to handle TCM in lockstep mode

Changes in v9:
- Fix rproc lockstep dts
- Introduce new API to request and release core1 TCM power-domains in
lockstep mode. This will be used during prepare -> add_tcm_banks
callback to enable TCM in lockstep mode.
- Parse TCM from device-tree in lockstep mode and split mode in
uniform way.
- Fix TCM representation in device-tree in lockstep mode.
- Fix comments as suggested

Changes in v8:
- Remove use of pm_domains framework
- Remove checking of pm_domain_id validation to power on/off tcm
- Remove spurious change
- parse power-domains property from device-tree and use EEMI calls
to power on/off TCM instead of using pm domains framework

Changes in v7:
- %s/pm_dev1/pm_dev_core0/r
- %s/pm_dev_link1/pm_dev_core0_link/r
- %s/pm_dev2/pm_dev_core1/r
- %s/pm_dev_link2/pm_dev_core1_link/r
- remove pm_domain_id check to move next patch
- add comment about how 1st entry in pm domain list is used
- fix loop when jump to fail_add_pm_domains loop
- move checking of pm_domain_id from previous patch
- fix mem_bank_data memory allocation

Changes in v6:
- Introduce new node entry for r5f cluster split mode dts and
keep it disabled by default.
- Keep remoteproc lockstep mode enabled by default to maintian
back compatibility.
- Enable split mode only for zcu102 board to demo split mode use
- Remove spurious change
- Handle errors in add_pm_domains function
- Remove redundant code to handle errors from remove_pm_domains
- Missing . at the end of the commit message
- remove redundant initialization of variables
- remove fail_tcm label and relevant code to free memory
acquired using devm_* API. As this will be freed when device free it
- add extra check to see if "reg" property is supported or not

Changes in v5:
- maintain Rob's Ack on bindings patch as no changes in bindings
- split previous patch into multiple patches
- Use pm domain framework to turn on/off TCM
- Add support of parsing TCM information from device-tree
- maintain backward compatibility with previous bindings without
TCM information available in device-tree

This patch series continues previous effort to upstream ZynqMP
TCM bindings:
Previous v4 version link:
https://lore.kernel.org/all/[email protected]/

Previous v3 version link:
https://lore.kernel.org/all/[email protected]/

Radhey Shyam Pandey (1):
dt-bindings: remoteproc: add Tightly Coupled Memory (TCM) bindings

Tanmay Shah (3):
remoteproc: zynqmp: fix lockstep mode memory region
dts: zynqmp: add properties for TCM in remoteproc
remoteproc: zynqmp: parse TCM from device tree

.../remoteproc/xlnx,zynqmp-r5fss.yaml | 279 +++++++++++++--
.../boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts | 8 +
arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 67 +++-
drivers/remoteproc/xlnx_r5_remoteproc.c | 319 ++++++++----------
4 files changed, 471 insertions(+), 202 deletions(-)


base-commit: 39cd87c4eb2b893354f3b850f916353f2658ae6f
prerequisite-patch-id: f6c4bf78d30a332948d38e5c937f031496cd3b5a
--
2.25.1



2024-04-08 20:54:46

by Tanmay Shah

[permalink] [raw]
Subject: [PATCH v14 2/4] dt-bindings: remoteproc: add Tightly Coupled Memory (TCM) bindings

From: Radhey Shyam Pandey <[email protected]>

Introduce bindings for TCM memory address space on AMD-xilinx Zynq
UltraScale+ platform. It will help in defining TCM in device-tree
and make it's access platform agnostic and data-driven.

Tightly-coupled memories(TCMs) are low-latency memory that provides
predictable instruction execution and predictable data load/store
timing. Each Cortex-R5F processor contains two 64-bit wide 64 KB memory
banks on the ATCM and BTCM ports, for a total of 128 KB of memory.

The TCM resources(reg, reg-names and power-domain) are documented for
each TCM in the R5 node. The reg and reg-names are made as required
properties as we don't want to hardcode TCM addresses for future
platforms and for zu+ legacy implementation will ensure that the
old dts w/o reg/reg-names works and stable ABI is maintained.

It also extends the examples for TCM split and lockstep modes.

Signed-off-by: Radhey Shyam Pandey <[email protected]>
Signed-off-by: Tanmay Shah <[email protected]>

---

Changes in v14:
- Remove previous RB tag
- Add xlnx,tcm-mode property
- Add Versal platform support
- Add Versal-NET platform support

.../remoteproc/xlnx,zynqmp-r5fss.yaml | 279 ++++++++++++++++--
1 file changed, 257 insertions(+), 22 deletions(-)

diff --git a/Documentation/devicetree/bindings/remoteproc/xlnx,zynqmp-r5fss.yaml b/Documentation/devicetree/bindings/remoteproc/xlnx,zynqmp-r5fss.yaml
index 78aac69f1060..6f13da11f593 100644
--- a/Documentation/devicetree/bindings/remoteproc/xlnx,zynqmp-r5fss.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/xlnx,zynqmp-r5fss.yaml
@@ -18,11 +18,26 @@ description: |

properties:
compatible:
- const: xlnx,zynqmp-r5fss
+ enum:
+ - xlnx,zynqmp-r5fss
+ - xlnx,versal-r5fss
+ - xlnx,versal-net-r52fss
+
+ "#address-cells":
+ const: 2
+
+ "#size-cells":
+ const: 2
+
+ ranges:
+ description: |
+ Standard ranges definition providing address translations for
+ local R5F TCM address spaces to bus addresses.

xlnx,cluster-mode:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2]
+ default: 1
description: |
The RPU MPCore can operate in split mode (Dual-processor performance), Safety
lock-step mode(Both RPU cores execute the same code in lock-step,
@@ -36,8 +51,16 @@ properties:
1: lockstep mode (default)
2: single cpu mode

+ xlnx,tcm-mode:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+ description: |
+ Configure RPU TCM
+ 0: split mode
+ 1: lockstep mode
+
patternProperties:
- "^r5f-[a-f0-9]+$":
+ "^r(.*)@[0-9a-f]+$":
type: object
description: |
The RPU is located in the Low Power Domain of the Processor Subsystem.
@@ -52,10 +75,22 @@ patternProperties:

properties:
compatible:
- const: xlnx,zynqmp-r5f
+ enum:
+ - xlnx,zynqmp-r5f
+ - xlnx,versal-r5f
+ - xlnx,versal-net-r52f
+
+ reg:
+ minItems: 1
+ maxItems: 4
+
+ reg-names:
+ minItems: 1
+ maxItems: 4

power-domains:
- maxItems: 1
+ minItems: 2
+ maxItems: 5

mboxes:
minItems: 1
@@ -101,35 +136,235 @@ patternProperties:

required:
- compatible
+ - reg
+ - reg-names
- power-domains

- unevaluatedProperties: false
-
required:
- compatible
+ - "#address-cells"
+ - "#size-cells"
+ - ranges
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - xlnx,versal-net-r52fss
+ then:
+ properties:
+ xlnx,tcm-mode: false
+
+ patternProperties:
+ "^r52f@[0-9a-f]+$":
+ type: object
+
+ properties:
+ reg:
+ minItems: 1
+ items:
+ - description: ATCM internal memory
+ - description: BTCM internal memory
+ - description: CTCM internal memory
+
+ reg-names:
+ minItems: 1
+ items:
+ - const: atcm0
+ - const: btcm0
+ - const: ctcm0
+
+ power-domains:
+ minItems: 2
+ items:
+ - description: RPU core power domain
+ - description: ATCM power domain
+ - description: BTCM power domain
+ - description: CTCM power domain
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - xlnx,zynqmp-r5fss
+ - xlnx,versal-r5fss
+ then:
+ if:
+ properties:
+ xlnx,cluster-mode:
+ enum: [1, 2]
+ then:
+ properties:
+ xlnx,tcm-mode:
+ enum: [1]
+
+ patternProperties:
+ "^r5f@[0-9a-f]+$":
+ type: object
+
+ properties:
+ reg:
+ minItems: 1
+ items:
+ - description: ATCM internal memory
+ - description: BTCM internal memory
+ - description: extra ATCM memory in lockstep mode
+ - description: extra BTCM memory in lockstep mode
+
+ reg-names:
+ minItems: 1
+ items:
+ - const: atcm0
+ - const: btcm0
+ - const: atcm1
+ - const: btcm1
+
+ power-domains:
+ minItems: 2
+ items:
+ - description: RPU core power domain
+ - description: ATCM power domain
+ - description: BTCM power domain
+ - description: second ATCM power domain
+ - description: second BTCM power domain
+
+ required:
+ - xlnx,tcm-mode
+
+ else:
+ properties:
+ xlnx,tcm-mode:
+ enum: [0]
+
+ patternProperties:
+ "^r5f@[0-9a-f]+$":
+ type: object
+
+ properties:
+ reg:
+ minItems: 1
+ items:
+ - description: ATCM internal memory
+ - description: BTCM internal memory
+
+ reg-names:
+ minItems: 1
+ items:
+ - const: atcm0
+ - const: btcm0
+
+ power-domains:
+ minItems: 2
+ items:
+ - description: RPU core power domain
+ - description: ATCM power domain
+ - description: BTCM power domain
+
+ required:
+ - xlnx,tcm-mode

additionalProperties: false

examples:
- |
- remoteproc {
- compatible = "xlnx,zynqmp-r5fss";
- xlnx,cluster-mode = <1>;
-
- r5f-0 {
- compatible = "xlnx,zynqmp-r5f";
- power-domains = <&zynqmp_firmware 0x7>;
- memory-region = <&rproc_0_fw_image>, <&rpu0vdev0buffer>, <&rpu0vdev0vring0>, <&rpu0vdev0vring1>;
- mboxes = <&ipi_mailbox_rpu0 0>, <&ipi_mailbox_rpu0 1>;
- mbox-names = "tx", "rx";
+ #include <dt-bindings/power/xlnx-zynqmp-power.h>
+
+ // Split mode configuration
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ remoteproc@ffe00000 {
+ compatible = "xlnx,zynqmp-r5fss";
+ xlnx,cluster-mode = <0>;
+ xlnx,tcm-mode = <0>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x0 0x0 0xffe00000 0x0 0x10000>,
+ <0x0 0x20000 0x0 0xffe20000 0x0 0x10000>,
+ <0x1 0x0 0x0 0xffe90000 0x0 0x10000>,
+ <0x1 0x20000 0x0 0xffeb0000 0x0 0x10000>;
+
+ r5f@0 {
+ compatible = "xlnx,zynqmp-r5f";
+ reg = <0x0 0x0 0x0 0x10000>, <0x0 0x20000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0";
+ power-domains = <&zynqmp_firmware PD_RPU_0>,
+ <&zynqmp_firmware PD_R5_0_ATCM>,
+ <&zynqmp_firmware PD_R5_0_BTCM>;
+ memory-region = <&rproc_0_fw_image>, <&rpu0vdev0buffer>,
+ <&rpu0vdev0vring0>, <&rpu0vdev0vring1>;
+ mboxes = <&ipi_mailbox_rpu0 0>, <&ipi_mailbox_rpu0 1>;
+ mbox-names = "tx", "rx";
+ };
+
+ r5f@1 {
+ compatible = "xlnx,zynqmp-r5f";
+ reg = <0x1 0x0 0x0 0x10000>, <0x1 0x20000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0";
+ power-domains = <&zynqmp_firmware PD_RPU_1>,
+ <&zynqmp_firmware PD_R5_1_ATCM>,
+ <&zynqmp_firmware PD_R5_1_BTCM>;
+ memory-region = <&rproc_1_fw_image>, <&rpu1vdev0buffer>,
+ <&rpu1vdev0vring0>, <&rpu1vdev0vring1>;
+ mboxes = <&ipi_mailbox_rpu1 0>, <&ipi_mailbox_rpu1 1>;
+ mbox-names = "tx", "rx";
+ };
};
+ };
+
+ - |
+ //Lockstep configuration
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ remoteproc@ffe00000 {
+ compatible = "xlnx,zynqmp-r5fss";
+ xlnx,cluster-mode = <1>;
+ xlnx,tcm-mode = <1>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x0 0x0 0xffe00000 0x0 0x10000>,
+ <0x0 0x20000 0x0 0xffe20000 0x0 0x10000>,
+ <0x0 0x10000 0x0 0xffe10000 0x0 0x10000>,
+ <0x0 0x30000 0x0 0xffe30000 0x0 0x10000>;
+
+ r5f@0 {
+ compatible = "xlnx,zynqmp-r5f";
+ reg = <0x0 0x0 0x0 0x10000>,
+ <0x0 0x20000 0x0 0x10000>,
+ <0x0 0x10000 0x0 0x10000>,
+ <0x0 0x30000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0", "atcm1", "btcm1";
+ power-domains = <&zynqmp_firmware PD_RPU_0>,
+ <&zynqmp_firmware PD_R5_0_ATCM>,
+ <&zynqmp_firmware PD_R5_0_BTCM>,
+ <&zynqmp_firmware PD_R5_1_ATCM>,
+ <&zynqmp_firmware PD_R5_1_BTCM>;
+ memory-region = <&rproc_0_fw_image>, <&rpu0vdev0buffer>,
+ <&rpu0vdev0vring0>, <&rpu0vdev0vring1>;
+ mboxes = <&ipi_mailbox_rpu0 0>, <&ipi_mailbox_rpu0 1>;
+ mbox-names = "tx", "rx";
+ };

- r5f-1 {
- compatible = "xlnx,zynqmp-r5f";
- power-domains = <&zynqmp_firmware 0x8>;
- memory-region = <&rproc_1_fw_image>, <&rpu1vdev0buffer>, <&rpu1vdev0vring0>, <&rpu1vdev0vring1>;
- mboxes = <&ipi_mailbox_rpu1 0>, <&ipi_mailbox_rpu1 1>;
- mbox-names = "tx", "rx";
+ r5f@1 {
+ compatible = "xlnx,zynqmp-r5f";
+ reg = <0x1 0x0 0x0 0x10000>, <0x1 0x20000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0";
+ power-domains = <&zynqmp_firmware PD_RPU_1>,
+ <&zynqmp_firmware PD_R5_1_ATCM>,
+ <&zynqmp_firmware PD_R5_1_BTCM>;
+ memory-region = <&rproc_1_fw_image>, <&rpu1vdev0buffer>,
+ <&rpu1vdev0vring0>, <&rpu1vdev0vring1>;
+ mboxes = <&ipi_mailbox_rpu1 0>, <&ipi_mailbox_rpu1 1>;
+ mbox-names = "tx", "rx";
+ };
};
};
...
--
2.25.1


2024-04-08 20:55:00

by Tanmay Shah

[permalink] [raw]
Subject: [PATCH v14 3/4] dts: zynqmp: add properties for TCM in remoteproc

Add properties as per new bindings in zynqmp remoteproc node
to represent TCM address and size.

This patch also adds alternative remoteproc node to represent
remoteproc cluster in split mode. By default lockstep mode is
enabled and users should disable it before using split mode
dts. Both device-tree nodes can't be used simultaneously one
of them must be disabled. For zcu102-1.0 and zcu102-1.1 board
remoteproc split mode dts node is enabled and lockstep mode
dts is disabled.

Signed-off-by: Tanmay Shah <[email protected]>
---

Changes in v14:
- Add xlnx,tcm-mode property in remoteproc node

.../boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts | 8 +++
arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 67 +++++++++++++++++--
2 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts
index c8f71a1aec89..495ca94b45db 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts
@@ -14,6 +14,14 @@ / {
compatible = "xlnx,zynqmp-zcu102-rev1.0", "xlnx,zynqmp-zcu102", "xlnx,zynqmp";
};

+&rproc_split {
+ status = "okay";
+};
+
+&rproc_lockstep {
+ status = "disabled";
+};
+
&eeprom {
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index 25d20d803230..ef31b0fc73d1 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -260,19 +260,76 @@ fpga_full: fpga-full {
ranges;
};

- remoteproc {
+ rproc_lockstep: remoteproc@ffe00000 {
compatible = "xlnx,zynqmp-r5fss";
xlnx,cluster-mode = <1>;
+ xlnx,tcm-mode = <1>;

- r5f-0 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ ranges = <0x0 0x0 0x0 0xffe00000 0x0 0x10000>,
+ <0x0 0x20000 0x0 0xffe20000 0x0 0x10000>,
+ <0x0 0x10000 0x0 0xffe10000 0x0 0x10000>,
+ <0x0 0x30000 0x0 0xffe30000 0x0 0x10000>;
+
+ r5f@0 {
+ compatible = "xlnx,zynqmp-r5f";
+ reg = <0x0 0x0 0x0 0x10000>,
+ <0x0 0x20000 0x0 0x10000>,
+ <0x0 0x10000 0x0 0x10000>,
+ <0x0 0x30000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0", "atcm1", "btcm1";
+ power-domains = <&zynqmp_firmware PD_RPU_0>,
+ <&zynqmp_firmware PD_R5_0_ATCM>,
+ <&zynqmp_firmware PD_R5_0_BTCM>,
+ <&zynqmp_firmware PD_R5_1_ATCM>,
+ <&zynqmp_firmware PD_R5_1_BTCM>;
+ memory-region = <&rproc_0_fw_image>;
+ };
+
+ r5f@1 {
+ compatible = "xlnx,zynqmp-r5f";
+ reg = <0x1 0x0 0x0 0x10000>, <0x1 0x20000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0";
+ power-domains = <&zynqmp_firmware PD_RPU_1>,
+ <&zynqmp_firmware PD_R5_1_ATCM>,
+ <&zynqmp_firmware PD_R5_1_BTCM>;
+ memory-region = <&rproc_1_fw_image>;
+ };
+ };
+
+ rproc_split: remoteproc-split@ffe00000 {
+ status = "disabled";
+ compatible = "xlnx,zynqmp-r5fss";
+ xlnx,cluster-mode = <0>;
+ xlnx,tcm-mode = <0>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ ranges = <0x0 0x0 0x0 0xffe00000 0x0 0x10000>,
+ <0x0 0x20000 0x0 0xffe20000 0x0 0x10000>,
+ <0x1 0x0 0x0 0xffe90000 0x0 0x10000>,
+ <0x1 0x20000 0x0 0xffeb0000 0x0 0x10000>;
+
+ r5f@0 {
compatible = "xlnx,zynqmp-r5f";
- power-domains = <&zynqmp_firmware PD_RPU_0>;
+ reg = <0x0 0x0 0x0 0x10000>, <0x0 0x20000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0";
+ power-domains = <&zynqmp_firmware PD_RPU_0>,
+ <&zynqmp_firmware PD_R5_0_ATCM>,
+ <&zynqmp_firmware PD_R5_0_BTCM>;
memory-region = <&rproc_0_fw_image>;
};

- r5f-1 {
+ r5f@1 {
compatible = "xlnx,zynqmp-r5f";
- power-domains = <&zynqmp_firmware PD_RPU_1>;
+ reg = <0x1 0x0 0x0 0x10000>, <0x1 0x20000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0";
+ power-domains = <&zynqmp_firmware PD_RPU_1>,
+ <&zynqmp_firmware PD_R5_1_ATCM>,
+ <&zynqmp_firmware PD_R5_1_BTCM>;
memory-region = <&rproc_1_fw_image>;
};
};
--
2.25.1


2024-04-08 20:55:08

by Tanmay Shah

[permalink] [raw]
Subject: [PATCH v14 4/4] remoteproc: zynqmp: parse TCM from device tree

ZynqMP TCM information was fixed in driver. Now ZynqMP TCM information
is available in device-tree. Parse TCM information in driver
as per new bindings.

Signed-off-by: Tanmay Shah <[email protected]>
---

Changes in v14:
- Add Versal platform support
- Add Versal-NET platform support
- Maintain backward compatibility for ZynqMP platform and use hardcode
TCM addresses
- Configure TCM based on xlnx,tcm-mode property for Versal
- Avoid TCM configuration if that property isn't available in DT

drivers/remoteproc/xlnx_r5_remoteproc.c | 173 ++++++++++++++++++------
1 file changed, 132 insertions(+), 41 deletions(-)

diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c
index 0f942440b4e2..504492f930ac 100644
--- a/drivers/remoteproc/xlnx_r5_remoteproc.c
+++ b/drivers/remoteproc/xlnx_r5_remoteproc.c
@@ -74,8 +74,8 @@ struct mbox_info {
};

/*
- * Hardcoded TCM bank values. This will be removed once TCM bindings are
- * accepted for system-dt specifications and upstreamed in linux kernel
+ * Hardcoded TCM bank values. This will stay in driver to maintain backward
+ * compatibility with device-tree that does not have TCM information.
*/
static const struct mem_bank_data zynqmp_tcm_banks_split[] = {
{0xffe00000UL, 0x0, 0x10000UL, PD_R5_0_ATCM, "atcm0"}, /* TCM 64KB each */
@@ -300,36 +300,6 @@ static void zynqmp_r5_rproc_kick(struct rproc *rproc, int vqid)
dev_warn(dev, "failed to send message\n");
}

-/*
- * zynqmp_r5_set_mode()
- *
- * set RPU cluster and TCM operation mode
- *
- * @r5_core: pointer to zynqmp_r5_core type object
- * @fw_reg_val: value expected by firmware to configure RPU cluster mode
- * @tcm_mode: value expected by fw to configure TCM mode (lockstep or split)
- *
- * Return: 0 for success and < 0 for failure
- */
-static int zynqmp_r5_set_mode(struct zynqmp_r5_core *r5_core,
- enum rpu_oper_mode fw_reg_val,
- enum rpu_tcm_comb tcm_mode)
-{
- int ret;
-
- ret = zynqmp_pm_set_rpu_mode(r5_core->pm_domain_id, fw_reg_val);
- if (ret < 0) {
- dev_err(r5_core->dev, "failed to set RPU mode\n");
- return ret;
- }
-
- ret = zynqmp_pm_set_tcm_config(r5_core->pm_domain_id, tcm_mode);
- if (ret < 0)
- dev_err(r5_core->dev, "failed to configure TCM\n");
-
- return ret;
-}
-
/*
* zynqmp_r5_rproc_start()
* @rproc: single R5 core's corresponding rproc instance
@@ -761,6 +731,103 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
return ERR_PTR(ret);
}

+static int zynqmp_r5_get_tcm_node_from_dt(struct zynqmp_r5_cluster *cluster)
+{
+ int i, j, tcm_bank_count, ret, tcm_pd_idx, pd_count;
+ struct of_phandle_args out_args;
+ struct zynqmp_r5_core *r5_core;
+ struct platform_device *cpdev;
+ struct mem_bank_data *tcm;
+ struct device_node *np;
+ struct resource *res;
+ u64 abs_addr, size;
+ struct device *dev;
+
+ for (i = 0; i < cluster->core_count; i++) {
+ r5_core = cluster->r5_cores[i];
+ dev = r5_core->dev;
+ np = r5_core->np;
+
+ pd_count = of_count_phandle_with_args(np, "power-domains",
+ "#power-domain-cells");
+
+ if (pd_count <= 0) {
+ dev_err(dev, "invalid power-domains property, %d\n", pd_count);
+ return -EINVAL;
+ }
+
+ /* First entry in power-domains list is for r5 core, rest for TCM. */
+ tcm_bank_count = pd_count - 1;
+
+ if (tcm_bank_count <= 0) {
+ dev_err(dev, "invalid TCM count %d\n", tcm_bank_count);
+ return -EINVAL;
+ }
+
+ r5_core->tcm_banks = devm_kcalloc(dev, tcm_bank_count,
+ sizeof(struct mem_bank_data *),
+ GFP_KERNEL);
+ if (!r5_core->tcm_banks)
+ return -ENOMEM;
+
+ r5_core->tcm_bank_count = tcm_bank_count;
+ for (j = 0, tcm_pd_idx = 1; j < tcm_bank_count; j++, tcm_pd_idx++) {
+ tcm = devm_kzalloc(dev, sizeof(struct mem_bank_data),
+ GFP_KERNEL);
+ if (!tcm)
+ return -ENOMEM;
+
+ r5_core->tcm_banks[j] = tcm;
+
+ /* Get power-domains id of TCM. */
+ ret = of_parse_phandle_with_args(np, "power-domains",
+ "#power-domain-cells",
+ tcm_pd_idx, &out_args);
+ if (ret) {
+ dev_err(r5_core->dev,
+ "failed to get tcm %d pm domain, ret %d\n",
+ tcm_pd_idx, ret);
+ return ret;
+ }
+ tcm->pm_domain_id = out_args.args[0];
+ of_node_put(out_args.np);
+
+ /* Get TCM address without translation. */
+ ret = of_property_read_reg(np, j, &abs_addr, &size);
+ if (ret) {
+ dev_err(dev, "failed to get reg property\n");
+ return ret;
+ }
+
+ /*
+ * Remote processor can address only 32 bits
+ * so convert 64-bits into 32-bits. This will discard
+ * any unwanted upper 32-bits.
+ */
+ tcm->da = (u32)abs_addr;
+ tcm->size = (u32)size;
+
+ cpdev = to_platform_device(dev);
+ res = platform_get_resource(cpdev, IORESOURCE_MEM, j);
+ if (!res) {
+ dev_err(dev, "failed to get tcm resource\n");
+ return -EINVAL;
+ }
+
+ tcm->addr = (u32)res->start;
+ tcm->bank_name = (char *)res->name;
+ res = devm_request_mem_region(dev, tcm->addr, tcm->size,
+ tcm->bank_name);
+ if (!res) {
+ dev_err(dev, "failed to request tcm resource\n");
+ return -EINVAL;
+ }
+ }
+ }
+
+ return 0;
+}
+
/**
* zynqmp_r5_get_tcm_node()
* Ideally this function should parse tcm node and store information
@@ -839,9 +906,16 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
struct zynqmp_r5_core *r5_core;
int ret, i;

- ret = zynqmp_r5_get_tcm_node(cluster);
- if (ret < 0) {
- dev_err(dev, "can't get tcm node, err %d\n", ret);
+ r5_core = cluster->r5_cores[0];
+
+ /* Maintain backward compatibility for zynqmp by using hardcode TCM address. */
+ if (device_is_compatible(dev, "xlnx,zynqmp-r5fss"))
+ ret = zynqmp_r5_get_tcm_node(cluster);
+ else
+ ret = zynqmp_r5_get_tcm_node_from_dt(cluster);
+
+ if (ret) {
+ dev_err(dev, "can't get tcm, err %d\n", ret);
return ret;
}

@@ -856,12 +930,18 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
return ret;
}

- ret = zynqmp_r5_set_mode(r5_core, fw_reg_val, tcm_mode);
- if (ret) {
- dev_err(dev, "failed to set r5 cluster mode %d, err %d\n",
- cluster->mode, ret);
+ ret = zynqmp_pm_set_rpu_mode(r5_core->pm_domain_id, fw_reg_val);
+ if (ret < 0) {
+ dev_err(r5_core->dev, "failed to set RPU mode\n");
return ret;
}
+
+ if (device_is_compatible(dev, "xlnx,zynqmp-r5fss") ||
+ of_find_property(dev_of_node(dev), "xlnx,tcm-mode", NULL)) {
+ ret = zynqmp_pm_set_tcm_config(r5_core->pm_domain_id, tcm_mode);
+ if (ret < 0)
+ dev_err(r5_core->dev, "failed to configure TCM\n");
+ }
}

return 0;
@@ -906,16 +986,25 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
* fail driver probe if either of that is not set in dts.
*/
if (cluster_mode == LOCKSTEP_MODE) {
- tcm_mode = PM_RPU_TCM_COMB;
fw_reg_val = PM_RPU_MODE_LOCKSTEP;
} else if (cluster_mode == SPLIT_MODE) {
- tcm_mode = PM_RPU_TCM_SPLIT;
fw_reg_val = PM_RPU_MODE_SPLIT;
} else {
dev_err(dev, "driver does not support cluster mode %d\n", cluster_mode);
return -EINVAL;
}

+ if (device_is_compatible(dev, "xlnx,zynqmp-r5fss")) {
+ if (cluster_mode == LOCKSTEP_MODE)
+ tcm_mode = PM_RPU_TCM_COMB;
+ else
+ tcm_mode = PM_RPU_TCM_SPLIT;
+ } else if (of_find_property(dev_node, "xlnx,tcm-mode", NULL)) {
+ ret = of_property_read_u32(dev_node, "xlnx,tcm-mode", (u32 *)&tcm_mode);
+ if (ret)
+ return ret;
+ }
+
/*
* Number of cores is decided by number of child nodes of
* r5f subsystem node in dts. If Split mode is used in dts
@@ -1100,6 +1189,8 @@ static int zynqmp_r5_remoteproc_probe(struct platform_device *pdev)
/* Match table for OF platform binding */
static const struct of_device_id zynqmp_r5_remoteproc_match[] = {
{ .compatible = "xlnx,zynqmp-r5fss", },
+ { .compatible = "xlnx,versal-r5fss", },
+ { .compatible = "xlnx,versal-net-r52fss", },
{ /* end of list */ },
};
MODULE_DEVICE_TABLE(of, zynqmp_r5_remoteproc_match);
--
2.25.1


2024-04-09 07:30:13

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH v14 2/4] dt-bindings: remoteproc: add Tightly Coupled Memory (TCM) bindings

On 08/04/2024 22:53, Tanmay Shah wrote:
> From: Radhey Shyam Pandey <[email protected]>
>
> Introduce bindings for TCM memory address space on AMD-xilinx Zynq
> UltraScale+ platform. It will help in defining TCM in device-tree
> and make it's access platform agnostic and data-driven.
>
> Tightly-coupled memories(TCMs) are low-latency memory that provides
> predictable instruction execution and predictable data load/store
> timing. Each Cortex-R5F processor contains two 64-bit wide 64 KB memory
> banks on the ATCM and BTCM ports, for a total of 128 KB of memory.
>
> The TCM resources(reg, reg-names and power-domain) are documented for
> each TCM in the R5 node. The reg and reg-names are made as required
> properties as we don't want to hardcode TCM addresses for future
> platforms and for zu+ legacy implementation will ensure that the
> old dts w/o reg/reg-names works and stable ABI is maintained.
>
> It also extends the examples for TCM split and lockstep modes.
>
> Signed-off-by: Radhey Shyam Pandey <[email protected]>
> Signed-off-by: Tanmay Shah <[email protected]>

Reviewed-by: Krzysztof Kozlowski <[email protected]>

Best regards,
Krzysztof


2024-04-10 16:59:55

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v14 4/4] remoteproc: zynqmp: parse TCM from device tree

On Mon, Apr 08, 2024 at 01:53:14PM -0700, Tanmay Shah wrote:
> ZynqMP TCM information was fixed in driver. Now ZynqMP TCM information
> is available in device-tree. Parse TCM information in driver
> as per new bindings.
>
> Signed-off-by: Tanmay Shah <[email protected]>
> ---
>
> Changes in v14:
> - Add Versal platform support
> - Add Versal-NET platform support
> - Maintain backward compatibility for ZynqMP platform and use hardcode
> TCM addresses
> - Configure TCM based on xlnx,tcm-mode property for Versal
> - Avoid TCM configuration if that property isn't available in DT
>
> drivers/remoteproc/xlnx_r5_remoteproc.c | 173 ++++++++++++++++++------
> 1 file changed, 132 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c
> index 0f942440b4e2..504492f930ac 100644
> --- a/drivers/remoteproc/xlnx_r5_remoteproc.c
> +++ b/drivers/remoteproc/xlnx_r5_remoteproc.c
> @@ -74,8 +74,8 @@ struct mbox_info {
> };
>
> /*
> - * Hardcoded TCM bank values. This will be removed once TCM bindings are
> - * accepted for system-dt specifications and upstreamed in linux kernel
> + * Hardcoded TCM bank values. This will stay in driver to maintain backward
> + * compatibility with device-tree that does not have TCM information.
> */
> static const struct mem_bank_data zynqmp_tcm_banks_split[] = {
> {0xffe00000UL, 0x0, 0x10000UL, PD_R5_0_ATCM, "atcm0"}, /* TCM 64KB each */
> @@ -300,36 +300,6 @@ static void zynqmp_r5_rproc_kick(struct rproc *rproc, int vqid)
> dev_warn(dev, "failed to send message\n");
> }
>
> -/*
> - * zynqmp_r5_set_mode()
> - *
> - * set RPU cluster and TCM operation mode
> - *
> - * @r5_core: pointer to zynqmp_r5_core type object
> - * @fw_reg_val: value expected by firmware to configure RPU cluster mode
> - * @tcm_mode: value expected by fw to configure TCM mode (lockstep or split)
> - *
> - * Return: 0 for success and < 0 for failure
> - */
> -static int zynqmp_r5_set_mode(struct zynqmp_r5_core *r5_core,
> - enum rpu_oper_mode fw_reg_val,
> - enum rpu_tcm_comb tcm_mode)
> -{
> - int ret;
> -
> - ret = zynqmp_pm_set_rpu_mode(r5_core->pm_domain_id, fw_reg_val);
> - if (ret < 0) {
> - dev_err(r5_core->dev, "failed to set RPU mode\n");
> - return ret;
> - }
> -
> - ret = zynqmp_pm_set_tcm_config(r5_core->pm_domain_id, tcm_mode);
> - if (ret < 0)
> - dev_err(r5_core->dev, "failed to configure TCM\n");
> -
> - return ret;
> -}
> -
> /*
> * zynqmp_r5_rproc_start()
> * @rproc: single R5 core's corresponding rproc instance
> @@ -761,6 +731,103 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
> return ERR_PTR(ret);
> }
>
> +static int zynqmp_r5_get_tcm_node_from_dt(struct zynqmp_r5_cluster *cluster)
> +{
> + int i, j, tcm_bank_count, ret, tcm_pd_idx, pd_count;
> + struct of_phandle_args out_args;
> + struct zynqmp_r5_core *r5_core;
> + struct platform_device *cpdev;
> + struct mem_bank_data *tcm;
> + struct device_node *np;
> + struct resource *res;
> + u64 abs_addr, size;
> + struct device *dev;
> +
> + for (i = 0; i < cluster->core_count; i++) {
> + r5_core = cluster->r5_cores[i];
> + dev = r5_core->dev;
> + np = r5_core->np;
> +
> + pd_count = of_count_phandle_with_args(np, "power-domains",
> + "#power-domain-cells");
> +
> + if (pd_count <= 0) {
> + dev_err(dev, "invalid power-domains property, %d\n", pd_count);
> + return -EINVAL;
> + }
> +
> + /* First entry in power-domains list is for r5 core, rest for TCM. */
> + tcm_bank_count = pd_count - 1;
> +
> + if (tcm_bank_count <= 0) {
> + dev_err(dev, "invalid TCM count %d\n", tcm_bank_count);
> + return -EINVAL;
> + }
> +
> + r5_core->tcm_banks = devm_kcalloc(dev, tcm_bank_count,
> + sizeof(struct mem_bank_data *),
> + GFP_KERNEL);
> + if (!r5_core->tcm_banks)
> + return -ENOMEM;
> +
> + r5_core->tcm_bank_count = tcm_bank_count;
> + for (j = 0, tcm_pd_idx = 1; j < tcm_bank_count; j++, tcm_pd_idx++) {
> + tcm = devm_kzalloc(dev, sizeof(struct mem_bank_data),
> + GFP_KERNEL);
> + if (!tcm)
> + return -ENOMEM;
> +
> + r5_core->tcm_banks[j] = tcm;
> +
> + /* Get power-domains id of TCM. */
> + ret = of_parse_phandle_with_args(np, "power-domains",
> + "#power-domain-cells",
> + tcm_pd_idx, &out_args);
> + if (ret) {
> + dev_err(r5_core->dev,
> + "failed to get tcm %d pm domain, ret %d\n",
> + tcm_pd_idx, ret);
> + return ret;
> + }
> + tcm->pm_domain_id = out_args.args[0];
> + of_node_put(out_args.np);
> +
> + /* Get TCM address without translation. */
> + ret = of_property_read_reg(np, j, &abs_addr, &size);
> + if (ret) {
> + dev_err(dev, "failed to get reg property\n");
> + return ret;
> + }
> +
> + /*
> + * Remote processor can address only 32 bits
> + * so convert 64-bits into 32-bits. This will discard
> + * any unwanted upper 32-bits.
> + */
> + tcm->da = (u32)abs_addr;
> + tcm->size = (u32)size;
> +
> + cpdev = to_platform_device(dev);
> + res = platform_get_resource(cpdev, IORESOURCE_MEM, j);
> + if (!res) {
> + dev_err(dev, "failed to get tcm resource\n");
> + return -EINVAL;
> + }
> +
> + tcm->addr = (u32)res->start;
> + tcm->bank_name = (char *)res->name;
> + res = devm_request_mem_region(dev, tcm->addr, tcm->size,
> + tcm->bank_name);
> + if (!res) {
> + dev_err(dev, "failed to request tcm resource\n");
> + return -EINVAL;
> + }
> + }
> + }
> +
> + return 0;
> +}
> +
> /**
> * zynqmp_r5_get_tcm_node()
> * Ideally this function should parse tcm node and store information
> @@ -839,9 +906,16 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
> struct zynqmp_r5_core *r5_core;
> int ret, i;
>
> - ret = zynqmp_r5_get_tcm_node(cluster);
> - if (ret < 0) {
> - dev_err(dev, "can't get tcm node, err %d\n", ret);
> + r5_core = cluster->r5_cores[0];
> +
> + /* Maintain backward compatibility for zynqmp by using hardcode TCM address. */
> + if (device_is_compatible(dev, "xlnx,zynqmp-r5fss"))

The previous patch moved the definition of the R5FSS to the new bindings but
this is forcing to use the old bindings - did I something?

> + ret = zynqmp_r5_get_tcm_node(cluster);
> + else
> + ret = zynqmp_r5_get_tcm_node_from_dt(cluster);
> +
> + if (ret) {
> + dev_err(dev, "can't get tcm, err %d\n", ret);
> return ret;
> }
>
> @@ -856,12 +930,18 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
> return ret;
> }
>
> - ret = zynqmp_r5_set_mode(r5_core, fw_reg_val, tcm_mode);
> - if (ret) {
> - dev_err(dev, "failed to set r5 cluster mode %d, err %d\n",
> - cluster->mode, ret);
> + ret = zynqmp_pm_set_rpu_mode(r5_core->pm_domain_id, fw_reg_val);
> + if (ret < 0) {
> + dev_err(r5_core->dev, "failed to set RPU mode\n");
> return ret;
> }
> +
> + if (device_is_compatible(dev, "xlnx,zynqmp-r5fss") ||
> + of_find_property(dev_of_node(dev), "xlnx,tcm-mode", NULL)) {
> + ret = zynqmp_pm_set_tcm_config(r5_core->pm_domain_id, tcm_mode);
> + if (ret < 0)
> + dev_err(r5_core->dev, "failed to configure TCM\n");
> + }
> }
>
> return 0;
> @@ -906,16 +986,25 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
> * fail driver probe if either of that is not set in dts.
> */
> if (cluster_mode == LOCKSTEP_MODE) {
> - tcm_mode = PM_RPU_TCM_COMB;
> fw_reg_val = PM_RPU_MODE_LOCKSTEP;
> } else if (cluster_mode == SPLIT_MODE) {
> - tcm_mode = PM_RPU_TCM_SPLIT;
> fw_reg_val = PM_RPU_MODE_SPLIT;
> } else {
> dev_err(dev, "driver does not support cluster mode %d\n", cluster_mode);
> return -EINVAL;
> }
>
> + if (device_is_compatible(dev, "xlnx,zynqmp-r5fss")) {
> + if (cluster_mode == LOCKSTEP_MODE)
> + tcm_mode = PM_RPU_TCM_COMB;
> + else
> + tcm_mode = PM_RPU_TCM_SPLIT;
> + } else if (of_find_property(dev_node, "xlnx,tcm-mode", NULL)) {
> + ret = of_property_read_u32(dev_node, "xlnx,tcm-mode", (u32 *)&tcm_mode);
> + if (ret)
> + return ret;
> + }
> +
> /*
> * Number of cores is decided by number of child nodes of
> * r5f subsystem node in dts. If Split mode is used in dts
> @@ -1100,6 +1189,8 @@ static int zynqmp_r5_remoteproc_probe(struct platform_device *pdev)
> /* Match table for OF platform binding */
> static const struct of_device_id zynqmp_r5_remoteproc_match[] = {
> { .compatible = "xlnx,zynqmp-r5fss", },
> + { .compatible = "xlnx,versal-r5fss", },
> + { .compatible = "xlnx,versal-net-r52fss", },
> { /* end of list */ },
> };
> MODULE_DEVICE_TABLE(of, zynqmp_r5_remoteproc_match);
> --
> 2.25.1
>

2024-04-10 22:38:17

by Tanmay Shah

[permalink] [raw]
Subject: Re: [PATCH v14 4/4] remoteproc: zynqmp: parse TCM from device tree



On 4/10/24 11:59 AM, Mathieu Poirier wrote:
> On Mon, Apr 08, 2024 at 01:53:14PM -0700, Tanmay Shah wrote:
>> ZynqMP TCM information was fixed in driver. Now ZynqMP TCM information
>> is available in device-tree. Parse TCM information in driver
>> as per new bindings.
>>
>> Signed-off-by: Tanmay Shah <[email protected]>
>> ---
>>
>> Changes in v14:
>> - Add Versal platform support
>> - Add Versal-NET platform support
>> - Maintain backward compatibility for ZynqMP platform and use hardcode
>> TCM addresses
>> - Configure TCM based on xlnx,tcm-mode property for Versal
>> - Avoid TCM configuration if that property isn't available in DT
>>
>> drivers/remoteproc/xlnx_r5_remoteproc.c | 173 ++++++++++++++++++------
>> 1 file changed, 132 insertions(+), 41 deletions(-)
>>
>> diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c
>> index 0f942440b4e2..504492f930ac 100644
>> --- a/drivers/remoteproc/xlnx_r5_remoteproc.c
>> +++ b/drivers/remoteproc/xlnx_r5_remoteproc.c
>> @@ -74,8 +74,8 @@ struct mbox_info {
>> };
>>
>> /*
>> - * Hardcoded TCM bank values. This will be removed once TCM bindings are
>> - * accepted for system-dt specifications and upstreamed in linux kernel
>> + * Hardcoded TCM bank values. This will stay in driver to maintain backward
>> + * compatibility with device-tree that does not have TCM information.
>> */
>> static const struct mem_bank_data zynqmp_tcm_banks_split[] = {
>> {0xffe00000UL, 0x0, 0x10000UL, PD_R5_0_ATCM, "atcm0"}, /* TCM 64KB each */
>> @@ -300,36 +300,6 @@ static void zynqmp_r5_rproc_kick(struct rproc *rproc, int vqid)
>> dev_warn(dev, "failed to send message\n");
>> }
>>
>> -/*
>> - * zynqmp_r5_set_mode()
>> - *
>> - * set RPU cluster and TCM operation mode
>> - *
>> - * @r5_core: pointer to zynqmp_r5_core type object
>> - * @fw_reg_val: value expected by firmware to configure RPU cluster mode
>> - * @tcm_mode: value expected by fw to configure TCM mode (lockstep or split)
>> - *
>> - * Return: 0 for success and < 0 for failure
>> - */
>> -static int zynqmp_r5_set_mode(struct zynqmp_r5_core *r5_core,
>> - enum rpu_oper_mode fw_reg_val,
>> - enum rpu_tcm_comb tcm_mode)
>> -{
>> - int ret;
>> -
>> - ret = zynqmp_pm_set_rpu_mode(r5_core->pm_domain_id, fw_reg_val);
>> - if (ret < 0) {
>> - dev_err(r5_core->dev, "failed to set RPU mode\n");
>> - return ret;
>> - }
>> -
>> - ret = zynqmp_pm_set_tcm_config(r5_core->pm_domain_id, tcm_mode);
>> - if (ret < 0)
>> - dev_err(r5_core->dev, "failed to configure TCM\n");
>> -
>> - return ret;
>> -}
>> -
>> /*
>> * zynqmp_r5_rproc_start()
>> * @rproc: single R5 core's corresponding rproc instance
>> @@ -761,6 +731,103 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
>> return ERR_PTR(ret);
>> }
>>
>> +static int zynqmp_r5_get_tcm_node_from_dt(struct zynqmp_r5_cluster *cluster)
>> +{
>> + int i, j, tcm_bank_count, ret, tcm_pd_idx, pd_count;
>> + struct of_phandle_args out_args;
>> + struct zynqmp_r5_core *r5_core;
>> + struct platform_device *cpdev;
>> + struct mem_bank_data *tcm;
>> + struct device_node *np;
>> + struct resource *res;
>> + u64 abs_addr, size;
>> + struct device *dev;
>> +
>> + for (i = 0; i < cluster->core_count; i++) {
>> + r5_core = cluster->r5_cores[i];
>> + dev = r5_core->dev;
>> + np = r5_core->np;
>> +
>> + pd_count = of_count_phandle_with_args(np, "power-domains",
>> + "#power-domain-cells");
>> +
>> + if (pd_count <= 0) {
>> + dev_err(dev, "invalid power-domains property, %d\n", pd_count);
>> + return -EINVAL;
>> + }
>> +
>> + /* First entry in power-domains list is for r5 core, rest for TCM. */
>> + tcm_bank_count = pd_count - 1;
>> +
>> + if (tcm_bank_count <= 0) {
>> + dev_err(dev, "invalid TCM count %d\n", tcm_bank_count);
>> + return -EINVAL;
>> + }
>> +
>> + r5_core->tcm_banks = devm_kcalloc(dev, tcm_bank_count,
>> + sizeof(struct mem_bank_data *),
>> + GFP_KERNEL);
>> + if (!r5_core->tcm_banks)
>> + return -ENOMEM;
>> +
>> + r5_core->tcm_bank_count = tcm_bank_count;
>> + for (j = 0, tcm_pd_idx = 1; j < tcm_bank_count; j++, tcm_pd_idx++) {
>> + tcm = devm_kzalloc(dev, sizeof(struct mem_bank_data),
>> + GFP_KERNEL);
>> + if (!tcm)
>> + return -ENOMEM;
>> +
>> + r5_core->tcm_banks[j] = tcm;
>> +
>> + /* Get power-domains id of TCM. */
>> + ret = of_parse_phandle_with_args(np, "power-domains",
>> + "#power-domain-cells",
>> + tcm_pd_idx, &out_args);
>> + if (ret) {
>> + dev_err(r5_core->dev,
>> + "failed to get tcm %d pm domain, ret %d\n",
>> + tcm_pd_idx, ret);
>> + return ret;
>> + }
>> + tcm->pm_domain_id = out_args.args[0];
>> + of_node_put(out_args.np);
>> +
>> + /* Get TCM address without translation. */
>> + ret = of_property_read_reg(np, j, &abs_addr, &size);
>> + if (ret) {
>> + dev_err(dev, "failed to get reg property\n");
>> + return ret;
>> + }
>> +
>> + /*
>> + * Remote processor can address only 32 bits
>> + * so convert 64-bits into 32-bits. This will discard
>> + * any unwanted upper 32-bits.
>> + */
>> + tcm->da = (u32)abs_addr;
>> + tcm->size = (u32)size;
>> +
>> + cpdev = to_platform_device(dev);
>> + res = platform_get_resource(cpdev, IORESOURCE_MEM, j);
>> + if (!res) {
>> + dev_err(dev, "failed to get tcm resource\n");
>> + return -EINVAL;
>> + }
>> +
>> + tcm->addr = (u32)res->start;
>> + tcm->bank_name = (char *)res->name;
>> + res = devm_request_mem_region(dev, tcm->addr, tcm->size,
>> + tcm->bank_name);
>> + if (!res) {
>> + dev_err(dev, "failed to request tcm resource\n");
>> + return -EINVAL;
>> + }
>> + }
>> + }
>> +
>> + return 0;
>> +}
>> +
>> /**
>> * zynqmp_r5_get_tcm_node()
>> * Ideally this function should parse tcm node and store information
>> @@ -839,9 +906,16 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
>> struct zynqmp_r5_core *r5_core;
>> int ret, i;
>>
>> - ret = zynqmp_r5_get_tcm_node(cluster);
>> - if (ret < 0) {
>> - dev_err(dev, "can't get tcm node, err %d\n", ret);
>> + r5_core = cluster->r5_cores[0];
>> +
>> + /* Maintain backward compatibility for zynqmp by using hardcode TCM address. */
>> + if (device_is_compatible(dev, "xlnx,zynqmp-r5fss"))
>
> The previous patch moved the definition of the R5FSS to the new bindings but
> this is forcing to use the old bindings - did I something?

Hi Mathieu,

We need to maintain backward compatibility for zynqmp device. So, using old bindings
for zynqmp. For new devices (Versal and Versal-NET) new bindings are enforced in driver.
It's not recommended to map two programming sequences to same device. So for
"xlnx,zynqmp-r5fss" device old bindings are used.

Device tree is matching with new bindings. But that's hardware description. I believe,
driver can still choose to use hardcode addresses to maintain backward compatibility.

The end result will be same.

Thanks,
Tanmay

>
>> + ret = zynqmp_r5_get_tcm_node(cluster);
>> + else
>> + ret = zynqmp_r5_get_tcm_node_from_dt(cluster);
>> +
>> + if (ret) {
>> + dev_err(dev, "can't get tcm, err %d\n", ret);
>> return ret;
>> }
>>
>> @@ -856,12 +930,18 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
>> return ret;
>> }
>>
>> - ret = zynqmp_r5_set_mode(r5_core, fw_reg_val, tcm_mode);
>> - if (ret) {
>> - dev_err(dev, "failed to set r5 cluster mode %d, err %d\n",
>> - cluster->mode, ret);
>> + ret = zynqmp_pm_set_rpu_mode(r5_core->pm_domain_id, fw_reg_val);
>> + if (ret < 0) {
>> + dev_err(r5_core->dev, "failed to set RPU mode\n");
>> return ret;
>> }
>> +
>> + if (device_is_compatible(dev, "xlnx,zynqmp-r5fss") ||
>> + of_find_property(dev_of_node(dev), "xlnx,tcm-mode", NULL)) {
>> + ret = zynqmp_pm_set_tcm_config(r5_core->pm_domain_id, tcm_mode);
>> + if (ret < 0)
>> + dev_err(r5_core->dev, "failed to configure TCM\n");
>> + }
>> }
>>
>> return 0;
>> @@ -906,16 +986,25 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
>> * fail driver probe if either of that is not set in dts.
>> */
>> if (cluster_mode == LOCKSTEP_MODE) {
>> - tcm_mode = PM_RPU_TCM_COMB;
>> fw_reg_val = PM_RPU_MODE_LOCKSTEP;
>> } else if (cluster_mode == SPLIT_MODE) {
>> - tcm_mode = PM_RPU_TCM_SPLIT;
>> fw_reg_val = PM_RPU_MODE_SPLIT;
>> } else {
>> dev_err(dev, "driver does not support cluster mode %d\n", cluster_mode);
>> return -EINVAL;
>> }
>>
>> + if (device_is_compatible(dev, "xlnx,zynqmp-r5fss")) {
>> + if (cluster_mode == LOCKSTEP_MODE)
>> + tcm_mode = PM_RPU_TCM_COMB;
>> + else
>> + tcm_mode = PM_RPU_TCM_SPLIT;
>> + } else if (of_find_property(dev_node, "xlnx,tcm-mode", NULL)) {
>> + ret = of_property_read_u32(dev_node, "xlnx,tcm-mode", (u32 *)&tcm_mode);
>> + if (ret)
>> + return ret;
>> + }
>> +
>> /*
>> * Number of cores is decided by number of child nodes of
>> * r5f subsystem node in dts. If Split mode is used in dts
>> @@ -1100,6 +1189,8 @@ static int zynqmp_r5_remoteproc_probe(struct platform_device *pdev)
>> /* Match table for OF platform binding */
>> static const struct of_device_id zynqmp_r5_remoteproc_match[] = {
>> { .compatible = "xlnx,zynqmp-r5fss", },
>> + { .compatible = "xlnx,versal-r5fss", },
>> + { .compatible = "xlnx,versal-net-r52fss", },
>> { /* end of list */ },
>> };
>> MODULE_DEVICE_TABLE(of, zynqmp_r5_remoteproc_match);
>> --
>> 2.25.1
>>


2024-04-11 17:53:33

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v14 4/4] remoteproc: zynqmp: parse TCM from device tree

On Wed, Apr 10, 2024 at 05:36:30PM -0500, Tanmay Shah wrote:
>
>
> On 4/10/24 11:59 AM, Mathieu Poirier wrote:
> > On Mon, Apr 08, 2024 at 01:53:14PM -0700, Tanmay Shah wrote:
> >> ZynqMP TCM information was fixed in driver. Now ZynqMP TCM information
> >> is available in device-tree. Parse TCM information in driver
> >> as per new bindings.
> >>
> >> Signed-off-by: Tanmay Shah <[email protected]>
> >> ---
> >>
> >> Changes in v14:
> >> - Add Versal platform support
> >> - Add Versal-NET platform support
> >> - Maintain backward compatibility for ZynqMP platform and use hardcode
> >> TCM addresses
> >> - Configure TCM based on xlnx,tcm-mode property for Versal
> >> - Avoid TCM configuration if that property isn't available in DT
> >>
> >> drivers/remoteproc/xlnx_r5_remoteproc.c | 173 ++++++++++++++++++------
> >> 1 file changed, 132 insertions(+), 41 deletions(-)
> >>
> >> diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c
> >> index 0f942440b4e2..504492f930ac 100644
> >> --- a/drivers/remoteproc/xlnx_r5_remoteproc.c
> >> +++ b/drivers/remoteproc/xlnx_r5_remoteproc.c
> >> @@ -74,8 +74,8 @@ struct mbox_info {
> >> };
> >>
> >> /*
> >> - * Hardcoded TCM bank values. This will be removed once TCM bindings are
> >> - * accepted for system-dt specifications and upstreamed in linux kernel
> >> + * Hardcoded TCM bank values. This will stay in driver to maintain backward
> >> + * compatibility with device-tree that does not have TCM information.
> >> */
> >> static const struct mem_bank_data zynqmp_tcm_banks_split[] = {
> >> {0xffe00000UL, 0x0, 0x10000UL, PD_R5_0_ATCM, "atcm0"}, /* TCM 64KB each */
> >> @@ -300,36 +300,6 @@ static void zynqmp_r5_rproc_kick(struct rproc *rproc, int vqid)
> >> dev_warn(dev, "failed to send message\n");
> >> }
> >>
> >> -/*
> >> - * zynqmp_r5_set_mode()
> >> - *
> >> - * set RPU cluster and TCM operation mode
> >> - *
> >> - * @r5_core: pointer to zynqmp_r5_core type object
> >> - * @fw_reg_val: value expected by firmware to configure RPU cluster mode
> >> - * @tcm_mode: value expected by fw to configure TCM mode (lockstep or split)
> >> - *
> >> - * Return: 0 for success and < 0 for failure
> >> - */
> >> -static int zynqmp_r5_set_mode(struct zynqmp_r5_core *r5_core,
> >> - enum rpu_oper_mode fw_reg_val,
> >> - enum rpu_tcm_comb tcm_mode)
> >> -{
> >> - int ret;
> >> -
> >> - ret = zynqmp_pm_set_rpu_mode(r5_core->pm_domain_id, fw_reg_val);
> >> - if (ret < 0) {
> >> - dev_err(r5_core->dev, "failed to set RPU mode\n");
> >> - return ret;
> >> - }
> >> -
> >> - ret = zynqmp_pm_set_tcm_config(r5_core->pm_domain_id, tcm_mode);
> >> - if (ret < 0)
> >> - dev_err(r5_core->dev, "failed to configure TCM\n");
> >> -
> >> - return ret;
> >> -}
> >> -
> >> /*
> >> * zynqmp_r5_rproc_start()
> >> * @rproc: single R5 core's corresponding rproc instance
> >> @@ -761,6 +731,103 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
> >> return ERR_PTR(ret);
> >> }
> >>
> >> +static int zynqmp_r5_get_tcm_node_from_dt(struct zynqmp_r5_cluster *cluster)
> >> +{
> >> + int i, j, tcm_bank_count, ret, tcm_pd_idx, pd_count;
> >> + struct of_phandle_args out_args;
> >> + struct zynqmp_r5_core *r5_core;
> >> + struct platform_device *cpdev;
> >> + struct mem_bank_data *tcm;
> >> + struct device_node *np;
> >> + struct resource *res;
> >> + u64 abs_addr, size;
> >> + struct device *dev;
> >> +
> >> + for (i = 0; i < cluster->core_count; i++) {
> >> + r5_core = cluster->r5_cores[i];
> >> + dev = r5_core->dev;
> >> + np = r5_core->np;
> >> +
> >> + pd_count = of_count_phandle_with_args(np, "power-domains",
> >> + "#power-domain-cells");
> >> +
> >> + if (pd_count <= 0) {
> >> + dev_err(dev, "invalid power-domains property, %d\n", pd_count);
> >> + return -EINVAL;
> >> + }
> >> +
> >> + /* First entry in power-domains list is for r5 core, rest for TCM. */
> >> + tcm_bank_count = pd_count - 1;
> >> +
> >> + if (tcm_bank_count <= 0) {
> >> + dev_err(dev, "invalid TCM count %d\n", tcm_bank_count);
> >> + return -EINVAL;
> >> + }
> >> +
> >> + r5_core->tcm_banks = devm_kcalloc(dev, tcm_bank_count,
> >> + sizeof(struct mem_bank_data *),
> >> + GFP_KERNEL);
> >> + if (!r5_core->tcm_banks)
> >> + return -ENOMEM;
> >> +
> >> + r5_core->tcm_bank_count = tcm_bank_count;
> >> + for (j = 0, tcm_pd_idx = 1; j < tcm_bank_count; j++, tcm_pd_idx++) {
> >> + tcm = devm_kzalloc(dev, sizeof(struct mem_bank_data),
> >> + GFP_KERNEL);
> >> + if (!tcm)
> >> + return -ENOMEM;
> >> +
> >> + r5_core->tcm_banks[j] = tcm;
> >> +
> >> + /* Get power-domains id of TCM. */
> >> + ret = of_parse_phandle_with_args(np, "power-domains",
> >> + "#power-domain-cells",
> >> + tcm_pd_idx, &out_args);
> >> + if (ret) {
> >> + dev_err(r5_core->dev,
> >> + "failed to get tcm %d pm domain, ret %d\n",
> >> + tcm_pd_idx, ret);
> >> + return ret;
> >> + }
> >> + tcm->pm_domain_id = out_args.args[0];
> >> + of_node_put(out_args.np);
> >> +
> >> + /* Get TCM address without translation. */
> >> + ret = of_property_read_reg(np, j, &abs_addr, &size);
> >> + if (ret) {
> >> + dev_err(dev, "failed to get reg property\n");
> >> + return ret;
> >> + }
> >> +
> >> + /*
> >> + * Remote processor can address only 32 bits
> >> + * so convert 64-bits into 32-bits. This will discard
> >> + * any unwanted upper 32-bits.
> >> + */
> >> + tcm->da = (u32)abs_addr;
> >> + tcm->size = (u32)size;
> >> +
> >> + cpdev = to_platform_device(dev);
> >> + res = platform_get_resource(cpdev, IORESOURCE_MEM, j);
> >> + if (!res) {
> >> + dev_err(dev, "failed to get tcm resource\n");
> >> + return -EINVAL;
> >> + }
> >> +
> >> + tcm->addr = (u32)res->start;
> >> + tcm->bank_name = (char *)res->name;
> >> + res = devm_request_mem_region(dev, tcm->addr, tcm->size,
> >> + tcm->bank_name);
> >> + if (!res) {
> >> + dev_err(dev, "failed to request tcm resource\n");
> >> + return -EINVAL;
> >> + }
> >> + }
> >> + }
> >> +
> >> + return 0;
> >> +}
> >> +
> >> /**
> >> * zynqmp_r5_get_tcm_node()
> >> * Ideally this function should parse tcm node and store information
> >> @@ -839,9 +906,16 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
> >> struct zynqmp_r5_core *r5_core;
> >> int ret, i;
> >>
> >> - ret = zynqmp_r5_get_tcm_node(cluster);
> >> - if (ret < 0) {
> >> - dev_err(dev, "can't get tcm node, err %d\n", ret);
> >> + r5_core = cluster->r5_cores[0];
> >> +
> >> + /* Maintain backward compatibility for zynqmp by using hardcode TCM address. */
> >> + if (device_is_compatible(dev, "xlnx,zynqmp-r5fss"))
> >
> > The previous patch moved the definition of the R5FSS to the new bindings but
> > this is forcing to use the old bindings - did I something?
>
> Hi Mathieu,
>
> We need to maintain backward compatibility for zynqmp device. So, using old bindings
> for zynqmp. For new devices (Versal and Versal-NET) new bindings are enforced in driver.
> It's not recommended to map two programming sequences to same device. So for
> "xlnx,zynqmp-r5fss" device old bindings are used.
>

You are not using two programming sequences for the same device, you are simply
ensuring backward compatibility for older device tree. The bindings for r5fss
have been updated so the driver should be using the new method. You have used
"xlnx,tcm-mode" to switch between new and old bindings, do that here too.

I'm also not sure why Versal and Versal-NET are being added to this patchset...
It should be in another patchset of its own.

> Device tree is matching with new bindings. But that's hardware description. I believe,
> driver can still choose to use hardcode addresses to maintain backward compatibility.
>
> The end result will be same.
>
> Thanks,
> Tanmay
>
> >
> >> + ret = zynqmp_r5_get_tcm_node(cluster);
> >> + else
> >> + ret = zynqmp_r5_get_tcm_node_from_dt(cluster);
> >> +
> >> + if (ret) {
> >> + dev_err(dev, "can't get tcm, err %d\n", ret);
> >> return ret;
> >> }
> >>
> >> @@ -856,12 +930,18 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
> >> return ret;
> >> }
> >>
> >> - ret = zynqmp_r5_set_mode(r5_core, fw_reg_val, tcm_mode);
> >> - if (ret) {
> >> - dev_err(dev, "failed to set r5 cluster mode %d, err %d\n",
> >> - cluster->mode, ret);
> >> + ret = zynqmp_pm_set_rpu_mode(r5_core->pm_domain_id, fw_reg_val);
> >> + if (ret < 0) {
> >> + dev_err(r5_core->dev, "failed to set RPU mode\n");
> >> return ret;
> >> }
> >> +
> >> + if (device_is_compatible(dev, "xlnx,zynqmp-r5fss") ||
> >> + of_find_property(dev_of_node(dev), "xlnx,tcm-mode", NULL)) {
> >> + ret = zynqmp_pm_set_tcm_config(r5_core->pm_domain_id, tcm_mode);
> >> + if (ret < 0)
> >> + dev_err(r5_core->dev, "failed to configure TCM\n");
> >> + }
> >> }
> >>
> >> return 0;
> >> @@ -906,16 +986,25 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
> >> * fail driver probe if either of that is not set in dts.
> >> */
> >> if (cluster_mode == LOCKSTEP_MODE) {
> >> - tcm_mode = PM_RPU_TCM_COMB;
> >> fw_reg_val = PM_RPU_MODE_LOCKSTEP;
> >> } else if (cluster_mode == SPLIT_MODE) {
> >> - tcm_mode = PM_RPU_TCM_SPLIT;
> >> fw_reg_val = PM_RPU_MODE_SPLIT;
> >> } else {
> >> dev_err(dev, "driver does not support cluster mode %d\n", cluster_mode);
> >> return -EINVAL;
> >> }
> >>
> >> + if (device_is_compatible(dev, "xlnx,zynqmp-r5fss")) {
> >> + if (cluster_mode == LOCKSTEP_MODE)
> >> + tcm_mode = PM_RPU_TCM_COMB;
> >> + else
> >> + tcm_mode = PM_RPU_TCM_SPLIT;
> >> + } else if (of_find_property(dev_node, "xlnx,tcm-mode", NULL)) {
> >> + ret = of_property_read_u32(dev_node, "xlnx,tcm-mode", (u32 *)&tcm_mode);
> >> + if (ret)
> >> + return ret;
> >> + }
> >> +
> >> /*
> >> * Number of cores is decided by number of child nodes of
> >> * r5f subsystem node in dts. If Split mode is used in dts
> >> @@ -1100,6 +1189,8 @@ static int zynqmp_r5_remoteproc_probe(struct platform_device *pdev)
> >> /* Match table for OF platform binding */
> >> static const struct of_device_id zynqmp_r5_remoteproc_match[] = {
> >> { .compatible = "xlnx,zynqmp-r5fss", },
> >> + { .compatible = "xlnx,versal-r5fss", },
> >> + { .compatible = "xlnx,versal-net-r52fss", },
> >> { /* end of list */ },
> >> };
> >> MODULE_DEVICE_TABLE(of, zynqmp_r5_remoteproc_match);
> >> --
> >> 2.25.1
> >>
>

2024-04-11 18:08:22

by Tanmay Shah

[permalink] [raw]
Subject: Re: [PATCH v14 4/4] remoteproc: zynqmp: parse TCM from device tree



On 4/11/24 11:12 AM, Mathieu Poirier wrote:
> On Wed, Apr 10, 2024 at 05:36:30PM -0500, Tanmay Shah wrote:
>>
>>
>> On 4/10/24 11:59 AM, Mathieu Poirier wrote:
>> > On Mon, Apr 08, 2024 at 01:53:14PM -0700, Tanmay Shah wrote:
>> >> ZynqMP TCM information was fixed in driver. Now ZynqMP TCM information
>> >> is available in device-tree. Parse TCM information in driver
>> >> as per new bindings.
>> >>
>> >> Signed-off-by: Tanmay Shah <[email protected]>
>> >> ---
>> >>
>> >> Changes in v14:
>> >> - Add Versal platform support
>> >> - Add Versal-NET platform support
>> >> - Maintain backward compatibility for ZynqMP platform and use hardcode
>> >> TCM addresses
>> >> - Configure TCM based on xlnx,tcm-mode property for Versal
>> >> - Avoid TCM configuration if that property isn't available in DT
>> >>
>> >> drivers/remoteproc/xlnx_r5_remoteproc.c | 173 ++++++++++++++++++------
>> >> 1 file changed, 132 insertions(+), 41 deletions(-)
>> >>
>> >> diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c
>> >> index 0f942440b4e2..504492f930ac 100644
>> >> --- a/drivers/remoteproc/xlnx_r5_remoteproc.c
>> >> +++ b/drivers/remoteproc/xlnx_r5_remoteproc.c
>> >> @@ -74,8 +74,8 @@ struct mbox_info {
>> >> };
>> >>
>> >> /*
>> >> - * Hardcoded TCM bank values. This will be removed once TCM bindings are
>> >> - * accepted for system-dt specifications and upstreamed in linux kernel
>> >> + * Hardcoded TCM bank values. This will stay in driver to maintain backward
>> >> + * compatibility with device-tree that does not have TCM information.
>> >> */
>> >> static const struct mem_bank_data zynqmp_tcm_banks_split[] = {
>> >> {0xffe00000UL, 0x0, 0x10000UL, PD_R5_0_ATCM, "atcm0"}, /* TCM 64KB each */
>> >> @@ -300,36 +300,6 @@ static void zynqmp_r5_rproc_kick(struct rproc *rproc, int vqid)
>> >> dev_warn(dev, "failed to send message\n");
>> >> }
>> >>
>> >> -/*
>> >> - * zynqmp_r5_set_mode()
>> >> - *
>> >> - * set RPU cluster and TCM operation mode
>> >> - *
>> >> - * @r5_core: pointer to zynqmp_r5_core type object
>> >> - * @fw_reg_val: value expected by firmware to configure RPU cluster mode
>> >> - * @tcm_mode: value expected by fw to configure TCM mode (lockstep or split)
>> >> - *
>> >> - * Return: 0 for success and < 0 for failure
>> >> - */
>> >> -static int zynqmp_r5_set_mode(struct zynqmp_r5_core *r5_core,
>> >> - enum rpu_oper_mode fw_reg_val,
>> >> - enum rpu_tcm_comb tcm_mode)
>> >> -{
>> >> - int ret;
>> >> -
>> >> - ret = zynqmp_pm_set_rpu_mode(r5_core->pm_domain_id, fw_reg_val);
>> >> - if (ret < 0) {
>> >> - dev_err(r5_core->dev, "failed to set RPU mode\n");
>> >> - return ret;
>> >> - }
>> >> -
>> >> - ret = zynqmp_pm_set_tcm_config(r5_core->pm_domain_id, tcm_mode);
>> >> - if (ret < 0)
>> >> - dev_err(r5_core->dev, "failed to configure TCM\n");
>> >> -
>> >> - return ret;
>> >> -}
>> >> -
>> >> /*
>> >> * zynqmp_r5_rproc_start()
>> >> * @rproc: single R5 core's corresponding rproc instance
>> >> @@ -761,6 +731,103 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
>> >> return ERR_PTR(ret);
>> >> }
>> >>
>> >> +static int zynqmp_r5_get_tcm_node_from_dt(struct zynqmp_r5_cluster *cluster)
>> >> +{
>> >> + int i, j, tcm_bank_count, ret, tcm_pd_idx, pd_count;
>> >> + struct of_phandle_args out_args;
>> >> + struct zynqmp_r5_core *r5_core;
>> >> + struct platform_device *cpdev;
>> >> + struct mem_bank_data *tcm;
>> >> + struct device_node *np;
>> >> + struct resource *res;
>> >> + u64 abs_addr, size;
>> >> + struct device *dev;
>> >> +
>> >> + for (i = 0; i < cluster->core_count; i++) {
>> >> + r5_core = cluster->r5_cores[i];
>> >> + dev = r5_core->dev;
>> >> + np = r5_core->np;
>> >> +
>> >> + pd_count = of_count_phandle_with_args(np, "power-domains",
>> >> + "#power-domain-cells");
>> >> +
>> >> + if (pd_count <= 0) {
>> >> + dev_err(dev, "invalid power-domains property, %d\n", pd_count);
>> >> + return -EINVAL;
>> >> + }
>> >> +
>> >> + /* First entry in power-domains list is for r5 core, rest for TCM. */
>> >> + tcm_bank_count = pd_count - 1;
>> >> +
>> >> + if (tcm_bank_count <= 0) {
>> >> + dev_err(dev, "invalid TCM count %d\n", tcm_bank_count);
>> >> + return -EINVAL;
>> >> + }
>> >> +
>> >> + r5_core->tcm_banks = devm_kcalloc(dev, tcm_bank_count,
>> >> + sizeof(struct mem_bank_data *),
>> >> + GFP_KERNEL);
>> >> + if (!r5_core->tcm_banks)
>> >> + return -ENOMEM;
>> >> +
>> >> + r5_core->tcm_bank_count = tcm_bank_count;
>> >> + for (j = 0, tcm_pd_idx = 1; j < tcm_bank_count; j++, tcm_pd_idx++) {
>> >> + tcm = devm_kzalloc(dev, sizeof(struct mem_bank_data),
>> >> + GFP_KERNEL);
>> >> + if (!tcm)
>> >> + return -ENOMEM;
>> >> +
>> >> + r5_core->tcm_banks[j] = tcm;
>> >> +
>> >> + /* Get power-domains id of TCM. */
>> >> + ret = of_parse_phandle_with_args(np, "power-domains",
>> >> + "#power-domain-cells",
>> >> + tcm_pd_idx, &out_args);
>> >> + if (ret) {
>> >> + dev_err(r5_core->dev,
>> >> + "failed to get tcm %d pm domain, ret %d\n",
>> >> + tcm_pd_idx, ret);
>> >> + return ret;
>> >> + }
>> >> + tcm->pm_domain_id = out_args.args[0];
>> >> + of_node_put(out_args.np);
>> >> +
>> >> + /* Get TCM address without translation. */
>> >> + ret = of_property_read_reg(np, j, &abs_addr, &size);
>> >> + if (ret) {
>> >> + dev_err(dev, "failed to get reg property\n");
>> >> + return ret;
>> >> + }
>> >> +
>> >> + /*
>> >> + * Remote processor can address only 32 bits
>> >> + * so convert 64-bits into 32-bits. This will discard
>> >> + * any unwanted upper 32-bits.
>> >> + */
>> >> + tcm->da = (u32)abs_addr;
>> >> + tcm->size = (u32)size;
>> >> +
>> >> + cpdev = to_platform_device(dev);
>> >> + res = platform_get_resource(cpdev, IORESOURCE_MEM, j);
>> >> + if (!res) {
>> >> + dev_err(dev, "failed to get tcm resource\n");
>> >> + return -EINVAL;
>> >> + }
>> >> +
>> >> + tcm->addr = (u32)res->start;
>> >> + tcm->bank_name = (char *)res->name;
>> >> + res = devm_request_mem_region(dev, tcm->addr, tcm->size,
>> >> + tcm->bank_name);
>> >> + if (!res) {
>> >> + dev_err(dev, "failed to request tcm resource\n");
>> >> + return -EINVAL;
>> >> + }
>> >> + }
>> >> + }
>> >> +
>> >> + return 0;
>> >> +}
>> >> +
>> >> /**
>> >> * zynqmp_r5_get_tcm_node()
>> >> * Ideally this function should parse tcm node and store information
>> >> @@ -839,9 +906,16 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
>> >> struct zynqmp_r5_core *r5_core;
>> >> int ret, i;
>> >>
>> >> - ret = zynqmp_r5_get_tcm_node(cluster);
>> >> - if (ret < 0) {
>> >> - dev_err(dev, "can't get tcm node, err %d\n", ret);
>> >> + r5_core = cluster->r5_cores[0];
>> >> +
>> >> + /* Maintain backward compatibility for zynqmp by using hardcode TCM address. */
>> >> + if (device_is_compatible(dev, "xlnx,zynqmp-r5fss"))
>> >
>> > The previous patch moved the definition of the R5FSS to the new bindings but
>> > this is forcing to use the old bindings - did I something?
>>
>> Hi Mathieu,
>>
>> We need to maintain backward compatibility for zynqmp device. So, using old bindings
>> for zynqmp. For new devices (Versal and Versal-NET) new bindings are enforced in driver.
>> It's not recommended to map two programming sequences to same device. So for
>> "xlnx,zynqmp-r5fss" device old bindings are used.
>>
>
> You are not using two programming sequences for the same device, you are simply
> ensuring backward compatibility for older device tree. The bindings for r5fss
> have been updated so the driver should be using the new method. You have used
> "xlnx,tcm-mode" to switch between new and old bindings, do that here too.
>

Okay. That means checking on "reg" property as it was done before.

> I'm also not sure why Versal and Versal-NET are being added to this patchset...
> It should be in another patchset of its own.
>

For driver I am okay to send new patchset, but for bindings I prefer to keep it.
This was discussed with Krzysztof earlier.

>> Device tree is matching with new bindings. But that's hardware description. I believe,
>> driver can still choose to use hardcode addresses to maintain backward compatibility.
>>
>> The end result will be same.
>>
>> Thanks,
>> Tanmay
>>
>> >
>> >> + ret = zynqmp_r5_get_tcm_node(cluster);
>> >> + else
>> >> + ret = zynqmp_r5_get_tcm_node_from_dt(cluster);
>> >> +
>> >> + if (ret) {
>> >> + dev_err(dev, "can't get tcm, err %d\n", ret);
>> >> return ret;
>> >> }
>> >>
>> >> @@ -856,12 +930,18 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
>> >> return ret;
>> >> }
>> >>
>> >> - ret = zynqmp_r5_set_mode(r5_core, fw_reg_val, tcm_mode);
>> >> - if (ret) {
>> >> - dev_err(dev, "failed to set r5 cluster mode %d, err %d\n",
>> >> - cluster->mode, ret);
>> >> + ret = zynqmp_pm_set_rpu_mode(r5_core->pm_domain_id, fw_reg_val);
>> >> + if (ret < 0) {
>> >> + dev_err(r5_core->dev, "failed to set RPU mode\n");
>> >> return ret;
>> >> }
>> >> +
>> >> + if (device_is_compatible(dev, "xlnx,zynqmp-r5fss") ||
>> >> + of_find_property(dev_of_node(dev), "xlnx,tcm-mode", NULL)) {
>> >> + ret = zynqmp_pm_set_tcm_config(r5_core->pm_domain_id, tcm_mode);
>> >> + if (ret < 0)
>> >> + dev_err(r5_core->dev, "failed to configure TCM\n");
>> >> + }
>> >> }
>> >>
>> >> return 0;
>> >> @@ -906,16 +986,25 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
>> >> * fail driver probe if either of that is not set in dts.
>> >> */
>> >> if (cluster_mode == LOCKSTEP_MODE) {
>> >> - tcm_mode = PM_RPU_TCM_COMB;
>> >> fw_reg_val = PM_RPU_MODE_LOCKSTEP;
>> >> } else if (cluster_mode == SPLIT_MODE) {
>> >> - tcm_mode = PM_RPU_TCM_SPLIT;
>> >> fw_reg_val = PM_RPU_MODE_SPLIT;
>> >> } else {
>> >> dev_err(dev, "driver does not support cluster mode %d\n", cluster_mode);
>> >> return -EINVAL;
>> >> }
>> >>
>> >> + if (device_is_compatible(dev, "xlnx,zynqmp-r5fss")) {
>> >> + if (cluster_mode == LOCKSTEP_MODE)
>> >> + tcm_mode = PM_RPU_TCM_COMB;
>> >> + else
>> >> + tcm_mode = PM_RPU_TCM_SPLIT;
>> >> + } else if (of_find_property(dev_node, "xlnx,tcm-mode", NULL)) {
>> >> + ret = of_property_read_u32(dev_node, "xlnx,tcm-mode", (u32 *)&tcm_mode);
>> >> + if (ret)
>> >> + return ret;
>> >> + }
>> >> +
>> >> /*
>> >> * Number of cores is decided by number of child nodes of
>> >> * r5f subsystem node in dts. If Split mode is used in dts
>> >> @@ -1100,6 +1189,8 @@ static int zynqmp_r5_remoteproc_probe(struct platform_device *pdev)
>> >> /* Match table for OF platform binding */
>> >> static const struct of_device_id zynqmp_r5_remoteproc_match[] = {
>> >> { .compatible = "xlnx,zynqmp-r5fss", },
>> >> + { .compatible = "xlnx,versal-r5fss", },
>> >> + { .compatible = "xlnx,versal-net-r52fss", },
>> >> { /* end of list */ },
>> >> };
>> >> MODULE_DEVICE_TABLE(of, zynqmp_r5_remoteproc_match);
>> >> --
>> >> 2.25.1
>> >>
>>