Devicetree
 help / color / mirror / Atom feed
* [PATCH 2/2] arm64: dts: imx952: Describe Mali G310 GPU
From: Guangliu Ding @ 2026-03-31 10:12 UTC (permalink / raw)
  To: Daniel Almeida, Alice Ryhl, Boris Brezillon, Steven Price,
	Liviu Dudau, David Airlie, Simona Vetter, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam
  Cc: dri-devel, devicetree, linux-kernel, imx, linux-arm-kernel,
	Guangliu Ding, Jiyu Yang
In-Reply-To: <20260331-master-v1-0-65c8e318d462@nxp.com>

Support Mali G310 GPU on i.MX952 board. Describe this GPU in the DT.
Include dummy GPU voltage regulator and OPP tables.

Signed-off-by: Guangliu Ding <guangliu.ding@nxp.com>
Reviewed-by: Jiyu Yang <jiyu.yang@nxp.com>
---
 arch/arm64/boot/dts/freescale/imx952.dtsi | 36 +++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx952.dtsi b/arch/arm64/boot/dts/freescale/imx952.dtsi
index 91fe4916ac04..0bd3e7fc0674 100644
--- a/arch/arm64/boot/dts/freescale/imx952.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx952.dtsi
@@ -318,6 +318,28 @@ usbphynop2: usbphynop2 {
 		clock-names = "main_clk";
 	};
 
+	gpu_opp_table: opp-table {
+		compatible = "operating-points-v2";
+
+		opp-500000000 {
+			opp-hz = /bits/ 64 <500000000>;
+			opp-hz-real = /bits/ 64 <500000000>;
+			opp-microvolt = <920000>;
+		};
+
+		opp-800000000 {
+			opp-hz = /bits/ 64 <800000000>;
+			opp-hz-real = /bits/ 64 <800000000>;
+			opp-microvolt = <920000>;
+		};
+
+		opp-1000000000 {
+			opp-hz = /bits/ 64 <1000000000>;
+			opp-hz-real = /bits/ 64 <1000000000>;
+			opp-microvolt = <920000>;
+		};
+	};
+
 	soc {
 		compatible = "simple-bus";
 		#address-cells = <2>;
@@ -1262,5 +1284,19 @@ usbmisc2: usbmisc@4c200200 {
 			reg = <0x0 0x4c200200 0x0 0x200>,
 			      <0x0 0x4c010014 0x0 0x4>;
 		};
+
+		gpu: gpu@4d900000 {
+			compatible = "nxp,imx952-mali", "arm,mali-valhall-csf";
+			reg = <0 0x4d900000 0 0x480000>;
+			interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 289 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "gpu", "job", "mmu";
+			clocks = <&scmi_clk IMX952_CLK_GPU>;
+			clock-names = "core";
+			power-domains = <&scmi_devpd IMX952_PD_GPU>;
+			operating-points-v2 = <&gpu_opp_table>;
+			dynamic-power-coefficient = <1013>;
+		};
 	};
 };

-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH 04/12] i3c: master: Support ACPI enumeration
From: Akhil R @ 2026-03-31 10:09 UTC (permalink / raw)
  To: thierry.reding
  Cc: Frank.Li, acpica-devel, akhilrajeev, alexandre.belloni, conor+dt,
	devicetree, ebiggers, fredrik.markstrom, jonathanh, krzk, lenb,
	linux-acpi, linux-hwmon, linux-i3c, linux-kernel, linux-tegra,
	linux, lkp, llvm, miquel.raynal, oe-kbuild-all, p.zabel, rafael,
	robert.moore, robh
In-Reply-To: <acO_PUjS_VG07qcS@orome>

On Wed, 25 Mar 2026 11:59:12 +0100, Thierry Reding wrote:
> On Tue, Mar 24, 2026 at 10:52:15PM +0530, Akhil R wrote:
>> On Tue, 24 Mar 2026 09:43:27 +0100, Alexandre Belloni wrote:
>> 
>> ...
>> 
>> >> #include <linux/acpi.h> is added in PATCH 03/12. The functions' prototypes
>> >> are present in acpi.h. I think the bot checked this patch individually,
>> >> or did I miss something?
>> >> 
>> > 
>> > #include <acpi/acpi_bus.h> is behind an #ifdef in acpi.h and your code
>> > is not.
>> 
>> Thanks for pointing Alexandre and Guenter. I also noticed that we do not
>> have stub functions for a few of the acpi_* functions in #else.
>> 
>> Looks like I will have to guard calls to these functions under
>> #ifdef CONFIG_ACPI.
> 
> Alternatively it might make sense to add the stubs in a separate patch.
> I don't know if they were purposefully left out or nobody's ever run
> into the lack of these before.

I looked into this and it turns out to be more involved than expected,
and requires adding stubs at multiple layers. We may end up either
sneaking in only what we require or a non-trivial change which may
involve too many parameters.

If you would agree, I will guard the ACPI calls used in this patchset with
#ifdef CONFIG_ACPI to keep things self-contained. If you think adding the
stubs is worthwhile, we can take them up as a separate series.

Best Regards,
Akhil

^ permalink raw reply

* Re: [PATCH v2 2/2] mfd: tps65219: Make poweroff handler conditional on system-power-controller
From: Lee Jones @ 2026-03-31 10:12 UTC (permalink / raw)
  To: Akashdeep Kaur
  Cc: praneeth, nm, afd, vigneshr, kristo, robh, krzk+dt, conor+dt,
	aaro.koskinen, andreas, khilman, rogerq, tony, linux-arm-kernel,
	devicetree, linux-kernel, linux-omap, s-ramamoorthy, vishalm,
	sebin.francis, d-gole, k-willis
In-Reply-To: <20260324101419.95616-3-a-kaur@ti.com>

---

On Tue, 24 Mar 2026, Akashdeep Kaur wrote:

> Currently, the TPS65219 driver unconditionally registers a poweroff
> handler. This causes issues on systems where a different component
> (such as TF-A firmware) should handle system poweroff instead.
> 
> Make the poweroff handler registration conditional based on the
> "system-power-controller" device tree property. This follows the
> standard kernel pattern where only the designated power controller
> registers for system poweroff operations.
> 
> On systems where the property is absent, the PMIC will not register
> a poweroff handler, allowing other poweroff mechanisms to function.
> 
> Signed-off-by: Akashdeep Kaur <a-kaur@ti.com>
> ---
>  drivers/mfd/tps65219.c | 14 ++++++++------
>  1 file changed, 8 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/mfd/tps65219.c b/drivers/mfd/tps65219.c
> index 7275dcdb7c44..6fa202339a0c 100644
> --- a/drivers/mfd/tps65219.c
> +++ b/drivers/mfd/tps65219.c
> @@ -541,13 +541,15 @@ static int tps65219_probe(struct i2c_client *client)
>  		return ret;
>  	}
>  
> -	ret = devm_register_power_off_handler(tps->dev,
> -					      tps65219_power_off_handler,
> -					      tps);
> -	if (ret) {
> -		dev_err(tps->dev, "failed to register power-off handler: %d\n", ret);
> -		return ret;
> +	if (of_device_is_system_power_controller(tps->dev->of_node)) {
> +		ret = devm_register_power_off_handler(tps->dev,
> +						      tps65219_power_off_handler,
> +						      tps);
> +		if (ret)
> +			return dev_err_probe(tps->dev, ret,
> +					"failed to register power-off handler\n");

Couple of nits to fix.

The `"` should be aligned with the `(` and the `failed` should be capitalised.

>  	}
> +
>  	return 0;
>  }
>  
> -- 
> 2.34.1
> 

-- 
Lee Jones [李琼斯]

^ permalink raw reply

* Re: [PATCH v8 01/10] dt-bindings: mfd: add support for the NXP SIUL2 module
From: Arnd Bergmann @ 2026-03-31 10:11 UTC (permalink / raw)
  To: Khristine Andreea Barbulescu, Krzysztof Kozlowski,
	Ghennadi Procopciuc
  Cc: Linus Walleij, Bartosz Golaszewski, Krzysztof Kozlowski,
	Conor Dooley, Chester Lin, Matthias Brugger, Ghennadi Procopciuc,
	Larisa Grigore, Lee Jones, Shawn Guo, Sascha Hauer, Fabio Estevam,
	Aisheng Dong, Jacky Bai, Greg Kroah-Hartman, Rafael J . Wysocki,
	Alberto Ruiz, Christophe Lizzi, devicetree, Enric Balletbo,
	Eric Chanudet, imx, linux-arm-kernel, open list:GPIO SUBSYSTEM,
	linux-kernel, NXP S32 Linux Team, Pengutronix Kernel Team,
	Vincent Guittot, Rob Herring
In-Reply-To: <4c46909d-641b-4389-bc4a-29394cb1d46d@oss.nxp.com>

On Tue, Mar 31, 2026, at 09:48, Khristine Andreea Barbulescu wrote:
> 
> With the current layout, the SIUL2 node itself now contains the two
> MMIO ranges directly, while the remaining child node is only the
> pinctrl/GPIO function.

The thread started by saying this is an MFD "It can export information
about the SoC, configure the pinmux&pinconf for pins and it is also
a GPIO controller with interrupt capability." Having a combined
pinctrl/gpio/irqchip driver is normal, but can you clarify what
you plan to do with the "information about the SoC" part?

Was this a "soc_device" driver, or something else? Have you
concluded now that this is not going to be needed at all?
In that case, I guess having a monolithic driver is
indeed simpler than an MFD.

What I wonder about then is whether the binding needs to be changed
at all. With the current nxp,s32g2-siul2-pinctrl.yaml binding
and pinctrl-s32g2.c implementation, you seem to have a monolithic
device already, though missing the gpio functionality. Rather
than completely replacing this, I assume the easiest way then
would be to add the PGPD registers into this device node, right?

It is still a bit weird to list the individual register areas
inside of the larger device here, but that still seems better
than an incompatible binding change.

    Arnd

^ permalink raw reply

* [PATCH 0/2] Fix active-low handling of MIPI CSI resets on i.MX8MQ
From: Robby Cai @ 2026-03-31 10:13 UTC (permalink / raw)
  To: p.zabel, robh, krzk+dt, conor+dt, Frank.Li, s.hauer, festevam
  Cc: devicetree, kernel, imx, linux-arm-kernel, linux-kernel,
	aisheng.dong

Hi all,

This series updates the Device Tree bindings and reset controller driver
to correctly reflect the active-low polarity of the MIPI CSI reset lines
on i.MX8MQ.

The MIPI CSI reset signals are active-low, but the original reset
identifiers and driver implementation did not clearly indicate or handle
this polarity. Patch 1 updates the DT binding header to add *_RESET_N
variants for the MIPI CSI reset definitions, while keeping the old names
temporarily for DT ABI compatibility. Patch 2 updates the imx7 reset
controller driver to correctly treat these resets as active-low.



Thanks,
Robby

Robby Cai (2):
  dt-bindings: reset: imx8mq: Add _N suffix to
    IMX8MQ_RESET_MIPI_CSI*_RESET
  reset: imx7: Fix handling of MIPI CSI resets on i.MX8MQ

 drivers/reset/reset-imx7.c               | 18 ++++++++++++------
 include/dt-bindings/reset/imx8mq-reset.h | 18 ++++++++++++------
 2 files changed, 24 insertions(+), 12 deletions(-)

-- 
2.37.1


^ permalink raw reply

* [PATCH 1/2] dt-bindings: reset: imx8mq: Add _N suffix to IMX8MQ_RESET_MIPI_CSI*_RESET
From: Robby Cai @ 2026-03-31 10:13 UTC (permalink / raw)
  To: p.zabel, robh, krzk+dt, conor+dt, Frank.Li, s.hauer, festevam
  Cc: devicetree, kernel, imx, linux-arm-kernel, linux-kernel,
	aisheng.dong
In-Reply-To: <20260331101331.1405588-1-robby.cai@nxp.com>

The assert logic of the MIPI CSI reset signals is active-low on i.MX8MQ,
but the existing names do not indicate this explicitly. To improve
consistency and clarity, append the _N suffix to all
IMX8MQ_RESET_MIPI_CSI*_RESET definitions. The deprecated
IMX8MQ_RESET_MIPI_CSI*_RESET versions remain temporarily for DT ABI
compatibility and will be removed at an appropriate time in the future.

Signed-off-by: Robby Cai <robby.cai@nxp.com>
---
 include/dt-bindings/reset/imx8mq-reset.h | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/include/dt-bindings/reset/imx8mq-reset.h b/include/dt-bindings/reset/imx8mq-reset.h
index 705870693ec2..83a155dbbd4a 100644
--- a/include/dt-bindings/reset/imx8mq-reset.h
+++ b/include/dt-bindings/reset/imx8mq-reset.h
@@ -46,12 +46,18 @@
 #define IMX8MQ_RESET_PCIEPHY2_PERST		35	/* i.MX8MM/i.MX8MN does NOT support */
 #define IMX8MQ_RESET_PCIE2_CTRL_APPS_EN		36	/* i.MX8MM/i.MX8MN does NOT support */
 #define IMX8MQ_RESET_PCIE2_CTRL_APPS_TURNOFF	37	/* i.MX8MM/i.MX8MN does NOT support */
-#define IMX8MQ_RESET_MIPI_CSI1_CORE_RESET	38	/* i.MX8MM/i.MX8MN does NOT support */
-#define IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET	39	/* i.MX8MM/i.MX8MN does NOT support */
-#define IMX8MQ_RESET_MIPI_CSI1_ESC_RESET	40	/* i.MX8MM/i.MX8MN does NOT support */
-#define IMX8MQ_RESET_MIPI_CSI2_CORE_RESET	41	/* i.MX8MM/i.MX8MN does NOT support */
-#define IMX8MQ_RESET_MIPI_CSI2_PHY_REF_RESET	42	/* i.MX8MM/i.MX8MN does NOT support */
-#define IMX8MQ_RESET_MIPI_CSI2_ESC_RESET	43	/* i.MX8MM/i.MX8MN does NOT support */
+#define IMX8MQ_RESET_MIPI_CSI1_CORE_RESET	38	/* Deprecated. Use *_RESET_N instead */
+#define IMX8MQ_RESET_MIPI_CSI1_CORE_RESET_N	38	/* i.MX8MM/i.MX8MN does NOT support */
+#define IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET	39	/* Deprecated. Use *_RESET_N instead */
+#define IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET_N	39	/* i.MX8MM/i.MX8MN does NOT support */
+#define IMX8MQ_RESET_MIPI_CSI1_ESC_RESET	40	/* Deprecated. Use *_RESET_N instead */
+#define IMX8MQ_RESET_MIPI_CSI1_ESC_RESET_N	40	/* i.MX8MM/i.MX8MN does NOT support */
+#define IMX8MQ_RESET_MIPI_CSI2_CORE_RESET	41	/* Deprecated. Use *_RESET_N instead */
+#define IMX8MQ_RESET_MIPI_CSI2_CORE_RESET_N	41	/* i.MX8MM/i.MX8MN does NOT support */
+#define IMX8MQ_RESET_MIPI_CSI2_PHY_REF_RESET	42	/* Deprecated. Use *_RESET_N instead */
+#define IMX8MQ_RESET_MIPI_CSI2_PHY_REF_RESET_N	42	/* i.MX8MM/i.MX8MN does NOT support */
+#define IMX8MQ_RESET_MIPI_CSI2_ESC_RESET	43	/* Deprecated. Use *_RESET_N instead */
+#define IMX8MQ_RESET_MIPI_CSI2_ESC_RESET_N	43	/* i.MX8MM/i.MX8MN does NOT support */
 #define IMX8MQ_RESET_DDRC1_PRST			44	/* i.MX8MN does NOT support */
 #define IMX8MQ_RESET_DDRC1_CORE_RESET		45	/* i.MX8MN does NOT support */
 #define IMX8MQ_RESET_DDRC1_PHY_RESET		46	/* i.MX8MN does NOT support */
-- 
2.37.1


^ permalink raw reply related

* [PATCH 2/2] reset: imx7: Fix handling of MIPI CSI resets on i.MX8MQ
From: Robby Cai @ 2026-03-31 10:13 UTC (permalink / raw)
  To: p.zabel, robh, krzk+dt, conor+dt, Frank.Li, s.hauer, festevam
  Cc: devicetree, kernel, imx, linux-arm-kernel, linux-kernel,
	aisheng.dong
In-Reply-To: <20260331101331.1405588-1-robby.cai@nxp.com>

The MIPI CSI reset signals on i.MX8MQ are active-low, but the reset
controller driver previously treated them as active-high, resulting in
incorrect assert/deassert behavior. Update the reset handling logic to
correctly process these active-low reset lines.

Signed-off-by: Robby Cai <robby.cai@nxp.com>
---
 drivers/reset/reset-imx7.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c
index dd01fe11c5cb..b7048e1f10df 100644
--- a/drivers/reset/reset-imx7.c
+++ b/drivers/reset/reset-imx7.c
@@ -202,12 +202,12 @@ static const struct imx7_src_signal imx8mq_src_signals[IMX8MQ_RESET_NUM] = {
 	[IMX8MQ_RESET_PCIEPHY2_PERST]		= { SRC_PCIE2_RCR, BIT(3) },
 	[IMX8MQ_RESET_PCIE2_CTRL_APPS_EN]	= { SRC_PCIE2_RCR, BIT(6) },
 	[IMX8MQ_RESET_PCIE2_CTRL_APPS_TURNOFF]	= { SRC_PCIE2_RCR, BIT(11) },
-	[IMX8MQ_RESET_MIPI_CSI1_CORE_RESET]	= { SRC_MIPIPHY1_RCR, BIT(0) },
-	[IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET]	= { SRC_MIPIPHY1_RCR, BIT(1) },
-	[IMX8MQ_RESET_MIPI_CSI1_ESC_RESET]	= { SRC_MIPIPHY1_RCR, BIT(2) },
-	[IMX8MQ_RESET_MIPI_CSI2_CORE_RESET]	= { SRC_MIPIPHY2_RCR, BIT(0) },
-	[IMX8MQ_RESET_MIPI_CSI2_PHY_REF_RESET]	= { SRC_MIPIPHY2_RCR, BIT(1) },
-	[IMX8MQ_RESET_MIPI_CSI2_ESC_RESET]	= { SRC_MIPIPHY2_RCR, BIT(2) },
+	[IMX8MQ_RESET_MIPI_CSI1_CORE_RESET_N]	= { SRC_MIPIPHY1_RCR, BIT(0) },
+	[IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET_N] = { SRC_MIPIPHY1_RCR, BIT(1) },
+	[IMX8MQ_RESET_MIPI_CSI1_ESC_RESET_N]	= { SRC_MIPIPHY1_RCR, BIT(2) },
+	[IMX8MQ_RESET_MIPI_CSI2_CORE_RESET_N]	= { SRC_MIPIPHY2_RCR, BIT(0) },
+	[IMX8MQ_RESET_MIPI_CSI2_PHY_REF_RESET_N] = { SRC_MIPIPHY2_RCR, BIT(1) },
+	[IMX8MQ_RESET_MIPI_CSI2_ESC_RESET_N]	= { SRC_MIPIPHY2_RCR, BIT(2) },
 	[IMX8MQ_RESET_DDRC1_PRST]		= { SRC_DDRC_RCR, BIT(0) },
 	[IMX8MQ_RESET_DDRC1_CORE_RESET]		= { SRC_DDRC_RCR, BIT(1) },
 	[IMX8MQ_RESET_DDRC1_PHY_RESET]		= { SRC_DDRC_RCR, BIT(2) },
@@ -236,6 +236,12 @@ static int imx8mq_reset_set(struct reset_controller_dev *rcdev,
 
 	case IMX8MQ_RESET_PCIE_CTRL_APPS_EN:
 	case IMX8MQ_RESET_PCIE2_CTRL_APPS_EN:
+	case IMX8MQ_RESET_MIPI_CSI1_CORE_RESET_N:
+	case IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET_N:
+	case IMX8MQ_RESET_MIPI_CSI1_ESC_RESET_N:
+	case IMX8MQ_RESET_MIPI_CSI2_CORE_RESET_N:
+	case IMX8MQ_RESET_MIPI_CSI2_PHY_REF_RESET_N:
+	case IMX8MQ_RESET_MIPI_CSI2_ESC_RESET_N:
 	case IMX8MQ_RESET_MIPI_DSI_PCLK_RESET_N:
 	case IMX8MQ_RESET_MIPI_DSI_ESC_RESET_N:
 	case IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N:
-- 
2.37.1


^ permalink raw reply related

* Re: [PATCH V3 1/3] net: stmmac: Fix PTP ref clock for Tegra234
From: Jon Hunter @ 2026-03-31 10:14 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Thierry Reding, netdev, devicetree, linux-tegra
In-Reply-To: <20260326-gigantic-tentacled-hornet-cbdb8d@quoll>


On 26/03/2026 08:32, Krzysztof Kozlowski wrote:

...

>> @@ -257,9 +258,23 @@ static int tegra_mgbe_probe(struct platform_device *pdev)
>>   	if (!mgbe->clks)
>>   		return -ENOMEM;
>>   
>> -	for (i = 0; i <  ARRAY_SIZE(mgbe_clks); i++)
>> +	/*
>> +	 * Older device-trees use 'ptp-ref' rather than 'ptp_ref'.
>> +	 * Fall back to the legacy name when 'ptp_ref' is absent.
>> +	 */
>> +	use_legacy_ptp = of_property_match_string(pdev->dev.of_node,
>> +						  "clock-names", "ptp_ref") < 0;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(mgbe_clks); i++) {
>>   		mgbe->clks[i].id = mgbe_clks[i];
>>   
>> +		if (use_legacy_ptp && !strcmp(mgbe_clks[i], "ptp_ref")) {
> 
> Why index 0 is not valid? And why -EINVAL would be considered as legacy
> clock present?

Index 0 is valid. However, yes I guess that treating an -EINVAL from 
of_property_match_string() is not correct. I will switch the logic to be ...

  use_legacy_ptp = of_property_match_string(pdev->dev.of_node,
                                    "clock-names", "ptp-ref") >= 0;

Jon

-- 
nvpublic


^ permalink raw reply

* Re: [PATCH v4 1/9] dt-bindings: mfd: mt6397: Add MT6392 PMIC
From: Chen-Yu Tsai @ 2026-03-31 10:15 UTC (permalink / raw)
  To: Luca Leonardo Scorcia
  Cc: Krzysztof Kozlowski, linux-mediatek, Fabien Parent, Val Packett,
	Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Matthias Brugger,
	AngeloGioacchino Del Regno, Linus Walleij, Liam Girdwood,
	Mark Brown, Louis-Alexis Eyraud, Gary Bisson, Julien Massot,
	Chen Zhong, linux-input, devicetree, linux-kernel, linux-pm,
	linux-arm-kernel, linux-gpio
In-Reply-To: <CAORyz2+1bc9Z-opoNqyUU_WFzyXZKGQmR_Ur=4UonOC=AWtQ8w@mail.gmail.com>

On Tue, Mar 31, 2026 at 4:36 PM Luca Leonardo Scorcia
<l.scorcia@gmail.com> wrote:
>
> > > -    required:
> > > -      - compatible
> >
> > Not really, this affects existing ABI and might make the child schema
> > being applied. Basically regulators node can be anything now.
> >
> > This is definitely not a binding we want. The syntax for parent schema
> > when listing only compatibles is requiring this compatible. You cannot
> > have here whatever empty node.
>
> Hi, it felt quite strange to me too, but that's what I thought you
> meant with your previous suggestion [1].
> To keep the required attribute I would be happy to reintroduce the
> compatible here, in the regulator schema and the pmic dtsi.
>
> Before I do that and resubmit, could you please help me understand
> what you meant before?

I think the point is that compatibles for regulator sub-nodes on MFDs
is no longer accepted.

Instead if you want to have a separate binding for the regulator part,
you would need to reference the binding directly.

Say the binding is at bindings/regulator/mt6392.yaml, in this patch
you would have something after the "additionalProperties: false" like:

allOf:
  - if:
      properties:
        "compatible":
          contains:
            const: mediatek,mt6392
    then:
      properties:
        regulators:
          $ref: /schemas/regulator/mt6392.yaml
    else:
      properties:
        regulators:
          required:
            - compatible

And drop the "required: - compatible" part from the common regulator
node bits of the binding.


ChenYu

> Thank you!
>
> [1] https://lists.infradead.org/pipermail/linux-mediatek/2026-March/105060.html
> --
> Luca Leonardo Scorcia
> l.scorcia@gmail.com
>

^ permalink raw reply

* Re: [PATCH V3 1/3] net: stmmac: Fix PTP ref clock for Tegra234
From: Krzysztof Kozlowski @ 2026-03-31 10:18 UTC (permalink / raw)
  To: Jon Hunter
  Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Thierry Reding, netdev, devicetree, linux-tegra
In-Reply-To: <01f56e6f-5459-4a96-9042-8a003a340fab@nvidia.com>

On 31/03/2026 12:14, Jon Hunter wrote:
> 
> On 26/03/2026 08:32, Krzysztof Kozlowski wrote:
> 
> ...
> 
>>> @@ -257,9 +258,23 @@ static int tegra_mgbe_probe(struct platform_device *pdev)
>>>   	if (!mgbe->clks)
>>>   		return -ENOMEM;
>>>   
>>> -	for (i = 0; i <  ARRAY_SIZE(mgbe_clks); i++)
>>> +	/*
>>> +	 * Older device-trees use 'ptp-ref' rather than 'ptp_ref'.
>>> +	 * Fall back to the legacy name when 'ptp_ref' is absent.
>>> +	 */
>>> +	use_legacy_ptp = of_property_match_string(pdev->dev.of_node,
>>> +						  "clock-names", "ptp_ref") < 0;
>>> +
>>> +	for (i = 0; i < ARRAY_SIZE(mgbe_clks); i++) {
>>>   		mgbe->clks[i].id = mgbe_clks[i];
>>>   
>>> +		if (use_legacy_ptp && !strcmp(mgbe_clks[i], "ptp_ref")) {
>>
>> Why index 0 is not valid? And why -EINVAL would be considered as legacy
>> clock present?
> 
> Index 0 is valid. However, yes I guess that treating an -EINVAL from 
> of_property_match_string() is not correct. I will switch the logic to be ...
> 
>   use_legacy_ptp = of_property_match_string(pdev->dev.of_node,
>                                     "clock-names", "ptp-ref") >= 0;

No, apologies, I think my comment was not correct and your reply made me
rethink. I missed final "< 0" in of_property_match_string().

So the code is good, you do not store index in 'use_legacy_ptp', but the
error return value.

Can you however make it more obvious code, so something like:

if (of_property_match_string...))
	use_legacy_ptp = true;;



Best regards,
Krzysztof

^ permalink raw reply

* [PATCH v6 00/10] Add GPCDMA support in Tegra264
From: Akhil R @ 2026-03-31 10:22 UTC (permalink / raw)
  To: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
	Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
  Cc: Akhil R

This series adds support for GPCDMA in Tegra264 with additional
support for separate stream ID for each channel. Tegra264 GPCDMA
controller has changes in the register offsets and uses 41-bit
addressing for memory. Add changes in the tegra186-gpc-dma driver
to support these.

v5->v6:
- Replace dev_err() with dev_err_probe() in the probe function for fixed
  return values also.
v4->v5:
- Use dev_err_probe() when returning error from the probe function.
- Remove tegra194 and tegra234 compatible from the reset 'if' condition
  in the bindings as suggested in v2 (which I missed).
v3->v4:
- Split device tree changes to two patches.
- Reordered patches to have fixes first.
- Added fixes tag to dt-bindings and device tree changes.
v2->v3:
- Add description for iommu-map property and update commit descriptions.
- Use enum for compatible string instead of const.
- Remove unused registers from struct tegra_dma_channel_regs.
- Use devm_of_dma_controller_register() to register the DMA controller.
- Remove return value check for mask setting in the driver as the bitmask
  value is always greater than 32.
v1->v2:
- Fix dt_bindings_check warnings
- Drop fallback compatible "nvidia,tegra186-gpcdma" from Tegra264 DT
- Use dma_addr_t for sg_req src/dst fields and drop separate high_add
  variable and check for the addr_bits only when programming the
  registers.
- Update address width to 39 bits for Tegra234 and before since the SMMU
  supports only up to 39 bits till Tegra234.
- Add a patch to do managed DMA controller registration.
- Describe the second iteration in the probe.
- Update commit descriptions.

Akhil R (10):
  dt-bindings: dma: nvidia,tegra186-gpc-dma: Make reset optional
  arm64: tegra: Remove fallback compatible for GPCDMA
  dt-bindings: dma: nvidia,tegra186-gpc-dma: Add iommu-map property
  dmaengine: tegra: Make reset control optional
  dmaengine: tegra: Use struct for register offsets
  dmaengine: tegra: Support address width > 39 bits
  dmaengine: tegra: Use managed DMA controller registration
  dmaengine: tegra: Use iommu-map for stream ID
  dmaengine: tegra: Add Tegra264 support
  arm64: tegra: Enable GPCDMA in Tegra264 and add iommu-map

 .../bindings/dma/nvidia,tegra186-gpc-dma.yaml |  32 +-
 .../arm64/boot/dts/nvidia/tegra264-p3834.dtsi |   4 +
 arch/arm64/boot/dts/nvidia/tegra264.dtsi      |   3 +-
 drivers/dma/tegra186-gpc-dma.c                | 429 +++++++++++-------
 4 files changed, 284 insertions(+), 184 deletions(-)

-- 
2.50.1


^ permalink raw reply

* [PATCH v6 01/10] dt-bindings: dma: nvidia,tegra186-gpc-dma: Make reset optional
From: Akhil R @ 2026-03-31 10:22 UTC (permalink / raw)
  To: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
	Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
  Cc: Akhil R
In-Reply-To: <20260331102303.33181-1-akhilrajeev@nvidia.com>

On Tegra264, GPCDMA reset control is not exposed to Linux and is handled
by the boot firmware.

Although reset was not exposed in Tegra234 as well, the firmware supported
a dummy reset which just returns success on reset without doing an actual
reset. This is also not supported in Tegra264 BPMP. Therefore mark 'reset'
and 'reset-names' properties as required only for devices prior to
Tegra264.

This also necessitates that the Tegra264 compatible be standalone and
cannot have the fallback compatible of Tegra186. Since there is no
functional impact, we keep reset as required for Tegra234 to avoid
breaking the ABI.

Fixes: bb8c97571db5 ("dt-bindings: dma: Add Tegra264 compatible string")
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
---
 .../bindings/dma/nvidia,tegra186-gpc-dma.yaml | 23 +++++++++++++------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/dma/nvidia,tegra186-gpc-dma.yaml b/Documentation/devicetree/bindings/dma/nvidia,tegra186-gpc-dma.yaml
index 0dabe9bbb219..64f1e9d9896d 100644
--- a/Documentation/devicetree/bindings/dma/nvidia,tegra186-gpc-dma.yaml
+++ b/Documentation/devicetree/bindings/dma/nvidia,tegra186-gpc-dma.yaml
@@ -15,16 +15,14 @@ maintainers:
   - Jon Hunter <jonathanh@nvidia.com>
   - Rajesh Gumasta <rgumasta@nvidia.com>
 
-allOf:
-  - $ref: dma-controller.yaml#
-
 properties:
   compatible:
     oneOf:
-      - const: nvidia,tegra186-gpcdma
+      - enum:
+          - nvidia,tegra264-gpcdma
+          - nvidia,tegra186-gpcdma
       - items:
           - enum:
-              - nvidia,tegra264-gpcdma
               - nvidia,tegra234-gpcdma
               - nvidia,tegra194-gpcdma
           - const: nvidia,tegra186-gpcdma
@@ -60,12 +58,23 @@ required:
   - compatible
   - reg
   - interrupts
-  - resets
-  - reset-names
   - "#dma-cells"
   - iommus
   - dma-channel-mask
 
+allOf:
+  - $ref: dma-controller.yaml#
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - nvidia,tegra186-gpcdma
+    then:
+      required:
+        - resets
+        - reset-names
+
 additionalProperties: false
 
 examples:
-- 
2.50.1


^ permalink raw reply related

* [PATCH v6 02/10] arm64: tegra: Remove fallback compatible for GPCDMA
From: Akhil R @ 2026-03-31 10:22 UTC (permalink / raw)
  To: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
	Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
  Cc: Akhil R
In-Reply-To: <20260331102303.33181-1-akhilrajeev@nvidia.com>

Remove the fallback compatible string "nvidia,tegra186-gpcdma" for GPCDMA
in Tegra264. Tegra186 compatible cannot work on Tegra264 because of the
register offset changes and absence of the reset property.

Fixes: 65ef237e4810 ("arm64: tegra: Add Tegra264 support")
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra264.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra264.dtsi b/arch/arm64/boot/dts/nvidia/tegra264.dtsi
index 24cc2c51a272..af077420d7d9 100644
--- a/arch/arm64/boot/dts/nvidia/tegra264.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra264.dtsi
@@ -3208,7 +3208,7 @@ agic_page5: interrupt-controller@99b0000 {
 		};
 
 		gpcdma: dma-controller@8400000 {
-			compatible = "nvidia,tegra264-gpcdma", "nvidia,tegra186-gpcdma";
+			compatible = "nvidia,tegra264-gpcdma";
 			reg = <0x0 0x08400000 0x0 0x210000>;
 			interrupts = <GIC_SPI 584 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 585 IRQ_TYPE_LEVEL_HIGH>,
-- 
2.50.1


^ permalink raw reply related

* [PATCH v6 04/10] dmaengine: tegra: Make reset control optional
From: Akhil R @ 2026-03-31 10:22 UTC (permalink / raw)
  To: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
	Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
  Cc: Akhil R, Frank Li
In-Reply-To: <20260331102303.33181-1-akhilrajeev@nvidia.com>

On Tegra264, reset is not available for the driver to control as
this is handled by the boot firmware. Hence make the reset control
optional and update the error message to reflect the correct error.

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/dma/tegra186-gpc-dma.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
index 5948fbf32c21..a0522a992ebc 100644
--- a/drivers/dma/tegra186-gpc-dma.c
+++ b/drivers/dma/tegra186-gpc-dma.c
@@ -1381,10 +1381,10 @@ static int tegra_dma_probe(struct platform_device *pdev)
 	if (IS_ERR(tdma->base_addr))
 		return PTR_ERR(tdma->base_addr);
 
-	tdma->rst = devm_reset_control_get_exclusive(&pdev->dev, "gpcdma");
+	tdma->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, "gpcdma");
 	if (IS_ERR(tdma->rst)) {
 		return dev_err_probe(&pdev->dev, PTR_ERR(tdma->rst),
-			      "Missing controller reset\n");
+			      "Failed to get controller reset\n");
 	}
 	reset_control_reset(tdma->rst);
 
-- 
2.50.1


^ permalink raw reply related

* [PATCH v6 03/10] dt-bindings: dma: nvidia,tegra186-gpc-dma: Add iommu-map property
From: Akhil R @ 2026-03-31 10:22 UTC (permalink / raw)
  To: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
	Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
  Cc: Akhil R
In-Reply-To: <20260331102303.33181-1-akhilrajeev@nvidia.com>

Add iommu-map property to specify separate stream IDs for each DMA
channel. This enables each channel to be in its own IOMMU domain,
keeping memory isolated from other devices sharing the same DMA
controller.

Define the constraints such that if the channel and stream IDs are
contiguous, a single entry can map all the channels, but if the
channels or stream IDs are non-contiguous support multiple entries.

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
---
 .../devicetree/bindings/dma/nvidia,tegra186-gpc-dma.yaml | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/Documentation/devicetree/bindings/dma/nvidia,tegra186-gpc-dma.yaml b/Documentation/devicetree/bindings/dma/nvidia,tegra186-gpc-dma.yaml
index 64f1e9d9896d..bc093c783d98 100644
--- a/Documentation/devicetree/bindings/dma/nvidia,tegra186-gpc-dma.yaml
+++ b/Documentation/devicetree/bindings/dma/nvidia,tegra186-gpc-dma.yaml
@@ -14,6 +14,7 @@ description: |
 maintainers:
   - Jon Hunter <jonathanh@nvidia.com>
   - Rajesh Gumasta <rgumasta@nvidia.com>
+  - Akhil R <akhilrajeev@nvidia.com>
 
 properties:
   compatible:
@@ -49,6 +50,14 @@ properties:
   iommus:
     maxItems: 1
 
+  iommu-map:
+    description:
+      Maps DMA channel numbers to IOMMU stream IDs. A single entry can map all
+      channels when stream IDs are contiguous. In systems where the channels or
+      stream IDs are not contiguous, multiple entries may be needed.
+    minItems: 1
+    maxItems: 32
+
   dma-coherent: true
 
   dma-channel-mask:
-- 
2.50.1


^ permalink raw reply related

* [PATCH v6 05/10] dmaengine: tegra: Use struct for register offsets
From: Akhil R @ 2026-03-31 10:22 UTC (permalink / raw)
  To: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
	Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
  Cc: Akhil R, Frank Li
In-Reply-To: <20260331102303.33181-1-akhilrajeev@nvidia.com>

Repurpose the struct tegra_dma_channel_regs to define offsets for all the
channel registers. Previously, the struct only held the register values
for each transfer and was wrapped within tegra_dma_sg_req. Move the
values directly into tegra_dma_sg_req and use channel_regs for
storing the register offsets. Update all register reads/writes to use
the struct channel_regs. This prepares for the register offset change
in Tegra264.

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/dma/tegra186-gpc-dma.c | 282 +++++++++++++++++----------------
 1 file changed, 142 insertions(+), 140 deletions(-)

diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
index a0522a992ebc..b213c4ae07d2 100644
--- a/drivers/dma/tegra186-gpc-dma.c
+++ b/drivers/dma/tegra186-gpc-dma.c
@@ -22,7 +22,6 @@
 #include "virt-dma.h"
 
 /* CSR register */
-#define TEGRA_GPCDMA_CHAN_CSR			0x00
 #define TEGRA_GPCDMA_CSR_ENB			BIT(31)
 #define TEGRA_GPCDMA_CSR_IE_EOC			BIT(30)
 #define TEGRA_GPCDMA_CSR_ONCE			BIT(27)
@@ -58,7 +57,6 @@
 #define TEGRA_GPCDMA_CSR_WEIGHT			GENMASK(13, 10)
 
 /* STATUS register */
-#define TEGRA_GPCDMA_CHAN_STATUS		0x004
 #define TEGRA_GPCDMA_STATUS_BUSY		BIT(31)
 #define TEGRA_GPCDMA_STATUS_ISE_EOC		BIT(30)
 #define TEGRA_GPCDMA_STATUS_PING_PONG		BIT(28)
@@ -70,22 +68,13 @@
 #define TEGRA_GPCDMA_STATUS_IRQ_STA		BIT(21)
 #define TEGRA_GPCDMA_STATUS_IRQ_TRIG_STA	BIT(20)
 
-#define TEGRA_GPCDMA_CHAN_CSRE			0x008
 #define TEGRA_GPCDMA_CHAN_CSRE_PAUSE		BIT(31)
 
-/* Source address */
-#define TEGRA_GPCDMA_CHAN_SRC_PTR		0x00C
-
-/* Destination address */
-#define TEGRA_GPCDMA_CHAN_DST_PTR		0x010
-
 /* High address pointer */
-#define TEGRA_GPCDMA_CHAN_HIGH_ADDR_PTR		0x014
 #define TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR		GENMASK(7, 0)
 #define TEGRA_GPCDMA_HIGH_ADDR_DST_PTR		GENMASK(23, 16)
 
 /* MC sequence register */
-#define TEGRA_GPCDMA_CHAN_MCSEQ			0x18
 #define TEGRA_GPCDMA_MCSEQ_DATA_SWAP		BIT(31)
 #define TEGRA_GPCDMA_MCSEQ_REQ_COUNT		GENMASK(30, 25)
 #define TEGRA_GPCDMA_MCSEQ_BURST		GENMASK(24, 23)
@@ -101,7 +90,6 @@
 #define TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK	GENMASK(6, 0)
 
 /* MMIO sequence register */
-#define TEGRA_GPCDMA_CHAN_MMIOSEQ			0x01c
 #define TEGRA_GPCDMA_MMIOSEQ_DBL_BUF		BIT(31)
 #define TEGRA_GPCDMA_MMIOSEQ_BUS_WIDTH		GENMASK(30, 28)
 #define TEGRA_GPCDMA_MMIOSEQ_BUS_WIDTH_8	\
@@ -120,17 +108,7 @@
 #define TEGRA_GPCDMA_MMIOSEQ_WRAP_WORD		GENMASK(18, 16)
 #define TEGRA_GPCDMA_MMIOSEQ_MMIO_PROT		GENMASK(8, 7)
 
-/* Channel WCOUNT */
-#define TEGRA_GPCDMA_CHAN_WCOUNT		0x20
-
-/* Transfer count */
-#define TEGRA_GPCDMA_CHAN_XFER_COUNT		0x24
-
-/* DMA byte count status */
-#define TEGRA_GPCDMA_CHAN_DMA_BYTE_STATUS	0x28
-
 /* Error Status Register */
-#define TEGRA_GPCDMA_CHAN_ERR_STATUS		0x30
 #define TEGRA_GPCDMA_CHAN_ERR_TYPE_SHIFT	8
 #define TEGRA_GPCDMA_CHAN_ERR_TYPE_MASK	0xF
 #define TEGRA_GPCDMA_CHAN_ERR_TYPE(err)	(			\
@@ -143,16 +121,6 @@
 #define TEGRA_DMA_MC_SLAVE_ERR			0xB
 #define TEGRA_DMA_MMIO_SLAVE_ERR		0xA
 
-/* Fixed Pattern */
-#define TEGRA_GPCDMA_CHAN_FIXED_PATTERN		0x34
-
-#define TEGRA_GPCDMA_CHAN_TZ			0x38
-#define TEGRA_GPCDMA_CHAN_TZ_MMIO_PROT_1	BIT(0)
-#define TEGRA_GPCDMA_CHAN_TZ_MC_PROT_1		BIT(1)
-
-#define TEGRA_GPCDMA_CHAN_SPARE			0x3c
-#define TEGRA_GPCDMA_CHAN_SPARE_EN_LEGACY_FC	BIT(16)
-
 /*
  * If any burst is in flight and DMA paused then this is the time to complete
  * on-flight burst and update DMA status register.
@@ -181,18 +149,24 @@ struct tegra_dma_chip_data {
 	unsigned int nr_channels;
 	unsigned int channel_reg_size;
 	unsigned int max_dma_count;
+	const struct tegra_dma_channel_regs *channel_regs;
 	int (*terminate)(struct tegra_dma_channel *tdc);
 };
 
 /* DMA channel registers */
 struct tegra_dma_channel_regs {
 	u32 csr;
-	u32 src_ptr;
-	u32 dst_ptr;
-	u32 high_addr_ptr;
+	u32 status;
+	u32 csre;
+	u32 src;
+	u32 dst;
+	u32 high_addr;
 	u32 mc_seq;
 	u32 mmio_seq;
 	u32 wcount;
+	u32 wxfer;
+	u32 wstatus;
+	u32 err_status;
 	u32 fixed_pattern;
 };
 
@@ -205,7 +179,14 @@ struct tegra_dma_channel_regs {
  */
 struct tegra_dma_sg_req {
 	unsigned int len;
-	struct tegra_dma_channel_regs ch_regs;
+	u32 csr;
+	u32 src;
+	u32 dst;
+	u32 high_addr;
+	u32 mc_seq;
+	u32 mmio_seq;
+	u32 wcount;
+	u32 fixed_pattern;
 };
 
 /*
@@ -228,19 +209,20 @@ struct tegra_dma_desc {
  * tegra_dma_channel: Channel specific information
  */
 struct tegra_dma_channel {
-	bool config_init;
-	char name[30];
-	enum dma_transfer_direction sid_dir;
-	enum dma_status status;
-	int id;
-	int irq;
-	int slave_id;
+	const struct tegra_dma_channel_regs *regs;
 	struct tegra_dma *tdma;
 	struct virt_dma_chan vc;
 	struct tegra_dma_desc *dma_desc;
 	struct dma_slave_config dma_sconfig;
+	enum dma_transfer_direction sid_dir;
+	enum dma_status status;
 	unsigned int stream_id;
 	unsigned long chan_base_offset;
+	bool config_init;
+	char name[30];
+	int id;
+	int irq;
+	int slave_id;
 };
 
 /*
@@ -288,22 +270,22 @@ static void tegra_dma_dump_chan_regs(struct tegra_dma_channel *tdc)
 {
 	dev_dbg(tdc2dev(tdc), "DMA Channel %d name %s register dump:\n",
 		tdc->id, tdc->name);
-	dev_dbg(tdc2dev(tdc), "CSR %x STA %x CSRE %x SRC %x DST %x\n",
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSR),
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS),
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE),
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_SRC_PTR),
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_DST_PTR)
-	);
-	dev_dbg(tdc2dev(tdc), "MCSEQ %x IOSEQ %x WCNT %x XFER %x BSTA %x\n",
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ),
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_MMIOSEQ),
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_WCOUNT),
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_XFER_COUNT),
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_DMA_BYTE_STATUS)
-	);
+	dev_dbg(tdc2dev(tdc), "CSR %x STA %x CSRE %x\n",
+		tdc_read(tdc, tdc->regs->csr),
+		tdc_read(tdc, tdc->regs->status),
+		tdc_read(tdc, tdc->regs->csre));
+	dev_dbg(tdc2dev(tdc), "SRC %x DST %x HI ADDR %x\n",
+		tdc_read(tdc, tdc->regs->src),
+		tdc_read(tdc, tdc->regs->dst),
+		tdc_read(tdc, tdc->regs->high_addr));
+	dev_dbg(tdc2dev(tdc), "MCSEQ %x IOSEQ %x WCNT %x XFER %x WSTA %x\n",
+		tdc_read(tdc, tdc->regs->mc_seq),
+		tdc_read(tdc, tdc->regs->mmio_seq),
+		tdc_read(tdc, tdc->regs->wcount),
+		tdc_read(tdc, tdc->regs->wxfer),
+		tdc_read(tdc, tdc->regs->wstatus));
 	dev_dbg(tdc2dev(tdc), "DMA ERR_STA %x\n",
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_ERR_STATUS));
+		tdc_read(tdc, tdc->regs->err_status));
 }
 
 static int tegra_dma_sid_reserve(struct tegra_dma_channel *tdc,
@@ -377,13 +359,13 @@ static int tegra_dma_pause(struct tegra_dma_channel *tdc)
 	int ret;
 	u32 val;
 
-	val = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE);
+	val = tdc_read(tdc, tdc->regs->csre);
 	val |= TEGRA_GPCDMA_CHAN_CSRE_PAUSE;
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSRE, val);
+	tdc_write(tdc, tdc->regs->csre, val);
 
 	/* Wait until busy bit is de-asserted */
 	ret = readl_relaxed_poll_timeout_atomic(tdc->tdma->base_addr +
-			tdc->chan_base_offset + TEGRA_GPCDMA_CHAN_STATUS,
+			tdc->chan_base_offset + tdc->regs->status,
 			val,
 			!(val & TEGRA_GPCDMA_STATUS_BUSY),
 			TEGRA_GPCDMA_BURST_COMPLETE_TIME,
@@ -419,9 +401,9 @@ static void tegra_dma_resume(struct tegra_dma_channel *tdc)
 {
 	u32 val;
 
-	val = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE);
+	val = tdc_read(tdc, tdc->regs->csre);
 	val &= ~TEGRA_GPCDMA_CHAN_CSRE_PAUSE;
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSRE, val);
+	tdc_write(tdc, tdc->regs->csre, val);
 
 	tdc->status = DMA_IN_PROGRESS;
 }
@@ -456,27 +438,27 @@ static void tegra_dma_disable(struct tegra_dma_channel *tdc)
 {
 	u32 csr, status;
 
-	csr = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSR);
+	csr = tdc_read(tdc, tdc->regs->csr);
 
 	/* Disable interrupts */
 	csr &= ~TEGRA_GPCDMA_CSR_IE_EOC;
 
 	/* Disable DMA */
 	csr &= ~TEGRA_GPCDMA_CSR_ENB;
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, csr);
+	tdc_write(tdc, tdc->regs->csr, csr);
 
 	/* Clear interrupt status if it is there */
-	status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS);
+	status = tdc_read(tdc, tdc->regs->status);
 	if (status & TEGRA_GPCDMA_STATUS_ISE_EOC) {
 		dev_dbg(tdc2dev(tdc), "%s():clearing interrupt\n", __func__);
-		tdc_write(tdc, TEGRA_GPCDMA_CHAN_STATUS, status);
+		tdc_write(tdc, tdc->regs->status, status);
 	}
 }
 
 static void tegra_dma_configure_next_sg(struct tegra_dma_channel *tdc)
 {
 	struct tegra_dma_desc *dma_desc = tdc->dma_desc;
-	struct tegra_dma_channel_regs *ch_regs;
+	struct tegra_dma_sg_req *sg_req;
 	int ret;
 	u32 val;
 
@@ -488,29 +470,29 @@ static void tegra_dma_configure_next_sg(struct tegra_dma_channel *tdc)
 
 	/* Configure next transfer immediately after DMA is busy */
 	ret = readl_relaxed_poll_timeout_atomic(tdc->tdma->base_addr +
-			tdc->chan_base_offset + TEGRA_GPCDMA_CHAN_STATUS,
+			tdc->chan_base_offset + tdc->regs->status,
 			val,
 			(val & TEGRA_GPCDMA_STATUS_BUSY), 0,
 			TEGRA_GPCDMA_BURST_COMPLETION_TIMEOUT);
 	if (ret)
 		return;
 
-	ch_regs = &dma_desc->sg_req[dma_desc->sg_idx].ch_regs;
+	sg_req = &dma_desc->sg_req[dma_desc->sg_idx];
 
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_WCOUNT, ch_regs->wcount);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_SRC_PTR, ch_regs->src_ptr);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_DST_PTR, ch_regs->dst_ptr);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_HIGH_ADDR_PTR, ch_regs->high_addr_ptr);
+	tdc_write(tdc, tdc->regs->wcount, sg_req->wcount);
+	tdc_write(tdc, tdc->regs->src, sg_req->src);
+	tdc_write(tdc, tdc->regs->dst, sg_req->dst);
+	tdc_write(tdc, tdc->regs->high_addr, sg_req->high_addr);
 
 	/* Start DMA */
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR,
-		  ch_regs->csr | TEGRA_GPCDMA_CSR_ENB);
+	tdc_write(tdc, tdc->regs->csr,
+		  sg_req->csr | TEGRA_GPCDMA_CSR_ENB);
 }
 
 static void tegra_dma_start(struct tegra_dma_channel *tdc)
 {
 	struct tegra_dma_desc *dma_desc = tdc->dma_desc;
-	struct tegra_dma_channel_regs *ch_regs;
+	struct tegra_dma_sg_req *sg_req;
 	struct virt_dma_desc *vdesc;
 
 	if (!dma_desc) {
@@ -526,21 +508,21 @@ static void tegra_dma_start(struct tegra_dma_channel *tdc)
 		tegra_dma_resume(tdc);
 	}
 
-	ch_regs = &dma_desc->sg_req[dma_desc->sg_idx].ch_regs;
+	sg_req = &dma_desc->sg_req[dma_desc->sg_idx];
 
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_WCOUNT, ch_regs->wcount);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, 0);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_SRC_PTR, ch_regs->src_ptr);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_DST_PTR, ch_regs->dst_ptr);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_HIGH_ADDR_PTR, ch_regs->high_addr_ptr);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_FIXED_PATTERN, ch_regs->fixed_pattern);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_MMIOSEQ, ch_regs->mmio_seq);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_MCSEQ, ch_regs->mc_seq);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, ch_regs->csr);
+	tdc_write(tdc, tdc->regs->wcount, sg_req->wcount);
+	tdc_write(tdc, tdc->regs->csr, 0);
+	tdc_write(tdc, tdc->regs->src, sg_req->src);
+	tdc_write(tdc, tdc->regs->dst, sg_req->dst);
+	tdc_write(tdc, tdc->regs->high_addr, sg_req->high_addr);
+	tdc_write(tdc, tdc->regs->fixed_pattern, sg_req->fixed_pattern);
+	tdc_write(tdc, tdc->regs->mmio_seq, sg_req->mmio_seq);
+	tdc_write(tdc, tdc->regs->mc_seq, sg_req->mc_seq);
+	tdc_write(tdc, tdc->regs->csr, sg_req->csr);
 
 	/* Start DMA */
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR,
-		  ch_regs->csr | TEGRA_GPCDMA_CSR_ENB);
+	tdc_write(tdc, tdc->regs->csr,
+		  sg_req->csr | TEGRA_GPCDMA_CSR_ENB);
 }
 
 static void tegra_dma_xfer_complete(struct tegra_dma_channel *tdc)
@@ -601,19 +583,19 @@ static irqreturn_t tegra_dma_isr(int irq, void *dev_id)
 	u32 status;
 
 	/* Check channel error status register */
-	status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_ERR_STATUS);
+	status = tdc_read(tdc, tdc->regs->err_status);
 	if (status) {
 		tegra_dma_chan_decode_error(tdc, status);
 		tegra_dma_dump_chan_regs(tdc);
-		tdc_write(tdc, TEGRA_GPCDMA_CHAN_ERR_STATUS, 0xFFFFFFFF);
+		tdc_write(tdc, tdc->regs->err_status, 0xFFFFFFFF);
 	}
 
 	spin_lock(&tdc->vc.lock);
-	status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS);
+	status = tdc_read(tdc, tdc->regs->status);
 	if (!(status & TEGRA_GPCDMA_STATUS_ISE_EOC))
 		goto irq_done;
 
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_STATUS,
+	tdc_write(tdc, tdc->regs->status,
 		  TEGRA_GPCDMA_STATUS_ISE_EOC);
 
 	if (!dma_desc)
@@ -673,10 +655,10 @@ static int tegra_dma_stop_client(struct tegra_dma_channel *tdc)
 	 * to stop DMA engine from starting any more bursts for
 	 * the given client and wait for in flight bursts to complete
 	 */
-	csr = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSR);
+	csr = tdc_read(tdc, tdc->regs->csr);
 	csr &= ~(TEGRA_GPCDMA_CSR_REQ_SEL_MASK);
 	csr |= TEGRA_GPCDMA_CSR_REQ_SEL_UNUSED;
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, csr);
+	tdc_write(tdc, tdc->regs->csr, csr);
 
 	/* Wait for in flight data transfer to finish */
 	udelay(TEGRA_GPCDMA_BURST_COMPLETE_TIME);
@@ -687,7 +669,7 @@ static int tegra_dma_stop_client(struct tegra_dma_channel *tdc)
 
 	ret = readl_relaxed_poll_timeout_atomic(tdc->tdma->base_addr +
 				tdc->chan_base_offset +
-				TEGRA_GPCDMA_CHAN_STATUS,
+				tdc->regs->status,
 				status,
 				!(status & (TEGRA_GPCDMA_STATUS_CHANNEL_TX |
 				TEGRA_GPCDMA_STATUS_CHANNEL_RX)),
@@ -739,14 +721,14 @@ static int tegra_dma_get_residual(struct tegra_dma_channel *tdc)
 	unsigned int bytes_xfer, residual;
 	u32 wcount = 0, status;
 
-	wcount = tdc_read(tdc, TEGRA_GPCDMA_CHAN_XFER_COUNT);
+	wcount = tdc_read(tdc, tdc->regs->wxfer);
 
 	/*
 	 * Set wcount = 0 if EOC bit is set. The transfer would have
 	 * already completed and the CHAN_XFER_COUNT could have updated
 	 * for the next transfer, specifically in case of cyclic transfers.
 	 */
-	status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS);
+	status = tdc_read(tdc, tdc->regs->status);
 	if (status & TEGRA_GPCDMA_STATUS_ISE_EOC)
 		wcount = 0;
 
@@ -893,7 +875,7 @@ tegra_dma_prep_dma_memset(struct dma_chan *dc, dma_addr_t dest, int value,
 	/* Configure default priority weight for the channel */
 	csr |= FIELD_PREP(TEGRA_GPCDMA_CSR_WEIGHT, 1);
 
-	mc_seq =  tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
+	mc_seq =  tdc_read(tdc, tdc->regs->mc_seq);
 	/* retain stream-id and clean rest */
 	mc_seq &= TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK;
 
@@ -916,16 +898,16 @@ tegra_dma_prep_dma_memset(struct dma_chan *dc, dma_addr_t dest, int value,
 	dma_desc->sg_count = 1;
 	sg_req = dma_desc->sg_req;
 
-	sg_req[0].ch_regs.src_ptr = 0;
-	sg_req[0].ch_regs.dst_ptr = dest;
-	sg_req[0].ch_regs.high_addr_ptr =
+	sg_req[0].src = 0;
+	sg_req[0].dst = dest;
+	sg_req[0].high_addr =
 			FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (dest >> 32));
-	sg_req[0].ch_regs.fixed_pattern = value;
+	sg_req[0].fixed_pattern = value;
 	/* Word count reg takes value as (N +1) words */
-	sg_req[0].ch_regs.wcount = ((len - 4) >> 2);
-	sg_req[0].ch_regs.csr = csr;
-	sg_req[0].ch_regs.mmio_seq = 0;
-	sg_req[0].ch_regs.mc_seq = mc_seq;
+	sg_req[0].wcount = ((len - 4) >> 2);
+	sg_req[0].csr = csr;
+	sg_req[0].mmio_seq = 0;
+	sg_req[0].mc_seq = mc_seq;
 	sg_req[0].len = len;
 
 	dma_desc->cyclic = false;
@@ -961,7 +943,7 @@ tegra_dma_prep_dma_memcpy(struct dma_chan *dc, dma_addr_t dest,
 	/* Configure default priority weight for the channel */
 	csr |= FIELD_PREP(TEGRA_GPCDMA_CSR_WEIGHT, 1);
 
-	mc_seq =  tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
+	mc_seq =  tdc_read(tdc, tdc->regs->mc_seq);
 	/* retain stream-id and clean rest */
 	mc_seq &= (TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK) |
 		  (TEGRA_GPCDMA_MCSEQ_STREAM_ID1_MASK);
@@ -985,17 +967,17 @@ tegra_dma_prep_dma_memcpy(struct dma_chan *dc, dma_addr_t dest,
 	dma_desc->sg_count = 1;
 	sg_req = dma_desc->sg_req;
 
-	sg_req[0].ch_regs.src_ptr = src;
-	sg_req[0].ch_regs.dst_ptr = dest;
-	sg_req[0].ch_regs.high_addr_ptr =
+	sg_req[0].src = src;
+	sg_req[0].dst = dest;
+	sg_req[0].high_addr =
 		FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (src >> 32));
-	sg_req[0].ch_regs.high_addr_ptr |=
+	sg_req[0].high_addr |=
 		FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (dest >> 32));
 	/* Word count reg takes value as (N +1) words */
-	sg_req[0].ch_regs.wcount = ((len - 4) >> 2);
-	sg_req[0].ch_regs.csr = csr;
-	sg_req[0].ch_regs.mmio_seq = 0;
-	sg_req[0].ch_regs.mc_seq = mc_seq;
+	sg_req[0].wcount = ((len - 4) >> 2);
+	sg_req[0].csr = csr;
+	sg_req[0].mmio_seq = 0;
+	sg_req[0].mc_seq = mc_seq;
 	sg_req[0].len = len;
 
 	dma_desc->cyclic = false;
@@ -1049,7 +1031,7 @@ tegra_dma_prep_slave_sg(struct dma_chan *dc, struct scatterlist *sgl,
 	if (flags & DMA_PREP_INTERRUPT)
 		csr |= TEGRA_GPCDMA_CSR_IE_EOC;
 
-	mc_seq =  tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
+	mc_seq =  tdc_read(tdc, tdc->regs->mc_seq);
 	/* retain stream-id and clean rest */
 	mc_seq &= TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK;
 
@@ -1096,14 +1078,14 @@ tegra_dma_prep_slave_sg(struct dma_chan *dc, struct scatterlist *sgl,
 		dma_desc->bytes_req += len;
 
 		if (direction == DMA_MEM_TO_DEV) {
-			sg_req[i].ch_regs.src_ptr = mem;
-			sg_req[i].ch_regs.dst_ptr = apb_ptr;
-			sg_req[i].ch_regs.high_addr_ptr =
+			sg_req[i].src = mem;
+			sg_req[i].dst = apb_ptr;
+			sg_req[i].high_addr =
 				FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (mem >> 32));
 		} else if (direction == DMA_DEV_TO_MEM) {
-			sg_req[i].ch_regs.src_ptr = apb_ptr;
-			sg_req[i].ch_regs.dst_ptr = mem;
-			sg_req[i].ch_regs.high_addr_ptr =
+			sg_req[i].src = apb_ptr;
+			sg_req[i].dst = mem;
+			sg_req[i].high_addr =
 				FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (mem >> 32));
 		}
 
@@ -1111,10 +1093,10 @@ tegra_dma_prep_slave_sg(struct dma_chan *dc, struct scatterlist *sgl,
 		 * Word count register takes input in words. Writing a value
 		 * of N into word count register means a req of (N+1) words.
 		 */
-		sg_req[i].ch_regs.wcount = ((len - 4) >> 2);
-		sg_req[i].ch_regs.csr = csr;
-		sg_req[i].ch_regs.mmio_seq = mmio_seq;
-		sg_req[i].ch_regs.mc_seq = mc_seq;
+		sg_req[i].wcount = ((len - 4) >> 2);
+		sg_req[i].csr = csr;
+		sg_req[i].mmio_seq = mmio_seq;
+		sg_req[i].mc_seq = mc_seq;
 		sg_req[i].len = len;
 	}
 
@@ -1186,7 +1168,7 @@ tegra_dma_prep_dma_cyclic(struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_l
 
 	mmio_seq |= FIELD_PREP(TEGRA_GPCDMA_MMIOSEQ_WRAP_WORD, 1);
 
-	mc_seq =  tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
+	mc_seq =  tdc_read(tdc, tdc->regs->mc_seq);
 	/* retain stream-id and clean rest */
 	mc_seq &= TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK;
 
@@ -1217,24 +1199,24 @@ tegra_dma_prep_dma_cyclic(struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_l
 	for (i = 0; i < period_count; i++) {
 		mmio_seq |= get_burst_size(tdc, burst_size, slave_bw, len);
 		if (direction == DMA_MEM_TO_DEV) {
-			sg_req[i].ch_regs.src_ptr = mem;
-			sg_req[i].ch_regs.dst_ptr = apb_ptr;
-			sg_req[i].ch_regs.high_addr_ptr =
+			sg_req[i].src = mem;
+			sg_req[i].dst = apb_ptr;
+			sg_req[i].high_addr =
 				FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (mem >> 32));
 		} else if (direction == DMA_DEV_TO_MEM) {
-			sg_req[i].ch_regs.src_ptr = apb_ptr;
-			sg_req[i].ch_regs.dst_ptr = mem;
-			sg_req[i].ch_regs.high_addr_ptr =
+			sg_req[i].src = apb_ptr;
+			sg_req[i].dst = mem;
+			sg_req[i].high_addr =
 				FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (mem >> 32));
 		}
 		/*
 		 * Word count register takes input in words. Writing a value
 		 * of N into word count register means a req of (N+1) words.
 		 */
-		sg_req[i].ch_regs.wcount = ((len - 4) >> 2);
-		sg_req[i].ch_regs.csr = csr;
-		sg_req[i].ch_regs.mmio_seq = mmio_seq;
-		sg_req[i].ch_regs.mc_seq = mc_seq;
+		sg_req[i].wcount = ((len - 4) >> 2);
+		sg_req[i].csr = csr;
+		sg_req[i].mmio_seq = mmio_seq;
+		sg_req[i].mc_seq = mc_seq;
 		sg_req[i].len = len;
 
 		mem += len;
@@ -1304,11 +1286,28 @@ static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec,
 	return chan;
 }
 
+static const struct tegra_dma_channel_regs tegra186_reg_offsets = {
+	.csr = 0x0,
+	.status = 0x4,
+	.csre = 0x8,
+	.src = 0xc,
+	.dst = 0x10,
+	.high_addr = 0x14,
+	.mc_seq = 0x18,
+	.mmio_seq = 0x1c,
+	.wcount = 0x20,
+	.wxfer = 0x24,
+	.wstatus = 0x28,
+	.err_status = 0x30,
+	.fixed_pattern = 0x34,
+};
+
 static const struct tegra_dma_chip_data tegra186_dma_chip_data = {
 	.nr_channels = 32,
 	.channel_reg_size = SZ_64K,
 	.max_dma_count = SZ_1G,
 	.hw_support_pause = false,
+	.channel_regs = &tegra186_reg_offsets,
 	.terminate = tegra_dma_stop_client,
 };
 
@@ -1317,6 +1316,7 @@ static const struct tegra_dma_chip_data tegra194_dma_chip_data = {
 	.channel_reg_size = SZ_64K,
 	.max_dma_count = SZ_1G,
 	.hw_support_pause = true,
+	.channel_regs = &tegra186_reg_offsets,
 	.terminate = tegra_dma_pause,
 };
 
@@ -1325,6 +1325,7 @@ static const struct tegra_dma_chip_data tegra234_dma_chip_data = {
 	.channel_reg_size = SZ_64K,
 	.max_dma_count = SZ_1G,
 	.hw_support_pause = true,
+	.channel_regs = &tegra186_reg_offsets,
 	.terminate = tegra_dma_pause_noerr,
 };
 
@@ -1345,7 +1346,7 @@ MODULE_DEVICE_TABLE(of, tegra_dma_of_match);
 
 static int tegra_dma_program_sid(struct tegra_dma_channel *tdc, int stream_id)
 {
-	unsigned int reg_val =  tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
+	unsigned int reg_val =  tdc_read(tdc, tdc->regs->mc_seq);
 
 	reg_val &= ~(TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK);
 	reg_val &= ~(TEGRA_GPCDMA_MCSEQ_STREAM_ID1_MASK);
@@ -1353,7 +1354,7 @@ static int tegra_dma_program_sid(struct tegra_dma_channel *tdc, int stream_id)
 	reg_val |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK, stream_id);
 	reg_val |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_STREAM_ID1_MASK, stream_id);
 
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_MCSEQ, reg_val);
+	tdc_write(tdc, tdc->regs->mc_seq, reg_val);
 	return 0;
 }
 
@@ -1419,6 +1420,7 @@ static int tegra_dma_probe(struct platform_device *pdev)
 		tdc->chan_base_offset = TEGRA_GPCDMA_CHANNEL_BASE_ADDR_OFFSET +
 					i * cdata->channel_reg_size;
 		snprintf(tdc->name, sizeof(tdc->name), "gpcdma.%d", i);
+		tdc->regs = cdata->channel_regs;
 		tdc->tdma = tdma;
 		tdc->id = i;
 		tdc->slave_id = -1;
-- 
2.50.1


^ permalink raw reply related

* [PATCH v6 06/10] dmaengine: tegra: Support address width > 39 bits
From: Akhil R @ 2026-03-31 10:22 UTC (permalink / raw)
  To: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
	Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
  Cc: Akhil R, Frank Li
In-Reply-To: <20260331102303.33181-1-akhilrajeev@nvidia.com>

Tegra264 supports address width of 41 bits. Unlike older SoCs which use
a common high_addr register for upper address bits, Tegra264 has separate
src_high and dst_high registers to accommodate this wider address space.

Add an addr_bits property to the device data structure to specify the
number of address bits supported on each device and use that to program
the appropriate registers.

Update the sg_req struct to remove the high_addr field and use
dma_addr_t for src and dst to store the complete addresses. Extract
the high address bits only when programming the registers.

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/dma/tegra186-gpc-dma.c | 83 +++++++++++++++++++++-------------
 1 file changed, 52 insertions(+), 31 deletions(-)

diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
index b213c4ae07d2..3ac43ad19ed6 100644
--- a/drivers/dma/tegra186-gpc-dma.c
+++ b/drivers/dma/tegra186-gpc-dma.c
@@ -146,6 +146,7 @@ struct tegra_dma_channel;
  */
 struct tegra_dma_chip_data {
 	bool hw_support_pause;
+	unsigned int addr_bits;
 	unsigned int nr_channels;
 	unsigned int channel_reg_size;
 	unsigned int max_dma_count;
@@ -161,6 +162,8 @@ struct tegra_dma_channel_regs {
 	u32 src;
 	u32 dst;
 	u32 high_addr;
+	u32 src_high;
+	u32 dst_high;
 	u32 mc_seq;
 	u32 mmio_seq;
 	u32 wcount;
@@ -179,10 +182,9 @@ struct tegra_dma_channel_regs {
  */
 struct tegra_dma_sg_req {
 	unsigned int len;
+	dma_addr_t src;
+	dma_addr_t dst;
 	u32 csr;
-	u32 src;
-	u32 dst;
-	u32 high_addr;
 	u32 mc_seq;
 	u32 mmio_seq;
 	u32 wcount;
@@ -266,6 +268,25 @@ static inline struct device *tdc2dev(struct tegra_dma_channel *tdc)
 	return tdc->vc.chan.device->dev;
 }
 
+static void tegra_dma_program_addr(struct tegra_dma_channel *tdc,
+				   struct tegra_dma_sg_req *sg_req)
+{
+	tdc_write(tdc, tdc->regs->src, lower_32_bits(sg_req->src));
+	tdc_write(tdc, tdc->regs->dst, lower_32_bits(sg_req->dst));
+
+	if (tdc->tdma->chip_data->addr_bits > 39) {
+		tdc_write(tdc, tdc->regs->src_high, upper_32_bits(sg_req->src));
+		tdc_write(tdc, tdc->regs->dst_high, upper_32_bits(sg_req->dst));
+	} else {
+		u32 src_high = FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR,
+					      upper_32_bits(sg_req->src));
+		u32 dst_high = FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR,
+					      upper_32_bits(sg_req->dst));
+
+		tdc_write(tdc, tdc->regs->high_addr, src_high | dst_high);
+	}
+}
+
 static void tegra_dma_dump_chan_regs(struct tegra_dma_channel *tdc)
 {
 	dev_dbg(tdc2dev(tdc), "DMA Channel %d name %s register dump:\n",
@@ -274,10 +295,20 @@ static void tegra_dma_dump_chan_regs(struct tegra_dma_channel *tdc)
 		tdc_read(tdc, tdc->regs->csr),
 		tdc_read(tdc, tdc->regs->status),
 		tdc_read(tdc, tdc->regs->csre));
-	dev_dbg(tdc2dev(tdc), "SRC %x DST %x HI ADDR %x\n",
-		tdc_read(tdc, tdc->regs->src),
-		tdc_read(tdc, tdc->regs->dst),
-		tdc_read(tdc, tdc->regs->high_addr));
+
+	if (tdc->tdma->chip_data->addr_bits > 39) {
+		dev_dbg(tdc2dev(tdc), "SRC %x SRC HI %x DST %x DST HI %x\n",
+			tdc_read(tdc, tdc->regs->src),
+			tdc_read(tdc, tdc->regs->src_high),
+			tdc_read(tdc, tdc->regs->dst),
+			tdc_read(tdc, tdc->regs->dst_high));
+	} else {
+		dev_dbg(tdc2dev(tdc), "SRC %x DST %x HI ADDR %x\n",
+			tdc_read(tdc, tdc->regs->src),
+			tdc_read(tdc, tdc->regs->dst),
+			tdc_read(tdc, tdc->regs->high_addr));
+	}
+
 	dev_dbg(tdc2dev(tdc), "MCSEQ %x IOSEQ %x WCNT %x XFER %x WSTA %x\n",
 		tdc_read(tdc, tdc->regs->mc_seq),
 		tdc_read(tdc, tdc->regs->mmio_seq),
@@ -480,9 +511,7 @@ static void tegra_dma_configure_next_sg(struct tegra_dma_channel *tdc)
 	sg_req = &dma_desc->sg_req[dma_desc->sg_idx];
 
 	tdc_write(tdc, tdc->regs->wcount, sg_req->wcount);
-	tdc_write(tdc, tdc->regs->src, sg_req->src);
-	tdc_write(tdc, tdc->regs->dst, sg_req->dst);
-	tdc_write(tdc, tdc->regs->high_addr, sg_req->high_addr);
+	tegra_dma_program_addr(tdc, sg_req);
 
 	/* Start DMA */
 	tdc_write(tdc, tdc->regs->csr,
@@ -510,11 +539,9 @@ static void tegra_dma_start(struct tegra_dma_channel *tdc)
 
 	sg_req = &dma_desc->sg_req[dma_desc->sg_idx];
 
+	tegra_dma_program_addr(tdc, sg_req);
 	tdc_write(tdc, tdc->regs->wcount, sg_req->wcount);
 	tdc_write(tdc, tdc->regs->csr, 0);
-	tdc_write(tdc, tdc->regs->src, sg_req->src);
-	tdc_write(tdc, tdc->regs->dst, sg_req->dst);
-	tdc_write(tdc, tdc->regs->high_addr, sg_req->high_addr);
 	tdc_write(tdc, tdc->regs->fixed_pattern, sg_req->fixed_pattern);
 	tdc_write(tdc, tdc->regs->mmio_seq, sg_req->mmio_seq);
 	tdc_write(tdc, tdc->regs->mc_seq, sg_req->mc_seq);
@@ -819,7 +846,7 @@ static unsigned int get_burst_size(struct tegra_dma_channel *tdc,
 
 static int get_transfer_param(struct tegra_dma_channel *tdc,
 			      enum dma_transfer_direction direction,
-			      u32 *apb_addr,
+			      dma_addr_t *apb_addr,
 			      u32 *mmio_seq,
 			      u32 *csr,
 			      unsigned int *burst_size,
@@ -897,11 +924,9 @@ tegra_dma_prep_dma_memset(struct dma_chan *dc, dma_addr_t dest, int value,
 	dma_desc->bytes_req = len;
 	dma_desc->sg_count = 1;
 	sg_req = dma_desc->sg_req;
-
 	sg_req[0].src = 0;
 	sg_req[0].dst = dest;
-	sg_req[0].high_addr =
-			FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (dest >> 32));
+
 	sg_req[0].fixed_pattern = value;
 	/* Word count reg takes value as (N +1) words */
 	sg_req[0].wcount = ((len - 4) >> 2);
@@ -969,10 +994,7 @@ tegra_dma_prep_dma_memcpy(struct dma_chan *dc, dma_addr_t dest,
 
 	sg_req[0].src = src;
 	sg_req[0].dst = dest;
-	sg_req[0].high_addr =
-		FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (src >> 32));
-	sg_req[0].high_addr |=
-		FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (dest >> 32));
+
 	/* Word count reg takes value as (N +1) words */
 	sg_req[0].wcount = ((len - 4) >> 2);
 	sg_req[0].csr = csr;
@@ -992,7 +1014,8 @@ tegra_dma_prep_slave_sg(struct dma_chan *dc, struct scatterlist *sgl,
 	struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc);
 	unsigned int max_dma_count = tdc->tdma->chip_data->max_dma_count;
 	enum dma_slave_buswidth slave_bw = DMA_SLAVE_BUSWIDTH_UNDEFINED;
-	u32 csr, mc_seq, apb_ptr = 0, mmio_seq = 0;
+	u32 csr, mc_seq, mmio_seq = 0;
+	dma_addr_t apb_ptr = 0;
 	struct tegra_dma_sg_req *sg_req;
 	struct tegra_dma_desc *dma_desc;
 	struct scatterlist *sg;
@@ -1080,13 +1103,9 @@ tegra_dma_prep_slave_sg(struct dma_chan *dc, struct scatterlist *sgl,
 		if (direction == DMA_MEM_TO_DEV) {
 			sg_req[i].src = mem;
 			sg_req[i].dst = apb_ptr;
-			sg_req[i].high_addr =
-				FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (mem >> 32));
 		} else if (direction == DMA_DEV_TO_MEM) {
 			sg_req[i].src = apb_ptr;
 			sg_req[i].dst = mem;
-			sg_req[i].high_addr =
-				FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (mem >> 32));
 		}
 
 		/*
@@ -1110,7 +1129,8 @@ tegra_dma_prep_dma_cyclic(struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_l
 			  unsigned long flags)
 {
 	enum dma_slave_buswidth slave_bw = DMA_SLAVE_BUSWIDTH_UNDEFINED;
-	u32 csr, mc_seq, apb_ptr = 0, mmio_seq = 0, burst_size;
+	u32 csr, mc_seq, mmio_seq = 0, burst_size;
+	dma_addr_t apb_ptr = 0;
 	unsigned int max_dma_count, len, period_count, i;
 	struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc);
 	struct tegra_dma_desc *dma_desc;
@@ -1201,13 +1221,9 @@ tegra_dma_prep_dma_cyclic(struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_l
 		if (direction == DMA_MEM_TO_DEV) {
 			sg_req[i].src = mem;
 			sg_req[i].dst = apb_ptr;
-			sg_req[i].high_addr =
-				FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (mem >> 32));
 		} else if (direction == DMA_DEV_TO_MEM) {
 			sg_req[i].src = apb_ptr;
 			sg_req[i].dst = mem;
-			sg_req[i].high_addr =
-				FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (mem >> 32));
 		}
 		/*
 		 * Word count register takes input in words. Writing a value
@@ -1304,6 +1320,7 @@ static const struct tegra_dma_channel_regs tegra186_reg_offsets = {
 
 static const struct tegra_dma_chip_data tegra186_dma_chip_data = {
 	.nr_channels = 32,
+	.addr_bits = 39,
 	.channel_reg_size = SZ_64K,
 	.max_dma_count = SZ_1G,
 	.hw_support_pause = false,
@@ -1313,6 +1330,7 @@ static const struct tegra_dma_chip_data tegra186_dma_chip_data = {
 
 static const struct tegra_dma_chip_data tegra194_dma_chip_data = {
 	.nr_channels = 32,
+	.addr_bits = 39,
 	.channel_reg_size = SZ_64K,
 	.max_dma_count = SZ_1G,
 	.hw_support_pause = true,
@@ -1322,6 +1340,7 @@ static const struct tegra_dma_chip_data tegra194_dma_chip_data = {
 
 static const struct tegra_dma_chip_data tegra234_dma_chip_data = {
 	.nr_channels = 32,
+	.addr_bits = 39,
 	.channel_reg_size = SZ_64K,
 	.max_dma_count = SZ_1G,
 	.hw_support_pause = true,
@@ -1433,6 +1452,8 @@ static int tegra_dma_probe(struct platform_device *pdev)
 		tdc->stream_id = stream_id;
 	}
 
+	dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(cdata->addr_bits));
+
 	dma_cap_set(DMA_SLAVE, tdma->dma_dev.cap_mask);
 	dma_cap_set(DMA_PRIVATE, tdma->dma_dev.cap_mask);
 	dma_cap_set(DMA_MEMCPY, tdma->dma_dev.cap_mask);
-- 
2.50.1


^ permalink raw reply related

* [PATCH v6 07/10] dmaengine: tegra: Use managed DMA controller registration
From: Akhil R @ 2026-03-31 10:23 UTC (permalink / raw)
  To: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
	Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
  Cc: Akhil R, Frank Li
In-Reply-To: <20260331102303.33181-1-akhilrajeev@nvidia.com>

Switch to managed registration in probe. This simplifies the error
paths in the probe and also removes the requirement of the driver
remove function.

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Suggested-by: Frank Li <frank.li@nxp.com>
---
 drivers/dma/tegra186-gpc-dma.c | 19 ++++---------------
 1 file changed, 4 insertions(+), 15 deletions(-)

diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
index 3ac43ad19ed6..9bea2ffb3b9e 100644
--- a/drivers/dma/tegra186-gpc-dma.c
+++ b/drivers/dma/tegra186-gpc-dma.c
@@ -1483,37 +1483,27 @@ static int tegra_dma_probe(struct platform_device *pdev)
 	tdma->dma_dev.device_synchronize = tegra_dma_chan_synchronize;
 	tdma->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
 
-	ret = dma_async_device_register(&tdma->dma_dev);
+	ret = dmaenginem_async_device_register(&tdma->dma_dev);
 	if (ret < 0) {
 		dev_err_probe(&pdev->dev, ret,
 			      "GPC DMA driver registration failed\n");
 		return ret;
 	}
 
-	ret = of_dma_controller_register(pdev->dev.of_node,
-					 tegra_dma_of_xlate, tdma);
+	ret = devm_of_dma_controller_register(&pdev->dev, pdev->dev.of_node,
+					      tegra_dma_of_xlate, tdma);
 	if (ret < 0) {
 		dev_err_probe(&pdev->dev, ret,
 			      "GPC DMA OF registration failed\n");
-
-		dma_async_device_unregister(&tdma->dma_dev);
 		return ret;
 	}
 
-	dev_info(&pdev->dev, "GPC DMA driver register %lu channels\n",
+	dev_info(&pdev->dev, "GPC DMA driver registered %lu channels\n",
 		 hweight_long(tdma->chan_mask));
 
 	return 0;
 }
 
-static void tegra_dma_remove(struct platform_device *pdev)
-{
-	struct tegra_dma *tdma = platform_get_drvdata(pdev);
-
-	of_dma_controller_free(pdev->dev.of_node);
-	dma_async_device_unregister(&tdma->dma_dev);
-}
-
 static int __maybe_unused tegra_dma_pm_suspend(struct device *dev)
 {
 	struct tegra_dma *tdma = dev_get_drvdata(dev);
@@ -1564,7 +1554,6 @@ static struct platform_driver tegra_dma_driver = {
 		.of_match_table = tegra_dma_of_match,
 	},
 	.probe		= tegra_dma_probe,
-	.remove		= tegra_dma_remove,
 };
 
 module_platform_driver(tegra_dma_driver);
-- 
2.50.1


^ permalink raw reply related

* [PATCH v6 08/10] dmaengine: tegra: Use iommu-map for stream ID
From: Akhil R @ 2026-03-31 10:23 UTC (permalink / raw)
  To: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
	Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
  Cc: Akhil R
In-Reply-To: <20260331102303.33181-1-akhilrajeev@nvidia.com>

Use 'iommu-map', when provided, to get the stream ID to be programmed
for each channel. Iterate over the channels registered and configure
each channel device separately using of_dma_configure_id() to allow
it to use a separate IOMMU domain for the transfer. However, do this
in a second loop since the first loop populates the DMA device channels
list and async_device_register() registers the channels. Both are
prerequisites for using the channel device in the next loop.

Channels will continue to use the same global stream ID if the
'iommu-map' property is not present in the device tree.

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
---
 drivers/dma/tegra186-gpc-dma.c | 53 ++++++++++++++++++++++++++++------
 1 file changed, 44 insertions(+), 9 deletions(-)

diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
index 9bea2ffb3b9e..cd480d047204 100644
--- a/drivers/dma/tegra186-gpc-dma.c
+++ b/drivers/dma/tegra186-gpc-dma.c
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_dma.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/reset.h>
 #include <linux/slab.h>
@@ -1380,9 +1381,13 @@ static int tegra_dma_program_sid(struct tegra_dma_channel *tdc, int stream_id)
 static int tegra_dma_probe(struct platform_device *pdev)
 {
 	const struct tegra_dma_chip_data *cdata = NULL;
+	struct tegra_dma_channel *tdc;
+	struct tegra_dma *tdma;
+	struct dma_chan *chan;
+	struct device *chdev;
+	bool use_iommu_map = false;
 	unsigned int i;
 	u32 stream_id;
-	struct tegra_dma *tdma;
 	int ret;
 
 	cdata = of_device_get_match_data(&pdev->dev);
@@ -1410,9 +1415,10 @@ static int tegra_dma_probe(struct platform_device *pdev)
 
 	tdma->dma_dev.dev = &pdev->dev;
 
-	if (!tegra_dev_iommu_get_stream_id(&pdev->dev, &stream_id)) {
-		dev_err(&pdev->dev, "Missing iommu stream-id\n");
-		return -EINVAL;
+	use_iommu_map = of_property_present(pdev->dev.of_node, "iommu-map");
+	if (!use_iommu_map) {
+		if (!tegra_dev_iommu_get_stream_id(&pdev->dev, &stream_id))
+			return dev_err_probe(&pdev->dev, -EINVAL, "Missing iommu stream-id\n");
 	}
 
 	ret = device_property_read_u32(&pdev->dev, "dma-channel-mask",
@@ -1424,9 +1430,10 @@ static int tegra_dma_probe(struct platform_device *pdev)
 		tdma->chan_mask = TEGRA_GPCDMA_DEFAULT_CHANNEL_MASK;
 	}
 
+	/* Initialize vchan for each channel and populate the channels list */
 	INIT_LIST_HEAD(&tdma->dma_dev.channels);
 	for (i = 0; i < cdata->nr_channels; i++) {
-		struct tegra_dma_channel *tdc = &tdma->channels[i];
+		tdc = &tdma->channels[i];
 
 		/* Check for channel mask */
 		if (!(tdma->chan_mask & BIT(i)))
@@ -1446,10 +1453,6 @@ static int tegra_dma_probe(struct platform_device *pdev)
 
 		vchan_init(&tdc->vc, &tdma->dma_dev);
 		tdc->vc.desc_free = tegra_dma_desc_free;
-
-		/* program stream-id for this channel */
-		tegra_dma_program_sid(tdc, stream_id);
-		tdc->stream_id = stream_id;
 	}
 
 	dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(cdata->addr_bits));
@@ -1483,6 +1486,7 @@ static int tegra_dma_probe(struct platform_device *pdev)
 	tdma->dma_dev.device_synchronize = tegra_dma_chan_synchronize;
 	tdma->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
 
+	/* Register the DMA device and the channels */
 	ret = dmaenginem_async_device_register(&tdma->dma_dev);
 	if (ret < 0) {
 		dev_err_probe(&pdev->dev, ret,
@@ -1490,6 +1494,37 @@ static int tegra_dma_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	/*
+	 * Configure stream ID for each channel from the channels registered
+	 * above. This is done in a separate iteration to ensure that only
+	 * the channels available and registered for the DMA device are used.
+	 */
+	list_for_each_entry(chan, &tdma->dma_dev.channels, device_node) {
+		chdev = &chan->dev->device;
+		tdc = to_tegra_dma_chan(chan);
+
+		if (use_iommu_map) {
+			chdev->bus = pdev->dev.bus;
+			dma_coerce_mask_and_coherent(chdev, DMA_BIT_MASK(cdata->addr_bits));
+
+			ret = of_dma_configure_id(chdev, pdev->dev.of_node,
+						  true, &tdc->id);
+			if (ret)
+				return dev_err_probe(chdev, ret,
+					   "Failed to configure IOMMU for channel %d\n", tdc->id);
+
+			if (!tegra_dev_iommu_get_stream_id(chdev, &stream_id))
+				return dev_err_probe(chdev, -EINVAL,
+					   "Failed to get stream ID for channel %d\n", tdc->id);
+
+			chan->dev->chan_dma_dev = true;
+		}
+
+		/* program stream-id for this channel */
+		tegra_dma_program_sid(tdc, stream_id);
+		tdc->stream_id = stream_id;
+	}
+
 	ret = devm_of_dma_controller_register(&pdev->dev, pdev->dev.of_node,
 					      tegra_dma_of_xlate, tdma);
 	if (ret < 0) {
-- 
2.50.1


^ permalink raw reply related

* Re: [PATCH v1 1/2] dt-bindings: riscv: spacemit: add deepcomputing,fml13v05
From: Krzysztof Kozlowski @ 2026-03-31 10:25 UTC (permalink / raw)
  To: Sandie Cao
  Cc: Conor Dooley, Emil Renner Berthing, Rob Herring,
	Krzysztof Kozlowski, Yixun Lan, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Heinrich Schuchardt, Troy Mitchell, Michael Opdenacker,
	Guodong Xu, Hendrik Hamerlinck, Yangyu Chen, spacemit,
	linux-riscv, devicetree, linux-kernel
In-Reply-To: <20260331034539.67167-1-sandie.cao@deepcomputing.io>

On Tue, Mar 31, 2026 at 11:45:39AM +0800, Sandie Cao wrote:
> From: sandiecao <sandie.cao@deepcomputing.io>
> 
> Document the compatible string for the Deepcomputing fml13v05.
> It's based on the SpacemiT K3 RISC-V SoC and is designed for the Framework
> Laptop 13 Chassis, which has (Framework) SKU FRANHQ0001.
> 
> Signed-off-by: sandiecao <sandie.cao@deepcomputing.io>

Name feels clsoe to login name and even login name has a '.' in the
middle, so a bit tricky to judge. Please clarify your name.

> Reviewed-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>

Is the review coming from some internal sysstems or downstream forks? If
so, does the review checks the same things as upstream is expected,
including known identity in DCO?


Best regards,
Krzysztof


^ permalink raw reply

* [PATCH v6 09/10] dmaengine: tegra: Add Tegra264 support
From: Akhil R @ 2026-03-31 10:23 UTC (permalink / raw)
  To: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
	Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
  Cc: Akhil R, Frank Li
In-Reply-To: <20260331102303.33181-1-akhilrajeev@nvidia.com>

Add compatible and chip data to support GPCDMA in Tegra264, which has
differences in register layout and address bits compared to previous
versions.

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/dma/tegra186-gpc-dma.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
index cd480d047204..2383a2fe73f1 100644
--- a/drivers/dma/tegra186-gpc-dma.c
+++ b/drivers/dma/tegra186-gpc-dma.c
@@ -1319,6 +1319,23 @@ static const struct tegra_dma_channel_regs tegra186_reg_offsets = {
 	.fixed_pattern = 0x34,
 };
 
+static const struct tegra_dma_channel_regs tegra264_reg_offsets = {
+	.csr = 0x0,
+	.status = 0x4,
+	.csre = 0x8,
+	.src = 0xc,
+	.dst = 0x10,
+	.src_high = 0x14,
+	.dst_high = 0x18,
+	.mc_seq = 0x1c,
+	.mmio_seq = 0x20,
+	.wcount = 0x24,
+	.wxfer = 0x28,
+	.wstatus = 0x2c,
+	.err_status = 0x34,
+	.fixed_pattern = 0x38,
+};
+
 static const struct tegra_dma_chip_data tegra186_dma_chip_data = {
 	.nr_channels = 32,
 	.addr_bits = 39,
@@ -1349,6 +1366,16 @@ static const struct tegra_dma_chip_data tegra234_dma_chip_data = {
 	.terminate = tegra_dma_pause_noerr,
 };
 
+static const struct tegra_dma_chip_data tegra264_dma_chip_data = {
+	.nr_channels = 32,
+	.addr_bits = 41,
+	.channel_reg_size = SZ_64K,
+	.max_dma_count = SZ_1G,
+	.hw_support_pause = true,
+	.channel_regs = &tegra264_reg_offsets,
+	.terminate = tegra_dma_pause_noerr,
+};
+
 static const struct of_device_id tegra_dma_of_match[] = {
 	{
 		.compatible = "nvidia,tegra186-gpcdma",
@@ -1359,6 +1386,9 @@ static const struct of_device_id tegra_dma_of_match[] = {
 	}, {
 		.compatible = "nvidia,tegra234-gpcdma",
 		.data = &tegra234_dma_chip_data,
+	}, {
+		.compatible = "nvidia,tegra264-gpcdma",
+		.data = &tegra264_dma_chip_data,
 	}, {
 	},
 };
-- 
2.50.1


^ permalink raw reply related

* [PATCH v6 10/10] arm64: tegra: Enable GPCDMA in Tegra264 and add iommu-map
From: Akhil R @ 2026-03-31 10:23 UTC (permalink / raw)
  To: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
	Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
  Cc: Akhil R
In-Reply-To: <20260331102303.33181-1-akhilrajeev@nvidia.com>

Enable GPCDMA in Tegra264 and add the iommu-map property so that each
channel uses a separate stream ID and gets its own IOMMU domain for
memory.

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra264-p3834.dtsi | 4 ++++
 arch/arm64/boot/dts/nvidia/tegra264.dtsi       | 1 +
 2 files changed, 5 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra264-p3834.dtsi b/arch/arm64/boot/dts/nvidia/tegra264-p3834.dtsi
index 7e2c3e66c2ab..58cd81bc33d7 100644
--- a/arch/arm64/boot/dts/nvidia/tegra264-p3834.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra264-p3834.dtsi
@@ -9,6 +9,10 @@ aliases {
 	};
 
 	bus@0 {
+		dma-controller@8400000 {
+			status = "okay";
+		};
+
 		serial@c4e0000 {
 			status = "okay";
 		};
diff --git a/arch/arm64/boot/dts/nvidia/tegra264.dtsi b/arch/arm64/boot/dts/nvidia/tegra264.dtsi
index af077420d7d9..b2f20d4b567a 100644
--- a/arch/arm64/boot/dts/nvidia/tegra264.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra264.dtsi
@@ -3244,6 +3244,7 @@ gpcdma: dma-controller@8400000 {
 				     <GIC_SPI 615 IRQ_TYPE_LEVEL_HIGH>;
 			#dma-cells = <1>;
 			iommus = <&smmu1 0x00000800>;
+			iommu-map = <1 &smmu1 0x801 31>;
 			dma-coherent;
 			dma-channel-mask = <0xfffffffe>;
 			status = "disabled";
-- 
2.50.1


^ permalink raw reply related

* Re: [PATCH v5 09/11] mfd: bq257xx: Add BQ25792 support
From: Lee Jones @ 2026-03-31 10:27 UTC (permalink / raw)
  To: Alexey Charkov
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chris Morgan,
	Liam Girdwood, Mark Brown, Sebastian Reichel, devicetree,
	linux-kernel, Sebastian Reichel, linux-pm
In-Reply-To: <20260324-bq25792-v5-9-0a2eb58cf11d@flipper.net>

On Tue, 24 Mar 2026, Alexey Charkov wrote:

> Add register definitions and a new 'type' enum to be passed via MFD
> private data to support the BQ25792, which is a newer variant of the
> BQ257xx family.
> 
> BQ25792 shares similar logic of operation with the already supported
> BQ25703A but has a completely different register map and different
> electrical constraints.
> 
> Tested-by: Chris Morgan <macromorgan@hotmail.com>
> Signed-off-by: Alexey Charkov <alchark@flipper.net>
> ---
>  drivers/mfd/bq257xx.c       |  54 +++++-
>  include/linux/mfd/bq257xx.h | 412 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 463 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mfd/bq257xx.c b/drivers/mfd/bq257xx.c
> index e9d49dac0a16..31654925afa5 100644
> --- a/drivers/mfd/bq257xx.c
> +++ b/drivers/mfd/bq257xx.c
> @@ -39,6 +39,39 @@ static const struct regmap_config bq25703_regmap_config = {
>  	.val_format_endian = REGMAP_ENDIAN_LITTLE,
>  };
>  
> +static const struct regmap_range bq25792_writeable_reg_ranges[] = {
> +	regmap_reg_range(BQ25792_REG00_MIN_SYS_VOLTAGE,
> +			 BQ25792_REG18_NTC_CONTROL_1),
> +	regmap_reg_range(BQ25792_REG28_CHARGER_MASK_0,
> +			 BQ25792_REG30_ADC_FUNCTION_DISABLE_1),
> +};
> +
> +static const struct regmap_access_table bq25792_writeable_regs = {
> +	.yes_ranges = bq25792_writeable_reg_ranges,
> +	.n_yes_ranges = ARRAY_SIZE(bq25792_writeable_reg_ranges),
> +};
> +
> +static const struct regmap_range bq25792_volatile_reg_ranges[] = {
> +	regmap_reg_range(BQ25792_REG19_ICO_CURRENT_LIMIT,
> +			 BQ25792_REG27_FAULT_FLAG_1),
> +	regmap_reg_range(BQ25792_REG31_IBUS_ADC,
> +			 BQ25792_REG47_DPDM_DRIVER),
> +};
> +
> +static const struct regmap_access_table bq25792_volatile_regs = {
> +	.yes_ranges = bq25792_volatile_reg_ranges,
> +	.n_yes_ranges = ARRAY_SIZE(bq25792_volatile_reg_ranges),
> +};
> +
> +static const struct regmap_config bq25792_regmap_config = {
> +	.reg_bits = 8,
> +	.val_bits = 8,
> +	.max_register = BQ25792_REG48_PART_INFORMATION,
> +	.cache_type = REGCACHE_MAPLE,
> +	.wr_table = &bq25792_writeable_regs,
> +	.volatile_table = &bq25792_volatile_regs,
> +};
> +
>  static const struct mfd_cell cells[] = {
>  	MFD_CELL_NAME("bq257xx-regulator"),
>  	MFD_CELL_NAME("bq257xx-charger"),
> @@ -46,6 +79,7 @@ static const struct mfd_cell cells[] = {
>  
>  static int bq257xx_probe(struct i2c_client *client)
>  {
> +	const struct regmap_config *rcfg;
>  	struct bq257xx_device *ddata;
>  	int ret;
>  
> @@ -53,9 +87,21 @@ static int bq257xx_probe(struct i2c_client *client)
>  	if (!ddata)
>  		return -ENOMEM;
>  
> +	ddata->type = (uintptr_t)i2c_get_match_data(client);
>  	ddata->client = client;
>  
> -	ddata->regmap = devm_regmap_init_i2c(client, &bq25703_regmap_config);
> +	switch (ddata->type) {
> +	case BQ25703A:
> +		rcfg = &bq25703_regmap_config;
> +		break;
> +	case BQ25792:
> +		rcfg = &bq25792_regmap_config;
> +		break;
> +	default:
> +		return dev_err_probe(&client->dev, -EINVAL, "Unsupported device type\n");

Nit: Shouldn't we be returning '-ENODEV' here for an unsupported device?

> +	}
> +
> +	ddata->regmap = devm_regmap_init_i2c(client, rcfg);
>  	if (IS_ERR(ddata->regmap)) {
>  		return dev_err_probe(&client->dev, PTR_ERR(ddata->regmap),
>  				     "Failed to allocate register map\n");
> @@ -73,13 +119,15 @@ static int bq257xx_probe(struct i2c_client *client)
>  }
>  
>  static const struct i2c_device_id bq257xx_i2c_ids[] = {
> -	{ "bq25703a" },
> +	{ "bq25703a", BQ25703A },
> +	{ "bq25792", BQ25792 },
>  	{}
>  };
>  MODULE_DEVICE_TABLE(i2c, bq257xx_i2c_ids);
>  
>  static const struct of_device_id bq257xx_of_match[] = {
> -	{ .compatible = "ti,bq25703a" },
> +	{ .compatible = "ti,bq25703a", .data = (void *)BQ25703A },
> +	{ .compatible = "ti,bq25792", .data = (void *)BQ25792 },
>  	{}
>  };
>  MODULE_DEVICE_TABLE(of, bq257xx_of_match);
> diff --git a/include/linux/mfd/bq257xx.h b/include/linux/mfd/bq257xx.h
> index 1d6ddc7fb09f..4ec72eb920f2 100644
> --- a/include/linux/mfd/bq257xx.h
> +++ b/include/linux/mfd/bq257xx.h
> @@ -98,7 +98,419 @@
>  
>  #define BQ25703_EN_OTG_MASK			BIT(12)
>  
> +#define BQ25792_REG00_MIN_SYS_VOLTAGE		0x00
> +#define BQ25792_REG01_CHARGE_VOLTAGE_LIMIT	0x01
> +#define BQ25792_REG03_CHARGE_CURRENT_LIMIT	0x03
> +#define BQ25792_REG05_INPUT_VOLTAGE_LIMIT	0x05
> +#define BQ25792_REG06_INPUT_CURRENT_LIMIT	0x06
> +#define BQ25792_REG08_PRECHARGE_CONTROL		0x08
> +#define BQ25792_REG09_TERMINATION_CONTROL	0x09
> +#define BQ25792_REG0A_RECHARGE_CONTROL		0x0a
> +#define BQ25792_REG0B_VOTG_REGULATION		0x0b
> +#define BQ25792_REG0D_IOTG_REGULATION		0x0d
> +#define BQ25792_REG0E_TIMER_CONTROL		0x0e
> +#define BQ25792_REG0F_CHARGER_CONTROL_0		0x0f
> +#define BQ25792_REG10_CHARGER_CONTROL_1		0x10
> +#define BQ25792_REG11_CHARGER_CONTROL_2		0x11
> +#define BQ25792_REG12_CHARGER_CONTROL_3		0x12
> +#define BQ25792_REG13_CHARGER_CONTROL_4		0x13
> +#define BQ25792_REG14_CHARGER_CONTROL_5		0x14
> +/* REG15 reserved */
> +#define BQ25792_REG16_TEMPERATURE_CONTROL	0x16
> +#define BQ25792_REG17_NTC_CONTROL_0		0x17
> +#define BQ25792_REG18_NTC_CONTROL_1		0x18
> +#define BQ25792_REG19_ICO_CURRENT_LIMIT		0x19
> +#define BQ25792_REG1B_CHARGER_STATUS_0		0x1b
> +#define BQ25792_REG1C_CHARGER_STATUS_1		0x1c
> +#define BQ25792_REG1D_CHARGER_STATUS_2		0x1d
> +#define BQ25792_REG1E_CHARGER_STATUS_3		0x1e
> +#define BQ25792_REG1F_CHARGER_STATUS_4		0x1f
> +#define BQ25792_REG20_FAULT_STATUS_0		0x20
> +#define BQ25792_REG21_FAULT_STATUS_1		0x21
> +#define BQ25792_REG22_CHARGER_FLAG_0		0x22
> +#define BQ25792_REG23_CHARGER_FLAG_1		0x23
> +#define BQ25792_REG24_CHARGER_FLAG_2		0x24
> +#define BQ25792_REG25_CHARGER_FLAG_3		0x25
> +#define BQ25792_REG26_FAULT_FLAG_0		0x26
> +#define BQ25792_REG27_FAULT_FLAG_1		0x27
> +#define BQ25792_REG28_CHARGER_MASK_0		0x28
> +#define BQ25792_REG29_CHARGER_MASK_1		0x29
> +#define BQ25792_REG2A_CHARGER_MASK_2		0x2a
> +#define BQ25792_REG2B_CHARGER_MASK_3		0x2b
> +#define BQ25792_REG2C_FAULT_MASK_0		0x2c
> +#define BQ25792_REG2D_FAULT_MASK_1		0x2d
> +#define BQ25792_REG2E_ADC_CONTROL		0x2e
> +#define BQ25792_REG2F_ADC_FUNCTION_DISABLE_0	0x2f
> +#define BQ25792_REG30_ADC_FUNCTION_DISABLE_1	0x30
> +#define BQ25792_REG31_IBUS_ADC			0x31
> +#define BQ25792_REG33_IBAT_ADC			0x33
> +#define BQ25792_REG35_VBUS_ADC			0x35
> +#define BQ25792_REG37_VAC1_ADC			0x37
> +#define BQ25792_REG39_VAC2_ADC			0x39
> +#define BQ25792_REG3B_VBAT_ADC			0x3b
> +#define BQ25792_REG3D_VSYS_ADC			0x3d
> +#define BQ25792_REG3F_TS_ADC			0x3f
> +#define BQ25792_REG41_TDIE_ADC			0x41
> +#define BQ25792_REG43_DP_ADC			0x43
> +#define BQ25792_REG45_DM_ADC			0x45
> +#define BQ25792_REG47_DPDM_DRIVER		0x47
> +#define BQ25792_REG48_PART_INFORMATION		0x48
> +
> +/* Minimal System Voltage */
> +#define BQ25792_REG00_VSYSMIN_MASK		GENMASK(5, 0)
> +
> +#define BQ25792_MINVSYS_MIN_UV			2500000
> +#define BQ25792_MINVSYS_STEP_UV			250000
> +#define BQ25792_MINVSYS_MAX_UV			16000000
> +
> +/* Charge Voltage Limit */
> +#define BQ25792_REG01_VREG_MASK			GENMASK(10, 0)
> +
> +#define BQ25792_VBATREG_MIN_UV			3000000
> +#define BQ25792_VBATREG_STEP_UV			10000
> +#define BQ25792_VBATREG_MAX_UV			18800000
> +
> +/* Charge Current Limit */
> +#define BQ25792_REG03_ICHG_MASK			GENMASK(8, 0)
> +
> +#define BQ25792_ICHG_MIN_UA			50000
> +#define BQ25792_ICHG_STEP_UA			10000
> +#define BQ25792_ICHG_MAX_UA			5000000
> +
> +/* Input Voltage Limit */
> +#define BQ25792_REG05_VINDPM_MASK		GENMASK(7, 0)
> +
> +/* Input Current Limit */
> +#define BQ25792_REG06_IINDPM_MASK		GENMASK(8, 0)
> +#define BQ25792_IINDPM_DEFAULT_UA		3000000
> +#define BQ25792_IINDPM_STEP_UA			10000
> +#define BQ25792_IINDPM_MIN_UA			100000
> +#define BQ25792_IINDPM_MAX_UA			3300000
> +
> +/* Precharge Control */
> +#define BQ25792_REG08_VBAT_LOWV_MASK		GENMASK(7, 6)
> +#define BQ25792_REG08_IPRECHG_MASK		GENMASK(5, 0)
> +
> +/* Termination Control */
> +#define BQ25792_REG09_REG_RST			BIT(6)
> +#define BQ25792_REG09_ITERM_MASK		GENMASK(4, 0)
> +
> +/* Re-charge Control */
> +#define BQ25792_REG0A_CELL_MASK			GENMASK(7, 6)
> +#define BQ25792_REG0A_TRECHG_MASK		GENMASK(5, 4)
> +#define BQ25792_REG0A_VRECHG_MASK		GENMASK(3, 0)
> +
> +/* VOTG regulation */
> +#define BQ25792_REG0B_VOTG_MASK			GENMASK(10, 0)
> +
> +#define BQ25792_OTG_VOLT_MIN_UV			2800000
> +#define BQ25792_OTG_VOLT_STEP_UV		10000
> +#define BQ25792_OTG_VOLT_MAX_UV			22000000
> +#define BQ25792_OTG_VOLT_NUM_VOLT		((BQ25792_OTG_VOLT_MAX_UV \
> +						  - BQ25792_OTG_VOLT_MIN_UV) \
> +						  / BQ25792_OTG_VOLT_STEP_UV + 1)
> +
> +/* IOTG regulation */
> +#define BQ25792_REG0D_PRECHG_TMR		BIT(7)
> +#define BQ25792_REG0D_IOTG_MASK			GENMASK(6, 0)
> +
> +#define BQ25792_OTG_CUR_MIN_UA		120000
> +#define BQ25792_OTG_CUR_STEP_UA		40000
> +#define BQ25792_OTG_CUR_MAX_UA		3320000
> +
> +/* Timer Control */
> +#define BQ25792_REG0E_TOPOFF_TMR_MASK		GENMASK(7, 6)
> +#define BQ25792_REG0E_EN_TRICHG_TMR		BIT(5)
> +#define BQ25792_REG0E_EN_PRECHG_TMR		BIT(4)
> +#define BQ25792_REG0E_EN_CHG_TMR		BIT(3)
> +#define BQ25792_REG0E_CHG_TMR_MASK		GENMASK(2, 1)
> +#define BQ25792_REG0E_TMR2X_EN			BIT(0)
> +
> +/* Charger Control 0 */
> +#define BQ25792_REG0F_EN_AUTO_IBATDIS		BIT(7)
> +#define BQ25792_REG0F_FORCE_IBATDIS		BIT(6)
> +#define BQ25792_REG0F_EN_CHG			BIT(5)
> +#define BQ25792_REG0F_EN_ICO			BIT(4)
> +#define BQ25792_REG0F_FORCE_ICO			BIT(3)
> +#define BQ25792_REG0F_EN_HIZ			BIT(2)
> +#define BQ25792_REG0F_EN_TERM			BIT(1)
> +/* bit0 reserved */
> +
> +/* Charger Control 1 */
> +#define BQ25792_REG10_VAC_OVP_MASK		GENMASK(5, 4)
> +#define BQ25792_REG10_WD_RST			BIT(3)
> +#define BQ25792_REG10_WATCHDOG_MASK		GENMASK(2, 0)
> +
> +/* Charger Control 2 */
> +#define BQ25792_REG11_FORCE_INDET		BIT(7)
> +#define BQ25792_REG11_AUTO_INDET_EN		BIT(6)
> +#define BQ25792_REG11_EN_12V			BIT(5)
> +#define BQ25792_REG11_EN_9V			BIT(4)
> +#define BQ25792_REG11_HVDCP_EN			BIT(3)
> +#define BQ25792_REG11_SDRV_CTRL_MASK		GENMASK(2, 1)
> +#define BQ25792_REG11_SDRV_DLY			BIT(0)
> +
> +/* Charger Control 3 */
> +#define BQ25792_REG12_DIS_ACDRV			BIT(7)
> +#define BQ25792_REG12_EN_OTG			BIT(6)
> +#define BQ25792_REG12_PFM_OTG_DIS		BIT(5)
> +#define BQ25792_REG12_PFM_FWD_DIS		BIT(4)
> +#define BQ25792_REG12_WKUP_DLY			BIT(3)
> +#define BQ25792_REG12_DIS_LDO			BIT(2)
> +#define BQ25792_REG12_DIS_OTG_OOA		BIT(1)
> +#define BQ25792_REG12_DIS_FWD_OOA		BIT(0)
> +
> +/* Charger Control 4 */
> +#define BQ25792_REG13_EN_ACDRV2			BIT(7)
> +#define BQ25792_REG13_EN_ACDRV1			BIT(6)
> +#define BQ25792_REG13_PWM_FREQ			BIT(5)
> +#define BQ25792_REG13_DIS_STAT			BIT(4)
> +#define BQ25792_REG13_DIS_VSYS_SHORT		BIT(3)
> +#define BQ25792_REG13_DIS_VOTG_UVP		BIT(2)
> +#define BQ25792_REG13_FORCE_VINDPM_DET		BIT(1)
> +#define BQ25792_REG13_EN_IBUS_OCP		BIT(0)
> +
> +/* Charger Control 5 */
> +#define BQ25792_REG14_SFET_PRESENT		BIT(7)
> +/* bit6 reserved */
> +#define BQ25792_REG14_EN_IBAT			BIT(5)
> +#define BQ25792_REG14_IBAT_REG_MASK		GENMASK(4, 3)
> +#define BQ25792_REG14_EN_IINDPM			BIT(2)
> +#define BQ25792_REG14_EN_EXTILIM		BIT(1)
> +#define BQ25792_REG14_EN_BATOC			BIT(0)
> +
> +#define BQ25792_IBAT_3A				FIELD_PREP(BQ25792_REG14_IBAT_REG_MASK, 0)
> +#define BQ25792_IBAT_4A				FIELD_PREP(BQ25792_REG14_IBAT_REG_MASK, 1)
> +#define BQ25792_IBAT_5A				FIELD_PREP(BQ25792_REG14_IBAT_REG_MASK, 2)
> +#define BQ25792_IBAT_UNLIM			FIELD_PREP(BQ25792_REG14_IBAT_REG_MASK, 3)
> +
> +/* Temperature Control */
> +#define BQ25792_REG16_TREG_MASK			GENMASK(7, 6)
> +#define BQ25792_REG16_TSHUT_MASK		GENMASK(5, 4)
> +#define BQ25792_REG16_VBUS_PD_EN		BIT(3)
> +#define BQ25792_REG16_VAC1_PD_EN		BIT(2)
> +#define BQ25792_REG16_VAC2_PD_EN		BIT(1)
> +
> +/* NTC Control 0 */
> +#define BQ25792_REG17_JEITA_VSET_MASK		GENMASK(7, 5)
> +#define BQ25792_REG17_JEITA_ISETH_MASK		GENMASK(4, 3)
> +#define BQ25792_REG17_JEITA_ISETC_MASK		GENMASK(2, 1)
> +
> +/* NTC Control 1 */
> +#define BQ25792_REG18_TS_COOL_MASK		GENMASK(7, 6)
> +#define BQ25792_REG18_TS_WARM_MASK		GENMASK(5, 4)
> +#define BQ25792_REG18_BHOT_MASK			GENMASK(3, 2)
> +#define BQ25792_REG18_BCOLD			BIT(1)
> +#define BQ25792_REG18_TS_IGNORE			BIT(0)
> +
> +/* ICO Current Limit */
> +#define BQ25792_REG19_ICO_ILIM_MASK		GENMASK(8, 0)
> +
> +/* Charger Status 0 */
> +#define BQ25792_REG1B_IINDPM_STAT		BIT(7)
> +#define BQ25792_REG1B_VINDPM_STAT		BIT(6)
> +#define BQ25792_REG1B_WD_STAT			BIT(5)
> +#define BQ25792_REG1B_POORSRC_STAT		BIT(4)
> +#define BQ25792_REG1B_PG_STAT			BIT(3)
> +#define BQ25792_REG1B_AC2_PRESENT_STAT		BIT(2)
> +#define BQ25792_REG1B_AC1_PRESENT_STAT		BIT(1)
> +#define BQ25792_REG1B_VBUS_PRESENT_STAT		BIT(0)
> +
> +/* Charger Status 1 */
> +#define BQ25792_REG1C_CHG_STAT_MASK		GENMASK(7, 5)
> +#define BQ25792_REG1C_VBUS_STAT_MASK		GENMASK(4, 1)
> +#define BQ25792_REG1C_BC12_DONE_STAT		BIT(0)
> +
> +/* Charger Status 2 */
> +#define BQ25792_REG1D_ICO_STAT_MASK		GENMASK(7, 6)
> +#define BQ25792_REG1D_TREG_STAT			BIT(2)
> +#define BQ25792_REG1D_DPDM_STAT			BIT(1)
> +#define BQ25792_REG1D_VBAT_PRESENT_STAT		BIT(0)
> +
> +/* Charger Status 3 */
> +#define BQ25792_REG1E_ACRB2_STAT		BIT(7)
> +#define BQ25792_REG1E_ACRB1_STAT		BIT(6)
> +#define BQ25792_REG1E_ADC_DONE_STAT		BIT(5)
> +#define BQ25792_REG1E_VSYS_STAT			BIT(4)
> +#define BQ25792_REG1E_CHG_TMR_STAT		BIT(3)
> +#define BQ25792_REG1E_TRICHG_TMR_STAT		BIT(2)
> +#define BQ25792_REG1E_PRECHG_TMR_STAT		BIT(1)
> +
> +/* Charger Status 4 */
> +#define BQ25792_REG1F_VBATOTG_LOW_STAT		BIT(4)
> +#define BQ25792_REG1F_TS_COLD_STAT		BIT(3)
> +#define BQ25792_REG1F_TS_COOL_STAT		BIT(2)
> +#define BQ25792_REG1F_TS_WARM_STAT		BIT(1)
> +#define BQ25792_REG1F_TS_HOT_STAT		BIT(0)
> +
> +/* FAULT Status 0 */
> +#define BQ25792_REG20_IBAT_REG_STAT		BIT(7)
> +#define BQ25792_REG20_VBUS_OVP_STAT		BIT(6)
> +#define BQ25792_REG20_VBAT_OVP_STAT		BIT(5)
> +#define BQ25792_REG20_IBUS_OCP_STAT		BIT(4)
> +#define BQ25792_REG20_IBAT_OCP_STAT		BIT(3)
> +#define BQ25792_REG20_CONV_OCP_STAT		BIT(2)
> +#define BQ25792_REG20_VAC2_OVP_STAT		BIT(1)
> +#define BQ25792_REG20_VAC1_OVP_STAT		BIT(0)
> +
> +#define BQ25792_REG20_OVERVOLTAGE_MASK		(BQ25792_REG20_VBAT_OVP_STAT | \
> +						 BQ25792_REG20_VAC2_OVP_STAT | \
> +						 BQ25792_REG20_VAC1_OVP_STAT)
> +#define BQ25792_REG20_OVERCURRENT_MASK		(BQ25792_REG20_IBAT_OCP_STAT | \
> +						 BQ25792_REG20_CONV_OCP_STAT)
> +
> +/* FAULT Status 1 */
> +#define BQ25792_REG21_VSYS_SHORT_STAT		BIT(7)
> +#define BQ25792_REG21_VSYS_OVP_STAT		BIT(6)
> +#define BQ25792_REG21_OTG_OVP_STAT		BIT(5)
> +#define BQ25792_REG21_OTG_UVP_STAT		BIT(4)
> +#define BQ25792_REG21_TSHUT_STAT		BIT(2)
> +
> +
> +/* Charger Flag 0 */
> +#define BQ25792_REG22_IINDPM_FLAG		BIT(7)
> +#define BQ25792_REG22_VINDPM_FLAG		BIT(6)
> +#define BQ25792_REG22_WD_FLAG			BIT(5)
> +#define BQ25792_REG22_POORSRC_FLAG		BIT(4)
> +#define BQ25792_REG22_PG_FLAG			BIT(3)
> +#define BQ25792_REG22_AC2_PRESENT_FLAG		BIT(2)
> +#define BQ25792_REG22_AC1_PRESENT_FLAG		BIT(1)
> +#define BQ25792_REG22_VBUS_PRESENT_FLAG		BIT(0)
> +
> +/* Charger Flag 1 */
> +#define BQ25792_REG23_CHG_FLAG			BIT(7)
> +#define BQ25792_REG23_ICO_FLAG			BIT(6)
> +#define BQ25792_REG23_VBUS_FLAG			BIT(4)
> +#define BQ25792_REG23_TREG_FLAG			BIT(2)
> +#define BQ25792_REG23_VBAT_PRESENT_FLAG		BIT(1)
> +#define BQ25792_REG23_BC12_DONE_FLAG		BIT(0)
> +
> +/* Charger Flag 2 */
> +#define BQ25792_REG24_DPDM_DONE_FLAG		BIT(6)
> +#define BQ25792_REG24_ADC_DONE_FLAG		BIT(5)
> +#define BQ25792_REG24_VSYS_FLAG			BIT(4)
> +#define BQ25792_REG24_CHG_TMR_FLAG		BIT(3)
> +#define BQ25792_REG24_TRICHG_TMR_FLAG		BIT(2)
> +#define BQ25792_REG24_PRECHG_TMR_FLAG		BIT(1)
> +#define BQ25792_REG24_TOPOFF_TMR_FLAG		BIT(0)
> +
> +/* Charger Flag 3 */
> +#define BQ25792_REG25_VBATOTG_LOW_FLAG		BIT(4)
> +#define BQ25792_REG25_TS_COLD_FLAG		BIT(3)
> +#define BQ25792_REG25_TS_COOL_FLAG		BIT(2)
> +#define BQ25792_REG25_TS_WARM_FLAG		BIT(1)
> +#define BQ25792_REG25_TS_HOT_FLAG		BIT(0)
> +
> +/* FAULT Flag 0 */
> +#define BQ25792_REG26_IBAT_REG_FLAG		BIT(7)
> +#define BQ25792_REG26_VBUS_OVP_FLAG		BIT(6)
> +#define BQ25792_REG26_VBAT_OVP_FLAG		BIT(5)
> +#define BQ25792_REG26_IBUS_OCP_FLAG		BIT(4)
> +#define BQ25792_REG26_IBAT_OCP_FLAG		BIT(3)
> +#define BQ25792_REG26_CONV_OCP_FLAG		BIT(2)
> +#define BQ25792_REG26_VAC2_OVP_FLAG		BIT(1)
> +#define BQ25792_REG26_VAC1_OVP_FLAG		BIT(0)
> +
> +/* FAULT Flag 1 */
> +#define BQ25792_REG27_VSYS_SHORT_FLAG		BIT(7)
> +#define BQ25792_REG27_VSYS_OVP_FLAG		BIT(6)
> +#define BQ25792_REG27_OTG_OVP_FLAG		BIT(5)
> +#define BQ25792_REG27_OTG_UVP_FLAG		BIT(4)
> +#define BQ25792_REG27_TSHUT_FLAG		BIT(2)
> +
> +/* Charger Mask 0 */
> +#define BQ25792_REG28_IINDPM_MASK		BIT(7)
> +#define BQ25792_REG28_VINDPM_MASK		BIT(6)
> +#define BQ25792_REG28_WD_MASK			BIT(5)
> +#define BQ25792_REG28_POORSRC_MASK		BIT(4)
> +#define BQ25792_REG28_PG_MASK			BIT(3)
> +#define BQ25792_REG28_AC2_PRESENT_MASK		BIT(2)
> +#define BQ25792_REG28_AC1_PRESENT_MASK		BIT(1)
> +#define BQ25792_REG28_VBUS_PRESENT_MASK		BIT(0)
> +
> +/* Charger Mask 1 */
> +#define BQ25792_REG29_CHG_MASK			BIT(7)
> +#define BQ25792_REG29_ICO_MASK			BIT(6)
> +#define BQ25792_REG29_VBUS_MASK			BIT(4)
> +#define BQ25792_REG29_TREG_MASK			BIT(2)
> +#define BQ25792_REG29_VBAT_PRESENT_MASK		BIT(1)
> +#define BQ25792_REG29_BC12_DONE_MASK		BIT(0)
> +
> +/* Charger Mask 2 */
> +#define BQ25792_REG2A_DPDM_DONE_MASK		BIT(6)
> +#define BQ25792_REG2A_ADC_DONE_MASK		BIT(5)
> +#define BQ25792_REG2A_VSYS_MASK			BIT(4)
> +#define BQ25792_REG2A_CHG_TMR_MASK		BIT(3)
> +#define BQ25792_REG2A_TRICHG_TMR_MASK		BIT(2)
> +#define BQ25792_REG2A_PRECHG_TMR_MASK		BIT(1)
> +#define BQ25792_REG2A_TOPOFF_TMR_MASK		BIT(0)
> +
> +/* Charger Mask 3 */
> +#define BQ25792_REG2B_VBATOTG_LOW_MASK		BIT(4)
> +#define BQ25792_REG2B_TS_COLD_MASK		BIT(3)
> +#define BQ25792_REG2B_TS_COOL_MASK		BIT(2)
> +#define BQ25792_REG2B_TS_WARM_MASK		BIT(1)
> +#define BQ25792_REG2B_TS_HOT_MASK		BIT(0)
> +
> +/* FAULT Mask 0 */
> +#define BQ25792_REG2C_IBAT_REG_MASK		BIT(7)
> +#define BQ25792_REG2C_VBUS_OVP_MASK		BIT(6)
> +#define BQ25792_REG2C_VBAT_OVP_MASK		BIT(5)
> +#define BQ25792_REG2C_IBUS_OCP_MASK		BIT(4)
> +#define BQ25792_REG2C_IBAT_OCP_MASK		BIT(3)
> +#define BQ25792_REG2C_CONV_OCP_MASK		BIT(2)
> +#define BQ25792_REG2C_VAC2_OVP_MASK		BIT(1)
> +#define BQ25792_REG2C_VAC1_OVP_MASK		BIT(0)
> +
> +/* FAULT Mask 1 */
> +#define BQ25792_REG2D_VSYS_SHORT_MASK		BIT(7)
> +#define BQ25792_REG2D_VSYS_OVP_MASK		BIT(6)
> +#define BQ25792_REG2D_OTG_OVP_MASK		BIT(5)
> +#define BQ25792_REG2D_OTG_UVP_MASK		BIT(4)
> +#define BQ25792_REG2D_TSHUT_MASK		BIT(2)
> +
> +/* ADC Control */
> +#define BQ25792_REG2E_ADC_EN			BIT(7)
> +#define BQ25792_REG2E_ADC_RATE			BIT(6)
> +#define BQ25792_REG2E_ADC_SAMPLE_MASK		GENMASK(5, 4)
> +#define BQ25792_REG2E_ADC_AVG			BIT(3)
> +#define BQ25792_REG2E_ADC_AVG_INIT		BIT(2)
> +
> +/* ADC Function Disable 0 */
> +#define BQ25792_REG2F_IBUS_ADC_DIS		BIT(7)
> +#define BQ25792_REG2F_IBAT_ADC_DIS		BIT(6)
> +#define BQ25792_REG2F_VBUS_ADC_DIS		BIT(5)
> +#define BQ25792_REG2F_VBAT_ADC_DIS		BIT(4)
> +#define BQ25792_REG2F_VSYS_ADC_DIS		BIT(3)
> +#define BQ25792_REG2F_TS_ADC_DIS		BIT(2)
> +#define BQ25792_REG2F_TDIE_ADC_DIS		BIT(1)
> +
> +/* ADC Function Disable 1 */
> +#define BQ25792_REG30_DP_ADC_DIS		BIT(7)
> +#define BQ25792_REG30_DM_ADC_DIS		BIT(6)
> +#define BQ25792_REG30_VAC2_ADC_DIS		BIT(5)
> +#define BQ25792_REG30_VAC1_ADC_DIS		BIT(4)
> +
> +/* 0x31-0x45: ADC result registers (16-bit, RO): single full-width field */
> +
> +#define BQ25792_ADCVSYSVBAT_STEP_UV		1000
> +#define BQ25792_ADCIBAT_STEP_UA			1000
> +
> +/* DPDM Driver */
> +#define BQ25792_REG47_DPLUS_DAC_MASK		GENMASK(7, 5)
> +#define BQ25792_REG47_DMINUS_DAC_MASK		GENMASK(4, 2)
> +
> +/* Part Information */
> +#define BQ25792_REG48_PN_MASK			GENMASK(5, 3)
> +#define BQ25792_REG48_DEV_REV_MASK		GENMASK(2, 0)
> +
> +enum bq257xx_type {
> +	BQ25703A = 1,
> +	BQ25792,
> +};
> +
>  struct bq257xx_device {
>  	struct i2c_client *client;
>  	struct regmap *regmap;
> +	enum bq257xx_type type;
>  };
> 
> -- 
> 2.52.0
> 

-- 
Lee Jones [李琼斯]

^ permalink raw reply

* Re: [PATCH v2 5/7] phy: ti: gmii-sel: add support for J722S SoC family
From: Nora Schiffer @ 2026-03-31 10:35 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Nishanth Menon, Vignesh Raghavendra, Tero Kristo,
	Siddharth Vadapalli, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Vinod Koul, Neil Armstrong, netdev, devicetree,
	linux-kernel, linux-phy, linux-arm-kernel, linux
In-Reply-To: <20260330223741.pmrx25cslrlpbcea@skbuf>

On Tue, 2026-03-31 at 01:37 +0300, Vladimir Oltean wrote:
> Hi Nora,
> 
> On Tue, Mar 24, 2026 at 01:29:41PM +0100, Nora Schiffer wrote:
> > The J722S gmii-sel is mostly identical to the AM64's, but additionally
> > supports SGMII.
> > 
> > Signed-off-by: Nora Schiffer <nora.schiffer@ew.tq-group.com>
> > ---
> >  drivers/phy/ti/phy-gmii-sel.c | 11 +++++++++++
> >  1 file changed, 11 insertions(+)
> > 
> > diff --git a/drivers/phy/ti/phy-gmii-sel.c b/drivers/phy/ti/phy-gmii-sel.c
> > index 6213c2b6005a5..4e242b1892334 100644
> > --- a/drivers/phy/ti/phy-gmii-sel.c
> > +++ b/drivers/phy/ti/phy-gmii-sel.c
> > @@ -251,6 +251,13 @@ struct phy_gmii_sel_soc_data phy_gmii_sel_soc_am654 = {
> >  	.regfields = phy_gmii_sel_fields_am654,
> >  };
> >  
> > +static const
> > +struct phy_gmii_sel_soc_data phy_gmii_sel_soc_j722s = {
> > +	.use_of_data = true,
> > +	.regfields = phy_gmii_sel_fields_am654,
> > +	.extra_modes = BIT(PHY_INTERFACE_MODE_SGMII),
> 
> I'm not familiar with the hardware, but "mostly identical to AM64, but
> additionally supports SGMII" does not explain why j722s does not inherit
> the features that am654 has (PHY_GMII_SEL_RGMII_ID_MODE and
> BIT(PHY_GMII_SEL_FIXED_TX_DELAY).
> 
> The phy-gmii-sel from j722s does support RGMII, right? Because in lack
> of the PHY_GMII_SEL_RGMII_ID_MODE feature, phy_gmii_sel_mode() will just
> silently skip the regmap_field_write(regfield, rgmii_id) call, and
> return successfully despite an incomplete configuration.
> 
> We have the phy_validate() call and phy_ops::validate() through which
> the PHY can report to the Ethernet controller which phy_interface_t it
> supports and which it doesn't. If the j722s doesn't support RGMII, maybe
> it should implement this method.

Thanks for noticing this, PHY_GMII_SEL_RGMII_ID_MODE and
PHY_GMII_SEL_FIXED_TX_DELAY are missing indeed - will fix in v3. I made the
mistake to rebase from an older kernel version where these flags didn't exist
yet and neglected to double check when the rebase went through without
conflicts. I assume I didn't notice any issues because our bootloader left the
controller in the correct state.

Best,
Nora


> 
> > +};
> > +

-- 
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
https://www.tq-group.com/

^ permalink raw reply

* [PATCH 0/3] arm64: dts: qcom: eliza: Add ADSP and USB support
From: Abel Vesa @ 2026-03-31 10:37 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: linux-arm-msm, devicetree, linux-kernel, Abel Vesa

The following patchsets document all necessary bindings:

https://lore.kernel.org/all/20260327-eliza-bindings-mailbox-ipcc-v1-1-3f1c89bdf72e@oss.qualcomm.com/
https://lore.kernel.org/all/20260327-eliza-remoteproc-adsp-v1-1-1c46c5e5f809@oss.qualcomm.com/
https://lore.kernel.org/all/20260327-eliza-bindings-phy-eusb2-v1-1-1f8a9ad6a033@oss.qualcomm.com/
https://lore.kernel.org/all/20260318-eliza-bindings-qmp-phy-v1-1-96a0d529ad2d@oss.qualcomm.com/
https://lore.kernel.org/all/20260327-eliza-bindings-dwc3-v2-1-28439482ebce@oss.qualcomm.com/
https://lore.kernel.org/all/20260327-eliza-bindings-aoss-v1-1-70df76adc69b@oss.qualcomm.com/
https://lore.kernel.org/all/20260327-eliza-bindings-pmic-glink-v1-1-f9a65495f599@oss.qualcomm.com/

Signed-off-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
---
Abel Vesa (3):
      arm64: dts: qcom: eliza: Describe the ADSP and USB related nodes
      arm64: dts: qcom: Add Eliza-specific PM7750BA dtsi
      arm64: dts: qcom: eliza-mtp: Enable USB and ADSP support

 arch/arm64/boot/dts/qcom/eliza-mtp.dts       |  83 +++++++++
 arch/arm64/boot/dts/qcom/eliza.dtsi          | 261 +++++++++++++++++++++++++++
 arch/arm64/boot/dts/qcom/pm7550ba-eliza.dtsi |  69 +++++++
 3 files changed, 413 insertions(+)
---
base-commit: 5e59a51e3378f5d31e1f4f8efcb9763db3e322cf
change-id: 20260330-eliza-adsp-usb-8ef2b1b0fc13

Best regards,
--  
Abel Vesa <abel.vesa@oss.qualcomm.com>


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox