* Re: [PATCH RFC 06/10] arm64: dts: qcom: msm8939-asus-z00t: add Venus
From: André Apitzsch @ 2026-04-19 20:26 UTC (permalink / raw)
To: Dmitry Baryshkov, Erikas Bitovtas
Cc: Konrad Dybcio, Bryan O'Donoghue, Vikash Garodia,
Dikshita Agarwal, Mauro Carvalho Chehab, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio,
Michael Turquette, Stephen Boyd, linux-media, linux-arm-msm,
devicetree, linux-kernel, linux-clk, ~postmarketos/upstreaming,
phone-devel
In-Reply-To: <37poakqgqhsuavvrm2dyzwk36syyq44o4cfdsylkzwsupbh2yt@ycdvyrxgnrcs>
Hi Dmitry,
Am Samstag, dem 18.04.2026 um 02:40 +0300 schrieb Dmitry Baryshkov:
> On Thu, Apr 16, 2026 at 07:57:30PM +0300, Erikas Bitovtas wrote:
> >
> >
> > On 4/16/26 6:17 PM, Konrad Dybcio wrote:
> > > On 4/16/26 3:43 PM, Erikas Bitovtas wrote:
> > > > Enable Venus video encoder/decoder for Asus ZenFone 2
> > > > Laser/Selfie.
> > > >
> > > > Signed-off-by: Erikas Bitovtas <xerikasxx@gmail.com>
> > > > ---
> > > > arch/arm64/boot/dts/qcom/msm8939-asus-z00t.dts | 8 ++++++++
> > > > 1 file changed, 8 insertions(+)
> > > >
> > > > diff --git a/arch/arm64/boot/dts/qcom/msm8939-asus-z00t.dts
> > > > b/arch/arm64/boot/dts/qcom/msm8939-asus-z00t.dts
> > > > index 90e966242720..231a3e9c1929 100644
> > > > --- a/arch/arm64/boot/dts/qcom/msm8939-asus-z00t.dts
> > > > +++ b/arch/arm64/boot/dts/qcom/msm8939-asus-z00t.dts
> > > > @@ -267,6 +267,14 @@ &usb_hs_phy {
> > > > extcon = <&usb_id>;
> > > > };
> > > >
> > > > +&venus {
> > > > + status = "okay";
> > >
> > > You need a firmware path here
> >
> > When I tested Venus on my device, it loaded without one specified -
> > msm-firmware-loader creates a symbolic link from modem partition
> > for firmware. Additionally, none of the MSM8916 devices seem to
> > include a firmware name. Has something changed since then?
>
> Us becoming more strict? Or more caring? The default file paths are
> supposed to be used for unfused devices. So if they don't work with
> yours (most likely they don't), please add firmware-name:
>
> firmware-name = "qcom/msm8916/Asus/z00t/venus.mbn";
For BQ M5 (msm8939-longcheer-l9100), venus works with the firmware
provided by linux-firmware [1] and the default path (here "qcom/venus-
1.8/venus.mbn").
Just to be clear, should the firmware-name still be added in this case,
even if it is the default one?
Best regards,
André
[1] https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/qcom/venus-1.8
^ permalink raw reply
* Re: [PATCH v2 07/21] drm/panel: himax-hx83102: support Waveshare 12.3" DSI panel
From: Linus Walleij @ 2026-04-19 20:18 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Neil Armstrong, Jessica Zhang, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
Bartosz Golaszewski, dri-devel, devicetree, linux-kernel,
linux-gpio
In-Reply-To: <20260411-waveshare-dsi-touch-v2-7-75cdbeac5156@oss.qualcomm.com>
On Sat, Apr 11, 2026 at 2:11 PM Dmitry Baryshkov
<dmitry.baryshkov@oss.qualcomm.com> wrote:
> Add support for the Waveshare 12.3" DSI TOUCH-A panel. According to the
> vendor driver, it uses different mode_flags, so let the panel
> descriptions override driver-wide defaults.
>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Acked-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v2 17/21] drm/panel: ilitek-ili9881c: support Waveshare 7.0" DSI panel
From: Linus Walleij @ 2026-04-19 20:17 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Neil Armstrong, Jessica Zhang, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
Bartosz Golaszewski, dri-devel, devicetree, linux-kernel,
linux-gpio
In-Reply-To: <20260411-waveshare-dsi-touch-v2-17-75cdbeac5156@oss.qualcomm.com>
On Sat, Apr 11, 2026 at 2:11 PM Dmitry Baryshkov
<dmitry.baryshkov@oss.qualcomm.com> wrote:
> Enable support for Waveshare 7.0" DSI TOUCH-A panel. It requires
> additional voltage regulator, iovcc.
>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v2 16/21] drm/panel: jadard-jd9365da-h3: support Waveshare 720p DSI panels
From: Linus Walleij @ 2026-04-19 20:16 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Neil Armstrong, Jessica Zhang, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
Bartosz Golaszewski, dri-devel, devicetree, linux-kernel,
linux-gpio, Riccardo Mereu
In-Reply-To: <20260411-waveshare-dsi-touch-v2-16-75cdbeac5156@oss.qualcomm.com>
On Sat, Apr 11, 2026 at 2:11 PM Dmitry Baryshkov
<dmitry.baryshkov@oss.qualcomm.com> wrote:
> Add configuration for Waveshare 9.0" and 10.1" 720p DSI panels using
> JD9365 controller.
>
> Tested-by: Riccardo Mereu <r.mereu@arduino.cc>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v2 15/21] drm/panel: jadard-jd9365da-h3: support Waveshare WXGA DSI panels
From: Linus Walleij @ 2026-04-19 20:16 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Neil Armstrong, Jessica Zhang, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
Bartosz Golaszewski, dri-devel, devicetree, linux-kernel,
linux-gpio, Riccardo Mereu
In-Reply-To: <20260411-waveshare-dsi-touch-v2-15-75cdbeac5156@oss.qualcomm.com>
On Sat, Apr 11, 2026 at 2:11 PM Dmitry Baryshkov
<dmitry.baryshkov@oss.qualcomm.com> wrote:
> Add configuration for several Waveshare 8.0" and 10.1" WXGA DSI panels
> using JD9365 controller
>
> Tested-by: Riccardo Mereu <r.mereu@arduino.cc>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v2 14/21] drm/panel: jadard-jd9365da-h3: support Waveshare round DSI panels
From: Linus Walleij @ 2026-04-19 20:16 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Neil Armstrong, Jessica Zhang, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
Bartosz Golaszewski, dri-devel, devicetree, linux-kernel,
linux-gpio, Riccardo Mereu
In-Reply-To: <20260411-waveshare-dsi-touch-v2-14-75cdbeac5156@oss.qualcomm.com>
On Sat, Apr 11, 2026 at 2:11 PM Dmitry Baryshkov
<dmitry.baryshkov@oss.qualcomm.com> wrote:
> Add configuration for Waveshare 3.4" and 4.0" round DSI panels using
> JD9365 controller.
>
> Tested-by: Riccardo Mereu <r.mereu@arduino.cc>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH v2 2/3] counter: add GPIO-based quadrature encoder driver
From: Wadim Mueller @ 2026-04-19 19:59 UTC (permalink / raw)
To: linux-iio, devicetree
Cc: wbg, conor+dt, krzk+dt, robh, linux-kernel, Wadim Mueller
In-Reply-To: <20260419195908.12202-1-wafgo01@gmail.com>
Add a platform driver that turns ordinary GPIOs into a quadrature
encoder counter device. The driver requests edge-triggered interrupts
on the A and B (and optional Index) GPIOs and decodes the quadrature
signal in software using a classic state-table approach.
Supported counting modes:
- Quadrature X1 (count on A rising edge only)
- Quadrature X2 (count on both A edges)
- Quadrature X4 (count on every A and B edge)
- Pulse-direction (A = pulse, B = direction)
An optional index signal resets the count to zero on its rising edge
when enabled through sysfs. A configurable ceiling clamps the count
to [0, ceiling].
Signed-off-by: Wadim Mueller <wafgo01@gmail.com>
---
drivers/counter/Kconfig | 15 +
drivers/counter/Makefile | 1 +
drivers/counter/gpio-quadrature-encoder.c | 710 ++++++++++++++++++++++
3 files changed, 726 insertions(+)
create mode 100644 drivers/counter/gpio-quadrature-encoder.c
diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig
index d30d22dfe..72c5c8159 100644
--- a/drivers/counter/Kconfig
+++ b/drivers/counter/Kconfig
@@ -68,6 +68,21 @@ config INTEL_QEP
To compile this driver as a module, choose M here: the module
will be called intel-qep.
+config GPIO_QUADRATURE_ENCODER
+ tristate "GPIO-based quadrature encoder counter driver"
+ depends on GPIOLIB
+ help
+ Select this option to enable the GPIO-based quadrature encoder
+ counter driver. It reads A/B quadrature signals and an optional
+ index pulse via edge-triggered GPIO interrupts, supporting X1, X2,
+ X4 quadrature decoding and pulse-direction mode.
+
+ This is useful on SoCs that lack a dedicated hardware quadrature
+ decoder or where the encoder is wired to generic GPIO pins.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gpio-quadrature-encoder.
+
config INTERRUPT_CNT
tristate "Interrupt counter driver"
depends on GPIOLIB
diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile
index fa3c1d08f..2bef64d10 100644
--- a/drivers/counter/Makefile
+++ b/drivers/counter/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_STM32_TIMER_CNT) += stm32-timer-cnt.o
obj-$(CONFIG_STM32_LPTIMER_CNT) += stm32-lptimer-cnt.o
obj-$(CONFIG_TI_EQEP) += ti-eqep.o
obj-$(CONFIG_FTM_QUADDEC) += ftm-quaddec.o
+obj-$(CONFIG_GPIO_QUADRATURE_ENCODER) += gpio-quadrature-encoder.o
obj-$(CONFIG_MICROCHIP_TCB_CAPTURE) += microchip-tcb-capture.o
obj-$(CONFIG_INTEL_QEP) += intel-qep.o
obj-$(CONFIG_TI_ECAP_CAPTURE) += ti-ecap-capture.o
diff --git a/drivers/counter/gpio-quadrature-encoder.c b/drivers/counter/gpio-quadrature-encoder.c
new file mode 100644
index 000000000..0822f0a8a
--- /dev/null
+++ b/drivers/counter/gpio-quadrature-encoder.c
@@ -0,0 +1,710 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * GPIO-based Quadrature Encoder Counter Driver
+ *
+ * Reads quadrature encoder signals (A, B, and optional Index) via GPIOs.
+ * Supports X1, X2, X4 quadrature decoding and pulse-direction mode.
+ *
+ * Copyright (C) 2026 CMBlu Energy AG
+ * Author: Wadim Mueller <wafgo01@gmail.com>
+ */
+
+#include <linux/counter.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+enum gpio_qenc_function {
+ GPIO_QENC_FUNC_QUAD_X1 = 0,
+ GPIO_QENC_FUNC_QUAD_X2,
+ GPIO_QENC_FUNC_QUAD_X4,
+ GPIO_QENC_FUNC_PULSE_DIR,
+};
+
+enum gpio_qenc_signal_id {
+ GPIO_QENC_SIGNAL_A = 0,
+ GPIO_QENC_SIGNAL_B,
+ GPIO_QENC_SIGNAL_INDEX,
+};
+
+struct gpio_qenc_priv {
+ struct gpio_desc *gpio_a;
+ struct gpio_desc *gpio_b;
+ struct gpio_desc *gpio_index;
+
+ int irq_a;
+ int irq_b;
+ int irq_index;
+
+ spinlock_t lock;
+
+ s64 count;
+ u64 ceiling;
+ bool enabled;
+ enum counter_count_direction direction;
+ enum gpio_qenc_function function;
+
+ int prev_a;
+ int prev_b;
+
+ bool index_enabled;
+
+ struct counter_signal signals[3];
+ struct counter_synapse synapses[3];
+ struct counter_count cnts;
+};
+
+/*
+ * Quadrature state table for X4 decoding.
+ * Rows = previous state (A<<1 | B), Columns = new state (A<<1 | B).
+ * Values: 0 = no change, +1 = forward, -1 = backward, 2 = error (skip).
+ */
+static const int quad_table[4][4] = {
+ /* 00 01 10 11 <- new */
+ /* 00 */ { 0, -1, 1, 2 },
+ /* 01 */ { 1, 0, 2, -1 },
+ /* 10 */ { -1, 2, 0, 1 },
+ /* 11 */ { 2, 1, -1, 0 },
+};
+
+static void gpio_qenc_update_count(struct gpio_qenc_priv *priv, int delta)
+{
+ s64 new_count;
+
+ if (!delta)
+ return;
+
+ new_count = priv->count + delta;
+
+ if (priv->ceiling) {
+ if (new_count < 0)
+ new_count = 0;
+ else if (new_count > (s64)priv->ceiling)
+ new_count = priv->ceiling;
+ }
+
+ priv->count = new_count;
+ priv->direction = (delta > 0) ? COUNTER_COUNT_DIRECTION_FORWARD
+ : COUNTER_COUNT_DIRECTION_BACKWARD;
+}
+
+static irqreturn_t gpio_qenc_a_isr(int irq, void *dev_id)
+{
+ struct counter_device *counter = dev_id;
+ struct gpio_qenc_priv *priv = counter_priv(counter);
+ unsigned long flags;
+ int a, b, prev_state, new_state, delta;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (!priv->enabled)
+ goto out;
+
+ a = gpiod_get_value(priv->gpio_a);
+ b = gpiod_get_value(priv->gpio_b);
+
+ prev_state = (priv->prev_a << 1) | priv->prev_b;
+ new_state = (a << 1) | b;
+
+ switch (priv->function) {
+ case GPIO_QENC_FUNC_QUAD_X4:
+ delta = quad_table[prev_state][new_state];
+ if (delta == 2)
+ delta = 0;
+ gpio_qenc_update_count(priv, delta);
+ break;
+
+ case GPIO_QENC_FUNC_QUAD_X2:
+ delta = quad_table[prev_state][new_state];
+ if (delta == 2)
+ delta = 0;
+ gpio_qenc_update_count(priv, delta);
+ break;
+
+ case GPIO_QENC_FUNC_QUAD_X1:
+ if (!priv->prev_a && a) {
+ delta = b ? -1 : 1;
+ gpio_qenc_update_count(priv, delta);
+ }
+ break;
+
+ case GPIO_QENC_FUNC_PULSE_DIR:
+ if (!priv->prev_a && a) {
+ delta = b ? -1 : 1;
+ gpio_qenc_update_count(priv, delta);
+ }
+ break;
+ }
+
+ priv->prev_a = a;
+ priv->prev_b = b;
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ counter_push_event(counter, COUNTER_EVENT_CHANGE_OF_STATE, 0);
+
+ return IRQ_HANDLED;
+
+out:
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t gpio_qenc_b_isr(int irq, void *dev_id)
+{
+ struct counter_device *counter = dev_id;
+ struct gpio_qenc_priv *priv = counter_priv(counter);
+ unsigned long flags;
+ int a, b, prev_state, new_state, delta;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (!priv->enabled)
+ goto out;
+
+ a = gpiod_get_value(priv->gpio_a);
+ b = gpiod_get_value(priv->gpio_b);
+
+ prev_state = (priv->prev_a << 1) | priv->prev_b;
+ new_state = (a << 1) | b;
+
+ switch (priv->function) {
+ case GPIO_QENC_FUNC_QUAD_X4:
+ delta = quad_table[prev_state][new_state];
+ if (delta == 2)
+ delta = 0;
+ gpio_qenc_update_count(priv, delta);
+ break;
+
+ case GPIO_QENC_FUNC_QUAD_X2:
+ /* X2: only A-channel edges update count */
+ break;
+
+ case GPIO_QENC_FUNC_QUAD_X1:
+ case GPIO_QENC_FUNC_PULSE_DIR:
+ break;
+ }
+
+ priv->prev_a = a;
+ priv->prev_b = b;
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return IRQ_HANDLED;
+
+out:
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t gpio_qenc_index_isr(int irq, void *dev_id)
+{
+ struct counter_device *counter = dev_id;
+ struct gpio_qenc_priv *priv = counter_priv(counter);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (priv->enabled && priv->index_enabled)
+ priv->count = 0;
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ counter_push_event(counter, COUNTER_EVENT_INDEX, 0);
+
+ return IRQ_HANDLED;
+}
+
+static int gpio_qenc_count_read(struct counter_device *counter,
+ struct counter_count *count, u64 *val)
+{
+ struct gpio_qenc_priv *priv = counter_priv(counter);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ *val = (u64)priv->count;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+static int gpio_qenc_count_write(struct counter_device *counter,
+ struct counter_count *count, const u64 val)
+{
+ struct gpio_qenc_priv *priv = counter_priv(counter);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (priv->ceiling && val > priv->ceiling) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return -EINVAL;
+ }
+
+ priv->count = (s64)val;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+static const enum counter_function gpio_qenc_functions[] = {
+ COUNTER_FUNCTION_QUADRATURE_X1_A,
+ COUNTER_FUNCTION_QUADRATURE_X2_A,
+ COUNTER_FUNCTION_QUADRATURE_X4,
+ COUNTER_FUNCTION_PULSE_DIRECTION,
+};
+
+static int gpio_qenc_function_read(struct counter_device *counter,
+ struct counter_count *count,
+ enum counter_function *function)
+{
+ struct gpio_qenc_priv *priv = counter_priv(counter);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ switch (priv->function) {
+ case GPIO_QENC_FUNC_QUAD_X1:
+ *function = COUNTER_FUNCTION_QUADRATURE_X1_A;
+ break;
+ case GPIO_QENC_FUNC_QUAD_X2:
+ *function = COUNTER_FUNCTION_QUADRATURE_X2_A;
+ break;
+ case GPIO_QENC_FUNC_QUAD_X4:
+ *function = COUNTER_FUNCTION_QUADRATURE_X4;
+ break;
+ case GPIO_QENC_FUNC_PULSE_DIR:
+ *function = COUNTER_FUNCTION_PULSE_DIRECTION;
+ break;
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return 0;
+}
+
+static int gpio_qenc_function_write(struct counter_device *counter,
+ struct counter_count *count,
+ enum counter_function function)
+{
+ struct gpio_qenc_priv *priv = counter_priv(counter);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ switch (function) {
+ case COUNTER_FUNCTION_QUADRATURE_X1_A:
+ priv->function = GPIO_QENC_FUNC_QUAD_X1;
+ break;
+ case COUNTER_FUNCTION_QUADRATURE_X2_A:
+ priv->function = GPIO_QENC_FUNC_QUAD_X2;
+ break;
+ case COUNTER_FUNCTION_QUADRATURE_X4:
+ priv->function = GPIO_QENC_FUNC_QUAD_X4;
+ break;
+ case COUNTER_FUNCTION_PULSE_DIRECTION:
+ priv->function = GPIO_QENC_FUNC_PULSE_DIR;
+ break;
+ default:
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return -EINVAL;
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return 0;
+}
+
+static const enum counter_synapse_action gpio_qenc_synapse_actions[] = {
+ COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
+ COUNTER_SYNAPSE_ACTION_RISING_EDGE,
+ COUNTER_SYNAPSE_ACTION_NONE,
+};
+
+static int gpio_qenc_action_read(struct counter_device *counter,
+ struct counter_count *count,
+ struct counter_synapse *synapse,
+ enum counter_synapse_action *action)
+{
+ struct gpio_qenc_priv *priv = counter_priv(counter);
+ enum gpio_qenc_signal_id signal_id = synapse->signal->id;
+
+ switch (priv->function) {
+ case GPIO_QENC_FUNC_QUAD_X4:
+ if (signal_id == GPIO_QENC_SIGNAL_A ||
+ signal_id == GPIO_QENC_SIGNAL_B)
+ *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
+ else
+ *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
+ return 0;
+
+ case GPIO_QENC_FUNC_QUAD_X2:
+ if (signal_id == GPIO_QENC_SIGNAL_A)
+ *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
+ else if (signal_id == GPIO_QENC_SIGNAL_B)
+ *action = COUNTER_SYNAPSE_ACTION_NONE;
+ else
+ *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
+ return 0;
+
+ case GPIO_QENC_FUNC_QUAD_X1:
+ if (signal_id == GPIO_QENC_SIGNAL_A)
+ *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
+ else if (signal_id == GPIO_QENC_SIGNAL_B)
+ *action = COUNTER_SYNAPSE_ACTION_NONE;
+ else
+ *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
+ return 0;
+
+ case GPIO_QENC_FUNC_PULSE_DIR:
+ if (signal_id == GPIO_QENC_SIGNAL_A)
+ *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
+ else
+ *action = COUNTER_SYNAPSE_ACTION_NONE;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int gpio_qenc_signal_read(struct counter_device *counter,
+ struct counter_signal *signal,
+ enum counter_signal_level *level)
+{
+ struct gpio_qenc_priv *priv = counter_priv(counter);
+ struct gpio_desc *gpio;
+ int ret;
+
+ switch (signal->id) {
+ case GPIO_QENC_SIGNAL_A:
+ gpio = priv->gpio_a;
+ break;
+ case GPIO_QENC_SIGNAL_B:
+ gpio = priv->gpio_b;
+ break;
+ case GPIO_QENC_SIGNAL_INDEX:
+ gpio = priv->gpio_index;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (!gpio)
+ return -EINVAL;
+
+ ret = gpiod_get_value(gpio);
+ if (ret < 0)
+ return ret;
+
+ *level = ret ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW;
+ return 0;
+}
+
+static int gpio_qenc_events_configure(struct counter_device *counter)
+{
+ return 0;
+}
+
+static int gpio_qenc_watch_validate(struct counter_device *counter,
+ const struct counter_watch *watch)
+{
+ if (watch->channel != 0)
+ return -EINVAL;
+
+ switch (watch->event) {
+ case COUNTER_EVENT_CHANGE_OF_STATE:
+ case COUNTER_EVENT_INDEX:
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct counter_ops gpio_qenc_ops = {
+ .count_read = gpio_qenc_count_read,
+ .count_write = gpio_qenc_count_write,
+ .function_read = gpio_qenc_function_read,
+ .function_write = gpio_qenc_function_write,
+ .action_read = gpio_qenc_action_read,
+ .signal_read = gpio_qenc_signal_read,
+ .events_configure = gpio_qenc_events_configure,
+ .watch_validate = gpio_qenc_watch_validate,
+};
+
+static int gpio_qenc_ceiling_read(struct counter_device *counter,
+ struct counter_count *count, u64 *val)
+{
+ struct gpio_qenc_priv *priv = counter_priv(counter);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ *val = priv->ceiling;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+static int gpio_qenc_ceiling_write(struct counter_device *counter,
+ struct counter_count *count, const u64 val)
+{
+ struct gpio_qenc_priv *priv = counter_priv(counter);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->ceiling = val;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+static int gpio_qenc_enable_read(struct counter_device *counter,
+ struct counter_count *count, u8 *enable)
+{
+ struct gpio_qenc_priv *priv = counter_priv(counter);
+
+ *enable = priv->enabled;
+ return 0;
+}
+
+static int gpio_qenc_enable_write(struct counter_device *counter,
+ struct counter_count *count, u8 enable)
+{
+ struct gpio_qenc_priv *priv = counter_priv(counter);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (priv->enabled == !!enable) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return 0;
+ }
+
+ if (enable) {
+ priv->enabled = true;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ enable_irq(priv->irq_a);
+ enable_irq(priv->irq_b);
+ if (priv->irq_index)
+ enable_irq(priv->irq_index);
+ } else {
+ priv->enabled = false;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ disable_irq(priv->irq_a);
+ disable_irq(priv->irq_b);
+ if (priv->irq_index)
+ disable_irq(priv->irq_index);
+ }
+
+ return 0;
+}
+
+static int gpio_qenc_direction_read(struct counter_device *counter,
+ struct counter_count *count, u32 *direction)
+{
+ struct gpio_qenc_priv *priv = counter_priv(counter);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ *direction = priv->direction;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+static int gpio_qenc_index_enable_read(struct counter_device *counter,
+ struct counter_count *count, u8 *val)
+{
+ struct gpio_qenc_priv *priv = counter_priv(counter);
+
+ *val = priv->index_enabled;
+ return 0;
+}
+
+static int gpio_qenc_index_enable_write(struct counter_device *counter,
+ struct counter_count *count, u8 val)
+{
+ struct gpio_qenc_priv *priv = counter_priv(counter);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->index_enabled = !!val;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+static struct counter_comp gpio_qenc_count_ext[] = {
+ COUNTER_COMP_CEILING(gpio_qenc_ceiling_read, gpio_qenc_ceiling_write),
+ COUNTER_COMP_ENABLE(gpio_qenc_enable_read, gpio_qenc_enable_write),
+ COUNTER_COMP_DIRECTION(gpio_qenc_direction_read),
+ COUNTER_COMP_COUNT_BOOL("index_enabled",
+ gpio_qenc_index_enable_read,
+ gpio_qenc_index_enable_write),
+};
+
+static int gpio_qenc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct counter_device *counter;
+ struct gpio_qenc_priv *priv;
+ bool has_index;
+ int num_signals;
+ int num_synapses;
+ int ret;
+
+ counter = devm_counter_alloc(dev, sizeof(*priv));
+ if (!counter)
+ return -ENOMEM;
+
+ priv = counter_priv(counter);
+ spin_lock_init(&priv->lock);
+
+ priv->gpio_a = devm_gpiod_get(dev, "encoder-a", GPIOD_IN);
+ if (IS_ERR(priv->gpio_a))
+ return dev_err_probe(dev, PTR_ERR(priv->gpio_a),
+ "failed to get encoder-a GPIO\n");
+
+ priv->gpio_b = devm_gpiod_get(dev, "encoder-b", GPIOD_IN);
+ if (IS_ERR(priv->gpio_b))
+ return dev_err_probe(dev, PTR_ERR(priv->gpio_b),
+ "failed to get encoder-b GPIO\n");
+
+ priv->gpio_index = devm_gpiod_get_optional(dev, "encoder-index",
+ GPIOD_IN);
+ if (IS_ERR(priv->gpio_index))
+ return dev_err_probe(dev, PTR_ERR(priv->gpio_index),
+ "failed to get encoder-index GPIO\n");
+
+ has_index = !!priv->gpio_index;
+
+ priv->irq_a = gpiod_to_irq(priv->gpio_a);
+ if (priv->irq_a < 0)
+ return dev_err_probe(dev, priv->irq_a,
+ "failed to get IRQ for encoder-a\n");
+
+ priv->irq_b = gpiod_to_irq(priv->gpio_b);
+ if (priv->irq_b < 0)
+ return dev_err_probe(dev, priv->irq_b,
+ "failed to get IRQ for encoder-b\n");
+
+ if (has_index) {
+ priv->irq_index = gpiod_to_irq(priv->gpio_index);
+ if (priv->irq_index < 0)
+ return dev_err_probe(dev, priv->irq_index,
+ "failed to get IRQ for encoder-index\n");
+ }
+
+ priv->prev_a = gpiod_get_value(priv->gpio_a);
+ priv->prev_b = gpiod_get_value(priv->gpio_b);
+
+ priv->function = GPIO_QENC_FUNC_QUAD_X4;
+ priv->direction = COUNTER_COUNT_DIRECTION_FORWARD;
+
+ num_signals = has_index ? 3 : 2;
+
+ priv->signals[GPIO_QENC_SIGNAL_A].id = GPIO_QENC_SIGNAL_A;
+ priv->signals[GPIO_QENC_SIGNAL_A].name = "Signal A";
+
+ priv->signals[GPIO_QENC_SIGNAL_B].id = GPIO_QENC_SIGNAL_B;
+ priv->signals[GPIO_QENC_SIGNAL_B].name = "Signal B";
+
+ if (has_index) {
+ priv->signals[GPIO_QENC_SIGNAL_INDEX].id =
+ GPIO_QENC_SIGNAL_INDEX;
+ priv->signals[GPIO_QENC_SIGNAL_INDEX].name = "Index";
+ }
+
+ num_synapses = num_signals;
+
+ priv->synapses[0].actions_list = gpio_qenc_synapse_actions;
+ priv->synapses[0].num_actions = ARRAY_SIZE(gpio_qenc_synapse_actions);
+ priv->synapses[0].signal = &priv->signals[GPIO_QENC_SIGNAL_A];
+
+ priv->synapses[1].actions_list = gpio_qenc_synapse_actions;
+ priv->synapses[1].num_actions = ARRAY_SIZE(gpio_qenc_synapse_actions);
+ priv->synapses[1].signal = &priv->signals[GPIO_QENC_SIGNAL_B];
+
+ if (has_index) {
+ priv->synapses[2].actions_list = gpio_qenc_synapse_actions;
+ priv->synapses[2].num_actions =
+ ARRAY_SIZE(gpio_qenc_synapse_actions);
+ priv->synapses[2].signal =
+ &priv->signals[GPIO_QENC_SIGNAL_INDEX];
+ }
+
+ priv->cnts.id = 0;
+ priv->cnts.name = "Position";
+ priv->cnts.functions_list = gpio_qenc_functions;
+ priv->cnts.num_functions = ARRAY_SIZE(gpio_qenc_functions);
+ priv->cnts.synapses = priv->synapses;
+ priv->cnts.num_synapses = num_synapses;
+ priv->cnts.ext = gpio_qenc_count_ext;
+ priv->cnts.num_ext = ARRAY_SIZE(gpio_qenc_count_ext);
+
+ counter->name = dev_name(dev);
+ counter->parent = dev;
+ counter->ops = &gpio_qenc_ops;
+ counter->signals = priv->signals;
+ counter->num_signals = num_signals;
+ counter->counts = &priv->cnts;
+ counter->num_counts = 1;
+
+ irq_set_status_flags(priv->irq_a, IRQ_NOAUTOEN);
+ ret = devm_request_irq(dev, priv->irq_a, gpio_qenc_a_isr,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "gpio-qenc-a", counter);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to request IRQ for encoder-a\n");
+
+ irq_set_status_flags(priv->irq_b, IRQ_NOAUTOEN);
+ ret = devm_request_irq(dev, priv->irq_b, gpio_qenc_b_isr,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "gpio-qenc-b", counter);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to request IRQ for encoder-b\n");
+
+ if (has_index) {
+ irq_set_status_flags(priv->irq_index, IRQ_NOAUTOEN);
+ ret = devm_request_irq(dev, priv->irq_index,
+ gpio_qenc_index_isr,
+ IRQF_TRIGGER_RISING,
+ "gpio-qenc-index", counter);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to request IRQ for encoder-index\n");
+ }
+
+ ret = devm_counter_add(dev, counter);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to add counter\n");
+
+ dev_info(dev, "GPIO quadrature encoder registered (signals: A, B%s)\n",
+ has_index ? ", Index" : "");
+
+ return 0;
+}
+
+static const struct of_device_id gpio_qenc_of_match[] = {
+ { .compatible = "gpio-quadrature-encoder" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, gpio_qenc_of_match);
+
+static struct platform_driver gpio_qenc_driver = {
+ .probe = gpio_qenc_probe,
+ .driver = {
+ .name = "gpio-quadrature-encoder",
+ .of_match_table = gpio_qenc_of_match,
+ },
+};
+module_platform_driver(gpio_qenc_driver);
+
+MODULE_ALIAS("platform:gpio-quadrature-encoder");
+MODULE_AUTHOR("Wadim Mueller <wafgo01@gmail.com>");
+MODULE_DESCRIPTION("GPIO-based quadrature encoder counter driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("COUNTER");
--
2.52.0
^ permalink raw reply related
* [PATCH v2 3/3] MAINTAINERS: add entry for GPIO quadrature encoder counter driver
From: Wadim Mueller @ 2026-04-19 19:59 UTC (permalink / raw)
To: linux-iio, devicetree
Cc: wbg, conor+dt, krzk+dt, robh, linux-kernel, Wadim Mueller
In-Reply-To: <20260419195908.12202-1-wafgo01@gmail.com>
Add myself as maintainer for the new gpio-quadrature-encoder counter
driver and its devicetree binding.
Signed-off-by: Wadim Mueller <wafgo01@gmail.com>
---
MAINTAINERS | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 06a8c7457..fca62baa7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11018,6 +11018,13 @@ F: Documentation/dev-tools/gpio-sloppy-logic-analyzer.rst
F: drivers/gpio/gpio-sloppy-logic-analyzer.c
F: tools/gpio/gpio-sloppy-logic-analyzer.sh
+GPIO QUADRATURE ENCODER COUNTER DRIVER
+M: Wadim Mueller <wafgo01@gmail.com>
+L: linux-iio@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/counter/gpio-quadrature-encoder.yaml
+F: drivers/counter/gpio-quadrature-encoder.c
+
GPIO SUBSYSTEM
M: Linus Walleij <linusw@kernel.org>
M: Bartosz Golaszewski <brgl@kernel.org>
--
2.52.0
^ permalink raw reply related
* [PATCH v2 1/3] dt-bindings: counter: add gpio-quadrature-encoder binding
From: Wadim Mueller @ 2026-04-19 19:59 UTC (permalink / raw)
To: linux-iio, devicetree
Cc: wbg, conor+dt, krzk+dt, robh, linux-kernel, Wadim Mueller
In-Reply-To: <20260419195908.12202-1-wafgo01@gmail.com>
Add devicetree binding documentation for the GPIO-based quadrature
encoder counter driver. The driver reads A/B quadrature signals and
an optional index pulse via edge-triggered GPIO interrupts, supporting
X1, X2, X4 quadrature decoding and pulse-direction mode.
This is useful on SoCs that lack a dedicated hardware quadrature
decoder or where the encoder is wired to generic GPIO pins.
Signed-off-by: Wadim Mueller <wafgo01@gmail.com>
---
.../counter/gpio-quadrature-encoder.yaml | 60 +++++++++++++++++++
1 file changed, 60 insertions(+)
create mode 100644 Documentation/devicetree/bindings/counter/gpio-quadrature-encoder.yaml
diff --git a/Documentation/devicetree/bindings/counter/gpio-quadrature-encoder.yaml b/Documentation/devicetree/bindings/counter/gpio-quadrature-encoder.yaml
new file mode 100644
index 000000000..741396b29
--- /dev/null
+++ b/Documentation/devicetree/bindings/counter/gpio-quadrature-encoder.yaml
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/counter/gpio-quadrature-encoder.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: GPIO-based Quadrature Encoder
+
+maintainers:
+ - Wadim Mueller <wadim.mueller@cmblu.de>
+
+description: |
+ A generic GPIO-based quadrature encoder counter. Reads A/B quadrature
+ signals and an optional index pulse via edge-triggered GPIO interrupts.
+ Supports X1, X2, X4 quadrature decoding and pulse-direction mode.
+
+ This is useful on SoCs that lack a dedicated hardware quadrature
+ decoder (eQEP, QEI, etc.) or where the encoder is wired to generic
+ GPIO pins rather than to a dedicated peripheral.
+
+properties:
+ compatible:
+ const: gpio-quadrature-encoder
+
+ encoder-a-gpios:
+ maxItems: 1
+ description:
+ GPIO connected to the encoder's A (phase A) output.
+
+ encoder-b-gpios:
+ maxItems: 1
+ description:
+ GPIO connected to the encoder's B (phase B) output.
+
+ encoder-index-gpios:
+ maxItems: 1
+ description:
+ Optional GPIO connected to the encoder's index (Z) output.
+ The index signal pulses once per revolution and can be used
+ as a reference point for absolute position tracking.
+
+required:
+ - compatible
+ - encoder-a-gpios
+ - encoder-b-gpios
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ quadrature-encoder {
+ compatible = "gpio-quadrature-encoder";
+ encoder-a-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
+ encoder-b-gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;
+ encoder-index-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
+ };
+
+...
--
2.52.0
^ permalink raw reply related
* [PATCH v2 0/3] counter: add GPIO-based quadrature encoder driver
From: Wadim Mueller @ 2026-04-19 19:59 UTC (permalink / raw)
To: linux-iio, devicetree
Cc: wbg, conor+dt, krzk+dt, robh, linux-kernel, Wadim Mueller
This series adds a new counter subsystem driver that implements
quadrature encoder position tracking using plain GPIO pins with
edge-triggered interrupts.
The driver is intended for low to medium speed rotary encoders where
hardware counter peripherals (eQEP, FTM, etc.) are unavailable or
already in use. It targets the same use-cases as interrupt-cnt.c but
provides full quadrature decoding instead of simple pulse counting.
Features:
- X1, X2, X4 quadrature decoding and pulse-direction mode
- Optional index signal for zero-reset
- Configurable ceiling (position clamping)
- Standard counter subsystem sysfs + chrdev interface
- Enable/disable via sysfs with IRQ gating
Tested on TI AM64x (Cortex-A53) with a motor-driven rotary encoder
at up to 2 kHz quadrature edge rate.
Changes in v2:
- DT binding: rephrase description to describe hardware, not
driver/sysfs behaviour (Conor Dooley)
- DT binding: drop redundant example without index GPIO (Conor Dooley)
Wadim Mueller (3):
dt-bindings: counter: add gpio-quadrature-encoder binding
counter: add GPIO-based quadrature encoder driver
MAINTAINERS: add entry for GPIO quadrature encoder counter driver
.../counter/gpio-quadrature-encoder.yaml | 60 ++
MAINTAINERS | 7 +
drivers/counter/Kconfig | 15 +
drivers/counter/Makefile | 1 +
drivers/counter/gpio-quadrature-encoder.c | 710 ++++++++++++++++++
5 files changed, 793 insertions(+)
create mode 100644 Documentation/devicetree/bindings/counter/gpio-quadrature-encoder.yaml
create mode 100644 drivers/counter/gpio-quadrature-encoder.c
--
2.52.0
^ permalink raw reply
* Re: [PATCH 1/3] dt-bindings: counter: add gpio-quadrature-encoder binding
From: Wadim Mueller @ 2026-04-19 19:50 UTC (permalink / raw)
To: Conor Dooley
Cc: wbg, robh, krzk+dt, conor+dt, linux-iio, devicetree, linux-kernel
In-Reply-To: <20260417-banjo-uncross-fbec3af75617@spud>
On 2026-04-17 17:13, Conor Dooley wrote:
Thanks for the review
> On Thu, Apr 16, 2026 at 10:48:17PM +0200, Wadim Mueller wrote:
> > Add devicetree binding documentation for the GPIO-based quadrature
> > encoder counter driver. The driver reads A/B quadrature signals and
> > an optional index pulse via edge-triggered GPIO interrupts, supporting
> > X1, X2, X4 quadrature decoding and pulse-direction mode.
> >
> > This is useful on SoCs that lack a dedicated hardware quadrature
> > decoder or where the encoder is wired to generic GPIO pins.
> >
> > Signed-off-by: Wadim Mueller <wafgo01@gmail.com>
> > ---
> > .../counter/gpio-quadrature-encoder.yaml | 69 +++++++++++++++++++
> > 1 file changed, 69 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/counter/gpio-quadrature-encoder.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/counter/gpio-quadrature-encoder.yaml b/Documentation/devicetree/bindings/counter/gpio-quadrature-encoder.yaml
> > new file mode 100644
> > index 000000000..a52deaab6
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/counter/gpio-quadrature-encoder.yaml
> > @@ -0,0 +1,69 @@
> > +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/counter/gpio-quadrature-encoder.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: GPIO-based Quadrature Encoder
> > +
> > +maintainers:
> > + - Wadim Mueller <wadim.mueller@cmblu.de>
> > +
> > +description: |
> > + A generic GPIO-based quadrature encoder counter. Reads A/B quadrature
> > + signals and an optional index pulse via edge-triggered GPIO interrupts.
> > + Supports X1, X2, X4 quadrature decoding and pulse-direction mode.
> > +
>
> > + This driver is useful on SoCs that lack a dedicated hardware quadrature
> > + decoder (eQEP, QEI, etc.) or where the encoder is wired to generic GPIO
> > + pins rather than to a dedicated peripheral.
>
> Idea seems okay to me. Please rephrase this section to avoid talking
> about drivers...
Thanks, will fix that in v2.
>
> > +
> > +properties:
> > + compatible:
> > + const: gpio-quadrature-encoder
> > +
> > + encoder-a-gpios:
> > + maxItems: 1
> > + description:
> > + GPIO connected to the encoder's A (phase A) output.
> > +
> > + encoder-b-gpios:
> > + maxItems: 1
> > + description:
> > + GPIO connected to the encoder's B (phase B) output.
> > +
> > + encoder-index-gpios:
> > + maxItems: 1
> > + description:
> > + Optional GPIO connected to the encoder's index (Z) output.
> > + When the index input is enabled via sysfs, the count resets
> > + to zero on each index pulse.
>
> ...and this to stop talking about sysfs and driver behaviour though.
> Bindings are about hardware.
> pw-bot: changes-requested
>
Agreed, will rephrase to mention hardware signals only
> > +
> > +required:
> > + - compatible
> > + - encoder-a-gpios
> > + - encoder-b-gpios
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > + - |
> > + #include <dt-bindings/gpio/gpio.h>
> > +
> > + quadrature-encoder-0 {
> > + compatible = "gpio-quadrature-encoder";
> > + encoder-a-gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>;
> > + encoder-b-gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>;
> > + };
> > +
> > + - |
> > + #include <dt-bindings/gpio/gpio.h>
> > +
> > + quadrature-encoder-1 {
> > + compatible = "gpio-quadrature-encoder";
> > + encoder-a-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
> > + encoder-b-gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;
> > + encoder-index-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
> > + };
>
> I think this example alone is sufficient btw.
>
Ack, will drop the first example
> Cheers,
> Conor.
> > +
> > +...
> > --
> > 2.52.0
> >
^ permalink raw reply
* [PATCH 7/7] arm64: dts: renesas: r8a779md: Add support for R-Car M3Le R8A779MD Geist
From: Marek Vasut @ 2026-04-19 19:35 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Nguyen Tran, Marek Vasut, Conor Dooley, David Airlie,
Geert Uytterhoeven, Kieran Bingham, Krzysztof Kozlowski,
Kuninori Morimoto, Laurent Pinchart, Magnus Damm, Maxime Ripard,
Michael Turquette, Rob Herring, Simona Vetter, Stephen Boyd,
Thomas Zimmermann, Tomi Valkeinen, devicetree, dri-devel,
linux-clk, linux-kernel, linux-renesas-soc
In-Reply-To: <20260419193718.133174-1-marek.vasut+renesas@mailbox.org>
From: Nguyen Tran <nguyen.tran.pz@bp.renesas.com>
Add support for the Geist board based on the Renesas R-Car R8A779MD (M3Le)
SoC, a register-compatible variant of the R8A77965 (M3-N) with reduced set
of peripherals. The Geist board design references the Renesas Salvator-X/XS
boards, adapting their configuration for the R8A779MD SoC.
Signed-off-by: Nguyen Tran <nguyen.tran.pz@bp.renesas.com>
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: David Airlie <airlied@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Cc: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
Cc: devicetree@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Cc: linux-clk@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
arch/arm64/boot/dts/renesas/Makefile | 3 +
.../dts/renesas/geist-panel-aa104xd12.dtso | 17 +
.../arm64/boot/dts/renesas/r8a779md-geist.dts | 832 ++++++++++++++++++
3 files changed, 852 insertions(+)
create mode 100644 arch/arm64/boot/dts/renesas/geist-panel-aa104xd12.dtso
create mode 100644 arch/arm64/boot/dts/renesas/r8a779md-geist.dts
diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
index ca45d2857ea7f..0b8fbc7b00c6e 100644
--- a/arch/arm64/boot/dts/renesas/Makefile
+++ b/arch/arm64/boot/dts/renesas/Makefile
@@ -60,6 +60,9 @@ r8a77965-salvator-xs-panel-aa104xd12-dtbs := r8a77965-salvator-xs.dtb salvator-p
dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-xs-panel-aa104xd12.dtb
dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-ulcb.dtb
dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-ulcb-kf.dtb
+dtb-$(CONFIG_ARCH_R8A77965) += r8a779md-geist.dtb
+r8a779md-geist-panel-aa104xd12-dtbs := r8a779md-geist.dtb geist-panel-aa104xd12.dtbo
+dtb-$(CONFIG_ARCH_R8A77965) += r8a779md-geist-panel-aa104xd12.dtb
dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-eagle.dtb
dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-eagle-function-expansion.dtbo
diff --git a/arch/arm64/boot/dts/renesas/geist-panel-aa104xd12.dtso b/arch/arm64/boot/dts/renesas/geist-panel-aa104xd12.dtso
new file mode 100644
index 0000000000000..c8e39811eb051
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/geist-panel-aa104xd12.dtso
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree overlay for the AA104XD12 panel connected to LVDS0 on a Geist board
+ *
+ * Copyright 2026 Marek Vasut
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "salvator-panel-aa104xd12.dtso"
+
+&{/panel} {
+ data-mapping = "jeida-24";
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a779md-geist.dts b/arch/arm64/boot/dts/renesas/r8a779md-geist.dts
new file mode 100644
index 0000000000000..1a25acf638ea1
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a779md-geist.dts
@@ -0,0 +1,832 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/*
+ * Device Tree Source for the Geist board with R-Car M3Le
+ *
+ * Copyright (C) 2025-2026 Renesas Electronics Corp.
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "r8a779md.dtsi"
+
+/ {
+ model = "Renesas Geist board based on r8a779md";
+ compatible = "renesas,geist", "renesas,r8a779md", "renesas,r8a77965";
+
+ aliases {
+ serial0 = &scif2;
+ serial1 = &hscif1;
+ ethernet0 = &avb;
+ mmc0 = &sdhi2;
+ mmc1 = &sdhi0;
+ };
+
+ chosen {
+ bootargs = "ignore_loglevel rw root=/dev/nfs ip=on";
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory@48000000 {
+ device_type = "memory";
+ /* first 128MB is reserved for secure area. */
+ reg = <0x0 0x48000000 0x0 0x78000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* Device specific region for Lossy Decompression */
+ lossy_decompress: linux,lossy_decompress@54000000 {
+ no-map;
+ reg = <0x00000000 0x54000000 0x0 0x03000000>;
+ };
+ };
+
+ audio_clkout: audio-clkout {
+ /*
+ * FIXME
+ * This is same as <&rcar_sound 0>
+ * but needed to avoid cs2500/rcar_sound probe dead-lock
+ */
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <12288000>;
+ };
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 50000>;
+
+ brightness-levels = <256 128 64 16 8 4 0>;
+ default-brightness-level = <6>;
+
+ power-supply = <®_12v>;
+ enable-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>;
+ };
+
+ cvbs-in {
+ compatible = "composite-video-connector";
+ label = "CVBS IN";
+
+ port {
+ cvbs_con: endpoint {
+ remote-endpoint = <&adv7482_ain7>;
+ };
+ };
+ };
+
+ hdmi-in {
+ compatible = "hdmi-connector";
+ label = "HDMI IN";
+ type = "a";
+
+ port {
+ hdmi_in_con: endpoint {
+ remote-endpoint = <&adv7482_hdmi>;
+ };
+ };
+ };
+
+ keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&keys_pins>;
+ pinctrl-names = "default";
+
+ key-1 {
+ gpios = <&gpio5 17 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_1>;
+ label = "SW4-1";
+ wakeup-source;
+ debounce-interval = <20>;
+ };
+
+ key-2 {
+ gpios = <&gpio5 20 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_2>;
+ label = "SW4-2";
+ wakeup-source;
+ debounce-interval = <20>;
+ };
+
+ key-3 {
+ gpios = <&gpio5 22 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_3>;
+ label = "SW4-3";
+ wakeup-source;
+ debounce-interval = <20>;
+ };
+
+ key-4 {
+ gpios = <&gpio5 23 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_4>;
+ label = "SW4-4";
+ wakeup-source;
+ debounce-interval = <20>;
+ };
+
+ key-a {
+ gpios = <&gpio6 11 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_A>;
+ label = "TSW0";
+ wakeup-source;
+ debounce-interval = <20>;
+ };
+
+ key-b {
+ gpios = <&gpio6 12 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_B>;
+ label = "TSW1";
+ wakeup-source;
+ debounce-interval = <20>;
+ };
+
+ key-c {
+ gpios = <&gpio6 13 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_C>;
+ label = "TSW2";
+ wakeup-source;
+ debounce-interval = <20>;
+ };
+ };
+
+ reg_1p8v: regulator0 {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_3p3v: regulator1 {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_12v: regulator2 {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-12V";
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sound_card: sound {
+ compatible = "audio-graph-card";
+
+ label = "rcar-sound";
+ dais = <&rsnd_port0>; /* AK4619 Audio Codec */
+ };
+
+ vbus0_usb2: regulator-vbus0-usb2 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "USB20_VBUS0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+
+ gpio = <&gpio6 16 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ vcc_sdhi0: regulator-vcc-sdhi0 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "SDHI0 Vcc";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ vccq_sdhi0: regulator-vccq-sdhi0 {
+ compatible = "regulator-gpio";
+
+ regulator-name = "SDHI0 VccQ";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
+ gpios-states = <1>;
+ states = <3300000 1>, <1800000 0>;
+ };
+
+ vga {
+ compatible = "vga-connector";
+
+ port {
+ vga_in: endpoint {
+ remote-endpoint = <&adv7123_out>;
+ };
+ };
+ };
+
+ vga-encoder {
+ compatible = "adi,adv7123";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ adv7123_in: endpoint {
+ remote-endpoint = <&du_out_rgb>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ adv7123_out: endpoint {
+ remote-endpoint = <&vga_in>;
+ };
+ };
+ };
+ };
+
+ x12_clk: x12 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24576000>;
+ };
+
+ /* External DU dot clocks */
+ x21_clk: x21-clock {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <33000000>;
+ };
+
+ x22_clk: x22-clock {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <33000000>;
+ };
+
+ x23_clk: x23-clock {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <25000000>;
+ };
+
+ x3013_clk: x3013-clock {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <25000000>;
+ };
+};
+
+&audio_clk_a {
+ clock-frequency = <22579200>;
+};
+
+&avb {
+ pinctrl-0 = <&avb_pins>;
+ pinctrl-names = "default";
+ phy-handle = <&phy0>;
+ tx-internal-delay-ps = <2000>;
+ status = "okay";
+
+ phy0: ethernet-phy@0 {
+ rxc-skew-ps = <1500>;
+ reg = <0>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+ reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <100>;
+ reset-deassert-us = <100>;
+ };
+};
+
+&csi40 {
+ status = "okay";
+
+ ports {
+ port@0 {
+ csi40_in: endpoint {
+ clock-lanes = <0>;
+ data-lanes = <1 2 3 4>;
+ remote-endpoint = <&adv7482_txa>;
+ };
+ };
+ };
+};
+
+&du {
+ pinctrl-0 = <&du_pins>;
+ pinctrl-names = "default";
+ clocks = <&cpg CPG_MOD 724>,
+ <&cpg CPG_MOD 723>,
+ <&cpg CPG_MOD 721>,
+ <&versaclock5 1>,
+ <&x21_clk>,
+ <&versaclock5 2>;
+ clock-names = "du.0", "du.1", "du.3",
+ "dclkin.0", "dclkin.1", "dclkin.3";
+ status = "okay";
+
+ ports {
+ port@0 {
+ du_out_rgb: endpoint {
+ remote-endpoint = <&adv7123_in>;
+ };
+ };
+ };
+};
+
+&ehci0 {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&extalr_clk {
+ clock-frequency = <32768>;
+};
+
+&extal_clk {
+ clock-frequency = <16666666>;
+};
+
+&hscif1 {
+ pinctrl-0 = <&hscif1_pins>;
+ pinctrl-names = "default";
+
+ uart-has-rtscts;
+ /* Please only enable hscif1 or scif1 */
+ status = "okay";
+};
+
+&hsusb {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&i2c2 {
+ pinctrl-0 = <&i2c2_pins>;
+ pinctrl-names = "default";
+ clock-frequency = <100000>;
+ status = "okay";
+
+ ak4619: codec@10 {
+ compatible = "asahi-kasei,ak4619";
+ reg = <0x10>;
+ clocks = <&rcar_sound 3>;
+ clock-names = "mclk";
+ #sound-dai-cells = <0>;
+
+ port {
+ ak4619_endpoint: endpoint {
+ remote-endpoint = <&rsnd_endpoint0>;
+ };
+ };
+ };
+
+ /* Pin-to-pin, register map, and control compatible with CS2000 and CS2200 */
+ cs2500: clk_multiplier@4f {
+ #clock-cells = <0>;
+ compatible = "cirrus,cs2500-cp", "cirrus,cs2000-cp";
+ reg = <0x4f>;
+ clocks = <&audio_clkout>, <&x12_clk>;
+ clock-names = "clk_in", "ref_clk";
+
+ assigned-clocks = <&cs2500>;
+ assigned-clock-rates = <24576000>; /* 1/1 divide */
+ };
+};
+
+&i2c4 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ versaclock3: clock-generator@68 {
+ compatible = "renesas,5p35023";
+ reg = <0x68>;
+ #clock-cells = <1>;
+ clocks = <&x3013_clk>;
+ assigned-clocks = <&versaclock3 4>, <&versaclock3 5>;
+ assigned-clock-rates = <100000000>, <100000000>;
+ };
+
+ versaclock5: clock-generator@6a {
+ compatible = "idt,5p49v5923";
+ reg = <0x6a>;
+ #clock-cells = <1>;
+ clocks = <&x23_clk>;
+ clock-names = "xin";
+ };
+
+ video-receiver@70 {
+ compatible = "adi,adv7482";
+ reg = <0x70 0x71 0x72 0x73 0x74 0x75
+ 0x60 0x61 0x62 0x63 0x64 0x65>;
+ reg-names = "main", "dpll", "cp", "hdmi", "edid", "repeater",
+ "infoframe", "cbus", "cec", "sdp", "txa", "txb" ;
+
+ interrupt-parent = <&gpio6>;
+ interrupts = <30 IRQ_TYPE_LEVEL_LOW>,
+ <31 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "intrq1", "intrq2";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@7 {
+ reg = <7>;
+
+ adv7482_ain7: endpoint {
+ remote-endpoint = <&cvbs_con>;
+ };
+ };
+
+ port@8 {
+ reg = <8>;
+
+ adv7482_hdmi: endpoint {
+ remote-endpoint = <&hdmi_in_con>;
+ };
+ };
+
+ port@a {
+ reg = <10>;
+
+ adv7482_txa: endpoint {
+ clock-lanes = <0>;
+ data-lanes = <1 2 3 4>;
+ remote-endpoint = <&csi40_in>;
+ };
+ };
+ };
+ };
+
+ csa_vdd: adc@7c {
+ compatible = "maxim,max9611";
+ reg = <0x7c>;
+
+ shunt-resistor-micro-ohms = <5000>;
+ };
+
+ csa_dvfs: adc@7f {
+ compatible = "maxim,max9611";
+ reg = <0x7f>;
+
+ shunt-resistor-micro-ohms = <5000>;
+ };
+};
+
+&i2c_dvfs {
+ status = "okay";
+
+ clock-frequency = <400000>;
+
+ eeprom@50 {
+ compatible = "rohm,br24t01", "atmel,24c01";
+ reg = <0x50>;
+ pagesize = <8>;
+ };
+};
+
+&ohci0 {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&pcie_bus_clk {
+ status = "disabled";
+};
+
+&pciec0 {
+ clocks = <&cpg CPG_MOD 319>, <&versaclock3 4>;
+ status = "okay";
+};
+
+&pciec0_rp {
+ clocks = <&versaclock3 5>;
+};
+
+&pfc {
+ pinctrl-0 = <&scif_clk_pins>;
+ pinctrl-names = "default";
+
+ avb_pins: avb {
+ mux {
+ groups = "avb_link", "avb_mdio", "avb_mii";
+ function = "avb";
+ };
+
+ pins_mdio {
+ groups = "avb_mdio";
+ drive-strength = <24>;
+ };
+
+ pins_mii_tx {
+ pins = "PIN_AVB_TX_CTL", "PIN_AVB_TXC", "PIN_AVB_TD0",
+ "PIN_AVB_TD1", "PIN_AVB_TD2", "PIN_AVB_TD3";
+ drive-strength = <12>;
+ };
+ };
+
+ du_pins: du {
+ groups = "du_rgb888", "du_sync", "du_oddf", "du_clk_out_0";
+ function = "du";
+ };
+
+ hscif1_pins: hscif1 {
+ groups = "hscif1_data_a", "hscif1_ctrl_a";
+ function = "hscif1";
+ };
+
+ i2c2_pins: i2c2 {
+ groups = "i2c2_a";
+ function = "i2c2";
+ };
+
+ irq0_pins: irq0 {
+ groups = "intc_ex_irq0";
+ function = "intc_ex";
+ };
+
+ keys_pins: keys {
+ pins = "GP_5_17", "GP_5_20", "GP_5_22";
+ bias-pull-up;
+ };
+
+ pwm1_pins: pwm1 {
+ groups = "pwm1_a";
+ function = "pwm1";
+ };
+
+ pwm2_pins: pwm2 {
+ groups = "pwm2_a";
+ function = "pwm2";
+ };
+
+ scif1_pins: scif1 {
+ groups = "scif1_data_a", "scif1_ctrl";
+ function = "scif1";
+ };
+
+ scif2_pins: scif2 {
+ groups = "scif2_data_a";
+ function = "scif2";
+ };
+
+ scif_clk_pins: scif_clk {
+ groups = "scif_clk_a";
+ function = "scif_clk";
+ };
+
+ sdhi0_pins: sd0 {
+ groups = "sdhi0_data4", "sdhi0_ctrl";
+ function = "sdhi0";
+ power-source = <3300>;
+ };
+
+ sdhi0_pins_uhs: sd0_uhs {
+ groups = "sdhi0_data4", "sdhi0_ctrl";
+ function = "sdhi0";
+ power-source = <1800>;
+ };
+
+ sdhi2_pins: sd2 {
+ groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds";
+ function = "sdhi2";
+ power-source = <1800>;
+ };
+
+ sound_pins: sound {
+ groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a";
+ function = "ssi";
+ };
+
+ sound_clk_pins: sound_clk {
+ groups = "audio_clk_a_a", "audio_clk_b_a", "audio_clk_c_a",
+ "audio_clkout_a", "audio_clkout3_a";
+ function = "audio_clk";
+ };
+
+ usb0_pins: usb0 {
+ groups = "usb0";
+ function = "usb0";
+ };
+
+ usb1_pins: usb1 {
+ mux {
+ groups = "usb1";
+ function = "usb1";
+ };
+
+ ovc {
+ pins = "GP_6_27";
+ bias-pull-up;
+ };
+
+ pwen {
+ pins = "GP_6_26";
+ bias-pull-down;
+ };
+ };
+};
+
+&pwm1 {
+ pinctrl-0 = <&pwm1_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&pwm2 {
+ pinctrl-0 = <&pwm2_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&rcar_sound {
+ pinctrl-0 = <&sound_pins>, <&sound_clk_pins>;
+ pinctrl-names = "default";
+
+ /* Single DAI */
+ #sound-dai-cells = <0>;
+
+ /* audio_clkout0/1/2/3 */
+ #clock-cells = <1>;
+ clock-frequency = <12288000 11289600>;
+
+ status = "okay";
+
+ /* update <audio_clk_b> to <cs2500> */
+ clocks = <&cpg CPG_MOD 1005>,
+ <&cpg CPG_MOD 1006>, <&cpg CPG_MOD 1007>,
+ <&cpg CPG_MOD 1008>, <&cpg CPG_MOD 1009>,
+ <&cpg CPG_MOD 1010>, <&cpg CPG_MOD 1011>,
+ <&cpg CPG_MOD 1012>, <&cpg CPG_MOD 1013>,
+ <&cpg CPG_MOD 1014>, <&cpg CPG_MOD 1015>,
+ <&cpg CPG_MOD 1022>, <&cpg CPG_MOD 1023>,
+ <&cpg CPG_MOD 1024>, <&cpg CPG_MOD 1025>,
+ <&cpg CPG_MOD 1026>, <&cpg CPG_MOD 1027>,
+ <&cpg CPG_MOD 1028>, <&cpg CPG_MOD 1029>,
+ <&cpg CPG_MOD 1030>, <&cpg CPG_MOD 1031>,
+ <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>,
+ <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>,
+ <&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
+ <&audio_clk_a>, <&cs2500>,
+ <&audio_clk_c>,
+ <&cpg CPG_MOD 922>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rsnd_port0: port {
+ rsnd_endpoint0: endpoint {
+ remote-endpoint = <&ak4619_endpoint>;
+ dai-format = "left_j";
+ bitclock-master = <&rsnd_endpoint0>;
+ frame-master = <&rsnd_endpoint0>;
+ playback = <&ssi0>, <&src0>, <&dvc0>;
+ capture = <&ssi1>, <&src1>, <&dvc1>;
+ };
+ };
+ };
+};
+
+&rwdt {
+ timeout-sec = <60>;
+ status = "okay";
+};
+
+&scif1 {
+ pinctrl-0 = <&scif1_pins>;
+ pinctrl-names = "default";
+
+ uart-has-rtscts;
+ /* Please only enable hscif1 or scif1 */
+ /* status = "okay"; */
+};
+
+&scif2 {
+ pinctrl-0 = <&scif2_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&scif_clk {
+ clock-frequency = <14745600>;
+};
+
+&sdhi0 {
+ pinctrl-0 = <&sdhi0_pins>;
+ pinctrl-1 = <&sdhi0_pins_uhs>;
+ pinctrl-names = "default", "state_uhs";
+
+ vmmc-supply = <&vcc_sdhi0>;
+ vqmmc-supply = <&vccq_sdhi0>;
+ cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
+ bus-width = <4>;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ status = "okay";
+};
+
+&sdhi2 {
+ /* used for on-board 8bit eMMC */
+ pinctrl-0 = <&sdhi2_pins>;
+ pinctrl-1 = <&sdhi2_pins>;
+ pinctrl-names = "default", "state_uhs";
+
+ iommus = <&ipmmu_ds1 34>;
+
+ vmmc-supply = <®_3p3v>;
+ vqmmc-supply = <®_1p8v>;
+ bus-width = <8>;
+ mmc-hs200-1_8v;
+ no-sd;
+ no-sdio;
+ non-removable;
+ fixed-emmc-driver-type = <1>;
+ full-pwr-cycle-in-suspend;
+ status = "okay";
+};
+
+&ssi1 {
+ shared-pin;
+};
+
+&usb_extal_clk {
+ clock-frequency = <50000000>;
+};
+
+&usb2_phy0 {
+ pinctrl-0 = <&usb0_pins>;
+ pinctrl-names = "default";
+
+ vbus-supply = <&vbus0_usb2>;
+ status = "okay";
+};
+
+&usb2_phy1 {
+ pinctrl-0 = <&usb1_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&vin0 {
+ status = "okay";
+};
+
+&vin1 {
+ status = "okay";
+};
+
+&vin2 {
+ status = "okay";
+};
+
+&vin3 {
+ status = "okay";
+};
+
+&vin4 {
+ status = "okay";
+};
+
+&vin5 {
+ status = "okay";
+};
+
+&vin6 {
+ status = "okay";
+};
+
+&vin7 {
+ status = "okay";
+};
+
+&vspb {
+ status = "okay";
+};
+
+&vspi0 {
+ status = "okay";
+};
--
2.53.0
^ permalink raw reply related
* [PATCH 6/7] arm64: dts: renesas: r8a779md: Add Renesas R-Car R8A779MD M3Le DTs
From: Marek Vasut @ 2026-04-19 19:35 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Nguyen Tran, Marek Vasut, Conor Dooley, David Airlie,
Geert Uytterhoeven, Kieran Bingham, Krzysztof Kozlowski,
Kuninori Morimoto, Laurent Pinchart, Magnus Damm, Maxime Ripard,
Michael Turquette, Rob Herring, Simona Vetter, Stephen Boyd,
Thomas Zimmermann, Tomi Valkeinen, devicetree, dri-devel,
linux-clk, linux-kernel, linux-renesas-soc
In-Reply-To: <20260419193718.133174-1-marek.vasut+renesas@mailbox.org>
From: Nguyen Tran <nguyen.tran.pz@bp.renesas.com>
Add support for the Renesas R-Car M3Le (R8A779MD) SoC, a variant of the
R-Car M3-N (R8A77965) SoC. The Renesas M3Le SoC is a register-compatible
variant of the R8A77965 (M3-N) with reduced set of peripherals.
Signed-off-by: Nguyen Tran <nguyen.tran.pz@bp.renesas.com>
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: David Airlie <airlied@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Cc: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
Cc: devicetree@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Cc: linux-clk@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
arch/arm64/boot/dts/renesas/r8a779md.dtsi | 48 +++++++++++++++++++++++
1 file changed, 48 insertions(+)
create mode 100644 arch/arm64/boot/dts/renesas/r8a779md.dtsi
diff --git a/arch/arm64/boot/dts/renesas/r8a779md.dtsi b/arch/arm64/boot/dts/renesas/r8a779md.dtsi
new file mode 100644
index 0000000000000..7e0f5fe4cd439
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a779md.dtsi
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/*
+ * Device Tree Source for the R-Car M3Le (R8A779MD) SoC
+ *
+ * Copyright (C) 2025-2026 Renesas Electronics Corp.
+ */
+
+#include "r8a77965.dtsi"
+
+/ {
+ compatible = "renesas,r8a779md", "renesas,r8a77965";
+};
+
+/delete-node/ &csi20;
+/delete-node/ &drif00;
+/delete-node/ &drif01;
+/delete-node/ &drif10;
+/delete-node/ &drif11;
+/delete-node/ &drif20;
+/delete-node/ &drif21;
+/delete-node/ &drif30;
+/delete-node/ &drif31;
+/delete-node/ &hdmi0;
+/delete-node/ &mlp;
+/delete-node/ &pciec1;
+/delete-node/ &sata;
+/delete-node/ &sdhi3;
+/delete-node/ &usb3_peri0;
+/delete-node/ &usb3_phy0;
+/delete-node/ &vin0csi20;
+/delete-node/ &vin1csi20;
+/delete-node/ &vin2csi20;
+/delete-node/ &vin3csi20;
+/delete-node/ &vin4csi20;
+/delete-node/ &vin5csi20;
+/delete-node/ &vin6csi20;
+/delete-node/ &vin7csi20;
+/delete-node/ &xhci0;
+
+&du {
+ compatible = "renesas,du-r8a779md";
+ renesas,cmms = <&cmm0>, <&cmm3>;
+ renesas,vsps = <&vspd0 0>, <&vspd1 0>;
+
+ ports {
+ /delete-node/ port@1;
+ };
+};
--
2.53.0
^ permalink raw reply related
* [PATCH 5/7] soc: renesas: Identify Renesas R-Car R8A779MD M3Le SoC
From: Marek Vasut @ 2026-04-19 19:35 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Marek Vasut, Conor Dooley, David Airlie, Geert Uytterhoeven,
Kieran Bingham, Krzysztof Kozlowski, Kuninori Morimoto,
Laurent Pinchart, Magnus Damm, Maxime Ripard, Michael Turquette,
Rob Herring, Simona Vetter, Stephen Boyd, Thomas Zimmermann,
Tomi Valkeinen, devicetree, dri-devel, linux-clk, linux-kernel,
linux-renesas-soc
In-Reply-To: <20260419193718.133174-1-marek.vasut+renesas@mailbox.org>
Add support for identifying the R-Car M3Le (R8A779MD) SoC.
The Renesas R-Car R8A779MD M3Le SoC is a variant of the
already supported R-Car M3-N SoC with reduced peripherals.
Enable support for the M3Le SoC through already existing
ARCH_R8A77965 configuration symbol. PRR reads 0x67c05501 .
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: David Airlie <airlied@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Cc: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
Cc: devicetree@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Cc: linux-clk@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
drivers/soc/renesas/renesas-soc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c
index 38ff0b823bdaf..c82835cf6d8e9 100644
--- a/drivers/soc/renesas/renesas-soc.c
+++ b/drivers/soc/renesas/renesas-soc.c
@@ -361,6 +361,7 @@ static const struct of_device_id renesas_socs[] __initconst __maybe_unused = {
{ .compatible = "renesas,r8a77965", .data = &soc_rcar_m3_n },
{ .compatible = "renesas,r8a779m4", .data = &soc_rcar_m3_n },
{ .compatible = "renesas,r8a779m5", .data = &soc_rcar_m3_n },
+ { .compatible = "renesas,r8a779md", .data = &soc_rcar_m3_n },
#endif
#ifdef CONFIG_ARCH_R8A77970
{ .compatible = "renesas,r8a77970", .data = &soc_rcar_v3m },
--
2.53.0
^ permalink raw reply related
* [PATCH 3/7] dt-bindings: clock: cs2000-cp: document CS2500
From: Marek Vasut @ 2026-04-19 19:35 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Marek Vasut, Conor Dooley, David Airlie, Geert Uytterhoeven,
Kieran Bingham, Krzysztof Kozlowski, Kuninori Morimoto,
Laurent Pinchart, Magnus Damm, Maxime Ripard, Michael Turquette,
Rob Herring, Simona Vetter, Stephen Boyd, Thomas Zimmermann,
Tomi Valkeinen, devicetree, dri-devel, linux-clk, linux-kernel,
linux-renesas-soc
In-Reply-To: <20260419193718.133174-1-marek.vasut+renesas@mailbox.org>
Document backward compatibility support for CS2500 chip, which
is a drop-in replacement for CS2000 chip.
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: David Airlie <airlied@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Cc: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
Cc: devicetree@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Cc: linux-clk@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
.../devicetree/bindings/clock/cirrus,cs2000-cp.yaml | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml b/Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml
index d416c374e8534..031c52b2e5cec 100644
--- a/Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml
+++ b/Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml
@@ -11,14 +11,18 @@ maintainers:
description: |
The CS2000-CP is an extremely versatile system clocking device that
- utilizes a programmable phase lock loop.
+ utilizes a programmable phase lock loop. CP2500-CP is a compatible
+ drop-in replacement for CP2000-CP.
Link: https://www.cirrus.com/products/cs2000/
properties:
compatible:
- enum:
- - cirrus,cs2000-cp
+ oneOf:
+ - items:
+ - const: cirrus,cs2500-cp
+ - const: cirrus,cs2000-cp
+ - const: cirrus,cs2000-cp
clocks:
description:
--
2.53.0
^ permalink raw reply related
* [PATCH 4/7] dt-bindings: soc: renesas: Document Renesas R-Car R8A779MD Geist
From: Marek Vasut @ 2026-04-19 19:35 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Marek Vasut, Conor Dooley, David Airlie, Geert Uytterhoeven,
Kieran Bingham, Krzysztof Kozlowski, Kuninori Morimoto,
Laurent Pinchart, Magnus Damm, Maxime Ripard, Michael Turquette,
Rob Herring, Simona Vetter, Stephen Boyd, Thomas Zimmermann,
Tomi Valkeinen, devicetree, dri-devel, linux-clk, linux-kernel,
linux-renesas-soc
In-Reply-To: <20260419193718.133174-1-marek.vasut+renesas@mailbox.org>
Document the compatible value for the Renesas R-Car M3Le (R8A779MD)
SoC and the Renesas Geist development board. The Renesas M3Le SoC is
a register-compatible variant of the R8A77965 (M3-N) with reduced set
of peripherals. The Geist board is derived from Renesas Salvator-X/XS
boards, with adjustment for the R8A779MD SoC.
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: David Airlie <airlied@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Cc: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
Cc: devicetree@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Cc: linux-clk@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
Documentation/devicetree/bindings/soc/renesas/renesas.yaml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/soc/renesas/renesas.yaml b/Documentation/devicetree/bindings/soc/renesas/renesas.yaml
index 5c22c51b1533d..bda223237c812 100644
--- a/Documentation/devicetree/bindings/soc/renesas/renesas.yaml
+++ b/Documentation/devicetree/bindings/soc/renesas/renesas.yaml
@@ -473,6 +473,12 @@ properties:
- const: renesas,r8a779mb
- const: renesas,r8a7795
+ - description: R-Car M3Le (R8A779MD)
+ items:
+ - const: renesas,geist # M3Le Geist
+ - const: renesas,r8a779md
+ - const: renesas,r8a77965
+
- description: R-Car X5H (R8A78000)
items:
- enum:
--
2.53.0
^ permalink raw reply related
* [PATCH 2/7] drm/rcar-du: Add support for Renesas R-Car R8A779MD M3Le
From: Marek Vasut @ 2026-04-19 19:35 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Marek Vasut, Conor Dooley, David Airlie, Geert Uytterhoeven,
Kieran Bingham, Krzysztof Kozlowski, Kuninori Morimoto,
Laurent Pinchart, Magnus Damm, Maxime Ripard, Michael Turquette,
Rob Herring, Simona Vetter, Stephen Boyd, Thomas Zimmermann,
Tomi Valkeinen, devicetree, dri-devel, linux-clk, linux-kernel,
linux-renesas-soc
In-Reply-To: <20260419193718.133174-1-marek.vasut+renesas@mailbox.org>
Add support the Renesas R-Car R8A779MD M3Le SoC. This SoC is
similar to R-Car R8A77965 M3-N SoC, except the HDMI port@1 is
not present.
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: David Airlie <airlied@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Cc: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
Cc: devicetree@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Cc: linux-clk@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c | 25 +++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c
index 031d07f4508e9..be862b5524fd2 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c
@@ -564,6 +564,30 @@ static const struct rcar_du_device_info rcar_du_r8a779h0_info = {
.dsi_clk_mask = BIT(0),
};
+static const struct rcar_du_device_info rcar_du_r8a779md_info = {
+ .gen = 3,
+ .features = RCAR_DU_FEATURE_CRTC_IRQ
+ | RCAR_DU_FEATURE_CRTC_CLOCK
+ | RCAR_DU_FEATURE_VSP1_SOURCE
+ | RCAR_DU_FEATURE_INTERLACED
+ | RCAR_DU_FEATURE_TVM_SYNC,
+ .channels_mask = BIT(1) | BIT(0),
+ .routes = {
+ /* R8A779MD has one RGB output and one LVDS output. */
+ [RCAR_DU_OUTPUT_DPAD0] = {
+ .possible_crtcs = BIT(1),
+ .port = 0,
+ },
+ [RCAR_DU_OUTPUT_LVDS0] = {
+ .possible_crtcs = BIT(0),
+ .port = 2,
+ },
+ },
+ .num_lvds = 1,
+ .num_rpf = 5,
+ .dpll_mask = BIT(1),
+};
+
static const struct of_device_id rcar_du_of_table[] = {
{ .compatible = "renesas,du-r8a7742", .data = &rcar_du_r8a7790_info },
{ .compatible = "renesas,du-r8a7743", .data = &rzg1_du_r8a7743_info },
@@ -591,6 +615,7 @@ static const struct of_device_id rcar_du_of_table[] = {
{ .compatible = "renesas,du-r8a779a0", .data = &rcar_du_r8a779a0_info },
{ .compatible = "renesas,du-r8a779g0", .data = &rcar_du_r8a779g0_info },
{ .compatible = "renesas,du-r8a779h0", .data = &rcar_du_r8a779h0_info },
+ { .compatible = "renesas,du-r8a779md", .data = &rcar_du_r8a779md_info },
{ }
};
--
2.53.0
^ permalink raw reply related
* [PATCH 1/7] dt-bindings: display: renesas,du: Document Renesas R-Car R8A779MD M3Le
From: Marek Vasut @ 2026-04-19 19:35 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Marek Vasut, Conor Dooley, David Airlie, Geert Uytterhoeven,
Kieran Bingham, Krzysztof Kozlowski, Kuninori Morimoto,
Laurent Pinchart, Magnus Damm, Maxime Ripard, Michael Turquette,
Rob Herring, Simona Vetter, Stephen Boyd, Thomas Zimmermann,
Tomi Valkeinen, devicetree, dri-devel, linux-clk, linux-kernel,
linux-renesas-soc
In-Reply-To: <20260419193718.133174-1-marek.vasut+renesas@mailbox.org>
Extend the Renesas DU display bindings to support the Renesas R-Car
R8A779MD M3Le SoC. This SoC is similar to R-Car R8A77965 M3-N SoC,
except the HDMI port@1 is not present.
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: David Airlie <airlied@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Cc: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
Cc: devicetree@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Cc: linux-clk@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
.../bindings/display/renesas,du.yaml | 70 +++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/renesas,du.yaml b/Documentation/devicetree/bindings/display/renesas,du.yaml
index c27dfea7fc622..3c3667ff4a27f 100644
--- a/Documentation/devicetree/bindings/display/renesas,du.yaml
+++ b/Documentation/devicetree/bindings/display/renesas,du.yaml
@@ -42,6 +42,7 @@ properties:
- renesas,du-r8a779a0 # for R-Car V3U compatible DU
- renesas,du-r8a779g0 # for R-Car V4H compatible DU
- renesas,du-r8a779h0 # for R-Car V4M compatible DU
+ - renesas,du-r8a779md # for R-Car M3Le compatible DU
reg:
maxItems: 1
@@ -890,6 +891,75 @@ allOf:
- reset-names
- renesas,vsps
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - renesas,du-r8a779md
+ then:
+ properties:
+ clocks:
+ minItems: 3
+ items:
+ - description: Functional clock for DU0
+ - description: Functional clock for DU1
+ - description: Functional clock for DU3
+ - description: DU_DOTCLKIN0 input clock
+ - description: DU_DOTCLKIN1 input clock
+ - description: DU_DOTCLKIN3 input clock
+
+ clock-names:
+ minItems: 3
+ items:
+ - const: du.0
+ - const: du.1
+ - const: du.3
+ - pattern: '^dclkin\.[013]$'
+ - pattern: '^dclkin\.[013]$'
+ - pattern: '^dclkin\.[013]$'
+
+ interrupts:
+ minItems: 3
+ maxItems: 3
+
+ resets:
+ minItems: 2
+ maxItems: 2
+
+ reset-names:
+ items:
+ - const: du.0
+ - const: du.3
+
+ ports:
+ properties:
+ port@0:
+ description: DPAD 0
+ port@1: false
+ port@2:
+ description: LVDS 0
+ port@3: false
+
+ required:
+ - port@0
+ - port@2
+
+ renesas,cmms:
+ minItems: 3
+ maxItems: 3
+
+ renesas,vsps:
+ minItems: 3
+ maxItems: 3
+
+ required:
+ - clock-names
+ - interrupts
+ - resets
+ - reset-names
+ - renesas,vsps
+
additionalProperties: false
examples:
--
2.53.0
^ permalink raw reply related
* [PATCH 0/7] arm64: dts: renesas: r8a779md: Add support for R-Car M3Le R8A779MD SoC and Geist board
From: Marek Vasut @ 2026-04-19 19:35 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Marek Vasut, Conor Dooley, David Airlie, Geert Uytterhoeven,
Kieran Bingham, Krzysztof Kozlowski, Kuninori Morimoto,
Laurent Pinchart, Magnus Damm, Maxime Ripard, Michael Turquette,
Rob Herring, Simona Vetter, Stephen Boyd, Thomas Zimmermann,
Tomi Valkeinen, devicetree, dri-devel, linux-clk, linux-kernel,
linux-renesas-soc
Add support for the Renesas R-Car M3Le (R8A779MD) SoC, a register-compatible
variant of the R8A77965 (M3-N) with reduced set of peripherals. Add support
for the Geist board based on the Renesas R-Car R8A779MD (M3Le).
The DU part does probe, and to the best of my knowledge, should correctly
describe the hardware, but is otherwise untested due to no remote display
access. Note that the DU uses ports 0 and 2, which is unusual.
VIN is also untested due to no remote hardware access.
Marek Vasut (5):
dt-bindings: display: renesas,du: Document Renesas R-Car R8A779MD M3Le
drm/rcar-du: Add support for Renesas R-Car R8A779MD M3Le
dt-bindings: clock: cs2000-cp: document CS2500
dt-bindings: soc: renesas: Document Renesas R-Car R8A779MD Geist
soc: renesas: Identify Renesas R-Car R8A779MD M3Le SoC
Nguyen Tran (2):
arm64: dts: renesas: r8a779md: Add Renesas R-Car R8A779MD M3Le DTs
arm64: dts: renesas: r8a779md: Add support for R-Car M3Le R8A779MD
Geist
.../bindings/clock/cirrus,cs2000-cp.yaml | 10 +-
.../bindings/display/renesas,du.yaml | 70 ++
.../bindings/soc/renesas/renesas.yaml | 6 +
arch/arm64/boot/dts/renesas/Makefile | 3 +
.../dts/renesas/geist-panel-aa104xd12.dtso | 17 +
.../arm64/boot/dts/renesas/r8a779md-geist.dts | 832 ++++++++++++++++++
arch/arm64/boot/dts/renesas/r8a779md.dtsi | 48 +
drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c | 25 +
drivers/soc/renesas/renesas-soc.c | 1 +
9 files changed, 1009 insertions(+), 3 deletions(-)
create mode 100644 arch/arm64/boot/dts/renesas/geist-panel-aa104xd12.dtso
create mode 100644 arch/arm64/boot/dts/renesas/r8a779md-geist.dts
create mode 100644 arch/arm64/boot/dts/renesas/r8a779md.dtsi
---
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: David Airlie <airlied@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Cc: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
Cc: devicetree@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Cc: linux-clk@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
--
2.53.0
^ permalink raw reply
* [PATCH v1 14/14] dt-bindings: thermal: cooling-devices: Update support for 3 cells cooling device
From: Daniel Lezcano @ 2026-04-19 18:21 UTC (permalink / raw)
To: rafael
Cc: gaurav.kohli, Zhang Rui, Lukasz Luba, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Lucas Stach, Russell King,
Christian Gmeiner, David Airlie, Simona Vetter, Guenter Roeck,
Joel Stanley, Andrew Jeffery, Thomas Weißschuh, Benson Leung,
Pali Rohár, Avi Fishman, Tomer Maimon, Tali Perry,
Patrick Venture, Nancy Yuen, Benjamin Fair, Heiko Stuebner,
Thierry Reding, Jonathan Hunter, Bjorn Andersson, Konrad Dybcio,
Amit Daniel Kachhap, Viresh Kumar, Neil Armstrong, Amit Kucheria,
linux-pm, linux-kernel, linux-hwmon, Daniel Lezcano,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
In-Reply-To: <20260419182203.4083985-1-daniel.lezcano@oss.qualcomm.com>
From: Gaurav Kohli <gaurav.kohli@oss.qualcomm.com>
Extend the thermal cooling device binding to support a 3 cells specifier
along with tje 2 cells format.
Update #cooling-cells property to enum to support both 2 and 3 arguments.
Signed-off-by: Gaurav Kohli <gaurav.kohli@oss.qualcomm.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
---
.../bindings/thermal/thermal-cooling-devices.yaml | 8 ++++++--
.../devicetree/bindings/thermal/thermal-zones.yaml | 3 ++-
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml b/Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml
index b9022f1613d8..28f5818f1e60 100644
--- a/Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml
+++ b/Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml
@@ -44,10 +44,14 @@ select: true
properties:
"#cooling-cells":
description:
- Must be 2, in order to specify minimum and maximum cooling state used in
+ Must be 2 or 3. If 2, specifies minimum and maximum cooling state used in
the cooling-maps reference. The first cell is the minimum cooling state
and the second cell is the maximum cooling state requested.
- const: 2
+ If 3, the first cell specifies the thermal mitigation device specifier
+ index for devices that support multiple thermal mitigation mechanisms.
+ The two other cells are respectively the minimum cooling state and the
+ maximum cooling state.
+ enum: [2, 3]
additionalProperties: true
diff --git a/Documentation/devicetree/bindings/thermal/thermal-zones.yaml b/Documentation/devicetree/bindings/thermal/thermal-zones.yaml
index 0de0a9757ccc..1261ba0e802e 100644
--- a/Documentation/devicetree/bindings/thermal/thermal-zones.yaml
+++ b/Documentation/devicetree/bindings/thermal/thermal-zones.yaml
@@ -214,7 +214,8 @@ patternProperties:
device. Using the THERMAL_NO_LIMIT (-1UL) constant in the
cooling-device phandle limit specifier lets the framework
use the minimum and maximum cooling state for that cooling
- device automatically.
+ device automatically. If three arguments are specified,
+ the first argument is the cooling device specifier.
contribution:
$ref: /schemas/types.yaml#/definitions/uint32
--
2.43.0
^ permalink raw reply related
* Re: [PATCH] arm64: dts: amlogic: add support for Amedia X98Q
From: Christian Stefan Köver-Draxl @ 2026-04-19 17:59 UTC (permalink / raw)
To: Ferass El Hafidi, linux-amlogic, neil.armstrong, khilman
Cc: devicetree, linux-arm-kernel
In-Reply-To: <tdqzjg.e0dtukngm56y@postmarketos.org>
On 4/19/26 17:19, Ferass El Hafidi wrote:
> Hi, some drive-by feedback
>
> On Sun, 19 Apr 2026 15:08, christian.koever-draxl@student.uibk.ac.at
> wrote:
>> From: Christian Stefan Kövér-Draxl
>> <christian.koever-draxl@student.uibk.ac.at>
>>
>> The X98Q is a TV box based on the Amlogic S4 (S905W2) SoC.
>> Add the device tree for this board and document the compatible string.
>>
>> Supported features:
>> - 1GB/2GB RAM (via U-Boot memory fixup)
>> - 10/100 Ethernet (Internal PHY)
>> - eMMC and SD card storage
>> - PWM-based CPU voltage regulation
>> - UART (Serial console)
>>
>> Signed-off-by: Christian Stefan Kövér-Draxl
>> <christian.koever-draxl@student.uibk.ac.at>
>> ---
>> - The Wi-Fi chip on this board is Amlogic W150S1. I have left the
>> SDIO node enabled
>> but omitted the specific chip sub-node due to lack of mainline
>> drivers (yet).
>> - The console uses uart_b at 921600 baud.
>> - Verified memory via /proc/device-tree; U-Boot patches the node to
>> around 2GB if board supports more than 1GB.
>> - Tested on the 2GB RAM plus 16GB EMMC variant.
>>
>> .../devicetree/bindings/arm/amlogic.yaml | 7 +
>> arch/arm64/boot/dts/amlogic/Makefile | 1 +
>> .../boot/dts/amlogic/meson-s4-s905w2-x98q.dts | 244 ++++++++++++++++++
>> 3 files changed, 252 insertions(+)
>> create mode 100644 arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts
>>
>> diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml
>> b/Documentation/devicetree/bindings/arm/amlogic.yaml
>> index a885278bc4e2..82671d58d1da 100644
>> --- a/Documentation/devicetree/bindings/arm/amlogic.yaml
>> +++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
>> @@ -254,6 +254,13 @@ properties:
>> - khadas,vim1s
>> - const: amlogic,s905y4
>> - const: amlogic,s4
>> + + - description: Boards with the Amlogic Meson S4 S905W2 SoC
>> + items:
>> + - enum:
>> + - amediatech,x98q
>> + - const: amlogic,s905w2
>> + - const: amlogic,s4
>>
>> - description: Boards with the Amlogic S6 S905X5 SoC
>> items:
>
> It is better to send the dt-binding changes separate from the actual
> DTS. The golden rule is one commit per change.
>
> You can (and should) send both patches as part of a patch series.
Thanks for the Review! I have split this for v2.
>
>> diff --git a/arch/arm64/boot/dts/amlogic/Makefile
>> b/arch/arm64/boot/dts/amlogic/Makefile
>> index 15f9c817e502..6f0bdd5bdca2 100644
>> --- a/arch/arm64/boot/dts/amlogic/Makefile
>> +++ b/arch/arm64/boot/dts/amlogic/Makefile
>> @@ -86,6 +86,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxm-vega-s96.dtb
>> dtb-$(CONFIG_ARCH_MESON) += meson-gxm-wetek-core2.dtb
>> dtb-$(CONFIG_ARCH_MESON) += meson-s4-s805x2-aq222.dtb
>> dtb-$(CONFIG_ARCH_MESON) += meson-s4-s905y4-khadas-vim1s.dtb
>> +dtb-$(CONFIG_ARCH_MESON) += meson-s4-s905w2-x98q.dtb
>
> Keep this file in alphabetic order.
Thanks, i have fixed it!
>
>> dtb-$(CONFIG_ARCH_MESON) += meson-sm1-a95xf3-air-gbit.dtb
>> dtb-$(CONFIG_ARCH_MESON) += meson-sm1-a95xf3-air.dtb
>> dtb-$(CONFIG_ARCH_MESON) += meson-sm1-bananapi-m2-pro.dtb
>> diff --git a/arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts
>> b/arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts
>> new file mode 100644
>> index 000000000000..f2db01730a3d
>> --- /dev/null
>> +++ b/arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts
>> @@ -0,0 +1,244 @@
>> +
>> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>> +/*
>> + * Copyright (c) 2026 Christian Stefan Köver-Draxl
>> + */
>
> Did you base this DTS on another DTS that is already upstream? This
> looks a lot like
> https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux.git/tree/arch/arm64/boot/dts/amlogic/meson-s4-s905y4-khadas-vim1s.dts?h=v7.1/arm64-dt
>
>
> If so, then you should keep their copyright. Something like:
>
> /*
> * Copyright (c) 2026 Christian Stefan Köver-Draxl
> * Based on <...>:
> * - Copyright (c) <authors of the DTB this one is based on>
> */
>
> Correct me if I'm wrong.
Yes, I used the VIM1S as a base. I will update the copyright header to
include the original authors.
>
>> +
>> +/dts-v1/;
>> +
>> +#include "meson-s4.dtsi"
>> +
>> +/ {
>> + model = "Shenzhen Amedia X98Q";
>
> Shouldn't this be
> model = "Shenzhen Amediatech Technology Co., Ltd X98Q";
> ?
>
> There are other Amediatech boards supported currently:
>
> dts/amlogic/meson-g12a-x96-max.dts: model = "Shenzhen Amediatech
> Technology Co., Ltd X96 Max";
> dts/amlogic/meson-sm1-x96-air-gbit.dts: model = "Shenzhen Amediatech
> Technology Co., Ltd X96 Air";
> dts/amlogic/meson-sm1-x96-air.dts: model = "Shenzhen Amediatech
> Technology Co., Ltd X96 Air";
>
> I think it might be preferable to use a similar model format for
> consistency.
>
> It is also the documented vendor prefix for amediatech. (see
> Documentation/devicetree/bindings/vendor-prefixes.yaml)
I have updated the vendor prefix accordingly.
>
>> + compatible = "amediatech,x98q", "amlogic,s905w2", "amlogic,s4";
>> + interrupt-parent = <&gic>;
>> + #address-cells = <2>;
>> + #size-cells = <2>;
>> +
>> + aliases {
>> + mmc0 = &emmc; /* eMMC */
>> + mmc1 = &sd; /* SD card */
>> + mmc2 = &sdio; /* SDIO */
>> + serial0 = &uart_b;
>> + };
>> +
>> + memory@0 {
>> + device_type = "memory";
>> + reg = <0x0 0x0 0x0 0x40000000>;
>> + };
>> +
>> + reserved-memory {
>> + #address-cells = <2>;
>> + #size-cells = <2>;
>> + ranges;
>> +
>> + /* 52 MiB reserved for ARM Trusted Firmware */
>> + secmon_reserved: secmon@5000000 {
>> + reg = <0x0 0x05000000 0x0 0x3400000>;
>> + no-map;
>> + };
>> + };
>> +
>> + emmc_pwrseq: emmc-pwrseq {
>> + compatible = "mmc-pwrseq-emmc";
>> + reset-gpios = <&gpio GPIOB_9 GPIO_ACTIVE_LOW>;
>> + };
>> +
>> + sdio_32k: sdio-32k {
>> + compatible = "pwm-clock";
>> + #clock-cells = <0>;
>> + clock-frequency = <32768>;
>> + pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
>> + };
>> +
>> + sdio_pwrseq: sdio-pwrseq {
>> + compatible = "mmc-pwrseq-simple";
>> + reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
>> + clocks = <&sdio_32k>;
>> + clock-names = "ext_clock";
>> + };
>> +
>> + main_5v: regulator-main-5v {
>> + compatible = "regulator-fixed";
>> + regulator-name = "5V";
>> + regulator-min-microvolt = <5000000>;
>> + regulator-max-microvolt = <5000000>;
>> + regulator-always-on;
>> + };
>> +
>> + sd_3v3: regulator-sd-3v3 {
>> + compatible = "regulator-fixed";
>> + regulator-name = "SD_3V3";
>> + regulator-min-microvolt = <3300000>;
>> + regulator-max-microvolt = <3300000>;
>> + gpio = <&gpio GPIOD_4 GPIO_ACTIVE_LOW>;
>> + regulator-always-on;
>> + };
>> +
>> + vddio_sd: regulator-vddio-sd {
>> + compatible = "regulator-gpio";
>> + regulator-name = "VDDIO_SD";
>> + regulator-min-microvolt = <1800000>;
>> + regulator-max-microvolt = <3300000>;
>> + gpios = <&gpio GPIOD_9 GPIO_ACTIVE_HIGH>;
>> + gpios-states = <1>;
>> + states = <1800000 1
>> + 3300000 0>;
>
> nit: keep this in one line.
Done for v2!
BTW: I applied this part from the VIM1S. So maybe that dts needs to be
adjusted too in the future.
>
>> + };
>> +
>> + vddao_3v3: regulator-vddao-3v3 {
>> + compatible = "regulator-fixed";
>> + regulator-name = "VDDAO_3V3";
>> + regulator-min-microvolt = <3300000>;
>> + regulator-max-microvolt = <3300000>;
>> + vin-supply = <&main_5v>;
>> + regulator-always-on;
>> + };
>> +
>> + vddio_ao1v8: regulator-vddio-ao1v8 {
>> + compatible = "regulator-fixed";
>> + regulator-name = "VDDIO_AO1V8";
>> + regulator-min-microvolt = <1800000>;
>> + regulator-max-microvolt = <1800000>;
>> + vin-supply = <&vddao_3v3>;
>> + regulator-always-on;
>> + };
>> +
>> + /* SY8120B1ABC DC/DC Regulator. */
>> + vddcpu: regulator-vddcpu {
>> + compatible = "pwm-regulator";
>> +
>> + regulator-name = "VDDCPU";
>> + regulator-min-microvolt = <689000>;
>> + regulator-max-microvolt = <1049000>;
>> +
>> + vin-supply = <&main_5v>;
>> +
>> + pwms = <&pwm_ij 1 1500 0>;
>> + pwm-dutycycle-range = <100 0>;
>> +
>> + regulator-boot-on;
>> + regulator-always-on;
>> + /* Voltage Duty-Cycle */
>> + voltage-table = <1049000 0>,
>> + <1039000 3>,
>> + <1029000 6>,
>> + <1019000 9>,
>> + <1009000 12>,
>> + <999000 14>,
>> + <989000 17>,
>> + <979000 20>,
>> + <969000 23>,
>> + <959000 26>,
>> + <949000 29>,
>> + <939000 31>,
>> + <929000 34>,
>> + <919000 37>,
>> + <909000 40>,
>> + <899000 43>,
>> + <889000 45>,
>> + <879000 48>,
>> + <869000 51>,
>> + <859000 54>,
>> + <849000 56>,
>> + <839000 59>,
>> + <829000 62>,
>> + <819000 65>,
>> + <809000 68>,
>> + <799000 70>,
>> + <789000 73>,
>> + <779000 76>,
>> + <769000 79>,
>> + <759000 81>,
>> + <749000 84>,
>> + <739000 87>,
>> + <729000 89>,
>> + <719000 92>,
>> + <709000 95>,
>> + <699000 98>,
>> + <689000 100>;
>> + };
>> +};
>> +
>> +&emmc {
>> + status = "okay";
>> + pinctrl-0 = <&emmc_pins>, <&emmc_ds_pins>;
>> + pinctrl-1 = <&emmc_clk_gate_pins>;
>> + pinctrl-names = "default", "clk-gate";
>> +
>> + bus-width = <8>;
>> + cap-mmc-highspeed;
>> + mmc-ddr-1_8v;
>> + mmc-hs200-1_8v;
>> + max-frequency = <200000000>;
>> + non-removable;
>> + disable-wp;
>> +
>> + mmc-pwrseq = <&emmc_pwrseq>;
>> + vmmc-supply = <&vddao_3v3>;
>> + vqmmc-supply = <&vddio_ao1v8>;
>> +};
>> +
>> +ðmac {
>> + status = "okay";
>> + phy-handle = <&internal_ephy>;
>> + phy-mode = "rmii";
>> +};
>> +
>> +&ir {
>> + status = "okay";
>> + pinctrl-0 = <&remote_pins>;
>> + pinctrl-names = "default";
>> +};
>> +
>> +&pwm_ef {
>> + status = "okay";
>> + pinctrl-0 = <&pwm_e_pins1>;
>> + pinctrl-names = "default";
>> +};
>> +
>> +&pwm_ij {
>> + status = "okay";
>> +};
>> +
>> +&sd {
>> + status = "okay";
>> + pinctrl-0 = <&sdcard_pins>;
>> + pinctrl-1 = <&sdcard_clk_gate_pins>;
>> + pinctrl-names = "default", "clk-gate";
>> + bus-width = <4>;
>> + cap-sd-highspeed;
>> + max-frequency = <50000000>;
>> + disable-wp;
>> +
>> + cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>;
>> +
>> + vmmc-supply = <&vddao_3v3>;
>> + vqmmc-supply = <&vddao_3v3>;
>> +};
>> +
>> +&sdio {
>> + status = "okay";
>> + pinctrl-0 = <&sdio_pins>;
>> + pinctrl-1 = <&sdio_clk_gate_pins>;
>> + pinctrl-names = "default", "clk-gate";
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> + bus-width = <4>;
>> + cap-sd-highspeed;
>> + sd-uhs-sdr50;
>> + sd-uhs-sdr104;
>> + max-frequency = <200000000>;
>> + non-removable;
>> + disable-wp;
>> +
>> + no-sd;
>> + no-mmc;
>> + mmc-pwrseq = <&sdio_pwrseq>;
>> + vmmc-supply = <&vddao_3v3>;
>> + vqmmc-supply = <&vddio_ao1v8>;
>> +};
>
> I suppose that's the Wi-Fi module you're talking about. I would put a
> comment
> above to specify that it is indeed Wi-Fi and not yet supported.
>
> Something like:
>
> /*
> * Wireless SDIO Module (Amlogic W150S1)
> * Note: There is no driver for this at the moment.
> */
>
Yes that makes sense. I will add that.
>> +
>> +&uart_b {
>> + status = "okay";
>> +};
>> --
>> 2.53.0
>
> --
> Best regards,
> Ferass
Thanks again,
Christian
^ permalink raw reply
* [PATCH v2 2/2] iio: adc: hx711: add support for HX710B
From: Piyush Patle @ 2026-04-19 17:46 UTC (permalink / raw)
To: jic23, ak
Cc: dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt, linux-iio,
devicetree, linux-kernel
In-Reply-To: <20260419174654.683692-1-piyushpatle228@gmail.com>
The HX711 uses trailing SCK pulses after each 24-bit conversion to
select the channel and gain for the next measurement: 1 pulse gives
channel A at gain 128, 2 pulses give channel B at gain 32, and 3 pulses
give channel A at gain 64.
The HX710B works differently: gain is fixed at 128 and the trailing
pulses select only the channel. One trailing pulse selects the
differential input (channel 0, 10 SPS) and two trailing pulses select
the DVDD-AVDD supply monitor (channel 1, 40 SPS).
Refactor the driver around a per-chip hx711_chip_info structure so both
variants can share the same core. Each chip provides its own
iio_chan_spec array and iio_info pointer. The HX710B stores per-channel
trailing pulse counts in chan->address (1 for channel 0, 2 for
channel 1) instead of a separate array. A bool fixed_gain flag and
fixed_gain_val field in hx711_chip_info distinguish the fixed-gain path
from the HX711's user-selectable gain path without conflating unrelated
properties. The HX710B differential input channel is described with
.differential=1 and .channel2=1 as required by the IIO ABI.
Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
---
Changes in v2:
- Fix pulse count bug: hx710b values were {25, 26} (total SCK cycles);
corrected to {1, 2} (trailing-only, hx711_read() clocks 24 data bits)
- Add .differential = 1 and .channel2 = 1 to HX710B channel 0
- Move trailing pulse counts from a separate array to chan->address
(1 for ch0, 2 for ch1); remove chan_pulse_count / num_chan_pulses
- Replace chan_pulse_count != NULL tests with dedicated bool fixed_gain
flag; add fixed_gain_val field to hx711_chip_info
- Add const struct iio_info *iio_info to hx711_chip_info; probe sets
indio_dev->info = chip_info->iio_info directly
- Remove NULL check after device_get_match_data()
- Remove reset_channel from hx711_chip_info (always 0; use literal)
- Change hx711_reset_read() and hx710b_set_channel() to take
const struct iio_chan_spec * instead of int chan
- Revert hx711_data struct member alignment noise
- Restore trailing blank line at end of file (unrelated removal reverted)
- Sort of_device_id entries alphabetically (hx710b before hx711)
- Expand commit message to explain HX711 vs HX710B trailing-pulse model
- Restore file header to mention weight sensor modules
drivers/iio/adc/Kconfig | 9 +-
drivers/iio/adc/hx711.c | 206 ++++++++++++++++++++++++++++++++--------
2 files changed, 174 insertions(+), 41 deletions(-)
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 60038ae8dfc4..ddf981fa72a2 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -784,18 +784,21 @@ config HI8435
called hi8435.
config HX711
- tristate "AVIA HX711 ADC for weight cells"
+ tristate "AVIA HX711 and HX710B ADC"
depends on GPIOLIB
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
- If you say yes here you get support for AVIA HX711 ADC which is used
- for weigh cells
+ If you say yes here you get support for AVIA HX711 and HX710B ADCs
+ which are used for bridge sensors such as weigh cells.
This driver uses two GPIOs, one acts as the clock and controls the
channel selection and gain, the other one is used for the measurement
data
+ The HX710B is a variant with fixed gain and a different channel
+ selection scheme.
+
Currently the raw value is read from the chip and delivered.
To get an actual weight one needs to subtract the
zero offset and multiply by a scale factor.
diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
index 1db8b68a8f64..b024fb341b2e 100644
--- a/drivers/iio/adc/hx711.c
+++ b/drivers/iio/adc/hx711.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * HX711: analog to digital converter for weight sensor module
+ * HX711/HX710B: ADC driver for weight sensor modules
*
* Copyright (c) 2016 Andreas Klinger <ak@it-klinger.de>
*/
@@ -76,12 +76,33 @@ static int hx711_get_scale_to_gain(int scale)
return -EINVAL;
}
+/**
+ * struct hx711_chip_info - per-variant static configuration
+ * @name: IIO device name
+ * @channels: channel specification
+ * @num_channels: number of channels
+ * @iio_info: IIO info ops for this variant
+ * @fixed_gain: true if the variant has a fixed ADC gain (e.g. HX710B)
+ * @fixed_gain_val: the fixed gain value used to compute scale (when fixed_gain)
+ */
+struct hx711_chip_info {
+ const char *name;
+ const struct iio_chan_spec *channels;
+ int num_channels;
+ const struct iio_info *iio_info;
+ bool fixed_gain;
+ int fixed_gain_val;
+};
+
struct hx711_data {
struct device *dev;
struct gpio_desc *gpiod_pd_sck;
struct gpio_desc *gpiod_dout;
int gain_set; /* gain set on device */
int gain_chan_a; /* gain for channel A */
+ int channel_set; /* HX710B current channel */
+ int scale; /* HX710B fixed scale */
+ const struct hx711_chip_info *chip_info;
struct mutex lock;
/*
* triggered buffer
@@ -92,10 +113,7 @@ struct hx711_data {
aligned_s64 timestamp;
} buffer;
/*
- * delay after a rising edge on SCK until the data is ready DOUT
- * this is dependent on the hx711 where the datasheet tells a
- * maximum value of 100 ns
- * but also on potential parasitic capacities on the wiring
+ * Delay after SCK rising edge before sampling DOUT.
*/
u32 data_ready_delay_ns;
u32 clock_frequency;
@@ -139,7 +157,11 @@ static int hx711_cycle(struct hx711_data *hx711_data)
return gpiod_get_value(hx711_data->gpiod_dout);
}
-static int hx711_read(struct hx711_data *hx711_data)
+/*
+ * Clock out 24 data bits and then send trailing pulses to select the
+ * next channel/gain state.
+ */
+static int hx711_read(struct hx711_data *hx711_data, int trailing_pulses)
{
int i, ret;
int value = 0;
@@ -158,7 +180,7 @@ static int hx711_read(struct hx711_data *hx711_data)
value ^= 0x800000;
- for (i = 0; i < hx711_get_gain_to_pulse(hx711_data->gain_set); i++)
+ for (i = 0; i < trailing_pulses; i++)
hx711_cycle(hx711_data);
return value;
@@ -188,6 +210,7 @@ static int hx711_wait_for_ready(struct hx711_data *hx711_data)
static int hx711_reset(struct hx711_data *hx711_data)
{
+ const struct hx711_chip_info *info = hx711_data->chip_info;
int val = hx711_wait_for_ready(hx711_data);
if (val) {
@@ -206,13 +229,17 @@ static int hx711_reset(struct hx711_data *hx711_data)
val = hx711_wait_for_ready(hx711_data);
- /* after a reset the gain is 128 */
- hx711_data->gain_set = HX711_RESET_GAIN;
+ /* Restore variant default after reset. */
+ if (info->fixed_gain)
+ hx711_data->channel_set = 0;
+ else
+ hx711_data->gain_set = HX711_RESET_GAIN;
}
return val;
}
+/* Select HX711 channel/gain for the next conversion. */
static int hx711_set_gain_for_channel(struct hx711_data *hx711_data, int chan)
{
int ret;
@@ -221,7 +248,8 @@ static int hx711_set_gain_for_channel(struct hx711_data *hx711_data, int chan)
if (hx711_data->gain_set == 32) {
hx711_data->gain_set = hx711_data->gain_chan_a;
- ret = hx711_read(hx711_data);
+ ret = hx711_read(hx711_data,
+ hx711_get_gain_to_pulse(hx711_data->gain_set));
if (ret < 0)
return ret;
@@ -233,7 +261,8 @@ static int hx711_set_gain_for_channel(struct hx711_data *hx711_data, int chan)
if (hx711_data->gain_set != 32) {
hx711_data->gain_set = 32;
- ret = hx711_read(hx711_data);
+ ret = hx711_read(hx711_data,
+ hx711_get_gain_to_pulse(hx711_data->gain_set));
if (ret < 0)
return ret;
@@ -246,27 +275,50 @@ static int hx711_set_gain_for_channel(struct hx711_data *hx711_data, int chan)
return 0;
}
-static int hx711_reset_read(struct hx711_data *hx711_data, int chan)
+/* Select HX710B channel for the next conversion. */
+static int hx710b_set_channel(struct hx711_data *hx711_data,
+ const struct iio_chan_spec *chan)
{
int ret;
- int val;
- /*
- * hx711_reset() must be called from here
- * because it could be calling hx711_read() by itself
- */
+ if (hx711_data->channel_set == chan->channel)
+ return 0;
+
+ hx711_data->channel_set = chan->channel;
+
+ ret = hx711_read(hx711_data, chan->address);
+ if (ret < 0)
+ return ret;
+
+ return hx711_wait_for_ready(hx711_data);
+}
+
+static int hx711_reset_read(struct hx711_data *hx711_data,
+ const struct iio_chan_spec *chan)
+{
+ const struct hx711_chip_info *info = hx711_data->chip_info;
+ int trailing_pulses;
+ int ret;
+
+ /* Reset first so the read starts from a known chip state. */
if (hx711_reset(hx711_data)) {
dev_err(hx711_data->dev, "reset failed!");
return -EIO;
}
- ret = hx711_set_gain_for_channel(hx711_data, chan);
- if (ret < 0)
- return ret;
-
- val = hx711_read(hx711_data);
+ if (info->fixed_gain) {
+ ret = hx710b_set_channel(hx711_data, chan);
+ if (ret < 0)
+ return ret;
+ trailing_pulses = chan->address;
+ } else {
+ ret = hx711_set_gain_for_channel(hx711_data, chan->channel);
+ if (ret < 0)
+ return ret;
+ trailing_pulses = hx711_get_gain_to_pulse(hx711_data->gain_set);
+ }
- return val;
+ return hx711_read(hx711_data, trailing_pulses);
}
static int hx711_read_raw(struct iio_dev *indio_dev,
@@ -274,12 +326,13 @@ static int hx711_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask)
{
struct hx711_data *hx711_data = iio_priv(indio_dev);
+ const struct hx711_chip_info *info = hx711_data->chip_info;
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&hx711_data->lock);
- *val = hx711_reset_read(hx711_data, chan->channel);
+ *val = hx711_reset_read(hx711_data, chan);
mutex_unlock(&hx711_data->lock);
@@ -290,7 +343,10 @@ static int hx711_read_raw(struct iio_dev *indio_dev,
*val = 0;
mutex_lock(&hx711_data->lock);
- *val2 = hx711_get_gain_to_scale(hx711_data->gain_set);
+ if (info->fixed_gain)
+ *val2 = hx711_data->scale;
+ else
+ *val2 = hx711_get_gain_to_scale(hx711_data->gain_set);
mutex_unlock(&hx711_data->lock);
@@ -332,7 +388,8 @@ static int hx711_write_raw(struct iio_dev *indio_dev,
if (gain != 32)
hx711_data->gain_chan_a = gain;
- ret = hx711_read(hx711_data);
+ ret = hx711_read(hx711_data,
+ hx711_get_gain_to_pulse(hx711_data->gain_set));
if (ret < 0) {
mutex_unlock(&hx711_data->lock);
return ret;
@@ -368,7 +425,7 @@ static irqreturn_t hx711_trigger(int irq, void *p)
iio_for_each_active_channel(indio_dev, i) {
hx711_data->buffer.channel[j] = hx711_reset_read(hx711_data,
- indio_dev->channels[i].channel);
+ &indio_dev->channels[i]);
j++;
}
@@ -423,6 +480,10 @@ static const struct iio_info hx711_iio_info = {
.attrs = &hx711_attribute_group,
};
+static const struct iio_info hx710b_iio_info = {
+ .read_raw = hx711_read_raw,
+};
+
static const struct iio_chan_spec hx711_chan_spec[] = {
{
.type = IIO_VOLTAGE,
@@ -455,10 +516,69 @@ static const struct iio_chan_spec hx711_chan_spec[] = {
IIO_CHAN_SOFT_TIMESTAMP(2),
};
+/*
+ * HX710B channels.
+ * Channel 0: differential input (IN+ vs IN-), 10 SPS, 1 trailing pulse.
+ * Channel 1: DVDD-AVDD supply monitor, 40 SPS, 2 trailing pulses.
+ * .address holds the trailing pulse count used by hx710b_set_channel().
+ */
+static const struct iio_chan_spec hx710b_chan_spec[] = {
+ {
+ .type = IIO_VOLTAGE,
+ .differential = 1,
+ .channel = 0,
+ .channel2 = 1,
+ .indexed = 1,
+ .address = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 24,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
+ },
+ {
+ .type = IIO_VOLTAGE,
+ .channel = 1,
+ .indexed = 1,
+ .address = 2,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .scan_index = 1,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 24,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(2),
+};
+
+static const struct hx711_chip_info hx711_chip = {
+ .name = "hx711",
+ .channels = hx711_chan_spec,
+ .num_channels = ARRAY_SIZE(hx711_chan_spec),
+ .iio_info = &hx711_iio_info,
+};
+
+static const struct hx711_chip_info hx710b_chip = {
+ .name = "hx710b",
+ .channels = hx710b_chan_spec,
+ .num_channels = ARRAY_SIZE(hx710b_chan_spec),
+ .iio_info = &hx710b_iio_info,
+ .fixed_gain = true,
+ .fixed_gain_val = 128,
+};
+
static int hx711_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct hx711_data *hx711_data;
+ const struct hx711_chip_info *chip_info;
struct iio_dev *indio_dev;
int ret;
int i;
@@ -472,6 +592,9 @@ static int hx711_probe(struct platform_device *pdev)
mutex_init(&hx711_data->lock);
+ chip_info = device_get_match_data(dev);
+ hx711_data->chip_info = chip_info;
+
/*
* PD_SCK stands for power down and serial clock input of HX711
* in the driver it is an output
@@ -510,12 +633,19 @@ static int hx711_probe(struct platform_device *pdev)
/* we need 10^-9 mV */
ret *= 100;
- for (i = 0; i < HX711_GAIN_MAX; i++)
- hx711_gain_to_scale[i].scale =
- ret / hx711_gain_to_scale[i].gain / 1678;
+ if (chip_info->fixed_gain) {
+ /* Fixed-gain variant: compute scale once at probe. */
+ hx711_data->scale = ret / chip_info->fixed_gain_val / 1678;
+ } else {
+ for (i = 0; i < HX711_GAIN_MAX; i++)
+ hx711_gain_to_scale[i].scale =
+ ret / hx711_gain_to_scale[i].gain / 1678;
+
+ hx711_data->gain_set = 128;
+ hx711_data->gain_chan_a = 128;
+ }
- hx711_data->gain_set = 128;
- hx711_data->gain_chan_a = 128;
+ indio_dev->info = chip_info->iio_info;
hx711_data->clock_frequency = 400000;
ret = device_property_read_u32(&pdev->dev, "clock-frequency",
@@ -533,11 +663,10 @@ static int hx711_probe(struct platform_device *pdev)
hx711_data->data_ready_delay_ns =
1000000000 / hx711_data->clock_frequency;
- indio_dev->name = "hx711";
- indio_dev->info = &hx711_iio_info;
+ indio_dev->name = chip_info->name;
indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->channels = hx711_chan_spec;
- indio_dev->num_channels = ARRAY_SIZE(hx711_chan_spec);
+ indio_dev->channels = chip_info->channels;
+ indio_dev->num_channels = chip_info->num_channels;
ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
iio_pollfunc_store_time,
@@ -554,7 +683,8 @@ static int hx711_probe(struct platform_device *pdev)
}
static const struct of_device_id of_hx711_match[] = {
- { .compatible = "avia,hx711", },
+ { .compatible = "avia,hx710b", .data = &hx710b_chip },
+ { .compatible = "avia,hx711", .data = &hx711_chip },
{ }
};
@@ -571,7 +701,7 @@ static struct platform_driver hx711_driver = {
module_platform_driver(hx711_driver);
MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
-MODULE_DESCRIPTION("HX711 bitbanging driver - ADC for weight cells");
+MODULE_DESCRIPTION("HX711/HX710B GPIO ADC driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:hx711-gpio");
--
2.43.0
^ permalink raw reply related
* [PATCH v2 1/2] dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible
From: Piyush Patle @ 2026-04-19 17:46 UTC (permalink / raw)
To: jic23, ak
Cc: dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt, linux-iio,
devicetree, linux-kernel
In-Reply-To: <20260419174654.683692-1-piyushpatle228@gmail.com>
The HX710B shares the same two-wire interface as the HX711 but differs
in its channel and gain model: gain is fixed at 128 and the number of
trailing PD_SCK pulses selects the input channel rather than the gain.
Add avia,hx710b to the compatible enum. Document the chip differences
in the description and add chip-specific supply properties (dvdd-supply,
vsup-supply) for the HX711, a rate-gpios property for the HX711 RATE
pin, and an allOf constraint that forbids HX711-only properties on
HX710B nodes. Clarify the clock-frequency description to reflect its
actual purpose: controlling the SCK bit-bang timing. Note that AVDD
serves as the voltage reference on both chips so no separate
vref-supply is needed.
Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
---
Changes in v2:
- Remove driver implementation details (bit-banging, channel-selection
mechanics) from the description; describe hardware behaviour only
- Drop unrelated punctuation cleanup (trailing period on PD_SCK description)
- Add dvdd-supply and vsup-supply optional properties for HX711
- Add rate-gpios optional property for the HX711 RATE pin; forbid it on
HX710B via the allOf if/then block
- Add note to avdd-supply clarifying it serves as voltage reference on
both chips (no separate vref-supply needed)
- Add allOf if/then block forbidding HX711-only properties on HX710B
- Fix clock-frequency description to reflect its true purpose (SCK
bit-bang timing control, not a crystal/external clock frequency)
- Sort compatible enum alphabetically (hx710b before hx711)
- Remove redundant example comments (compatible already identifies part)
- Update HX711 example to exercise the new rate-gpios property
.../bindings/iio/adc/avia-hx711.yaml | 61 ++++++++++++++++---
1 file changed, 51 insertions(+), 10 deletions(-)
diff --git a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
index 9c57eb13f892..35ac74a490b1 100644
--- a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
@@ -4,24 +4,24 @@
$id: http://devicetree.org/schemas/iio/adc/avia-hx711.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: AVIA HX711 ADC chip for weight cells
+title: AVIA HX711 and HX710B ADCs
maintainers:
- Andreas Klinger <ak@it-klinger.de>
description: |
- Bit-banging driver using two GPIOs:
- - sck-gpio gives a clock to the sensor with 24 cycles for data retrieval
- and up to 3 cycles for selection of the input channel and gain for the
- next measurement
- - dout-gpio is the sensor data the sensor responds to the clock
+ The HX711 is a 24-bit ADC with selectable gain (32/64/128) and two
+ differential input channels. Channel A supports gain 64 and 128;
+ channel B supports gain 32.
- Specifications about the driver can be found at:
- http://www.aviaic.com/ENProducts.aspx
+ The HX710B is a 24-bit ADC with fixed gain of 128. Channel 0 is the
+ differential input and channel 1 measures the DVDD-AVDD supply
+ voltage difference.
properties:
compatible:
enum:
+ - avia,hx710b
- avia,hx711
sck-gpios:
@@ -40,13 +40,45 @@ properties:
avdd-supply:
description:
- Definition of the regulator used as analog supply
+ Analog supply voltage (AVDD). Also serves as the voltage reference on
+ both chips; no separate vref-supply is required.
+
+ dvdd-supply:
+ description:
+ Digital supply voltage (DVDD). HX711 only.
+
+ vsup-supply:
+ description:
+ Supply voltage for the on-chip regulator (VSUP). HX711 only.
+
+ rate-gpios:
+ description:
+ GPIO connected to the RATE pin (HX711 only). When driven low the
+ output data rate is 10 SPS; when driven high it is 80 SPS. If
+ omitted the RATE pin state is determined by the board wiring.
+ maxItems: 1
clock-frequency:
+ description:
+ Controls the SCK bit-bang timing. The value is used to derive the
+ delay between SCK edges; keep the SCK high time below 60 us to
+ avoid triggering chip power-down mode. Defaults to 400 kHz if not
+ specified.
minimum: 20000
maximum: 2500000
default: 400000
+allOf:
+ - if:
+ properties:
+ compatible:
+ const: avia,hx710b
+ then:
+ properties:
+ vsup-supply: false
+ dvdd-supply: false
+ rate-gpios: false
+
required:
- compatible
- sck-gpios
@@ -58,10 +90,19 @@ additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
- weight {
+ weight0 {
compatible = "avia,hx711";
sck-gpios = <&gpio3 10 GPIO_ACTIVE_HIGH>;
dout-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
+ rate-gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>;
avdd-supply = <&avdd>;
clock-frequency = <100000>;
};
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ weight1 {
+ compatible = "avia,hx710b";
+ sck-gpios = <&gpio3 11 GPIO_ACTIVE_HIGH>;
+ dout-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>;
+ avdd-supply = <&avdd>;
+ };
--
2.43.0
^ permalink raw reply related
* [PATCH v2 0/2] iio: adc: hx711: add HX710B support
From: Piyush Patle @ 2026-04-19 17:46 UTC (permalink / raw)
To: jic23, ak
Cc: dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt, linux-iio,
devicetree, linux-kernel
Add support for the HX710B ADC, a variant of the HX711 with the same
GPIO interface but a different channel and gain model.
The first patch updates the devicetree binding to add the
`avia,hx710b` compatible, document the variant-specific behavior, and
add chip-specific properties for supplies, the RATE pin, and an allOf
constraint for HX710B nodes.
The second patch refactors the driver with per-chip configuration,
pulse counts stored in chan->address, a dedicated fixed_gain flag, and
the differential channel descriptor for the HX710B input.
Tested on PocketBeagle2 with an HX710B breakout module. The device
probed successfully and raw readings were stable.
Changes in v2:
- See individual patch changelogs for full details.
- dt-bindings: add dvdd-supply, vsup-supply, rate-gpios; allOf if/then
for HX710B; fix clock-frequency description; remove dead vendor URL;
clarify vref not needed (AVDD serves as reference on both chips)
- driver: fix pulse count bug ({25,26}→{1,2}); move counts to
chan->address; add fixed_gain flag; add .differential/.channel2;
remove NULL check; drop reset_channel; pass iio_chan_spec * directly
Piyush Patle (2):
dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible
iio: adc: hx711: add support for HX710B
.../bindings/iio/adc/avia-hx711.yaml | 61 +++++-
drivers/iio/adc/Kconfig | 9 +-
drivers/iio/adc/hx711.c | 206 ++++++++++++++----
3 files changed, 225 insertions(+), 51 deletions(-)
--
2.43.0
^ permalink raw reply
* [PATCH 2/2] arm64: dts: qcom: sc8280xp: gaokun3: correct EC interrupt pin
From: Pengyu Luo @ 2026-04-19 17:32 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: Pengyu Luo, linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <20260419173251.1180026-1-mitltlatltl@gmail.com>
Unlike other sc8280xp platforms, on this platform, in dsdt, gpio 0x2c0
is not mapped to gpio107, it is gpio103, so fix it. I found this until
I did a trigger track, irq is regularly triggerd every several
millisecs. In the past, since here gpio107 was low forever, ec irq
would keep to be triggered and polling the event every several
millisecs.
About how to get the map, please check openbsd driver for it
https://github.com/openbsd/src/blob/master/sys/dev/acpi/qcgpio.c
Signed-off-by: Pengyu Luo <mitltlatltl@gmail.com>
---
arch/arm64/boot/dts/qcom/sc8280xp-huawei-gaokun3.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/sc8280xp-huawei-gaokun3.dts b/arch/arm64/boot/dts/qcom/sc8280xp-huawei-gaokun3.dts
index 9819454abe13..d9d55241336e 100644
--- a/arch/arm64/boot/dts/qcom/sc8280xp-huawei-gaokun3.dts
+++ b/arch/arm64/boot/dts/qcom/sc8280xp-huawei-gaokun3.dts
@@ -637,7 +637,7 @@ embedded-controller@38 {
compatible = "huawei,gaokun3-ec";
reg = <0x38>;
- interrupts-extended = <&tlmm 107 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&tlmm 103 IRQ_TYPE_LEVEL_LOW>;
#address-cells = <1>;
#size-cells = <0>;
--
2.53.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox