Devicetree
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Yu-Chun Lin" <eleanor.lin@realtek.com>
Cc: devicetree@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH v4 3/4] gpio: realtek: Add driver for Realtek DHC RTD1625 SoC
Date: Mon, 22 Jun 2026 09:48:36 +0000	[thread overview]
Message-ID: <20260622094836.869CE1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260622092335.1166876-4-eleanor.lin@realtek.com>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] Incorrect hardware configuration and filtering for IRQ_TYPE_EDGE_BOTH causes missed falling edges and spurious double-interrupts.
- [High] Unmapped level interrupts are not masked, causing an infinite interrupt storm.
- [High] Clearing the hardware interrupt status in the .irq_unmask callback causes lost edge interrupts.
- [Medium] The driver uses a global raw_spinlock_irqsave for all register accesses, causing severe unnecessary contention.
--

commit 2c67ad7ec485f951d81fe09ef1853cbf7ebd2d95
Author: Tzuyi Chang <tychang@realtek.com>

gpio: realtek: Add driver for Realtek DHC RTD1625 SoC

Add support for the GPIO controller found on Realtek DHC RTD1625 SoCs.
The RTD1625 introduces a per-pin register architecture with a dedicated
32-bit control register per GPIO line. Interrupt support is optional.

> diff --git a/drivers/gpio/gpio-rtd1625.c b/drivers/gpio/gpio-rtd1625.c
> new file mode 100644
> index 0000000000000..409e540bf40b3
> --- /dev/null
> +++ b/drivers/gpio/gpio-rtd1625.c

[ ... ]

> +static int rtd1625_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
> +{
> +	struct rtd1625_gpio *data = gpiochip_get_data(chip);
> +	u32 val = RTD1625_GPIO_WREN(RTD1625_GPIO_OUT);
> +
> +	if (value)
> +		val |= RTD1625_GPIO_OUT;
> +
> +	guard(raw_spinlock_irqsave)(&data->lock);
> +
> +	writel_relaxed(val, data->base + GPIO_CONTROL(offset));
> +
> +	return 0;
> +}
> +
> +static int rtd1625_gpio_get(struct gpio_chip *chip, unsigned int offset)
> +{
> +	struct rtd1625_gpio *data = gpiochip_get_data(chip);
> +	u32 val;
> +
> +	guard(raw_spinlock_irqsave)(&data->lock);
> +
> +	val = readl_relaxed(data->base + GPIO_CONTROL(offset));

[Severity: Medium]
Since the RTD1625 hardware features a dedicated control register per GPIO
line and uses a Write-Enable bitmask design, do we need this global raw
spinlock?

It seems updates to individual bits are independent and atomic, and
readl_relaxed is inherently an atomic bus operation. Does wrapping these
operations in a single global lock across all 166 GPIOs unnecessarily
serialize all GPIO operations globally?

[ ... ]

> +static void rtd1625_gpio_irq_handle(struct irq_desc *desc)
> +{

[ ... ]

> +		for_each_set_bit(j, &status, 32) {
> +			hwirq = i + j;
> +			girq = irq_find_mapping(domain, hwirq);
> +			irq_type = irq_get_trigger_type(girq);

[Severity: High]
If a level interrupt fires on a pin that has no mapping (for example, if it
was left enabled by the bootloader), irq_find_mapping() returns 0 and
generic_handle_domain_irq() will return -EINVAL.

Because the child handler is never invoked, the active level interrupt is
never cleared or masked. Once the parent IRQ is unmasked, will the pending
level interrupt immediately re-trigger and cause an interrupt storm?

> +
> +			/*
> +			 * Filter out the hardware-forced de-assert interrupt unless
> +			 * the user explicitly requested IRQ_TYPE_EDGE_BOTH.
> +			 */
> +			if (irq == data->irqs[RTD1625_IRQ_DEASSERT] &&
> +			    irq_type != IRQ_TYPE_EDGE_BOTH)
> +				continue;
> +
> +			generic_handle_domain_irq(domain, hwirq);
> +		}

[Severity: High]
For IRQ_TYPE_EDGE_BOTH, does this filter intentionally let the duplicate
de-assert interrupt through?

Due to the hardware quirk where a single edge triggers both the assert and
de-assert IRQ lines, it appears this would cause generic_handle_domain_irq()
to be called twice sequentially for the exact same physical rising edge.

[ ... ]

> +static void rtd1625_gpio_enable_edge_irq(struct rtd1625_gpio *data, irq_hw_number_t hwirq)
> +{
> +	int gpda_reg_offset = rtd1625_gpio_gpda_offset(data, hwirq);
> +	int gpa_reg_offset = rtd1625_gpio_gpa_offset(data, hwirq);
> +	u32 clr_mask = BIT(hwirq % 32);
> +	u32 val;
> +
> +	guard(raw_spinlock_irqsave)(&data->lock);
> +
> +	writel_relaxed(clr_mask, data->irq_base + gpa_reg_offset);
> +	writel_relaxed(clr_mask, data->irq_base + gpda_reg_offset);
> +	val = RTD1625_GPIO_EDGE_INT_EN | RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_INT_EN);
> +	writel_relaxed(val, data->base + GPIO_CONTROL(hwirq));
> +}

[Severity: High]
This explicitly clears any pending hardware interrupts. Since this function
is called via the irq_unmask callback (mapped to rtd1625_gpio_enable_irq),
will this cause edge interrupts to be permanently lost if a hardware edge
occurs while the IRQ is temporarily masked?

Could status clearing be restricted to irq_startup or irq_ack?

[ ... ]

> +static int rtd1625_gpio_irq_set_type(struct irq_data *d, unsigned int type)
> +{
> +	switch (type & IRQ_TYPE_SENSE_MASK) {
> +	case IRQ_TYPE_EDGE_RISING:
> +		return rtd1625_gpio_irq_set_edge_type(d, 1);
> +
> +	case IRQ_TYPE_EDGE_FALLING:
> +		return rtd1625_gpio_irq_set_edge_type(d, 0);
> +
> +	case IRQ_TYPE_EDGE_BOTH:
> +		return rtd1625_gpio_irq_set_edge_type(d, 1);

[Severity: High]
Does this map IRQ_TYPE_EDGE_BOTH to the exact same hardware polarity
configuration as IRQ_TYPE_EDGE_RISING?

It seems the hardware will only detect rising edges and completely miss
falling edges. When combined with the filter in rtd1625_gpio_irq_handle(),
does EDGE_BOTH miss all falling edges and duplicate all rising edges?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260622092335.1166876-1-eleanor.lin@realtek.com?part=3

  reply	other threads:[~2026-06-22  9:48 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-22  9:23 [PATCH v4 0/4] gpio: realtek: Add support for Realtek DHC RTD1625 Yu-Chun Lin
2026-06-22  9:23 ` [PATCH v4 1/4] dt-bindings: gpio: realtek: Add realtek,rtd1625-gpio Yu-Chun Lin
2026-06-22  9:39   ` sashiko-bot
2026-06-22  9:23 ` [PATCH v4 2/4] gpio: Replace "default y" with "default ARCH_REALTEK" in Kconfig Yu-Chun Lin
2026-06-22  9:23 ` [PATCH v4 3/4] gpio: realtek: Add driver for Realtek DHC RTD1625 SoC Yu-Chun Lin
2026-06-22  9:48   ` sashiko-bot [this message]
2026-06-22  9:23 ` [PATCH v4 4/4] arm64: dts: realtek: Add GPIO support for RTD1625 Yu-Chun Lin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260622094836.869CE1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=eleanor.lin@realtek.com \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox