* Re: [PATCH v2 2/2] iio: magnetometer: add support for Melexis MLX90393
From: Andy Shevchenko @ 2026-06-19 6:40 UTC (permalink / raw)
To: Nikhil Gautam
Cc: linux-iio, jic23, dlechner, nuno.sa, andy, robh, krzk+dt,
conor+dt, devicetree, linux-kernel
In-Reply-To: <98a08d17-5b70-4f4d-bf52-fe1073fde2b6@gmail.com>
On Fri, Jun 19, 2026 at 02:36:00AM +0530, Nikhil Gautam wrote:
> On 19-06-2026 12:56 am, Andy Shevchenko wrote:
> > On Thu, Jun 18, 2026 at 09:31:41PM +0530, Nikhil Gautam wrote:
>
> Thank you very much for taking the time to do such a thorough review of this
> patch series.
>
> Your detailed comments and suggestions are very helpful.
> I'll address the issues you've pointed out, update the cover letter to
> better explain the design decisions,
> and incorporate the requested coding style and API changes in the next
> revision.
>
> I appreciate your review and feedback.
You're welcome!
...
> > > +config MLX90393
> > > + tristate "MELEXIS MLX90393 3-axis magnetometer sensor"
> > > + depends on I2C
> > Why not a regmap?
> The MLX90393 uses both register-based and command-based transactions.
> Since regmap does not naturally model the command-based interface,
> using it would require workarounds such as virtual registers or bypass
> paths.
> A custom transport abstraction is therefore simpler and better suited for
> this device.
>
> I already discussed this on thread, Link :
> https://lore.kernel.org/linux-iio/20260423121834.4244-1-nikhilgtr@gmail.com/
Right, but please, put a summary in the commit message as it's important
detail of implementation choice.
...
> > > + for (unsigned int i = 0; i < MLX90393_OSR_MAX; i++)
> > > + if (mlx90393_osr_avail[i] == val) {
> > > + *osr = i;
> > > + return 0;
> > > + }
> > Missing {}.
> Agreed, removed intentionally as single statement, will add as per
> guidelines all the places
> where needed
It's also better to have them when it might be ambiguous. And also when even
a single statement takes a few lines. TL;DR: Also apply a common sense.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* [PATCH v6 2/2] arm64: dts: ti: Add audio overlay for k3-j721s2-evm
From: Moteen Shah @ 2026-06-19 6:27 UTC (permalink / raw)
To: krzk+dt, robh, conor+dt, nm, vigneshr, kristo
Cc: devicetree, linux-arm-kernel, linux-kernel, u-kumar1,
gehariprasath, y-abhilashchandra, m-shah, sen
In-Reply-To: <20260619062749.1575066-1-m-shah@ti.com>
From: Jayesh Choudhary <j-choudhary@ti.com>
Add device tree overlay to enable analog audio support on J721S2-EVM
using PCM3168A codec connected to McASP4 serializers.
- Add audio_refclk1 clock node to k3-j721s2-main.dtsi
- Add nodes for sound-card, audio codec, I2C3 and McASP4
- Add pinmux for I2C3, McASP4, AUDIO_EXT_REFCLK1 and WKUP_GPIO_0
- Add GPIO expander (TCA6408) for codec control
- Add GPIO hogs to route I2C3 lines and McASP serializers
- Set idle-state to 0 in mux0 and mux1 for McASP signal routing
Reviewed-by: Hari Prasath Gujulan Elango <gehariprasath@ti.com>
Signed-off-by: Jayesh Choudhary <j-choudhary@ti.com>
Co-developed-by: Moteen Shah <m-shah@ti.com>
Signed-off-by: Moteen Shah <m-shah@ti.com>
---
arch/arm64/boot/dts/ti/Makefile | 4 +
.../boot/dts/ti/k3-j721s2-evm-audio.dtso | 157 ++++++++++++++++++
arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi | 9 +
3 files changed, 170 insertions(+)
create mode 100644 arch/arm64/boot/dts/ti/k3-j721s2-evm-audio.dtso
diff --git a/arch/arm64/boot/dts/ti/Makefile b/arch/arm64/boot/dts/ti/Makefile
index 371f9a043fe52..d9824e17085f4 100644
--- a/arch/arm64/boot/dts/ti/Makefile
+++ b/arch/arm64/boot/dts/ti/Makefile
@@ -180,6 +180,7 @@ dtb-$(CONFIG_ARCH_K3) += k3-j721s2-common-proc-board.dtb
dtb-$(CONFIG_ARCH_K3) += k3-j721s2-evm-gesi-exp-board.dtbo
k3-j721s2-evm-dtbs := k3-j721s2-common-proc-board.dtb k3-j721s2-evm-gesi-exp-board.dtbo
dtb-$(CONFIG_ARCH_K3) += k3-j721s2-evm.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-j721s2-evm-audio.dtbo
dtb-$(CONFIG_ARCH_K3) += k3-j721s2-evm-pcie1-ep.dtbo
dtb-$(CONFIG_ARCH_K3) += k3-j721s2-evm-usb0-type-a.dtbo
@@ -320,6 +321,8 @@ k3-j721e-evm-pcie1-ep-dtbs := k3-j721e-common-proc-board.dtb \
k3-j721e-evm-pcie1-ep.dtbo
k3-j721e-sk-csi2-dual-imx219-dtbs := k3-j721e-sk.dtb \
k3-j721e-sk-csi2-dual-imx219.dtbo
+k3-j721s2-evm-audio-dtbs := k3-j721s2-common-proc-board.dtb \
+ k3-j721s2-evm-audio.dtbo
k3-j721s2-evm-pcie1-ep-dtbs := k3-j721s2-common-proc-board.dtb \
k3-j721s2-evm-pcie1-ep.dtbo
k3-j721s2-evm-usb0-type-a-dtbs := k3-j721s2-common-proc-board.dtb \
@@ -396,6 +399,7 @@ dtb- += k3-am625-beagleplay-csi2-ov5640.dtb \
k3-j721e-evm-pcie0-ep.dtb \
k3-j721e-evm-pcie1-ep.dtb \
k3-j721e-sk-csi2-dual-imx219.dtb \
+ k3-j721s2-evm-audio.dtb \
k3-j721s2-evm-pcie1-ep.dtb \
k3-j721s2-evm-usb0-type-a.dtb \
k3-j722s-evm-csi2-quad-rpi-cam-imx219.dtb \
diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-evm-audio.dtso b/arch/arm64/boot/dts/ti/k3-j721s2-evm-audio.dtso
new file mode 100644
index 0000000000000..ac5a827e1b750
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-evm-audio.dtso
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Device Tree Overlay for J721S2 Audio Support
+ *
+ * Copyright (C) 2026 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "k3-pinctrl.h"
+
+&{/} {
+ codec_audio: sound {
+ compatible = "ti,j7200-cpb-audio";
+ model = "j721s2-cpb";
+
+ ti,cpb-mcasp = <&mcasp4>;
+ ti,cpb-codec = <&pcm3168a_1>;
+
+ clocks = <&k3_clks 213 0>, <&k3_clks 213 1>,
+ <&k3_clks 157 299>, <&k3_clks 157 328>;
+ clock-names = "cpb-mcasp-auxclk", "cpb-mcasp-auxclk-48000",
+ "cpb-codec-scki", "cpb-codec-scki-48000";
+ };
+
+ i2c_mux: mux-controller-2 {
+ compatible = "gpio-mux";
+ #mux-state-cells = <1>;
+ mux-gpios = <&wkup_gpio0 54 GPIO_ACTIVE_HIGH>;
+ idle-state = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c3_mux_pins_default>;
+ };
+};
+
+&main_pmx0 {
+ mcasp4_pins_default: mcasp4-default-pins {
+ pinctrl-single,pins = <
+ J721S2_IOPAD(0x0c8, PIN_OUTPUT_PULLDOWN, 1) /* (AD28) MCASP4_ACLKX */
+ J721S2_IOPAD(0x06c, PIN_OUTPUT_PULLDOWN, 1) /* (V26) MCASP4_AFSX */
+ J721S2_IOPAD(0x068, PIN_INPUT_PULLDOWN, 1) /* (U28) MCASP4_AXR1 */
+ J721S2_IOPAD(0x0c4, PIN_OUTPUT_PULLDOWN, 1) /* (AB26) MCASP4_AXR2 */
+ J721S2_IOPAD(0x070, PIN_OUTPUT_PULLDOWN, 1) /* (R27) MCASP4_AXR3 */
+ >;
+ };
+
+ audio_ext_refclk1_pins_default: audio-ext-refclk1-default-pins {
+ pinctrl-single,pins = <
+ J721S2_IOPAD(0x078, PIN_OUTPUT, 1) /* (Y25) MCAN2_RX.AUDIO_EXT_REFCLK1 */
+ >;
+ };
+};
+
+&wkup_pmx2 {
+ main_i2c3_mux_pins_default: main-i2c3-mux-default-pins {
+ pinctrl-single,pins = <
+ J721S2_WKUP_IOPAD(0x038, PIN_OUTPUT, 7) /* (B27) WKUP_GPIO0_54 */
+ >;
+ };
+};
+
+&exp2 {
+ p09-hog {
+ /* P09 - MCASP/TRACE_MUX_S0 */
+ gpio-hog;
+ gpios = <9 GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "MCASP/TRACE_MUX_S0";
+ };
+
+ p10-hog {
+ /* P10 - MCASP/TRACE_MUX_S1 */
+ gpio-hog;
+ gpios = <10 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "MCASP/TRACE_MUX_S1";
+ };
+};
+
+&mux0 {
+ idle-state = <0>;
+};
+
+&mux1 {
+ idle-state = <0>;
+};
+
+&main_mcan3 {
+ /* Conflicts with McASP4 signal routing via mux0 */
+ status = "disabled";
+};
+
+&main_mcan5 {
+ /* Conflicts with McASP4 signal routing via mux1 */
+ status = "disabled";
+};
+
+&k3_clks {
+ /* Configure AUDIO_EXT_REFCLK1 pin as output */
+ pinctrl-names = "default";
+ pinctrl-0 = <&audio_ext_refclk1_pins_default>;
+};
+
+&main_i2c3 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c3_pins_default>;
+ clock-frequency = <400000>;
+ mux-states = <&i2c_mux 1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ exp3: gpio@20 {
+ compatible = "ti,tca6408";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-line-names = "CODEC_RSTZ", "CODEC_SPARE1",
+ "UB926_RESETN", "UB926_LOCK",
+ "UB926_PWR_SW_CNTRL", "UB926_TUNER_RESET",
+ "UB926_GPIO_SPARE";
+ };
+
+ pcm3168a_1: audio-codec@44 {
+ compatible = "ti,pcm3168a";
+ reg = <0x44>;
+ #sound-dai-cells = <1>;
+ reset-gpios = <&exp3 0 GPIO_ACTIVE_LOW>;
+ clocks = <&audio_refclk1>;
+ clock-names = "scki";
+ VDD1-supply = <&vsys_3v3>;
+ VDD2-supply = <&vsys_3v3>;
+ VCCAD1-supply = <&vsys_5v0>;
+ VCCAD2-supply = <&vsys_5v0>;
+ VCCDA1-supply = <&vsys_5v0>;
+ VCCDA2-supply = <&vsys_5v0>;
+ };
+};
+
+&mcasp4 {
+ status = "okay";
+ #sound-dai-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcasp4_pins_default>;
+ op-mode = <0>; /* MCASP_IIS_MODE */
+ tdm-slots = <2>;
+ auxclk-fs-ratio = <256>;
+ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
+ 0 2 1 1
+ 0 0 0 0
+ 0 0 0 0
+ 0 0 0 0
+ >;
+};
diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
index 1228ac5711bf0..36a01a06dd254 100644
--- a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
@@ -74,6 +74,15 @@ ehrpwm_tbclk: clock-controller@140 {
reg = <0x140 0x18>;
#clock-cells = <1>;
};
+
+ audio_refclk1: clock-controller@42e4 {
+ compatible = "ti,j721s2-audio-refclk", "ti,am62-audio-refclk";
+ reg = <0x42e4 0x4>;
+ clocks = <&k3_clks 157 299>;
+ assigned-clocks = <&k3_clks 157 299>;
+ assigned-clock-parents = <&k3_clks 157 328>;
+ #clock-cells = <0>;
+ };
};
main_ehrpwm0: pwm@3000000 {
--
2.34.1
^ permalink raw reply related
* [PATCH v6 1/2] dt-bindings: ti: Update audio-refclk binding and j721e system controller
From: Moteen Shah @ 2026-06-19 6:27 UTC (permalink / raw)
To: krzk+dt, robh, conor+dt, nm, vigneshr, kristo
Cc: devicetree, linux-arm-kernel, linux-kernel, u-kumar1,
gehariprasath, y-abhilashchandra, m-shah, sen
In-Reply-To: <20260619062749.1575066-1-m-shah@ti.com>
Add ti,j721s2-audio-refclk as a supported compatible string in the
ti,am62-audio-refclk binding. J721S2 uses the same audio reference
clock IP block first introduced on AM62. Per writing-bindings
guidelines, the J721S2-specific compatible is added as the primary
string with ti,am62-audio-refclk as the fallback.
Also extend the ti,j721e-system-controller clock-controller@ child
pattern to accept audio-refclk schemas alongside ehrpwm-tbclk via a
oneOf constraint, fixing the alphanumerical ordering of $refs.
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Moteen Shah <m-shah@ti.com>
---
.../devicetree/bindings/clock/ti,am62-audio-refclk.yaml | 8 ++++++--
.../bindings/soc/ti/ti,j721e-system-controller.yaml | 6 ++++--
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/clock/ti,am62-audio-refclk.yaml b/Documentation/devicetree/bindings/clock/ti,am62-audio-refclk.yaml
index b2e40bd39a3af..6c8fb0793070d 100644
--- a/Documentation/devicetree/bindings/clock/ti,am62-audio-refclk.yaml
+++ b/Documentation/devicetree/bindings/clock/ti,am62-audio-refclk.yaml
@@ -11,8 +11,12 @@ maintainers:
properties:
compatible:
- items:
- - const: ti,am62-audio-refclk
+ oneOf:
+ - items:
+ - const: ti,am62-audio-refclk
+ - items:
+ - const: ti,j721s2-audio-refclk
+ - const: ti,am62-audio-refclk
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/soc/ti/ti,j721e-system-controller.yaml b/Documentation/devicetree/bindings/soc/ti/ti,j721e-system-controller.yaml
index f3bd0be3b279f..364be49f8c7c7 100644
--- a/Documentation/devicetree/bindings/soc/ti/ti,j721e-system-controller.yaml
+++ b/Documentation/devicetree/bindings/soc/ti/ti,j721e-system-controller.yaml
@@ -53,9 +53,11 @@ patternProperties:
"^clock-controller@[0-9a-f]+$":
type: object
- $ref: /schemas/clock/ti,am654-ehrpwm-tbclk.yaml#
+ oneOf:
+ - $ref: /schemas/clock/ti,am62-audio-refclk.yaml#
+ - $ref: /schemas/clock/ti,am654-ehrpwm-tbclk.yaml#
description:
- Clock provider for TI EHRPWM nodes.
+ Clock provider for TI EHRPWM or Audio Reference Clock nodes.
"phy@[0-9a-f]+$":
type: object
--
2.34.1
^ permalink raw reply related
* [PATCH v6 0/2] Enable audio support for J721S2 EVM
From: Moteen Shah @ 2026-06-19 6:27 UTC (permalink / raw)
To: krzk+dt, robh, conor+dt, nm, vigneshr, kristo
Cc: devicetree, linux-arm-kernel, linux-kernel, u-kumar1,
gehariprasath, y-abhilashchandra, m-shah, sen
Earlier version of the patchset sent upstream[0] was rejected as
its dependency[1], which resolves the DTBS check errors introduced
by [0] also got rejected on the grounds of ABI breakage.
Another solution to fix the DTBS check errors introduced by [0] is
to modify the ti,j721e-system-controller.yaml binding to allow
audio-refclk as clock-controller child. This is done in the first
patch of this series.
Changes since v5:
Link to v5:
https://lore.kernel.org/all/20260520115603.2662930-1-m-shah@ti.com/
- Move audio_refclk1 clock node from the overlay (k3-j721s2-evm-audio.dtso)
to the main DTSI (k3-j721s2-main.dtsi) so it is always available
independent of the overlay being applied
- Drop the &scm_conf block from the overlay since it is now in main.dtsi
Changes since v4:
Link to v4:
https://lore.kernel.org/all/20260519142341.2531948-1-m-shah@ti.com/
- Explicitly disable main_mcan3 and main_mcan5 as they will silently
break mcasp audio routing
Link to v3:
https://lore.kernel.org/all/20260330094459.128648-1-m-shah@ti.com/
Link to v2:
https://lore.kernel.org/all/20260205130707.2033197-1-m-shah@ti.com/
Link to v1:
https://lore.kernel.org/all/20260112104536.83309-1-m-shah@ti.com/
Bootlogs:
https://gist.github.com/Jamm02/8ee551c2c8db3a58a9aa7976e049fa28
[0]: https://lore.kernel.org/linux-arm-kernel/20250604104656.38752-1-j-choudhary@ti.com/
[1]: https://lore.kernel.org/all/20250603095609.33569-4-j-choudhary@ti.com/
Jayesh Choudhary (1):
arm64: dts: ti: Add audio overlay for k3-j721s2-evm
Moteen Shah (1):
dt-bindings: ti: Update audio-refclk binding and j721e system
controller
.../bindings/clock/ti,am62-audio-refclk.yaml | 8 +-
.../soc/ti/ti,j721e-system-controller.yaml | 6 +-
arch/arm64/boot/dts/ti/Makefile | 4 +
.../boot/dts/ti/k3-j721s2-evm-audio.dtso | 157 ++++++++++++++++++
arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi | 9 +
5 files changed, 180 insertions(+), 4 deletions(-)
create mode 100644 arch/arm64/boot/dts/ti/k3-j721s2-evm-audio.dtso
--
2.34.1
^ permalink raw reply
* Re: [PATCH 2/2] thermal: qcom: Add support for Qualcomm MBG thermal monitoring
From: Sachin Gupta @ 2026-06-19 6:00 UTC (permalink / raw)
To: sashiko-reviews; +Cc: robh, devicetree, conor+dt
In-Reply-To: <20260601114035.2D9A81F00893@smtp.kernel.org>
On 6/1/2026 5:10 PM, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
> - [High] Data race and TOCTOU window on `last_thres_crossed` leading to missed thermal violations.
> - [High] Potential NULL pointer dereference accessing `node->name` on non-OF platforms.
> - [High] Incorrect bitwise AND used to check a 4-bit fault status enumeration.
> - [High] Silent disablement of supported thermal trips.
> - [Medium] Hardware threshold interrupt is enabled before configuring the threshold value.
> - [Low] Incompatible pointer type passed to `regmap_read`.
> --
>
> commit 59e6da95c48d5200129439570e254b1f9180acf4
> Author: Satya Priya Kakitapalli <quic_skakitap@quicinc.com>
> Subject: thermal: qcom: Add support for Qualcomm MBG thermal monitoring
>
> This patch adds a driver for the Qualcomm MBG thermal monitoring device.
> It monitors the die temperature and notifies the thermal framework when a
> level 1 upper threshold violation occurs via an SPMI interrupt.
>
>> diff --git a/drivers/thermal/qcom/qcom-spmi-mbg-tm.c b/drivers/thermal/qcom/qcom-spmi-mbg-tm.c
>> new file mode 100644
>> index 0000000000000..60190b341fc7c
>> --- /dev/null
>> +++ b/drivers/thermal/qcom/qcom-spmi-mbg-tm.c
>
> [ ... ]
>
>> +static int mbg_tm_get_temp(struct thermal_zone_device *tz, int *temp)
>> +{
>> + struct mbg_tm_chip *chip = thermal_zone_device_priv(tz);
>> + int ret, milli_celsius;
>> +
>> + if (chip->last_thres_crossed) {
>> + dev_dbg(chip->dev, "last_temp: %d\n", chip->last_temp);
>> + chip->last_thres_crossed = false;
>> + *temp = chip->last_temp;
>> + return 0;
>> + }
>
> [Severity: High]
> Could this lockless read and clear of chip->last_thres_crossed cause missed
> thermal violations?
>
> If a user-space sysfs read occurs concurrently with the thermal worker
> execution (which is triggered by the ISR), the sysfs read might consume the
> flag by setting it to false.
>
> When the thermal worker subsequently calls mbg_tm_get_temp(), it would see
> false and read the raw ADC value. Because ADC readings can fluctuate and
> lag, it might read a value below the threshold, entirely missing the
> violation.
>
I will address this by adding proper locking for this state in the next
patch series.
> [ ... ]
>
>> +static int mbg_tm_set_trip_temp(struct thermal_zone_device *tz, int low_temp,
>> + int temp)
>> +{
>> + struct mbg_tm_chip *chip = thermal_zone_device_priv(tz);
>> + int ret = 0;
>> +
>> + guard(mutex)(&chip->lock);
>> +
>> + /* The HW has a limitation that the trip set must be above 25C */
>> + if (temp > MBG_MIN_TRIP_TEMP && temp < MBG_MAX_SUPPORTED_TEMP) {
>> + ret = regmap_set_bits(chip->map, chip->base + MBG_TEMP_MON2_MISC_CFG,
>> + MON2_UP_THRESH_EN);
>> + if (ret < 0)
>> + return ret;
>> +
>> + ret = regmap_write(chip->map, chip->base + MON2_LVL1_UP_THRESH,
>> + temp_to_vtemp_mv(temp));
>
> [Severity: Medium]
> Is it safe to enable the threshold comparator before programming the new
> threshold value?
>
> If the hardware retains a stale threshold from a prior state that is lower
> than the current temperature, enabling the comparator first could
> immediately trigger a spurious interrupt.
>
> Would it be better to write the threshold value before enabling the
> interrupt?
>
You are right that enabling the comparator before programming
MON2_LVL1_UP_THRESH can allow a stale threshold to trigger a spurious
interrupt. I will update the programming sequence to write the threshold
first and enable the comparator afterward in the next patch series.
>> + if (ret < 0)
>> + return ret;
>> + } else {
>> + dev_dbg(chip->dev, "Set trip b/w 25C and 160C\n");
>> + ret = regmap_clear_bits(chip->map, chip->base + MBG_TEMP_MON2_MISC_CFG,
>> + MON2_UP_THRESH_EN);
>> + return ret;
>> + }
>
> [Severity: High]
> When the requested temperature falls outside the hardware's supported bounds,
> the driver disables the threshold interrupt and returns 0.
>
> By returning 0, does the driver deceptively signal to the thermal core that
> the trip has been successfully configured?
>
> Because the interrupt is disabled, the core will never be notified when the
> temperature violates the trip point. Should this return an error code like
> -ERANGE instead?
>
I agree returning 0 here is not correct for an out-of-range request,
since the trip is not actually configured. I will return -ERANGE for
unsupported trip temperatures and update this in the next patch series.
> [ ... ]
>
>> +static irqreturn_t mbg_tm_isr(int irq, void *data)
>> +{
>> + struct mbg_tm_chip *chip = data;
>> + int ret, val;
>
> [Severity: Low]
> The regmap_read() function expects an unsigned int pointer for the value
> parameter, but val is declared as a signed int here.
>
We can keep this as-is for now to stay consistent with the surrounding
driver style, where int is commonly used for temporary readback
variables with regmap_read(). Since the value is only used for bit
checks and not sign-sensitive arithmetic, this does not cause a
functional issue. I plan to keep it unchanged in this series for
consistency.
>> +
>> + scoped_guard(mutex, &chip->lock) {
>> + ret = regmap_read(chip->map, chip->base + MBG_TEMP_MON2_FAULT_STATUS, &val);
>> + if (ret < 0)
>> + return IRQ_HANDLED;
>> + }
>> +
>> + if (FIELD_GET(MON_FAULT_STATUS_MASK, val) & MON_FAULT_LVL1_UPR) {
>
> [Severity: High]
> Does this bitwise AND correctly check the 4-bit fault status enumeration?
>
> MON_FAULT_LVL1_UPR is defined as 0x5 (binary 0101). A bitwise AND against
> 0x5 will evaluate to true if either bit 0 or bit 2 is set, matching
> unrelated fault states like 0x1, 0x4, or 0x7.
>
> Should this use an exact equality check (==) instead?
>
I’ll correct this to use == in the next patch series.
>> + chip->last_thres_crossed = true;
>
> [Severity: High]
> This sets chip->last_thres_crossed to true outside of the mutex. As
> mentioned earlier in mbg_tm_get_temp(), this flag is read and cleared
> locklessly.
>
> Could this lead to a data race if mbg_tm_get_temp() executes concurrently?
>
Agree updating last_thres_crossed outside the lock can race with
concurrent reads in mbg_tm_get_temp(). I will move this update under the
lock in the next patch series.
>> + dev_dbg(chip->dev, "Notifying Thermal, fault status=%d\n", val);
>> + thermal_zone_device_update(chip->tz_dev, THERMAL_TRIP_VIOLATED);
>> + } else {
>> + dev_dbg(chip->dev, "Lvl1 upper threshold not violated, ignoring interrupt\n");
>> + }
>> +
>> + return IRQ_HANDLED;
>> +}
>> +
>> +static int mbg_tm_probe(struct platform_device *pdev)
>> +{
>> + struct mbg_tm_chip *chip;
>> + struct device_node *node = pdev->dev.of_node;
>
> [ ... ]
>
>> + chip->tz_dev = devm_thermal_of_zone_register(chip->dev, 0, chip, &mbg_tm_ops);
>> + if (IS_ERR(chip->tz_dev))
>> + return dev_err_probe(chip->dev, PTR_ERR(chip->tz_dev),
>> + "Failed to register sensor\n");
>> +
>> + return devm_request_threaded_irq(&pdev->dev, chip->irq, NULL, mbg_tm_isr, IRQF_ONESHOT,
>> + node->name, chip);
>> +}
>
> [Severity: High]
> Will node->name cause a NULL pointer dereference on non-OF platforms?
>
> Because the driver uses device_property_read_u32(), it can be instantiated
> via ACPI or MFD without a device tree node, meaning pdev->dev.of_node
> could be NULL.
>
> Would it be safer to use dev_name(&pdev->dev) instead?
>
This driver is intended to support DT-only instantiation, so of_node is
expected to be present for valid platforms. In that context, using
node->name is consistent with the intended usage model.
Thanks,
Sachin Gupta
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: thermal: Add Qualcomm MBG thermal monitor support
From: Sachin Gupta @ 2026-06-19 5:59 UTC (permalink / raw)
To: sashiko-reviews; +Cc: robh, conor+dt, devicetree
In-Reply-To: <20260601113009.38FC81F00893@smtp.kernel.org>
On 6/1/2026 5:00 PM, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Low] The PMIC schema restricts the standard 'temperature-sensor@' node name exclusively to the new MBG TM binding, causing false positive validation failures for standard-compliant legacy nodes.
> --
>
> commit 1c6b45c4d32f87b04fb868a977041acc92be3854
> Author: Satya Priya Kakitapalli <quic_skakitap@quicinc.com>
>
> dt-bindings: thermal: Add Qualcomm MBG thermal monitor support
>
> This commit adds device tree bindings for the Qualcomm Master Bandgap (MBG)
> temperature alarm peripheral found on the PM8775 PMIC. It introduces a new
> schema for the MBG thermal monitor and maps it in the SPMI PMIC bindings.
>
>> diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
>> --- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
>> +++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
>> @@ -193,6 +193,10 @@ patternProperties:
>> type: object
>> $ref: /schemas/thermal/qcom,spmi-temp-alarm.yaml#
>>
>> + "^temperature-sensor@[0-9a-f]+$":
>> + type: object
>> + $ref: /schemas/thermal/qcom-spmi-mbg-tm.yaml#
>
> [Severity: Low]
> Does mapping this generic pattern exclusively to the MBG thermal monitor
> schema cause validation conflicts with other thermal sensors?
>
> Since temperature-sensor is the standard generic node name, other thermal
> sensors under the PMIC (like qcom,spmi-temp-alarm) might use it. If a node
> uses temperature-sensor@a00 for a standard SPMI temp alarm, wouldn't it be
> evaluated solely against this MBG-specific schema and fail with a compatible
> string mismatch error?
>
> Would it be better to structure this using a oneOf block to allow multiple
> applicable thermal bindings to share the standard node name?
>
The reported case does not seem valid for this binding update.
temperature-sensor@... is intended for the MBG TM block
(qcom-spmi-mbg-tm), while the existing SPMI temp-alarm block uses
temp-alarm@... and its own binding (qcom,spmi-temp-alarm). So in
practice they are distinct node names for distinct peripherals, and a
normal temp-alarm node is
not expected to be described as temperature-sensor@....
Because of that, this should not cause a real conflict for standard PMIC
DTS usage. A qcom,spmi-temp-alarm node named temperature-sensor@...
would be a misnamed node rather than a valid legacy form we need to
preserve.
Thanks,
Sachin
^ permalink raw reply
* [PATCH] of: Fix RST inline emphasis warnings in of_map_id() kernel-doc
From: Vijayanand Jitta @ 2026-06-19 5:46 UTC (permalink / raw)
To: Rob Herring, Saravana Kannan
Cc: linux-arm-msm, devicetree, linux-kernel, kernel test robot,
Vijayanand Jitta
The @filter_np parameter descriptions in of_map_id() and of_map_msi_id()
contained the text '*filter_np' in prose. Docutils interprets a leading
'*' as the start of RST emphasis (italic), but finds no closing '*',
triggering:
Documentation/devicetree/kernel-api:11: ./drivers/of/base.c:2134:
WARNING: Inline emphasis start-string without end-string. [docutils]
Documentation/devicetree/kernel-api:11: ./drivers/of/base.c:2260:
WARNING: Inline emphasis start-string without end-string. [docutils]
Fix by wrapping '*filter_np' in double backticks (*filter_np) to
render it as an RST inline code literal, which is also the correct
kernel-doc convention for pointer expressions.
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202606130111.ldC96rqf-lkp@intel.com/
Signed-off-by: Vijayanand Jitta <vijayanand.jitta@oss.qualcomm.com>
---
drivers/of/base.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 7cb0d7e88247b..6e7a42dedad3f 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2160,7 +2160,7 @@ static bool of_check_bad_map(const __be32 *map, int len)
* @map_mask_name: optional property name of the mask to use.
* @filter_np: pointer to an optional filter node, or NULL to allow bypass.
* If non-NULL, the map property must exist (-ENODEV if absent). If
- * *filter_np is also non-NULL, only entries targeting that node match.
+ * ``*filter_np`` is also non-NULL, only entries targeting that node match.
* @arg: pointer to a &struct of_phandle_args for the result. On success,
* @arg->args_count will be set to the number of output specifier cells
* as defined by @cells_name in the target node, and
@@ -2350,7 +2350,7 @@ EXPORT_SYMBOL_GPL(of_map_iommu_id);
* stream/device ID) used as the lookup key in the msi-map table.
* @filter_np: pointer to an optional filter node, or NULL to allow bypass.
* If non-NULL, the map property must exist (-ENODEV if absent). If
- * *filter_np is also non-NULL, only entries targeting that node match.
+ * ``*filter_np`` is also non-NULL, only entries targeting that node match.
* @arg: pointer to a &struct of_phandle_args for the result. On success,
* @arg->args_count will be set to the number of output specifier cells
* and @arg->args[0..args_count-1] will contain the translated output
---
base-commit: 598c7067dd8b65b93f3ccada47e9014a13137f1b
change-id: 20260619-iommu_map_kdoc_fix-906ad8a33f1d
Best regards,
--
Vijayanand Jitta <vijayanand.jitta@oss.qualcomm.com>
^ permalink raw reply related
* Re: [PATCH 1/5] dmaengine: sun6i-dma: Refactor to support A733 interrupt and register handling
From: sashiko-bot @ 2026-06-19 5:13 UTC (permalink / raw)
To: Yuanshen Cao
Cc: dmaengine, linux-sunxi, robh, conor+dt, Frank.Li, devicetree,
vkoul
In-Reply-To: <20260619-sun60i-a733-dma-v1-1-da4b649fc72a@gmail.com>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
New issues:
- [Low] The parameter `chan_num` in the newly introduced `read_irq_en` and `write_irq_en` callbacks is highly misleading because it expects a register index, not a channel number.
Pre-existing issues:
- [Critical] `sun6i_dma_interrupt` incorrectly maps interrupts for higher channels to the wrong physical channel structs because it ignores the outer register index.
- [High] Integer division truncation in the `sun6i_dma_interrupt` loop bound completely ignores interrupts for higher channels on SoCs where the channel count is not a multiple of the channels per register.
- [High] `sun6i_dma_terminate_all` and `sun6i_dma_pause`/`resume` acquire `sdev->lock` without disabling softirqs, creating a deadlock with the DMA tasklet.
- [High] `sun6i_dma_interrupt` accesses `vchan->cyclic` and dereferences `pchan->desc` without holding `vc.lock`, racing with channel teardown.
--
commit 47f7d45b0543fc62a4eb37d06b46eeffe4dd06c6
Author: Yuanshen Cao <alex.caoys@gmail.com>
dmaengine: sun6i-dma: Refactor to support A733 interrupt and register handling
This patch refactors the sun6i-dma driver to support the Allwinner A733 DMA
controller. It moves interrupt handling and register dumping functions into
the sun6i_dma_config structure to handle different register layouts.
> diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> index a9a254dbf8cb9..d92e702320d9f 100644
> --- a/drivers/dma/sun6i-dma.c
> +++ b/drivers/dma/sun6i-dma.c
> @@ -138,6 +138,11 @@ struct sun6i_dma_config {
> void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
> void (*set_drq)(u32 *p_cfg, s8 src_drq, s8 dst_drq);
> void (*set_mode)(u32 *p_cfg, s8 src_mode, s8 dst_mode);
> + void (*dump_com_regs)(struct sun6i_dma_dev *sdev);
> + u32 (*read_irq_en)(struct sun6i_dma_dev *sdev, u32 chan_num);
> + void (*write_irq_en)(struct sun6i_dma_dev *sdev, u32 chan_num, u32 irq_val);
[Severity: Low]
Is the chan_num parameter name misleading here?
Looking at sun6i_dma_start_desc(), the value passed to these callbacks is
actually the register index (irq_reg), not the physical channel number.
Could this cause confusion for future implementers who might try to use it
as a literal channel index?
[ ... ]
> @@ -549,14 +573,14 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void *dev_id)
> u32 status;
>
> for (i = 0; i < sdev->num_pchans / DMA_IRQ_CHAN_NR; i++) {
[Severity: High]
This is a pre-existing issue, but does this loop bound properly handle
platforms where the channel count is not a multiple of the channels per
register?
Because integer division truncates, a platform like sun8i-h3 (which defines
nr_max_channels = 12) will evaluate 12 / 8 as 1.
Does this mean the loop only runs for i = 0 (handling channels 0-7) and
completely drops interrupts for channels 8-11, potentially leading to an
unhandled hardware interrupt storm? Should this use DIV_ROUND_UP?
> - status = readl(sdev->base + DMA_IRQ_STAT(i));
> + status = sdev->cfg->read_irq_stat(sdev, i);
> if (!status)
> continue;
>
> dev_dbg(sdev->slave.dev, "DMA irq status %s: 0x%x\n",
> str_high_low(i), status);
>
> - writel(status, sdev->base + DMA_IRQ_STAT(i));
> + sdev->cfg->write_irq_stat(sdev, i, status);
>
> for (j = 0; (j < DMA_IRQ_CHAN_NR) && status; j++) {
> pchan = sdev->pchans + j;
[Severity: Critical]
This is a pre-existing issue, but does this correctly calculate the physical
channel pointer for higher channels?
Inside this interrupt loop, i represents the interrupt register index and j
is the local bit offset within that register. By calculating the physical
channel as sdev->pchans + j, it completely ignores the outer register index
offset.
If an interrupt triggers on physical channel 8 (i=1, j=0), won't the code
incorrectly assign it to sdev->pchans + 0?
Could this incorrectly complete the active transfer for channel 0, causing
use-after-free issues and DMA state corruption? Should the assignment be
sdev->pchans + j + i * sdev->cfg->num_channels_per_reg?
[Severity: High]
This is a pre-existing issue, but does sun6i_dma_interrupt() have a race
condition with channel teardown?
In the hardirq handler sun6i_dma_interrupt(), vchan->cyclic is checked
locklessly:
drivers/dma/sun6i-dma.c:sun6i_dma_interrupt() {
...
if (vchan->cyclic) {
vchan_cyclic_callback(&pchan->desc->vd);
}
...
}
Concurrently, sun6i_dma_terminate_all() can run on another CPU, acquire
vchan->vc.lock, set vchan->cyclic = false, set pchan->desc = NULL, and free
the descriptors:
drivers/dma/sun6i-dma.c:sun6i_dma_terminate_all() {
...
vchan->cyclic = false;
...
}
If the IRQ handler checks vchan->cyclic just before it is modified, could it
proceed to dereference pchan->desc after it has been nulled or freed?
[Severity: High]
This is a pre-existing issue, but do sun6i_dma_terminate_all(),
sun6i_dma_pause(), and sun6i_dma_resume() have a deadlock window?
These functions acquire sdev->lock using a plain spin_lock() from process
context:
drivers/dma/sun6i-dma.c:sun6i_dma_terminate_all() {
...
spin_lock(&sdev->lock);
...
}
However, sdev->lock is also acquired by sun6i_dma_tasklet(), which runs in
softirq context.
If a hard interrupt occurs on the same CPU while this lock is held, and the
interrupt handler returns and processes pending softirqs (including the
scheduled sun6i_dma_tasklet()), won't the tasklet attempt to acquire
sdev->lock using spin_lock_irq(), resulting in a same-CPU ABBA deadlock?
Should process context use spin_lock_bh() or spin_lock_irqsave() when locking
resources shared with softirqs?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260619-sun60i-a733-dma-v1-0-da4b649fc72a@gmail.com?part=1
^ permalink raw reply
* Re: [PATCH 3/5] dmaengine: sun6i-dma: Add num_channels_per_reg for flexible interrupt mapping
From: sashiko-bot @ 2026-06-19 5:08 UTC (permalink / raw)
To: Yuanshen Cao
Cc: robh, conor+dt, devicetree, linux-sunxi, Frank.Li, dmaengine,
vkoul
In-Reply-To: <20260619-sun60i-a733-dma-v1-3-da4b649fc72a@gmail.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Incorrect physical channel indexing in `sun6i_dma_interrupt` ignores the register index, applying status to the wrong physical channel.
- [High] Integer division truncation in the `sun6i_dma_interrupt` loop bound skips polling for trailing channels.
- [High] Time-of-Check to Time-of-Use (TOCTOU) race condition in `sun6i_dma_interrupt` risks a NULL pointer dereference.
--
commit 3bfcb64969bffa1792e80eaa282fc15450f3870b
Author: Yuanshen Cao <alex.caoys@gmail.com>
dmaengine: sun6i-dma: Add num_channels_per_reg for flexible interrupt mapping
This commit introduces num_channels_per_reg to the sun6i_dma_config to
handle SoCs with varying channels per interrupt register. It modifies
the interrupt logic to use this new configuration value and bounds checking.
> diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> index 059455425e19c..fb1c1a28744bb 100644
> --- a/drivers/dma/sun6i-dma.c
> +++ b/drivers/dma/sun6i-dma.c
[ ... ]
> @@ -574,7 +575,7 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void *dev_id)
> int i, j, ret = IRQ_NONE;
> u32 status;
>
> - for (i = 0; i < sdev->num_pchans / DMA_IRQ_CHAN_NR; i++) {
> + for (i = 0; i < sdev->num_pchans / sdev->cfg->num_channels_per_reg; i++) {
[Severity: High]
This is a pre-existing issue, but does this loop condition truncate the
division and miss trailing channels?
If sdev->num_pchans is not perfectly divisible by num_channels_per_reg
(for example, 12 channels with 8 channels per register), the integer
division truncates the remainder. This means the loop will skip the second
register entirely, permanently missing interrupts for the trailing channels.
> status = sdev->cfg->read_irq_stat(sdev, i);
> if (!status)
> continue;
> @@ -584,7 +585,7 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void *dev_id)
>
> sdev->cfg->write_irq_stat(sdev, i, status);
>
> - for (j = 0; (j < DMA_IRQ_CHAN_NR) && status; j++) {
> + for (j = 0; (j < sdev->cfg->num_channels_per_reg) && status; j++) {
> pchan = sdev->pchans + j;
[Severity: Critical]
This is a pre-existing issue, but does this apply the status to the wrong
physical channel?
The array lookup uses only the local offset j, discarding the register
index i. For any register i > 0, it accesses sdev->pchans[j] instead of
sdev->pchans[i * num_channels_per_reg + j].
With the newly added hardware where num_channels_per_reg is 1, j is always
0, which seems like it would cause all channels to incorrectly map to
channel 0.
> vchan = pchan->vchan;
> if (vchan && (status & vchan->irq_type)) {
[Severity: High]
This is a pre-existing issue, but is there a race condition here that could
lead to a NULL pointer dereference?
The interrupt handler reads vchan = pchan->vchan locklessly, and eventually
blocks to acquire vchan->vc.lock. Concurrently, sun6i_dma_terminate_all()
could acquire the same lock, nullify pchan->desc, and free the descriptors.
When the interrupt handler successfully acquires the lock:
spin_lock(&vchan->vc.lock);
vchan_cookie_complete(&pchan->desc->vd);
it does not re-verify pchan->desc before passing &pchan->desc->vd to
vchan_cookie_complete(), which would crash if pchan->desc was concurrently
set to NULL.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260619-sun60i-a733-dma-v1-0-da4b649fc72a@gmail.com?part=3
^ permalink raw reply
* Re: [PATCH 2/5] dmaengine: sun6i-dma: Add set_addr function pointer for variable address widths
From: sashiko-bot @ 2026-06-19 5:03 UTC (permalink / raw)
To: Yuanshen Cao
Cc: robh, vkoul, Frank.Li, devicetree, dmaengine, conor+dt,
linux-sunxi
In-Reply-To: <20260619-sun60i-a733-dma-v1-2-da4b649fc72a@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Use-after-free vulnerability in the error handling paths of `sun6i_dma_prep_slave_sg` and `sun6i_dma_prep_dma_cyclic` when freeing DMA pool items.
--
commit ea99a7147f9100709dbaea854d96eccdbc89f235
Author: Yuanshen Cao <alex.caoys@gmail.com>
dmaengine: sun6i-dma: Add set_addr function pointer for variable address widths
The A733 DMA controller supports higher address (up to 32G) compared to
previous generations. By moving set_addr into the sun6i_dma_config
structure, we can provide specialized implementations for different hardware.
> diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> index d92e702320d9f..059455425e19c 100644
> --- a/drivers/dma/sun6i-dma.c
> +++ b/drivers/dma/sun6i-dma.c
[ ... ]
> @@ -787,7 +796,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
> sg_dma_len(sg), flags);
>
> } else {
> - sun6i_dma_set_addr(sdev, v_lli,
> + sdev->cfg->set_addr(sdev, v_lli,
> sconfig->src_addr,
> sg_dma_address(sg));
> v_lli->cfg = lli_cfg;
[Severity: High]
This isn't a bug introduced by this patch, but looking at the error handling
paths for sun6i_dma_prep_slave_sg() and sun6i_dma_prep_dma_cyclic(), is there
a use-after-free when freeing DMA pool items?
In the err_lli_free path, the code iterates over the linked list of items:
err_lli_free:
for (p_lli = txd->p_lli, v_lli = txd->v_lli; v_lli;
p_lli = v_lli->p_lli_next, v_lli = v_lli->v_lli_next)
dma_pool_free(sdev->pool, v_lli, p_lli);
When dma_pool_free() executes, the memory associated with v_lli is returned
to the pool. The loop's update step then accesses v_lli->p_lli_next and
v_lli->v_lli_next to advance the pointers.
Under memory pressure, another thread might allocate this newly freed item
and overwrite its contents, potentially causing an invalid pointer
dereference. Should this loop use a safe iteration method that reads the
next pointers before calling dma_pool_free()?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260619-sun60i-a733-dma-v1-0-da4b649fc72a@gmail.com?part=2
^ permalink raw reply
* [PATCH 5/5] dt-bindings: dma: sun50i-a64-dma: Update device tree bindings documentation for A733
From: Yuanshen Cao @ 2026-06-19 4:53 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maxime Ripard
Cc: dmaengine, linux-arm-kernel, linux-sunxi, linux-kernel,
devicetree, Yuanshen Cao
In-Reply-To: <20260619-sun60i-a733-dma-v1-0-da4b649fc72a@gmail.com>
To complete the support for the A733 DMA controller, added
`allwinner,sun60i-a733-dma` to the list of compatible strings for
`allwinner,sun50i-a64-dma` dt-binding documentations..
Signed-off-by: Yuanshen Cao <alex.caoys@gmail.com>
---
Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml b/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml
index c3e14eb6cfff..1cc3304b7414 100644
--- a/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml
+++ b/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml
@@ -25,6 +25,7 @@ properties:
- allwinner,sun50i-a64-dma
- allwinner,sun50i-a100-dma
- allwinner,sun50i-h6-dma
+ - allwinner,sun60i-a733-dma
- items:
- const: allwinner,sun8i-r40-dma
- const: allwinner,sun50i-a64-dma
@@ -70,6 +71,7 @@ if:
- allwinner,sun20i-d1-dma
- allwinner,sun50i-a100-dma
- allwinner,sun50i-h6-dma
+ - allwinner,sun60i-a733-dma
then:
properties:
--
2.54.0
^ permalink raw reply related
* [PATCH 4/5] dmaengine: sun6i-dma: Implement support for Allwinner A733 DMA controller
From: Yuanshen Cao @ 2026-06-19 4:53 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maxime Ripard
Cc: dmaengine, linux-arm-kernel, linux-sunxi, linux-kernel,
devicetree, Yuanshen Cao
In-Reply-To: <20260619-sun60i-a733-dma-v1-0-da4b649fc72a@gmail.com>
This patch implements the actual support for the Allwinner A733 DMA
controller. It defines the new register offsets and bitfield mappings
required for the A733, which slightly differs from the older `sun6i`
series.
Changes:
- New register macros for A733 interrupt enable `DMA_IRQ_EN_A733` and
status `DMA_IRQ_STAT_A733`.
- New `SRC_HIGH_ADDR_32G` and `DST_HIGH_ADDR_32G` macro to handle the
32G high-address field in the LLI.
- Implemented `sun6i_dma_set_addr_a733` and A733-specific interrupt
register accessors.
- Added `sun60i_a733_dma_config`, which ties all the refactored
functionality together for this specific hardware.
Signed-off-by: Yuanshen Cao <alex.caoys@gmail.com>
---
drivers/dma/sun6i-dma.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index fb1c1a28744b..9585b4a9e00d 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -52,6 +52,15 @@
#define SUNXI_H3_SECURE_REG 0x20
#define SUNXI_H3_DMA_GATE 0x28
#define SUNXI_H3_DMA_GATE_ENABLE 0x4
+
+/*
+ * sun60i specific registers
+ */
+#define DMA_IRQ_EN_A733(x) ((x) * 0x40 + 0x134)
+#define DMA_IRQ_STAT_A733(x) ((x) * 0x40 + 0x138)
+
+#define DMA_IRQ_CHAN_NR_A733 1
+
/*
* Channels specific registers
*/
@@ -100,6 +109,8 @@
*/
#define SRC_HIGH_ADDR(x) (((x) & 0x3U) << 16)
#define DST_HIGH_ADDR(x) (((x) & 0x3U) << 18)
+#define SRC_HIGH_ADDR_32G(x) (((x) & 0x7U) << 11)
+#define DST_HIGH_ADDR_32G(x) (((x) & 0x7U) << 15)
/*
* Various hardware related defines
@@ -257,6 +268,23 @@ static inline void sun6i_dma_dump_com_regs(struct sun6i_dma_dev *sdev)
DMA_STAT, readl(sdev->base + DMA_STAT));
}
+static inline void sun6i_dma_dump_com_regs_a733(struct sun6i_dma_dev *sdev)
+{
+ int i;
+
+ for (i = 0; i < sdev->num_pchans / sdev->cfg->num_channels_per_reg; i++) {
+ dev_dbg(sdev->slave.dev, "Common register:\n"
+ "chan num %d\n"
+ "\tmask(%04x): 0x%08x\n"
+ "\tpend(%04x): 0x%08x\n"
+ "\tstats(%04x): 0x%08x\n",
+ i,
+ DMA_IRQ_EN_A733(i), readl(sdev->base + DMA_IRQ_EN_A733(i)),
+ DMA_IRQ_STAT_A733(i), readl(sdev->base + DMA_IRQ_STAT_A733(i)),
+ DMA_STAT, readl(sdev->base + DMA_STAT));
+ }
+}
+
static inline void sun6i_dma_dump_chan_regs(struct sun6i_dma_dev *sdev,
struct sun6i_pchan *pchan)
{
@@ -360,20 +388,41 @@ static u32 sun6i_read_irq_en(struct sun6i_dma_dev *sdev, u32 chan_num)
return readl(sdev->base + DMA_IRQ_EN(chan_num));
}
+static u32 sun6i_read_irq_en_a733(struct sun6i_dma_dev *sdev, u32 chan_num)
+{
+ return readl(sdev->base + DMA_IRQ_EN_A733(chan_num));
+}
+
static void sun6i_write_irq_en(struct sun6i_dma_dev *sdev, u32 chan_num, u32 irq_val)
{
writel(irq_val, sdev->base + DMA_IRQ_EN(chan_num));
}
+
+static void sun6i_write_irq_en_a733(struct sun6i_dma_dev *sdev, u32 chan_num, u32 irq_val)
+{
+ writel(irq_val, sdev->base + DMA_IRQ_EN_A733(chan_num));
+}
+
static u32 sun6i_read_irq_stat(struct sun6i_dma_dev *sdev, u32 chan_num)
{
return readl(sdev->base + DMA_IRQ_STAT(chan_num));
}
+static u32 sun6i_read_irq_stat_a733(struct sun6i_dma_dev *sdev, u32 chan_num)
+{
+ return readl(sdev->base + DMA_IRQ_STAT_A733(chan_num));
+}
+
static void sun6i_write_irq_stat(struct sun6i_dma_dev *sdev, u32 chan_num, u32 status)
{
writel(status, sdev->base + DMA_IRQ_STAT(chan_num));
}
+static void sun6i_write_irq_stat_a733(struct sun6i_dma_dev *sdev, u32 chan_num, u32 status)
+{
+ writel(status, sdev->base + DMA_IRQ_STAT_A733(chan_num));
+}
+
static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
{
struct sun6i_desc *txd = pchan->desc;
@@ -694,6 +743,17 @@ static inline void sun6i_dma_set_addr_a100(struct sun6i_dma_dev *sdev,
DST_HIGH_ADDR(upper_32_bits(dst));
}
+static inline void sun6i_dma_set_addr_a733(struct sun6i_dma_dev *sdev,
+ struct sun6i_dma_lli *v_lli,
+ dma_addr_t src, dma_addr_t dst)
+{
+ v_lli->src = lower_32_bits(src);
+ v_lli->dst = lower_32_bits(dst);
+
+ v_lli->para |= SRC_HIGH_ADDR_32G(upper_32_bits(src)) |
+ DST_HIGH_ADDR_32G(upper_32_bits(dst));
+}
+
static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy(
struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
size_t len, unsigned long flags)
@@ -1352,6 +1412,33 @@ static struct sun6i_dma_config sun50i_h6_dma_cfg = {
.has_mbus_clk = true,
};
+/*
+ * The A733 binding uses the number of dma channels from the
+ * device tree node.
+ */
+static struct sun6i_dma_config sun60i_a733_dma_cfg = {
+ .clock_autogate_enable = sun6i_enable_clock_autogate_h3,
+ .set_burst_length = sun6i_set_burst_length_h3,
+ .set_drq = sun6i_set_drq_h6,
+ .set_mode = sun6i_set_mode_h6,
+ .set_addr = sun6i_dma_set_addr_a733,
+ .dump_com_regs = sun6i_dma_dump_com_regs_a733,
+ .read_irq_en = sun6i_read_irq_en_a733,
+ .write_irq_en = sun6i_write_irq_en_a733,
+ .read_irq_stat = sun6i_read_irq_stat_a733,
+ .write_irq_stat = sun6i_write_irq_stat_a733,
+ .src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+ .dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+ .src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
+ .dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
+ .num_channels_per_reg = DMA_IRQ_CHAN_NR_A733,
+ .has_mbus_clk = true,
+};
+
/*
* The V3s have only 8 physical channels, a maximum DRQ port id of 23,
* and a total of 24 usable source and destination endpoints.
@@ -1392,6 +1479,7 @@ static const struct of_device_id sun6i_dma_match[] = {
{ .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg },
{ .compatible = "allwinner,sun50i-a100-dma", .data = &sun50i_a100_dma_cfg },
{ .compatible = "allwinner,sun50i-h6-dma", .data = &sun50i_h6_dma_cfg },
+ { .compatible = "allwinner,sun60i-a733-dma", .data = &sun60i_a733_dma_cfg },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sun6i_dma_match);
--
2.54.0
^ permalink raw reply related
* [PATCH 3/5] dmaengine: sun6i-dma: Add num_channels_per_reg for flexible interrupt mapping
From: Yuanshen Cao @ 2026-06-19 4:53 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maxime Ripard
Cc: dmaengine, linux-arm-kernel, linux-sunxi, linux-kernel,
devicetree, Yuanshen Cao
In-Reply-To: <20260619-sun60i-a733-dma-v1-0-da4b649fc72a@gmail.com>
The previous implementation of `sun6i-dma` had some implicit assumptions
about the number of channels per interrupt register. Specifically,
functions like `sun6i_kill_tasklet` were hardcoded to only disable
interrupts for IRQ 0 and 1. `DMA_MAX_CHANNELS` is also not in used in
the past, and the old SoCs never has more than 16 channels.
The A733 has a different interrupt structure where the number of
channels per register may differ. This patch introduces
`num_channels_per_reg` to the `sun6i_dma_config`, similar to BSP, to
make the interrupt handling logic hardware-agnostic. It also sets
`DMA_MAX_CHANNELS` to 16 to align with the new BSP code and ensure loops
over interrupts are correctly bounded.
Changes:
- Change `DMA_MAX_CHANNELS` definition to 16.
- Added `num_channels_per_reg` to `struct sun6i_dma_config`.
- Replaced hardcoded IRQ register calculations with values from
`sdev->cfg->num_channels_per_reg`.
- Updated `sun6i_kill_tasklet` to loop through all possible interrupt
registers based on `DMA_MAX_CHANNELS` and the configuration.
Signed-off-by: Yuanshen Cao <alex.caoys@gmail.com>
---
drivers/dma/sun6i-dma.c | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 059455425e19..fb1c1a28744b 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -41,7 +41,7 @@
#define DMA_STAT 0x30
/* Offset between DMA_IRQ_EN and DMA_IRQ_STAT limits number of channels */
-#define DMA_MAX_CHANNELS (DMA_IRQ_CHAN_NR * 0x10 / 4)
+#define DMA_MAX_CHANNELS 16
/*
* sun8i specific registers
@@ -151,6 +151,7 @@ struct sun6i_dma_config {
u32 src_addr_widths;
u32 dst_addr_widths;
bool has_mbus_clk;
+ u32 num_channels_per_reg;
};
/*
@@ -481,8 +482,8 @@ static int sun6i_dma_start_desc(struct sun6i_vchan *vchan)
sun6i_dma_dump_lli(vchan, pchan->desc->v_lli, pchan->desc->p_lli);
- irq_reg = pchan->idx / DMA_IRQ_CHAN_NR;
- irq_offset = pchan->idx % DMA_IRQ_CHAN_NR;
+ irq_reg = pchan->idx / sdev->cfg->num_channels_per_reg;
+ irq_offset = pchan->idx % sdev->cfg->num_channels_per_reg;
vchan->irq_type = vchan->cyclic ? DMA_IRQ_PKG : DMA_IRQ_QUEUE;
@@ -574,7 +575,7 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void *dev_id)
int i, j, ret = IRQ_NONE;
u32 status;
- for (i = 0; i < sdev->num_pchans / DMA_IRQ_CHAN_NR; i++) {
+ for (i = 0; i < sdev->num_pchans / sdev->cfg->num_channels_per_reg; i++) {
status = sdev->cfg->read_irq_stat(sdev, i);
if (!status)
continue;
@@ -584,7 +585,7 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void *dev_id)
sdev->cfg->write_irq_stat(sdev, i, status);
- for (j = 0; (j < DMA_IRQ_CHAN_NR) && status; j++) {
+ for (j = 0; (j < sdev->cfg->num_channels_per_reg) && status; j++) {
pchan = sdev->pchans + j;
vchan = pchan->vchan;
if (vchan && (status & vchan->irq_type)) {
@@ -1108,9 +1109,11 @@ static struct dma_chan *sun6i_dma_of_xlate(struct of_phandle_args *dma_spec,
static inline void sun6i_kill_tasklet(struct sun6i_dma_dev *sdev)
{
+ int i;
+
/* Disable all interrupts from DMA */
- writel(0, sdev->base + DMA_IRQ_EN(0));
- writel(0, sdev->base + DMA_IRQ_EN(1));
+ for (i = 0; i < DMA_MAX_CHANNELS / sdev->cfg->num_channels_per_reg; i++)
+ sdev->cfg->write_irq_en(sdev, i, 0);
/* Prevent spurious interrupts from scheduling the tasklet */
atomic_inc(&sdev->tasklet_shutdown);
@@ -1171,6 +1174,7 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
+ .num_channels_per_reg = DMA_IRQ_CHAN_NR,
};
/*
@@ -1200,6 +1204,7 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
+ .num_channels_per_reg = DMA_IRQ_CHAN_NR,
};
static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
@@ -1224,6 +1229,7 @@ static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
+ .num_channels_per_reg = DMA_IRQ_CHAN_NR,
};
/*
@@ -1257,6 +1263,7 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+ .num_channels_per_reg = DMA_IRQ_CHAN_NR,
};
/*
@@ -1284,6 +1291,7 @@ static struct sun6i_dma_config sun50i_a64_dma_cfg = {
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+ .num_channels_per_reg = DMA_IRQ_CHAN_NR,
};
/*
@@ -1311,6 +1319,7 @@ static struct sun6i_dma_config sun50i_a100_dma_cfg = {
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+ .num_channels_per_reg = DMA_IRQ_CHAN_NR,
.has_mbus_clk = true,
};
@@ -1339,6 +1348,7 @@ static struct sun6i_dma_config sun50i_h6_dma_cfg = {
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+ .num_channels_per_reg = DMA_IRQ_CHAN_NR,
.has_mbus_clk = true,
};
@@ -1369,6 +1379,7 @@ static struct sun6i_dma_config sun8i_v3s_dma_cfg = {
.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
+ .num_channels_per_reg = DMA_IRQ_CHAN_NR,
};
static const struct of_device_id sun6i_dma_match[] = {
--
2.54.0
^ permalink raw reply related
* [PATCH 2/5] dmaengine: sun6i-dma: Add set_addr function pointer for variable address widths
From: Yuanshen Cao @ 2026-06-19 4:53 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maxime Ripard
Cc: dmaengine, linux-arm-kernel, linux-sunxi, linux-kernel,
devicetree, Yuanshen Cao
In-Reply-To: <20260619-sun60i-a733-dma-v1-0-da4b649fc72a@gmail.com>
The A733 DMA controller supports higher address (up to 32G) compared to
previous generations. The existing `sun6i_dma_set_addr` function uses a
hardcoded logic for setting the high-address bits in the LLI parameters.
By moving `set_addr` into the `sun6i_dma_config` structure, we can
provide specialized implementations for different hardware. This allows
the A733 to use a version of `set_addr` that correctly handles its
specific `SRC_HIGH_ADDR_32G` and `DST_HIGH_ADDR_32G` in the `set_addr`
register later in the series.
Changes:
- Added `set_addr` function pointer to `struct sun6i_dma_config`.
- Refactored `sun6i_dma_set_addr` and introduced
`sun6i_dma_set_addr_a100` (keeping the logic for high address
support).
- Updated all existing configuration structs to include the new
`set_addr` pointer.
- Removed `has_high_addr` since the logic is replaced by
`sun6i_dma_set_addr_a100`.
Signed-off-by: Yuanshen Cao <alex.caoys@gmail.com>
---
drivers/dma/sun6i-dma.c | 36 ++++++++++++++++++++++++++----------
1 file changed, 26 insertions(+), 10 deletions(-)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index d92e702320d9..059455425e19 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -112,6 +112,7 @@
/* forward declaration */
struct sun6i_dma_dev;
+struct sun6i_dma_lli;
/*
* Hardware channels / ports representation
@@ -138,6 +139,8 @@ struct sun6i_dma_config {
void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
void (*set_drq)(u32 *p_cfg, s8 src_drq, s8 dst_drq);
void (*set_mode)(u32 *p_cfg, s8 src_mode, s8 dst_mode);
+ void (*set_addr)(struct sun6i_dma_dev *sdev, struct sun6i_dma_lli *v_lli,
+ dma_addr_t src, dma_addr_t dst);
void (*dump_com_regs)(struct sun6i_dma_dev *sdev);
u32 (*read_irq_en)(struct sun6i_dma_dev *sdev, u32 chan_num);
void (*write_irq_en)(struct sun6i_dma_dev *sdev, u32 chan_num, u32 irq_val);
@@ -147,7 +150,6 @@ struct sun6i_dma_config {
u32 dst_burst_lengths;
u32 src_addr_widths;
u32 dst_addr_widths;
- bool has_high_addr;
bool has_mbus_clk;
};
@@ -675,13 +677,20 @@ static int set_config(struct sun6i_dma_dev *sdev,
static inline void sun6i_dma_set_addr(struct sun6i_dma_dev *sdev,
struct sun6i_dma_lli *v_lli,
dma_addr_t src, dma_addr_t dst)
+{
+ v_lli->src = lower_32_bits(src);
+ v_lli->dst = lower_32_bits(dst);
+}
+
+static inline void sun6i_dma_set_addr_a100(struct sun6i_dma_dev *sdev,
+ struct sun6i_dma_lli *v_lli,
+ dma_addr_t src, dma_addr_t dst)
{
v_lli->src = lower_32_bits(src);
v_lli->dst = lower_32_bits(dst);
- if (sdev->cfg->has_high_addr)
- v_lli->para |= SRC_HIGH_ADDR(upper_32_bits(src)) |
- DST_HIGH_ADDR(upper_32_bits(dst));
+ v_lli->para |= SRC_HIGH_ADDR(upper_32_bits(src)) |
+ DST_HIGH_ADDR(upper_32_bits(dst));
}
static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy(
@@ -714,7 +723,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy(
v_lli->len = len;
v_lli->para = NORMAL_WAIT;
- sun6i_dma_set_addr(sdev, v_lli, src, dest);
+ sdev->cfg->set_addr(sdev, v_lli, src, dest);
burst = convert_burst(8);
width = convert_buswidth(DMA_SLAVE_BUSWIDTH_4_BYTES);
@@ -773,7 +782,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
v_lli->para = NORMAL_WAIT;
if (dir == DMA_MEM_TO_DEV) {
- sun6i_dma_set_addr(sdev, v_lli,
+ sdev->cfg->set_addr(sdev, v_lli,
sg_dma_address(sg),
sconfig->dst_addr);
v_lli->cfg = lli_cfg;
@@ -787,7 +796,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
sg_dma_len(sg), flags);
} else {
- sun6i_dma_set_addr(sdev, v_lli,
+ sdev->cfg->set_addr(sdev, v_lli,
sconfig->src_addr,
sg_dma_address(sg));
v_lli->cfg = lli_cfg;
@@ -858,7 +867,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic(
v_lli->para = NORMAL_WAIT;
if (dir == DMA_MEM_TO_DEV) {
- sun6i_dma_set_addr(sdev, v_lli,
+ sdev->cfg->set_addr(sdev, v_lli,
buf_addr + period_len * i,
sconfig->dst_addr);
v_lli->cfg = lli_cfg;
@@ -870,7 +879,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic(
&sconfig->dst_addr, &buf_addr,
buf_len, flags);
} else {
- sun6i_dma_set_addr(sdev, v_lli,
+ sdev->cfg->set_addr(sdev, v_lli,
sconfig->src_addr,
buf_addr + period_len * i);
v_lli->cfg = lli_cfg;
@@ -1148,6 +1157,7 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31,
.set_drq = sun6i_set_drq_a31,
.set_mode = sun6i_set_mode_a31,
+ .set_addr = sun6i_dma_set_addr,
.dump_com_regs = sun6i_dma_dump_com_regs,
.read_irq_en = sun6i_read_irq_en,
.write_irq_en = sun6i_write_irq_en,
@@ -1176,6 +1186,7 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31,
.set_drq = sun6i_set_drq_a31,
.set_mode = sun6i_set_mode_a31,
+ .set_addr = sun6i_dma_set_addr,
.dump_com_regs = sun6i_dma_dump_com_regs,
.read_irq_en = sun6i_read_irq_en,
.write_irq_en = sun6i_write_irq_en,
@@ -1199,6 +1210,7 @@ static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31,
.set_drq = sun6i_set_drq_a31,
.set_mode = sun6i_set_mode_a31,
+ .set_addr = sun6i_dma_set_addr,
.dump_com_regs = sun6i_dma_dump_com_regs,
.read_irq_en = sun6i_read_irq_en,
.write_irq_en = sun6i_write_irq_en,
@@ -1229,6 +1241,7 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_h3,
.set_drq = sun6i_set_drq_a31,
.set_mode = sun6i_set_mode_a31,
+ .set_addr = sun6i_dma_set_addr,
.dump_com_regs = sun6i_dma_dump_com_regs,
.read_irq_en = sun6i_read_irq_en,
.write_irq_en = sun6i_write_irq_en,
@@ -1255,6 +1268,7 @@ static struct sun6i_dma_config sun50i_a64_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_h3,
.set_drq = sun6i_set_drq_a31,
.set_mode = sun6i_set_mode_a31,
+ .set_addr = sun6i_dma_set_addr,
.dump_com_regs = sun6i_dma_dump_com_regs,
.read_irq_en = sun6i_read_irq_en,
.write_irq_en = sun6i_write_irq_en,
@@ -1281,6 +1295,7 @@ static struct sun6i_dma_config sun50i_a100_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_h3,
.set_drq = sun6i_set_drq_h6,
.set_mode = sun6i_set_mode_h6,
+ .set_addr = sun6i_dma_set_addr_a100,
.dump_com_regs = sun6i_dma_dump_com_regs,
.read_irq_en = sun6i_read_irq_en,
.write_irq_en = sun6i_write_irq_en,
@@ -1296,7 +1311,6 @@ static struct sun6i_dma_config sun50i_a100_dma_cfg = {
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
- .has_high_addr = true,
.has_mbus_clk = true,
};
@@ -1309,6 +1323,7 @@ static struct sun6i_dma_config sun50i_h6_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_h3,
.set_drq = sun6i_set_drq_h6,
.set_mode = sun6i_set_mode_h6,
+ .set_addr = sun6i_dma_set_addr,
.dump_com_regs = sun6i_dma_dump_com_regs,
.read_irq_en = sun6i_read_irq_en,
.write_irq_en = sun6i_write_irq_en,
@@ -1340,6 +1355,7 @@ static struct sun6i_dma_config sun8i_v3s_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31,
.set_drq = sun6i_set_drq_a31,
.set_mode = sun6i_set_mode_a31,
+ .set_addr = sun6i_dma_set_addr,
.dump_com_regs = sun6i_dma_dump_com_regs,
.read_irq_en = sun6i_read_irq_en,
.write_irq_en = sun6i_write_irq_en,
--
2.54.0
^ permalink raw reply related
* [PATCH 1/5] dmaengine: sun6i-dma: Refactor to support A733 interrupt and register handling
From: Yuanshen Cao @ 2026-06-19 4:53 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maxime Ripard
Cc: dmaengine, linux-arm-kernel, linux-sunxi, linux-kernel,
devicetree, Yuanshen Cao
In-Reply-To: <20260619-sun60i-a733-dma-v1-0-da4b649fc72a@gmail.com>
This patch is the first step in a refactoring effort to support the
Allwinner A733 DMA controller. Currently, the `sun6i-dma` driver has
several functions related to interrupt handling (reading/writing
interrupt enable and status registers) and register dumping that are
hardcoded.
To support the A733, which has different register layouts and interrupt
handling logic, these functions are being moved into the
`sun6i_dma_config` structure as function pointers. This allows the
driver to use a polymorphic approach where the specific implementation
is determined by the hardware configuration assigned during device
probing.
Changes:
- Added function pointers to `struct sun6i_dma_config` for:
- `dump_com_regs`
- `read_irq_en`
- `write_irq_en`
- `read_irq_stat`
- `write_irq_stat`
- Implemented generic `sun6i_read/write_irq_*` functions for existing
hardware.
- Updated existing `sun6i_dma_config` instances (A31, A23, H3, A64,
A100, H6, V3S) to use these new function pointers.
Signed-off-by: Yuanshen Cao <alex.caoys@gmail.com>
---
drivers/dma/sun6i-dma.c | 74 +++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 69 insertions(+), 5 deletions(-)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index a9a254dbf8cb..d92e702320d9 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -138,6 +138,11 @@ struct sun6i_dma_config {
void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
void (*set_drq)(u32 *p_cfg, s8 src_drq, s8 dst_drq);
void (*set_mode)(u32 *p_cfg, s8 src_mode, s8 dst_mode);
+ void (*dump_com_regs)(struct sun6i_dma_dev *sdev);
+ u32 (*read_irq_en)(struct sun6i_dma_dev *sdev, u32 chan_num);
+ void (*write_irq_en)(struct sun6i_dma_dev *sdev, u32 chan_num, u32 irq_val);
+ u32 (*read_irq_stat)(struct sun6i_dma_dev *sdev, u32 chan_num);
+ void (*write_irq_stat)(struct sun6i_dma_dev *sdev, u32 chan_num, u32 status);
u32 src_burst_lengths;
u32 dst_burst_lengths;
u32 src_addr_widths;
@@ -347,6 +352,25 @@ static void sun6i_set_mode_h6(u32 *p_cfg, s8 src_mode, s8 dst_mode)
DMA_CHAN_CFG_DST_MODE_H6(dst_mode);
}
+static u32 sun6i_read_irq_en(struct sun6i_dma_dev *sdev, u32 chan_num)
+{
+ return readl(sdev->base + DMA_IRQ_EN(chan_num));
+}
+
+static void sun6i_write_irq_en(struct sun6i_dma_dev *sdev, u32 chan_num, u32 irq_val)
+{
+ writel(irq_val, sdev->base + DMA_IRQ_EN(chan_num));
+}
+static u32 sun6i_read_irq_stat(struct sun6i_dma_dev *sdev, u32 chan_num)
+{
+ return readl(sdev->base + DMA_IRQ_STAT(chan_num));
+}
+
+static void sun6i_write_irq_stat(struct sun6i_dma_dev *sdev, u32 chan_num, u32 status)
+{
+ writel(status, sdev->base + DMA_IRQ_STAT(chan_num));
+}
+
static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
{
struct sun6i_desc *txd = pchan->desc;
@@ -460,16 +484,16 @@ static int sun6i_dma_start_desc(struct sun6i_vchan *vchan)
vchan->irq_type = vchan->cyclic ? DMA_IRQ_PKG : DMA_IRQ_QUEUE;
- irq_val = readl(sdev->base + DMA_IRQ_EN(irq_reg));
+ irq_val = sdev->cfg->read_irq_en(sdev, irq_reg);
irq_val &= ~((DMA_IRQ_HALF | DMA_IRQ_PKG | DMA_IRQ_QUEUE) <<
(irq_offset * DMA_IRQ_CHAN_WIDTH));
irq_val |= vchan->irq_type << (irq_offset * DMA_IRQ_CHAN_WIDTH);
- writel(irq_val, sdev->base + DMA_IRQ_EN(irq_reg));
+ sdev->cfg->write_irq_en(sdev, irq_reg, irq_val);
writel(pchan->desc->p_lli, pchan->base + DMA_CHAN_LLI_ADDR);
writel(DMA_CHAN_ENABLE_START, pchan->base + DMA_CHAN_ENABLE);
- sun6i_dma_dump_com_regs(sdev);
+ sdev->cfg->dump_com_regs(sdev);
sun6i_dma_dump_chan_regs(sdev, pchan);
return 0;
@@ -549,14 +573,14 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void *dev_id)
u32 status;
for (i = 0; i < sdev->num_pchans / DMA_IRQ_CHAN_NR; i++) {
- status = readl(sdev->base + DMA_IRQ_STAT(i));
+ status = sdev->cfg->read_irq_stat(sdev, i);
if (!status)
continue;
dev_dbg(sdev->slave.dev, "DMA irq status %s: 0x%x\n",
str_high_low(i), status);
- writel(status, sdev->base + DMA_IRQ_STAT(i));
+ sdev->cfg->write_irq_stat(sdev, i, status);
for (j = 0; (j < DMA_IRQ_CHAN_NR) && status; j++) {
pchan = sdev->pchans + j;
@@ -1124,6 +1148,11 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31,
.set_drq = sun6i_set_drq_a31,
.set_mode = sun6i_set_mode_a31,
+ .dump_com_regs = sun6i_dma_dump_com_regs,
+ .read_irq_en = sun6i_read_irq_en,
+ .write_irq_en = sun6i_write_irq_en,
+ .read_irq_stat = sun6i_read_irq_stat,
+ .write_irq_stat = sun6i_write_irq_stat,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1147,6 +1176,11 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31,
.set_drq = sun6i_set_drq_a31,
.set_mode = sun6i_set_mode_a31,
+ .dump_com_regs = sun6i_dma_dump_com_regs,
+ .read_irq_en = sun6i_read_irq_en,
+ .write_irq_en = sun6i_write_irq_en,
+ .read_irq_stat = sun6i_read_irq_stat,
+ .write_irq_stat = sun6i_write_irq_stat,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1165,6 +1199,11 @@ static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31,
.set_drq = sun6i_set_drq_a31,
.set_mode = sun6i_set_mode_a31,
+ .dump_com_regs = sun6i_dma_dump_com_regs,
+ .read_irq_en = sun6i_read_irq_en,
+ .write_irq_en = sun6i_write_irq_en,
+ .read_irq_stat = sun6i_read_irq_stat,
+ .write_irq_stat = sun6i_write_irq_stat,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1190,6 +1229,11 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_h3,
.set_drq = sun6i_set_drq_a31,
.set_mode = sun6i_set_mode_a31,
+ .dump_com_regs = sun6i_dma_dump_com_regs,
+ .read_irq_en = sun6i_read_irq_en,
+ .write_irq_en = sun6i_write_irq_en,
+ .read_irq_stat = sun6i_read_irq_stat,
+ .write_irq_stat = sun6i_write_irq_stat,
.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1211,6 +1255,11 @@ static struct sun6i_dma_config sun50i_a64_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_h3,
.set_drq = sun6i_set_drq_a31,
.set_mode = sun6i_set_mode_a31,
+ .dump_com_regs = sun6i_dma_dump_com_regs,
+ .read_irq_en = sun6i_read_irq_en,
+ .write_irq_en = sun6i_write_irq_en,
+ .read_irq_stat = sun6i_read_irq_stat,
+ .write_irq_stat = sun6i_write_irq_stat,
.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1232,6 +1281,11 @@ static struct sun6i_dma_config sun50i_a100_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_h3,
.set_drq = sun6i_set_drq_h6,
.set_mode = sun6i_set_mode_h6,
+ .dump_com_regs = sun6i_dma_dump_com_regs,
+ .read_irq_en = sun6i_read_irq_en,
+ .write_irq_en = sun6i_write_irq_en,
+ .read_irq_stat = sun6i_read_irq_stat,
+ .write_irq_stat = sun6i_write_irq_stat,
.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1255,6 +1309,11 @@ static struct sun6i_dma_config sun50i_h6_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_h3,
.set_drq = sun6i_set_drq_h6,
.set_mode = sun6i_set_mode_h6,
+ .dump_com_regs = sun6i_dma_dump_com_regs,
+ .read_irq_en = sun6i_read_irq_en,
+ .write_irq_en = sun6i_write_irq_en,
+ .read_irq_stat = sun6i_read_irq_stat,
+ .write_irq_stat = sun6i_write_irq_stat,
.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1281,6 +1340,11 @@ static struct sun6i_dma_config sun8i_v3s_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31,
.set_drq = sun6i_set_drq_a31,
.set_mode = sun6i_set_mode_a31,
+ .dump_com_regs = sun6i_dma_dump_com_regs,
+ .read_irq_en = sun6i_read_irq_en,
+ .write_irq_en = sun6i_write_irq_en,
+ .read_irq_stat = sun6i_read_irq_stat,
+ .write_irq_stat = sun6i_write_irq_stat,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
--
2.54.0
^ permalink raw reply related
* [PATCH 0/5] dmaengine: sun6i-dma: Add support for Allwinner A733 DMA controller
From: Yuanshen Cao @ 2026-06-19 4:53 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maxime Ripard
Cc: dmaengine, linux-arm-kernel, linux-sunxi, linux-kernel,
devicetree, Yuanshen Cao
Hi everyone,
This patch series introduces support for the Allwinner A733 DMA
controller in the `sun6i-dma` driver.
The A733 DMA controller differs from previous generations in several key
ways:
1. It supports higher address (up to 32G).
2. It uses a different interrupt register layout and mapping.
3. It has a different number of channels per interrupt register.
To support these differences without introducing complex conditional
logic throughout the driver, this series first refactors the
`sun6i_dma_config` structure. By moving interrupt handling, register
dumping, and address configuration into function pointers within the
configuration structure. This allows the driver to support the A733
and future hardware revisions. It also aligns with the DMA drivers in
Radxa BSP Package[1].
The series is organized as follows:
- Refactors the configuration structure to include function pointers for
interrupt and register operations.
- Moves address setting logic into the configuration structure to handle
varying address widths.
- Adds support for variable channels per interrupt register.
- Implements the A733-specific configuration and register mappings.
- Updates the device tree bindings documentation.
Tested on Radxa Cubie A7Z.
[1] https://github.com/radxa/allwinner-bsp/blob/cubie-aiot-v1.4.8/drivers/dma/sunxi-dma.c
Thanks!
Signed-off-by: Yuanshen Cao <alex.caoys@gmail.com>
---
Yuanshen Cao (5):
dmaengine: sun6i-dma: Refactor to support A733 interrupt and register handling
dmaengine: sun6i-dma: Add set_addr function pointer for variable address widths
dmaengine: sun6i-dma: Add num_channels_per_reg for flexible interrupt mapping
dmaengine: sun6i-dma: Implement support for Allwinner A733 DMA controller
dt-bindings: dma: sun50i-a64-dma: Update device tree bindings documentation for A733
.../bindings/dma/allwinner,sun50i-a64-dma.yaml | 2 +
drivers/dma/sun6i-dma.c | 223 +++++++++++++++++++--
2 files changed, 203 insertions(+), 22 deletions(-)
---
base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6
change-id: 20260619-sun60i-a733-dma-c2455149165d
Best regards,
--
Yuanshen Cao <alex.caoys@gmail.com>
^ permalink raw reply
* Re: [PATCH v3 3/3] arm64: dts: qcom: shikra-evk: Enable Iris core
From: Vishnu Reddy @ 2026-06-19 4:48 UTC (permalink / raw)
To: Vikash Garodia, Bryan O'Donoghue, Dikshita Agarwal,
Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jorge Ramirez-Ortiz, Bjorn Andersson, Konrad Dybcio
Cc: linux-arm-msm, linux-media, devicetree, linux-kernel,
Dmitry Baryshkov
In-Reply-To: <20260618-shikra_vpu-v3-3-1a32e26a35a1@oss.qualcomm.com>
On 6/18/2026 4:09 PM, Vikash Garodia wrote:
> Enable video en/decoder on the Shikra EVK board.
>
> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> Signed-off-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
> ---
> arch/arm64/boot/dts/qcom/shikra-evk.dtsi | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi
> index d0c48bad704c61d17309753ba2a97e89bbfe083f..e2a3131594f0410931122657b12c8a6e70b435f0 100644
> --- a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi
> +++ b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi
> @@ -3,6 +3,12 @@
> * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> */
>
> +&iris {
> + firmware-name = "qcom/vpu/ar50lt_p1_gen2_s6.mbn";
> +
> + status = "okay";
> +};
> +
> &qupv3_0 {
> firmware-name = "qcom/shikra/qupv3fw.elf";
>
Reviewed-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v3 2/3] arm64: dts: qcom: shikra: Add Iris video codec node
From: Vishnu Reddy @ 2026-06-19 4:38 UTC (permalink / raw)
To: Vikash Garodia, Bryan O'Donoghue, Dikshita Agarwal,
Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jorge Ramirez-Ortiz, Bjorn Andersson, Konrad Dybcio
Cc: linux-arm-msm, linux-media, devicetree, linux-kernel,
Konrad Dybcio, Dmitry Baryshkov
In-Reply-To: <20260618-shikra_vpu-v3-2-1a32e26a35a1@oss.qualcomm.com>
On 6/18/2026 4:09 PM, Vikash Garodia wrote:
> Add the Iris video codec device tree node for the Shikra platform.
>
> Shikra reuses the QCM2290-class video hardware and programming model.
> The video node is added to describe the Iris based video decoder
> encoder block, allowing the media driver to probe and initialize
> the hardware.
>
> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> Signed-off-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
> ---
> arch/arm64/boot/dts/qcom/shikra.dtsi | 61 ++++++++++++++++++++++++++++++++++++
> 1 file changed, 61 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi
> index 1ccb0f1419aaa34d32f3c3eaabdb8727a497b501..d8edd14d1f81a49e352f6939d27ea9cf8bb0f019 100644
> --- a/arch/arm64/boot/dts/qcom/shikra.dtsi
> +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi
> @@ -655,6 +655,67 @@ gpucc: clock-controller@5990000 {
> #power-domain-cells = <1>;
> };
>
> + iris: video-codec@5a00000 {
> + compatible = "qcom,shikra-venus", "qcom,qcm2290-venus";
> + reg = <0x0 0x5a00000 0x0 0x200000>;
> + interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH 0>;
> +
> + power-domains = <&gcc GCC_VENUS_GDSC>,
> + <&gcc GCC_VCODEC0_GDSC>,
> + <&rpmpd QCM2290_VDDCX>;
> + power-domain-names = "venus",
> + "vcodec0",
> + "cx";
> + operating-points-v2 = <&venus_opp_table>;
> +
> + clocks = <&gcc GCC_VIDEO_VENUS_CTL_CLK>,
> + <&gcc GCC_VIDEO_AHB_CLK>,
> + <&gcc GCC_VENUS_CTL_AXI_CLK>,
> + <&gcc GCC_VIDEO_THROTTLE_CORE_CLK>,
> + <&gcc GCC_VIDEO_VCODEC0_SYS_CLK>,
> + <&gcc GCC_VCODEC0_AXI_CLK>;
> + clock-names = "core",
> + "iface",
> + "bus",
> + "throttle",
> + "vcodec0_core",
> + "vcodec0_bus";
> +
> + memory-region = <&video_mem>;
> + interconnects = <&mmnrt_virt MASTER_VIDEO_P0 RPM_ALWAYS_TAG
> + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>,
> + <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG
> + &config_noc SLAVE_VENUS_CFG RPM_ACTIVE_TAG>;
> + interconnect-names = "video-mem",
> + "cpu-cfg";
> +
> + iommus = <&apps_smmu 0x780 0x0020>;
> +
> + venus_opp_table: opp-table {
> + compatible = "operating-points-v2";
> +
> + opp-133333333 {
> + opp-hz = /bits/ 64 <133333333>;
> + required-opps = <&rpmpd_opp_low_svs>;
> + };
> +
> + opp-240000000 {
> + opp-hz = /bits/ 64 <240000000>;
> + required-opps = <&rpmpd_opp_svs>;
> + };
> +
> + opp-300000000 {
> + opp-hz = /bits/ 64 <300000000>;
> + required-opps = <&rpmpd_opp_svs_plus>;
> + };
> +
> + opp-384000000 {
> + opp-hz = /bits/ 64 <384000000>;
> + required-opps = <&rpmpd_opp_nom>;
> + };
> + };
> + };
> +
> dispcc: clock-controller@5f00000 {
> compatible = "qcom,shikra-dispcc", "qcom,qcm2290-dispcc";
> reg = <0x0 0x05f00000 0x0 0x20000>;
Reviewed-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH 1/4] dt-bindings: input: Add binding for Qualcomm SPMI PMIC haptics
From: Krzysztof Kozlowski @ 2026-06-19 4:18 UTC (permalink / raw)
To: Fenglin Wu
Cc: linux-arm-msm, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Lee Jones, Stephen Boyd, Bjorn Andersson,
Konrad Dybcio, David Collins, Subbaraman Narayanamurthy,
Kamal Wadhwa, kernel, linux-input, devicetree, linux-kernel
In-Reply-To: <c7191868-d141-4095-b703-230237721f28@oss.qualcomm.com>
On 17/06/2026 13:02, Fenglin Wu wrote:
>
> On 6/17/2026 6:35 PM, Krzysztof Kozlowski wrote:
>> On Tue, Jun 16, 2026 at 03:08:24AM -0700, Fenglin Wu wrote:
>>> ....
>>> +
>>> + qcom,lra-period-us:
>>> + description:
>>> + LRA actuator initial resonance period in microseconds
>>> + (1,000,000 / resonant_freq_hz). Used to configure T_LRA-based play
>>> + rates and the auto-resonance zero-crossing window.
>> This does not feel like static characteristic. Isn't period depending on
>> intensity of vibration you want to have? Why would that be fixed per
>> board?
>
> This period is specifically used for playbacks that require
> auto-resonance to be enabled, which I referred to as "T_LRA-based" and
> "auto-resonance zero-crossing window." It plays a key role in the
> "DIRECT_PLAY" mode, which produces a constant vibration effect. To
> adjust the vibration intensity during this constant effect, the hardware
> does it by scaling the peak voltage of the driver signals, rather than
> changing the frequency.
But maybe changing frequency runtime still would be useful?
What does the frequency depend on? IOW, how do you choose the value here
- based on some motor-part characteristics?
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v3 1/3] dt-bindings: media: qcom,qcm2290-venus: document shikra Iris compatible
From: Vishnu Reddy @ 2026-06-19 3:38 UTC (permalink / raw)
To: Vikash Garodia, Bryan O'Donoghue, Dikshita Agarwal,
Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jorge Ramirez-Ortiz, Bjorn Andersson, Konrad Dybcio
Cc: linux-arm-msm, linux-media, devicetree, linux-kernel
In-Reply-To: <20260618-shikra_vpu-v3-1-1a32e26a35a1@oss.qualcomm.com>
On 6/18/2026 4:09 PM, Vikash Garodia wrote:
> Document the iris video accelerator used on shikra platforms by adding
> the qcom,shikra-iris compatible.
>
> Although QCM2290 and shikra share the same video hardware and overall
> integration, their SMMU programming differs. QCM2290 exposes separate
> stream IDs for the video hardware and the Xtensa path, requiring two
> explicit IOMMU entries, whereas shikra uses a masked SMR to collapse
> equivalent stream IDs into a single mapping. Due to QCM2290’s SID layout
> and Xtensa isolation requirements, such SMR masking is not applicable on
> QCM2290 platforms.
> Since shikra uses the same video hardware as QCM2290 and shares the same
> programming model and capabilities, it is added as a fallback compatible
> to qcom,qcm2290-venus, with conditional handling to allow either one or
> two IOMMU entries.
>
> Signed-off-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
> ---
> .../bindings/media/qcom,qcm2290-venus.yaml | 26 ++++++++++++++++------
> 1 file changed, 19 insertions(+), 7 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml b/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml
> index 5977e7d0a71b4fb5681f1c2094439c251366f01f..b27899ebf164229ceff1ca5cda50ee30d875e953 100644
> --- a/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml
> +++ b/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml
> @@ -13,14 +13,13 @@ description:
> The Venus AR50_LITE IP is a video encode and decode accelerator present
> on Qualcomm platforms.
>
> -allOf:
> - - $ref: qcom,venus-common.yaml#
> -
> properties:
> compatible:
> oneOf:
> - items:
> - - const: qcom,sm6115-venus
> + - enum:
> + - qcom,shikra-venus
> + - qcom,sm6115-venus
> - const: qcom,qcm2290-venus
> - const: qcom,qcm2290-venus
>
> @@ -45,9 +44,6 @@ properties:
> - const: vcodec0_core
> - const: vcodec0_bus
>
> - iommus:
> - maxItems: 2
> -
> interconnects:
> maxItems: 2
>
> @@ -65,6 +61,22 @@ required:
> - power-domain-names
> - iommus
>
> +allOf:
> + - $ref: qcom,venus-common.yaml#
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: qcom,shikra-venus
> + then:
> + properties:
> + iommus:
> + maxItems: 1
> + else:
> + properties:
> + iommus:
> + maxItems: 2
> +
> unevaluatedProperties: false
>
> examples:
Reviewed-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH RFC 3/3] dt-bindings: iio: adc: Add burn-out current properties
From: sashiko-bot @ 2026-06-19 0:45 UTC (permalink / raw)
To: Kurt Borja; +Cc: robh, devicetree, conor+dt
In-Reply-To: <20260618-new-channel-props-v1-3-963c1b5cf40a@gmail.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] The `burn-out-current-microamp` property lacks array bounds (e.g., `maxItems`), allowing unbounded arrays to silently pass schema validation.
- [Low] The description for `burn-out-current-polarity` is incorrectly copy-pasted from `burn-out-current-microamp` and fails to describe the polarity property itself.
--
commit a77887c22cdfb0d199c09b61e65157768374c14a
Author: Kurt Borja <kuurtb@gmail.com>
dt-bindings: iio: adc: Add burn-out current properties
This commit adds the burn-out-current-microamp and burn-out-current-polarity
properties to the generic IIO ADC bindings to allow configuration of burn-out
current sources.
> diff --git a/Documentation/devicetree/bindings/iio/adc/adc.yaml b/Documentation/devicetree/bindings/iio/adc/adc.yaml
> --- a/Documentation/devicetree/bindings/iio/adc/adc.yaml
> +++ b/Documentation/devicetree/bindings/iio/adc/adc.yaml
> @@ -106,6 +106,20 @@ properties:
> This array describes the current configuration of the excitation current
> sources or the single matched current for all sources.
>
> + burn-out-current-microamp:
> + description:
> + Burn-out current sources provide current to the channel's input pins for
> + open-circuit or short-circuit detection.
[Severity: Medium]
Since standard device tree schema tools automatically map properties ending in
"-microamp" to an array structure, does this property need an array bound like
maxItems? Without bounds, the schema validator might incorrectly accept an
array of arbitrary size instead of enforcing a single configuration value per
channel.
> +
> + burn-out-current-polarity:
> + $ref: /schemas/types.yaml#/definitions/string
> + description:
> + Burn-out current sources provide current to the channel's input pins for
> + open-circuit or short-circuit detection.
[Severity: Low]
This isn't a bug, but it looks like this description was copy-pasted from
burn-out-current-microamp. Could the description be updated to explain what
the polarity configuration (pull-up/pull-down) actually does?
> + enum:
> + - pull-up
> + - pull-down
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260618-new-channel-props-v1-0-963c1b5cf40a@gmail.com?part=3
^ permalink raw reply
* Re: [PATCH RFC 1/3] dt-bindings: iio: adc: Add reference-source property
From: sashiko-bot @ 2026-06-19 0:40 UTC (permalink / raw)
To: Kurt Borja; +Cc: devicetree, robh, conor+dt
In-Reply-To: <20260618-new-channel-props-v1-1-963c1b5cf40a@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The `reference-source` property lacks specification for the order of positive and negative reference sources when two items are provided.
--
commit 5840bfcda5df91dc955f660547ba3a189d50489a
Author: Kurt Borja <kuurtb@gmail.com>
dt-bindings: iio: adc: Add reference-source property
This commit adds a new reference-source property to the IIO ADC bindings
to allow configuring the voltage reference source or sources for each channel.
> diff --git a/Documentation/devicetree/bindings/iio/adc/adc.yaml b/Documentation/devicetree/bindings/iio/adc/adc.yaml
> --- a/Documentation/devicetree/bindings/iio/adc/adc.yaml
> +++ b/Documentation/devicetree/bindings/iio/adc/adc.yaml
> @@ -73,6 +73,16 @@ properties:
> device design and can interact with other characteristics such as
> settling time.
>
> + reference-source:
> + $ref: /schemas/types.yaml#/definitions/uint32-array
> + maxItems: 2
> + minItems: 1
> + description:
> + Indicates the voltage reference source or sources for this channel.
> +
> + This array describes either a single reference source or a positive and
> + negative reference sources.
[Severity: Medium]
When two items are provided, how do we know which index corresponds to the
positive source and which to the negative source?
Without defining the order explicitly (for example, whether the first value
is positive and the second is negative), could this ambiguity lead to
inconsistent interpretations across different drivers and device trees?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260618-new-channel-props-v1-0-963c1b5cf40a@gmail.com?part=1
^ permalink raw reply
* [PATCH RFC 3/3] dt-bindings: iio: adc: Add burn-out current properties
From: Kurt Borja @ 2026-06-19 0:33 UTC (permalink / raw)
To: Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
David Lechner
Cc: Nuno Sá, Andy Shevchenko, linux-iio, devicetree,
linux-kernel, Kurt Borja
In-Reply-To: <20260618-new-channel-props-v1-0-963c1b5cf40a@gmail.com>
Some ADCs incorporate burn-out current sources that provide current to
the channel's input pins for open-circuit or short-circuit detection.
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
Documentation/devicetree/bindings/iio/adc/adc.yaml | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/adc/adc.yaml b/Documentation/devicetree/bindings/iio/adc/adc.yaml
index 106b1e317411d5..6b63aac9ac04dd 100644
--- a/Documentation/devicetree/bindings/iio/adc/adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adc.yaml
@@ -106,6 +106,20 @@ properties:
This array describes the current configuration of the excitation current
sources or the single matched current for all sources.
+ burn-out-current-microamp:
+ description:
+ Burn-out current sources provide current to the channel's input pins for
+ open-circuit or short-circuit detection.
+
+ burn-out-current-polarity:
+ $ref: /schemas/types.yaml#/definitions/string
+ description:
+ Burn-out current sources provide current to the channel's input pins for
+ open-circuit or short-circuit detection.
+ enum:
+ - pull-up
+ - pull-down
+
anyOf:
- oneOf:
- required:
--
2.54.0
^ permalink raw reply related
* [PATCH RFC 2/3] dt-bindings: iio: adc: Add excitation current sources properties
From: Kurt Borja @ 2026-06-19 0:33 UTC (permalink / raw)
To: Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
David Lechner
Cc: Nuno Sá, Andy Shevchenko, linux-iio, devicetree,
linux-kernel, Kurt Borja
In-Reply-To: <20260618-new-channel-props-v1-0-963c1b5cf40a@gmail.com>
Some ADCs incorporate current sources that provide excitation current to
resistive temperature devices (RTDs), thermistors diodes and other
resistive sensors that require constant current biasing.
The maxItems constraint of 16 is arbitrary but should be big enough for
most devices.
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
Documentation/devicetree/bindings/iio/adc/adc.yaml | 23 ++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/adc/adc.yaml b/Documentation/devicetree/bindings/iio/adc/adc.yaml
index c74c2084fdb68c..106b1e317411d5 100644
--- a/Documentation/devicetree/bindings/iio/adc/adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adc.yaml
@@ -83,6 +83,29 @@ properties:
This array describes either a single reference source or a positive and
negative reference sources.
+ excitation-channels:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ maxItems: 16
+ minItems: 1
+ description:
+ Excitation current sources provide current to resistive temperature
+ devices (RTDs), thermistors diodes and other resistive sensors that
+ require constant current biasing.
+
+ This array describes the mux configuration of the excitation current
+ sources.
+
+ excitation-current-microamp:
+ maxItems: 16
+ minItems: 1
+ description:
+ Excitation current sources provide current to resistive temperature
+ devices (RTDs), thermistors diodes and other resistive sensors that
+ require constant current biasing.
+
+ This array describes the current configuration of the excitation current
+ sources or the single matched current for all sources.
+
anyOf:
- oneOf:
- required:
--
2.54.0
^ permalink raw reply related
* [PATCH RFC 1/3] dt-bindings: iio: adc: Add reference-source property
From: Kurt Borja @ 2026-06-19 0:33 UTC (permalink / raw)
To: Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
David Lechner
Cc: Nuno Sá, Andy Shevchenko, linux-iio, devicetree,
linux-kernel, Kurt Borja
In-Reply-To: <20260618-new-channel-props-v1-0-963c1b5cf40a@gmail.com>
Some ADCs have configurable voltage reference sources for each channel.
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
Documentation/devicetree/bindings/iio/adc/adc.yaml | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/adc/adc.yaml b/Documentation/devicetree/bindings/iio/adc/adc.yaml
index b9bc02b5b07a4c..c74c2084fdb68c 100644
--- a/Documentation/devicetree/bindings/iio/adc/adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adc.yaml
@@ -73,6 +73,16 @@ properties:
device design and can interact with other characteristics such as
settling time.
+ reference-source:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ maxItems: 2
+ minItems: 1
+ description:
+ Indicates the voltage reference source or sources for this channel.
+
+ This array describes either a single reference source or a positive and
+ negative reference sources.
+
anyOf:
- oneOf:
- required:
--
2.54.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox