Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH 4/5] hwmon: add Stratix 10 SoC FPGA hardware monitor driver
From: Krzysztof Kozlowski @ 2026-06-22 14:08 UTC (permalink / raw)
  To: tze.yee.ng
  Cc: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-hwmon, devicetree, linux-kernel, Dinh Nguyen, Mahesh Rao,
	Jonathan Corbet, Shuah Khan, linux-doc
In-Reply-To: <081650bc4d92e9497b7a5a926e79a067cca3519f.1781861409.git.tze.yee.ng@altera.com>

On Fri, Jun 19, 2026 at 02:38:55AM -0700, tze.yee.ng@altera.com wrote:
> +	dev_warn(dev, "unsupported sensor type %s\n", type);
> +	return 0;
> +}
> +
> +static int stratix10_hwmon_probe_child_from_dt(struct device *dev,
> +					       struct device_node *child,

np

> +					      struct stratix10_hwmon_priv *priv)
> +{
> +	struct device_node *grandchild;

child

> +	const char *label;
> +	u32 val;
> +	int ret;
> +
> +	for_each_child_of_node(child, grandchild) {

child

> +		ret = of_property_read_u32(grandchild, "reg", &val);
> +		if (ret) {
> +			dev_err(dev, "missing reg property of %pOFn\n",
> +				grandchild);
> +			of_node_put(grandchild);
> +			return ret;
> +		}
> +
> +		ret = of_property_read_string(grandchild, "label", &label);
> +		if (ret)
> +			label = grandchild->name;
> +
> +		stratix10_hwmon_add_channel(dev, child->name, val, label, priv);
> +	}
> +
> +	return 0;
> +}
> +
> +static int stratix10_hwmon_probe_from_dt(struct device *dev,
> +					 struct stratix10_hwmon_priv *priv)
> +{
> +	struct device_node *child;
> +	int ret;
> +
> +	if (!dev->of_node)
> +		return 0;
> +
> +	for_each_child_of_node(dev->of_node, child) {

Just use scoped. And why not available child node? Why do you probe
disabled channels?

> +		ret = stratix10_hwmon_probe_child_from_dt(dev, child, priv);
> +		if (ret) {
> +			of_node_put(child);
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int stratix10_hwmon_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct stratix10_hwmon_priv *priv;
> +	struct device *hwmon_dev;
> +	int ret;
> +
> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->client.dev = dev;
> +	priv->client.priv = priv;
> +	init_completion(&priv->completion);
> +	mutex_init(&priv->lock);
> +
> +	ret = stratix10_hwmon_probe_from_dt(dev, priv);
> +	if (ret) {
> +		dev_err(dev, "Unable to probe from device tree\n");
> +		return ret;
> +	}
> +
> +	if (!priv->temperature_channels && !priv->voltage_channels) {
> +		dev_err(dev, "no temperature or voltage channels in device tree\n");
> +		return -ENODEV;
> +	}
> +
> +	priv->chan = stratix10_svc_request_channel_byname(&priv->client,
> +							  SVC_CLIENT_HWMON);
> +	if (IS_ERR(priv->chan)) {
> +		ret = PTR_ERR(priv->chan);
> +		if (ret == -EPROBE_DEFER)
> +			dev_dbg(dev, "service channel %s not ready, deferring probe\n",
> +				SVC_CLIENT_HWMON);
> +		else
> +			dev_err(dev, "couldn't get service channel %s: %d\n",
> +				SVC_CLIENT_HWMON, ret);
> +		return ret;
> +	}
> +
> +	ret = stratix10_svc_add_async_client(priv->chan, false);
> +	switch (ret) {
> +	case 0:
> +		priv->async = true;
> +		break;
> +	case -EINVAL:
> +		dev_dbg(dev, "async operations not supported, using sync mode\n");
> +		priv->async = false;
> +		break;
> +	default:
> +		dev_err(dev, "failed to add async client: %d\n", ret);
> +		stratix10_svc_free_channel(priv->chan);
> +		return ret;
> +	}
> +
> +	dev_info(dev, "Initialized %d temperature and %d voltage channels\n",
> +		 priv->temperature_channels, priv->voltage_channels);

Drop, driver should be silent on success. dev_dbg might be fine, but
honestly that's static information from DT so zero usefulness.

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH 0/6] Additional regulator support for the Qualcomm SGMII SerDes PHY
From: Loic Poulain @ 2026-06-22 14:08 UTC (permalink / raw)
  To: Mohd Ayaan Anwar
  Cc: Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Bartosz Golaszewski,
	Bjorn Andersson, Konrad Dybcio, Wasim Nazir, Mohd Ayaan Anwar,
	Yijie Yang, linux-arm-msm, linux-phy, devicetree, linux-kernel,
	Konrad Dybcio
In-Reply-To: <20251124-sgmiieth_serdes_regulator-v1-0-73ae8f9cbe2a@oss.qualcomm.com>

Hi,

On Mon, Nov 24, 2025 at 10:26 AM Mohd Ayaan Anwar
<mohd.anwar@oss.qualcomm.com> wrote:
>
> This patch series addresses a SerDes power-up failure observed on the
> QCS8300 Ride board using the phy-qcom-sgmii-eth driver. The issue occurs
> because the SerDes PHY requires both L5A and L4A regulators to be
> enabled during initialization. If either one of them is disabled, the
> status register does not reset, and the Ethernet interface fails to come
> up due to a timeout:
>
> [   77.105651] qcom-dwmac-sgmii-phy 8909000.phy: QSERDES_COM_C_READY_STATUS timed-out
> [   77.113447] qcom-ethqos 23040000.ethernet eth0: __stmmac_open: Serdes powerup failed
>
> Presumably, the issue is not seen on all users of this PHY because both
> regulators are often shared with other peripherals. However, the power
> rail schematics for boards using this SerDes PHY show that it is
> supplied by both L5A (1.2V) and L4A (0.9V) regulators.
>
> This series has been tested on the QCS8300 Ride board, and the reported
> issue was resolved. All Monaco and Lemans derivative boards require this
> new configuration as they use the same SerDes PHY.
>
> Signed-off-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>

This appears to be a real issue, but I haven’t seen a new version of
the series or any response to the feedback so far. Could you please
follow up on this?

> ---
> Mohd Ayaan Anwar (6):
>       dt-bindings: phy: describe additional regulator for Qualcomm SGMII PHY
>       arm64: dts: qcom: lemans-evk: add additional SerDes PHY regulator
>       arm64: dts: qcom: lemans-ride-common: add additional SerDes PHY regulators
>       arm64: dts: qcom: monaco-evk: fix the SerDes PHY regulators
>       arm64: dts: qcom: qcs8300-ride: add additional SerDes PHY regulator
>       phy: qcom: sgmii-eth: add second regulator support
>
>  .../bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml |  4 ++++
>  arch/arm64/boot/dts/qcom/lemans-evk.dts            |  1 +
>  arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi   |  4 ++++
>  arch/arm64/boot/dts/qcom/monaco-evk.dts            |  3 ++-
>  arch/arm64/boot/dts/qcom/qcs8300-ride.dts          |  2 ++
>  drivers/phy/qualcomm/phy-qcom-sgmii-eth.c          | 24 +++++++++++++++++++++-
>  6 files changed, 36 insertions(+), 2 deletions(-)
> ---
> base-commit: 0f2995693867bfb26197b117cd55624ddc57582f
> change-id: 20251124-sgmiieth_serdes_regulator-027fc6b15216
>
> Best regards,
> --
> Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
>
>

^ permalink raw reply

* Re: [PATCH 1/9] dt-bindings: nvmem: imx-ocotp: Add support for secure-enclave
From: Frank Li @ 2026-06-22 14:14 UTC (permalink / raw)
  To: Frieder Schrempf
  Cc: Krzysztof Kozlowski, Frieder Schrempf, Srinivas Kandagatla,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Shawn Guo,
	devicetree, imx, linux-arm-kernel, linux-kernel
In-Reply-To: <085262ba-32e5-4011-8df3-5a677575b2db@kontron.de>

On Wed, Jun 17, 2026 at 01:36:30PM +0200, Frieder Schrempf wrote:
> On 17.06.26 12:49, Krzysztof Kozlowski wrote:
> > On Tue, Jun 16, 2026 at 01:52:16PM +0200, Frieder Schrempf wrote:
> >> From: Frieder Schrempf <frieder.schrempf@kontron.de>
> >>
> >> Some SoCs like the i.MX9 family allow full access to the fuses only
> >> through the secure enclave firmware API. Add a property to reference
> >> the secure enclave node and let the driver use the API.
> >>
> >> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> >> ---
> >>  Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml | 4 ++++
> >>  1 file changed, 4 insertions(+)
> >>
> >> diff --git a/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml b/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml
> >> index a8076d0e2737..14a6429f4a4c 100644
> >> --- a/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml
> >> +++ b/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml
> >> @@ -53,6 +53,10 @@ properties:
> >>    reg:
> >>      maxItems: 1
> >>
> >> +  secure-enclave:
> >> +    $ref: /schemas/types.yaml#/definitions/phandle
> >> +    description: A phandle to the secure enclave node
> >
> > Two things here:
> > 1. Here you describe what for is that phandle, how it is used by the
> > hardware. Currently the description repeats the property name and type,
> > so not much useful.
>
> Ok, agree.
>
> >
> > 2. If you access OTP via firmware, then this is completely different
> > interface than MMIO, thus:
> > A. reg is not appropriate
> > B. Device is very different thus it has different compatible and I even
> > claim should be in different binding. Devices having completely
> > different SW interface should not be in the same binding, at least
> > usually.
> >
> > If any of above is not accurate, then your commit msg should answer why
> > and give some background.
>
> Thanks for the feedback!
>
> The driver currently uses the limited MMIO (FSB) interface to access the
> OTPs. The intention is to support the firmware interface alongside the
> MMIO interface so the driver can pick the interface that is available
> (firmware might not be loaded) and fallback to MMIO.

Does ELE and MMIO access the same bank of fuse? If access the same bank,
why not always use MMIO. Any beneafit from ELE firmware?

Frank
>
> Following your argument would mean a driver deciding by itself which
> interface to use at runtime is not something we want to have in general,
> right?
>
> In turn this would mean we need two drivers, or at least two
> compatibles/bindings for something that is effectively the same hardware.
>
> Actually, my first RFC approach [1] was to create a separate driver. But
> in the end it seemed very weird to have two drivers and two DT nodes for
> the same hardware block. Also I have no idea what happens if both
> interfaces are used at the same time.
>
> The other idea from back then was to replace the MMIO (FSB) interface
> with ELE, but this would mean that we rely on the proprietary ELE
> firmware to be available for simple things like reading a MAC address,
> which is not desirable either, I guess.
>
> In which direction should I move on with this?
>
> [1]
> https://patchwork.kernel.org/project/linux-arm-kernel/patch/20250416142715.1042363-1-frieder@fris.de/
>

^ permalink raw reply

* Re: [PATCH v2 1/4] dt-bindings: timer: Add the Renesas RZ/N1 timer
From: Geert Uytterhoeven @ 2026-06-22 14:22 UTC (permalink / raw)
  To: Herve Codina (Schneider Electric)
  Cc: Wolfram Sang, Daniel Lezcano, Thomas Gleixner, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven,
	Magnus Damm, linux-renesas-soc, linux-kernel, devicetree,
	Pascal Eberhard, Miquel Raynal, Thomas Petazzoni,
	Krzysztof Kozlowski
In-Reply-To: <20260429115054.158160-2-herve.codina@bootlin.com>

On Wed, 29 Apr 2026 at 13:51, Herve Codina (Schneider Electric)
<herve.codina@bootlin.com> wrote:
> The Renesas RZ/N1 timer block controller is the controller in charge of
> timers available in the Renesas RZ/N1 SoCs family.
>
> This controller handles 8 timers:
>  - 6 16-bit timers
>  - 2 32-bit timers
>
> Signed-off-by: Herve Codina (Schneider Electric) <herve.codina@bootlin.com>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

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 v2 3/4] ARM: dts: r9a06g032: Add support for timers
From: Geert Uytterhoeven @ 2026-06-22 14:23 UTC (permalink / raw)
  To: Herve Codina (Schneider Electric)
  Cc: Wolfram Sang, Daniel Lezcano, Thomas Gleixner, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Magnus Damm, linux-renesas-soc,
	linux-kernel, devicetree, Pascal Eberhard, Miquel Raynal,
	Thomas Petazzoni
In-Reply-To: <20260429115054.158160-4-herve.codina@bootlin.com>

On Wed, 29 Apr 2026 at 13:51, Herve Codina (Schneider Electric)
<herve.codina@bootlin.com> wrote:
> In the Renesas RZ/N1 SoCs family, two timers block are available.
>
> Each block contains 8 timers composed of 6 16-bits timers and 2 32-bits
> timers.
>
> Each timer has its own interrupt line.
>
> Describe those timers blocks.
>
> Signed-off-by: Herve Codina (Schneider Electric) <herve.codina@bootlin.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
i.e. will queue in renesas-devel for v7.3, pending acceptance of the
DT bindings.

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 v2 2/4] clocksource/drivers: Add support for the Renesas RZ/N1 timers
From: Geert Uytterhoeven @ 2026-06-22 14:22 UTC (permalink / raw)
  To: Herve Codina (Schneider Electric)
  Cc: Wolfram Sang, Daniel Lezcano, Thomas Gleixner, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Magnus Damm, linux-renesas-soc,
	linux-kernel, devicetree, Pascal Eberhard, Miquel Raynal,
	Thomas Petazzoni
In-Reply-To: <20260429115054.158160-3-herve.codina@bootlin.com>

Hi Hervé,

Thanks for your patch!

Just a few generic comments, as I am not a timer expert, and have no
access to the hardware.

On Wed, 29 Apr 2026 at 13:51, Herve Codina (Schneider Electric)
<herve.codina@bootlin.com> wrote:
> The Renesas RZ/N1 timer block controller is the controller in charge of
> timers available in the Renesas RZ/N1 SoCs family.
>
> This controller handles 8 timers:
>   - 6 16-bit timers
>   - 2 32-bit timers
>
> Each timer has its own interrupt, its own prescaler that can be used to
> device the clock by 25 and all of them can work in either one-shot or

divide

> periodic mode.
>
> Signed-off-by: Herve Codina (Schneider Electric) <herve.codina@bootlin.com>
> ---
>  drivers/clocksource/Kconfig      |  10 +
>  drivers/clocksource/Makefile     |   1 +
>  drivers/clocksource/timer-rzn1.c | 442 +++++++++++++++++++++++++++++++
>  3 files changed, 453 insertions(+)
>  create mode 100644 drivers/clocksource/timer-rzn1.c
>
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index d1a33a231a44..f8e49a4ac8f6 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -152,6 +152,16 @@ config REALTEK_OTTO_TIMER
>           RT8391, RTL8392, RTL8393 and RTL8396 and chips of the RTL930x series
>           such as RTL9301, RTL9302 or RTL9303.
>
> +config RZN1_TIMER
> +       bool "Renesas RZ/N1 Timer"

So this cannot be a module.

> +       depends on HAS_IOMEM && COMMON_CLK && (ARCH_RZN1 || COMPILE_TEST)

I would split this in two lines, to make it easier to read (and
maintain, if the same timer ends up in a different SoC series).

> +       help
> +         Enables support for RZ/N1 SoC timers.
> +         A timers block in RZ/N1 SoCs is composed of 8 timers
> +           - 6 16-bit timers
> +           - 2 32-bit timers
> +         Two timers blocks are available in RZ/N1 SoCs.
> +
>  config SUN4I_TIMER
>         bool "Sun4i timer driver" if COMPILE_TEST
>         depends on HAS_IOMEM

> --- /dev/null
> +++ b/drivers/clocksource/timer-rzn1.c

> +/*
> + * 8 timers are available. Among those 8 timers, the first 6 timers are 16-bit
> + * timers and the last two ones are 32-bit timers.
> + */
> +#define RZN1_TIMER_BASE_INDEX_16BIT_TIMERS 0
> +#define RZN1_TIMER_NB_16BIT_TIMERS 6
> +
> +#define RZN1_TIMER_BASE_INDEX_32BIT_TIMER 6
> +#define RZN1_TIMER_NB_32BIT_TIMERS 2

Align the number columns?

> +static int rzn1_timer_probe_first(struct platform_device *pdev, struct rzn1_timer *tab_timers,
> +                                 void __iomem *base, unsigned long clock_rate)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct rzn1_timer *timer;
> +       unsigned int i;
> +       char *name;
> +       int irq;
> +       int ret;
> +
> +       /*
> +        * Probe the first instance. In that case, timers are assigned as
> +        * follow:
> +        *   - First 16-bit timer: clocksource and sched_clock
> +        *   - Other 16-bit timers: clock events for all possible CPUs
> +        *   - 32-bit timers: clock events per CPU
> +        *
> +        * First step, perform all operation that could fail without calling
> +        * clockevents_config_and_register(), sched_clock_register() nor
> +        * cpuhp_setup_state(). Those operation don't have unregister nor
> +        * teardown counterparts and so, once called, we cannot remove the
> +        * related resource.
> +        */
> +
> +       /*
> +        * First step for 16-bit timers except the first one and all 32-bit
> +        * timers.
> +        */
> +       for (i = RZN1_TIMER_BASE_INDEX_16BIT_TIMERS + 1; i < RZN1_TIMER_NB_TIMERS; i++) {
> +               timer = &tab_timers[i];
> +
> +               rzn1_timer_init(timer, i, base, clock_rate);
> +
> +               irq = platform_get_irq(pdev, i);
> +               if (irq < 0)
> +                       return irq;
> +
> +               name = devm_kasprintf(dev, GFP_KERNEL, "%s-%u", dev_name(dev), i);
> +               if (!name)
> +                       return -ENOMEM;
> +
> +               rzn1_timer_clkevt_init_ced(timer, name, irq);
> +
> +               ret = devm_request_irq(dev, timer->ced.irq, rzn1_timer_interrupt,
> +                                      IRQF_TIMER, timer->ced.name, timer);
> +               if (ret < 0)
> +                       return dev_err_probe(dev, irq, "timer%d: Failed to request IRQ\n", i);

%u

> +
> +               rzn1_timer_int_enable(timer);
> +       }
> +
> +       /*
> +        * Second step, almost all operations that can fail have been called.
> +        * Timers are ready to work. Start with the last operation that can fail,
> +        * installing and invoking hotplug callbacks
> +        */
> +       rzn1_tab_timers = tab_timers;
> +       ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
> +                               "clockevents/rzn1/global_timer:starting",
> +                               rzn1_local_timer_starting_cpu, NULL);
> +       if (ret < 0)
> +               return dev_err_probe(dev, ret, "Setup CPU hotplug state failed\n");
> +
> +       /*
> +        * At this point, no more operations can fail. Perform remaining
> +        * operations. Starting by handling the first 16-bit timer
> +        */
> +       timer = &tab_timers[RZN1_TIMER_BASE_INDEX_16BIT_TIMERS];
> +
> +       rzn1_timer_init(timer, RZN1_TIMER_BASE_INDEX_16BIT_TIMERS, base, clock_rate);
> +       rzn1_timer_config(timer, GENMASK(timer->width - 1, 0), true);
> +
> +       rzn1_sched_clock = timer;
> +
> +       sched_clock_register(rzn1_sched_read, rzn1_sched_clock->width, rzn1_sched_clock->rate);
> +
> +       rzn1_clocksource.mask = CLOCKSOURCE_MASK(rzn1_sched_clock->width);
> +       clocksource_register_hz(&rzn1_clocksource, rzn1_sched_clock->rate);
> +
> +       /*
> +        * Register clockevents only for 16-bit timers. 32-bit timers clockevents
> +        * are registered by CPU hotplug startup function set previously by the
> +        * cpuhp_setup_state() call.
> +        */
> +       for (i = RZN1_TIMER_BASE_INDEX_16BIT_TIMERS + 1; i < RZN1_TIMER_NB_16BIT_TIMERS; i++) {
> +               timer = &tab_timers[i];
> +               clockevents_config_and_register(&timer->ced, timer->rate,
> +                                               1, GENMASK(timer->width - 1, 0));
> +       }
> +
> +       return 0;
> +}
> +
> +static int rzn1_timer_probe_other(struct platform_device *pdev, struct rzn1_timer *tab_timers,
> +                                 void __iomem *base, unsigned long clock_rate)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct rzn1_timer *timer;
> +       unsigned int i;
> +       char *name;
> +       int irq;
> +       int ret;
> +
> +       /*
> +        * Probe other instance(s), i.e. not the first one. In that case,
> +        * all timers are used as clock events and available for all possible
> +        * CPUs
> +        *
> +        * First step, perform all operation that could fail without calling
> +        * clockevents_config_and_register(). Unregister counterpart does not
> +        * exist and so, once called, we cannot remove the related resource.
> +        */
> +       for (i = 0; i < RZN1_TIMER_NB_TIMERS; i++) {

Technically "0" is RZN1_TIMER_BASE_INDEX_16BIT_TIMERS.

> +               timer = &tab_timers[i];
> +
> +               rzn1_timer_init(timer, i, base, clock_rate);
> +
> +               irq = platform_get_irq(pdev, i);
> +               if (irq < 0)
> +                       return irq;
> +
> +               name = devm_kasprintf(dev, GFP_KERNEL, "%s-%u", dev_name(dev), i);
> +               if (!name)
> +                       return -ENOMEM;
> +
> +               rzn1_timer_clkevt_init_ced(timer, name, irq);
> +
> +               ret = devm_request_irq(dev, timer->ced.irq, rzn1_timer_interrupt,
> +                                      IRQF_TIMER, timer->ced.name, timer);
> +               if (ret < 0)
> +                       return dev_err_probe(dev, irq, "timer%d: Failed to request IRQ\n", i);

%u

> +
> +               rzn1_timer_int_enable(timer);
> +       }

This loop is identical to the first loop in rzn1_timer_probe_first(),
except for the lower bound. Perhaps it can be factored out?

> +
> +       /*
> +        * Second step, all operation that can fail have been called. We can
> +        * register our timers
> +        */
> +
> +       for (i = 0; i < RZN1_TIMER_NB_TIMERS; i++) {

Technically "0" is RZN1_TIMER_BASE_INDEX_16BIT_TIMERS.

> +               timer = &tab_timers[i];
> +               clockevents_config_and_register(&timer->ced, timer->rate,
> +                                               1, GENMASK(timer->width - 1, 0));
> +       }
> +
> +       return 0;
> +}

This loop is identical to the second loop in rzn1_timer_probe_first(),
except for the lower and upper bound. Perhaps it can be factored out?

Alternatively, you can
  1. Unify rzn1_timer_probe_{first,other}(), and pass the different
     bounds as parameters, OR
  2. Split rzn1_timer_probe_first() in three sub-functions, and call
     these from rzn1_timer_probe() directly.

> +static struct platform_driver rzn1_timer_driver = {
> +       .driver = {
> +               .name = "rzn1_timer",
> +               .of_match_table = rzn1_timer_of_match,

This driver can't be modular, and can't be unbound:

    .suppress_bind_attrs = true

> +       },
> +};
> +builtin_platform_driver_probe(rzn1_timer_driver, rzn1_timer_probe);

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 v4 2/4] PCI: rzg3s-host: Use shared reset controls for power domain resets
From: Manivannan Sadhasivam @ 2026-06-22 14:30 UTC (permalink / raw)
  To: Lad, Prabhakar
  Cc: Philipp Zabel, Claudiu Beznea, Lorenzo Pieralisi,
	Krzysztof Wilczyński, Rob Herring, Bjorn Helgaas,
	Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven,
	Magnus Damm, linux-pci, linux-renesas-soc, devicetree,
	linux-kernel, Biju Das, Fabrizio Castro, Lad Prabhakar
In-Reply-To: <CA+V-a8uGho2RMhreDgieOOZTggUALoF0bGyjdEEDvyL_75sAyw@mail.gmail.com>

On Fri, Jun 05, 2026 at 12:54:46PM +0100, Lad, Prabhakar wrote:
> Hi Philipp,
> 
> Thank you for the review.
> 
> On Wed, Jun 3, 2026 at 9:16 AM Philipp Zabel <p.zabel@pengutronix.de> wrote:
> >
> > On Di, 2026-06-02 at 20:50 +0100, Prabhakar wrote:
> > > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > >
> > > Switch to shared reset controls for PCIe power resets to prepare for
> > > RZ/V2H(P) support. On this platform, multiple PCIe controllers share
> > > the same reset line, requiring shared ownership of the reset control.
> > >
> > > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > Reviewed-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> > > Tested-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> > > ---
> > > v3->v4:
> > > - Added RB/TB tags.
> > >
> > > v2->v3:
> > > - No change.
> > >
> > > v1->v2:
> > > - Updated commit message.
> > > ---
> > >  drivers/pci/controller/pcie-rzg3s-host.c | 6 +++---
> > >  1 file changed, 3 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/controller/pcie-rzg3s-host.c
> > > index d86e7516dcc2..a5192e4b58df 100644
> > > --- a/drivers/pci/controller/pcie-rzg3s-host.c
> > > +++ b/drivers/pci/controller/pcie-rzg3s-host.c
> > > @@ -1276,9 +1276,9 @@ static int rzg3s_pcie_resets_prepare_and_get(struct rzg3s_pcie_host *host)
> > >       for (i = 0; i < data->num_cfg_resets; i++)
> > >               host->cfg_resets[i].id = data->cfg_resets[i];
> > >
> > > -     ret = devm_reset_control_bulk_get_exclusive(host->dev,
> > > -                                                 data->num_power_resets,
> > > -                                                 host->power_resets);
> > > +     ret = devm_reset_control_bulk_get_shared(host->dev,
> > > +                                              data->num_power_resets,
> > > +                                              host->power_resets);
> > >       if (ret)
> > >               return ret;
> > >
> >
> > I have a few questions about this.
> >
> > Can you move rzg3s_pcie_resets_prepare_and_get() and
> > rzg3s_pcie_power_resets_deassert() up before setting
> > RZG3S_SYSC_FUNC_ID_MODE and RZG3S_SYSC_FUNC_ID_RST_RSM_B in
> > rzg3s_pcie_probe() without ill effect?
> >
> > Can you move rzg3s_pcie_power_resets_deassert() up before setting
> > RZG3S_SYSC_FUNC_ID_MODE and RZG3S_SYSC_FUNC_ID_RST_RSM_B
> > rzg3s_pcie_resume_noirq()?
> >
> > Those would have the same effect as the reset already being deasserted
> > by the other controller.
> >
> Yes to both. I have reordered the sequences as suggested, and it works
> perfectly without any ill effects.
> 

Are you going to respin the patches incorporating the review comments?

- Mani

-- 
மணிவண்ணன் சதாசிவம்

^ permalink raw reply

* Re: [PATCH v2 4/4] MAINTAINERS: Add the Renesas RZ/N1 timers driver entry
From: Geert Uytterhoeven @ 2026-06-22 14:23 UTC (permalink / raw)
  To: Herve Codina (Schneider Electric)
  Cc: Wolfram Sang, Daniel Lezcano, Thomas Gleixner, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven,
	Magnus Damm, linux-renesas-soc, linux-kernel, devicetree,
	Pascal Eberhard, Miquel Raynal, Thomas Petazzoni
In-Reply-To: <20260429115054.158160-5-herve.codina@bootlin.com>

On Wed, 29 Apr 2026 at 13:51, Herve Codina (Schneider Electric)
<herve.codina@bootlin.com> wrote:
> After contributing the driver, add myself as the maintainer for the
> Renesas RZ/N1 timers driver.
>
> Signed-off-by: Herve Codina (Schneider Electric) <herve.codina@bootlin.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

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 v2 2/4] irqchip/gic-v3: Refactor GIC600 limited to 32bit PA erratum handling
From: Marek Vasut @ 2026-06-22 14:22 UTC (permalink / raw)
  To: Geert Uytterhoeven, Marek Vasut
  Cc: linux-pci, Marc Zyngier, Krzysztof Wilczyński, Bjorn Helgaas,
	Catalin Marinas, Conor Dooley, Geert Uytterhoeven,
	Krzysztof Kozlowski, Lorenzo Pieralisi, Manivannan Sadhasivam,
	Rob Herring, Yoshihiro Shimoda, devicetree, linux-arm-kernel,
	linux-doc, linux-kernel, linux-renesas-soc
In-Reply-To: <CAMuHMdUxT87M1oQvPP_h4YX4vXFaVbbG+LCG8EdmuLTuHNtybQ@mail.gmail.com>

On 6/22/26 11:52 AM, Geert Uytterhoeven wrote:

Hello Geert,

>> +++ b/drivers/irqchip/irq-gic-v3-its.c
>> @@ -4890,10 +4890,17 @@ static bool __maybe_unused its_enable_quirk_hip09_162100801(void *data)
>>          return true;
>>   }
>>
>> -static bool __maybe_unused its_enable_rk3568002(void *data)
>> +static const char * const dma_32bit_impaired_platforms[] = {
>> +#ifdef CONFIG_ROCKCHIP_ERRATUM_3568002
>> +       "rockchip,rk3566",
>> +       "rockchip,rk3568",
>> +#endif
>> +       NULL,
>> +};
>> +
>> +static bool __maybe_unused its_enable_dma32(void *data)
> 
> __maybe_unused can be dropped...
I will fix that in V3. Thank you !

^ permalink raw reply

* Re: [PATCH] dt-bindings: clock: ti,clockdomain: Convert to DT schema
From: Rob Herring (Arm) @ 2026-06-22 14:35 UTC (permalink / raw)
  To: Bhargav Joshi
  Cc: simona.toaca, Krzysztof Kozlowski, Stephen Boyd, Conor Dooley,
	linux-clk, Brian Masney, devicetree, Tero Kristo, daniel.baluta,
	Michael Turquette, linux-kernel, goledhruva, m-chawdhry
In-Reply-To: <20260621-ti-clockdomain-v1-1-e99a56af98ea@gmail.com>


On Sun, 21 Jun 2026 21:23:35 +0530, Bhargav Joshi wrote:
> Convert TI clockdomain to yaml DT schema. Drop '#clock-cells' from the
> required list as this binding doesn't define a new clock binding type,
> it is used to group existing clock nodes under hardware hierarchy. Most
> existing dts omit '#clock-cells'.
> 
> Signed-off-by: Bhargav Joshi <j.bhargav.u@gmail.com>
> ---
>  .../devicetree/bindings/clock/ti/clockdomain.txt   | 25 -------------
>  .../bindings/clock/ti/ti,clockdomain.yaml          | 41 ++++++++++++++++++++++
>  2 files changed, 41 insertions(+), 25 deletions(-)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:


doc reference errors (make refcheckdocs):
Warning: Documentation/devicetree/bindings/clock/ti/ti,gate-clock.yaml references a file that doesn't exist: Documentation/devicetree/bindings/clock/ti/clockdomain.txt
Documentation/devicetree/bindings/clock/ti/ti,gate-clock.yaml: Documentation/devicetree/bindings/clock/ti/clockdomain.txt

See https://patchwork.kernel.org/project/devicetree/patch/20260621-ti-clockdomain-v1-1-e99a56af98ea@gmail.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.


^ permalink raw reply

* Re: [PATCH v3 5/5] dmaengine: sun6i-dma: Add support for Allwinner A733 DMA controller
From: Frank Li @ 2026-06-22 14:35 UTC (permalink / raw)
  To: Yuanshen Cao
  Cc: conor+dt, mripard, krzk+dt, robh, samuel, wens, jernej.skrabec,
	Frank.Li, vkoul, dmaengine, linux-arm-kernel, linux-sunxi,
	devicetree, linux-kernel
In-Reply-To: <20260622-sun60i-a733-dma-v3-5-f697ef296cbc@gmail.com>

On Mon, Jun 22, 2026 at 01:36:27AM +0000, Yuanshen Cao wrote:
> Support Allwinner A733 DMA controller. Define new register offsets,
> bitfield mappings and dma_config required for the A733, which slightly
> differs from the older `sun6i` DMA controllers.
>
> Changes:
> - New register macros for A733 interrupt enable `DMA_IRQ_EN_A733`,
>   status `DMA_IRQ_STAT_A733`, and channel count `DMA_IRQ_CHAN_NR_A733`.
> - New `SRC_HIGH_ADDR_32G` and `DST_HIGH_ADDR_32G` macro to handle the
>   32G high-address field in the LLI.
> - Implemented `sun6i_dma_set_addr_a733` and A733-specific interrupt
>   register accessors.
> - Added `sun60i_a733_dma_cfg`, which ties all the refactored
>   functionality together for this specific hardware.
>
> Signed-off-by: Yuanshen Cao <alex.caoys@gmail.com>
> ---
>  drivers/dma/sun6i-dma.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 87 insertions(+)
>
> diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> index 196a0d73b221..4808015934cc 100644
> --- a/drivers/dma/sun6i-dma.c
> +++ b/drivers/dma/sun6i-dma.c
> @@ -52,6 +52,15 @@
>  #define SUNXI_H3_SECURE_REG		0x20
>  #define SUNXI_H3_DMA_GATE		0x28
>  #define SUNXI_H3_DMA_GATE_ENABLE	0x4
> +
> +/*
> + * sun60i specific registers
> + */
> +#define DMA_IRQ_EN_A733(x)		((x) * 0x40 + 0x134)
> +#define DMA_IRQ_STAT_A733(x)		((x) * 0x40 + 0x138)
> +
> +#define DMA_IRQ_CHAN_NR_A733		1
> +
>  /*
>   * Channels specific registers
>   */
> @@ -100,6 +109,8 @@
>   */
>  #define SRC_HIGH_ADDR(x)		(((x) & 0x3U) << 16)
>  #define DST_HIGH_ADDR(x)		(((x) & 0x3U) << 18)
> +#define SRC_HIGH_ADDR_32G(x)	(((x) & 0x7U) << 11)
> +#define DST_HIGH_ADDR_32G(x)	(((x) & 0x7U) << 15)

Because the previous code use this pattern, I provide my reviewed-by tags.
I suggest change to use GEN_MASK and FIELD_PREP macro in future.

Reviewed-by: Frank Li <Frank.Li@nxp.com>
>
>  /*
>   * Various hardware related defines
> @@ -257,6 +268,23 @@ static inline void sun6i_dma_dump_com_regs(struct sun6i_dma_dev *sdev)
>  		DMA_STAT, readl(sdev->base + DMA_STAT));
>  }
>
> +static inline void sun6i_dma_dump_com_regs_a733(struct sun6i_dma_dev *sdev)
> +{
> +	int i;
> +
> +	for (i = 0; i < sdev->num_pchans / sdev->cfg->num_channels_per_reg; i++) {
> +		dev_dbg(sdev->slave.dev, "Common register:\n"
> +			"chan num %d\n"
> +			"\tmask(%04x): 0x%08x\n"
> +			"\tpend(%04x): 0x%08x\n"
> +			"\tstats(%04x): 0x%08x\n",
> +			i,
> +			DMA_IRQ_EN_A733(i), readl(sdev->base + DMA_IRQ_EN_A733(i)),
> +			DMA_IRQ_STAT_A733(i), readl(sdev->base + DMA_IRQ_STAT_A733(i)),
> +			DMA_STAT, readl(sdev->base + DMA_STAT));
> +	}
> +}
> +
>  static inline void sun6i_dma_dump_chan_regs(struct sun6i_dma_dev *sdev,
>  					    struct sun6i_pchan *pchan)
>  {
> @@ -360,21 +388,41 @@ static u32 sun6i_read_irq_en(struct sun6i_dma_dev *sdev, u32 irq_reg)
>  	return readl(sdev->base + DMA_IRQ_EN(irq_reg));
>  }
>
> +static u32 sun6i_read_irq_en_a733(struct sun6i_dma_dev *sdev, u32 irq_reg)
> +{
> +	return readl(sdev->base + DMA_IRQ_EN_A733(irq_reg));
> +}
> +
>  static void sun6i_write_irq_en(struct sun6i_dma_dev *sdev, u32 irq_reg, u32 irq_val)
>  {
>  	writel(irq_val, sdev->base + DMA_IRQ_EN(irq_reg));
>  }
>
> +static void sun6i_write_irq_en_a733(struct sun6i_dma_dev *sdev, u32 irq_reg, u32 irq_val)
> +{
> +	writel(irq_val, sdev->base + DMA_IRQ_EN_A733(irq_reg));
> +}
> +
>  static u32 sun6i_read_irq_stat(struct sun6i_dma_dev *sdev, u32 irq_reg)
>  {
>  	return readl(sdev->base + DMA_IRQ_STAT(irq_reg));
>  }
>
> +static u32 sun6i_read_irq_stat_a733(struct sun6i_dma_dev *sdev, u32 irq_reg)
> +{
> +	return readl(sdev->base + DMA_IRQ_STAT_A733(irq_reg));
> +}
> +
>  static void sun6i_write_irq_stat(struct sun6i_dma_dev *sdev, u32 irq_reg, u32 status)
>  {
>  	writel(status, sdev->base + DMA_IRQ_STAT(irq_reg));
>  }
>
> +static void sun6i_write_irq_stat_a733(struct sun6i_dma_dev *sdev, u32 irq_reg, u32 status)
> +{
> +	writel(status, sdev->base + DMA_IRQ_STAT_A733(irq_reg));
> +}
> +
>  static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
>  {
>  	struct sun6i_desc *txd = pchan->desc;
> @@ -695,6 +743,17 @@ static void sun6i_dma_set_addr_a100(struct sun6i_dma_dev *sdev,
>  				DST_HIGH_ADDR(upper_32_bits(dst));
>  }
>
> +static void sun6i_dma_set_addr_a733(struct sun6i_dma_dev *sdev,
> +				      struct sun6i_dma_lli *v_lli,
> +				      dma_addr_t src, dma_addr_t dst)
> +{
> +	v_lli->src = lower_32_bits(src);
> +	v_lli->dst = lower_32_bits(dst);
> +
> +	v_lli->para |= SRC_HIGH_ADDR_32G(upper_32_bits(src)) |
> +				DST_HIGH_ADDR_32G(upper_32_bits(dst));
> +}
> +
>  static inline void sun6i_dma_set_addr(struct sun6i_dma_dev *sdev,
>  				      struct sun6i_dma_lli *v_lli,
>  				      dma_addr_t src, dma_addr_t dst)
> @@ -1339,6 +1398,33 @@ static struct sun6i_dma_config sun50i_h6_dma_cfg = {
>  	SUN6I_DMA_IRQ_A31_COMMON_OPS
>  };
>
> +/*
> + * The A733 binding uses the number of dma channels from the
> + * device tree node.
> + */
> +static struct sun6i_dma_config sun60i_a733_dma_cfg = {
> +	.clock_autogate_enable = sun6i_enable_clock_autogate_h3,
> +	.set_burst_length = sun6i_set_burst_length_h3,
> +	.set_drq          = sun6i_set_drq_h6,
> +	.set_mode         = sun6i_set_mode_h6,
> +	.set_addr         = sun6i_dma_set_addr_a733,
> +	.dump_com_regs    = sun6i_dma_dump_com_regs_a733,
> +	.read_irq_en      = sun6i_read_irq_en_a733,
> +	.write_irq_en     = sun6i_write_irq_en_a733,
> +	.read_irq_stat    = sun6i_read_irq_stat_a733,
> +	.write_irq_stat   = sun6i_write_irq_stat_a733,
> +	.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
> +	.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
> +	.src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> +			     BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
> +			     BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
> +	.dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> +			     BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
> +			     BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
> +	.num_channels_per_reg = DMA_IRQ_CHAN_NR_A733,
> +	.has_mbus_clk = true,
> +};
> +
>  /*
>   * The V3s have only 8 physical channels, a maximum DRQ port id of 23,
>   * and a total of 24 usable source and destination endpoints.
> @@ -1375,6 +1461,7 @@ static const struct of_device_id sun6i_dma_match[] = {
>  	{ .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg },
>  	{ .compatible = "allwinner,sun50i-a100-dma", .data = &sun50i_a100_dma_cfg },
>  	{ .compatible = "allwinner,sun50i-h6-dma", .data = &sun50i_h6_dma_cfg },
> +	{ .compatible = "allwinner,sun60i-a733-dma", .data = &sun60i_a733_dma_cfg },
>  	{ /* sentinel */ }
>  };
>  MODULE_DEVICE_TABLE(of, sun6i_dma_match);
>
> --
> 2.54.0
>

^ permalink raw reply

* Re: [PATCH 1/9] arm64: dts: renesas: r8a774a1: Add soc: label to soc node
From: Geert Uytterhoeven @ 2026-06-22 14:37 UTC (permalink / raw)
  To: Marek Vasut
  Cc: linux-arm-kernel, Conor Dooley, Krzysztof Kozlowski, Rob Herring,
	devicetree, linux-kernel, linux-renesas-soc
In-Reply-To: <8cb1c3cb-3d8f-4e76-99e9-ad78ee149556@mailbox.org>

Hi Marek,

On Mon, 22 Jun 2026 at 15:56, Marek Vasut <marek.vasut@mailbox.org> wrote:
> On 6/22/26 12:35 PM, Geert Uytterhoeven wrote:
> > On Sun, 21 Jun 2026 at 04:51, Marek Vasut
> > <marek.vasut+renesas@mailbox.org> wrote:
> >> Add soc: label to the /soc {} node to align the DT with r8a77951.dtsi
> >> which already has that soc: label. The soc: label is useful in U-Boot
> >> where it is used in U-Boot extras DT fragments.
> >>
> >> Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
> >
> > For the whole series:
> > Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
> > i.e. will queue in renesas-devel for v7.3, squashed into a single
> > commit. Unfortunately there is no cover letter, so I will have to add
> > all nine Link-tags.
>
> Is that why cover letter helps you ?

Another reason is that my scripting turns cover letters into empty
commits in my local tree, serving as separators between patch series.

> If so, I will start generating ones ?

Thanks!

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 v4 2/4] PCI: rzg3s-host: Use shared reset controls for power domain resets
From: Lad, Prabhakar @ 2026-06-22 14:53 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: Philipp Zabel, Claudiu Beznea, Lorenzo Pieralisi,
	Krzysztof Wilczyński, Rob Herring, Bjorn Helgaas,
	Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven,
	Magnus Damm, linux-pci, linux-renesas-soc, devicetree,
	linux-kernel, Biju Das, Fabrizio Castro, Lad Prabhakar
In-Reply-To: <fuefvecgjdqbnbvpvam4gmewmpmhofllyq2ootwi6cjqhnyoys@edjzqlh6fjw4>

Hi Manivannan,

On Mon, Jun 22, 2026 at 3:30 PM Manivannan Sadhasivam <mani@kernel.org> wrote:
>
> On Fri, Jun 05, 2026 at 12:54:46PM +0100, Lad, Prabhakar wrote:
> > Hi Philipp,
> >
> > Thank you for the review.
> >
> > On Wed, Jun 3, 2026 at 9:16 AM Philipp Zabel <p.zabel@pengutronix.de> wrote:
> > >
> > > On Di, 2026-06-02 at 20:50 +0100, Prabhakar wrote:
> > > > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > >
> > > > Switch to shared reset controls for PCIe power resets to prepare for
> > > > RZ/V2H(P) support. On this platform, multiple PCIe controllers share
> > > > the same reset line, requiring shared ownership of the reset control.
> > > >
> > > > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > > Reviewed-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> > > > Tested-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> > > > ---
> > > > v3->v4:
> > > > - Added RB/TB tags.
> > > >
> > > > v2->v3:
> > > > - No change.
> > > >
> > > > v1->v2:
> > > > - Updated commit message.
> > > > ---
> > > >  drivers/pci/controller/pcie-rzg3s-host.c | 6 +++---
> > > >  1 file changed, 3 insertions(+), 3 deletions(-)
> > > >
> > > > diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/controller/pcie-rzg3s-host.c
> > > > index d86e7516dcc2..a5192e4b58df 100644
> > > > --- a/drivers/pci/controller/pcie-rzg3s-host.c
> > > > +++ b/drivers/pci/controller/pcie-rzg3s-host.c
> > > > @@ -1276,9 +1276,9 @@ static int rzg3s_pcie_resets_prepare_and_get(struct rzg3s_pcie_host *host)
> > > >       for (i = 0; i < data->num_cfg_resets; i++)
> > > >               host->cfg_resets[i].id = data->cfg_resets[i];
> > > >
> > > > -     ret = devm_reset_control_bulk_get_exclusive(host->dev,
> > > > -                                                 data->num_power_resets,
> > > > -                                                 host->power_resets);
> > > > +     ret = devm_reset_control_bulk_get_shared(host->dev,
> > > > +                                              data->num_power_resets,
> > > > +                                              host->power_resets);
> > > >       if (ret)
> > > >               return ret;
> > > >
> > >
> > > I have a few questions about this.
> > >
> > > Can you move rzg3s_pcie_resets_prepare_and_get() and
> > > rzg3s_pcie_power_resets_deassert() up before setting
> > > RZG3S_SYSC_FUNC_ID_MODE and RZG3S_SYSC_FUNC_ID_RST_RSM_B in
> > > rzg3s_pcie_probe() without ill effect?
> > >
> > > Can you move rzg3s_pcie_power_resets_deassert() up before setting
> > > RZG3S_SYSC_FUNC_ID_MODE and RZG3S_SYSC_FUNC_ID_RST_RSM_B
> > > rzg3s_pcie_resume_noirq()?
> > >
> > > Those would have the same effect as the reset already being deasserted
> > > by the other controller.
> > >
> > Yes to both. I have reordered the sequences as suggested, and it works
> > perfectly without any ill effects.
> >
>
> Are you going to respin the patches incorporating the review comments?
>
If I have not mistaken, no code changes were requested; it was just
that Philipp wanted to ensure the shared reset worked correctly after
shuffling the code around.

I can respin the series if it fails to apply on top of pci/next.

Cheers,
Prabhakar

^ permalink raw reply

* Re: [PATCH v4 2/2] media: i2c: ov5640: Add reset controller support with GPIO fallback
From: Frank Li @ 2026-06-22 15:02 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: robby.cai, robh, krzk+dt, conor+dt, Frank.Li, s.hauer, festevam,
	sebastian.krzyszkowiak, slongerbeam, sakari.ailus, mchehab,
	kieran.bingham, kernel, devicetree, imx, linux-arm-kernel,
	linux-kernel
In-Reply-To: <7ee62b699c5cabb00cd7706ea42573da81c5bc84.camel@pengutronix.de>

On Mon, Jun 22, 2026 at 11:05:34AM +0200, Philipp Zabel wrote:
> On Fr, 2026-06-19 at 09:18 -0500, Frank Li wrote:
> > On Fri, Jun 19, 2026 at 06:05:32PM +0800, robby.cai@oss.nxp.com wrote:
> > > [You don't often get email from robby.cai@oss.nxp.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
> > >
> > > From: Robby Cai <robby.cai@nxp.com>
> > >
> > > Add support for the reset controller framework by acquiring the reset
> > > line using devm_reset_control_get_optional_shared_deasserted(). This
> > > allows the driver to handle reset lines provided by a reset controller,
> > > including shared ones, while avoiding unbalanced deassert counts.
> > >
> > > Retain support for legacy reset-gpios as a fallback when no reset
> > > controller is defined. In that case, request the GPIO and keep it in the
> > > deasserted state as the initial configuration.
> > >
> > > This enables the driver to support both reset-controller-backed reset
> > > lines and older GPIO-based descriptions while preserving the existing
> > > power-up sequencing behavior.
> > >
> > > Signed-off-by: Robby Cai <robby.cai@nxp.com>
> > > ---
> > >  drivers/media/i2c/ov5640.c | 80 +++++++++++++++++++++++++++++++++-----
> > >  1 file changed, 70 insertions(+), 10 deletions(-)
> > >
> > > diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> > > index 85ecc23b3587..5e6db8aacb11 100644
> > > --- a/drivers/media/i2c/ov5640.c
> > > +++ b/drivers/media/i2c/ov5640.c
> > > @@ -17,6 +17,7 @@
> > >  #include <linux/module.h>
> > >  #include <linux/pm_runtime.h>
> > >  #include <linux/regulator/consumer.h>
> > > +#include <linux/reset.h>
> > >  #include <linux/slab.h>
> > >  #include <linux/types.h>
> > >  #include <media/v4l2-async.h>
> > > @@ -442,6 +443,7 @@ struct ov5640_dev {
> > >         u32 xclk_freq;
> > >
> > >         struct regulator_bulk_data supplies[OV5640_NUM_SUPPLIES];
> > > +       struct reset_control *reset;
> > >         struct gpio_desc *reset_gpio;
> > >         struct gpio_desc *pwdn_gpio;
> > >         bool   upside_down;
> > > @@ -2431,6 +2433,48 @@ static int ov5640_restore_mode(struct ov5640_dev *sensor)
> > >         return ov5640_set_framefmt(sensor, &sensor->fmt);
> > >  }
> > >
> > > +static int ov5640_get_reset(struct device *dev, struct ov5640_dev *sensor)
> > > +{
> > > +       /* use deasserted version to avoid unbalanced deassert counts */
> > > +       sensor->reset =
> > > +           devm_reset_control_get_optional_shared_deasserted(dev, NULL);
> > > +       if (IS_ERR(sensor->reset))
> > > +               return dev_err_probe(dev, PTR_ERR(sensor->reset),
> > > +                                    "Failed to get reset\n");
> > > +       else if (sensor->reset)
> > > +               return 0;
> > > +
> > > +       /*
> > > +        * fallback to legacy reset-gpios
> > > +        * GPIOD_OUT_HIGH ensures deasserted state for ACTIVE_LOW reset
> > > +        */
> > > +       sensor->reset_gpio = devm_gpiod_get_optional(dev, "reset",
> > > +                                                    GPIOD_OUT_HIGH);
> > > +       if (IS_ERR(sensor->reset_gpio))
> > > +               return dev_err_probe(dev, PTR_ERR(sensor->reset_gpio),
> > > +                                    "Failed to get reset gpio");
> >
> > I think needn't fallback here, NO ABI change, just change to use reset-gpio
> > driver.
>
> Please keep the gpiod fallback, the reset-gpio driver may not be
> available on all platforms using ov5640.

Maybe try promote reset-gpio is default build in / as module. Leave such
fallback every where make code complex.

Krysztof:
	Any suggestion?

Frank

>
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static int ov5640_reset_assert(struct ov5640_dev *sensor)
> > > +{
> > > +       if (sensor->reset)
> > > +               return reset_control_assert(sensor->reset);
> >
> > needn't check sensor->reset, reset_control_assert() is no ops if NULL.
> >
> > > +
> > > +       gpiod_set_value_cansleep(sensor->reset_gpio, 1);
> >
> > Needn't fallback, directly replace.
>
> See above.
>
>
> regards
> Philipp

^ permalink raw reply

* Re: [PATCH v2 1/3] dt-bindings: power: limits: Describe Qualcomm SPEL hardware
From: Manaf Meethalavalappu Pallikunhi @ 2026-06-22 15:11 UTC (permalink / raw)
  To: Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Rafael J. Wysocki, Bjorn Andersson, Konrad Dybcio, Daniel Lezcano
  Cc: Gaurav Kohli, linux-arm-msm, devicetree, linux-kernel, linux-pm
In-Reply-To: <50d92653-b403-402d-af82-a037114c3aab@oss.qualcomm.com>

Hi Konrad,


On 6/22/2026 4:32 PM, Konrad Dybcio wrote:
> On 6/19/26 10:39 PM, Manaf Meethalavalappu Pallikunhi wrote:
>> The Qualcomm SoC Power and Electrical Limits (SPEL) provides hardware
>> based power monitoring and limiting capabilities for various domains.
>>
>> Add a DeviceTree binding to describe the SPEL block on Qualcomm's SoC.
>>
>> Signed-off-by: Manaf Meethalavalappu Pallikunhi <manaf.pallikunhi@oss.qualcomm.com>
>> ---
>>   .../bindings/power/limits/qcom,spel.yaml           | 47 ++++++++++++++++++++++
>>   MAINTAINERS                                        |  6 +++
>>   2 files changed, 53 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/power/limits/qcom,spel.yaml b/Documentation/devicetree/bindings/power/limits/qcom,spel.yaml
>> new file mode 100644
>> index 000000000000..4c6e6cbfbfe4
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/power/limits/qcom,spel.yaml
>> @@ -0,0 +1,47 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/power/limits/qcom,spel.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Qualcomm SoC Power and Electrical Limits (SPEL)
>> +
>> +maintainers:
>> +  - Manaf Meethalavalappu Pallikunhi <manaf.pallikunhi@oss.qualcomm.com>
>> +
>> +description:
>> +  The Qualcomm SPEL (SoC Power and Electrical Limits) provides hardware-based
>> +  power monitoring and limiting capabilities for various power domains in
>> +  Qualcomm SoCs.
>> +
>> +properties:
>> +  compatible:
>> +    const: qcom,glymur-spel
>> +
>> +  reg:
>> +    maxItems: 3
>> +
>> +  reg-names:
>> +    items:
>> +      - const: config
>> +      - const: constraints
>> +      - const: nodes
>> +
>> +required:
>> +  - compatible
>> +  - reg
>> +  - reg-names
>> +
>> +additionalProperties: false
>> +
>> +examples:
>> +  - |
>> +    power-limits@ef3b000 {
>> +        compatible = "qcom,glymur-spel";
>> +        reg = <0x0ef3b000 0x1000>,
>> +              <0x0ef3d000 0x1000>,
> 
> Don't we need the range inbetween these two (base=0xef3c000)?
>

No, it is consumed by firmware.

Thanks,
Manaf
> Konrad


^ permalink raw reply

* Re: [PATCH v4 01/13] clk: qcom: gcc-qcm2290: Keep the critical clocks always-on from probe
From: Dmitry Baryshkov @ 2026-06-22 15:12 UTC (permalink / raw)
  To: Imran Shaik
  Cc: Bjorn Andersson, Michael Turquette, Stephen Boyd, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio, Loic Poulain,
	Brian Masney, Ajit Pandey, Taniya Das, Jagadeesh Kona,
	linux-arm-msm, linux-clk, devicetree, linux-kernel
In-Reply-To: <f6264995-a6f6-498f-9557-723c39becf1a@oss.qualcomm.com>

On Sun, 21 Jun 2026 at 16:28, Imran Shaik <imran.shaik@oss.qualcomm.com> wrote:
>
>
>
> On 06-06-2026 04:54 pm, Dmitry Baryshkov wrote:
> > On Thu, Jun 04, 2026 at 10:56:07AM +0530, Imran Shaik wrote:
> >> Some GCC branch clocks are required to be kept always-on due to the
> >> hardware requirements. Drop the modelling of those always-on QCM2290 GCC
> >> clocks and use the latest .clk_cbcr convention to keep them enabled from
> >> probe.
> >
> > You got the feedback, but it got ignored. There is no explanation about
> > gcc_gpu_iref_clk and several other clocks becoming always on.
> >
>
> Apologies for the late reply.
>
> I have updated generically that few clocks are required to be kept ON
> due to the hardware requirements. For gcc_gpu_iref_clk clock the
> Power-On-Reset value is default ON, and such clocks are kept ON from
> probe. As Agatti is working functionally, I will keep this clock
> modelling same as before.
>
> And I will update commit text that the GCC video ahb/xo clocks are
> required to be kept ON similar to other camera/disp ahb/xo clocks.

Why? What is _wrong_ with thow they are modelled now?

>
> Thanks,
> Imran
>
> >>
> >> Signed-off-by: Imran Shaik <imran.shaik@oss.qualcomm.com>
> >> ---
> >>   drivers/clk/qcom/gcc-qcm2290.c | 160 +++++------------------------------------
> >>   1 file changed, 18 insertions(+), 142 deletions(-)
> >>
> >
>


-- 
With best wishes
Dmitry

^ permalink raw reply

* Re: [PATCH v4 5/5] clk: renesas: r9a09g077: Add LCDC and PLL3 clock support for RZ/T2H display pipeline
From: Lad, Prabhakar @ 2026-06-22 15:21 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Magnus Damm, linux-kernel,
	linux-renesas-soc, linux-clk, devicetree, Biju Das,
	Fabrizio Castro, Lad Prabhakar
In-Reply-To: <CAMuHMdXX-3ddkTmHGQOySZygRmvhnG6snk7uv4xmA8NjM9MsDw@mail.gmail.com>

Hi Geert,

Thank you for the review.

On Mon, Jun 22, 2026 at 2:13 PM Geert Uytterhoeven <geert@linux-m68k.org> wrote:
>
> Hi Prabhakar,
>
> On Thu, 18 Jun 2026 at 20:19, Prabhakar <prabhakar.csengg@gmail.com> wrote:
> > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> >
> > Add the clock definitions and PLL logic required to supply the LCDC
> > (VSPD/FCPVD/DU) blocks on the RZ/T2H (R9A09G077) SoC. The RZ/T2H display
> > subsystem depends on a dedicated PLL (PLL3) and a set of new derived
> > clocks.
> >
> > Introduce a new PLL clock type and implement rate recalculation,
> > programming and locking sequences for PLL3 using the RZ/T2H specific
> > divider and VCO limits. Add the corresponding muxes and divider entries,
> > expose the LCDC core clock, and register the LCDC module clock using the
> > correct PCLK parent.
> >
> > This enables the RZ/T2H clock driver to generate the display pipeline
> > clocking tree needed by the DU and VSP-based composition engines, allowing
> > upcoming display support to be integrated without duplicating CPG logic.
> >
> > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
> > ---
> > v3->v4:
> > - Added RB tag from Geert.
>
> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
> i.e. will queue in renesas-clk for v7.3.
>
> > +       rate_millihz = mul_u32_u32(req->rate, MILLI);
>
> The issue pointed out by Sashiko (req->rate is unsigned long, i.e. can
> be larger than u32 on 64-bit) is valid, but I believe it can't happen
> in practice.  Still, would be good to fix it in a subsequent patch.
>
Agreed.

Cheers,
Prahakar

^ permalink raw reply

* [PATCH v2 0/4] drm/ssd130x: Add support for the Solomon SSD1351 OLED controller
From: Amit Barzilai @ 2026-06-22 15:25 UTC (permalink / raw)
  To: javierm, maarten.lankhorst, mripard, tzimmermann, airlied, simona,
	robh, krzk+dt, conor+dt, andy, gregkh, deller
  Cc: azuddinadam, chintanlike, dri-devel, devicetree, linux-kernel,
	linux-fbdev, linux-staging, Amit Barzilai

This series adds support for the Solomon SSD1351, a 128x128 65k-color
RGB OLED controller, to the ssd130x DRM driver, and removes the legacy
fbtft fb_ssd1351 driver it supersedes.

v1 [1] was a self-contained ssd1351.c driver. Following Javier's review,
the SSD1351 is instead folded into ssd130x as a new color family, which
also brings 65k color to the existing SSD1331. The work is split as:

  - Patch 1 adds the device tree binding. It was previously posted
    standalone as a v2 [2]; it is folded into this series here, as Conor
    asked, so the binding lands together with the driver and the fbtft
    removal.

  - Patch 2 changes the SSD133X family to drive RGB565 instead of
    RGB332, via a per-variant flag in deviceinfo. The SSD1331 is the
    only current member and gains 65k color from this.

  - Patch 3 adds the SSD1351 as a new SSD135X_FAMILY, reusing the
    SSD133X plane/CRTC and blit/clear helpers. The only data-path
    difference is the explicit Write RAM command (0x5c) the SSD1351
    needs before pixel data; it also gets its own init sequence and a
    longer post-reset settle delay.

  - Patch 4 removes the now-redundant staging fbtft fb_ssd1351 driver.

Testing:

  - The SSD1351 (patches 1 and 3) is tested on hardware.
  - The SSD1331 RGB565 change (patch 2) is compile-tested only; I do not
    currently have a working SSD1331 panel. Javier has kindly offered to
    test it on his SSD1331.

Dependency:

  The SSD1351 reuses ssd133x_update_rect(), which programs the column
  and row *end* address as a relative offset rather than an absolute
  coordinate. This breaks partial updates that do not start at (0,0). A
  separate fix is posted at [3]; until it lands, the SSD1351 shows the
  same partial-redraw artifacts. This series applies independently of
  that fix, but the two are best merged together.

Based on drm-misc-next.

[1] standalone v1 driver:
    https://lore.kernel.org/dri-devel/20260615181253.97551-1-amit.barzilai22@gmail.com
[2] standalone v2 binding:
    https://lore.kernel.org/dri-devel/20260615175620.88828-1-amit.barzilai22@gmail.com
[3] ssd132x/ssd133x update_rect end-address fix:
    https://lore.kernel.org/dri-devel/20260622122604.32500-1-amit.barzilai22@gmail.com

---

Changes since v1:
- Fold the SSD1351 into ssd130x as a new SSD135X family instead of a
  standalone ssd1351.c driver (per Javier).
- Add RGB565 to the SSD133X family, so the SSD1331 also gains 65k color.
- Drop native 256k color (no matching DRM fourcc) and the 0/180
  rotation support, to keep the series focused; both can return later.
- Binding: drop solomon,width / solomon,height (deducible from the
  compatible) and the rotation property (no consumer), per Krzysztof;
  use dt-bindings/gpio/gpio.h flag defines in the example.
- Remove the staging fbtft fb_ssd1351 driver in the same series (per
  Conor).

Amit Barzilai (4):
  dt-bindings: display: Add Solomon SSD1351 OLED controller
  drm/ssd130x: Add RGB565 support to SSD133X family
  drm/ssd130x: Add SSD135X_FAMILY and SSD1351 support
  staging: fbtft: remove fb_ssd1351 driver

 .../bindings/display/solomon,ssd1351.yaml     |  42 +++
 drivers/gpu/drm/solomon/ssd130x-spi.c         |   7 +
 drivers/gpu/drm/solomon/ssd130x.c             | 269 +++++++++++++++---
 drivers/gpu/drm/solomon/ssd130x.h             |  12 +-
 drivers/staging/fbtft/Kconfig                 |   5 -
 drivers/staging/fbtft/Makefile                |   1 -
 drivers/staging/fbtft/fb_ssd1351.c            | 240 ----------------
 7 files changed, 283 insertions(+), 293 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/solomon,ssd1351.yaml
 delete mode 100644 drivers/staging/fbtft/fb_ssd1351.c

-- 
2.54.0


^ permalink raw reply

* [PATCH v2 1/4] dt-bindings: display: Add Solomon SSD1351 OLED controller
From: Amit Barzilai @ 2026-06-22 15:25 UTC (permalink / raw)
  To: javierm, maarten.lankhorst, mripard, tzimmermann, airlied, simona,
	robh, krzk+dt, conor+dt, andy, gregkh, deller
  Cc: azuddinadam, chintanlike, dri-devel, devicetree, linux-kernel,
	linux-fbdev, linux-staging, Amit Barzilai
In-Reply-To: <20260622152506.78627-1-amit.barzilai22@gmail.com>

Add a device tree binding for the Solomon SSD1351, a 128x128 65k-color
RGB OLED display controller driven over a 4-wire SPI bus. The binding
builds on the shared solomon,ssd-common.yaml properties already used by
the other Solomon display controllers.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Amit Barzilai <amit.barzilai22@gmail.com>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
---
 .../bindings/display/solomon,ssd1351.yaml     | 42 +++++++++++++++++++
 1 file changed, 42 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/solomon,ssd1351.yaml

diff --git a/Documentation/devicetree/bindings/display/solomon,ssd1351.yaml b/Documentation/devicetree/bindings/display/solomon,ssd1351.yaml
new file mode 100644
index 000000000000..80850c2ab5b3
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/solomon,ssd1351.yaml
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/solomon,ssd1351.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Solomon SSD1351 OLED Display Controller
+
+maintainers:
+  - Amit Barzilai <amit.barzilai22@gmail.com>
+  - Javier Martinez Canillas <javierm@redhat.com>
+
+allOf:
+  - $ref: solomon,ssd-common.yaml#
+
+properties:
+  compatible:
+    enum:
+      - solomon,ssd1351
+
+required:
+  - compatible
+  - reg
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    spi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        oled@0 {
+            compatible = "solomon,ssd1351";
+            reg = <0x0>;
+            reset-gpios = <&gpio2 7 GPIO_ACTIVE_LOW>;
+            dc-gpios = <&gpio2 8 GPIO_ACTIVE_HIGH>;
+            spi-max-frequency = <10000000>;
+        };
+    };
-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 2/4] drm/ssd130x: Add RGB565 support to SSD133X family
From: Amit Barzilai @ 2026-06-22 15:25 UTC (permalink / raw)
  To: javierm, maarten.lankhorst, mripard, tzimmermann, airlied, simona,
	robh, krzk+dt, conor+dt, andy, gregkh, deller
  Cc: azuddinadam, chintanlike, dri-devel, devicetree, linux-kernel,
	linux-fbdev, linux-staging, Amit Barzilai
In-Reply-To: <20260622152506.78627-1-amit.barzilai22@gmail.com>

SSD133X screens were getting 8bpp (RGB332) instead of the 16bpp
(RGB565) that they support. This change adds a boolean to the
deviceinfo struct selecting whether the variant is driven at
DRM_FORMAT_RGB565.

Changed SSD133X to now utilize 65k color (RGB565).

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Amit Barzilai <amit.barzilai22@gmail.com>
---
 drivers/gpu/drm/solomon/ssd130x.c | 55 +++++++++++++++++++++++++------
 drivers/gpu/drm/solomon/ssd130x.h |  7 ++++
 2 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c
index 04da4f2f7d08..2b0a8218f529 100644
--- a/drivers/gpu/drm/solomon/ssd130x.c
+++ b/drivers/gpu/drm/solomon/ssd130x.c
@@ -140,6 +140,12 @@
 #define SSD133X_SET_PRECHARGE_VOLTAGE		0xbb
 #define SSD133X_SET_VCOMH_VOLTAGE		0xbe
 
+/* ssd133x remap byte (data of SSD13XX_SET_SEG_REMAP) */
+#define SSD133X_SET_REMAP_COM_SPLIT		BIT(5)
+#define SSD133X_SET_REMAP_COLOR_DEPTH_MASK	GENMASK(7, 6)
+#define SSD133X_COLOR_DEPTH_256			0x0
+#define SSD133X_COLOR_DEPTH_65K			0x1
+
 #define MAX_CONTRAST 255
 
 const struct ssd130x_deviceinfo ssd130x_variants[] = {
@@ -206,6 +212,7 @@ const struct ssd130x_deviceinfo ssd130x_variants[] = {
 	[SSD1331_ID] = {
 		.default_width = 96,
 		.default_height = 64,
+		.format_rgb565 = 1,
 		.family_id = SSD133X_FAMILY,
 	}
 };
@@ -584,6 +591,10 @@ static int ssd132x_init(struct ssd130x_device *ssd130x)
 
 static int ssd133x_init(struct ssd130x_device *ssd130x)
 {
+	u8 remap = SSD133X_SET_REMAP_COM_SPLIT |
+		   FIELD_PREP(SSD133X_SET_REMAP_COLOR_DEPTH_MASK,
+			      ssd130x->device_info->format_rgb565 ?
+			      SSD133X_COLOR_DEPTH_65K : SSD133X_COLOR_DEPTH_256);
 	const u8 cmds[] = {
 		2, SSD133X_CONTRAST_A, 0x91,
 		2, SSD133X_CONTRAST_B, 0x50,
@@ -595,9 +606,9 @@ static int ssd133x_init(struct ssd130x_device *ssd130x)
 		 * Horizontal Address Increment
 		 * Normal order SA,SB,SC (e.g. RGB)
 		 * COM Split Odd Even
-		 * 256 color format
+		 * 256 or 65k color format, depending on the variant
 		 */
-		2, SSD13XX_SET_SEG_REMAP, 0x20,
+		2, SSD13XX_SET_SEG_REMAP, remap,
 		2, SSD133X_SET_DISPLAY_START, 0x00,
 		2, SSD133X_SET_DISPLAY_OFFSET, 0x00,
 		1, SSD133X_SET_DISPLAY_NORMAL,
@@ -794,14 +805,20 @@ static int ssd133x_update_rect(struct ssd130x_device *ssd130x,
 	 * COM0 to COM[N - 1] are the rows and SEG0 to SEG[M - 1] are
 	 * the columns.
 	 *
-	 * Each Segment has a 8-bit pixel and each Common output has a
-	 * row of pixels. When using the (default) horizontal address
-	 * increment mode, each byte of data sent to the controller has
-	 * a Segment (e.g: SEG0).
+	 * Each Segment holds one pixel and each Common output has a row
+	 * of pixels. A pixel is 8 bits (one byte) in the 256 color
+	 * (RGB332) format or 16 bits (two bytes) in the 65k color
+	 * (RGB565) format. When using the (default) horizontal address
+	 * increment mode, the pixel data is sent Segment by Segment
+	 * (e.g: SEG0 first).
 	 *
 	 * When using the 256 color depth format, each pixel contains 3
 	 * sub-pixels for color A, B and C. These have 3 bit, 3 bit and
 	 * 2 bits respectively.
+	 *
+	 * When using the 65k color depth format, each pixel contains 3
+	 * sub-pixels for color A, B and C. These have 5 bit, 6 bit and
+	 * 5 bits respectively.
 	 */
 
 	/* Set column start and end */
@@ -872,9 +889,24 @@ static void ssd132x_clear_screen(struct ssd130x_device *ssd130x, u8 *data_array)
 	ssd130x_write_data(ssd130x, data_array, columns * height);
 }
 
+/*
+ * The SSD133X family can drive the panel in either RGB332 (1 byte per pixel)
+ * or RGB565 (2 bytes per pixel). The format is a per-variant policy choice
+ * selected through ssd130x_deviceinfo::format_rgb565, not a capability probe.
+ * Centralize the choice here so that the buffer sizing (allocation, clear and
+ * blit pitch) can never disagree.
+ */
+static const struct drm_format_info *ssd133x_format_info(struct ssd130x_device *ssd130x)
+{
+	if (ssd130x->device_info->format_rgb565)
+		return drm_format_info(DRM_FORMAT_RGB565);
+
+	return drm_format_info(DRM_FORMAT_RGB332);
+}
+
 static void ssd133x_clear_screen(struct ssd130x_device *ssd130x, u8 *data_array)
 {
-	const struct drm_format_info *fi = drm_format_info(DRM_FORMAT_RGB332);
+	const struct drm_format_info *fi = ssd133x_format_info(ssd130x);
 	unsigned int pitch;
 
 	if (!fi)
@@ -945,7 +977,7 @@ static int ssd133x_fb_blit_rect(struct drm_framebuffer *fb,
 				struct drm_format_conv_state *fmtcnv_state)
 {
 	struct ssd130x_device *ssd130x = drm_to_ssd130x(fb->dev);
-	const struct drm_format_info *fi = drm_format_info(DRM_FORMAT_RGB332);
+	const struct drm_format_info *fi = ssd133x_format_info(ssd130x);
 	unsigned int dst_pitch;
 	struct iosys_map dst;
 	int ret = 0;
@@ -956,7 +988,10 @@ static int ssd133x_fb_blit_rect(struct drm_framebuffer *fb,
 	dst_pitch = drm_format_info_min_pitch(fi, 0, drm_rect_width(rect));
 
 	iosys_map_set_vaddr(&dst, data_array);
-	drm_fb_xrgb8888_to_rgb332(&dst, &dst_pitch, vmap, fb, rect, fmtcnv_state);
+	if (ssd130x->device_info->format_rgb565)
+		drm_fb_xrgb8888_to_rgb565be(&dst, &dst_pitch, vmap, fb, rect, fmtcnv_state);
+	else
+		drm_fb_xrgb8888_to_rgb332(&dst, &dst_pitch, vmap, fb, rect, fmtcnv_state);
 
 	ssd133x_update_rect(ssd130x, rect, data_array, dst_pitch);
 
@@ -1414,7 +1449,7 @@ static int ssd133x_crtc_atomic_check(struct drm_crtc *crtc,
 	struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
 	struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
 	struct ssd130x_crtc_state *ssd130x_state = to_ssd130x_crtc_state(crtc_state);
-	const struct drm_format_info *fi = drm_format_info(DRM_FORMAT_RGB332);
+	const struct drm_format_info *fi = ssd133x_format_info(ssd130x);
 	unsigned int pitch;
 	int ret;
 
diff --git a/drivers/gpu/drm/solomon/ssd130x.h b/drivers/gpu/drm/solomon/ssd130x.h
index a4554018bb2a..b0b487c06e04 100644
--- a/drivers/gpu/drm/solomon/ssd130x.h
+++ b/drivers/gpu/drm/solomon/ssd130x.h
@@ -54,6 +54,13 @@ struct ssd130x_deviceinfo {
 	bool need_pwm;
 	bool need_chargepump;
 	bool page_mode_only;
+	/*
+	 * Per-variant output format selector for the SSD133X data path. The
+	 * hardware can drive the panel in RGB332 (1 byte/pixel) or RGB565
+	 * (2 bytes/pixel); this is a policy choice per variant, not a
+	 * capability probe. When set, the variant is driven at RGB565.
+	 */
+	bool format_rgb565;
 
 	enum ssd130x_family_ids family_id;
 };
-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 3/4] drm/ssd130x: Add SSD135X_FAMILY and SSD1351 support
From: Amit Barzilai @ 2026-06-22 15:25 UTC (permalink / raw)
  To: javierm, maarten.lankhorst, mripard, tzimmermann, airlied, simona,
	robh, krzk+dt, conor+dt, andy, gregkh, deller
  Cc: azuddinadam, chintanlike, dri-devel, devicetree, linux-kernel,
	linux-fbdev, linux-staging, Amit Barzilai
In-Reply-To: <20260622152506.78627-1-amit.barzilai22@gmail.com>

The Solomon SSD1351 is a 128x128 RGB color OLED controller. It shares
the SSD133X data path: a column/row addressing window followed by a bulk
RGB565 pixel write. Add it as a new SSD135X_FAMILY rather than a separate
driver, reusing the SSD133X plane, CRTC and blit/clear helpers.

The only data-path difference is that the SSD1351 requires an explicit
Write RAM command (0x5c) after the address window is programmed, before
pixel data is accepted, whereas the SSD133X enters data mode implicitly.
This is emitted from a shared ssd133x_write_pixels() helper so both the
damage-update and clear-screen paths cover it.

The SSD1351 also needs its own init sequence (ssd135x_init), dispatched
via ssd135x_encoder_atomic_enable, and a longer post-reset settle delay.
The re-map byte is fixed at 0 degrees, 65k color, COM split, BGR
sub-pixel order; rotation is not supported.

The SSD1351 is SPI-only, so only the SPI transport match tables gain an
entry; no new config symbol is needed.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Amit Barzilai <amit.barzilai22@gmail.com>
---
 drivers/gpu/drm/solomon/ssd130x-spi.c |   7 +
 drivers/gpu/drm/solomon/ssd130x.c     | 214 +++++++++++++++++++++-----
 drivers/gpu/drm/solomon/ssd130x.h     |   5 +-
 3 files changed, 189 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/solomon/ssd130x-spi.c b/drivers/gpu/drm/solomon/ssd130x-spi.c
index b52f5fd592a1..6e0dd6e5a88d 100644
--- a/drivers/gpu/drm/solomon/ssd130x-spi.c
+++ b/drivers/gpu/drm/solomon/ssd130x-spi.c
@@ -146,6 +146,11 @@ static const struct of_device_id ssd130x_of_match[] = {
 		.compatible = "solomon,ssd1331",
 		.data = &ssd130x_variants[SSD1331_ID],
 	},
+	/* ssd135x family */
+	{
+		.compatible = "solomon,ssd1351",
+		.data = &ssd130x_variants[SSD1351_ID],
+	},
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, ssd130x_of_match);
@@ -171,6 +176,8 @@ static const struct spi_device_id ssd130x_spi_id[] = {
 	{ "ssd1327", SSD1327_ID },
 	/* ssd133x family */
 	{ "ssd1331", SSD1331_ID },
+	/* ssd135x family */
+	{ "ssd1351", SSD1351_ID },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(spi, ssd130x_spi_id);
diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c
index 2b0a8218f529..e5a9428f91b8 100644
--- a/drivers/gpu/drm/solomon/ssd130x.c
+++ b/drivers/gpu/drm/solomon/ssd130x.c
@@ -146,6 +146,33 @@
 #define SSD133X_COLOR_DEPTH_256			0x0
 #define SSD133X_COLOR_DEPTH_65K			0x1
 
+/* ssd135x commands */
+#define SSD135X_SET_COL_RANGE			0x15
+#define SSD135X_WRITE_RAM			0x5c
+#define SSD135X_SET_ROW_RANGE			0x75
+#define SSD135X_SET_DISPLAY_START		0xa1
+#define SSD135X_SET_DISPLAY_OFFSET		0xa2
+#define SSD135X_SET_DISPLAY_NORMAL		0xa6
+#define SSD135X_SET_FUNCTION			0xab
+#define SSD135X_SET_PHASE_LENGTH		0xb1
+#define SSD135X_SET_CLOCK_FREQ			0xb3
+#define SSD135X_SET_VSL				0xb4
+#define SSD135X_SET_GPIO			0xb5
+#define SSD135X_SET_PRECHARGE2			0xb6
+#define SSD135X_SET_PRECHARGE			0xbb
+#define SSD135X_SET_VCOMH_VOLTAGE		0xbe
+#define SSD135X_SET_CONTRAST			0xc1
+#define SSD135X_SET_CONTRAST_MASTER		0xc7
+#define SSD135X_SET_MUX_RATIO			0xca
+#define SSD135X_SET_COMMAND_LOCK		0xfd
+
+/* ssd135x remap byte (data of SSD13XX_SET_SEG_REMAP) */
+#define SSD135X_SET_REMAP_COLUMN		BIT(1)
+#define SSD135X_SET_REMAP_COLOR_BGR		BIT(2)
+#define SSD135X_SET_REMAP_COM_SCAN		BIT(4)
+#define SSD135X_SET_REMAP_COM_SPLIT		BIT(5)
+#define SSD135X_SET_REMAP_65K			BIT(6)
+
 #define MAX_CONTRAST 255
 
 const struct ssd130x_deviceinfo ssd130x_variants[] = {
@@ -214,6 +241,13 @@ const struct ssd130x_deviceinfo ssd130x_variants[] = {
 		.default_height = 64,
 		.format_rgb565 = 1,
 		.family_id = SSD133X_FAMILY,
+	},
+	/* ssd135x family */
+	[SSD1351_ID] = {
+		.default_width = 128,
+		.default_height = 128,
+		.format_rgb565 = 1,
+		.family_id = SSD135X_FAMILY,
 	}
 };
 EXPORT_SYMBOL_NS_GPL(ssd130x_variants, "DRM_SSD130X");
@@ -248,47 +282,16 @@ static inline struct ssd130x_device *drm_to_ssd130x(struct drm_device *drm)
 /*
  * Helper to write data (SSD13XX_DATA) to the device.
  */
-static int ssd130x_write_data(struct ssd130x_device *ssd130x, u8 *values, int count)
+static int ssd130x_write_data(struct ssd130x_device *ssd130x, const u8 *values, int count)
 {
 	return regmap_bulk_write(ssd130x->regmap, SSD13XX_DATA, values, count);
 }
 
-/*
- * Helper to write command (SSD13XX_COMMAND). The fist variadic argument
- * is the command to write and the following are the command options.
- *
- * Note that the ssd13xx protocol requires each command and option to be
- * written as a SSD13XX_COMMAND device register value. That is why a call
- * to regmap_write(..., SSD13XX_COMMAND, ...) is done for each argument.
- */
-static int ssd130x_write_cmd(struct ssd130x_device *ssd130x, int count,
-			     /* u8 cmd, u8 option, ... */...)
-{
-	va_list ap;
-	u8 value;
-	int ret;
-
-	va_start(ap, count);
-
-	do {
-		value = va_arg(ap, int);
-		ret = regmap_write(ssd130x->regmap, SSD13XX_COMMAND, value);
-		if (ret)
-			goto out_end;
-	} while (--count);
-
-out_end:
-	va_end(ap);
-
-	return ret;
-}
-
 /*
  * Write a command byte sequence from a buffer.
  *
- * Like ssd130x_write_cmd() but takes a pre-built byte array instead of
- * variadic arguments, handy when the command is already in an array or
- * when the caller wants to use sizeof() for the length.
+ * The first byte is the command opcode and the following bytes are its
+ * options/parameters.
  */
 static int ssd130x_write_cmds(struct ssd130x_device *ssd130x, const u8 *cmd,
 			      size_t len)
@@ -296,6 +299,22 @@ static int ssd130x_write_cmds(struct ssd130x_device *ssd130x, const u8 *cmd,
 	unsigned int i;
 	int ret;
 
+	/*
+	 * The SSD135X family latches command parameters with D/C# HIGH (i.e.
+	 * clocked in as data), unlike the other families where the opcode and
+	 * all of its parameters are sent as commands (D/C# LOW). Send the
+	 * opcode as a command and any following parameter bytes as data.
+	 */
+	if (ssd130x->device_info->family_id == SSD135X_FAMILY) {
+		if (len == 0)
+			return 0;
+		ret = regmap_write(ssd130x->regmap, SSD13XX_COMMAND, cmd[0]);
+		if (ret || len == 1)
+			return ret;
+
+		return ssd130x_write_data(ssd130x, cmd + 1, len - 1);
+	}
+
 	for (i = 0; i < len; i++) {
 		ret = regmap_write(ssd130x->regmap, SSD13XX_COMMAND, cmd[i]);
 		if (ret)
@@ -305,6 +324,28 @@ static int ssd130x_write_cmds(struct ssd130x_device *ssd130x, const u8 *cmd,
 	return 0;
 }
 
+/*
+ * Variadic wrapper around ssd130x_write_cmds(). The first variadic argument is
+ * the command opcode and the following ones are its options/parameters.
+ */
+static int ssd130x_write_cmd(struct ssd130x_device *ssd130x, int count,
+			     /* u8 cmd, u8 option, ... */...)
+{
+	u8 buf[8];
+	va_list ap;
+	int i;
+
+	if (count > ARRAY_SIZE(buf))
+		return -EINVAL;
+
+	va_start(ap, count);
+	for (i = 0; i < count; i++)
+		buf[i] = va_arg(ap, int);
+	va_end(ap);
+
+	return ssd130x_write_cmds(ssd130x, buf, count);
+}
+
 /*
  * Run a packed command sequence.  The format is a flat byte array where each
  * entry starts with a length byte followed by that many command bytes.  A
@@ -628,6 +669,49 @@ static int ssd133x_init(struct ssd130x_device *ssd130x)
 	return ssd130x_run_cmd_seq(ssd130x, cmds);
 }
 
+static int ssd135x_init(struct ssd130x_device *ssd130x)
+{
+	/*
+	 * Horizontal address increment, COM split, reversed COM scan direction,
+	 * BGR sub-pixel order and 65k (RGB565) color depth. Rotation is not
+	 * supported, so the remap byte is fixed.
+	 */
+	u8 remap = SSD135X_SET_REMAP_65K | SSD135X_SET_REMAP_COM_SPLIT |
+		   SSD135X_SET_REMAP_COLOR_BGR | SSD135X_SET_REMAP_COM_SCAN;
+	const u8 cmds[] = {
+		2, SSD135X_SET_COMMAND_LOCK, 0x12,
+		2, SSD135X_SET_COMMAND_LOCK, 0xb1,
+		1, SSD13XX_DISPLAY_OFF,
+		2, SSD135X_SET_CLOCK_FREQ, 0xf1,
+		2, SSD135X_SET_MUX_RATIO, ssd130x->height - 1,
+		3, SSD135X_SET_COL_RANGE, 0x00, ssd130x->width - 1,
+		3, SSD135X_SET_ROW_RANGE, 0x00, ssd130x->height - 1,
+		2, SSD135X_SET_DISPLAY_START, 0x00,
+		2, SSD135X_SET_DISPLAY_OFFSET, 0x00,
+		2, SSD135X_SET_GPIO, 0x00,
+		2, SSD135X_SET_FUNCTION, 0x01,
+		2, SSD135X_SET_PHASE_LENGTH, 0x32,
+		4, SSD135X_SET_VSL, 0xa0, 0xb5, 0x55,
+		2, SSD135X_SET_PRECHARGE, 0x17,
+		2, SSD135X_SET_VCOMH_VOLTAGE, 0x05,
+		4, SSD135X_SET_CONTRAST, 0xc8, 0x80, 0xc8,
+		2, SSD135X_SET_CONTRAST_MASTER, 0x0f,
+		2, SSD135X_SET_PRECHARGE2, 0x01,
+		1, SSD135X_SET_DISPLAY_NORMAL,
+		2, SSD13XX_SET_SEG_REMAP, remap,
+		0,
+	};
+
+	/*
+	 * ssd130x_power_on() issues a short reset pulse, but the SSD1351 is not
+	 * ready to accept commands immediately afterwards. Give the controller
+	 * time to settle before sending the init sequence.
+	 */
+	msleep(120);
+
+	return ssd130x_run_cmd_seq(ssd130x, cmds);
+}
+
 static int ssd130x_update_rect(struct ssd130x_device *ssd130x,
 			       struct drm_rect *rect, u8 *buf,
 			       u8 *data_array)
@@ -790,6 +874,25 @@ static int ssd132x_update_rect(struct ssd130x_device *ssd130x,
 	return ret;
 }
 
+/*
+ * Write a run of pixel data to the controller's display RAM. The SSD135X
+ * family requires an explicit Write RAM command once the address window has
+ * been set, before any pixel data is accepted; the SSD133X family enters data
+ * mode implicitly after the column/row range is programmed.
+ */
+static int ssd133x_write_pixels(struct ssd130x_device *ssd130x,
+				u8 *data_array, unsigned int count)
+{
+	if (ssd130x->device_info->family_id == SSD135X_FAMILY) {
+		int ret = ssd130x_write_cmd(ssd130x, 1, SSD135X_WRITE_RAM);
+
+		if (ret < 0)
+			return ret;
+	}
+
+	return ssd130x_write_data(ssd130x, data_array, count);
+}
+
 static int ssd133x_update_rect(struct ssd130x_device *ssd130x,
 			       struct drm_rect *rect, u8 *data_array,
 			       unsigned int pitch)
@@ -832,7 +935,7 @@ static int ssd133x_update_rect(struct ssd130x_device *ssd130x,
 		return ret;
 
 	/* Write out update in one go since horizontal addressing mode is used */
-	ret = ssd130x_write_data(ssd130x, data_array, pitch * rows);
+	ret = ssd133x_write_pixels(ssd130x, data_array, pitch * rows);
 
 	return ret;
 }
@@ -917,7 +1020,7 @@ static void ssd133x_clear_screen(struct ssd130x_device *ssd130x, u8 *data_array)
 	memset(data_array, 0, pitch * ssd130x->height);
 
 	/* Write out update in one go since horizontal addressing mode is used */
-	ssd130x_write_data(ssd130x, data_array, pitch * ssd130x->height);
+	ssd133x_write_pixels(ssd130x, data_array, pitch * ssd130x->height);
 }
 
 static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb,
@@ -1380,6 +1483,12 @@ static const struct drm_plane_helper_funcs ssd130x_primary_plane_helper_funcs[]
 		.atomic_check = ssd133x_primary_plane_atomic_check,
 		.atomic_update = ssd133x_primary_plane_atomic_update,
 		.atomic_disable = ssd133x_primary_plane_atomic_disable,
+	},
+	[SSD135X_FAMILY] = {
+		DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
+		.atomic_check = ssd133x_primary_plane_atomic_check,
+		.atomic_update = ssd133x_primary_plane_atomic_update,
+		.atomic_disable = ssd133x_primary_plane_atomic_disable,
 	}
 };
 
@@ -1534,6 +1643,10 @@ static const struct drm_crtc_helper_funcs ssd130x_crtc_helper_funcs[] = {
 		.mode_valid = ssd130x_crtc_mode_valid,
 		.atomic_check = ssd133x_crtc_atomic_check,
 	},
+	[SSD135X_FAMILY] = {
+		.mode_valid = ssd130x_crtc_mode_valid,
+		.atomic_check = ssd133x_crtc_atomic_check,
+	},
 };
 
 static const struct drm_crtc_funcs ssd130x_crtc_funcs = {
@@ -1621,6 +1734,31 @@ static void ssd133x_encoder_atomic_enable(struct drm_encoder *encoder,
 	ssd130x_power_off(ssd130x);
 }
 
+static void ssd135x_encoder_atomic_enable(struct drm_encoder *encoder,
+					  struct drm_atomic_commit *state)
+{
+	struct drm_device *drm = encoder->dev;
+	struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
+	int ret;
+
+	ret = ssd130x_power_on(ssd130x);
+	if (ret)
+		return;
+
+	ret = ssd135x_init(ssd130x);
+	if (ret)
+		goto power_off;
+
+	ssd130x_write_cmd(ssd130x, 1, SSD13XX_DISPLAY_ON);
+
+	backlight_enable(ssd130x->bl_dev);
+
+	return;
+
+power_off:
+	ssd130x_power_off(ssd130x);
+}
+
 static void ssd130x_encoder_atomic_disable(struct drm_encoder *encoder,
 					   struct drm_atomic_commit *state)
 {
@@ -1646,6 +1784,10 @@ static const struct drm_encoder_helper_funcs ssd130x_encoder_helper_funcs[] = {
 	[SSD133X_FAMILY] = {
 		.atomic_enable = ssd133x_encoder_atomic_enable,
 		.atomic_disable = ssd130x_encoder_atomic_disable,
+	},
+	[SSD135X_FAMILY] = {
+		.atomic_enable = ssd135x_encoder_atomic_enable,
+		.atomic_disable = ssd130x_encoder_atomic_disable,
 	}
 };
 
diff --git a/drivers/gpu/drm/solomon/ssd130x.h b/drivers/gpu/drm/solomon/ssd130x.h
index b0b487c06e04..da89d4455270 100644
--- a/drivers/gpu/drm/solomon/ssd130x.h
+++ b/drivers/gpu/drm/solomon/ssd130x.h
@@ -26,7 +26,8 @@
 enum ssd130x_family_ids {
 	SSD130X_FAMILY,
 	SSD132X_FAMILY,
-	SSD133X_FAMILY
+	SSD133X_FAMILY,
+	SSD135X_FAMILY
 };
 
 enum ssd130x_variants {
@@ -42,6 +43,8 @@ enum ssd130x_variants {
 	SSD1327_ID,
 	/* ssd133x family */
 	SSD1331_ID,
+	/* ssd135x family */
+	SSD1351_ID,
 	NR_SSD130X_VARIANTS
 };
 
-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 4/4] staging: fbtft: remove fb_ssd1351 driver
From: Amit Barzilai @ 2026-06-22 15:25 UTC (permalink / raw)
  To: javierm, maarten.lankhorst, mripard, tzimmermann, airlied, simona,
	robh, krzk+dt, conor+dt, andy, gregkh, deller
  Cc: azuddinadam, chintanlike, dri-devel, devicetree, linux-kernel,
	linux-fbdev, linux-staging, Amit Barzilai
In-Reply-To: <20260622152506.78627-1-amit.barzilai22@gmail.com>

The SSD1351 support was added to the ssd130x DRM driver. To avoid
confusion and irrelevant updates, the staging fb_ssd1351 driver is
removed.

Signed-off-by: Amit Barzilai <amit.barzilai22@gmail.com>
---
 drivers/staging/fbtft/Kconfig      |   5 -
 drivers/staging/fbtft/Makefile     |   1 -
 drivers/staging/fbtft/fb_ssd1351.c | 240 -----------------------------
 3 files changed, 246 deletions(-)
 delete mode 100644 drivers/staging/fbtft/fb_ssd1351.c

diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig
index 92943564cb91..c8ea1a0f3fb0 100644
--- a/drivers/staging/fbtft/Kconfig
+++ b/drivers/staging/fbtft/Kconfig
@@ -133,11 +133,6 @@ config FB_TFT_SSD1331
 	help
 	  Framebuffer support for SSD1331
 
-config FB_TFT_SSD1351
-	tristate "FB driver for the SSD1351 LCD Controller"
-	help
-	  Framebuffer support for SSD1351
-
 config FB_TFT_ST7735R
 	tristate "FB driver for the ST7735R LCD Controller"
 	help
diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile
index e9cdf0f0a7da..c230bf008fc7 100644
--- a/drivers/staging/fbtft/Makefile
+++ b/drivers/staging/fbtft/Makefile
@@ -28,7 +28,6 @@ obj-$(CONFIG_FB_TFT_SSD1305)     += fb_ssd1305.o
 obj-$(CONFIG_FB_TFT_SSD1306)     += fb_ssd1306.o
 obj-$(CONFIG_FB_TFT_SSD1305)     += fb_ssd1325.o
 obj-$(CONFIG_FB_TFT_SSD1331)     += fb_ssd1331.o
-obj-$(CONFIG_FB_TFT_SSD1351)     += fb_ssd1351.o
 obj-$(CONFIG_FB_TFT_ST7735R)     += fb_st7735r.o
 obj-$(CONFIG_FB_TFT_ST7789V)     += fb_st7789v.o
 obj-$(CONFIG_FB_TFT_TINYLCD)     += fb_tinylcd.o
diff --git a/drivers/staging/fbtft/fb_ssd1351.c b/drivers/staging/fbtft/fb_ssd1351.c
deleted file mode 100644
index 6736b09b2f45..000000000000
--- a/drivers/staging/fbtft/fb_ssd1351.c
+++ /dev/null
@@ -1,240 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-#include <linux/backlight.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/spi/spi.h>
-#include <linux/delay.h>
-#include <linux/string_choices.h>
-
-#include "fbtft.h"
-
-#define DRVNAME		"fb_ssd1351"
-#define WIDTH		128
-#define HEIGHT		128
-#define GAMMA_NUM	1
-#define GAMMA_LEN	63
-#define DEFAULT_GAMMA	"0 2 2 2 2 2 2 2 " \
-			"2 2 2 2 2 2 2 2 " \
-			"2 2 2 2 2 2 2 2 " \
-			"2 2 2 2 2 2 2 2 " \
-			"2 2 2 2 2 2 2 2 " \
-			"2 2 2 2 2 2 2 2 " \
-			"2 2 2 2 2 2 2 2 " \
-			"2 2 2 2 2 2 2" \
-
-static void register_onboard_backlight(struct fbtft_par *par);
-
-static int init_display(struct fbtft_par *par)
-{
-	if (par->pdata &&
-	    par->pdata->display.backlight == FBTFT_ONBOARD_BACKLIGHT) {
-		/* module uses onboard GPIO for panel power */
-		par->fbtftops.register_backlight = register_onboard_backlight;
-	}
-
-	par->fbtftops.reset(par);
-
-	write_reg(par, 0xfd, 0x12); /* Command Lock */
-	write_reg(par, 0xfd, 0xb1); /* Command Lock */
-	write_reg(par, 0xae); /* Display Off */
-	write_reg(par, 0xb3, 0xf1); /* Front Clock Div */
-	write_reg(par, 0xca, 0x7f); /* Set Mux Ratio */
-	write_reg(par, 0x15, 0x00, 0x7f); /* Set Column Address */
-	write_reg(par, 0x75, 0x00, 0x7f); /* Set Row Address */
-	write_reg(par, 0xa1, 0x00); /* Set Display Start Line */
-	write_reg(par, 0xa2, 0x00); /* Set Display Offset */
-	write_reg(par, 0xb5, 0x00); /* Set GPIO */
-	write_reg(par, 0xab, 0x01); /* Set Function Selection */
-	write_reg(par, 0xb1, 0x32); /* Set Phase Length */
-	write_reg(par, 0xb4, 0xa0, 0xb5, 0x55); /* Set Segment Low Voltage */
-	write_reg(par, 0xbb, 0x17); /* Set Precharge Voltage */
-	write_reg(par, 0xbe, 0x05); /* Set VComH Voltage */
-	write_reg(par, 0xc1, 0xc8, 0x80, 0xc8); /* Set Contrast */
-	write_reg(par, 0xc7, 0x0f); /* Set Master Contrast */
-	write_reg(par, 0xb6, 0x01); /* Set Second Precharge Period */
-	write_reg(par, 0xa6); /* Set Display Mode Reset */
-	write_reg(par, 0xaf); /* Set Sleep Mode Display On */
-
-	return 0;
-}
-
-static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
-{
-	write_reg(par, 0x15, xs, xe);
-	write_reg(par, 0x75, ys, ye);
-	write_reg(par, 0x5c);
-}
-
-static int set_var(struct fbtft_par *par)
-{
-	unsigned int remap;
-
-	if (par->fbtftops.init_display != init_display) {
-		/* don't risk messing up register A0h */
-		return 0;
-	}
-
-	remap = 0x60 | (par->bgr << 2); /* Set Colour Depth */
-
-	switch (par->info->var.rotate) {
-	case 0:
-		write_reg(par, 0xA0, remap | 0x00 | BIT(4));
-		break;
-	case 270:
-		write_reg(par, 0xA0, remap | 0x03 | BIT(4));
-		break;
-	case 180:
-		write_reg(par, 0xA0, remap | 0x02);
-		break;
-	case 90:
-		write_reg(par, 0xA0, remap | 0x01);
-		break;
-	}
-
-	return 0;
-}
-
-/*
- * Grayscale Lookup Table
- * GS1 - GS63
- * The driver Gamma curve contains the relative values between the entries
- * in the Lookup table.
- *
- * From datasheet:
- * 8.8 Gray Scale Decoder
- *
- *	there are total 180 Gamma Settings (Setting 0 to Setting 180)
- *	available for the Gray Scale table.
- *
- *	The gray scale is defined in incremental way, with reference
- *	to the length of previous table entry:
- *		Setting of GS1 has to be >= 0
- *		Setting of GS2 has to be > Setting of GS1 +1
- *		Setting of GS3 has to be > Setting of GS2 +1
- *		:
- *		Setting of GS63 has to be > Setting of GS62 +1
- *
- */
-static int set_gamma(struct fbtft_par *par, u32 *curves)
-{
-	unsigned long tmp[GAMMA_NUM * GAMMA_LEN];
-	int i, acc = 0;
-
-	for (i = 0; i < 63; i++) {
-		if (i > 0 && curves[i] < 2) {
-			dev_err(par->info->device,
-				"Illegal value in Grayscale Lookup Table at index %d : %d. Must be greater than 1\n",
-				i, curves[i]);
-			return -EINVAL;
-		}
-		acc += curves[i];
-		tmp[i] = acc;
-		if (acc > 180) {
-			dev_err(par->info->device,
-				"Illegal value(s) in Grayscale Lookup Table. At index=%d : %d, the accumulated value has exceeded 180\n",
-				i, acc);
-			return -EINVAL;
-		}
-	}
-
-	write_reg(par, 0xB8,
-		  tmp[0],  tmp[1],  tmp[2],  tmp[3],
-		  tmp[4],  tmp[5],  tmp[6],  tmp[7],
-		  tmp[8],  tmp[9],  tmp[10], tmp[11],
-		  tmp[12], tmp[13], tmp[14], tmp[15],
-		  tmp[16], tmp[17], tmp[18], tmp[19],
-		  tmp[20], tmp[21], tmp[22], tmp[23],
-		  tmp[24], tmp[25], tmp[26], tmp[27],
-		  tmp[28], tmp[29], tmp[30], tmp[31],
-		  tmp[32], tmp[33], tmp[34], tmp[35],
-		  tmp[36], tmp[37], tmp[38], tmp[39],
-		  tmp[40], tmp[41], tmp[42], tmp[43],
-		  tmp[44], tmp[45], tmp[46], tmp[47],
-		  tmp[48], tmp[49], tmp[50], tmp[51],
-		  tmp[52], tmp[53], tmp[54], tmp[55],
-		  tmp[56], tmp[57], tmp[58], tmp[59],
-		  tmp[60], tmp[61], tmp[62]);
-
-	return 0;
-}
-
-static int blank(struct fbtft_par *par, bool on)
-{
-	fbtft_par_dbg(DEBUG_BLANK, par, "(%s=%s)\n",
-		      __func__, str_true_false(on));
-	if (on)
-		write_reg(par, 0xAE);
-	else
-		write_reg(par, 0xAF);
-	return 0;
-}
-
-static struct fbtft_display display = {
-	.regwidth = 8,
-	.width = WIDTH,
-	.height = HEIGHT,
-	.gamma_num = GAMMA_NUM,
-	.gamma_len = GAMMA_LEN,
-	.gamma = DEFAULT_GAMMA,
-	.fbtftops = {
-		.init_display = init_display,
-		.set_addr_win = set_addr_win,
-		.set_var = set_var,
-		.set_gamma = set_gamma,
-		.blank = blank,
-	},
-};
-
-static int update_onboard_backlight(struct backlight_device *bd)
-{
-	struct fbtft_par *par = bl_get_data(bd);
-	bool on;
-
-	fbtft_par_dbg(DEBUG_BACKLIGHT, par, "%s: power=%d\n", __func__, bd->props.power);
-
-	on = !backlight_is_blank(bd);
-	/* Onboard backlight connected to GPIO0 on SSD1351, GPIO1 unused */
-	write_reg(par, 0xB5, on ? 0x03 : 0x02);
-
-	return 0;
-}
-
-static const struct backlight_ops bl_ops = {
-	.update_status = update_onboard_backlight,
-};
-
-static void register_onboard_backlight(struct fbtft_par *par)
-{
-	struct backlight_device *bd;
-	struct backlight_properties bl_props = { 0, };
-
-	bl_props.type = BACKLIGHT_RAW;
-	bl_props.power = BACKLIGHT_POWER_OFF;
-
-	bd = backlight_device_register(dev_driver_string(par->info->device),
-				       par->info->device, par, &bl_ops,
-				       &bl_props);
-	if (IS_ERR(bd)) {
-		dev_err(par->info->device,
-			"cannot register backlight device (%ld)\n",
-			PTR_ERR(bd));
-		return;
-	}
-	par->info->bl_dev = bd;
-
-	if (!par->fbtftops.unregister_backlight)
-		par->fbtftops.unregister_backlight = fbtft_unregister_backlight;
-}
-
-FBTFT_REGISTER_DRIVER(DRVNAME, "solomon,ssd1351", &display);
-
-MODULE_ALIAS("spi:" DRVNAME);
-MODULE_ALIAS("platform:" DRVNAME);
-MODULE_ALIAS("spi:ssd1351");
-MODULE_ALIAS("platform:ssd1351");
-
-MODULE_DESCRIPTION("SSD1351 OLED Driver");
-MODULE_AUTHOR("James Davies");
-MODULE_LICENSE("GPL");
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH v3 1/2] dt-bindings: iio: dac: Add AD5529R
From: David Lechner @ 2026-06-22 15:36 UTC (permalink / raw)
  To: Nuno Sá, Rodrigo Alencar
  Cc: Jonathan Cameron, Conor Dooley, Janani Sunil, Janani Sunil,
	Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
	Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Philipp Zabel, Jonathan Corbet, Shuah Khan, linux-iio, devicetree,
	linux-kernel, linux-doc, Mark Brown
In-Reply-To: <ajklksIDLsj0BZul@nsa>

On 6/22/26 7:20 AM, Nuno Sá wrote:
> On Mon, Jun 22, 2026 at 12:51:20PM +0100, Rodrigo Alencar wrote:
>> On 22/06/26 11:29, Nuno Sá wrote:
>>> On Mon, Jun 22, 2026 at 10:24:05AM +0100, Rodrigo Alencar wrote:
>>>> On 21/06/26 15:33, Jonathan Cameron wrote:
>>>>> On Fri, 19 Jun 2026 16:54:11 +0100
>>>>> Nuno Sá <noname.nuno@gmail.com> wrote:
>>>>>
>>>>>> On Fri, Jun 19, 2026 at 03:12:07PM +0100, Conor Dooley wrote:
>>>>>>> On Fri, Jun 19, 2026 at 02:01:08PM +0100, Nuno Sá wrote:  
>>>>>>>> On Fri, Jun 19, 2026 at 12:40:54PM +0100, Conor Dooley wrote:  
>>>>>>>>> On Fri, Jun 19, 2026 at 12:36:55PM +0100, Conor Dooley wrote:  
>>>>>>>>>> On Fri, Jun 19, 2026 at 12:33:11PM +0200, Janani Sunil wrote:  
>>>>>>>>>>>
>>>>>>>>>>> On 6/14/26 21:44, Jonathan Cameron wrote:  
>>>>>>>>>>>> On Tue, 9 Jun 2026 16:47:23 +0200
>>>>>>>>>>>> Janani Sunil <jan.sun97@gmail.com> wrote:
>>>>>>>>>>>>   
>>>>>>>>>>>>> On 5/26/26 15:11, Rodrigo Alencar wrote:  
>>>>>>>>>>>>>> On 26/05/19 05:42PM, Janani Sunil wrote:  
>>>>>>>>>>>>>>> Devicetree bindings for AD5529R 16 channel 12/16 bit high voltage,
>>>>>>>>>>>>>>> buffered voltage output digital-to-analog converter (DAC) with an
>>>>>>>>>>>>>>> integrated precision reference.  
>>>>>>>>>>>>>> ...
>>>>>>>>>>>>>> Probably others may comment on that, but...
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> This parent node may support device addressing for multi-device support through
>>>>>>>>>>>>>> those ID pins. I suppose that each device may have its own power supplies or
>>>>>>>>>>>>>> other resources like the toggle pins or reset and enable.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> That way I suppose that an example would look like...  
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +patternProperties:
>>>>>>>>>>>>>>> +  "^channel@([0-9]|1[0-5])$":
>>>>>>>>>>>>>>> +    type: object
>>>>>>>>>>>>>>> +    description: Child nodes for individual channel configuration
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +    properties:
>>>>>>>>>>>>>>> +      reg:
>>>>>>>>>>>>>>> +        description: Channel number.
>>>>>>>>>>>>>>> +        minimum: 0
>>>>>>>>>>>>>>> +        maximum: 15
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +      adi,output-range-microvolt:
>>>>>>>>>>>>>>> +        description: |
>>>>>>>>>>>>>>> +          Output voltage range for this channel as [min, max] in microvolts.
>>>>>>>>>>>>>>> +          If not specified, defaults to 0V to 5V range.
>>>>>>>>>>>>>>> +        oneOf:
>>>>>>>>>>>>>>> +          - items:
>>>>>>>>>>>>>>> +              - const: 0
>>>>>>>>>>>>>>> +              - enum: [5000000, 10000000, 20000000, 40000000]
>>>>>>>>>>>>>>> +          - items:
>>>>>>>>>>>>>>> +              - const: -5000000
>>>>>>>>>>>>>>> +              - const: 5000000
>>>>>>>>>>>>>>> +          - items:
>>>>>>>>>>>>>>> +              - const: -10000000
>>>>>>>>>>>>>>> +              - const: 10000000
>>>>>>>>>>>>>>> +          - items:
>>>>>>>>>>>>>>> +              - const: -15000000
>>>>>>>>>>>>>>> +              - const: 15000000
>>>>>>>>>>>>>>> +          - items:
>>>>>>>>>>>>>>> +              - const: -20000000
>>>>>>>>>>>>>>> +              - const: 20000000
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +    required:
>>>>>>>>>>>>>>> +      - reg
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +    additionalProperties: false
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +required:
>>>>>>>>>>>>>>> +  - compatible
>>>>>>>>>>>>>>> +  - reg
>>>>>>>>>>>>>>> +  - vdd-supply
>>>>>>>>>>>>>>> +  - avdd-supply
>>>>>>>>>>>>>>> +  - hvdd-supply
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +dependencies:
>>>>>>>>>>>>>>> +  spi-cpha: [ spi-cpol ]
>>>>>>>>>>>>>>> +  spi-cpol: [ spi-cpha ]
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +allOf:
>>>>>>>>>>>>>>> +  - $ref: /schemas/spi/spi-peripheral-props.yaml#
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +unevaluatedProperties: false
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +examples:
>>>>>>>>>>>>>>> +  - |
>>>>>>>>>>>>>>> +    #include <dt-bindings/gpio/gpio.h>
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +    spi {
>>>>>>>>>>>>>>> +        #address-cells = <1>;
>>>>>>>>>>>>>>> +        #size-cells = <0>;
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +        dac@0 {
>>>>>>>>>>>>>>> +            compatible = "adi,ad5529r-16";
>>>>>>>>>>>>>>> +            reg = <0>;
>>>>>>>>>>>>>>> +            spi-max-frequency = <25000000>;
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +            vdd-supply = <&vdd_regulator>;
>>>>>>>>>>>>>>> +            avdd-supply = <&avdd_regulator>;
>>>>>>>>>>>>>>> +            hvdd-supply = <&hvdd_regulator>;
>>>>>>>>>>>>>>> +            hvss-supply = <&hvss_regulator>;
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +            reset-gpios = <&gpio0 87 GPIO_ACTIVE_LOW>;
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +            #address-cells = <1>;
>>>>>>>>>>>>>>> +            #size-cells = <0>;
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +            channel@0 {
>>>>>>>>>>>>>>> +                reg = <0>;
>>>>>>>>>>>>>>> +                adi,output-range-microvolt = <0 5000000>;
>>>>>>>>>>>>>>> +            };
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +            channel@1 {
>>>>>>>>>>>>>>> +                reg = <1>;
>>>>>>>>>>>>>>> +                adi,output-range-microvolt = <(-10000000) 10000000>;
>>>>>>>>>>>>>>> +            };
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +            channel@2 {
>>>>>>>>>>>>>>> +                reg = <2>;
>>>>>>>>>>>>>>> +                adi,output-range-microvolt = <0 40000000>;
>>>>>>>>>>>>>>> +            };
>>>>>>>>>>>>>>> +        };
>>>>>>>>>>>>>>> +    };  
>>>>>>>>>>>>>> ...
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 	spi {
>>>>>>>>>>>>>> 		#address-cells = <1>;
>>>>>>>>>>>>>> 		#size-cells = <0>;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 		multi-dac@0 {
>>>>>>>>>>>>>> 			compatible = "adi,ad5529r-16";
>>>>>>>>>>>>>> 			reg = <0>;
>>>>>>>>>>>>>> 			spi-max-frequency = <25000000>;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 			#address-cells = <1>;
>>>>>>>>>>>>>> 			#size-cells = <0>;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 			dac@0 {
>>>>>>>>>>>>>> 				reg = <0>;
>>>>>>>>>>>>>> 				vdd-supply = <&vdd_regulator>;
>>>>>>>>>>>>>> 				avdd-supply = <&avdd_regulator>;
>>>>>>>>>>>>>> 				hvdd-supply = <&hvdd_regulator>;
>>>>>>>>>>>>>> 				hvss-supply = <&hvss_regulator>;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 				reset-gpios = <&gpio0 87 GPIO_ACTIVE_LOW>;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 				#address-cells = <1>;
>>>>>>>>>>>>>> 				#size-cells = <0>;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 				channel@0 {
>>>>>>>>>>>>>> 					reg = <0>;
>>>>>>>>>>>>>> 					adi,output-range-microvolt = <0 5000000>;
>>>>>>>>>>>>>> 				};
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 				channel@1 {
>>>>>>>>>>>>>> 					reg = <1>;
>>>>>>>>>>>>>> 					adi,output-range-microvolt = <(-10000000) 10000000>;
>>>>>>>>>>>>>> 				};
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 				channel@2 {
>>>>>>>>>>>>>> 					reg = <2>;
>>>>>>>>>>>>>> 					adi,output-range-microvolt = <0 40000000>;
>>>>>>>>>>>>>> 				};
>>>>>>>>>>>>>> 			}
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 			dac@1 {
>>>>>>>>>>>>>> 				reg = <1>;
>>>>>>>>>>>>>> 				vdd-supply = <&vdd_regulator>;
>>>>>>>>>>>>>> 				avdd-supply = <&avdd_regulator>;
>>>>>>>>>>>>>> 				hvdd-supply = <&hvdd_regulator>;
>>>>>>>>>>>>>> 				hvss-supply = <&hvss_regulator>;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 				reset-gpios = <&gpio0 88 GPIO_ACTIVE_LOW>;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 				#address-cells = <1>;
>>>>>>>>>>>>>> 				#size-cells = <0>;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 				channel@0 {
>>>>>>>>>>>>>> 					reg = <0>;
>>>>>>>>>>>>>> 					adi,output-range-microvolt = <0 5000000>;
>>>>>>>>>>>>>> 				};
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 				channel@1 {
>>>>>>>>>>>>>> 					reg = <1>;
>>>>>>>>>>>>>> 					adi,output-range-microvolt = <(-10000000) 10000000>;
>>>>>>>>>>>>>> 				};
>>>>>>>>>>>>>> 			}
>>>>>>>>>>>>>> 		};
>>>>>>>>>>>>>> 	};
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> then you might need something like:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 	patternProperties:
>>>>>>>>>>>>>> 		"^dac@[0-3]$":
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> and put most of the things under this node pattern.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> So the main driver that you're putting together might need to handle up to four instances.
>>>>>>>>>>>>>> Even if your current driver cannot handle this, the dt-bindings might need cover that.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Need to double check if each dac node needs a separate compatible, so you would maybe populate
>>>>>>>>>>>>>> a platform data to be shared with the child nodes, which would be a separate driver.
>>>>>>>>>>>>>> (not sure if it would make sense to mix and match ad5529r-16 and ad5529r-12).  
>>>>>>>>>>>>> Hi Rodrigo,
>>>>>>>>>>>>>
>>>>>>>>>>>>> Thank you for looking at this.
>>>>>>>>>>>>>
>>>>>>>>>>>>> For now, I would prefer to keep the binding scoped to a single AD5529R device instance. The current
>>>>>>>>>>>>> hardware/use case we have only needs one device node and the driver is written around that model as well.
>>>>>>>>>>>>> While the device addressing pins could allow multi-device topology, we do not have an actual platform using
>>>>>>>>>>>>> that configuration at the moment, so I would prefer not to introduce an extra parent/child binding structure
>>>>>>>>>>>>> speculatively without a validating use case.  
>>>>>>>>>>>> Interesting feature - kind of similar to address control on a typical i2c bus device, or
>>>>>>>>>>>> looking at it another way a kind of distributed SPI mux.
>>>>>>>>>>>>
>>>>>>>>>>>> Challenge of a binding is we need to anticipate the future.  So I think we do need something
>>>>>>>>>>>> like Rodrigo is suggesting even if we only (for now) support a single instance in the driver.
>>>>>>>>>>>> That would leave the path open to supporting the addressing at a later date.
>>>>>>>>>>>> An alternative might be to look at it like a chained device setup. In those we pretend there
>>>>>>>>>>>> is just one device with a lot of channels etc.  The snag is that here things are more loosely
>>>>>>>>>>>> coupled whereas for those devices it tends to be you have to read / write the same register
>>>>>>>>>>>> in all devices in the chain as one big SPI message.
>>>>>>>>>>>>
>>>>>>>>>>>> +CC Mark Brown as he may know of some precedence for this feature. For his reference..
>>>>>>>>>>>> - Each of these device has 2 ID pins.  The SPI transfers have to contain the 2 bit
>>>>>>>>>>>> value that matches that or they are ignored.  Thus a single bus + 1 chip select can
>>>>>>>>>>>> be used to talk to 4 devices.  Question is what that looks like in device tree + I guess
>>>>>>>>>>>> longer term how to support it cleanly in SPI.  
>>>>>>>>>>
>>>>>>>>>> I'd swear I have seen this before, from some Microchip devices. Let me
>>>>>>>>>> see if I can find what I am thinking of...  
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> microchip,mcp3911 and microchip,mcp3564 both seem to do this with
>>>>>>>>> slightly different properties.
>>>>>>>>>
>>>>>>>>>   microchip,device-addr:
>>>>>>>>>     description: Device address when multiple MCP3911 chips are present on the same SPI bus.
>>>>>>>>>     $ref: /schemas/types.yaml#/definitions/uint32
>>>>>>>>>     enum: [0, 1, 2, 3]
>>>>>>>>>     default: 0
>>>>>>>>>
>>>>>>>>> and
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>   microchip,hw-device-address:
>>>>>>>>>     $ref: /schemas/types.yaml#/definitions/uint32
>>>>>>>>>     minimum: 0
>>>>>>>>>     maximum: 3
>>>>>>>>>     description:
>>>>>>>>>       The address is set on a per-device basis by fuses in the factory,
>>>>>>>>>       configured on request. If not requested, the fuses are set for 0x1.
>>>>>>>>>       The device address is part of the device markings to avoid
>>>>>>>>>       potential confusion. This address is coded on two bits, so four possible
>>>>>>>>>       addresses are available when multiple devices are present on the same
>>>>>>>>>       SPI bus with only one Chip Select line for all devices.
>>>>>>>>>       Each device communication starts by a CS falling edge, followed by the
>>>>>>>>>       clocking of the device address (BITS[7:6] - top two bits of COMMAND BYTE
>>>>>>>>>       which is first one on the wire).
>>>>>>>>>
>>>>>>>>> This sounds exactly like the sort of feature that you're dealing with
>>>>>>>>> here?
>>>>>>>>>   
>>>>>>>>
>>>>>>>> The core idea yes but for this chip, things are a bit more annoying (but
>>>>>>>> Janani can correct me if I'm wrong). Here, each device can, in theory,
>>>>>>>> have it's own supplies, pins and at the very least, channels with maybe
>>>>>>>> different scales. That is why Janani is proposing dac nodes. Given I
>>>>>>>> honestly don't like much of that "adi,ad5529r-bus" compatible I wondered
>>>>>>>> about solving this at the spi level.
>>>>>>>>
>>>>>>>> Ah and to make it more annoying, we can also mix 12 and 16 bits variants
>>>>>>>> together in the same bus.  
>>>>>>>
>>>>>>> I'm definitely missing something, because that property for the
>>>>>>> microchip devices is not impacted what else is on the bus. AFAICT, you
>>>>>>> could have an mcp3911 and an mcp3564 on the same bus even though both
>>>>>>> are completely different devices with different drivers. They have
>>>>>>> individual device nodes and their own supplies etc etc. These aren't
>>>>>>> per-channel properties on an adc or dac, they're per child device on a
>>>>>>> spi bus.  
>>>>>>
>>>>>> Maybe I'm the one missing something :). IIRC, spi would not allow two
>>>>>> devices on the same CS right? Because for this chip we would need
>>>>>> something like:
>>>>>>
>>>>>> spi {
>>>>>> 	dac@0 {
>>>>>> 		reg = <0>;
>>>>>> 		adi,pin-id = <0>;
>>>>>> 	};
>>>>>>
>>>>>> 	dac@1 {
>>>>>> 		reg = <0>; // which seems already problematic?
>>>>>> 		adi,pin-id <1>;
>>>>>> 	};
>>>>>>
>>>>>> 	...
>>>>>>
>>>>>> 	//up to 4
>>>>>> };
>>>>> Yeah. It's not clear to me how that works for the microchip devices
>>>>> (I suspect it doesn't!)
>>>>>
>>>>> Just thinking as I type, but could we do something a bit nasty with
>>>>> a gpio mux that doesn't actually switch but represents the GPIO being
>>>>> shared?  Given this is all tied to the spi bus that should all happen
>>>>> under serializing locks. 
>>>>>
>>>>> Agreed though that this would be nicer as an SPI thing that let
>>>>> us specify that a single CS is share by multiple devices and their
>>>>> is some other signal acting to select which one we are talking to.
>>>>>
>>>>
>>>> If the device-addressing on the same chip-select is to be handled
>>>> by the spi framework, wouldn't we lose device-specific features?
>>>>
>>>> I understand that this multi-device feature is there mostly to extend the
>>>> channel count from 16 to 32, 48 or 64. I suppose the command:
>>>>
>>>> 	"MULTI DEVICE SW LDAC MODE"
>>>>
>>>> exists so that software can update channel values accross multiple devices.
>>>
>>> Right! You do have a point! I agree the main driver for a feature like
>>> this is likely to extend the channel count and effectively "aggregate"
>>> devices.
>>>
>>> But I would say that even with the spi solution the MULTI DEVICE stuff
>>> should be doable (as we still need a sort of adi,pin-id property). 
>>
>> I don't think we can have something like an IIO buffer shared by multiple
>> devices. Synchronizing separate devices would be doable with proper hardware
>> support for this (probably involving an FGPA).
> 
> True!
> 
>>  
>>> But yes, I do feel that the whole feature is for aggregation so seeing
>>> one device with 32 channels is the expectation here? Rather than seeing
>>> two devices with 16 channels.
>>
>> Yes, I think aggregation is the whole point there... so that the IIO driver
>> is multi-device-aware.
> 
> Which makes me feel that different pins per device might be possible
> from an HW point of view but does not make much sense. For example, for
> the buffer example I would expect LDAC to be shared between all the
> devices.
> 
> - Nuno Sá

I think I mentioned this on a previous revision, but I still think the
simplest way to go about it would be to assume that all chips treated
as an aggregate device have everything wired in parallel and just add
support for per-chip wiring on an as-needed basis. This is how we have
handled daisy-chained devices so far.


^ permalink raw reply

* Re: [PATCH 2/8] power: sequencing: pcie-m2: Add PCI ID for NXP 88W9098 and AW693 Bluetooth
From: Manivannan Sadhasivam @ 2026-06-22 15:42 UTC (permalink / raw)
  To: Sherry Sun (OSS)
  Cc: robh, krzk+dt, conor+dt, Frank.Li, s.hauer, kernel, festevam,
	amitkumar.karwar, neeraj.sanjaykale, marcel, luiz.dentz,
	hongxing.zhu, l.stach, lpieralisi, kwilczynski, bhelgaas, brgl,
	imx, linux-pci, linux-arm-kernel, devicetree, linux-kernel,
	linux-bluetooth, linux-pm, sherry.sun
In-Reply-To: <20260618101047.4185497-3-sherry.sun@oss.nxp.com>

On Thu, Jun 18, 2026 at 06:10:41PM +0800, Sherry Sun (OSS) wrote:
> From: Sherry Sun <sherry.sun@nxp.com>
> 
> 88W9098 is a NXP Wi-Fi/BT combo chip with PCI device ID 0x2b43 under
> Marvell Extended vendor ID. AW693 is a NXP Wi-Fi/BT combo chip with
> PCI device ID 0x3003 under NXP/Philips vendor ID.
> 
> Add both chips to pwrseq_m2_pci_ids[] so that the pwrseq-pcie-m2 driver
> can create the Bluetooth serdev device when these cards are inserted into
> a PCIe M.2 Key E connector.
> 
> Both chips use "nxp,88w8987-bt" as the serdev compatible string, which
> is the entry point for the btnxpuart driver. The driver identifies the
> actual chip variant at runtime via chip ID auto-detection and loads the
> appropriate firmware accordingly.
> 
> Signed-off-by: Sherry Sun <sherry.sun@nxp.com>

Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>

- Mani

> ---
>  drivers/power/sequencing/pwrseq-pcie-m2.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/power/sequencing/pwrseq-pcie-m2.c b/drivers/power/sequencing/pwrseq-pcie-m2.c
> index 94c3f4b7ee36..9217ffcfa6e5 100644
> --- a/drivers/power/sequencing/pwrseq-pcie-m2.c
> +++ b/drivers/power/sequencing/pwrseq-pcie-m2.c
> @@ -186,6 +186,10 @@ static int pwrseq_pcie_m2_match(struct pwrseq_device *pwrseq,
>  }
>  
>  static const struct pci_device_id pwrseq_m2_pci_ids[] = {
> +	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x2b43),
> +	  .driver_data = (kernel_ulong_t)"nxp,88w8987-bt" },
> +	{ PCI_DEVICE(PCI_VENDOR_ID_PHILIPS, 0x3003),
> +	  .driver_data = (kernel_ulong_t)"nxp,88w8987-bt" },
>  	{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x1107),
>  	  .driver_data = (kernel_ulong_t)"qcom,wcn7850-bt" },
>  	{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x1103),
> -- 
> 2.50.1
> 

-- 
மணிவண்ணன் சதாசிவம்

^ permalink raw reply

* Re: [PATCH v2 0/2] iio: temperature: Add support for the STS30 temperature sensor
From: David Lechner @ 2026-06-22 15:45 UTC (permalink / raw)
  To: Maxwell Doose, Jonathan Cameron, Nuno Sá, Andy Shevchenko,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	open list:IIO SUBSYSTEM AND DRIVERS,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list
In-Reply-To: <20260621004626.66629-1-m32285159@gmail.com>

On 6/20/26 7:46 PM, Maxwell Doose wrote:
> Hi all,
> 
> This patch series adds support for the Sensirion STS30 temperature
> sensor family. This driver currently supports non clock stretched single
> shot measurements.
> 
> Given there were very little issues found with the v1 submission, I've
> decided to make this a regular patch series rather than an RFC patch.

You should wait at least one week for feedback on a new driver before
submitting the next revision.

Given that you said in v1 that don't actually have the hardware, I am not
going to review this. We are getting more patches than I can keep up with
already.

> 
> Changes since v1:
> * whole series:
> - Squashed MAINTAINERS updates into both the dt-bindings commit and the
>   driver commit.
> 

^ 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