Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH 00/11] arm64: dts: renesas: Specify ethernet PHY reset timings
From: Geert Uytterhoeven @ 2026-05-22 13:18 UTC (permalink / raw)
  To: Marek Vasut
  Cc: linux-arm-kernel, Conor Dooley, Geert Uytterhoeven,
	Krzysztof Kozlowski, Magnus Damm, Rob Herring, devicetree,
	linux-kernel, linux-renesas-soc
In-Reply-To: <20260505034325.167797-1-marek.vasut+renesas@mailbox.org>

Hi Marek,

On Tue, 5 May 2026 at 05:43, Marek Vasut
<marek.vasut+renesas@mailbox.org> wrote:
> This is the same patch for various boards, details are below.
> The discussion that prompted this patchset is at [0].

Thanks for your series!

> The KSZ9031RNX reference manual [1] DS00002096H page 60 FIGURE 7-7:

DS00002117K page 62 FIGURE 7-5

(and page 74 on the older document I had ;-)

> POWER-UP/POWER-DOWN/RESET TIMING Note 2 states, that after the
> de-assertion of reset, wait a minimum of 100 us before starting
> programming on the MIIM (MDC/MDIO) interface. Set DT property
> reset-deassert-us to three times that, 300 us, to provide ample
> time between reset deassertion and MDIO access.
>
> The KSZ9031RNX reference manual [1] DS00002096H page 60 TABLE 7-7:
> POWER-UP/POWER-DOWN/RESET TIMING PARAMETERS row tSR Stable supply

page 62 TABLE 7-4

> voltages to de-assertion of reset is at minimum 10 ms. Set DT
> property reset-assert-us to 10ms because the KSZ9031RNX RM does
> not explicitly spell out how long the reset has to be asserted,
> but this at least covers the worst case scenario.
>
> The Gray Hawk patch in this series depends on [2].
>
> [0] https://lore.kernel.org/all/CAMuHMdXJvrsXitGagqZJ_STdTTh_s1cBAKf6+esihaVWjfn40g@mail.gmail.com/
> [1] https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/DataSheets/KSZ9031MNX-Data-Sheet-DS00002096.pdf

This link leads to the KSZ9031MNX part. Correct link is:

https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/DataSheets/KSZ9031RNX-Data-Sheet-DS00002117.pdf

> [2] https://lore.kernel.org/all/20260504225428.114959-1-marek.vasut+renesas@mailbox.org/

Shall I do the big search-and-replace while applying?

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* Re: [PATCH v6 2/2] drm: panel: add support for the Renesas R63419 based dual-DSI video mode Display Panels
From: sashiko-bot @ 2026-05-22 13:17 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: conor+dt, robh, wsa+renesas, devicetree
In-Reply-To: <20260522-topic-sm8650-ayaneo-pocket-s2-r63419-v6-2-16edddda9951@linaro.org>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] The MIPI DCS initialization sequence in `renesas_r63419_on()` is inverted, sending 'Set Display On' before 'Exit Sleep Mode'.
- [High] Missing device link between the panel and the secondary DSI host creates a Use-After-Free risk.
- [High] The panel is published to the DRM subsystem before its DSI device properties are initialized and attached.
- [Medium] Asymmetrical DRM panel callbacks: DCS ON logic is in `.prepare` while DCS OFF logic is in `.disable`.
--

commit 2dc8ee5a664e9e795b047b17cd7126c4bd9d27d8
Author: KancyJoe <kancy2333@outlook.com>

drm: panel: add support for the Renesas R63419 based dual-DSI video mode Display Panels
    
Implement support for the Renesas 63419 based dual-DSI video mode
Display Panels found in the Ayaneo gaming handled devices.

> diff --git a/drivers/gpu/drm/panel/panel-renesas-r63419.c b/drivers/gpu/drm/panel/panel-renesas-r63419.c
> new file mode 100644
> index 0000000000000..dba156f8427cd
> --- /dev/null
> +++ b/drivers/gpu/drm/panel/panel-renesas-r63419.c

[ ... ]

> +static int renesas_r63419_on(struct renesas_r63419_panel *ctx)
> +{
> +	struct mipi_dsi_multi_context dsi_ctx = { 0 };
> +
> +	dsi_link_switch(ctx, &dsi_ctx, 0);
> +	mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
> +	dsi_link_switch(ctx, &dsi_ctx, 1);
> +	mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
> +	mipi_dsi_msleep(&dsi_ctx, 150);
> +
> +	dsi_link_switch(ctx, &dsi_ctx, 0);
> +	mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
> +	dsi_link_switch(ctx, &dsi_ctx, 1);
> +	mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
> +	mipi_dsi_msleep(&dsi_ctx, 50);

[Severity: High]
Does this send the MIPI DCS commands in the correct order?

The MIPI DCS specification requires a display module to be taken out of sleep
mode (0x11 command) and allowed to wake up before the display on command
(0x29) is sent. 

Here the display on command is sent while the panel is still in sleep mode,
which typically results in the command being ignored by the display
controller.

[ ... ]

> +static const struct drm_panel_funcs renesas_r63419_panel_funcs = {
> +	.disable = renesas_r63419_disable,
> +	.prepare = renesas_r63419_prepare,
> +	.unprepare = renesas_r63419_unprepare,
> +	.get_modes = renesas_r63419_get_modes,
> +	.get_orientation = renesas_r63419_get_orientation,
> +};

[Severity: Medium]
Should the DCS ON/OFF logic be symmetrical in these callbacks?

The driver executes its DCS turn-on sequence inside .prepare via
renesas_r63419_on(), but assigns its DCS turn-off sequence to the .disable
callback.

If the DRM core aborts display initialization after .prepare but before
.enable would logically occur, it will call .unprepare. However, .unprepare
only powers off the regulators and skips the DCS OFF sequence.

[ ... ]

> +	/* Register the second DSI device */
> +	ctx->dsi[1] = devm_mipi_dsi_device_register_full(dev, dsi1_host, &info);
> +	if (IS_ERR(ctx->dsi[1]))
> +		return dev_err_probe(dev, PTR_ERR(ctx->dsi[1]),
> +				     "Failed to register second DSI device\n");

[Severity: High]
Is a device link needed between the panel and the secondary DSI host?

The driver registers a secondary DSI device on a remote host, but it does
not establish a device link (e.g., via device_link_add()) to enforce
consumer-supplier unbind ordering.

If the secondary DSI host is unbound independently, the panel driver will
not be unbound along with it, leaving ctx->dsi[1] pointing to a freed or
unregistered host. Subsequent DRM atomic operations would dereference this
dangling pointer.

> +
> +	ctx->dsi[0] = dsi;
> +	mipi_dsi_set_drvdata(dsi, ctx);
> +
> +	/* Get panel orientation */
> +	ret = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation);
> +	if (ret < 0 && ret != -ENODEV)
> +		return dev_err_probe(dev, ret,
> +				     "Failed to get panel orientation\n");
> +
> +	ctx->panel.prepare_prev_first = true;
> +
> +	ret = drm_panel_of_backlight(&ctx->panel);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "Failed to get backlight\n");
> +
> +	ret = devm_drm_panel_add(dev, &ctx->panel);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "Failed to add panel\n");
> +
> +	/* Configure and attach both DSI devices */
> +	for (i = 0; i < ARRAY_SIZE(ctx->dsi); i++) {
> +		ctx->dsi[i]->lanes = ctx->desc->lanes;
> +		ctx->dsi[i]->format = ctx->desc->format;
> +		ctx->dsi[i]->mode_flags = ctx->desc->mode_flags;
> +
> +		ret = devm_mipi_dsi_attach(dev, ctx->dsi[i]);

[Severity: High]
Could the panel be probed by the DRM subsystem before it is fully initialized?

devm_drm_panel_add() adds the panel to the global DRM panel list, making it
visible to other drivers. However, critical DSI device properties like
lanes and format are set and devm_mipi_dsi_attach() is executed after this
call.

A concurrent display controller probing the panel could find it and attempt
to send DCS commands before the DSI physical links are attached.

> +		if (ret < 0)
> +			return dev_err_probe(dev, ret,
> +					     "Failed to attach DSI device %d\n", i);
> +	}
> +
> +	return 0;
> +}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260522-topic-sm8650-ayaneo-pocket-s2-r63419-v6-0-16edddda9951@linaro.org?part=2

^ permalink raw reply

* Re: [PATCH v3 7/8] dt-bindings: iio: temperature: Add ADT7604 support to adi,ltc2983
From: Jonathan Cameron @ 2026-05-22 13:17 UTC (permalink / raw)
  To: Liviu Stan
  Cc: David Lechner, Nuno Sá, Andy Shevchenko, Michael Hennerich,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Antoniu Miclaus,
	Francesco Lavra, linux-iio, linux-kernel, linux, devicetree
In-Reply-To: <20260522114259.841-1-liviu.stan@analog.com>

On Fri, 22 May 2026 14:42:53 +0300
Liviu Stan <liviu.stan@analog.com> wrote:

> On Thu, 21 May 2026 18:23:07 +0000 sashiko-bot@kernel.org wrote:
> 
> > Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> > - [Low] The new compatible string 'adi,adt7604' is omitted from the existing conditional block that disables '^temp@' nodes, violating subsystem guidelines.
> > - [Low] The schema allows invalid 'adi,sensor-type' values in '^rtd@' and '^thermistor@' nodes for the ADT7604.
> > --
> > 
> > commit fbbcd3bcbfbb106e48a6545868dd2b27a56b39b5
> > Author: Liviu Stan <liviu.stan@analog.com>
> > 
> > dt-bindings: iio: temperature: Add ADT7604 support to adi,ltc2983
> > 
> > This commit adds support for the ADT7604 to the LTC2983 binding schema. It
> > introduces the adi,adt7604 compatible string and adds two new sensor node
> > types: copper-trace@ and leak-detector@. It also adds conditional checks to
> > restrict unsupported nodes for the ADT7604 device.
> >   
> > > diff --git a/Documentation/devicetree/bindings/iio/temperature/adi,ltc2983.yaml b/Documentation/devicetree/bindings/iio/temperature/adi,ltc2983.yaml
> > > index a22725f7619b7..14cfa28809edd 100644
> > > --- a/Documentation/devicetree/bindings/iio/temperature/adi,ltc2983.yaml
> > > +++ b/Documentation/devicetree/bindings/iio/temperature/adi,ltc2983.yaml  
> > [ ... ]  
> > > @@ -477,6 +597,22 @@ allOf:
> > >        patternProperties:
> > >          '^temp@': false
> > >  
> > > +  - if:
> > > +      properties:
> > > +        compatible:
> > > +          contains:
> > > +            const: adi,adt7604
> > > +    then:
> > > +      patternProperties:
> > > +        '^thermocouple@': false
> > > +        '^diode@': false
> > > +        '^adc@': false
> > > +        '^temp@': false  
> > 
> > [Severity: Low]
> > Since ADT7604 shares the ^temp@: false constraint with the existing devices,
> > should adi,adt7604 be added to the existing compatible enum block instead of
> > duplicating the ^temp@ restriction in this new conditional?  
> 
> I think keeping all ADT7604 related constraints in one block is more readable.
> For the block above it's different because ltc2984 and ltc2983 share the same
> constraints.

Agreed

> 
> > 
> > [Severity: Low]
> > The commit message mentions that ADT7604 repurposes the custom RTD sensor type
> > (18) and custom thermistor type (27).
> > 
> > However, the schema doesn't restrict adi,sensor-type = <18> inside ^rtd@ nodes
> > or adi,sensor-type = <27> inside ^thermistor@ nodes for the adi,adt7604
> > compatible.
> > 
> > Should these restrictions be added to this block to prevent invalid device
> > tree configurations from passing validation?
> >   
> 
> This makes sense, we could restrict sensor type 18 and 27 for the ADT7604, even
> though the driver's supported_sensors bitmask already rejects them.
> 
> I could add something like:
> 
> - if:
>     properties:
>       compatible:
>         contains:
>           const: adi,adt7604
>   then:
>     patternProperties:
>       '^thermocouple@': false
>       '^diode@': false
>       '^adc@': false
>       '^temp@': false
>       '^rtd@':
>         properties:
>           adi,sensor-type:
>             not:
>               const: 18
>       '^thermistor@':
>         properties:
>           adi,sensor-type:
>             not:
>               const: 27
> 
> What do you think?
> 
Seems like a nice to have.

> Thanks,
> Liviu
> 


^ permalink raw reply

* [PATCH v2] arm64: dts: qcom: sm8650-ayaneo-pocket-s2: add display nodes
From: Neil Armstrong @ 2026-05-22 13:15 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Geert Uytterhoeven, Magnus Damm
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-renesas-soc,
	KancyJoe, Neil Armstrong

From: KancyJoe <kancy2333@outlook.com>

Add nodes for the dual DSI panel, the SGM3804 regulator, the
SY7758 backlight controller, the touch controller, and enable
the GPU to enable full display support.

Signed-off-by: KancyJoe <kancy2333@outlook.com>
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
Depends on follwing bindings, all reviewed:
- https://lore.kernel.org/all/20260522-topic-sm8650-ayaneo-pocket-s2-r63419-v6-1-16edddda9951@linaro.org/
- https://lore.kernel.org/all/20260521-topic-sm8650-ayaneo-pocket-s2-sy7758-v4-1-73c732615e4a@linaro.org/
- https://lore.kernel.org/all/20260522-topic-sm8650-ayaneo-pocket-s2-sgm3804-v5-1-bd6b1c300ecc@linaro.org/
---
Changes in v2:
- Update for bindings changes
- Remove empty line
- Link to v1: https://patch.msgid.link/20260428-topic-sm8650-ayaneo-pocket-s2-display-dt-v1-1-ff132c00d076@linaro.org
---
 .../boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts      | 241 +++++++++++++++++++++
 1 file changed, 241 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts b/arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts
index 0dc994f4e48d..af890e76813b 100644
--- a/arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts
+++ b/arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts
@@ -220,6 +220,22 @@ upd720201_vdd33_reg: upd720201-vdd33-regulator {
 		pinctrl-names = "default";
 	};
 
+	sy7758_vdd33_reg: sy7758-vdd33-regulator {
+		compatible = "regulator-fixed";
+
+		regulator-name = "sy7758_vdd33";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&tlmm 163 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+
+		vin-supply = <&vph_pwr>;
+
+		pinctrl-0 = <&sy7758_vdd33>;
+		pinctrl-names = "default";
+	};
+
 	sound {
 		compatible = "qcom,sm8650-sndcard", "qcom,sm8450-sndcard";
 		model = "SM8650-APS2";
@@ -986,6 +1002,14 @@ gpu7_active: trip-active {
 	};
 };
 
+&gpu {
+	status = "okay";
+
+	zap-shader {
+		firmware-name = "qcom/sm8650/ayaneo/ps2/gen70900_zap.mbn";
+	};
+};
+
 &i2c3 {
 	clock-frequency = <100000>;
 
@@ -1016,6 +1040,30 @@ wcd_usbss_sbu_mux: endpoint {
 	};
 };
 
+&i2c4 {
+	clock-frequency = <400000>;
+
+	status = "okay";
+
+	touchscreen@5d {
+		compatible = "goodix,gt911";
+		reg = <0x5d>;
+
+		interrupt-parent = <&tlmm>;
+		interrupts = <162 IRQ_TYPE_EDGE_FALLING>;
+
+		reset-gpios = <&tlmm 161 GPIO_ACTIVE_HIGH>;
+		VDDIO-supply = <&vreg_l14b_3p2>;
+		AVDD28-supply = <&vreg_l14b_3p2>;
+
+		touchscreen-size-x = <1440>;
+		touchscreen-size-y = <2560>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&ts_reset_default>, <&ts_irq_default>;
+	};
+};
+
 &i2c6 {
 	clock-frequency = <100000>;
 
@@ -1053,6 +1101,49 @@ redriver_ss_in: endpoint {
 	};
 };
 
+&i2c9 {
+	status = "okay";
+
+	/* Screen power */
+	regulator@3e {
+		compatible = "sgmicro,sgm3804";
+		reg = <0x3e>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&sgm3804_default>;
+
+		vin-supply = <&vph_pwr>;
+
+		sgm3804_pos: pos {
+			regulator-name = "panel-avdd-pos";
+			regulator-min-microvolt = <5200000>;
+			regulator-max-microvolt = <5200000>;
+			regulator-active-discharge = <1>;
+			enable-gpios = <&tlmm 59 GPIO_ACTIVE_HIGH>;
+		};
+
+		sgm3804_neg: neg {
+			regulator-name = "panel-avdd-neg";
+			regulator-min-microvolt = <5200000>;
+			regulator-max-microvolt = <5200000>;
+			regulator-active-discharge = <1>;
+			enable-gpios = <&tlmm 58 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	/* Backlight */
+	sy7758_backlight: sy7758@2e {
+		compatible = "silergy,sy7758";
+		reg = <0x2e>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&sy7758_default>;
+
+		vddio-supply = <&sy7758_vdd33_reg>;
+		enable-gpios = <&tlmm 164 GPIO_ACTIVE_HIGH>;
+	};
+};
+
 &iris {
 	status = "okay";
 };
@@ -1065,6 +1156,93 @@ &mdss {
 	status = "okay";
 };
 
+&mdss_dsi0 {
+	vdda-supply = <&vreg_l3i_1p2>;
+
+	qcom,master-dsi;
+	qcom,dual-dsi-mode;
+	qcom,sync-dual-dsi;
+
+	status = "okay";
+
+	panel@0 {
+		status = "okay";
+		compatible = "ayaneo,wt0630-2k", "renesas,r63419";
+		reg = <0>;
+
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&disp0_reset_n_active>;
+		pinctrl-1 = <&disp0_reset_n_suspend>;
+
+		vddio-supply = <&vreg_l12b_1p8>;
+		vdd-supply = <&vreg_l11b_1p2>;
+		vsp-supply = <&sgm3804_pos>;
+		vsn-supply = <&sgm3804_neg>;
+		vci-supply = <&vreg_l13b_3p0>;
+
+		backlight = <&sy7758_backlight>;
+
+		reset-gpios = <&tlmm 133 GPIO_ACTIVE_LOW>;
+
+		rotation = <90>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				panel0_in_0: endpoint {
+					remote-endpoint = <&mdss_dsi0_out>;
+				};
+			};
+
+			port@1{
+				reg = <1>;
+				panel0_in_1: endpoint {
+					remote-endpoint = <&mdss_dsi1_out>;
+				};
+			};
+		};
+	};
+};
+
+&mdss_dsi0_out {
+	remote-endpoint = <&panel0_in_0>;
+
+	data-lanes = <0 1 2 3>;
+};
+
+&mdss_dsi0_phy {
+	vdds-supply = <&vreg_l1i_0p88>;
+
+	status = "okay";
+};
+
+&mdss_dsi1 {
+	vdda-supply = <&vreg_l3i_1p2>;
+
+	assigned-clock-parents = <&mdss_dsi0_phy DSI_BYTE_PLL_CLK>,
+				 <&mdss_dsi0_phy DSI_PIXEL_PLL_CLK>;
+
+	qcom,dual-dsi-mode;
+	qcom,sync-dual-dsi;
+
+	status = "okay";
+};
+
+&mdss_dsi1_out {
+	remote-endpoint = <&panel0_in_1>;
+
+	data-lanes = <0 1 2 3>;
+};
+
+&mdss_dsi1_phy {
+	vdds-supply = <&vreg_l1i_0p88>;
+
+	status = "okay";
+};
+
 &mdss_dp0 {
 	status = "okay";
 };
@@ -1390,6 +1568,20 @@ sw-ctrl-pins {
 		};
 	};
 
+	disp0_reset_n_active: disp0-reset-n-active-state {
+		pins = "gpio133";
+		function = "gpio";
+		drive-strength = <8>;
+		bias-disable;
+	};
+
+	disp0_reset_n_suspend: disp0-reset-n-suspend-state {
+		pins = "gpio133";
+		function = "gpio";
+		drive-strength = <2>;
+		bias-pull-down;
+	};
+
 	fan_pwr_pins: fan-pwr-state {
 		pins = "gpio125";
 		function = "gpio";
@@ -1411,6 +1603,20 @@ fan_int: fan-int-state {
 		bias-pull-up;
 	};
 
+	mdp_vsync_active: mdp-vsync-active-state {
+		pins = "gpio86";
+		function = "mdp_vsync";
+		drive-strength = <2>;
+		bias-pull-down;
+	};
+
+	mdp_vsync_suspend: mdp-vsync-suspend-state {
+		pins = "gpio86";
+		function = "mdp_vsync";
+		drive-strength = <2>;
+		bias-pull-down;
+	};
+
 	upd720201_avdd33: upd720201-avdd33-state {
 		pins = "gpio123";
 		function = "gpio";
@@ -1440,6 +1646,13 @@ gamepad_pwr_en: gamepad-pwr-en-active-state {
 		output-high;
 	};
 
+	sgm3804_default: sgm3804-default-state {
+		pins = "gpio58", "gpio59";
+		function = "gpio";
+		drive-strength = <8>;
+		bias-disable;
+	};
+
 	spkr_23_sd_n_active: spkr-23-sd-n-active-state {
 		pins = "gpio77";
 		function = "gpio";
@@ -1454,6 +1667,34 @@ spkr_01_sd_n_active: spkr-01-sd-n-active-state {
 		bias-disable;
 	};
 
+	sy7758_default: sy7758-default-state {
+		pins = "gpio164";
+		function = "gpio";
+		drive-strength = <2>;
+		bias-disable;
+	};
+
+	sy7758_vdd33: sy7758-vdd33-state {
+		pins = "gpio163";
+		function = "gpio";
+		drive-strength = <2>;
+		bias-disable;
+	};
+
+	ts_irq_default: ts-irq-active-state {
+		pins = "gpio162";
+		function = "gpio";
+		drive-strength = <8>;
+		bias-disable;
+	};
+
+	ts_reset_default: ts-reset-active-state {
+		pins = "gpio161";
+		function = "gpio";
+		drive-strength = <8>;
+		bias-pull-down;
+	};
+
 	wcd_default: wcd-reset-n-active-state {
 		pins = "gpio107";
 		function = "gpio";

---
base-commit: 5e9b7d093f3f77cb0af4409559e3d139babfb443
change-id: 20260428-topic-sm8650-ayaneo-pocket-s2-display-dt-539bb79eb709
prerequisite-change-id: 20260428-topic-sm8650-ayaneo-pocket-s2-sgm3804-8764fbb72eb7:v5
prerequisite-patch-id: 901a0948e1afbb03ff78a063d4f66c17665588ef
prerequisite-patch-id: 5ca959a92d05c86ae7a77400d5c4c9bb8bb214f4
prerequisite-change-id: 20260428-topic-sm8650-ayaneo-pocket-s2-sy7758-3081ee7f1e25:v4
prerequisite-patch-id: eba24fd4013ddf353136a6b77cba84678e60edce
prerequisite-patch-id: 63b9ea68bb624685fae324bd8db9545f73658e23
prerequisite-change-id: 20260428-topic-sm8650-ayaneo-pocket-s2-r63419-e72467e2db0f:v6
prerequisite-patch-id: 53130195c1df5886a953f3eb1ffea6e5b32257ec
prerequisite-patch-id: 268452dda581581e0126cfd331cf99537544fe65

Best regards,
--  
Neil Armstrong <neil.armstrong@linaro.org>


^ permalink raw reply related

* Re: [PATCH v7 2/9] reset: eyeq: Add EyeQ7H compatibles
From: sashiko-bot @ 2026-05-22 13:15 UTC (permalink / raw)
  To: Benoît Monin; +Cc: devicetree, robh, conor+dt
In-Reply-To: <20260522-clk-eyeq7-v7-2-14ad6c2c5213@bootlin.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The `valid_mask` values for several new EyeQ7H reset domains are incorrectly calculated based on the total number of items rather than acting as a bitmask of valid hardware offsets, causing valid reset requests to be rejected.
--

commit 8189291a57ece537a6cbcca42424bb22f1515514
Author: Benoît Monin <benoit.monin@bootlin.com>

reset: eyeq: Add EyeQ7H compatibles

This commit adds support for the reset controllers found in the EyeQ7H OLB.
It introduces three new types of reset domains, defines their respective
configurations, and updates the wait timings.

> diff --git a/drivers/reset/reset-eyeq.c b/drivers/reset/reset-eyeq.c
> index 1a38579838970..381237d50f061 100644
> --- a/drivers/reset/reset-eyeq.c
> +++ b/drivers/reset/reset-eyeq.c
> @@ -73,6 +74,40 @@
>   *  9. PMA0	10. PMA1	11. MPC0	12. MPC1
>   * 13. MPC2	14. MPC3	15. PERIPH
>   *
> + * Known resets in EyeQ7H acc domain 0 (type EQR_EYEQ7H_ACRP)
> + *  1. VMP0	2. XVMP1	3. VMP2		4. VMP3
> + *  5. MPC0	6. MPC1		7. PMA0		8. PMA1
> + *
> + * Known resets in EyeQ7H acc domain 1 (type EQR_EYEQ7H_ACC)
> + *  1. NCORE0	 2. NCORE1	3. NCORE0_M	4. NCORE1_M
> + *  5. NCORE_NOC 6. VMP_NOC	7. MPC_NOC	8. PMA_NOC
> + *
> + * Known resets in EyeQ7H ddr (type EQR_EYEQ7H_CFG)
> + *  0. APB	2. DMI		3. DFI		4. PHY_SMS
> + *  5. CTL_SMS
> + *
> + * Known resets in EyeQ7H east (type EQR_EYEQ7H_CFG)
> + *  0. ISP	2. VEU		3. LBIST
> + *
> + * Known resets in EyeQ7H periph (type EQR_EYEQ6H_SARCR)
> + *  0. gpio	1.EXT TIMER	3.UART		4. SPI
> + *  5. I2C0	6. I2C1		7.I2C2		8. I2S

[ ... ]

> @@ -558,6 +681,113 @@ static const struct eqr_match_data eqr_eyeq6h_acc_data = {

[ ... ]

> +static const struct eqr_domain_descriptor eqr_eyeq7h_ddr_domains[] = {
> +	{
> +		.type = EQR_EYEQ7H_CFG,
> +		.valid_mask = 0x1F,

[Severity: High]
Will this valid_mask reject valid reset requests for the CTL_SMS (offset 5)
reset? 

The known resets listed above include APB (0), DMI (2), DFI (3), PHY_SMS (4),
and CTL_SMS (5). Using 0x1F only covers bits 0 through 4, meaning a request
for offset 5 will fail the bitmask check in eqr_of_xlate_internal() and
return -EINVAL.

Should this mask be 0x3D instead?

> +		.offset = 0x008,
> +	},
> +};

[ ... ]

> +static const struct eqr_domain_descriptor eqr_eyeq7h_per_domains[] = {
> +	{
> +		.type = EQR_EYEQ6H_SARCR,
> +		.valid_mask = 0xFF,

[Severity: High]
Is this mask calculated based on the total number of items rather than acting
as a bitmask of valid hardware offsets? 

The known resets for the periph domain include I2S at offset 8, but a mask
of 0xFF only covers bits 0 through 7. This appears to affect several other
new domains as well (like east and xnn), where the valid_mask value seems
to be calculated as (1 << num_resets) - 1 rather than setting the specific
bits that correspond to the valid offsets.

> +		.offset = 0x030,
> +	},
> +};

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260522-clk-eyeq7-v7-0-14ad6c2c5213@bootlin.com?part=2

^ permalink raw reply

* [PATCH v3 1/2] ASoC: dt-bindings: add SpacemiT K3 SoC compatible
From: Troy Mitchell @ 2026-05-22 13:12 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
	Yixun Lan, Jinmei Wei, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: linux-sound, linux-riscv, spacemit, linux-kernel, devicetree,
	Troy Mitchell
In-Reply-To: <20260522-k3-i2s-v3-0-08e3eb811d93@linux.spacemit.com>

Add the spacemit,k3-i2s compatible string for the K3 SoC I2S
controller. The K3 I2S IP is the same as K1 but requires additional
clocks: a dedicated sysclk_div clock, along with common_sysclk and
common_bclk which are shared across multiple I2S controllers on K3.

Acked-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
---
 .../devicetree/bindings/sound/spacemit,k1-i2s.yaml | 31 ++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/spacemit,k1-i2s.yaml b/Documentation/devicetree/bindings/sound/spacemit,k1-i2s.yaml
index 55bd0b307d22..240d90402e4f 100644
--- a/Documentation/devicetree/bindings/sound/spacemit,k1-i2s.yaml
+++ b/Documentation/devicetree/bindings/sound/spacemit,k1-i2s.yaml
@@ -4,7 +4,7 @@
 $id: http://devicetree.org/schemas/sound/spacemit,k1-i2s.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: K1 I2S controller
+title: SpacemiT K1/K3 I2S controller
 
 description:
   The I2S bus (Inter-IC sound bus) is a serial link for digital
@@ -15,27 +15,54 @@ maintainers:
 
 allOf:
   - $ref: dai-common.yaml#
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: spacemit,k3-i2s
+    then:
+      properties:
+        clocks:
+          minItems: 7
+        clock-names:
+          minItems: 7
+    else:
+      properties:
+        clocks:
+          maxItems: 4
+        clock-names:
+          maxItems: 4
 
 properties:
   compatible:
-    const: spacemit,k1-i2s
+    enum:
+      - spacemit,k1-i2s
+      - spacemit,k3-i2s
 
   reg:
     maxItems: 1
 
   clocks:
+    minItems: 4
     items:
       - description: clock for I2S sysclk
       - description: clock for I2S bclk
       - description: clock for I2S bus
       - description: clock for I2S controller
+      - description: clock for I2S sysclk divider
+      - description: clock for I2S common sysclk
+      - description: clock for I2S common bclk
 
   clock-names:
+    minItems: 4
     items:
       - const: sysclk
       - const: bclk
       - const: bus
       - const: func
+      - const: sysclk_div
+      - const: c_sysclk
+      - const: c_bclk
 
   dmas:
     minItems: 1

-- 
2.54.0


^ permalink raw reply related

* [PATCH v3 2/2] ASoC: spacemit: add K3 SoC support with additional clocks
From: Troy Mitchell @ 2026-05-22 13:12 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
	Yixun Lan, Jinmei Wei, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: linux-sound, linux-riscv, spacemit, linux-kernel, devicetree,
	Troy Mitchell
In-Reply-To: <20260522-k3-i2s-v3-0-08e3eb811d93@linux.spacemit.com>

Add support for the SpacemiT K3 SoC I2S controller, which shares the
same IP as K1 but requires additional clocks: sysclk_div, c_sysclk,
and c_bclk. These clocks only exist on K3 and are not present on K1.
The sysclk_div clock is present on most K3 I2S controllers except I2S1.
The c_sysclk and c_bclk clocks are shared across multiple I2S
controllers on K3.

Use devm_clk_get_optional_enabled() to acquire these clocks so that
the driver works on both K1 (where they are absent) and K3 without
needing SoC-specific match data. For K3, the sysclk_div rate is set
before sysclk in set_sysclk, and the common clock rates are configured
in hw_params based on the sample rate.

Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
---
 sound/soc/spacemit/k1_i2s.c | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/sound/soc/spacemit/k1_i2s.c b/sound/soc/spacemit/k1_i2s.c
index 1cb99f1abc7c..4e655d714623 100644
--- a/sound/soc/spacemit/k1_i2s.c
+++ b/sound/soc/spacemit/k1_i2s.c
@@ -53,6 +53,9 @@ struct spacemit_i2s_dev {
 	struct clk *sysclk;
 	struct clk *bclk;
 	struct clk *sspa_clk;
+	struct clk *sysclk_div;
+	struct clk *c_sysclk;
+	struct clk *c_bclk;
 
 	struct snd_dmaengine_dai_dma_data capture_dma_data;
 	struct snd_dmaengine_dai_dma_data playback_dma_data;
@@ -189,6 +192,14 @@ static int spacemit_i2s_hw_params(struct snd_pcm_substream *substream,
 		    params_rate(params) *
 		    data_bits;
 
+	ret = clk_set_rate(i2s->c_sysclk, bclk_rate * 2);
+	if (ret)
+		return ret;
+
+	ret = clk_set_rate(i2s->c_bclk, bclk_rate);
+	if (ret)
+		return ret;
+
 	ret = clk_set_rate(i2s->bclk, bclk_rate);
 	if (ret)
 		return ret;
@@ -200,10 +211,17 @@ static int spacemit_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
 				   unsigned int freq, int dir)
 {
 	struct spacemit_i2s_dev *i2s = dev_get_drvdata(cpu_dai->dev);
+	int ret;
 
 	if (freq == 0)
 		return 0;
 
+	if (i2s->sysclk_div) {
+		ret = clk_set_rate(i2s->sysclk_div, freq);
+		if (ret)
+			return ret;
+	}
+
 	return clk_set_rate(i2s->sysclk, freq);
 }
 
@@ -418,6 +436,21 @@ static int spacemit_i2s_probe(struct platform_device *pdev)
 		return dev_err_probe(i2s->dev, PTR_ERR(i2s->sspa_clk),
 				     "failed to enable sspa clock\n");
 
+	i2s->sysclk_div = devm_clk_get_optional_enabled(i2s->dev, "sysclk_div");
+	if (IS_ERR(i2s->sysclk_div))
+		return dev_err_probe(i2s->dev, PTR_ERR(i2s->sysclk_div),
+				     "failed to enable sysclk_div clock\n");
+
+	i2s->c_sysclk = devm_clk_get_optional_enabled(i2s->dev, "c_sysclk");
+	if (IS_ERR(i2s->c_sysclk))
+		return dev_err_probe(i2s->dev, PTR_ERR(i2s->c_sysclk),
+				     "failed to enable c_sysclk clock\n");
+
+	i2s->c_bclk = devm_clk_get_optional_enabled(i2s->dev, "c_bclk");
+	if (IS_ERR(i2s->c_bclk))
+		return dev_err_probe(i2s->dev, PTR_ERR(i2s->c_bclk),
+				     "failed to enable c_bclk clock\n");
+
 	i2s->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
 	if (IS_ERR(i2s->base))
 		return dev_err_probe(i2s->dev, PTR_ERR(i2s->base), "failed to map registers\n");
@@ -444,6 +477,7 @@ static int spacemit_i2s_probe(struct platform_device *pdev)
 
 static const struct of_device_id spacemit_i2s_of_match[] = {
 	{ .compatible = "spacemit,k1-i2s", },
+	{ .compatible = "spacemit,k3-i2s", },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, spacemit_i2s_of_match);
@@ -458,4 +492,4 @@ static struct platform_driver spacemit_i2s_driver = {
 module_platform_driver(spacemit_i2s_driver);
 
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("I2S bus driver for SpacemiT K1 SoC");
+MODULE_DESCRIPTION("I2S bus driver for SpacemiT K1/K3 SoC");

-- 
2.54.0


^ permalink raw reply related

* [PATCH v3 0/2] ASoC: spacemit: add K3 SoC support
From: Troy Mitchell @ 2026-05-22 13:12 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
	Yixun Lan, Jinmei Wei, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: linux-sound, linux-riscv, spacemit, linux-kernel, devicetree,
	Troy Mitchell

This series adds K3 SoC support for the SpacemiT I2S controller driver.

Patch 1 adds the dt-bindings for the spacemit,k3-i2s compatible. The K3
SoC uses the same I2S IP as K1 but requires additional clocks
(sysclk_div, c_sysclk, c_bclk) that are shared across multiple I2S
controllers.

Patch 2 adds driver support for K3 SoC with additional clocks.

Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
---
Changes in v3:
- remove patch 3/3, send it as a standalone patch later
- Link to v2: https://patch.msgid.link/20260507-k3-i2s-v2-0-9cdbf95b7533@linux.spacemit.com

Changes in v2:
- Drop bug fix patches (1-3/7) — patches 2-3 already merged, patch 1
  split into a standalone series
- Drop fixed-sample-rate patches (5-6/7) — will address shared BCLK
  constraint at the ASoC core level in a separate series
- update commit msg (1/7)
- Add rob's tag
- Link to v1: https://patch.msgid.link/20260429-k3-i2s-v1-0-2fe99db11ecb@linux.spacemit.com

To: Liam Girdwood <lgirdwood@gmail.com>
To: Mark Brown <broonie@kernel.org>
To: Rob Herring <robh@kernel.org>
To: Krzysztof Kozlowski <krzk+dt@kernel.org>
To: Conor Dooley <conor+dt@kernel.org>
To: Yixun Lan <dlan@kernel.org>
To: Troy Mitchell <troy.mitchell@linux.spacemit.com>
To: Jaroslav Kysela <perex@perex.cz>
To: Takashi Iwai <tiwai@suse.com>
Cc: linux-sound@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-riscv@lists.infradead.org
Cc: spacemit@lists.linux.dev
Cc: linux-kernel@vger.kernel.org

---
Troy Mitchell (2):
      ASoC: dt-bindings: add SpacemiT K3 SoC compatible
      ASoC: spacemit: add K3 SoC support with additional clocks

 .../devicetree/bindings/sound/spacemit,k1-i2s.yaml | 31 +++++++++++++++++--
 sound/soc/spacemit/k1_i2s.c                        | 36 +++++++++++++++++++++-
 2 files changed, 64 insertions(+), 3 deletions(-)
---
base-commit: f58f2e0137c2132a08a1ab42720a9540cf0093a8
change-id: 20260427-k3-i2s-52ae21807466

Best regards,
--  
Troy Mitchell <troy.mitchell@linux.spacemit.com>


^ permalink raw reply

* [PATCH v5 2/2] regulator: add SGM3804 Dual Output driver
From: Neil Armstrong @ 2026-05-22 13:09 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: linux-kernel, devicetree, KancyJoe, Neil Armstrong
In-Reply-To: <20260522-topic-sm8650-ayaneo-pocket-s2-sgm3804-v5-0-bd6b1c300ecc@linaro.org>

From: KancyJoe <kancy2333@outlook.com>

Add support for the SG Micro SGM3804 Single Inductor Dual Output
Buck/Boost Converter used to power LCD panels a provide positive
and negative power rails with configurable voltage and active
discharge function for each output.

The SGM3804 is powered by the enable GPIO pins inputs and only
supports I2C write messages.
In order to add flexibility and simplify the driver, the
regmap cache is enabled and populated with default values
since we can't write registers when the 2 GPIOs are down.

Signed-off-by: KancyJoe <kancy2333@outlook.com>
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 drivers/regulator/Kconfig             |   8 +
 drivers/regulator/Makefile            |   1 +
 drivers/regulator/sgm3804-regulator.c | 314 ++++++++++++++++++++++++++++++++++
 3 files changed, 323 insertions(+)

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index e8002526cfb0..b79ad8852033 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -1489,6 +1489,14 @@ config REGULATOR_SC2731
 	  This driver provides support for the voltage regulators on the
 	  SC2731 PMIC.
 
+config REGULATOR_SGM3804
+	tristate "SGMicro SGM3804 voltage regulator"
+	depends on I2C && OF
+	depends on GPIOLIB
+	select REGMAP_I2C
+	help
+	  This driver supports SGMicro SGM3804 dual-output voltage regulator.
+
 config REGULATOR_SKY81452
 	tristate "Skyworks Solutions SKY81452 voltage regulator"
 	depends on MFD_SKY81452
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 35639f3115fd..98ecbbc3c6b7 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -172,6 +172,7 @@ obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
 obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
 obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
 obj-$(CONFIG_REGULATOR_SC2731) += sc2731-regulator.o
+obj-$(CONFIG_REGULATOR_SGM3804) += sgm3804-regulator.o
 obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o
 obj-$(CONFIG_REGULATOR_SLG51000) += slg51000-regulator.o
 obj-$(CONFIG_REGULATOR_SPACEMIT_P1) += spacemit-p1.o
diff --git a/drivers/regulator/sgm3804-regulator.c b/drivers/regulator/sgm3804-regulator.c
new file mode 100644
index 000000000000..c3406cfb73d0
--- /dev/null
+++ b/drivers/regulator/sgm3804-regulator.c
@@ -0,0 +1,314 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// SGMicro SGM3804 regulator Driver
+//
+// Copyright (C) 2025 Kancy Joe <kancy2333@outlook.com>
+// Copyright (C) 2026 Linaro Limited
+// Author: Neil Armstrong <neil.armstrong@linaro.org>
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/gpio/consumer.h>
+
+#define SGM3804_POS_RAIL_VOLTAGE_REG	0x0
+#define SGM3804_NEG_RAIL_VOLTAGE_REG	0x1
+#define SGM3804_RAIL_DISCHARGE_REG	0x3
+
+#define RAIL_VOLTAGE_MASK	GENMASK(5, 0)
+
+#define POS_RAIL_DISCHARGE_EN	BIT(1)
+#define NEG_RAIL_DISCHARGE_EN	BIT(0)
+
+#define RAIL_VOLTAGE_INVALID		RAIL_VOLTAGE_MASK
+#define RAIL_DISCHARGE_REG_DEFAULT	(POS_RAIL_DISCHARGE_EN | NEG_RAIL_DISCHARGE_EN)
+
+#define SGM3804_VOLTAGES_MAX_SELECTOR	0x2f
+
+enum {
+	SGM3804_POS_RAIL = 0,
+	SGM3804_NEG_RAIL,
+	SGM3804_RAIL_COUNT,
+};
+
+/*
+ * The registers are only writable when the gpio is enabled, so
+ * we need to use the cache for read operations and set the regmap
+ * as cache_only when both GPIOs are down.
+ */
+struct sgm3804_data {
+	struct regmap *regmap;
+	/* Protects the regcache state update */
+	struct mutex lock;
+	struct gpio_desc *gpios[SGM3804_RAIL_COUNT];
+};
+
+static const struct linear_range sgm3804_voltages[] = {
+	REGULATOR_LINEAR_RANGE(2400000, 0x20, 0x2f, 100000),
+	REGULATOR_LINEAR_RANGE(4000000, 0x00, 0x17, 100000),
+};
+
+/*
+ * The cache is populated with those hardware default values
+ * so the regmap_update_bits operation will use the cached
+ * value to build a new register value and write it when GPIOs
+ * are enabled.
+ */
+static const struct reg_default sgm3804_reg_defaults[] = {
+	{ SGM3804_POS_RAIL_VOLTAGE_REG, RAIL_VOLTAGE_INVALID },
+	{ SGM3804_NEG_RAIL_VOLTAGE_REG, RAIL_VOLTAGE_INVALID },
+	{ SGM3804_RAIL_DISCHARGE_REG, RAIL_DISCHARGE_REG_DEFAULT },
+};
+
+/* Registers are only writable */
+static bool sgm3804_writeable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case SGM3804_POS_RAIL_VOLTAGE_REG:
+	case SGM3804_NEG_RAIL_VOLTAGE_REG:
+	case SGM3804_RAIL_DISCHARGE_REG:
+		return true;
+	default:
+		return false;
+	}
+}
+
+/*
+ * Since all registers are only writeable, regmap will only read from the cache data.
+ */
+static bool sgm3804_readable_reg(struct device *dev, unsigned int reg)
+{
+	return false;
+}
+
+static const struct regmap_config sgm3804_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = 0x03,
+	.writeable_reg = sgm3804_writeable_reg,
+	.readable_reg = sgm3804_readable_reg,
+	.cache_type = REGCACHE_MAPLE,
+	.reg_defaults = sgm3804_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(sgm3804_reg_defaults),
+};
+
+static int sgm3804_sync_regcache_state(struct sgm3804_data *ctx)
+{
+	guard(mutex)(&ctx->lock);
+
+	/* If both GPIOs are down, IC is powered down and I2C writes will fail */
+	if (!gpiod_get_value_cansleep(ctx->gpios[SGM3804_POS_RAIL]) &&
+	    !gpiod_get_value_cansleep(ctx->gpios[SGM3804_NEG_RAIL])) {
+		regcache_cache_only(ctx->regmap, true);
+		regcache_mark_dirty(ctx->regmap);
+	} else {
+		int ret;
+
+		/* At least a GPIO is up, we can write registers */
+		regcache_cache_only(ctx->regmap, false);
+		ret = regcache_sync(ctx->regmap);
+		if (ret) {
+			regcache_cache_only(ctx->regmap, true);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int sgm3804_get_voltage_sel(struct regulator_dev *rdev)
+{
+	int ret;
+
+	ret = regulator_get_voltage_sel_regmap(rdev);
+	if (ret < 0)
+		return ret;
+
+	/* Force setting a voltage on probe */
+	if (ret == RAIL_VOLTAGE_INVALID)
+		return -ENOTRECOVERABLE;
+
+	return ret;
+}
+
+static int sgm3804_enable(struct regulator_dev *rdev)
+{
+	struct sgm3804_data *ctx = rdev->reg_data;
+	int ret;
+
+	ret = gpiod_set_value_cansleep(ctx->gpios[rdev_get_id(rdev)], 1);
+	if (ret)
+		return ret;
+
+	ret = sgm3804_sync_regcache_state(ctx);
+	if (ret)
+		goto err;
+
+	return 0;
+
+err:
+	gpiod_set_value_cansleep(ctx->gpios[rdev_get_id(rdev)], 0);
+	return ret;
+}
+
+static int sgm3804_disable(struct regulator_dev *rdev)
+{
+	struct sgm3804_data *ctx = rdev->reg_data;
+	int ret;
+
+	ret = gpiod_set_value_cansleep(ctx->gpios[rdev_get_id(rdev)], 0);
+	if (ret)
+		return ret;
+
+	return sgm3804_sync_regcache_state(ctx);
+}
+
+static int sgm3804_is_enabled(struct regulator_dev *rdev)
+{
+	struct sgm3804_data *ctx = rdev->reg_data;
+
+	return gpiod_get_value_cansleep(ctx->gpios[rdev_get_id(rdev)]);
+}
+
+static const struct regulator_ops sgm3804_ops = {
+	.list_voltage = regulator_list_voltage_linear_range,
+	.map_voltage = regulator_map_voltage_linear_range,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = sgm3804_get_voltage_sel,
+	.set_active_discharge = regulator_set_active_discharge_regmap,
+	.enable = sgm3804_enable,
+	.disable = sgm3804_disable,
+	.is_enabled = sgm3804_is_enabled,
+};
+
+static const struct regulator_desc sgm3804_regulator_desc[] = {
+	/* Positive Output */
+	{
+		.name = "pos",
+		.of_match = "pos",
+		.supply_name = "vin",
+		.id = SGM3804_POS_RAIL,
+		.ops = &sgm3804_ops,
+		.type = REGULATOR_VOLTAGE,
+		.linear_ranges = sgm3804_voltages,
+		.n_linear_ranges = ARRAY_SIZE(sgm3804_voltages),
+		.n_voltages = SGM3804_VOLTAGES_MAX_SELECTOR + 1,
+		.vsel_reg = SGM3804_POS_RAIL_VOLTAGE_REG,
+		.vsel_mask = RAIL_VOLTAGE_MASK,
+		.active_discharge_on = POS_RAIL_DISCHARGE_EN,
+		.active_discharge_mask = POS_RAIL_DISCHARGE_EN,
+		.active_discharge_reg = SGM3804_RAIL_DISCHARGE_REG,
+		.enable_time = 40000,
+		.owner = THIS_MODULE,
+	},
+	/* Negative Output */
+	{
+		.name = "neg",
+		.of_match = "neg",
+		.supply_name = "vin",
+		.id = SGM3804_NEG_RAIL,
+		.ops = &sgm3804_ops,
+		.type = REGULATOR_VOLTAGE,
+		.linear_ranges = sgm3804_voltages,
+		.n_linear_ranges = ARRAY_SIZE(sgm3804_voltages),
+		.n_voltages = SGM3804_VOLTAGES_MAX_SELECTOR + 1,
+		.vsel_reg = SGM3804_NEG_RAIL_VOLTAGE_REG,
+		.vsel_mask = RAIL_VOLTAGE_MASK,
+		.active_discharge_on = NEG_RAIL_DISCHARGE_EN,
+		.active_discharge_mask = NEG_RAIL_DISCHARGE_EN,
+		.active_discharge_reg = SGM3804_RAIL_DISCHARGE_REG,
+		.enable_time = 40000,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int sgm3804_probe(struct i2c_client *i2c)
+{
+	struct device *dev = &i2c->dev;
+	struct sgm3804_data *ctx;
+	int ret, i;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	mutex_init(&ctx->lock);
+
+	ctx->regmap = devm_regmap_init_i2c(i2c, &sgm3804_regmap_config);
+	if (IS_ERR(ctx->regmap))
+		return dev_err_probe(dev, PTR_ERR(ctx->regmap),
+				     "failed to init regmap\n");
+
+	/* Get enable GPIOs */
+	for (i = 0; i < ARRAY_SIZE(sgm3804_regulator_desc); i++) {
+		const struct regulator_desc *reg = &sgm3804_regulator_desc[i];
+		struct fwnode_handle *child;
+
+		child = device_get_named_child_node(dev, reg->of_match);
+		if (!child) {
+			dev_err(dev, "missing child '%s'\n", reg->of_match);
+			return -EINVAL;
+		}
+
+		ctx->gpios[i] = devm_fwnode_gpiod_get(dev, child, "enable",
+						      GPIOD_ASIS, reg->name);
+		fwnode_handle_put(child);
+		if (IS_ERR(ctx->gpios[i]))
+			return dev_err_probe(dev, PTR_ERR(ctx->gpios[i]),
+					     "failed to get '%s' enable GPIO\n",
+					     reg->name);
+	}
+
+	ret = sgm3804_sync_regcache_state(ctx);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < ARRAY_SIZE(sgm3804_regulator_desc); i++) {
+		struct regulator_config config = { };
+		struct regulator_dev *rdev;
+
+		config.dev = dev;
+		config.regmap = ctx->regmap;
+		config.of_node = dev_of_node(dev);
+		config.driver_data = ctx;
+		rdev = devm_regulator_register(dev, &sgm3804_regulator_desc[i],
+					       &config);
+		if (IS_ERR(rdev))
+			return dev_err_probe(dev, PTR_ERR(rdev),
+					     "failed to register regulator %d\n", i);
+	}
+
+	return 0;
+}
+
+static const struct i2c_device_id sgm3804_id[] = {
+	{ "sgm3804" },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, sgm3804_id);
+
+static const struct of_device_id sgm3804_of_match[] = {
+	{ .compatible = "sgmicro,sgm3804" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sgm3804_of_match);
+
+static struct i2c_driver sgm3804_regulator_driver = {
+	.driver = {
+		.name = "sgm3804",
+		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
+		.of_match_table = sgm3804_of_match,
+	},
+	.probe = sgm3804_probe,
+	.id_table = sgm3804_id,
+};
+
+module_i2c_driver(sgm3804_regulator_driver);
+
+MODULE_DESCRIPTION("SGMicro SGM3804 regulator Driver");
+MODULE_AUTHOR("Kancy Joe <kancy2333@outlook.com>");
+MODULE_AUTHOR("Neil Armstrong <neil.armstrong@linaro.org>");
+MODULE_LICENSE("GPL");

-- 
2.34.1


^ permalink raw reply related

* [PATCH v5 1/2] regulator: dt-bindings: document the SGM3804 Dual Output regulator
From: Neil Armstrong @ 2026-05-22 13:09 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: linux-kernel, devicetree, KancyJoe, Neil Armstrong
In-Reply-To: <20260522-topic-sm8650-ayaneo-pocket-s2-sgm3804-v5-0-bd6b1c300ecc@linaro.org>

Document the SG Micro SGM3804 Single Inductor Dual Output Buck/Boost
Converter used to power LCD panels a provide positive and negative
power rails with configurable voltage and active discharge function
for each output.

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 .../bindings/regulator/sgmicro,sgm3804.yaml        | 77 ++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/Documentation/devicetree/bindings/regulator/sgmicro,sgm3804.yaml b/Documentation/devicetree/bindings/regulator/sgmicro,sgm3804.yaml
new file mode 100644
index 000000000000..3716eaf81aa9
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/sgmicro,sgm3804.yaml
@@ -0,0 +1,77 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/sgmicro,sgm3804.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: SG Micro SGM3804 Single Inductor Dual Output Buck/Boost Converter
+
+maintainers:
+  - Neil Armstrong <neil.armstrong@linaro.org>
+
+description:
+  The SGM3804 is a dual voltage regulator, designed to support positive/negative
+  supply for driving LCD panels. It support software-configurable output
+  switching. The output voltages can be programmed via an I2C compatible interface.
+
+properties:
+  compatible:
+    const: sgmicro,sgm3804
+
+  reg:
+    maxItems: 1
+
+  vin-supply: true
+
+patternProperties:
+  "^(pos|neg)$":
+    type: object
+    $ref: regulator.yaml#
+
+    properties:
+      enable-gpios: true
+
+    unevaluatedProperties: false
+
+    required:
+      - enable-gpios
+
+required:
+  - compatible
+  - reg
+  - pos
+  - neg
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        regulator@3e {
+            compatible = "sgmicro,sgm3804";
+            reg = <0x3e>;
+
+            vin-supply = <&vin_reg>;
+
+            pos {
+                regulator-name = "outpos";
+                regulator-min-microvolt = <5000000>;
+                regulator-max-microvolt = <5000000>;
+                enable-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
+            };
+
+            neg {
+                regulator-name = "outneg";
+                regulator-min-microvolt = <5000000>;
+                regulator-max-microvolt = <5000000>;
+                enable-gpios = <&gpio 18 GPIO_ACTIVE_HIGH>;
+            };
+        };
+    };
+...
+

-- 
2.34.1


^ permalink raw reply related

* [PATCH v5 0/2] regulator: add support for SGM3804 Dual Output driver
From: Neil Armstrong @ 2026-05-22 13:09 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: linux-kernel, devicetree, KancyJoe, Neil Armstrong

Add support for the SG Micro SGM3804 Single Inductor Dual Output
Buck/Boost Converter used to power LCD panels a provide positive
and negative power rails with configurable voltage and active
discharge function for each output.

The SGM3804 is powered by the enable GPIO pins inputs and only
supports I2C write messages. 
In order to add flexibility and simplify the driver, the
regmap cache is enabled and populated with default values
since we can't write registers when the 2 GPIOs are down.

This regulator is used to provide vsn and vsn power to the
Ayaneo Pocket S2 dual-DSI LCD panel.

Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
Changes in v5:
- Add dependencies on GPIOLIB
- Mark as cache only if sync fails
- Use proper selector number for n_voltages
- Link to v4: https://patch.msgid.link/20260506-topic-sm8650-ayaneo-pocket-s2-sgm3804-v4-0-7495e7905693@linaro.org

Changes in v4:
- Moved the enable-gpios to subnodes due to enable-gpio bindings constraint
- Added code to get enable gpios from subnodes using fwnode to avoid the of->fwnode dance
- Switch last gpio call to cansleep
- Moved the Kconfig/Makefile entry in the right place
- Link to v3: https://patch.msgid.link/20260504-topic-sm8650-ayaneo-pocket-s2-sgm3804-v3-0-c4783443890b@linaro.org

Changes in v3:
- Change header in c++ comment block
- Switch to regcache dirty/only instead of custom handling
- Use GPIO_ASIS to avoid turning off regulator on boot
- Use gpio cansleep
- Add my MODULE_AUTHOR and reorder the signoff
- Link to v2: https://patch.msgid.link/20260430-topic-sm8650-ayaneo-pocket-s2-sgm3804-v2-0-76108c65a560@linaro.org

Changes in v2:
- Fixed bindings subject and gpios minItems
- Fixed regulator signed-off order
- Added second MODULE_AUTHOR entry
- Added more comments on how regmap cache is configured to work
- Link to v1: https://patch.msgid.link/20260428-topic-sm8650-ayaneo-pocket-s2-sgm3804-v1-0-1d8dc7620256@linaro.org

---
KancyJoe (1):
      regulator: add SGM3804 Dual Output driver

Neil Armstrong (1):
      regulator: dt-bindings: document the SGM3804 Dual Output regulator

 .../bindings/regulator/sgmicro,sgm3804.yaml        |  77 +++++
 drivers/regulator/Kconfig                          |   8 +
 drivers/regulator/Makefile                         |   1 +
 drivers/regulator/sgm3804-regulator.c              | 314 +++++++++++++++++++++
 4 files changed, 400 insertions(+)
---
base-commit: 39704f00f747aba3144289870b5fd8ac230a9aaf
change-id: 20260428-topic-sm8650-ayaneo-pocket-s2-sgm3804-8764fbb72eb7

Best regards,
--  
Neil Armstrong <neil.armstrong@linaro.org>


^ permalink raw reply

* Re: [PATCH v3 2/2] remoteproc: qcom: pas: Add Shikra remoteproc support
From: Komal Bajaj @ 2026-05-22 13:08 UTC (permalink / raw)
  To: sashiko-reviews; +Cc: robh, conor+dt, devicetree
In-Reply-To: <20260521135659.A15C11F000E9@smtp.kernel.org>

On 5/21/2026 7:26 PM, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [High] Missing `ssctl_id` initialization for `shikra_lpaicp_resource` causing graceful shutdown failure.
> --
>
> commit de542ab4b48a2146f6973ba793bbbd6328de204c
> Author: Bibek Kumar Patro <bibek.patro@oss.qualcomm.com>
>
> remoteproc: qcom: pas: Add Shikra remoteproc support
>      
> This commit adds the CDSP, LPAICP and MPSS Peripheral Authentication Service
> support for the Qualcomm Shikra SoC.
>
>> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
>> index da27d1d3c9da6..0101f1db6458e 100644
>> --- a/drivers/remoteproc/qcom_q6v5_pas.c
>> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
> [ ... ]
>> @@ -1457,6 +1457,51 @@ static const struct qcom_pas_data sc7280_wpss_resource = {
> [ ... ]
>> +static const struct qcom_pas_data shikra_lpaicp_resource = {
>> +	.crash_reason_smem = 682,
>> +	.firmware_name = "lpaicp.mbn",
>> +	.dtb_firmware_name = "lpaicp_dtb.mbn",
>> +	.pas_id = 0x56,
>> +	.dtb_pas_id = 0x57,
>> +	.minidump_id = 0,
>> +	.auto_boot = true,
>> +	.ssr_name = "lpaicp",
>> +	.sysmon_name = "lpaicp",
>> +};
> [Severity: High]
> Does this resource definition need an ssctl_id initialized?
>
> The sysmon subdevice is enabled by setting .sysmon_name = "lpaicp", but it
> fails to define .ssctl_id. Because .ssctl_id is uninitialized, it defaults
> to 0, which means qcom_add_sysmon_subdev() will be passed 0 as the QMI
> SSCTL instance ID.
>
> Looking at ssctl_new_server() in drivers/remoteproc/qcom_sysmon.c, the
> version 2 QMI service binding requires svc->instance ==
> sysmon->ssctl_instance. Since modern Qualcomm PAS QMI SSCTL services
> advertise non-zero instance IDs, could this cause the binding to fail?
>
> If the remoteproc framework never establishes an SSCTL connection to the
> LPAICP DSP, sysmon_stop() will explicitly skip waiting for the SSCTL service
> connection since ssctl_instance == 0.
>
> When the DSP needs to be stopped, will sysmon_stop() bypass
> ssctl_request_shutdown() and forcefully power off the DSP instead of
> gracefully shutting down?
>
> Forceful shutdowns of active DSPs can lead to hardware state corruption
> or SMMU faults, which often cascade into kernel panics on these platforms.

On Shikra LPAICP, we are not hosting the QMI SSCTL service currently, so 
there is no SSCTL instance to bind to and .ssctl_id is intentionally 
left unset (defaults to 0). In this setup, the sysmon SSCTL 
connection/shutdown path is not used; shutdown relies on the normal PAS 
power-down sequence.

Thanks
Komal

>


^ permalink raw reply

* Re: [PATCH v3 5/8] iio: temperature: ltc2983: Fix n_wires default bypassing rotation check
From: Jonathan Cameron @ 2026-05-22 13:06 UTC (permalink / raw)
  To: Liviu Stan
  Cc: David Lechner, Nuno Sá, Andy Shevchenko, Michael Hennerich,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Antoniu Miclaus,
	Francesco Lavra, linux-iio, linux-kernel, linux, devicetree
In-Reply-To: <20260521164323.770626-6-liviu.stan@analog.com>

On Thu, 21 May 2026 19:42:58 +0300
Liviu Stan <liviu.stan@analog.com> wrote:

> When adi,number-of-wires is absent, n_wires is left at 0. The binding
> documents a default of 2 wires, matching the hardware default. However
> the current-rotate validation checks n_wires == 2 || n_wires == 3, so
> with n_wires = 0 the guard is bypassed and adi,current-rotate is accepted
> for a 2-wire RTD.
> 
> Initialize n_wires = 2 to match the binding default and ensure the
> rotation check fires correctly when the property is absent.
> 
> Fixes: f110f3188e56 ("iio: temperature: Add support for LTC2983")
> Signed-off-by: Liviu Stan <liviu.stan@analog.com>
This should be the first patch in the series so it is obvious that it
is easily backported without the rest + I might pick up via the fixes-togreg
tree.

Jonathan

> ---
> Changes in v3:
> - New patch
> 
>  drivers/iio/temperature/ltc2983.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c
> index 10f423fbe9cc..326f843f4271 100644
> --- a/drivers/iio/temperature/ltc2983.c
> +++ b/drivers/iio/temperature/ltc2983.c
> @@ -749,7 +749,7 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st,
>  	struct ltc2983_rtd *rtd;
>  	int ret = 0;
>  	struct device *dev = &st->spi->dev;
> -	u32 excitation_current = 0, n_wires = 0;
> +	u32 excitation_current = 0, n_wires = 2;
>  
>  	rtd = devm_kzalloc(dev, sizeof(*rtd), GFP_KERNEL);
>  	if (!rtd)


^ permalink raw reply

* Re: [PATCH v4 2/2] regulator: add SGM3804 Dual Output driver
From: Neil Armstrong @ 2026-05-22 13:03 UTC (permalink / raw)
  To: Mark Brown
  Cc: Liam Girdwood, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-kernel, devicetree, KancyJoe
In-Reply-To: <8916f45b-3a97-4a5e-b608-5feaea40f2b2@sirena.org.uk>

On 5/22/26 14:01, Mark Brown wrote:
> On Wed, May 06, 2026 at 09:34:07AM +0200, Neil Armstrong wrote:
> 
>> +config REGULATOR_SGM3804
>> +	tristate "SGMicro SGM3804 voltage regulator"
>> +	depends on I2C && OF
>> +	select REGMAP_I2C
>> +	help
>> +	  This driver supports SGMicro SGM3804 dual-output voltage regulator.
>> +
> 
> The GPIO usage in the driver looks non-optional so we should have a
> GPIOLIB dependency shouldn't we?

Indeed

> 
>> +static int sgm3804_sync_regcache_state(struct sgm3804_data *ctx)
>> +{
>> +	guard(mutex)(&ctx->lock);
>> +
>> +	/* If both GPIOs are down, IC is powered down and I2C writes will fail */
>> +	if (!gpiod_get_value_cansleep(ctx->gpios[SGM3804_POS_RAIL]) &&
>> +	    !gpiod_get_value_cansleep(ctx->gpios[SGM3804_NEG_RAIL])) {
>> +		regcache_cache_only(ctx->regmap, true);
>> +		regcache_mark_dirty(ctx->regmap);
>> +	} else {
>> +		/* At least a GPIO is up, we can write registers */
>> +		regcache_cache_only(ctx->regmap, false);
>> +		return regcache_sync(ctx->regmap);
> 
> This should really put the regmap back into cache only mode if the sync
> fails.

Right

> 
>> +static const struct regulator_desc sgm3804_regulator_desc[] = {
>> +	/* Positive Output */
>> +	{
>> +		.name = "pos",
>> +		.of_match = "pos",
>> +		.supply_name = "vin",
>> +		.id = SGM3804_POS_RAIL,
>> +		.ops = &sgm3804_ops,
>> +		.type = REGULATOR_VOLTAGE,
>> +		.linear_ranges = sgm3804_voltages,
>> +		.n_linear_ranges = ARRAY_SIZE(sgm3804_voltages),
>> +		.n_voltages = SGM3804_VOLTAGES_COUNT,
> 
> n_voltages is misnamed and should really be maximum selector, for a
> device like this with sparse selectors it doesn't do what you'd expect
> unfortunately.

OK indeed thanks, I overlooked this part

Neil

^ permalink raw reply

* Re: [PATCH v3 2/8] iio: temperature: ltc2983: Use local device pointer consistently
From: Jonathan Cameron @ 2026-05-22 13:02 UTC (permalink / raw)
  To: Liviu Stan
  Cc: David Lechner, Nuno Sá, Andy Shevchenko, Michael Hennerich,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Antoniu Miclaus,
	Francesco Lavra, linux-iio, linux-kernel, linux, devicetree
In-Reply-To: <20260521164323.770626-3-liviu.stan@analog.com>

On Thu, 21 May 2026 19:42:55 +0300
Liviu Stan <liviu.stan@analog.com> wrote:

> Some functions define a local 'dev' pointer but still use bare
> '&st->spi->dev' in some code paths, and some don't have it at all.
> Replace bare references with the local pointer for consistency.
> 
> Signed-off-by: Liviu Stan <liviu.stan@analog.com>

Hi Liviu,

When doing this sort of change, one of the advantages is often that code lines
get shorter. So look at the lines touched and see if the wrapping remains
appropriate.

At least some of the cases I point out below already fitted on one line
under 80 chars but none the less they are now even shorter so that needs
tidying up.  Note that a few other cases are just over 80 chars.
Take a look at those and decide if readability is improved much by just
going a few characters over.  That line length isn't the hard rule it
used to be!

> ---
> Changes in v3:
> - Dropped the Fixes: tag
> - Fixed one remaining dev_dbg() call in __ltc2983_chan_assign_common()
>   that was still using the raw device pointer instead of the dev local
>   variable introduced by this patch
> 
>  drivers/iio/temperature/ltc2983.c | 83 +++++++++++++++++--------------
>  1 file changed, 47 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c
> index 67a09934c5bd..d9dcf3e86696 100644
> --- a/drivers/iio/temperature/ltc2983.c
> +++ b/drivers/iio/temperature/ltc2983.c
> @@ -351,10 +351,11 @@ static int __ltc2983_chan_assign_common(struct ltc2983_data *st,
>  					const struct ltc2983_sensor *sensor,
>  					u32 chan_val)
>  {
> +	struct device *dev = &st->spi->dev;
>  	u32 reg = LTC2983_CHAN_ASSIGN_ADDR(sensor->chan);
>  
>  	chan_val |= LTC2983_CHAN_TYPE(sensor->type);
> -	dev_dbg(&st->spi->dev, "Assign reg:0x%04X, val:0x%08X\n", reg,
> +	dev_dbg(dev, "Assign reg:0x%04X, val:0x%08X\n", reg,
>  		chan_val);

chan_val easily fits on the line above now.  It actually did before
but given you are changing this lets tidy it up to;

	dev_dbg(dev, "Assign reg:0x%04X, val:0x%08X\n", reg, chan_val);


>  	st->chan_val = cpu_to_be32(chan_val);
>  	return regmap_bulk_write(st->regmap, reg, &st->chan_val,




> @@ -1222,11 +1229,12 @@ static int ltc2983_read_raw(struct iio_dev *indio_dev,
>  			    int *val, int *val2, long mask)
>  {
>  	struct ltc2983_data *st = iio_priv(indio_dev);
> +	struct device *dev = &st->spi->dev;
>  	int ret;
>  
>  	/* sanity check */
>  	if (chan->address >= st->num_channels) {
> -		dev_err(&st->spi->dev, "Invalid chan address:%ld",
> +		dev_err(dev, "Invalid chan address:%ld",
>  			chan->address);

		dev_err(dev, "Invalid chan address:%ld", chan->address);

>  		return -EINVAL;
>  	}

> @@ -1427,6 +1436,7 @@ static int ltc2983_eeprom_cmd(struct ltc2983_data *st, unsigned int cmd,
>  static int ltc2983_setup(struct ltc2983_data *st, bool assign_iio)
>  {
>  	u32 iio_chan_t = 0, iio_chan_v = 0, chan, iio_idx = 0, status;
> +	struct device *dev = &st->spi->dev;
>  	int ret;
>  
>  	/* make sure the device is up: start bit (7) is 0 and done bit (6) is 1 */
> @@ -1434,7 +1444,7 @@ static int ltc2983_setup(struct ltc2983_data *st, bool assign_iio)
>  				       LTC2983_STATUS_UP(status) == 1, 25000,
>  				       25000 * 10);
>  	if (ret)
> -		return dev_err_probe(&st->spi->dev, ret,
> +		return dev_err_probe(dev, ret,
>  				     "Device startup timed out\n");

		return dev_err_probe(dev, ret, "Device startup timed out\n");


>  
>  	ret = regmap_update_bits(st->regmap, LTC2983_GLOBAL_CONFIG_REG,
> @@ -1535,12 +1545,13 @@ static const struct  iio_info ltc2983_iio_info = {

> @@ -1589,10 +1600,10 @@ static int ltc2983_probe(struct spi_device *spi)
>  	if (ret)
>  		return ret;
>  
> -	ret = devm_request_irq(&spi->dev, spi->irq, ltc2983_irq_handler,
> +	ret = devm_request_irq(dev, spi->irq, ltc2983_irq_handler,
>  			       IRQF_TRIGGER_RISING, st->info->name, st);
>  	if (ret)
> -		return dev_err_probe(&spi->dev, ret,
> +		return dev_err_probe(dev, ret,
>  				     "failed to request an irq\n");

		return dev_err_probe(dev, ret, "failed to request an irq\n");

Thanks,

Jonathan




>  

^ permalink raw reply

* Re: [PATCH 9/9] arm64: dts: renesas: rzg3s-smarc-som: Enable I3C
From: Claudiu Beznea @ 2026-05-22 13:01 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: geert+renesas, linusw, robh, krzk+dt, conor+dt, magnus.damm,
	claudiu.beznea, linux-renesas-soc, linux-gpio, devicetree,
	linux-kernel, Claudiu Beznea
In-Reply-To: <ahBMKWrKQDko3cG8@shikoro>

Hi, Wolfram,

On 5/22/26 15:29, Wolfram Sang wrote:
> Hi Claudiu,
> 
>> +	i3c_pins: i3c {
>> +		pins = "I3C_SDA", "I3C_SCL";
>> +#if SW_CONFIG4 == SW_ON
>> +		power-source = <1200>;
>> +#else
>> +		power-source = <1800>;
>> +#endif
>> +		input-enable;
>> +		renesas,i3c-standby = <0>;
>> +	};
>> +
>> +	i3c_standby_pins: i3c-standby {
>> +		pins = "I3C_SDA", "I3C_SCL";
>> +#if SW_CONFIG4 == SW_ON
>> +		power-source = <1200>;
>> +#else
>> +		power-source = <1800>;
>> +#endif
>> +		renesas,i3c-standby = <1>;
>> +	};
> 
> That doesn't look like HW description to me because the pins are the
> same for regular and standby mode.

Yes, same pins, different states. Isn't that the role of different pinctrl 
entries in DT for the same node? E.g., for SHDI we use the same approach, same 
pins but different states. Bellow is an example from RZ/G3S but same approach is 
used for other Renesas SoCs as well:

https://elixir.bootlin.com/linux/v7.1-rc4/source/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi#L305

https://elixir.bootlin.com/linux/v7.1-rc4/source/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi#L321

> Their state is changed when powering
> down, but that should not need DT encoding, I'd think. The driver should
> know what to do, or?

Through different pinctrl states different pinctrl settings are applied in the 
pin controller HW by calling well known pinctrl APIs from the consumer drivers 
(e.g. pinctrl_pm_select_sleep_state() in case of the I3C driver as proposed in [1]).

Is there another way the I3C driver (or any pinctrl driver consumer) could apply 
pinctrl settings?

[1] https://lore.kernel.org/all/20260522101815.1722909-18-claudiu.beznea@kernel.org

-- 
Thank you,
Claudiu


^ permalink raw reply

* [PATCH] clk: canaan: k230: Fix sparse warnings reported by LKP
From: Xukai Wang @ 2026-05-22 12:59 UTC (permalink / raw)
  To: Conor Dooley, Michael Turquette, Stephen Boyd, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Conor Dooley, Xukai Wang
  Cc: linux-clk, devicetree, linux-kernel, linux-riscv, Samuel Holland,
	Troy Mitchell, Krzysztof Kozlowski, kernel test robot
In-Reply-To: <20260522-eligible-vivacious-3ce9bc30dd53@wendy>

Fix all sparse warnings detected during LKP randconfig testing:
- Replace plain integer 0 with NULL.
- Add static modifier to k230_plls and k230_pll_divs.

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202605220724.j4ZeM3KI-lkp@intel.com/
Signed-off-by: Xukai Wang <kingxukai@zohomail.com>
---
 drivers/clk/clk-k230.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/clk-k230.c b/drivers/clk/clk-k230.c
index d883a1e1118e..cfc437038e4e 100644
--- a/drivers/clk/clk-k230.c
+++ b/drivers/clk/clk-k230.c
@@ -270,12 +270,12 @@ static const struct clk_ops k230_clk_ops_mul_div = {
 	.recalc_rate	= k230_clk_get_rate_mul_div,
 };
 
-K230_CLK_PLL_FORMAT(pll0, 0, CLK_IS_CRITICAL, 0);
-K230_CLK_PLL_FORMAT(pll1, 1, CLK_IS_CRITICAL, 0);
-K230_CLK_PLL_FORMAT(pll2, 2, CLK_IS_CRITICAL, 0);
-K230_CLK_PLL_FORMAT(pll3, 3, CLK_IS_CRITICAL, 0);
+K230_CLK_PLL_FORMAT(pll0, 0, CLK_IS_CRITICAL, NULL);
+K230_CLK_PLL_FORMAT(pll1, 1, CLK_IS_CRITICAL, NULL);
+K230_CLK_PLL_FORMAT(pll2, 2, CLK_IS_CRITICAL, NULL);
+K230_CLK_PLL_FORMAT(pll3, 3, CLK_IS_CRITICAL, NULL);
 
-struct k230_pll *k230_plls[] = {
+static struct k230_pll *k230_plls[] = {
 	&pll0,
 	&pll1,
 	&pll2,
@@ -296,7 +296,7 @@ K230_CLK_FIXED_FACTOR_FORMAT(pll3_div2, 1, 2, 0, &pll3.hw);
 K230_CLK_FIXED_FACTOR_FORMAT(pll3_div3, 1, 3, 0, &pll3.hw);
 K230_CLK_FIXED_FACTOR_FORMAT(pll3_div4, 1, 4, 0, &pll3.hw);
 
-struct clk_fixed_factor *k230_pll_divs[] = {
+static struct clk_fixed_factor *k230_pll_divs[] = {
 	&pll0_div2,
 	&pll0_div3,
 	&pll0_div4,
-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH v6 1/2] dt-bindings: display: panel: document the Renesas R63419 based dual-DSI video mode Display Panels
From: sashiko-bot @ 2026-05-22 13:00 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: devicetree, conor+dt, wsa+renesas, robh
In-Reply-To: <20260522-topic-sm8650-ayaneo-pocket-s2-r63419-v6-1-16edddda9951@linaro.org>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Incorrect use of `additionalProperties: false` with a `$ref` to a common schema, causing validation failures for standard properties.
--

commit d5d9023fc9149b85c30a89eb9e658f1d3b246c85
Author: Neil Armstrong <neil.armstrong@linaro.org>

dt-bindings: display: panel: document the Renesas R63419 based dual-DSI video mode Display Panels

This commit documents the Renesas R63419 generic display driver IC used to
control dual-DSI LCD panels. It introduces a new YAML binding schema for
devices such as the Ayaneo gaming handheld panels.

> diff --git a/Documentation/devicetree/bindings/display/panel/renesas,r63419.yaml b/Documentation/devicetree/bindings/display/panel/renesas,r63419.yaml
> new file mode 100644
> index 0000000000000..adfdd2c300a35
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/panel/renesas,r63419.yaml
[ ... ]
> +allOf:
> +  - $ref: panel-common-dual.yaml#
> +
> +properties:
> +  compatible:
[ ... ]
> +  vdd-supply: true
> +  vddio-supply: true
> +  vsp-supply: true
> +  vsn-supply: true
> +  vci-supply: true
> +
> +  backlight: true
> +  reset-gpios: true
> +  rotation: true
> +  ports: true
> +
> +required:
> +  - compatible
> +  - reg
> +  - vdd-supply
> +  - vddio-supply
> +  - vsp-supply
> +  - vsn-supply
> +  - vci-supply
> +  - backlight
> +  - reset-gpios
> +  - ports
> +
> +additionalProperties: false

[Severity: Low]
Should unevaluatedProperties: false be used here instead of
additionalProperties: false?

Because this schema includes a reference to panel-common-dual.yaml in an
allOf block, additionalProperties only considers the properties explicitly
declared in this local file. This requires redundantly redeclaring standard
properties like backlight, reset-gpios, rotation, and ports to prevent
validation errors during dtbs_check.

Using unevaluatedProperties: false would properly evaluate against the
referenced schemas and allow removing the redundant property declarations.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260522-topic-sm8650-ayaneo-pocket-s2-r63419-v6-0-16edddda9951@linaro.org?part=1

^ permalink raw reply

* Re: [PATCH v3 1/8] iio: temperature: ltc2983: Fix macro parenthesization and rename
From: Jonathan Cameron @ 2026-05-22 12:56 UTC (permalink / raw)
  To: Joshua Crofts
  Cc: Liviu Stan, David Lechner, Nuno Sá, Andy Shevchenko,
	Michael Hennerich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Antoniu Miclaus, Francesco Lavra, linux-iio, linux-kernel, linux,
	devicetree
In-Reply-To: <CALoEA-xwm4bM+qp0jHu6SxcBz98y9v4jvdiJMdWWADSJBUdy=w@mail.gmail.com>

On Fri, 22 May 2026 11:11:59 +0200
Joshua Crofts <joshua.crofts1@gmail.com> wrote:

> On Thu, 21 May 2026 at 19:19, Liviu Stan <liviu.stan@analog.com> wrote:
> >
> > Wrap the 'chan' parameter in LTC2983_CHAN_START_ADDR() and
> > LTC2983_CHAN_RES_ADDR() with parentheses to prevent potential
> > macro argument expansion issues. Also rename LTC2983_CHAN_START_ADDR
> > to LTC2983_CHAN_ASSIGN_ADDR and LTC2983_CHAN_RES_ADDR to
> > LTC2983_RESULT_ADDR, to better reflect the datasheet names and avoid
> > them being confused as related.
> >
> > Signed-off-by: Liviu Stan <liviu.stan@analog.com>
> > ---  
> 
> Reviewed-by: Joshua Crofts <joshua.crofts1@gmail.com>
> 
I had a quick datasheet dive. The naming in there is rather
messy and to me seems inconsistent but these two names are indeed
used at least sometimes.  Along with conversion result start address
(which indexed by conversion channel)
(table 8).

So whilst I don't have a strong preference in favour of this rename
I guess it's fine.

Jonathan


^ permalink raw reply

* [PATCH v6 2/2] drm: panel: add support for the Renesas R63419 based dual-DSI video mode Display Panels
From: Neil Armstrong @ 2026-05-22 12:51 UTC (permalink / raw)
  To: Jessica Zhang, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven,
	Magnus Damm
  Cc: dri-devel, devicetree, linux-kernel, linux-renesas-soc,
	Dmitry Baryshkov, Neil Armstrong, KancyJoe
In-Reply-To: <20260522-topic-sm8650-ayaneo-pocket-s2-r63419-v6-0-16edddda9951@linaro.org>

From: KancyJoe <kancy2333@outlook.com>

Implement support for the Renesas 63419 based dual-DSI video mode
Display Panels found in the Ayaneo gaming handled devices.

Signed-off-by: KancyJoe <kancy2333@outlook.com>
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 drivers/gpu/drm/panel/Kconfig                |  12 +
 drivers/gpu/drm/panel/Makefile               |   1 +
 drivers/gpu/drm/panel/panel-renesas-r63419.c | 364 +++++++++++++++++++++++++++
 3 files changed, 377 insertions(+)

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 7450b27622a2..7295246cfa58 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -796,6 +796,18 @@ config DRM_PANEL_RENESAS_R61307
 	  This panel controller can be found in LG Optimus Vu P895 smartphone
 	  in combination with LCD panel.
 
+config DRM_PANEL_RENESAS_R63419
+	tristate "Renesas R63419 dual-DSI video mode panels"
+	depends on OF && GPIOLIB
+	depends on DRM_MIPI_DSI
+	depends on BACKLIGHT_CLASS_DEVICE
+	help
+	  Say Y here if you want to enable support for Ayaneo WT0600 and WT0630
+	  1440x2560 60Hz dual-DSI video mode display panels with Renesas
+	  R63419 IC.
+
+	  These panels are used in Ayaneo handheld gaming devices.
+
 config DRM_PANEL_RENESAS_R69328
 	tristate "Renesas R69328 720x1280 DSI video mode panel"
 	depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index c2c5cf817116..be9a6f3c9743 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -78,6 +78,7 @@ obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o
 obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM692E5) += panel-raydium-rm692e5.o
 obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM69380) += panel-raydium-rm69380.o
 obj-$(CONFIG_DRM_PANEL_RENESAS_R61307) += panel-renesas-r61307.o
+obj-$(CONFIG_DRM_PANEL_RENESAS_R63419) += panel-renesas-r63419.o
 obj-$(CONFIG_DRM_PANEL_RENESAS_R69328) += panel-renesas-r69328.o
 obj-$(CONFIG_DRM_PANEL_RONBO_RB070D30) += panel-ronbo-rb070d30.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_AMS581VF01) += panel-samsung-ams581vf01.o
diff --git a/drivers/gpu/drm/panel/panel-renesas-r63419.c b/drivers/gpu/drm/panel/panel-renesas-r63419.c
new file mode 100644
index 000000000000..dba156f8427c
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-renesas-r63419.c
@@ -0,0 +1,364 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * DRM driver for Renesas R63419 based dual-DSI video mode panels
+ *
+ * Copyright (c) 2025, Kancy Joe <kancy2333@outlook.com>
+ * Copyright (C) 2026 Linaro Limited
+ * Author: Neil Armstrong <neil.armstrong@linaro.org>
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_connector.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_probe_helper.h>
+
+struct renesas_r63419_panel {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi[2];
+	const struct panel_desc *desc;
+
+	struct gpio_desc *reset_gpio;
+	struct regulator_bulk_data *vdd_supplies;
+	struct regulator_bulk_data *vcc_supplies;
+	enum drm_panel_orientation orientation;
+};
+
+/* VDDIO/VDD Supplies */
+static const struct regulator_bulk_data renesas_r63419_vdd_supplies[] = {
+	{ .supply = "vddio" },
+	{ .supply = "vdd" },
+};
+
+/* VSP/VSN/VCI Supplies */
+static const struct regulator_bulk_data renesas_r63419_vcc_supplies[] = {
+	{ .supply = "vsp" },
+	{ .supply = "vsn" },
+	{ .supply = "vci" },
+};
+
+struct panel_desc {
+	const struct drm_display_mode *mode;
+	unsigned int lanes;
+	unsigned long mode_flags;
+	enum mipi_dsi_pixel_format format;
+	const struct mipi_dsi_device_info dsi_info;
+};
+
+static const struct drm_display_mode wt0600_mode = {
+	/* Dual dsi */
+	.clock = 2 * (720 + 100 + 8 + 40) * (2560 + 15 + 2 + 8) * 60 / 1000,
+	.hdisplay = 2 * 720,
+	.hsync_start = 2 * (720 + 100),
+	.hsync_end = 2 * (720 + 100 + 8),
+	.htotal = 2 * (720 + 100 + 8 + 40),
+	.vdisplay = 2560,
+	.vsync_start = 2560 + 15,
+	.vsync_end = 2560 + 15 + 2,
+	.vtotal = 2560 + 15 + 2 + 8,
+	.type = DRM_MODE_TYPE_DRIVER,
+	.width_mm = 74,
+	.height_mm = 131,
+};
+
+static const struct drm_display_mode wt0630_mode = {
+	/* Dual dsi */
+	.clock = 2 * (720 + 100 + 8 + 40) * (2560 + 15 + 2 + 8) * 60 / 1000,
+	.hdisplay = 2 * 720,
+	.hsync_start = 2 * (720 + 100),
+	.hsync_end = 2 * (720 + 100 + 8),
+	.htotal = 2 * (720 + 100 + 8 + 40),
+	.vdisplay = 2560,
+	.vsync_start = 2560 + 15,
+	.vsync_end = 2560 + 15 + 2,
+	.vtotal = 2560 + 15 + 2 + 8,
+	.type = DRM_MODE_TYPE_DRIVER,
+	.width_mm = 78,
+	.height_mm = 140,
+};
+
+static struct panel_desc wt0600_desc = {
+	.lanes = 4,
+	.mode = &wt0600_mode,
+	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+		      MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,
+	.format = MIPI_DSI_FMT_RGB888,
+};
+
+static struct panel_desc wt0630_desc = {
+	.lanes = 4,
+	.mode = &wt0630_mode,  /* wt0600 only has different screen size */
+	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+		      MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,
+	.format = MIPI_DSI_FMT_RGB888,
+};
+
+static inline struct renesas_r63419_panel *
+to_renesas_r63419_panel(struct drm_panel *panel)
+{
+	return container_of(panel, struct renesas_r63419_panel, panel);
+}
+
+/*
+ * Helper to switch between DSI links, so we share a single dsi_ctx
+ * for both links, so in case of an error all writes & sleep for
+ * both links are ignored.
+ */
+static inline void dsi_link_switch(struct renesas_r63419_panel *ctx,
+				   struct mipi_dsi_multi_context *dsi_ctx,
+				   unsigned int link)
+{
+	dsi_ctx->dsi = ctx->dsi[link];
+}
+
+static int renesas_r63419_on(struct renesas_r63419_panel *ctx)
+{
+	struct mipi_dsi_multi_context dsi_ctx = { 0 };
+
+	dsi_link_switch(ctx, &dsi_ctx, 0);
+	mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
+	dsi_link_switch(ctx, &dsi_ctx, 1);
+	mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
+	mipi_dsi_msleep(&dsi_ctx, 150);
+
+	dsi_link_switch(ctx, &dsi_ctx, 0);
+	mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
+	dsi_link_switch(ctx, &dsi_ctx, 1);
+	mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
+	mipi_dsi_msleep(&dsi_ctx, 50);
+
+	return dsi_ctx.accum_err;
+}
+
+static int renesas_r63419_disable(struct drm_panel *panel)
+{
+	struct renesas_r63419_panel *ctx = to_renesas_r63419_panel(panel);
+	struct mipi_dsi_multi_context dsi_ctx = { 0 };
+
+	dsi_link_switch(ctx, &dsi_ctx, 0);
+	mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
+	dsi_link_switch(ctx, &dsi_ctx, 1);
+	mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
+	mipi_dsi_msleep(&dsi_ctx, 50);
+
+	dsi_link_switch(ctx, &dsi_ctx, 0);
+	mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
+	dsi_link_switch(ctx, &dsi_ctx, 1);
+	mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
+	mipi_dsi_msleep(&dsi_ctx, 120);
+
+	return dsi_ctx.accum_err;
+}
+
+static int renesas_r63419_prepare(struct drm_panel *panel)
+{
+	struct renesas_r63419_panel *ctx = to_renesas_r63419_panel(panel);
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(renesas_r63419_vdd_supplies),
+				    ctx->vdd_supplies);
+	if (ret < 0)
+		return ret;
+
+	usleep_range(1000, 2000);
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(renesas_r63419_vcc_supplies),
+				    ctx->vcc_supplies);
+	if (ret < 0) {
+		regulator_bulk_disable(ARRAY_SIZE(renesas_r63419_vdd_supplies),
+				       ctx->vdd_supplies);
+		return ret;
+	}
+
+	usleep_range(1000, 2000);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+
+	usleep_range(3000, 4000);
+
+	ret = renesas_r63419_on(ctx);
+	if (ret < 0) {
+		dev_err(panel->dev, "Failed to initialize panel: %d\n", ret);
+
+		/* Power off sequence from the r63419 datasheet */
+		regulator_bulk_disable(ARRAY_SIZE(renesas_r63419_vcc_supplies),
+				       ctx->vcc_supplies);
+		regulator_bulk_disable(ARRAY_SIZE(renesas_r63419_vdd_supplies),
+				       ctx->vdd_supplies);
+
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+
+		return ret;
+	}
+
+	return 0;
+}
+
+static int renesas_r63419_unprepare(struct drm_panel *panel)
+{
+	struct renesas_r63419_panel *ctx = to_renesas_r63419_panel(panel);
+
+	/* Power off sequence from the r63419 datasheet */
+	regulator_bulk_disable(ARRAY_SIZE(renesas_r63419_vcc_supplies), ctx->vcc_supplies);
+	regulator_bulk_disable(ARRAY_SIZE(renesas_r63419_vdd_supplies), ctx->vdd_supplies);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+
+	return 0;
+}
+
+static int renesas_r63419_get_modes(struct drm_panel *panel,
+				    struct drm_connector *connector)
+{
+	struct renesas_r63419_panel *ctx = to_renesas_r63419_panel(panel);
+	const struct drm_display_mode *mode = ctx->desc->mode;
+
+	drm_connector_set_panel_orientation(connector, ctx->orientation);
+
+	return drm_connector_helper_get_modes_fixed(connector, mode);
+}
+
+static enum drm_panel_orientation
+renesas_r63419_get_orientation(struct drm_panel *panel)
+{
+	struct renesas_r63419_panel *ctx = to_renesas_r63419_panel(panel);
+
+	return ctx->orientation;
+}
+
+static const struct drm_panel_funcs renesas_r63419_panel_funcs = {
+	.disable = renesas_r63419_disable,
+	.prepare = renesas_r63419_prepare,
+	.unprepare = renesas_r63419_unprepare,
+	.get_modes = renesas_r63419_get_modes,
+	.get_orientation = renesas_r63419_get_orientation,
+};
+
+static int renesas_r63419_probe(struct mipi_dsi_device *dsi)
+{
+	struct mipi_dsi_device_info info = { };
+	struct device *dev = &dsi->dev;
+	struct renesas_r63419_panel *ctx;
+	struct device_node *dsi1_node;
+	struct mipi_dsi_host *dsi1_host;
+	int ret, i;
+
+	ctx = devm_drm_panel_alloc(dev, struct renesas_r63419_panel, panel,
+				   &renesas_r63419_panel_funcs, DRM_MODE_CONNECTOR_DSI);
+	if (IS_ERR(ctx))
+		return PTR_ERR(ctx);
+
+	ctx->desc = of_device_get_match_data(dev);
+	if (!ctx->desc)
+		return dev_err_probe(dev, -ENODEV,
+				     "Failed to get panel description\n");
+
+	ret = devm_regulator_bulk_get_const(&dsi->dev,
+					    ARRAY_SIZE(renesas_r63419_vdd_supplies),
+					    renesas_r63419_vdd_supplies, &ctx->vdd_supplies);
+	if (ret < 0)
+		return ret;
+
+	ret = devm_regulator_bulk_get_const(&dsi->dev,
+					    ARRAY_SIZE(renesas_r63419_vcc_supplies),
+					    renesas_r63419_vcc_supplies, &ctx->vcc_supplies);
+	if (ret < 0)
+		return ret;
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset gpio\n");
+
+	/* Get second DSI host */
+	dsi1_node = of_graph_get_remote_node(dsi->dev.of_node, 1, -1);
+	if (!dsi1_node)
+		return dev_err_probe(dev, -ENODEV,
+				     "Failed to get remote node for second DSI\n");
+
+	dsi1_host = of_find_mipi_dsi_host_by_node(dsi1_node);
+	of_node_put(dsi1_node);
+	if (!dsi1_host)
+		return dev_err_probe(dev, -EPROBE_DEFER,
+				     "Failed to find second DSI host\n");
+
+	/* Copy current DSI info, do not provide OF node since no driver needs to be attached */
+	strscpy(info.type, dsi->name, sizeof(info.type));
+	info.channel = dsi->channel;
+
+	/* Register the second DSI device */
+	ctx->dsi[1] = devm_mipi_dsi_device_register_full(dev, dsi1_host, &info);
+	if (IS_ERR(ctx->dsi[1]))
+		return dev_err_probe(dev, PTR_ERR(ctx->dsi[1]),
+				     "Failed to register second DSI device\n");
+
+	ctx->dsi[0] = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	/* Get panel orientation */
+	ret = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation);
+	if (ret < 0 && ret != -ENODEV)
+		return dev_err_probe(dev, ret,
+				     "Failed to get panel orientation\n");
+
+	ctx->panel.prepare_prev_first = true;
+
+	ret = drm_panel_of_backlight(&ctx->panel);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+	ret = devm_drm_panel_add(dev, &ctx->panel);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to add panel\n");
+
+	/* Configure and attach both DSI devices */
+	for (i = 0; i < ARRAY_SIZE(ctx->dsi); i++) {
+		ctx->dsi[i]->lanes = ctx->desc->lanes;
+		ctx->dsi[i]->format = ctx->desc->format;
+		ctx->dsi[i]->mode_flags = ctx->desc->mode_flags;
+
+		ret = devm_mipi_dsi_attach(dev, ctx->dsi[i]);
+		if (ret < 0)
+			return dev_err_probe(dev, ret,
+					     "Failed to attach DSI device %d\n", i);
+	}
+
+	return 0;
+}
+
+static const struct of_device_id renesas_r63419_of_match[] = {
+	{
+		.compatible = "ayaneo,wt0600-2k",
+		.data = &wt0600_desc,
+	},
+	{
+		.compatible = "ayaneo,wt0630-2k",
+		.data = &wt0630_desc,
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, renesas_r63419_of_match);
+
+static struct mipi_dsi_driver renesas_r63419_driver = {
+	.probe = renesas_r63419_probe,
+	.driver = {
+		.name = "panel-renesas-r63419",
+		.of_match_table = renesas_r63419_of_match,
+	},
+};
+module_mipi_dsi_driver(renesas_r63419_driver);
+
+MODULE_AUTHOR("Kancy Joe <kancy2333@outlook.com>");
+MODULE_AUTHOR("Neil Armstrong <neil.armstrong@linaro.org>");
+MODULE_DESCRIPTION("DRM driver for Renesas R63419 based dual-DSI video mode panels");
+MODULE_LICENSE("GPL");

-- 
2.34.1


^ permalink raw reply related

* [PATCH v6 1/2] dt-bindings: display: panel: document the Renesas R63419 based dual-DSI video mode Display Panels
From: Neil Armstrong @ 2026-05-22 12:51 UTC (permalink / raw)
  To: Jessica Zhang, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven,
	Magnus Damm
  Cc: dri-devel, devicetree, linux-kernel, linux-renesas-soc,
	Dmitry Baryshkov, Neil Armstrong, Conor Dooley
In-Reply-To: <20260522-topic-sm8650-ayaneo-pocket-s2-r63419-v6-0-16edddda9951@linaro.org>

Document the Renesas R63419 based dual-DSI video mode Display Panels found
in the Ayaneo gaming handled devices.

Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 .../bindings/display/panel/renesas,r63419.yaml     | 98 ++++++++++++++++++++++
 1 file changed, 98 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/panel/renesas,r63419.yaml b/Documentation/devicetree/bindings/display/panel/renesas,r63419.yaml
new file mode 100644
index 000000000000..adfdd2c300a3
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/renesas,r63419.yaml
@@ -0,0 +1,98 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/renesas,r63419.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas R63419 based dual-DSI video mode Display Panel
+
+maintainers:
+  - Neil Armstrong <neil.armstrong@linaro.org>
+
+description:
+  The Renesas R63419 is a generic DDIC used to control dual-DSI LCD panels.
+
+allOf:
+  - $ref: panel-common-dual.yaml#
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - ayaneo,wt0600-2k
+          - ayaneo,wt0630-2k
+      - const: renesas,r63419
+
+  reg:
+    maxItems: 1
+
+  vdd-supply: true
+  vddio-supply: true
+  vsp-supply: true
+  vsn-supply: true
+  vci-supply: true
+
+  backlight: true
+  reset-gpios: true
+  rotation: true
+  ports: true
+
+required:
+  - compatible
+  - reg
+  - vdd-supply
+  - vddio-supply
+  - vsp-supply
+  - vsn-supply
+  - vci-supply
+  - backlight
+  - reset-gpios
+  - ports
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    dsi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        panel@0 {
+            compatible = "ayaneo,wt0600-2k", "renesas,r63419";
+            reg = <0>;
+
+            reset-gpios = <&gpio 176 GPIO_ACTIVE_LOW>;
+
+            vdd-supply = <&vdd_3v0_lcd>;
+            vddio-supply = <&vdd_1v8_io>;
+            vsn-supply = <&vdd_5v0_neg>;
+            vsp-supply = <&vdd_5v0_pos>;
+            vci-supply = <&vdd_3v0_vci>;
+
+            backlight = <&backlight>;
+
+            rotation = <90>;
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port@0 {
+                    reg = <0>;
+                    panel_in0: endpoint {
+                        remote-endpoint = <&dsi0_out>;
+                    };
+                };
+
+                port@1 {
+                    reg = <1>;
+                    panel_in1: endpoint {
+                        remote-endpoint = <&dsi1_out>;
+                    };
+                };
+            };
+        };
+    };
+...

-- 
2.34.1


^ permalink raw reply related

* [PATCH v6 0/2] drm: panel: support the R63419 based dual-DSI video mode Display Panels
From: Neil Armstrong @ 2026-05-22 12:51 UTC (permalink / raw)
  To: Jessica Zhang, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven,
	Magnus Damm
  Cc: dri-devel, devicetree, linux-kernel, linux-renesas-soc,
	Dmitry Baryshkov, Neil Armstrong, Conor Dooley, KancyJoe

Add support for the Renesas 63419 based dual-DSI video mode
Display Panels found in the Ayaneo gaming handled devices.

Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
Changes in v6:
- Get new dt bindings review from Conor
- Properly init dsi_ctx
- Link to v5: https://patch.msgid.link/20260521-topic-sm8650-ayaneo-pocket-s2-r63419-v5-0-dd5700299390@linaro.org

Changes in v5:
- Import panel-common-dual.yaml in bindings
- Set reg as required
- fix bindings example typo
- Add helper to switch link in order to use single dsi_ctx to properly handle errors
- Disable vdd supplies if vcc supplied fail to enable
- Precise the power off sequence is recommended by the vendor spec
- Drop passing of node to second dsi to avoid re-probing the driver twice
- Link to v4: https://patch.msgid.link/20260519-topic-sm8650-ayaneo-pocket-s2-r63419-v4-0-b8929af5e951@linaro.org

Changes in v4:
- Moved height/width in the drm_mode, duplicated modes to use drm_connector_helper_get_modes_fixed
- Create dsi_info on the stack with proper OF node and name passed
- Switched to devm_drm_panel_add/devm_mipi_dsi_attach & dropped remove
- Link to v3: https://patch.msgid.link/20260504-topic-sm8650-ayaneo-pocket-s2-r63419-v3-0-9f61cf24aebf@linaro.org

Changes in v3:
- Added DDIC compatible as fallback
- Added rotation in bindings example
- Fixed bindings subject
- Added second MODULE_AUTHOR entry and re-ordered signed-off-by order
- Link to v2: https://patch.msgid.link/20260430-topic-sm8650-ayaneo-pocket-s2-r63419-v2-0-91ac10453d0c@linaro.org

Changes in v2:
- Add missing rotation property into bindings
- Fix commit message & subject typos
- Link to v1: https://patch.msgid.link/20260428-topic-sm8650-ayaneo-pocket-s2-r63419-v1-0-981eb5ab5a51@linaro.org

---
KancyJoe (1):
      drm: panel: add support for the Renesas R63419 based dual-DSI video mode Display Panels

Neil Armstrong (1):
      dt-bindings: display: panel: document the Renesas R63419 based dual-DSI video mode Display Panels

 .../bindings/display/panel/renesas,r63419.yaml     |  98 ++++++
 drivers/gpu/drm/panel/Kconfig                      |  12 +
 drivers/gpu/drm/panel/Makefile                     |   1 +
 drivers/gpu/drm/panel/panel-renesas-r63419.c       | 364 +++++++++++++++++++++
 4 files changed, 475 insertions(+)
---
base-commit: e98d21c170b01ddef366f023bbfcf6b31509fa83
change-id: 20260428-topic-sm8650-ayaneo-pocket-s2-r63419-e72467e2db0f

Best regards,
--  
Neil Armstrong <neil.armstrong@linaro.org>


^ permalink raw reply

* Re: [PATCH 5/5] arm64: dts: freescale: add DT overlay for MX95-15x15-FRDM RPMSG usage
From: sashiko-bot @ 2026-05-22 12:48 UTC (permalink / raw)
  To: Laurentiu Mihalcea; +Cc: conor+dt, Frank.Li, robh, imx, devicetree
In-Reply-To: <20260522111849.783-6-laurentiumihalcea111@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The `dma-channel-mask` property is incorrectly defined as a mask of unavailable (reserved) channels rather than available channels, violating standard DT binding semantics by relying on a buggy driver implementation.
--

commit cbf89994f08b1b68af6ef4fcaffd7d5ceac2c8f0
Author: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>

arm64: dts: freescale: add DT overlay for MX95-15x15-FRDM RPMSG usage

This commit adds an RPMSG device tree overlay for the MX95-15x15-FRDM board.
It configures reserved memory regions for vdev vrings and buffers, and
updates the cm7, edma, and micfil nodes to support remoteproc and audio
use cases.

> diff --git a/arch/arm64/boot/dts/freescale/imx95-15x15-frdm-rpmsg.dtso b/arch/arm64/boot/dts/freescale/imx95-15x15-frdm-rpmsg.dtso
> new file mode 100644
> index 0000000000000..b39444dde66e0
> --- /dev/null
> +++ b/arch/arm64/boot/dts/freescale/imx95-15x15-frdm-rpmsg.dtso

[ ... ]

> +&edma1 {
> +	/* reserved for M7 */
> +	dma-channel-mask = <0x40>;
> +};
> +
> +&edma2 {
> +	/* reserved for M7 and V2X */
> +	dma-channel-mask = <0xf>;
> +};

[Severity: Medium]
Is this property defining available or reserved channels?

The standard device tree binding in dma-common.yaml explicitly defines
dma-channel-mask as a bitmask of available DMA channels that are not reserved
by firmware. However, the comments here indicate the mask is being used to
define reserved channels.

While there appears to be an existing bug in the fsl-edma driver where it
interprets this property as unavailable channels, encoding a driver bug into
the hardware description breaks the device tree ABI and will cause issues
if the driver is ever corrected.

Could this be updated to correctly reflect available channels according to the
standard binding?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260522111849.783-1-laurentiumihalcea111@gmail.com?part=5

^ permalink raw reply

* [PATCH RFC] arm64: dts: qcom: qcm6490-fairphone-fp5: Add AW88261 amplifiers
From: Luca Weiss @ 2026-05-22 12:39 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Val Packett, Bharadwaj Raju, Bhushan Shah
  Cc: ~postmarketos/upstreaming, phone-devel, linux-arm-msm, devicetree,
	linux-kernel, Luca Weiss

Add nodes for the two AW88261 amplifiers, for the top and bottom
speakers of this phone. Hook them up to the sound card.

Co-developed-by: Bharadwaj Raju <bharadwaj.raju@machinesoul.in>
Signed-off-by: Bharadwaj Raju <bharadwaj.raju@machinesoul.in>
Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
---
RFC because the AW88261 patches aren't merged yet
---
 arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts | 59 +++++++++++++++++++++-
 1 file changed, 57 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts
index 04cb9230d29f..b1f489a9f449 100644
--- a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts
+++ b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts
@@ -866,8 +866,35 @@ vibrator@5a {
 &i2c2 {
 	status = "okay";
 
-	/* AW88261FCR amplifier @ 34 */
-	/* AW88261FCR amplifier @ 35 */
+	/* Top speaker / ear speaker */
+	aw88261_l: audio-codec@34 {
+		compatible = "awinic,aw88261";
+		reg = <0x34>;
+
+		dvdd-supply = <&vreg_l18b>;
+		sound-name-prefix = "Amplifier L";
+		firmware-name = "qcom/qcm6490/fairphone5/aw88261_acf.bin";
+
+		awinic,audio-channel = <0>;
+		awinic,sync-flag;
+
+		#sound-dai-cells = <0>;
+	};
+
+	/* Bottom speaker */
+	aw88261_r: audio-codec@35 {
+		compatible = "awinic,aw88261";
+		reg = <0x35>;
+
+		dvdd-supply = <&vreg_l18b>;
+		sound-name-prefix = "Amplifier R";
+		firmware-name = "qcom/qcm6490/fairphone5/aw88261_acf.bin";
+
+		awinic,audio-channel = <1>;
+		awinic,sync-flag;
+
+		#sound-dai-cells = <0>;
+	};
 };
 
 &i2c4 {
@@ -1161,6 +1188,13 @@ &pon_resin {
 	status = "okay";
 };
 
+&q6afedai {
+	dai@127 {
+		reg = <QUINARY_MI2S_RX>;
+		qcom,sd-lines = <0>;
+	};
+};
+
 &qup_spi13_cs {
 	drive-strength = <6>;
 	bias-disable;
@@ -1238,6 +1272,11 @@ &sound {
 	compatible = "fairphone,fp5-sndcard";
 	model = "Fairphone 5";
 
+	pinctrl-0 = <&lpass_i2s1_active>;
+	pinctrl-1 = <&lpass_i2s1_sleep>;
+	pinctrl-names = "default",
+			"sleep";
+
 	mm1-dai-link {
 		link-name = "MultiMedia1";
 
@@ -1246,6 +1285,22 @@ cpu {
 		};
 	};
 
+	i2s-dai-link {
+		link-name = "Quinary MI2S Playback";
+
+		codec {
+			sound-dai = <&aw88261_l>, <&aw88261_r>;
+		};
+
+		cpu {
+			sound-dai = <&q6afedai QUINARY_MI2S_RX>;
+		};
+
+		platform {
+			sound-dai = <&q6routing>;
+		};
+	};
+
 	displayport-rx-dai-link {
 		link-name = "DisplayPort Playback";
 

---
base-commit: 1e45adb287ae5d431afc9900b4d387f4e73d9406
change-id: 20260522-fp5-aw88261-a02bb0e4b697
prerequisite-message-id: <20260518220906.347958-1-val@packett.cool>
prerequisite-patch-id: cf63e24b374691738276d00e569ffa2d8b94ed72
prerequisite-patch-id: 9a075067099bfdbf52eabfe3f7121909955c8726
prerequisite-patch-id: 5453ac079d39ea13d849f880f9dde4b0a2192b91
prerequisite-patch-id: 3768d28b288dbb7d3245dc0de3a289303c3e45fd
prerequisite-patch-id: d84da7eec6f3755985ba55676a3bc893b89f002b
prerequisite-patch-id: ea19cd4cd8cc8519786c6f05cf4e35ccadd70839
prerequisite-patch-id: 6847a49b36dd8bd4cbb422b6a2b269faaca6c873

Best regards,
--  
Luca Weiss <luca.weiss@fairphone.com>


^ permalink raw reply related

* Re: [PATCH v4 5/5] drm/panel: Add driver for Synaptics R63455 DSI panel
From: Neil Armstrong @ 2026-05-22 12:40 UTC (permalink / raw)
  To: sashiko-reviews, Jun Nie; +Cc: robh, conor+dt, devicetree
In-Reply-To: <20260521163039.30D3A1F000E9@smtp.kernel.org>

On 5/21/26 18:30, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 10 potential issue(s) to consider:
> - [High] Incorrect order of error unwinding labels in `r63455_prepare` causes resource leaks and unbalanced regulator operations.
> - [High] The secondary DSI device registered during probe is never unregistered, causing a memory and device leak.
> - [High] Endianness extraction macros misuse host-endian functions, resulting in reversed byte order on Big Endian architectures.
> - [High] Unconditional access to `ctx->reset_gpios->desc[1]` leads to an out-of-bounds array read if only one reset GPIO is provided.
> - [High] Failure of `drm_dsc_setup_rc_params` is logged but ignored, leading to division by zero and uninitialized data usage.
> - [High] Backlight updates send DSI commands after the panel has entered sleep mode, risking hardware timeouts.
> - [High] Premature publication of backlight and panel interfaces leads to use-before-initialization races.
> - [High] Unprotected concurrent read-modify-write on `mode_flags` causes data races.
> - [High] Unaligned pointer cast causes unaligned memory access when packing DSC PPS payload.
> - [Low] Missing Kconfig dependencies for DRM DSC helpers causes build failures.
> --
> 
> commit b5b6e09241eeff17cb03a31aac27b70f4e5ca911
> Author: Jun Nie <jun.nie@linaro.org>
> Subject: drm/panel: Add driver for Synaptics R63455 DSI panel
> 
> This commit adds support for the DSI panels used in the virtual reality
> device. The device features two physical panels, each providing a MIPI DSI
> interface and a built-in LED backlight, and exposes a single logical panel
> to the DRM framework.
> 
>> diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
>> --- a/drivers/gpu/drm/panel/Kconfig
>> +++ b/drivers/gpu/drm/panel/Kconfig
> [ ... ]
>> @@ -1185,6 +1185,15 @@ config DRM_PANEL_SYNAPTICS_TDDI
>>   	  namesake, with varying resolutions and data lanes. They also have a
>>   	  built-in LED backlight and a touch controller.
>>   
>> +config DRM_PANEL_SYNAPTICS_R63455
>> +	tristate "Synaptics R63455-based panels"
>> +	depends on OF
>> +	depends on DRM_MIPI_DSI
>> +	depends on BACKLIGHT_CLASS_DEVICE
>> +	help
>> +	  Say Y if you want to enable support for panels based on the
>> +	  Synaptics R63455 controller.
> 
> [Severity: Low]
> Does this need to select DRM_DISPLAY_DSC_HELPER or DRM_DISPLAY_HELPER?
> The driver calls drm_dsc_set_const_params and other DSC helpers, which
> might cause link-time failures if the helper infrastructure is not built.

Yes

> 
> [ ... ]
>> diff --git a/drivers/gpu/drm/panel/panel-synaptics-r63455.c b/drivers/gpu/drm/panel/panel-synaptics-r63455.c
>> --- /dev/null
>> +++ b/drivers/gpu/drm/panel/panel-synaptics-r63455.c
> [ ... ]
>> +#define r63455_dsi_write_buffer(ctx, dsi_ctx, d)					\
>> +	do {										\
>> +		dsi_ctx.dsi = ctx->dsi[0];						\
>> +		mipi_dsi_dcs_write_buffer_multi(&dsi_ctx, d, ARRAY_SIZE(d));		\
>> +		dsi_ctx.dsi = ctx->dsi[1];						\
>> +		mipi_dsi_dcs_write_buffer_multi(&dsi_ctx, d, ARRAY_SIZE(d));		\
>> +	} while (0)
>> +
>> +#define LE16_BYTE0(val) (le16_to_cpu(val) & 0xff)
>> +#define LE16_BYTE1(val) ((le16_to_cpu(val) >> 8) & 0xff)
> 
> [Severity: High]
> Are these macros extracting the correct bytes on big endian architectures?
> Using le16_to_cpu() on a native integer constant swaps the bytes on big
> endian systems. Applying the bitwise operations afterward will extract the
> most significant byte instead of the least significant byte. Would standard
> bitwise shifts be safer here?

No we extract the low byte and high byte of the 16bit number converted to the cpu endianness,
so it's the right code here.

> 
> [ ... ]
>> +static int r63455_dsi_populate_dsc_params(struct r63455_ctx *ctx)
>> +{
>> +	int ret;
>> +	struct drm_dsc_config *dsc = &ctx->dsc_cfg;
> [ ... ]
>> +	/* handle only bpp = bpc = 8, pre-SCR panels */
>> +	ret = drm_dsc_setup_rc_params(dsc, DRM_DSC_1_1_PRE_SCR);
>> +	if (ret < 0)
>> +		DRM_DEV_ERROR(ctx->dev, "failed to setup dsc params\n");
>> +
>> +	dsc->initial_scale_value = drm_dsc_initial_scale_value(dsc);
> 
> [Severity: High]
> Should this return early if drm_dsc_setup_rc_params() fails? If execution
> continues, the driver will use uninitialized DSC configuration parameters.
> Because values like initial_xmit_delay might remain zero, it can result in
> a division by zero when calculating final_scale inside
> drm_dsc_compute_rc_parameters().

Good catch

> 
>> +	dsc->line_buf_depth = dsc->bits_per_component + 1;
>> +
>> +	return drm_dsc_compute_rc_parameters(dsc);
>> +}
> [ ... ]
>> +static int r63455_panel_on_sharp_ls026b3sa06(struct drm_panel *panel)
>> +{
>> +	struct r63455_ctx *ctx = panel_to_ctx(panel);
>> +	struct mipi_dsi_multi_context dsi_ctx = { 0 };
>> +
>> +	u8 pps_cmd[1 + sizeof(struct drm_dsc_picture_parameter_set)];
>> +
>> +	drm_dsc_pps_payload_pack((void *)&pps_cmd[1], &ctx->dsc_cfg);
> 
> [Severity: High]
> Can this unaligned pointer cause alignment faults? Passing &pps_cmd[1] forces
> the base address to be odd. Since drm_dsc_pps_payload_pack() treats the
> pointer as a struct and performs 16-bit stores to its fields, this might
> trigger alignment panics on architectures that strictly enforce memory
> alignment.

Yep, best would be to work on a struct drm_dsc_picture_parameter_set on the stack
and copy it to pps_cmd[1].

> 
> [ ... ]
>> +static int r63455_set_brightness(struct r63455_ctx *ctx, u16 brightness,
>> +				  u16 pulse_offset_rows)
>> +{
>> +	struct mipi_dsi_multi_context dsi_ctx = { 0 };
>> +	u16 gpo1_tew1;
>> +
>> +	gpo1_tew1 = brightness > BRIGHTNESS_MAX_120 ?
>> +		    BRIGHTNESS_MAX_120 : brightness;
>> +
>> +	ctx->dsi[0]->mode_flags &= ~MIPI_DSI_MODE_LPM;
> 
> [Severity: High]
> Can this read-modify-write of mode_flags race with the similar modifications
> in r63455_enable() and r63455_disable()? Because set_brightness() is called
> from sysfs context and enable/disable from DRM commit context, concurrent
> access might corrupt mode_flags and drop critical settings like
> MIPI_DSI_MODE_VIDEO.

It's very improbable this happens, panel cmds and backlight are called at very different times.

> 
>> +	ctx->dsi[1]->mode_flags &= ~MIPI_DSI_MODE_LPM;
> [ ... ]
>> +static int r63455_disable(struct drm_panel *panel)
>> +{
>> +	struct r63455_ctx *ctx = panel_to_ctx(panel);
>> +	struct mipi_dsi_multi_context dsi_ctx = { 0 };
>> +
>> +	ctx->dsi[0]->mode_flags &= ~MIPI_DSI_MODE_LPM;
>> +	ctx->dsi[1]->mode_flags &= ~MIPI_DSI_MODE_LPM;
>> +
>> +	r63455_dsi_write_seq(ctx, dsi_ctx, MIPI_DCS_SET_DISPLAY_OFF);
>> +	r63455_dsi_write_seq(ctx, dsi_ctx, MIPI_DCS_SET_TEAR_OFF);
>> +	r63455_dsi_write_seq(ctx, dsi_ctx, MIPI_DCS_ENTER_SLEEP_MODE);
>> +
>> +	mipi_dsi_msleep(&dsi_ctx, 200);
>> +
>> +	if (dsi_ctx.accum_err)
>> +		return dsi_ctx.accum_err;
>> +
>> +	return backlight_disable(ctx->backlight);
> 
> [Severity: High]
> Is it safe to disable the backlight here? The backlight_disable() function
> calls r63455_set_brightness(), which will send DSI configuration commands to
> the panel. Doing so after sending MIPI_DCS_ENTER_SLEEP_MODE violates the DSI
> hardware contracts and might cause bus timeouts or hardware crashes.

It's required by the hw spec.

> 
>> +}
>> +
>> +static int r63455_unprepare(struct drm_panel *panel)
>> +{
>> +	struct r63455_ctx *ctx = panel_to_ctx(panel);
>> +	int ret;
>> +
>> +	gpiod_set_value(ctx->reset_gpios->desc[0], 0);
>> +	gpiod_set_value(ctx->reset_gpios->desc[1], 0);
> 
> [Severity: High]
> What happens if the device tree only provides a single reset GPIO? If ndescs
> is 1, accessing desc[1] will read past the end of the flexible array,
> resulting in a garbage pointer dereference.

Won't happen, both are mandatory

> 
> [ ... ]
>> +static int r63455_prepare(struct drm_panel *panel)
>> +{
>> +	struct r63455_ctx *ctx = panel_to_ctx(panel);
>> +	int ret;
> [ ... ]
>> +	msleep(20);
>> +	gpiod_set_value(ctx->reset_gpios->desc[0], 1);
>> +	gpiod_set_value(ctx->reset_gpios->desc[1], 1);
>> +
>> +	return 0;
>> +
>> +bl_off:
>> +	regulator_bulk_disable(ARRAY_SIZE(ctx->reg_bl), ctx->reg_bl);
>> +vdda_off:
>> +	regulator_bulk_disable(ARRAY_SIZE(ctx->reg_vdda), ctx->reg_vdda);
>> +bias_off:
>> +	regulator_bulk_disable(ARRAY_SIZE(ctx->reg_lcd_bias_pos),
>> +			       ctx->reg_lcd_bias_pos);
>> +	return ret;
> 
> [Severity: High]
> Are these error labels in the correct order? They appear to fall through
> sequentially rather than unwinding in reverse. If reg_vdda fails to enable,
> the jump to bl_off will disable the backlight, but then incorrectly fall
> through to vdda_off and bias_off. This causes regulators that were never
> enabled to be disabled, and completely skips disabling regulators that were
> actually enabled.


Jun, please check the order

> 
>> +}
> [ ... ]
>> +static int r63455_probe(struct mipi_dsi_device *dsi)
>> +{
>> +	struct device *dev = &dsi->dev;
>> +	struct r63455_ctx *ctx;
>> +	struct mipi_dsi_device *dsi1_device;
> [ ... ]
>> +	dsi1_host = of_find_mipi_dsi_host_by_node(dsi1);
>> +	of_node_put(dsi1);
>> +	if (!dsi1_host) {
>> +		DRM_DEV_ERROR(dev, "failed to find secondary dsi host\n");
>> +		return -EPROBE_DEFER;
>> +	}
>> +
>> +	dsi1_device = mipi_dsi_device_register_full(dsi1_host, &info);
> 
> [Severity: High]
> Does this dynamically allocated dsi1_device need to be unregistered? There
> is no call to mipi_dsi_device_unregister() in the error paths below or in a
> remove callback for the driver, which could cause a permanent device and
> memory leak when the module is unloaded or fails to probe.

Good catchm, should be devm_mipi_dsi_device_register_full()

> 
>> +	if (IS_ERR(dsi1_device)) {
>> +		DRM_DEV_ERROR(dev, "failed to create dsi device\n");
>> +		return PTR_ERR(dsi1_device);
>> +	}
> [ ... ]
>> +	ret = r63455_panel_add(ctx);
>> +	if (ret) {
>> +		DRM_DEV_ERROR(dev, "failed to add panel %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	for (i = 0; i < 2; i++) {
>> +		dsi_dev = ctx->dsi[i];
>> +		dsi_dev->lanes = 3;
>> +		dsi_dev->format = MIPI_DSI_FMT_RGB888;
>> +		dsi_dev->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM |
>> +			MIPI_DSI_CLOCK_NON_CONTINUOUS;
>> +		ret = devm_mipi_dsi_attach(dev, dsi_dev);
> 
> [Severity: High]
> Does calling r63455_panel_add() before devm_mipi_dsi_attach() expose the
> backlight sysfs interface too early? If userspace writes to the brightness
> node before the DSI lanes and formats are configured and attached, it could
> trigger a DSI transfer on an unattached device and crash the system.

No

> 
>> +		if (ret < 0) {
>> +			DRM_DEV_ERROR(dev, "dsi attach failed i = %d\n", i);
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
> 


^ 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