Skip to contentSkip to conversation

Add Agilex5 AXI DMA support

PATCH Superseded Khairul Anuar Romli 2 participants 11 messages Dec 11, 2025 – Dec 15, 2025

Subsystems (3)

v3 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

v3 cover Add Agilex5 AXI DMA support

This series introduces support for Agilex5 SoC in the Synopsys DesignWare AXI DMA binding and updates the device tree to use the platform-specific compatible string.

The Agilex5 only has 40-bit DMA addressable bit instead of 64-bit. Hence, this specific addition will enable driver to handle this limitation.

---
Notes:
This patch series is applied on socfpga maintainer's tree
https://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git/log/?h=socfpga_dts_for_v6.19

Changes in v3:
- simplify dma-ranges addition without description as per input from Rob.
- Add simple-bus to with address-cells, size-cells, dma-ranges added under this bus-node.
- Move dma controller device node under simple-bus node.
- Rename "arm64: dts: intel: agilex5: Add dma-ranges, address and size cells to dma node" to #2
- Drop "dt-bindings: dma: snps,dw-axi-dmac: Add #address-cells and #size-cells"
- Refactor "dma: dw-axi-dmac: Add support for Agilex5 and dynamic bus width" to align with dma controller node now under simple-bus node.

Changes in v2:
- Add dma-ranges property.
- Add address-cells and size-cells due to warning when dma-ranges is define without address-cells and size-cells present. Also prevent kernel panic if address-cells and size-cells are not defined.
- Add driver support to handle defined properties and set the DMA BIT MASK according to value from DT.
- Rename "arm64: dts: agilex5: Use platform-specific compatible for AXI DMA" to "arm64: dts: intel: agilex5: Add dma-ranges and address cells to dma node"

This changes is validated on:
- intel/socfpga_agilex5_socdk.dtb
- snps,dw-axi-dmac.yaml
- snps,dw-axi-dmac.yaml intel/socfpga_agilex5_socdk.dtb
- Agilex5 devkit
---
Khairul Anuar Romli (3):
dt-bindings: dma: snps,dw-axi-dmac: Add compatible string for Agilex5
arm64: dts: intel: agilex5: Add simple-bus node on top of dma
controller node
dma: dw-axi-dmac: Add support for Agilex5 and dynamic bus width

 .../bindings/dma/snps,dw-axi-dmac.yaml        | 16 ++--
 .../arm64/boot/dts/intel/socfpga_agilex5.dtsi | 78 +++++++++++--------
 .../dma/dw-axi-dmac/dw-axi-dmac-platform.c    | 69 +++++++++++++++-
 drivers/dma/dw-axi-dmac/dw-axi-dmac.h         |  1 +
 4 files changed, 124 insertions(+), 40 deletions(-)
Signature · 1 line
2.43.7
#1 lore raw

PATCH v3 1/3 dt-bindings: dma: snps,dw-axi-dmac: Add compatible string for Agilex5

The address bus on Agilex5 is limited to 40 bits. When SMMU is enable this will cause address truncation and translation faults. Hence introducing "altr,agilex5-axi-dma" to enable platform specific configuration to configure the dma addressable bit mask.

Add a fallback capability for the compatible property to allow driver to probe and initialize with a newly added compatible string without requiring additional entry in the driver.

Add dma-ranges to the binding schema to allow specifying DMA address mapping between the controller and its parent bus.

---
Changes in v3:
- Simple dma-ranges property with true and without description
Changes in v2:
- Add dma-ranges

---
 .../bindings/dma/snps,dw-axi-dmac.yaml           | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)
Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml +11 -5
index a393a33c8908..1f4dcf3092c3 100644
@@ -17,11 +17,15 @@ allOf:
 
 properties:
   compatible:
-    enum:
-      - snps,axi-dma-1.01a
-      - intel,kmb-axi-dma
-      - starfive,jh7110-axi-dma
-      - starfive,jh8100-axi-dma
+    oneOf:
+      - enum:
+          - snps,axi-dma-1.01a
+          - intel,kmb-axi-dma
+          - starfive,jh7110-axi-dma
+          - starfive,jh8100-axi-dma
+      - items:
+          - const: altr,agilex5-axi-dma
+          - const: snps,axi-dma-1.01a
 
   reg:
     minItems: 1
@@ -104,6 +108,8 @@ properties:
     minimum: 1
     maximum: 256
 
+  dma-ranges: true
+
 required:
   - compatible
   - reg
Signature · 1 line
2.43.7
maintainer
#2 lore raw

Re: [PATCH v3 1/3] dt-bindings: dma: snps,dw-axi-dmac: Add compatible string for Agilex5

Quoted 48 lines · Khairul Anuar Romli

The address bus on Agilex5 is limited to 40 bits. When SMMU is enable this will cause address truncation and translation faults. Hence introducing "altr,agilex5-axi-dma" to enable platform specific configuration to configure the dma addressable bit mask.

Add a fallback capability for the compatible property to allow driver to probe and initialize with a newly added compatible string without requiring additional entry in the driver.

Add dma-ranges to the binding schema to allow specifying DMA address mapping between the controller and its parent bus.

---
Changes in v3:
- Simple dma-ranges property with true and without description
Changes in v2:
- Add dma-ranges

---
 .../bindings/dma/snps,dw-axi-dmac.yaml           | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)
Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml +9 -5
index a393a33c8908..1f4dcf3092c3 100644
@@ -17,11 +17,15 @@ allOf:
 
 properties:
   compatible:
-    enum:
-      - snps,axi-dma-1.01a
-      - intel,kmb-axi-dma
-      - starfive,jh7110-axi-dma
-      - starfive,jh8100-axi-dma
+    oneOf:
+      - enum:
+          - snps,axi-dma-1.01a
+          - intel,kmb-axi-dma
+          - starfive,jh7110-axi-dma
+          - starfive,jh8100-axi-dma
+      - items:
+          - const: altr,agilex5-axi-dma
+          - const: snps,axi-dma-1.01a
 
   reg:
     minItems: 1

Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml properties: · line 112

Quoted 5 lines
Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml +2 -0
@@ -104,6 +108,8 @@ properties:
     minimum: 1
     maximum: 256
 
+  dma-ranges: true
+

You no longer need this because it is in the bus node.

Rob

#3 lore raw

Re: [PATCH v3 1/3] dt-bindings: dma: snps,dw-axi-dmac: Add compatible string for Agilex5

Quoted 52 lines · Rob Herring
Quoted 51 lines · Khairul Anuar Romli

The address bus on Agilex5 is limited to 40 bits. When SMMU is enable this will cause address truncation and translation faults. Hence introducing "altr,agilex5-axi-dma" to enable platform specific configuration to configure the dma addressable bit mask.

Add a fallback capability for the compatible property to allow driver to probe and initialize with a newly added compatible string without requiring additional entry in the driver.

Add dma-ranges to the binding schema to allow specifying DMA address mapping between the controller and its parent bus.

---
Changes in v3:
- Simple dma-ranges property with true and without description
Changes in v2:
- Add dma-ranges

---
  .../bindings/dma/snps,dw-axi-dmac.yaml           | 16 +++++++++++-----
  1 file changed, 11 insertions(+), 5 deletions(-)
Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml +9 -5
index a393a33c8908..1f4dcf3092c3 100644
@@ -17,11 +17,15 @@ allOf:
 
  properties:
    compatible:
-    enum:
-      - snps,axi-dma-1.01a
-      - intel,kmb-axi-dma
-      - starfive,jh7110-axi-dma
-      - starfive,jh8100-axi-dma
+    oneOf:
+      - enum:
+          - snps,axi-dma-1.01a
+          - intel,kmb-axi-dma
+          - starfive,jh7110-axi-dma
+          - starfive,jh8100-axi-dma
+      - items:
+          - const: altr,agilex5-axi-dma
+          - const: snps,axi-dma-1.01a
 
    reg:
      minItems: 1
@@ -104,6 +108,8 @@ properties:
      minimum: 1
      maximum: 256
 
Quoted 6 lines

Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml properties: · line 112

Quoted 2 lines
Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml +2 -0
+  dma-ranges: true
+

You no longer need this because it is in the bus node.

Rob

I will remove the dma-ranges property in the next revision.

Thanks.

Khairul

#4 lore raw

PATCH v3 2/3 arm64: dts: intel: agilex5: Add simple-bus node on top of dma controller node

In reply to Khairul Anuar Romli

Move dma-controller node under simple-bus node to allow bus node specific property able to be properly defined. This is require to fulfill Agilex5 bus limitation that is limited to 40-addressable-bit.

Update the compatible string for the DMA controller nodes in the Agilex5 device tree from the generic "snps,axi-dma-1.01a" to the platform-specific "altr,agilex5-axi-dma". Add fallback capability to ensure driver is able to initialize properly.

This change enables the use of platform-specific features and constraints in the driver, such as setting a 40-bit DMA addressable mask through dma-ranges, which is required for Agilex5. It also aligns with the updated device tree bindings and driver support for this compatible string.

---
Changes in v3:
- Rename the patch "arm64: dts: intel: agilex5: Add dma-ranges, address and size cells to dma node"
- Add simple-bus and move dmac0 and dmac1 1 level down.
Changes in v2:
- Rename the from add platform specific to add dma-ranges, address and size cells.
- Define address-cells and size-cells for dmac0 and dmac1
- Add dma-ranges for agilex5 for 40-bit

---
 .../arm64/boot/dts/intel/socfpga_agilex5.dtsi | 78 +++++++++++--------
 1 file changed, 44 insertions(+), 34 deletions(-)
arch/arm64/boot/dts/intel/socfpga_agilex5.dtsi +44 -34
index 06f98667499b..bffd914cf051 100644
@@ -335,40 +335,50 @@ ocram: sram@0 {
 			#size-cells = <1>;
 		};
 
-		dmac0: dma-controller@10db0000 {
-			compatible = "snps,axi-dma-1.01a";
-			reg = <0x10db0000 0x500>;
-			clocks = <&clkmgr AGILEX5_L4_MAIN_CLK>,
-				 <&clkmgr AGILEX5_L4_MP_CLK>;
-			clock-names = "core-clk", "cfgr-clk";
-			interrupt-parent = <&intc>;
-			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
-			#dma-cells = <1>;
-			dma-channels = <4>;
-			snps,dma-masters = <1>;
-			snps,data-width = <2>;
-			snps,block-size = <32767 32767 32767 32767>;
-			snps,priority = <0 1 2 3>;
-			snps,axi-max-burst-len = <8>;
-			iommus = <&smmu 8>;
-		};
-
-		dmac1: dma-controller@10dc0000 {
-			compatible = "snps,axi-dma-1.01a";
-			reg = <0x10dc0000 0x500>;
-			clocks = <&clkmgr AGILEX5_L4_MAIN_CLK>,
-				 <&clkmgr AGILEX5_L4_MP_CLK>;
-			clock-names = "core-clk", "cfgr-clk";
-			interrupt-parent = <&intc>;
-			interrupts = <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
-			#dma-cells = <1>;
-			dma-channels = <4>;
-			snps,dma-masters = <1>;
-			snps,data-width = <2>;
-			snps,block-size = <32767 32767 32767 32767>;
-			snps,priority = <0 1 2 3>;
-			snps,axi-max-burst-len = <8>;
-			iommus = <&smmu 9>;
+		dma: dma-bus@10db0000 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <2>;
+			ranges = <0x00 0x10db0000 0x00 0x20000>;
+			dma-ranges = <0x00 0x00 0x100 0x00>;
+
+			dmac0: dma-controller@0 {
+				compatible = "altr,agilex5-axi-dma",
+					     "snps,axi-dma-1.01a";
+				reg = <0x0 0x0 0x500>;
+				clocks = <&clkmgr AGILEX5_L4_MAIN_CLK>,
+					 <&clkmgr AGILEX5_L4_MP_CLK>;
+				clock-names = "core-clk", "cfgr-clk";
+				interrupt-parent = <&intc>;
+				interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+				#dma-cells = <1>;
+				dma-channels = <4>;
+				snps,dma-masters = <1>;
+				snps,data-width = <2>;
+				snps,block-size = <32767 32767 32767 32767>;
+				snps,priority = <0 1 2 3>;
+				snps,axi-max-burst-len = <8>;
+				iommus = <&smmu 8>;
+			};
+
+			dmac1: dma-controller@10000 {
+				compatible = "altr,agilex5-axi-dma",
+					     "snps,axi-dma-1.01a";
+				reg = <0x10000 0x0 0x500>;
+				clocks = <&clkmgr AGILEX5_L4_MAIN_CLK>,
+					 <&clkmgr AGILEX5_L4_MP_CLK>;
+				clock-names = "core-clk", "cfgr-clk";
+				interrupt-parent = <&intc>;
+				interrupts = <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
+				#dma-cells = <1>;
+				dma-channels = <4>;
+				snps,dma-masters = <1>;
+				snps,data-width = <2>;
+				snps,block-size = <32767 32767 32767 32767>;
+				snps,priority = <0 1 2 3>;
+				snps,axi-max-burst-len = <8>;
+				iommus = <&smmu 9>;
+			};
 		};
 
 		rst: rstmgr@10d11000 {
Signature · 1 line
2.43.7
#5 lore raw

PATCH v3 3/3 dma: dw-axi-dmac: Add support for Agilex5 and dynamic bus width

In reply to Khairul Anuar Romli

Add device tree compatible string support for the Altera Agilex5 AXI DMA controller.

Introduces logic to parse the "dma-ranges" property and calculate the actual number of addressable bits (bus width) for the DMA engine. This calculated value is then used to set the coherent mask via 'dma_set_mask_and_coherent()', allowing the driver to correctly handle devices with bus widths less than 64 bits. The addressable bits default to 64 if 'dma-ranges' is not specified or cannot be parsed.

Introduce 'addressable_bits' to 'struct axi_dma_chip' to store this value.

---
Changes in v3:
- Refactor the code to align with dma controller device node move to 1 level down.
Changes in v2:
- Add driver implementation to set the DMA BIT MAST to 40 based on dma-ranges defined in DT.
- Add glue for driver and DT.

---
 .../dma/dw-axi-dmac/dw-axi-dmac-platform.c    | 69 ++++++++++++++++++-
 drivers/dma/dw-axi-dmac/dw-axi-dmac.h         |  1 +
 2 files changed, 69 insertions(+), 1 deletion(-)
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +68 -1
index b23536645ff7..96b0a0842ff5 100644
@@ -271,7 +271,9 @@ static void axi_dma_hw_init(struct axi_dma_chip *chip)
 		axi_chan_irq_disable(&chip->dw->chan[i], DWAXIDMAC_IRQ_ALL);
 		axi_chan_disable(&chip->dw->chan[i]);
 	}
-	ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(64));
+
+	dev_dbg(chip->dev, "Adressable bus width: %u\n", chip->addressable_bits);
+	ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(chip->addressable_bits));
 	if (ret)
 		dev_warn(chip->dev, "Unable to set coherent mask\n");
 }
@@ -1461,13 +1463,24 @@ static int axi_req_irqs(struct platform_device *pdev, struct axi_dma_chip *chip)
 	return 0;
 }
 
+/* Forward declaration (no size required) */
+static const struct of_device_id dw_dma_of_id_table[];
+
 static int dw_probe(struct platform_device *pdev)
 {
 	struct axi_dma_chip *chip;
 	struct dw_axi_dma *dw;
 	struct dw_axi_dma_hcfg *hdata;
 	struct reset_control *resets;
+	struct device_node *parent;
+	const struct of_device_id *match;
 	unsigned int flags;
+	unsigned int addressable_bits = 64;
+	unsigned int len_bytes;
+	unsigned int num_cells;
+	const __be32 *prop;
+	u64 bus_width;
+	u32 *cells;
 	u32 i;
 	int ret;
 
@@ -1483,9 +1496,61 @@ static int dw_probe(struct platform_device *pdev)
 	if (!hdata)
 		return -ENOMEM;
 
+	match = of_match_node(dw_dma_of_id_table, pdev->dev.of_node);
+	if (!match) {
+		dev_err(&pdev->dev, "Unsupported AXI DMA device\n");
+		return -ENODEV;
+	}
+
+	parent = of_get_parent(pdev->dev.of_node);
+	if (parent) {
+		prop = of_get_property(parent, "dma-ranges", &len_bytes);
+		if (prop) {
+			num_cells = len_bytes / sizeof(__be32);
+			cells = kcalloc(num_cells, sizeof(*cells), GFP_KERNEL);
+			if (!cells)
+				return -ENOMEM;
+
+			ret = of_property_read_u32(parent, "#address-cells", &i);
+			if (ret) {
+				dev_err(&pdev->dev, "missing #address-cells property\n");
+				return ret;
+			}
+
+			ret = of_property_read_u32(parent, "#size-cells", &i);
+			if (ret) {
+				dev_err(&pdev->dev, "missing #size-cells property\n");
+				return ret;
+			}
+
+			if (!of_property_read_u32_array(parent, "dma-ranges",
+							cells, num_cells)) {
+				dev_dbg(&pdev->dev, "dma-ranges number of cells: %u\n", num_cells);
+				// Check if size-cells is 2 cells.
+				if (i == 2 && num_cells > 3) {
+					// Combine size cells into 64-bit length
+					dev_dbg(&pdev->dev, "size-cells MSB: %u\n",
+						cells[num_cells - 2]);
+					dev_dbg(&pdev->dev, "size-cells LSB: %u\n",
+						cells[num_cells - 1]);
+					bus_width = ((u64)cells[num_cells - 2] << 32) |
+cells[num_cells - 1];
+				}
+
+				// Count number of bits in bus_width
+				if (bus_width)
+					addressable_bits = fls64(bus_width) - 1;
+
+				dev_dbg(&pdev->dev, "Bus width: %u bits (length: 0x%llx)\n",
+					addressable_bits, bus_width);
+			}
+		}
+	}
+
 	chip->dw = dw;
 	chip->dev = &pdev->dev;
 	chip->dw->hdata = hdata;
+	chip->addressable_bits = addressable_bits;
 
 	chip->regs = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(chip->regs))
@@ -1669,6 +1734,8 @@ static const struct of_device_id dw_dma_of_id_table[] = {
 	}, {
 		.compatible = "starfive,jh8100-axi-dma",
 		.data = (void *)AXI_DMA_FLAG_HAS_RESETS,
+	}, {
+		.compatible = "altr,agilex5-axi-dma"
 	},
 	{}
 };
drivers/dma/dw-axi-dmac/dw-axi-dmac.h +1 -0
index b842e6a8d90d..f8152f8b3798 100644
@@ -71,6 +71,7 @@ struct axi_dma_chip {
 	struct clk		*core_clk;
 	struct clk		*cfgr_clk;
 	struct dw_axi_dma	*dw;
+	u32			addressable_bits;
 };
 
 /* LLI == Linked List Item */
Signature · 1 line
2.43.7
maintainer
#6 lore raw

Re: [PATCH v3 3/3] dma: dw-axi-dmac: Add support for Agilex5 and dynamic bus width

Quoted 89 lines · Khairul Anuar Romli

Add device tree compatible string support for the Altera Agilex5 AXI DMA controller.

Introduces logic to parse the "dma-ranges" property and calculate the actual number of addressable bits (bus width) for the DMA engine. This calculated value is then used to set the coherent mask via 'dma_set_mask_and_coherent()', allowing the driver to correctly handle devices with bus widths less than 64 bits. The addressable bits default to 64 if 'dma-ranges' is not specified or cannot be parsed.

Introduce 'addressable_bits' to 'struct axi_dma_chip' to store this value.

---
Changes in v3:
- Refactor the code to align with dma controller device node move to 1 level down.
Changes in v2:
- Add driver implementation to set the DMA BIT MAST to 40 based on dma-ranges defined in DT.
- Add glue for driver and DT.

---
 .../dma/dw-axi-dmac/dw-axi-dmac-platform.c    | 69 ++++++++++++++++++-
 drivers/dma/dw-axi-dmac/dw-axi-dmac.h         |  1 +
 2 files changed, 69 insertions(+), 1 deletion(-)
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +33 -1
index b23536645ff7..96b0a0842ff5 100644
@@ -271,7 +271,9 @@ static void axi_dma_hw_init(struct axi_dma_chip *chip)
 		axi_chan_irq_disable(&chip->dw->chan[i], DWAXIDMAC_IRQ_ALL);
 		axi_chan_disable(&chip->dw->chan[i]);
 	}
-	ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(64));
+
+	dev_dbg(chip->dev, "Adressable bus width: %u\n", chip->addressable_bits);
+	ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(chip->addressable_bits));
 	if (ret)
 		dev_warn(chip->dev, "Unable to set coherent mask\n");
 }
@@ -1461,13 +1463,24 @@ static int axi_req_irqs(struct platform_device *pdev, struct axi_dma_chip *chip)
 	return 0;
 }
 
+/* Forward declaration (no size required) */
+static const struct of_device_id dw_dma_of_id_table[];
+
 static int dw_probe(struct platform_device *pdev)
 {
 	struct axi_dma_chip *chip;
 	struct dw_axi_dma *dw;
 	struct dw_axi_dma_hcfg *hdata;
 	struct reset_control *resets;
+	struct device_node *parent;
+	const struct of_device_id *match;
 	unsigned int flags;
+	unsigned int addressable_bits = 64;
+	unsigned int len_bytes;
+	unsigned int num_cells;
+	const __be32 *prop;
+	u64 bus_width;
+	u32 *cells;
 	u32 i;
 	int ret;
 
@@ -1483,9 +1496,61 @@ static int dw_probe(struct platform_device *pdev)
 	if (!hdata)
 		return -ENOMEM;
 
+	match = of_match_node(dw_dma_of_id_table, pdev->dev.of_node);
+	if (!match) {
+		dev_err(&pdev->dev, "Unsupported AXI DMA device\n");
+		return -ENODEV;
+	}
+
+	parent = of_get_parent(pdev->dev.of_node);
+	if (parent) {
+		prop = of_get_property(parent, "dma-ranges", &len_bytes);
+		if (prop) {
+			num_cells = len_bytes / sizeof(__be32);
+			cells = kcalloc(num_cells, sizeof(*cells), GFP_KERNEL);
+			if (!cells)
+				return -ENOMEM;
+
+			ret = of_property_read_u32(parent, "#address-cells", &i);
+			if (ret) {
+				dev_err(&pdev->dev, "missing #address-cells property\n");
+				return ret;

drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c static int dw_probe(struct platform_device *pdev) · line 1527

Quoted 10 lines
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +10 -0
+			}
+
+			ret = of_property_read_u32(parent, "#size-cells", &i);
+			if (ret) {
+				dev_err(&pdev->dev, "missing #size-cells property\n");
+				return ret;
+			}
+
+			if (!of_property_read_u32_array(parent, "dma-ranges",
+							cells, num_cells)) {

We have common code to parse dma-ranges. Use it and don't implement your own.

Rob

maintainer
#7 lore raw

Re: [PATCH v3 3/3] dma: dw-axi-dmac: Add support for Agilex5 and dynamic bus width

Quoted 96 lines · Rob Herring
Quoted 94 lines · Khairul Anuar Romli

Add device tree compatible string support for the Altera Agilex5 AXI DMA controller.

Introduces logic to parse the "dma-ranges" property and calculate the actual number of addressable bits (bus width) for the DMA engine. This calculated value is then used to set the coherent mask via 'dma_set_mask_and_coherent()', allowing the driver to correctly handle devices with bus widths less than 64 bits. The addressable bits default to 64 if 'dma-ranges' is not specified or cannot be parsed.

Introduce 'addressable_bits' to 'struct axi_dma_chip' to store this value.

---
Changes in v3:
- Refactor the code to align with dma controller device node move to 1 level down.
Changes in v2:
- Add driver implementation to set the DMA BIT MAST to 40 based on dma-ranges defined in DT.
- Add glue for driver and DT.

---
 .../dma/dw-axi-dmac/dw-axi-dmac-platform.c    | 69 ++++++++++++++++++-
 drivers/dma/dw-axi-dmac/dw-axi-dmac.h         |  1 +
 2 files changed, 69 insertions(+), 1 deletion(-)
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +38 -1
index b23536645ff7..96b0a0842ff5 100644
@@ -271,7 +271,9 @@ static void axi_dma_hw_init(struct axi_dma_chip *chip)
              axi_chan_irq_disable(&chip->dw->chan[i], DWAXIDMAC_IRQ_ALL);
              axi_chan_disable(&chip->dw->chan[i]);
      }
-     ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(64));
+
+     dev_dbg(chip->dev, "Adressable bus width: %u\n", chip->addressable_bits);
+     ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(chip->addressable_bits));
      if (ret)
              dev_warn(chip->dev, "Unable to set coherent mask\n");
 }
@@ -1461,13 +1463,24 @@ static int axi_req_irqs(struct platform_device *pdev, struct axi_dma_chip *chip)
      return 0;
 }
 
+/* Forward declaration (no size required) */
+static const struct of_device_id dw_dma_of_id_table[];
+
 static int dw_probe(struct platform_device *pdev)
 {
      struct axi_dma_chip *chip;
      struct dw_axi_dma *dw;
      struct dw_axi_dma_hcfg *hdata;
      struct reset_control *resets;
+     struct device_node *parent;
+     const struct of_device_id *match;
      unsigned int flags;
+     unsigned int addressable_bits = 64;
+     unsigned int len_bytes;
+     unsigned int num_cells;
+     const __be32 *prop;
+     u64 bus_width;
+     u32 *cells;
      u32 i;
      int ret;
 
@@ -1483,9 +1496,61 @@ static int dw_probe(struct platform_device *pdev)
      if (!hdata)
              return -ENOMEM;
 
+     match = of_match_node(dw_dma_of_id_table, pdev->dev.of_node);
+     if (!match) {
+             dev_err(&pdev->dev, "Unsupported AXI DMA device\n");
+             return -ENODEV;
+     }
+
+     parent = of_get_parent(pdev->dev.of_node);
+     if (parent) {
+             prop = of_get_property(parent, "dma-ranges", &len_bytes);
+             if (prop) {
+                     num_cells = len_bytes / sizeof(__be32);
+                     cells = kcalloc(num_cells, sizeof(*cells), GFP_KERNEL);
+                     if (!cells)
+                             return -ENOMEM;
+
+                     ret = of_property_read_u32(parent, "#address-cells", &i);
+                     if (ret) {
+                             dev_err(&pdev->dev, "missing #address-cells property\n");
+                             return ret;
+                     }
+
+                     ret = of_property_read_u32(parent, "#size-cells", &i);
+                     if (ret) {
+                             dev_err(&pdev->dev, "missing #size-cells property\n");
Quoted 8 lines

drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c static int dw_probe(struct platform_device *pdev) · line 1527

Quoted 5 lines
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +5 -0
+                             return ret;
+                     }
+
+                     if (!of_property_read_u32_array(parent, "dma-ranges",
+                                                     cells, num_cells)) {

We have common code to parse dma-ranges. Use it and don't implement your own.

Actually, the driver and DT core should take care of all this for you and there's nothing to do in the driver. A driver only needs to set the mask for the IP itself and only when >32 bits. The core takes care of any additional restrictions in the bus.

Rob

#8 lore raw

Re: [PATCH v3 3/3] dma: dw-axi-dmac: Add support for Agilex5 and dynamic bus width

Quoted 106 lines · Rob Herring
Quoted 96 lines · Rob Herring
Quoted 94 lines · Khairul Anuar Romli

Add device tree compatible string support for the Altera Agilex5 AXI DMA controller.

Introduces logic to parse the "dma-ranges" property and calculate the actual number of addressable bits (bus width) for the DMA engine. This calculated value is then used to set the coherent mask via 'dma_set_mask_and_coherent()', allowing the driver to correctly handle devices with bus widths less than 64 bits. The addressable bits default to 64 if 'dma-ranges' is not specified or cannot be parsed.

Introduce 'addressable_bits' to 'struct axi_dma_chip' to store this value.

---
Changes in v3:
- Refactor the code to align with dma controller device node move to 1 level down.
Changes in v2:
- Add driver implementation to set the DMA BIT MAST to 40 based on dma-ranges defined in DT.
- Add glue for driver and DT.

---
  .../dma/dw-axi-dmac/dw-axi-dmac-platform.c    | 69 ++++++++++++++++++-
  drivers/dma/dw-axi-dmac/dw-axi-dmac.h         |  1 +
  2 files changed, 69 insertions(+), 1 deletion(-)
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +38 -1
index b23536645ff7..96b0a0842ff5 100644
@@ -271,7 +271,9 @@ static void axi_dma_hw_init(struct axi_dma_chip *chip)
               axi_chan_irq_disable(&chip->dw->chan[i], DWAXIDMAC_IRQ_ALL);
               axi_chan_disable(&chip->dw->chan[i]);
       }
-     ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(64));
+
+     dev_dbg(chip->dev, "Adressable bus width: %u\n", chip->addressable_bits);
+     ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(chip->addressable_bits));
       if (ret)
               dev_warn(chip->dev, "Unable to set coherent mask\n");
  }
@@ -1461,13 +1463,24 @@ static int axi_req_irqs(struct platform_device *pdev, struct axi_dma_chip *chip)
       return 0;
  }
 
+/* Forward declaration (no size required) */
+static const struct of_device_id dw_dma_of_id_table[];
+
  static int dw_probe(struct platform_device *pdev)
  {
       struct axi_dma_chip *chip;
       struct dw_axi_dma *dw;
       struct dw_axi_dma_hcfg *hdata;
       struct reset_control *resets;
+     struct device_node *parent;
+     const struct of_device_id *match;
       unsigned int flags;
+     unsigned int addressable_bits = 64;
+     unsigned int len_bytes;
+     unsigned int num_cells;
+     const __be32 *prop;
+     u64 bus_width;
+     u32 *cells;
       u32 i;
       int ret;
 
@@ -1483,9 +1496,61 @@ static int dw_probe(struct platform_device *pdev)
       if (!hdata)
               return -ENOMEM;
 
+     match = of_match_node(dw_dma_of_id_table, pdev->dev.of_node);
+     if (!match) {
+             dev_err(&pdev->dev, "Unsupported AXI DMA device\n");
+             return -ENODEV;
+     }
+
+     parent = of_get_parent(pdev->dev.of_node);
+     if (parent) {
+             prop = of_get_property(parent, "dma-ranges", &len_bytes);
+             if (prop) {
+                     num_cells = len_bytes / sizeof(__be32);
+                     cells = kcalloc(num_cells, sizeof(*cells), GFP_KERNEL);
+                     if (!cells)
+                             return -ENOMEM;
+
+                     ret = of_property_read_u32(parent, "#address-cells", &i);
+                     if (ret) {
+                             dev_err(&pdev->dev, "missing #address-cells property\n");
+                             return ret;
+                     }
+
+                     ret = of_property_read_u32(parent, "#size-cells", &i);
+                     if (ret) {
+                             dev_err(&pdev->dev, "missing #size-cells property\n");
Quoted 8 lines

drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c static int dw_probe(struct platform_device *pdev) · line 1527

Quoted 5 lines
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +5 -0
+                             return ret;
+                     }
+
+                     if (!of_property_read_u32_array(parent, "dma-ranges",
+                                                     cells, num_cells)) {

We have common code to parse dma-ranges. Use it and don't implement your own.

Quoted 6 lines

Actually, the driver and DT core should take care of all this for you and there's nothing to do in the driver. A driver only needs to set the mask for the IP itself and only when >32 bits. The core takes care of any additional restrictions in the bus.

Rob

The current implementation explicitly set the mask to 64.

- ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(64));

Will the core re-set the mask based on the dma-ranges on DT?

Thanks.

Regards,
Khairul

maintainer
#9 lore raw

Re: [PATCH v3 3/3] dma: dw-axi-dmac: Add support for Agilex5 and dynamic bus width

Quoted 113 lines · Khairul Anuar
Quoted 111 lines · Rob Herring
Quoted 96 lines · Rob Herring
Quoted 94 lines · Khairul Anuar Romli

Add device tree compatible string support for the Altera Agilex5 AXI DMA controller.

Introduces logic to parse the "dma-ranges" property and calculate the actual number of addressable bits (bus width) for the DMA engine. This calculated value is then used to set the coherent mask via 'dma_set_mask_and_coherent()', allowing the driver to correctly handle devices with bus widths less than 64 bits. The addressable bits default to 64 if 'dma-ranges' is not specified or cannot be parsed.

Introduce 'addressable_bits' to 'struct axi_dma_chip' to store this value.

---
Changes in v3:
- Refactor the code to align with dma controller device node move to 1 level down.
Changes in v2:
- Add driver implementation to set the DMA BIT MAST to 40 based on dma-ranges defined in DT.
- Add glue for driver and DT.

---
  .../dma/dw-axi-dmac/dw-axi-dmac-platform.c    | 69 ++++++++++++++++++-
  drivers/dma/dw-axi-dmac/dw-axi-dmac.h         |  1 +
  2 files changed, 69 insertions(+), 1 deletion(-)
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +38 -1
index b23536645ff7..96b0a0842ff5 100644
@@ -271,7 +271,9 @@ static void axi_dma_hw_init(struct axi_dma_chip *chip)
               axi_chan_irq_disable(&chip->dw->chan[i], DWAXIDMAC_IRQ_ALL);
               axi_chan_disable(&chip->dw->chan[i]);
       }
-     ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(64));
+
+     dev_dbg(chip->dev, "Adressable bus width: %u\n", chip->addressable_bits);
+     ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(chip->addressable_bits));
       if (ret)
               dev_warn(chip->dev, "Unable to set coherent mask\n");
  }
@@ -1461,13 +1463,24 @@ static int axi_req_irqs(struct platform_device *pdev, struct axi_dma_chip *chip)
       return 0;
  }
 
+/* Forward declaration (no size required) */
+static const struct of_device_id dw_dma_of_id_table[];
+
  static int dw_probe(struct platform_device *pdev)
  {
       struct axi_dma_chip *chip;
       struct dw_axi_dma *dw;
       struct dw_axi_dma_hcfg *hdata;
       struct reset_control *resets;
+     struct device_node *parent;
+     const struct of_device_id *match;
       unsigned int flags;
+     unsigned int addressable_bits = 64;
+     unsigned int len_bytes;
+     unsigned int num_cells;
+     const __be32 *prop;
+     u64 bus_width;
+     u32 *cells;
       u32 i;
       int ret;
 
@@ -1483,9 +1496,61 @@ static int dw_probe(struct platform_device *pdev)
       if (!hdata)
               return -ENOMEM;
 
+     match = of_match_node(dw_dma_of_id_table, pdev->dev.of_node);
+     if (!match) {
+             dev_err(&pdev->dev, "Unsupported AXI DMA device\n");
+             return -ENODEV;
+     }
+
+     parent = of_get_parent(pdev->dev.of_node);
+     if (parent) {
+             prop = of_get_property(parent, "dma-ranges", &len_bytes);
+             if (prop) {
+                     num_cells = len_bytes / sizeof(__be32);
+                     cells = kcalloc(num_cells, sizeof(*cells), GFP_KERNEL);
+                     if (!cells)
+                             return -ENOMEM;
+
+                     ret = of_property_read_u32(parent, "#address-cells", &i);
+                     if (ret) {
+                             dev_err(&pdev->dev, "missing #address-cells property\n");
+                             return ret;
+                     }
+
+                     ret = of_property_read_u32(parent, "#size-cells", &i);
+                     if (ret) {
+                             dev_err(&pdev->dev, "missing #size-cells property\n");
Quoted 8 lines

drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c static int dw_probe(struct platform_device *pdev) · line 1527

Quoted 5 lines
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +5 -0
+                             return ret;
+                     }
+
+                     if (!of_property_read_u32_array(parent, "dma-ranges",
+                                                     cells, num_cells)) {

We have common code to parse dma-ranges. Use it and don't implement your own.

Actually, the driver and DT core should take care of all this for you and there's nothing to do in the driver. A driver only needs to set the mask for the IP itself and only when >32 bits. The core takes care of any additional restrictions in the bus.

Quoted 7 lines
Quoted 1 line

Rob

The current implementation explicitly set the mask to 64.

- ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(64));

Will the core re-set the mask based on the dma-ranges on DT?

I don't think it changes the mask, but there's also bus ranges which get factored in. See struct device.bus_dma_limit and dma_range_map.

Rob

#10 lore raw

Re: [PATCH v3 3/3] dma: dw-axi-dmac: Add support for Agilex5 and dynamic bus width

Quoted 119 lines · Rob Herring
Quoted 117 lines · Khairul Anuar
Quoted 106 lines · Rob Herring
Quoted 96 lines · Rob Herring
Quoted 94 lines · Khairul Anuar Romli

Add device tree compatible string support for the Altera Agilex5 AXI DMA controller.

Introduces logic to parse the "dma-ranges" property and calculate the actual number of addressable bits (bus width) for the DMA engine. This calculated value is then used to set the coherent mask via 'dma_set_mask_and_coherent()', allowing the driver to correctly handle devices with bus widths less than 64 bits. The addressable bits default to 64 if 'dma-ranges' is not specified or cannot be parsed.

Introduce 'addressable_bits' to 'struct axi_dma_chip' to store this value.

---
Changes in v3:
- Refactor the code to align with dma controller device node move to 1 level down.
Changes in v2:
- Add driver implementation to set the DMA BIT MAST to 40 based on dma-ranges defined in DT.
- Add glue for driver and DT.

---
   .../dma/dw-axi-dmac/dw-axi-dmac-platform.c    | 69 ++++++++++++++++++-
   drivers/dma/dw-axi-dmac/dw-axi-dmac.h         |  1 +
   2 files changed, 69 insertions(+), 1 deletion(-)
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +38 -1
index b23536645ff7..96b0a0842ff5 100644
@@ -271,7 +271,9 @@ static void axi_dma_hw_init(struct axi_dma_chip *chip)
                axi_chan_irq_disable(&chip->dw->chan[i], DWAXIDMAC_IRQ_ALL);
                axi_chan_disable(&chip->dw->chan[i]);
        }
-     ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(64));
+
+     dev_dbg(chip->dev, "Adressable bus width: %u\n", chip->addressable_bits);
+     ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(chip->addressable_bits));
        if (ret)
                dev_warn(chip->dev, "Unable to set coherent mask\n");
   }
@@ -1461,13 +1463,24 @@ static int axi_req_irqs(struct platform_device *pdev, struct axi_dma_chip *chip)
        return 0;
   }
 
+/* Forward declaration (no size required) */
+static const struct of_device_id dw_dma_of_id_table[];
+
   static int dw_probe(struct platform_device *pdev)
   {
        struct axi_dma_chip *chip;
        struct dw_axi_dma *dw;
        struct dw_axi_dma_hcfg *hdata;
        struct reset_control *resets;
+     struct device_node *parent;
+     const struct of_device_id *match;
        unsigned int flags;
+     unsigned int addressable_bits = 64;
+     unsigned int len_bytes;
+     unsigned int num_cells;
+     const __be32 *prop;
+     u64 bus_width;
+     u32 *cells;
        u32 i;
        int ret;
 
@@ -1483,9 +1496,61 @@ static int dw_probe(struct platform_device *pdev)
        if (!hdata)
                return -ENOMEM;
 
+     match = of_match_node(dw_dma_of_id_table, pdev->dev.of_node);
+     if (!match) {
+             dev_err(&pdev->dev, "Unsupported AXI DMA device\n");
+             return -ENODEV;
+     }
+
+     parent = of_get_parent(pdev->dev.of_node);
+     if (parent) {
+             prop = of_get_property(parent, "dma-ranges", &len_bytes);
+             if (prop) {
+                     num_cells = len_bytes / sizeof(__be32);
+                     cells = kcalloc(num_cells, sizeof(*cells), GFP_KERNEL);
+                     if (!cells)
+                             return -ENOMEM;
+
+                     ret = of_property_read_u32(parent, "#address-cells", &i);
+                     if (ret) {
+                             dev_err(&pdev->dev, "missing #address-cells property\n");
+                             return ret;
+                     }
+
+                     ret = of_property_read_u32(parent, "#size-cells", &i);
+                     if (ret) {
+                             dev_err(&pdev->dev, "missing #size-cells property\n");
Quoted 8 lines

drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c static int dw_probe(struct platform_device *pdev) · line 1527

Quoted 5 lines
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +5 -0
+                             return ret;
+                     }
+
+                     if (!of_property_read_u32_array(parent, "dma-ranges",
+                                                     cells, num_cells)) {

We have common code to parse dma-ranges. Use it and don't implement your own.

Quoted 6 lines

Actually, the driver and DT core should take care of all this for you and there's nothing to do in the driver. A driver only needs to set the mask for the IP itself and only when >32 bits. The core takes care of any additional restrictions in the bus.

Rob

The current implementation explicitly set the mask to 64.

Quoted 8 lines
Quoted 3 lines

- ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(64));

Will the core re-set the mask based on the dma-ranges on DT?

I don't think it changes the mask, but there's also bus ranges which get factored in. See struct device.bus_dma_limit and dma_range_map.

Rob

Yes, you're right. the core didn't change the mask that are set from the driver. I will send the next revision to use common code to get the dma-ranges and set dma_set_mask_and_coherent accordingly.

Thanks.

Best Regards,
Khairul