From nobody Fri Jul 24 05:22:04 2026 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E676034F497; Thu, 23 Jul 2026 03:43:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.75.126.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784778194; cv=none; b=KoZm2ZSIxU2rag0Q1BMnGkzjQ32qWTf5E/C3x/Snp9yPMWqwDwWvGGBXwiWieNCyxoe1G+SgGvuwJLF3HyJB4BnkcTMR6qwRTVKlW6UawTz2oh1dEAmRm+iHci71Izn62piBLjS5o5iFexf6H/gjC4TNOyObh6plJcBiFwuCo00= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784778194; c=relaxed/simple; bh=Jtzmvr/eS+6bIXGem7dg9wmyDatXm9TayvWUNa53CmE=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=U/Z5ggrQTO6zZVhiQS/elldpF+yc1/AvO4yOp924sNun/MNL9Yyn5dSLmjNhGkBsfxZ5uNgcydDDfIzluRX3kNRLrmwMmCYiRpxF3e9xV7hHmTCVYC2W74ajPDa4jpyr3zHmVfvJ8DD6YL7/jOE0ybokUV+FvsTMJ8ApNL7yf30= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com; spf=pass smtp.mailfrom=realtek.com; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b=MPRlwMj6; arc=none smtp.client-ip=211.75.126.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=realtek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b="MPRlwMj6" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 66N3gipR7179478, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realtek.com; s=dkim; t=1784778164; bh=Q4NFY3IzZpXs2fA+2q52QIn7YlGnwICLZjlI0B6J1nU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=MPRlwMj6RlClnAbXwdet3dJHcNtUv2yyXU1iq4R8FyfZILgmWTXpjdDwKjPB3jlki IOfFIJOf3B98qg+jyO8V9TkgM4wR9QMfhoVZFBrZG5Bdph2/OI2DPb3LbEy9MgY8Og tpfwWz4yEkNu0/Q89TtaBDtuFmu1Xnf6fpgObXP9C6O8g6SdZzU3RmsdwBf9MuoM0U O6ECzaROy1M2Ho6aqEbx8O21s1v3KVNMKdI5P+0t7K1LcxfWOP/CduzrV6KMFJlOra jyzXGce98lfkmD+NsDn5CVSJk8HLnHSjSZWonZt1z5gm9myehFtR4YKt2f7bE+jkGr hglP3GC6eqqQg== Received: from mail.realtek.com (rtkexhmbs04.realtek.com.tw[10.21.1.54]) by rtits2.realtek.com.tw (8.15.2/3.29/5.94) with ESMTPS id 66N3gipR7179478 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 23 Jul 2026 11:42:44 +0800 Received: from RTKEXHMBS06.realtek.com.tw (10.21.1.56) by RTKEXHMBS04.realtek.com.tw (10.21.1.54) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Thu, 23 Jul 2026 11:42:39 +0800 Received: from RTKEXHMBS06.realtek.com.tw (10.21.1.56) by RTKEXHMBS06.realtek.com.tw (10.21.1.56) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Thu, 23 Jul 2026 11:42:38 +0800 Received: from cn1dhc-k02 (172.21.252.101) by RTKEXHMBS06.realtek.com.tw (10.21.1.56) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Thu, 23 Jul 2026 11:42:38 +0800 From: Yu-Chun Lin To: , , , , , , , , , , , , , , CC: , , , , , , , Subject: [PATCH v7 1/9] Revert "gpio: realtek: Add driver for Realtek DHC RTD1625 SoC" Date: Thu, 23 Jul 2026 11:42:18 +0800 Message-ID: <20260723034237.2501507-2-eleanor.lin@realtek.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260723034237.2501507-1-eleanor.lin@realtek.com> References: <20260723034237.2501507-1-eleanor.lin@realtek.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This reverts commit a57e27c43b0315ee86c6896510d69be5257e093e. The driver will be rewritten to use the gpio-regmap infrastructure once Andy Shevchenko's patches for gpio-regmap are applied. Acked-by: Andy Shevchenko Signed-off-by: Yu-Chun Lin Acked-by: Linus Walleij --- Changes in v7: - Add Acked-by tag from Andy. --- drivers/gpio/Kconfig | 12 - drivers/gpio/Makefile | 1 - drivers/gpio/gpio-rtd1625.c | 611 ------------------------------------ 3 files changed, 624 deletions(-) delete mode 100644 drivers/gpio/gpio-rtd1625.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f03c05288376..ed2bc3113374 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -656,18 +656,6 @@ config GPIO_RTD Say yes here to support GPIO functionality and GPIO interrupt on Realtek DHC SoCs. =20 -config GPIO_RTD1625 - tristate "Realtek DHC RTD1625 GPIO support" - depends on ARCH_REALTEK || COMPILE_TEST - default ARCH_REALTEK - select GPIOLIB_IRQCHIP - help - This option enables support for the GPIO controller on Realtek - DHC (Digital Home Center) RTD1625 SoC. - - Say yes here to support both basic GPIO line functionality - and GPIO interrupt handling capabilities for this platform. - config GPIO_SAMA5D2_PIOBU tristate "SAMA5D2 PIOBU GPIO support" depends on OF diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index fa14581e3995..4d0e900402fc 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -160,7 +160,6 @@ obj-$(CONFIG_GPIO_REALTEK_OTTO) +=3D gpio-realtek-otto= .o obj-$(CONFIG_GPIO_REG) +=3D gpio-reg.o obj-$(CONFIG_GPIO_ROCKCHIP) +=3D gpio-rockchip.o obj-$(CONFIG_GPIO_RTD) +=3D gpio-rtd.o -obj-$(CONFIG_GPIO_RTD1625) +=3D gpio-rtd1625.o obj-$(CONFIG_ARCH_SA1100) +=3D gpio-sa1100.o obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) +=3D gpio-sama5d2-piobu.o obj-$(CONFIG_GPIO_SCH311X) +=3D gpio-sch311x.o diff --git a/drivers/gpio/gpio-rtd1625.c b/drivers/gpio/gpio-rtd1625.c deleted file mode 100644 index 409e540bf40b..000000000000 --- a/drivers/gpio/gpio-rtd1625.c +++ /dev/null @@ -1,611 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Realtek DHC RTD1625 gpio driver - * - * Copyright (c) 2023-2026 Realtek Semiconductor Corp. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTD1625_GPIO_DIR BIT(0) -#define RTD1625_GPIO_OUT BIT(2) -#define RTD1625_GPIO_IN BIT(4) -#define RTD1625_GPIO_EDGE_INT_DP BIT(6) -#define RTD1625_GPIO_EDGE_INT_EN BIT(8) -#define RTD1625_GPIO_LEVEL_INT_EN BIT(16) -#define RTD1625_GPIO_LEVEL_INT_DP BIT(18) -#define RTD1625_GPIO_DEBOUNCE GENMASK(30, 28) -#define RTD1625_GPIO_DEBOUNCE_WREN BIT(31) - -#define RTD1625_GPIO_WREN(x) ((x) << 1) - -/* Write-enable masks for all GPIO configs and reserved hardware bits */ -#define RTD1625_ISO_GPIO_WREN_ALL 0x8000aa8a -#define RTD1625_ISOM_GPIO_WREN_ALL 0x800aaa8a - -#define RTD1625_GPIO_DEBOUNCE_1US 0 -#define RTD1625_GPIO_DEBOUNCE_10US 1 -#define RTD1625_GPIO_DEBOUNCE_100US 2 -#define RTD1625_GPIO_DEBOUNCE_1MS 3 -#define RTD1625_GPIO_DEBOUNCE_10MS 4 -#define RTD1625_GPIO_DEBOUNCE_20MS 5 -#define RTD1625_GPIO_DEBOUNCE_30MS 6 -#define RTD1625_GPIO_DEBOUNCE_50MS 7 - -#define GPIO_CONTROL(gpio) ((gpio) * 4) - -enum rtd1625_irq_index { - RTD1625_IRQ_ASSERT, - RTD1625_IRQ_DEASSERT, - RTD1625_IRQ_LEVEL, - RTD1625_MAX_IRQS -}; - -/** - * struct rtd1625_gpio_info - Specific GPIO register information - * @num_gpios: The number of GPIOs - * @irq_type_support: Supported IRQ types - * @gpa_offset: Offset for GPIO assert interrupt status registers - * @gpda_offset: Offset for GPIO deassert interrupt status registers - * @level_offset: Offset of level interrupt status register - * @write_en_all: Write-enable mask for all configurable bits - */ -struct rtd1625_gpio_info { - unsigned int num_gpios; - unsigned int irq_type_support; - unsigned int base_offset; - unsigned int gpa_offset; - unsigned int gpda_offset; - unsigned int level_offset; - unsigned int write_en_all; -}; - -struct rtd1625_gpio { - struct gpio_chip gpio_chip; - const struct rtd1625_gpio_info *info; - void __iomem *base; - void __iomem *irq_base; - unsigned int irqs[RTD1625_MAX_IRQS]; - raw_spinlock_t lock; - unsigned int *save_regs; -}; - -static unsigned int rtd1625_gpio_gpa_offset(struct rtd1625_gpio *data, uns= igned int offset) -{ - return data->info->gpa_offset + ((offset / 32) * 4); -} - -static unsigned int rtd1625_gpio_gpda_offset(struct rtd1625_gpio *data, un= signed int offset) -{ - return data->info->gpda_offset + ((offset / 32) * 4); -} - -static unsigned int rtd1625_gpio_level_offset(struct rtd1625_gpio *data, u= nsigned int offset) -{ - return data->info->level_offset + ((offset / 32) * 4); -} - -static int rtd1625_gpio_set_debounce(struct gpio_chip *chip, unsigned int = offset, - unsigned int debounce) -{ - struct rtd1625_gpio *data =3D gpiochip_get_data(chip); - u8 deb_val; - u32 val; - - switch (debounce) { - case 1: - deb_val =3D RTD1625_GPIO_DEBOUNCE_1US; - break; - case 10: - deb_val =3D RTD1625_GPIO_DEBOUNCE_10US; - break; - case 100: - deb_val =3D RTD1625_GPIO_DEBOUNCE_100US; - break; - case 1000: - deb_val =3D RTD1625_GPIO_DEBOUNCE_1MS; - break; - case 10000: - deb_val =3D RTD1625_GPIO_DEBOUNCE_10MS; - break; - case 20000: - deb_val =3D RTD1625_GPIO_DEBOUNCE_20MS; - break; - case 30000: - deb_val =3D RTD1625_GPIO_DEBOUNCE_30MS; - break; - case 50000: - deb_val =3D RTD1625_GPIO_DEBOUNCE_50MS; - break; - default: - return -ENOTSUPP; - } - - val =3D FIELD_PREP(RTD1625_GPIO_DEBOUNCE, deb_val) | RTD1625_GPIO_DEBOUNC= E_WREN; - - guard(raw_spinlock_irqsave)(&data->lock); - - writel_relaxed(val, data->base + GPIO_CONTROL(offset)); - - return 0; -} - -static int rtd1625_gpio_set_config(struct gpio_chip *chip, unsigned int of= fset, - unsigned long config) -{ - u32 debounce; - - if (pinconf_to_config_param(config) =3D=3D PIN_CONFIG_INPUT_DEBOUNCE) { - debounce =3D pinconf_to_config_argument(config); - return rtd1625_gpio_set_debounce(chip, offset, debounce); - } - - return gpiochip_generic_config(chip, offset, config); -} - -static int rtd1625_gpio_set(struct gpio_chip *chip, unsigned int offset, i= nt value) -{ - struct rtd1625_gpio *data =3D gpiochip_get_data(chip); - u32 val =3D RTD1625_GPIO_WREN(RTD1625_GPIO_OUT); - - if (value) - val |=3D 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 =3D gpiochip_get_data(chip); - u32 val; - - guard(raw_spinlock_irqsave)(&data->lock); - - val =3D readl_relaxed(data->base + GPIO_CONTROL(offset)); - - if (val & RTD1625_GPIO_DIR) - return !!(val & RTD1625_GPIO_OUT); - else - return !!(val & RTD1625_GPIO_IN); -} - -static int rtd1625_gpio_get_direction(struct gpio_chip *chip, unsigned int= offset) -{ - struct rtd1625_gpio *data =3D gpiochip_get_data(chip); - u32 val; - - guard(raw_spinlock_irqsave)(&data->lock); - - val =3D readl_relaxed(data->base + GPIO_CONTROL(offset)); - - if (val & RTD1625_GPIO_DIR) - return GPIO_LINE_DIRECTION_OUT; - - return GPIO_LINE_DIRECTION_IN; -} - -static int rtd1625_gpio_set_direction(struct gpio_chip *chip, unsigned int= offset, bool out) -{ - struct rtd1625_gpio *data =3D gpiochip_get_data(chip); - u32 val =3D RTD1625_GPIO_WREN(RTD1625_GPIO_DIR); - - if (out) - val |=3D RTD1625_GPIO_DIR; - - guard(raw_spinlock_irqsave)(&data->lock); - - writel_relaxed(val, data->base + GPIO_CONTROL(offset)); - - return 0; -} - -static int rtd1625_gpio_direction_input(struct gpio_chip *chip, unsigned i= nt offset) -{ - return rtd1625_gpio_set_direction(chip, offset, false); -} - -static int rtd1625_gpio_direction_output(struct gpio_chip *chip, unsigned = int offset, int value) -{ - rtd1625_gpio_set(chip, offset, value); - - return rtd1625_gpio_set_direction(chip, offset, true); -} - -static void rtd1625_gpio_irq_handle(struct irq_desc *desc) -{ - unsigned int (*get_reg_offset)(struct rtd1625_gpio *gpio, unsigned int of= fset); - struct rtd1625_gpio *data =3D irq_desc_get_handler_data(desc); - struct irq_domain *domain =3D data->gpio_chip.irq.domain; - struct irq_chip *chip =3D irq_desc_get_chip(desc); - unsigned int irq =3D irq_desc_get_irq(desc); - unsigned long status; - unsigned int reg_offset, i, j; - unsigned int girq; - irq_hw_number_t hwirq; - u32 irq_type; - - if (irq =3D=3D data->irqs[RTD1625_IRQ_ASSERT]) - get_reg_offset =3D &rtd1625_gpio_gpa_offset; - else if (irq =3D=3D data->irqs[RTD1625_IRQ_DEASSERT]) - get_reg_offset =3D &rtd1625_gpio_gpda_offset; - else if (irq =3D=3D data->irqs[2]) - get_reg_offset =3D &rtd1625_gpio_level_offset; - else - return; - - chained_irq_enter(chip, desc); - - for (i =3D 0; i < data->info->num_gpios; i +=3D 32) { - reg_offset =3D get_reg_offset(data, i); - status =3D readl_relaxed(data->irq_base + reg_offset); - - /* - * Hardware quirk: The controller fires both "assert" and "de-assert" - * interrupts simultaneously on any edge toggle. - * We must pre-clear edge interrupts here. If we drop an unwanted - * de-assert interrupt below, it will never reach the IRQ core - * (generic_handle_domain_irq), meaning ->irq_ack() won't be called. - * Failing to clear it here leads to an interrupt storm. - */ - if (irq !=3D data->irqs[RTD1625_IRQ_LEVEL]) - writel_relaxed(status, data->irq_base + reg_offset); - - for_each_set_bit(j, &status, 32) { - hwirq =3D i + j; - girq =3D irq_find_mapping(domain, hwirq); - irq_type =3D irq_get_trigger_type(girq); - - /* - * Filter out the hardware-forced de-assert interrupt unless - * the user explicitly requested IRQ_TYPE_EDGE_BOTH. - */ - if (irq =3D=3D data->irqs[RTD1625_IRQ_DEASSERT] && - irq_type !=3D IRQ_TYPE_EDGE_BOTH) - continue; - - generic_handle_domain_irq(domain, hwirq); - } - } - - chained_irq_exit(chip, desc); -} - -static void rtd1625_gpio_ack_irq(struct irq_data *d) -{ - struct rtd1625_gpio *data =3D irq_data_get_irq_chip_data(d); - irq_hw_number_t hwirq =3D irqd_to_hwirq(d); - u32 irq_type =3D irqd_get_trigger_type(d); - u32 bit_mask =3D BIT(hwirq % 32); - int reg_offset; - - if (irq_type & IRQ_TYPE_LEVEL_MASK) { - reg_offset =3D rtd1625_gpio_level_offset(data, hwirq); - writel_relaxed(bit_mask, data->irq_base + reg_offset); - } -} - -static void rtd1625_gpio_enable_edge_irq(struct rtd1625_gpio *data, irq_hw= _number_t hwirq) -{ - int gpda_reg_offset =3D rtd1625_gpio_gpda_offset(data, hwirq); - int gpa_reg_offset =3D rtd1625_gpio_gpa_offset(data, hwirq); - u32 clr_mask =3D 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 =3D RTD1625_GPIO_EDGE_INT_EN | RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_IN= T_EN); - writel_relaxed(val, data->base + GPIO_CONTROL(hwirq)); -} - -static void rtd1625_gpio_disable_edge_irq(struct rtd1625_gpio *data, irq_h= w_number_t hwirq) -{ - u32 val; - - guard(raw_spinlock_irqsave)(&data->lock); - - val =3D RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_INT_EN); - writel_relaxed(val, data->base + GPIO_CONTROL(hwirq)); -} - -static void rtd1625_gpio_enable_level_irq(struct rtd1625_gpio *data, irq_h= w_number_t hwirq) -{ - int level_reg_offset =3D rtd1625_gpio_level_offset(data, hwirq); - u32 clr_mask =3D BIT(hwirq % 32); - u32 val; - - guard(raw_spinlock_irqsave)(&data->lock); - - writel_relaxed(clr_mask, data->irq_base + level_reg_offset); - val =3D RTD1625_GPIO_LEVEL_INT_EN | RTD1625_GPIO_WREN(RTD1625_GPIO_LEVEL_= INT_EN); - writel_relaxed(val, data->base + GPIO_CONTROL(hwirq)); -} - -static void rtd1625_gpio_disable_level_irq(struct rtd1625_gpio *data, irq_= hw_number_t hwirq) -{ - u32 val; - - guard(raw_spinlock_irqsave)(&data->lock); - - val =3D RTD1625_GPIO_WREN(RTD1625_GPIO_LEVEL_INT_EN); - writel_relaxed(val, data->base + GPIO_CONTROL(hwirq)); -} - -static void rtd1625_gpio_enable_irq(struct irq_data *d) -{ - struct gpio_chip *gc =3D irq_data_get_irq_chip_data(d); - struct rtd1625_gpio *data =3D gpiochip_get_data(gc); - irq_hw_number_t hwirq =3D irqd_to_hwirq(d); - u32 irq_type =3D irqd_get_trigger_type(d); - - gpiochip_enable_irq(gc, hwirq); - - if (irq_type & IRQ_TYPE_EDGE_BOTH) - rtd1625_gpio_enable_edge_irq(data, hwirq); - else if (irq_type & IRQ_TYPE_LEVEL_MASK) - rtd1625_gpio_enable_level_irq(data, hwirq); -} - -static void rtd1625_gpio_disable_irq(struct irq_data *d) -{ - struct gpio_chip *gc =3D irq_data_get_irq_chip_data(d); - struct rtd1625_gpio *data =3D gpiochip_get_data(gc); - irq_hw_number_t hwirq =3D irqd_to_hwirq(d); - u32 irq_type =3D irqd_get_trigger_type(d); - - if (irq_type & IRQ_TYPE_EDGE_BOTH) - rtd1625_gpio_disable_edge_irq(data, hwirq); - else if (irq_type & IRQ_TYPE_LEVEL_MASK) - rtd1625_gpio_disable_level_irq(data, hwirq); - - gpiochip_disable_irq(gc, hwirq); -} - -static int rtd1625_gpio_irq_set_level_type(struct irq_data *d, bool level) -{ - struct gpio_chip *gc =3D irq_data_get_irq_chip_data(d); - struct rtd1625_gpio *data =3D gpiochip_get_data(gc); - irq_hw_number_t hwirq =3D irqd_to_hwirq(d); - u32 val =3D RTD1625_GPIO_WREN(RTD1625_GPIO_LEVEL_INT_DP); - - if (!(data->info->irq_type_support & IRQ_TYPE_LEVEL_MASK)) - return -EINVAL; - - if (level) - val |=3D RTD1625_GPIO_LEVEL_INT_DP; - - scoped_guard(raw_spinlock_irqsave, &data->lock) - writel_relaxed(val, data->base + GPIO_CONTROL(hwirq)); - - irq_set_handler_locked(d, handle_level_irq); - - return 0; -} - -static int rtd1625_gpio_irq_set_edge_type(struct irq_data *d, bool polarit= y) -{ - struct gpio_chip *gc =3D irq_data_get_irq_chip_data(d); - struct rtd1625_gpio *data =3D gpiochip_get_data(gc); - irq_hw_number_t hwirq =3D irqd_to_hwirq(d); - u32 val =3D RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_INT_DP); - - if (!(data->info->irq_type_support & IRQ_TYPE_EDGE_BOTH)) - return -EINVAL; - - if (polarity) - val |=3D RTD1625_GPIO_EDGE_INT_DP; - - scoped_guard(raw_spinlock_irqsave, &data->lock) - writel_relaxed(val, data->base + GPIO_CONTROL(hwirq)); - - irq_set_handler_locked(d, handle_edge_irq); - - return 0; -} - -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); - - case IRQ_TYPE_LEVEL_HIGH: - return rtd1625_gpio_irq_set_level_type(d, 0); - - case IRQ_TYPE_LEVEL_LOW: - return rtd1625_gpio_irq_set_level_type(d, 1); - - default: - return -EINVAL; - } -} - -static struct irq_chip rtd1625_iso_gpio_irq_chip =3D { - .name =3D "rtd1625-gpio", - .irq_ack =3D rtd1625_gpio_ack_irq, - .irq_mask =3D rtd1625_gpio_disable_irq, - .irq_unmask =3D rtd1625_gpio_enable_irq, - .irq_set_type =3D rtd1625_gpio_irq_set_type, - .flags =3D IRQCHIP_IMMUTABLE | IRQCHIP_SKIP_SET_WAKE, - GPIOCHIP_IRQ_RESOURCE_HELPERS, -}; - -static int rtd1625_gpio_setup_irq(struct platform_device *pdev, struct rtd= 1625_gpio *data) -{ - struct gpio_irq_chip *irq_chip; - unsigned int num_irqs; - int irq; - - /* - * Interrupt support is optional. All IRQs must be provided together. - * If index 0 is missing, we assume no interrupts are configured in DT - * and fall back to basic GPIO operation. - */ - irq =3D platform_get_irq_optional(pdev, 0); - if (irq =3D=3D -ENXIO) - return 0; - if (irq < 0) - return irq; - - num_irqs =3D (data->info->irq_type_support & IRQ_TYPE_LEVEL_MASK) ? 3 : 2; - data->irqs[RTD1625_IRQ_ASSERT] =3D irq; - - for (unsigned int i =3D 1; i < num_irqs; i++) { - irq =3D platform_get_irq(pdev, i); - if (irq < 0) - return irq; - data->irqs[i] =3D irq; - } - - irq_chip =3D &data->gpio_chip.irq; - irq_chip->handler =3D handle_bad_irq; - irq_chip->default_type =3D IRQ_TYPE_NONE; - irq_chip->parent_handler =3D rtd1625_gpio_irq_handle; - irq_chip->parent_handler_data =3D data; - irq_chip->num_parents =3D num_irqs; - irq_chip->parents =3D data->irqs; - - gpio_irq_chip_set_chip(irq_chip, &rtd1625_iso_gpio_irq_chip); - - return 0; -} - -static int rtd1625_gpio_probe(struct platform_device *pdev) -{ - struct device *dev =3D &pdev->dev; - struct rtd1625_gpio *data; - void __iomem *irq_base; - int ret; - - data =3D devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->info =3D device_get_match_data(dev); - if (!data->info) - return -EINVAL; - - raw_spin_lock_init(&data->lock); - - irq_base =3D devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(irq_base)) - return PTR_ERR(irq_base); - - data->irq_base =3D irq_base; - data->base =3D irq_base + data->info->base_offset; - - data->save_regs =3D devm_kcalloc(dev, data->info->num_gpios, sizeof(*data= ->save_regs), - GFP_KERNEL); - if (!data->save_regs) - return -ENOMEM; - - data->gpio_chip.label =3D dev_name(dev); - data->gpio_chip.base =3D -1; - data->gpio_chip.ngpio =3D data->info->num_gpios; - data->gpio_chip.request =3D gpiochip_generic_request; - data->gpio_chip.free =3D gpiochip_generic_free; - data->gpio_chip.get_direction =3D rtd1625_gpio_get_direction; - data->gpio_chip.direction_input =3D rtd1625_gpio_direction_input; - data->gpio_chip.direction_output =3D rtd1625_gpio_direction_output; - data->gpio_chip.set =3D rtd1625_gpio_set; - data->gpio_chip.get =3D rtd1625_gpio_get; - data->gpio_chip.set_config =3D rtd1625_gpio_set_config; - data->gpio_chip.parent =3D dev; - - ret =3D rtd1625_gpio_setup_irq(pdev, data); - if (ret) - return ret; - - platform_set_drvdata(pdev, data); - - return devm_gpiochip_add_data(dev, &data->gpio_chip, data); -} - -static const struct rtd1625_gpio_info rtd1625_iso_gpio_info =3D { - .num_gpios =3D 166, - .irq_type_support =3D IRQ_TYPE_EDGE_BOTH, - .base_offset =3D 0x100, - .gpa_offset =3D 0x000, - .gpda_offset =3D 0x020, - .write_en_all =3D RTD1625_ISO_GPIO_WREN_ALL, -}; - -static const struct rtd1625_gpio_info rtd1625_isom_gpio_info =3D { - .num_gpios =3D 4, - .irq_type_support =3D IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_LEVEL_LOW | - IRQ_TYPE_LEVEL_HIGH, - .base_offset =3D 0x20, - .gpa_offset =3D 0x00, - .gpda_offset =3D 0x04, - .level_offset =3D 0x18, - .write_en_all =3D RTD1625_ISOM_GPIO_WREN_ALL, -}; - -static int rtd1625_gpio_suspend(struct device *dev) -{ - struct rtd1625_gpio *data =3D dev_get_drvdata(dev); - const struct rtd1625_gpio_info *info =3D data->info; - - for (unsigned int i =3D 0; i < info->num_gpios; i++) - data->save_regs[i] =3D readl_relaxed(data->base + GPIO_CONTROL(i)); - - return 0; -} - -static int rtd1625_gpio_resume(struct device *dev) -{ - struct rtd1625_gpio *data =3D dev_get_drvdata(dev); - const struct rtd1625_gpio_info *info =3D data->info; - - for (unsigned int i =3D 0; i < info->num_gpios; i++) - writel_relaxed(data->save_regs[i] | info->write_en_all, - data->base + GPIO_CONTROL(i)); - - return 0; -} - -static DEFINE_NOIRQ_DEV_PM_OPS(rtd1625_gpio_pm_ops, rtd1625_gpio_suspend, = rtd1625_gpio_resume); - -static const struct of_device_id rtd1625_gpio_of_matches[] =3D { - { .compatible =3D "realtek,rtd1625-iso-gpio", .data =3D &rtd1625_iso_gpio= _info }, - { .compatible =3D "realtek,rtd1625-isom-gpio", .data =3D &rtd1625_isom_gp= io_info }, - { } -}; -MODULE_DEVICE_TABLE(of, rtd1625_gpio_of_matches); - -static struct platform_driver rtd1625_gpio_platform_driver =3D { - .driver =3D { - .name =3D "gpio-rtd1625", - .of_match_table =3D rtd1625_gpio_of_matches, - .pm =3D pm_sleep_ptr(&rtd1625_gpio_pm_ops), - }, - .probe =3D rtd1625_gpio_probe, -}; -module_platform_driver(rtd1625_gpio_platform_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Realtek Semiconductor Corporation"); -MODULE_DESCRIPTION("Realtek DHC SoC RTD1625 gpio driver"); --=20 2.43.0 From nobody Fri Jul 24 05:22:04 2026 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0377E35C1B2; Thu, 23 Jul 2026 03:43:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.75.126.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784778195; cv=none; b=m1eNuW78VLHz9m6jwNv29eQs+s9GJNkWTUbX+V/FcJLyHggMOCZImpCBDFVN0RxDTaZnjIiKJD6a5Ggut+ixl9MYi63dFzRBtVms54iVjeFrAoQdo6JEHKJnth24ChVPeM4Jf09XULBaTFpfHX9j4ZWVWadUojjYEhKNGOIUCNM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784778195; c=relaxed/simple; bh=0Kf5mrxQNbj2Bt9nK9Srdu/hwTFLWaCBYKuE64lp1wU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=CLex6J5YG0kmiLuQUzHPdlM+37+zk4gqSSXIYOjUqF5gBrLNbVoY1ISFPo5WJ7O6ieUMljemFTCKfWOuFTk9KbuTaakkIXR8QjLpbsp1Jn+COmAG5FXtheT1e6iXUc9FV3scuS1J1CNCXaJubN0cFlIpE2EYPR9VP3o+Z2x3RoQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com; spf=pass smtp.mailfrom=realtek.com; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b=JQbF9DSb; arc=none smtp.client-ip=211.75.126.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=realtek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b="JQbF9DSb" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 66N3giWI3179480, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realtek.com; s=dkim; t=1784778164; bh=cZZ0lVXCD6wCWSv3NiWQbdaogTfhZ6MlrmbPdXV72LU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=JQbF9DSbuQGKfbeDqgiYVwqTHk2NqXnK6zbQezwgTFZjYFLMcIkKFwBY9hvUWIV1x 6he1YUp+vw1ap3IfLxGneK4p0IAS1Rm9pTkNq0SNAuxhYoxZmdvf4pf+srWYcaDkVx NrQWVyJm/JT2X45BlAkov4RrvOypGbZc2F4H1e/B3Eyje1mPYlwlPFdfmDasPwIl9Y ecgza0e7dH9H7P87EVhIeV9D86XUo0/9O7HKAntffV3pd/mwEGhvqZz32obF9Xbln4 rN5gNeLYLX5FhMZSTfX+N1p1jO7qzOdj4VEcfx851Q634ypWjHzq6nRscRwbG8Bf3b Y3DgaDDQ+5aYw== Received: from mail.realtek.com (rtkexhmbs04.realtek.com.tw[10.21.1.54]) by rtits2.realtek.com.tw (8.15.2/3.29/5.94) with ESMTPS id 66N3giWI3179480 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 23 Jul 2026 11:42:44 +0800 Received: from RTKEXHMBS06.realtek.com.tw (10.21.1.56) by RTKEXHMBS04.realtek.com.tw (10.21.1.54) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Thu, 23 Jul 2026 11:42:45 +0800 Received: from RTKEXHMBS06.realtek.com.tw (10.21.1.56) by RTKEXHMBS06.realtek.com.tw (10.21.1.56) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Thu, 23 Jul 2026 11:42:38 +0800 Received: from cn1dhc-k02 (172.21.252.101) by RTKEXHMBS06.realtek.com.tw (10.21.1.56) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Thu, 23 Jul 2026 11:42:38 +0800 From: Yu-Chun Lin To: , , , , , , , , , , , , , , CC: , , , , , , , , Andy Shevchenko Subject: [PATCH v7 2/9] gpio: regmap: Provide default IRQ resource request and release callbacks Date: Thu, 23 Jul 2026 11:42:19 +0800 Message-ID: <20260723034237.2501507-3-eleanor.lin@realtek.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260723034237.2501507-1-eleanor.lin@realtek.com> References: <20260723034237.2501507-1-eleanor.lin@realtek.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Andy Shevchenko When GPIO regmap based driver supplies its own IRQ domain, it might still want to keep track of the IRQ requests and releases, in particular to prevent a GPIO, which is used and locked as IRQ, to be requested via standard ways. Provide default callbacks for such cases and keep struct gpio_chip private to GPIO regmap implementation. Reviewed-by: Michael Walle Signed-off-by: Andy Shevchenko Signed-off-by: Yu-Chun Lin Reviewed-by: Linus Walleij --- Changes in v7: - Add Reviewed-by tag from Michael. --- drivers/gpio/gpio-regmap.c | 12 ++++++++++++ include/linux/gpio/regmap.h | 3 +++ 2 files changed, 15 insertions(+) diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c index 51b4d69b8740..535bd9deaa71 100644 --- a/drivers/gpio/gpio-regmap.c +++ b/drivers/gpio/gpio-regmap.c @@ -276,6 +276,18 @@ static int gpio_regmap_direction_output(struct gpio_ch= ip *chip, return gpio_regmap_set_direction(chip, offset, true); } =20 +int gpio_regmap_reqres_irq(struct gpio_regmap *gpio, unsigned int offset) +{ + return gpiochip_reqres_irq(&gpio->gpio_chip, offset); +} +EXPORT_SYMBOL_GPL(gpio_regmap_reqres_irq); + +void gpio_regmap_relres_irq(struct gpio_regmap *gpio, unsigned int offset) +{ + gpiochip_relres_irq(&gpio->gpio_chip, offset); +} +EXPORT_SYMBOL_GPL(gpio_regmap_relres_irq); + void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio) { return gpio->driver_data; diff --git a/include/linux/gpio/regmap.h b/include/linux/gpio/regmap.h index 06255756710d..e939709fde8d 100644 --- a/include/linux/gpio/regmap.h +++ b/include/linux/gpio/regmap.h @@ -121,4 +121,7 @@ struct gpio_regmap *devm_gpio_regmap_register(struct de= vice *dev, const struct gpio_regmap_config *config); void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio); =20 +int gpio_regmap_reqres_irq(struct gpio_regmap *gpio, unsigned int offset); +void gpio_regmap_relres_irq(struct gpio_regmap *gpio, unsigned int offset); + #endif /* _LINUX_GPIO_REGMAP_H */ --=20 2.43.0 From nobody Fri Jul 24 05:22:04 2026 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 036F335B63B; Thu, 23 Jul 2026 03:43:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.75.126.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784778195; cv=none; b=ThgC/3CYpx4jPdugXYbxIPoaiKGT1v0ql2VqAa8nej+QV6U352amHxXDN0PYoaVCC46k9gQnf4VF3sgtURbOllENTMWoEs3adyqAJCfihVNXPvvw27sN07MOV82+Hx1mVc6q72rm6z69762APN/IREPaHaFozSUfEHfqg4xmgE0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784778195; c=relaxed/simple; bh=ezQ+OkFt8NOqw2F6vKTeW2i9rDl4WSLpjRU1W5fmnvM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lznhKjMS4AkYTMnFM6EvbWKfWCGaRzB3m4y6ep2hoVO3JJEbCgralC/pR8UskWLbe827MGWGaun9WX0tvt0ubcz3FuCugtmfBAQ6vpn0SMkXAXlefhzu9nyhZhJ4YCcOVPwOVu7yo+BmfZHiLLfUFPcFJffG57Ko0S5cG4C01tg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com; spf=pass smtp.mailfrom=realtek.com; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b=HZj3kZA6; arc=none smtp.client-ip=211.75.126.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=realtek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b="HZj3kZA6" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 66N3giWK3179480, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realtek.com; s=dkim; t=1784778164; bh=l/qI6YwLPGByY44DwoS0pQF/mf2RQN5HFWtejzWxJTI=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=HZj3kZA69t0T4zgU6q1bughlr3PaWor5OR4EVsv9+Ihg0hWoPhY6OAUVHPNdPEbIM 5u4xqHQmMLMr0+TgDk82m3auaOZ7XZe1sCv+fdKS7ykd6dYDpfxTgyEY34QhZYUUoJ QtjqFdQLEl+9JRfm2gjdhhiYVL11pRXr/XepDRR0QyeBCctCWhxJSR+xdUYz/mjuj/ m6kY6svzd5v2+Ih0djX1t3G7QqJzBmBZC0o3JQchc+gFU9EZYmg8s2lAaiWtMpcE9a zZ3H6o3VLdcRhxPe1CgNhxcg7dERLosb0OxsdX/+SD6QHVKvDGjuOElHkRmYNg8ouR z7CkI68JG+vhQ== Received: from mail.realtek.com (rtkexhmbs04.realtek.com.tw[10.21.1.54]) by rtits2.realtek.com.tw (8.15.2/3.29/5.94) with ESMTPS id 66N3giWK3179480 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 23 Jul 2026 11:42:44 +0800 Received: from RTKEXHMBS06.realtek.com.tw (10.21.1.56) by RTKEXHMBS04.realtek.com.tw (10.21.1.54) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Thu, 23 Jul 2026 11:42:45 +0800 Received: from RTKEXHMBS06.realtek.com.tw (10.21.1.56) by RTKEXHMBS06.realtek.com.tw (10.21.1.56) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Thu, 23 Jul 2026 11:42:39 +0800 Received: from cn1dhc-k02 (172.21.252.101) by RTKEXHMBS06.realtek.com.tw (10.21.1.56) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Thu, 23 Jul 2026 11:42:39 +0800 From: Yu-Chun Lin To: , , , , , , , , , , , , , , CC: , , , , , , , , Andy Shevchenko Subject: [PATCH v7 3/9] gpio: regmap: Apply default resource callbacks for regmap IRQ chip Date: Thu, 23 Jul 2026 11:42:20 +0800 Message-ID: <20260723034237.2501507-4-eleanor.lin@realtek.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260723034237.2501507-1-eleanor.lin@realtek.com> References: <20260723034237.2501507-1-eleanor.lin@realtek.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Andy Shevchenko When GPIO regmap creates an IRQ chip on behalf of the user, it also takes an ownership of the respective callbacks and driver data. With that being done, apply default resource callbacks that keep tracking the IRQ requests and releases. Reviewed-by: Michael Walle Signed-off-by: Andy Shevchenko Signed-off-by: Yu-Chun Lin Reviewed-by: Linus Walleij Reviewed-by: Mathieu Dubois-Briand --- Changes in v7: - Add Reviewed-by tag from Michael. --- drivers/gpio/gpio-max7360.c | 7 ++++--- drivers/gpio/gpio-regmap.c | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-max7360.c b/drivers/gpio/gpio-max7360.c index d12cf1dc8d57..07eda49f375b 100644 --- a/drivers/gpio/gpio-max7360.c +++ b/drivers/gpio/gpio-max7360.c @@ -127,7 +127,7 @@ static int max7360_handle_mask_sync(const int index, const unsigned int mask_buf, void *const irq_drv_data) { - struct regmap *regmap =3D irq_drv_data; + struct regmap *regmap =3D gpio_regmap_get_drvdata(irq_drv_data); int ret; =20 for (unsigned int i =3D 0; i < MAX7360_MAX_GPIO; i++) { @@ -170,7 +170,6 @@ static int max7360_gpio_probe(struct platform_device *p= dev) =20 /* Create custom IRQ configuration. */ irq_chip =3D devm_kzalloc(dev, sizeof(*irq_chip), GFP_KERNEL); - gpio_config.regmap_irq_chip =3D irq_chip; if (!irq_chip) return -ENOMEM; =20 @@ -181,7 +180,9 @@ static int max7360_gpio_probe(struct platform_device *p= dev) irq_chip->num_irqs =3D MAX7360_MAX_GPIO; irq_chip->irqs =3D max7360_regmap_irqs; irq_chip->handle_mask_sync =3D max7360_handle_mask_sync; - irq_chip->irq_drv_data =3D regmap; + + gpio_config.regmap_irq_chip =3D irq_chip; + gpio_config.drvdata =3D regmap; =20 for (unsigned int i =3D 0; i < MAX7360_MAX_GPIO; i++) { ret =3D regmap_write_bits(regmap, MAX7360_REG_PWMCFG(i), diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c index 535bd9deaa71..658b892b624c 100644 --- a/drivers/gpio/gpio-regmap.c +++ b/drivers/gpio/gpio-regmap.c @@ -6,6 +6,7 @@ */ =20 #include +#include #include #include #include @@ -288,6 +289,16 @@ void gpio_regmap_relres_irq(struct gpio_regmap *gpio, = unsigned int offset) } EXPORT_SYMBOL_GPL(gpio_regmap_relres_irq); =20 +static int __maybe_unused gpio_regmap_irq_reqres(void *irq_drv_data, irq_h= w_number_t hwirq) +{ + return gpio_regmap_reqres_irq(irq_drv_data, hwirq); +} + +static void __maybe_unused gpio_regmap_irq_relres(void *irq_drv_data, irq_= hw_number_t hwirq) +{ + gpio_regmap_relres_irq(irq_drv_data, hwirq); +} + void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio) { return gpio->driver_data; @@ -409,6 +420,9 @@ struct gpio_regmap *gpio_regmap_register(const struct g= pio_regmap_config *config #ifdef CONFIG_REGMAP_IRQ if (config->regmap_irq_chip) { gpio->regmap_irq_line =3D config->regmap_irq_line; + config->regmap_irq_chip->irq_reqres =3D gpio_regmap_irq_reqres; + config->regmap_irq_chip->irq_relres =3D gpio_regmap_irq_relres; + config->regmap_irq_chip->irq_drv_data =3D gpio; ret =3D regmap_add_irq_chip_fwnode(dev_fwnode(config->parent), config->r= egmap, config->regmap_irq_line, config->regmap_irq_flags, 0, config->regmap_irq_chip, &gpio->irq_chip_data); --=20 2.43.0 From nobody Fri Jul 24 05:22:04 2026 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BD86F34DB41; Thu, 23 Jul 2026 03:43:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.75.126.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784778207; cv=none; b=bnwS2E8FnkTre0DjyGUhlDXGTeT37hPpTAzRL/qAkJ4zfj1/uCdn5grq954A9hMFyv4/ac7PchUqQI5H9co8EkyQF8Ui8wVyR4NPZEA2sZruiftiMWLypg4262qXt2+i3rql9lKJhhd06LNsXZhqHeP29Xvis9A3Fm/8yOZT+yc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784778207; c=relaxed/simple; bh=jxTtmT0MyaiHNlcNTGezbFY8S/0k2yAaWGDNXOYaD84=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=UKL4ndszuKOQ98jt2obt/XgzaaQ0tm/yOXaufxXZaFCRdNZZD3Bk7Ko7K2KXwHhn4H4N9I5dbz8CIQeljHdH/fzGwn7VlxnkHAuzKrUZbr8taDB+YUe1qBRbBo7RCn/lBCD+7+cee0dA1psJpjkhLD8vHqc/mOs9abZhKda2b9s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com; spf=pass smtp.mailfrom=realtek.com; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b=TMusY7tn; arc=none smtp.client-ip=211.75.126.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=realtek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b="TMusY7tn" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 66N3h0L91179581, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realtek.com; s=dkim; t=1784778181; bh=4J7kE3uhf8ifNvTJgZrsy1K3BpfHx2FxL1nQhdFEz/A=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=TMusY7tnszYANaST73kSjLYtqpCl5E+KG0zosato86O019SSyytXAUX/HwydDTpID Mj6OREJuadO60Z23fBGuWwR60u8UrWfgMTYzNIl9u6L968Z9XpvoHRi5fVipt1GlTm pWooWQ/zG2/zfAqWXJO5s0MLwRlGmEA361VaUJz416Tt7e38IGpJz4mvSKyM6Eh0Fs srqEKStxCeUnI+eLn6xpR12+yXSpmgzcNi3kTLC9qeEu/ZiXNbiQ/eurnt7/8HYwfI xjwANtGq+YsVi5FpIx3l+QylGAfvZ3NE4FbzyW0vDxfDBAvHFUYROAmINqppUOqJU6 eymcKNnu6bUfw== Received: from mail.realtek.com (rtkexhmbs02.realtek.com.tw[172.21.6.41]) by rtits2.realtek.com.tw (8.15.2/3.29/5.94) with ESMTPS id 66N3h0L91179581 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 23 Jul 2026 11:43:00 +0800 Received: from RTKEXHMBS05.realtek.com.tw (10.21.1.55) by RTKEXHMBS02.realtek.com.tw (172.21.6.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Thu, 23 Jul 2026 11:43:01 +0800 Received: from RTKEXHMBS06.realtek.com.tw (10.21.1.56) by RTKEXHMBS05.realtek.com.tw (10.21.1.55) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Thu, 23 Jul 2026 11:42:39 +0800 Received: from cn1dhc-k02 (172.21.252.101) by RTKEXHMBS06.realtek.com.tw (10.21.1.56) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Thu, 23 Jul 2026 11:42:39 +0800 From: Yu-Chun Lin To: , , , , , , , , , , , , , , CC: , , , , , , , , Andy Shevchenko Subject: [PATCH v7 4/9] gpio: regmap: Order kernel-doc descriptions with the actual appearance Date: Thu, 23 Jul 2026 11:42:21 +0800 Message-ID: <20260723034237.2501507-5-eleanor.lin@realtek.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260723034237.2501507-1-eleanor.lin@realtek.com> References: <20260723034237.2501507-1-eleanor.lin@realtek.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Andy Shevchenko Order kernel-doc descriptions with the actual appearance. Reviewed-by: Michael Walle Signed-off-by: Andy Shevchenko Signed-off-by: Yu-Chun Lin Reviewed-by: Linus Walleij --- Changes in v7: - Add Reviewed-by tag from Michael. - Fix indentation by replacing spaces with a tab. --- include/linux/gpio/regmap.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/linux/gpio/regmap.h b/include/linux/gpio/regmap.h index e939709fde8d..eb3931fbbad0 100644 --- a/include/linux/gpio/regmap.h +++ b/include/linux/gpio/regmap.h @@ -34,10 +34,6 @@ struct regmap; * @ngpio_per_reg: (Optional) Number of GPIOs per register * @irq_domain: (Optional) IRQ domain if the controller is * interrupt-capable - * @reg_mask_xlate: (Optional) Translates base address and GPIO - * offset to a register/bitmask pair. If not - * given the default gpio_regmap_simple_xlate() - * is used. * @fixed_direction_mask: * (Optional) Bitmap representing the GPIO lines that * make use of the @fixed_direction_output list to @@ -48,16 +44,20 @@ struct regmap; * (Optional) Bitmap representing the fixed direction of * the GPIO lines. Useful when there are GPIO lines with a * fixed direction mixed together in the same register. - * @drvdata: (Optional) Pointer to driver specific data which is - * not used by gpio-remap but is provided "as is" to the - * driver callback(s). - * @init_valid_mask: (Optional) Routine to initialize @valid_mask, to be u= sed - * if not all GPIOs are valid. * @regmap_irq_chip: (Optional) Pointer on an regmap_irq_chip structure. If * set, a regmap-irq device will be created and the IRQ * domain will be set accordingly. * @regmap_irq_line: (Optional) The IRQ the device uses to signal interrup= ts. * @regmap_irq_flags: (Optional) The IRQF_ flags to use for the interrupt. + * @reg_mask_xlate: (Optional) Translates base address and GPIO + * offset to a register/bitmask pair. If not + * given the default gpio_regmap_simple_xlate() + * is used. + * @init_valid_mask: (Optional) Routine to initialize @valid_mask, to be u= sed + * if not all GPIOs are valid. + * @drvdata: (Optional) Pointer to driver specific data which is + * not used by gpio-remap but is provided "as is" to the + * driver callback(s). * * The ->reg_mask_xlate translates a given base address and GPIO offset to * register and mask pair. The base address is one of the given register --=20 2.43.0 From nobody Fri Jul 24 05:22:04 2026 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3CD943603E8; Thu, 23 Jul 2026 03:43:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.75.126.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784778209; cv=none; b=Xu1AMuUDDYwSxF4xUpgkEK3X6SsavxkH6IbppmQTrTDyVQcIYvrRIVIkz+B+bc4svaq9BLTB3tDSje3wfw39yq0kHWpg7p266BXHR9Jm43KAv0YKJTLRGFz3H4rASlRFRukB8PKWAQuZjA3kvpXNvNLg2jaYCYXgaMnNBaDT1m0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784778209; c=relaxed/simple; bh=Ii0SncAnJrKg1DuNsXB2XzqJr0DyZ0AgXsyp4mP2mMw=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=uHWPou6a48r3+4i54bigxaF64FdMEQYE6fmLwwaiAQJ8lllNchLPCO/bxEfK4lIrFxm7JqGoCXrGiQexyQVxCbzh64tRkZGHODkYmsXPuGa6lk37NrnOIzwDIa0l7SWS8MUbbDEg3fuIC0NQg6kZYEEavjFUOJ/HKr6MJrsYu8Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com; spf=pass smtp.mailfrom=realtek.com; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b=JcP2dLLv; arc=none smtp.client-ip=211.75.126.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=realtek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b="JcP2dLLv" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 66N3h0K71179578, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realtek.com; s=dkim; t=1784778180; bh=UgVa1Pwpe/3NMs9yptxzF3PaFAoXJ6lYX3zZFmrziVk=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type:Content-Transfer-Encoding; b=JcP2dLLvvjUKbWMXmbj3ZkvFdgyrmgqctmPl/Xk1Pettzb66jmP7vK2l/havAp3Rs Ki8xTnWuqo9kTzMNCTRDUVtm9q8gUNqOy/UbCmslL6JJW5U0M39c3qpg3JwuLhng8e IxN1XpdDexmyN4XstDFPX2nzevwYdu5bErAVydDnYDseb4ZHzMwspCa5YmgUqlk/sQ +E+WOFQtVq+BcdK7WdrrptczKg3sqDWdKLd/7JiNRLzwWWJTD29Qqj56s7tF39tNL5 lOoPTOTL6Zb4Jo1yNnlNrNbUhEBr1HreYQ7wcW13geErT0k+KlLIaJBhWSD+Au08e5 FPrXZpCOPPTzA== Received: from mail.realtek.com (rtkexhmbs02.realtek.com.tw[172.21.6.41]) by rtits2.realtek.com.tw (8.15.2/3.29/5.94) with ESMTPS id 66N3h0K71179578 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 23 Jul 2026 11:43:00 +0800 Received: from RTKEXHMBS05.realtek.com.tw (10.21.1.55) by RTKEXHMBS02.realtek.com.tw (172.21.6.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Thu, 23 Jul 2026 11:43:01 +0800 Received: from RTKEXHMBS06.realtek.com.tw (10.21.1.56) by RTKEXHMBS05.realtek.com.tw (10.21.1.55) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Thu, 23 Jul 2026 11:42:45 +0800 Received: from cn1dhc-k02 (172.21.252.101) by RTKEXHMBS06.realtek.com.tw (10.21.1.56) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Thu, 23 Jul 2026 11:42:44 +0800 From: Yu-Chun Lin To: , , , , , , , , , , , , , , CC: , , , , , , , Subject: [PATCH v7 5/9] gpio: regmap: Add gpio_regmap_operation to extend reg_mask_xlate callback Date: Thu, 23 Jul 2026 11:42:22 +0800 Message-ID: <20260723034237.2501507-6-eleanor.lin@realtek.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260723034237.2501507-1-eleanor.lin@realtek.com> References: <20260723034237.2501507-1-eleanor.lin@realtek.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Extend the reg_mask_xlate callback with an operation type parameter (enum gpio_regmap_operation) to allow drivers to return different register/mask combinations depending on the specific GPIO operation. Consequently, update all existing drivers utilizing the gpio-regmap framework (across drivers/gpio, drivers/iio, and drivers/pinctrl) to accommodate the new reg_mask_xlate function signature. Suggested-by: Linus Walleij Signed-off-by: Yu-Chun Lin --- Changes in v7: - Move value_xlate changes into patch 6. - Add background context to kernel-doc comment for 'enum gpio_regmap_operation'. --- drivers/gpio/gpio-104-idi-48.c | 7 +++-- drivers/gpio/gpio-i8255.c | 4 +-- drivers/gpio/gpio-idio-16.c | 6 ++-- drivers/gpio/gpio-max7360.c | 1 + drivers/gpio/gpio-pcie-idio-24.c | 6 ++-- drivers/gpio/gpio-regmap.c | 31 +++++++++++++++------ drivers/iio/adc/ad7173.c | 8 +++--- drivers/iio/addac/stx104.c | 6 ++-- drivers/pinctrl/bcm/pinctrl-bcm63xx.c | 1 + drivers/pinctrl/pinctrl-tps6594.c | 1 + include/linux/gpio/regmap.h | 40 +++++++++++++++++++++++++-- 11 files changed, 81 insertions(+), 30 deletions(-) diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c index ba73ee9c0c29..fb017569cfa8 100644 --- a/drivers/gpio/gpio-104-idi-48.c +++ b/drivers/gpio/gpio-104-idi-48.c @@ -36,9 +36,10 @@ MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line n= umbers"); #define IDI48_IRQ_STATUS 0x7 #define IDI48_IRQ_ENABLE IDI48_IRQ_STATUS =20 -static int idi_48_reg_mask_xlate(struct gpio_regmap *gpio, unsigned int ba= se, - unsigned int offset, unsigned int *reg, - unsigned int *mask) +static int idi_48_reg_mask_xlate(struct gpio_regmap *gpio, + enum gpio_regmap_operation op, + unsigned int base, unsigned int offset, + unsigned int *reg, unsigned int *mask) { const unsigned int line =3D offset % 8; const unsigned int stride =3D offset / 8; diff --git a/drivers/gpio/gpio-i8255.c b/drivers/gpio/gpio-i8255.c index 953018bfa2b1..541a348447cd 100644 --- a/drivers/gpio/gpio-i8255.c +++ b/drivers/gpio/gpio-i8255.c @@ -67,8 +67,8 @@ static int i8255_ppi_init(struct regmap *const map, const= unsigned int base) return regmap_write(map, base + I8255_PORTC, 0x00); } =20 -static int i8255_reg_mask_xlate(struct gpio_regmap *gpio, unsigned int bas= e, - unsigned int offset, unsigned int *reg, +static int i8255_reg_mask_xlate(struct gpio_regmap *gpio, enum gpio_regmap= _operation op, + unsigned int base, unsigned int offset, unsigned int *reg, unsigned int *mask) { const unsigned int ppi =3D offset / I8255_NGPIO; diff --git a/drivers/gpio/gpio-idio-16.c b/drivers/gpio/gpio-idio-16.c index 4fbae6f6a497..9ac967c6b430 100644 --- a/drivers/gpio/gpio-idio-16.c +++ b/drivers/gpio/gpio-idio-16.c @@ -66,9 +66,9 @@ static int idio_16_handle_mask_sync(const int index, cons= t unsigned int mask_buf return 0; } =20 -static int idio_16_reg_mask_xlate(struct gpio_regmap *const gpio, const un= signed int base, - const unsigned int offset, unsigned int *const reg, - unsigned int *const mask) +static int idio_16_reg_mask_xlate(struct gpio_regmap *const gpio, enum gpi= o_regmap_operation op, + const unsigned int base, const unsigned int offset, + unsigned int *const reg, unsigned int *const mask) { unsigned int stride; =20 diff --git a/drivers/gpio/gpio-max7360.c b/drivers/gpio/gpio-max7360.c index 07eda49f375b..6755d58c4534 100644 --- a/drivers/gpio/gpio-max7360.c +++ b/drivers/gpio/gpio-max7360.c @@ -93,6 +93,7 @@ static int max7360_set_gpos_count(struct device *dev, str= uct regmap *regmap) } =20 static int max7360_gpio_reg_mask_xlate(struct gpio_regmap *gpio, + enum gpio_regmap_operation op, unsigned int base, unsigned int offset, unsigned int *reg, unsigned int *mask) { diff --git a/drivers/gpio/gpio-pcie-idio-24.c b/drivers/gpio/gpio-pcie-idio= -24.c index 80c0ba0afa67..b99f4863443d 100644 --- a/drivers/gpio/gpio-pcie-idio-24.c +++ b/drivers/gpio/gpio-pcie-idio-24.c @@ -225,9 +225,9 @@ static int idio_24_set_type_config(unsigned int **const= buf, const unsigned int return ret; } =20 -static int idio_24_reg_mask_xlate(struct gpio_regmap *const gpio, const un= signed int base, - const unsigned int offset, unsigned int *const reg, - unsigned int *const mask) +static int idio_24_reg_mask_xlate(struct gpio_regmap *const gpio, enum gpi= o_regmap_operation op, + const unsigned int base, const unsigned int offset, + unsigned int *const reg, unsigned int *const mask) { const unsigned int out_stride =3D offset / IDIO_24_NGPIO_PER_REG; const unsigned int in_stride =3D (offset - 24) / IDIO_24_NGPIO_PER_REG; diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c index 658b892b624c..1cc9c03ade99 100644 --- a/drivers/gpio/gpio-regmap.c +++ b/drivers/gpio/gpio-regmap.c @@ -40,9 +40,10 @@ struct gpio_regmap { struct regmap_irq_chip_data *irq_chip_data; #endif =20 - int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int base, - unsigned int offset, unsigned int *reg, - unsigned int *mask); + int (*reg_mask_xlate)(struct gpio_regmap *gpio, + enum gpio_regmap_operation op, + unsigned int base, unsigned int offset, + unsigned int *reg, unsigned int *mask); =20 void *driver_data; }; @@ -56,6 +57,7 @@ static unsigned int gpio_regmap_addr(unsigned int addr) } =20 static int gpio_regmap_simple_xlate(struct gpio_regmap *gpio, + enum gpio_regmap_operation __maybe_unused op, unsigned int base, unsigned int offset, unsigned int *reg, unsigned int *mask) { @@ -71,7 +73,7 @@ static int gpio_regmap_simple_xlate(struct gpio_regmap *g= pio, static int gpio_regmap_get(struct gpio_chip *chip, unsigned int offset) { struct gpio_regmap *gpio =3D gpiochip_get_data(chip); - unsigned int base, val, reg, mask; + unsigned int base, val, reg, mask, dir_mask; int ret; =20 /* we might not have an output register if we are input only */ @@ -80,7 +82,18 @@ static int gpio_regmap_get(struct gpio_chip *chip, unsig= ned int offset) else base =3D gpio_regmap_addr(gpio->reg_set_base); =20 - ret =3D gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); + ret =3D gpio->reg_mask_xlate(gpio, GPIO_REGMAP_GET_OP, base, offset, ®= , &dir_mask); + if (ret) + return ret; + + ret =3D regmap_read(gpio->regmap, reg, &val); + if (ret) + return ret; + + if (val & dir_mask) + ret =3D gpio->reg_mask_xlate(gpio, GPIO_REGMAP_OUT, base, offset, ®, = &mask); + else + ret =3D gpio->reg_mask_xlate(gpio, GPIO_REGMAP_IN, base, offset, ®, &= mask); if (ret) return ret; =20 @@ -103,7 +116,7 @@ static int gpio_regmap_set(struct gpio_chip *chip, unsi= gned int offset, unsigned int reg, mask, mask_val; int ret; =20 - ret =3D gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); + ret =3D gpio->reg_mask_xlate(gpio, GPIO_REGMAP_SET_OP, base, offset, ®= , &mask); if (ret) return ret; =20 @@ -133,7 +146,7 @@ static int gpio_regmap_set_with_clear(struct gpio_chip = *chip, else base =3D gpio_regmap_addr(gpio->reg_clr_base); =20 - ret =3D gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); + ret =3D gpio->reg_mask_xlate(gpio, GPIO_REGMAP_SET_OP, base, offset, ®= , &mask); if (ret) return ret; =20 @@ -183,7 +196,7 @@ static int gpio_regmap_get_direction(struct gpio_chip *= chip, return -ENOTSUPP; } =20 - ret =3D gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); + ret =3D gpio->reg_mask_xlate(gpio, GPIO_REGMAP_GET_DIR_OP, base, offset, = ®, &mask); if (ret) return ret; =20 @@ -237,7 +250,7 @@ static int gpio_regmap_set_direction(struct gpio_chip *= chip, return -ENOTSUPP; } =20 - ret =3D gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); + ret =3D gpio->reg_mask_xlate(gpio, GPIO_REGMAP_SET_DIR_OP, base, offset, = ®, &mask); if (ret) return ret; =20 diff --git a/drivers/iio/adc/ad7173.c b/drivers/iio/adc/ad7173.c index 9ee65d63c525..f78e758706ed 100644 --- a/drivers/iio/adc/ad7173.c +++ b/drivers/iio/adc/ad7173.c @@ -560,8 +560,8 @@ static int ad4111_openwire_event(struct iio_dev *indio_= dev, return ret; } =20 -static int ad7173_mask_xlate(struct gpio_regmap *gpio, unsigned int base, - unsigned int offset, unsigned int *reg, +static int ad7173_mask_xlate(struct gpio_regmap *gpio, enum gpio_regmap_op= eration op, + unsigned int base, unsigned int offset, unsigned int *reg, unsigned int *mask) { *mask =3D AD7173_GPO_DATA(offset); @@ -569,8 +569,8 @@ static int ad7173_mask_xlate(struct gpio_regmap *gpio, = unsigned int base, return 0; } =20 -static int ad4111_mask_xlate(struct gpio_regmap *gpio, unsigned int base, - unsigned int offset, unsigned int *reg, +static int ad4111_mask_xlate(struct gpio_regmap *gpio, enum gpio_regmap_op= eration op, + unsigned int base, unsigned int offset, unsigned int *reg, unsigned int *mask) { *mask =3D AD4111_GPO01_DATA(offset); diff --git a/drivers/iio/addac/stx104.c b/drivers/iio/addac/stx104.c index 7bdf2cb94176..6207eb2fac74 100644 --- a/drivers/iio/addac/stx104.c +++ b/drivers/iio/addac/stx104.c @@ -349,9 +349,9 @@ static const struct iio_chan_spec stx104_channels_diff[= ] =3D { STX104_IN_CHAN(6, 1), STX104_IN_CHAN(7, 1) }; =20 -static int stx104_reg_mask_xlate(struct gpio_regmap *const gpio, const uns= igned int base, - unsigned int offset, unsigned int *const reg, - unsigned int *const mask) +static int stx104_reg_mask_xlate(struct gpio_regmap *const gpio, enum gpio= _regmap_operation op, + const unsigned int base, unsigned int offset, + unsigned int *const reg, unsigned int *const mask) { /* Output lines are located at same register bit offsets as input lines */ if (offset >=3D 4) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm63xx.c b/drivers/pinctrl/bcm/pi= nctrl-bcm63xx.c index a4aa4146b530..b41a3d16aabe 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm63xx.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm63xx.c @@ -19,6 +19,7 @@ #define BCM63XX_DATA_REG 0x0c =20 static int bcm63xx_reg_mask_xlate(struct gpio_regmap *gpio, + enum gpio_regmap_operation op, unsigned int base, unsigned int offset, unsigned int *reg, unsigned int *mask) { diff --git a/drivers/pinctrl/pinctrl-tps6594.c b/drivers/pinctrl/pinctrl-tp= s6594.c index 456a3cfc8de9..937fc9cb54b7 100644 --- a/drivers/pinctrl/pinctrl-tps6594.c +++ b/drivers/pinctrl/pinctrl-tps6594.c @@ -346,6 +346,7 @@ static struct tps6594_pinctrl tps6594_template_pinctrl = =3D { }; =20 static int tps6594_gpio_regmap_xlate(struct gpio_regmap *gpio, + enum gpio_regmap_operation op, unsigned int base, unsigned int offset, unsigned int *reg, unsigned int *mask) { diff --git a/include/linux/gpio/regmap.h b/include/linux/gpio/regmap.h index eb3931fbbad0..ececc287d519 100644 --- a/include/linux/gpio/regmap.h +++ b/include/linux/gpio/regmap.h @@ -13,6 +13,40 @@ struct regmap; #define GPIO_REGMAP_ADDR_ZERO ((unsigned int)(-1)) #define GPIO_REGMAP_ADDR(addr) ((addr) ? : GPIO_REGMAP_ADDR_ZERO) =20 +/** + * enum gpio_regmap_operation - Operation type for reg_mask_xlate callback + * + * Traditionally, the operation type was inferred from the base register. + * However, that approach does not always work =E2=80=94 for example, when= all control + * bits of a single GPIO reside in the same register. This enum allows the + * reg_mask_xlate callback to explicitly distinguish between operation typ= es. + * The user is free to choose which method to use. + * + * Value operations: + * @GPIO_REGMAP_GET_OP: Mask for reading direction to detect if GPIO is in= put or + * output. Used in gpio_regmap_get() to determine the GPIO + * direction. + * @GPIO_REGMAP_IN: Mask for reading input value. Used when GPIO is config= ured as + * input. + * @GPIO_REGMAP_OUT: Mask for reading output value. Used when GPIO is conf= igured as + * output. + * + * Output operations: + * @GPIO_REGMAP_SET_OP: Mask for setting GPIO output value. + * + * Direction operations: + * @GPIO_REGMAP_GET_DIR_OP: Mask for reading GPIO direction (input/output). + * @GPIO_REGMAP_SET_DIR_OP: Mask for setting GPIO direction (input/output). + */ +enum gpio_regmap_operation { + GPIO_REGMAP_GET_OP, + GPIO_REGMAP_SET_OP, + GPIO_REGMAP_GET_DIR_OP, + GPIO_REGMAP_SET_DIR_OP, + GPIO_REGMAP_IN, + GPIO_REGMAP_OUT, +}; + /** * struct gpio_regmap_config - Description of a generic regmap gpio_chip. * @parent: The parent device @@ -104,9 +138,9 @@ struct gpio_regmap_config { unsigned long regmap_irq_flags; #endif =20 - int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int base, - unsigned int offset, unsigned int *reg, - unsigned int *mask); + int (*reg_mask_xlate)(struct gpio_regmap *gpio, enum gpio_regmap_operatio= n, + unsigned int base, unsigned int offset, + unsigned int *reg, unsigned int *mask); =20 int (*init_valid_mask)(struct gpio_chip *gc, unsigned long *valid_mask, --=20 2.43.0 From nobody Fri Jul 24 05:22:04 2026 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 24DEA34DB41; Thu, 23 Jul 2026 03:43:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.75.126.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784778201; cv=none; b=PncDlCxigq4v9dapTU7D0Z5nrKHt1VbMV1+3tqyH/sblx3vzOZr+zjCT0uPzwd/Nzq7ug2lHMq66zZSNauU1ATpeVvQO2gjxkNbpWuBEDMj7tBCOpdBoIkpkOyUjTOxGPVrRaYsIPJ2XEyqZ4m7ilFwSiF2gzYFYxIykzXPILlo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784778201; c=relaxed/simple; bh=7kqs3DMf/R6InNgEjhgwWNhfAWfAjGCag8CXa1NrSNg=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=V5xOP0mmFCpW/RpuQN7jEpXZ6ATf3R9PiHbKMJ8seWU9W+ku1IuddqtJd7bZQWI+HLc6lN6pL+1ac3P8xZhc7nvHZxDrRjKLR/f08CEn6SVxf5AjMGA0bi+L41EqAlmHfSmb+e7d2H5mRo7Fv8Z3afokC9BGCjI1kqKqDQhgjnA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com; spf=pass smtp.mailfrom=realtek.com; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b=Szt98KMB; arc=none smtp.client-ip=211.75.126.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=realtek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b="Szt98KMB" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 66N3gw0K3179525, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realtek.com; s=dkim; t=1784778178; bh=DLw0m+6lyX9ieILDuLH9M9GJ5YumVTZVgjbviF3a/d4=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=Szt98KMBygl0pyY1c1cUROu3wopdDgVC9rYLeKjhWDjw1Y07mD/xnhkOB631xgv0D ZUuIER1o28X+/ljlqVNV/SiMn1LRief24JjtGs2tSD4L9sYdPbGwCbB1eoOqXkMmPz ViNDL1MgHMZ7NWLLQSqwTqxxNOlNjcIMranZ1AL/UDa/lLkn8JDZ7cXoOy6U7wKjt8 Pe5m4Jjoe+acWm+XJl6/cpnoxMbynzGuf9Tem7Nsr3osKo+stQsZjrymUyiTTMLjgX Oj3s/bkD36P64RreNKATugG8AAcVkKEneyIpDDwj3sZ9q3YLFIpmoEwkAteRfKrJ0m Fp2ockELqTcKQ== Received: from mail.realtek.com (rtkexhmbs03.realtek.com.tw[10.21.1.53]) by rtits2.realtek.com.tw (8.15.2/3.29/5.94) with ESMTPS id 66N3gw0K3179525 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 23 Jul 2026 11:42:58 +0800 Received: from RTKEXHMBS06.realtek.com.tw (10.21.1.56) by RTKEXHMBS03.realtek.com.tw (10.21.1.53) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Thu, 23 Jul 2026 11:42:58 +0800 Received: from cn1dhc-k02 (172.21.252.101) by RTKEXHMBS06.realtek.com.tw (10.21.1.56) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Thu, 23 Jul 2026 11:42:58 +0800 From: Yu-Chun Lin To: , , , , , , , , , , , , , , CC: , , , , , , , Subject: [PATCH v7 6/9] gpio: regmap: Add value_xlate callback Date: Thu, 23 Jul 2026 11:42:23 +0800 Message-ID: <20260723034237.2501507-7-eleanor.lin@realtek.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260723034237.2501507-1-eleanor.lin@realtek.com> References: <20260723034237.2501507-1-eleanor.lin@realtek.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce a new optional 'value_xlate' callback. This routine allows drivers to translate or modify the register value and mask immediately before a wri= te operation. It is particularly useful for hardware that requires additional control bits, such as a write-enable bit, to be appended to the data dynamically. Suggested-by: Michael Walle Signed-off-by: Yu-Chun Lin Reviewed-by: Linus Walleij Reviewed-by: Michael Walle --- Changes in v7: - New patch --- drivers/gpio/gpio-regmap.c | 31 ++++++++++++++++++++++++++++++- include/linux/gpio/regmap.h | 8 ++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c index 1cc9c03ade99..8f58b272b870 100644 --- a/drivers/gpio/gpio-regmap.c +++ b/drivers/gpio/gpio-regmap.c @@ -45,6 +45,12 @@ struct gpio_regmap { unsigned int base, unsigned int offset, unsigned int *reg, unsigned int *mask); =20 + int (*value_xlate)(struct gpio_regmap *gpio, + enum gpio_regmap_operation op, + unsigned int base, unsigned int offset, + unsigned int reg, unsigned int *mask, + unsigned int *val); + void *driver_data; }; =20 @@ -125,6 +131,13 @@ static int gpio_regmap_set(struct gpio_chip *chip, uns= igned int offset, else mask_val =3D 0; =20 + if (gpio->value_xlate) { + ret =3D gpio->value_xlate(gpio, GPIO_REGMAP_SET_OP, base, offset, + reg, &mask, &mask_val); + if (ret) + return ret; + } + /* ignore input values which shadow the old output value */ if (gpio->reg_dat_base =3D=3D gpio->reg_set_base) ret =3D regmap_write_bits(gpio->regmap, reg, mask, mask_val); @@ -138,7 +151,7 @@ static int gpio_regmap_set_with_clear(struct gpio_chip = *chip, unsigned int offset, int val) { struct gpio_regmap *gpio =3D gpiochip_get_data(chip); - unsigned int base, reg, mask; + unsigned int base, reg, mask, value =3D 0; int ret; =20 if (val) @@ -150,6 +163,13 @@ static int gpio_regmap_set_with_clear(struct gpio_chip= *chip, if (ret) return ret; =20 + if (gpio->value_xlate) { + ret =3D gpio->value_xlate(gpio, GPIO_REGMAP_SET_OP, base, offset, + reg, &mask, &value); + if (ret) + return ret; + } + return regmap_write(gpio->regmap, reg, mask); } =20 @@ -259,6 +279,13 @@ static int gpio_regmap_set_direction(struct gpio_chip = *chip, else val =3D output ? mask : 0; =20 + if (gpio->value_xlate) { + ret =3D gpio->value_xlate(gpio, GPIO_REGMAP_SET_DIR_OP, base, offset, + reg, &mask, &val); + if (ret) + return ret; + } + return regmap_update_bits(gpio->regmap, reg, mask, val); } =20 @@ -426,6 +453,8 @@ struct gpio_regmap *gpio_regmap_register(const struct g= pio_regmap_config *config if (!gpio->reg_mask_xlate) gpio->reg_mask_xlate =3D gpio_regmap_simple_xlate; =20 + gpio->value_xlate =3D config->value_xlate; + ret =3D gpiochip_add_data(chip, gpio); if (ret < 0) goto err_free_bitmap_output; diff --git a/include/linux/gpio/regmap.h b/include/linux/gpio/regmap.h index ececc287d519..b77d6371cd9c 100644 --- a/include/linux/gpio/regmap.h +++ b/include/linux/gpio/regmap.h @@ -89,6 +89,10 @@ enum gpio_regmap_operation { * is used. * @init_valid_mask: (Optional) Routine to initialize @valid_mask, to be u= sed * if not all GPIOs are valid. + * @value_xlate: (Optional) Routine to translate the register value and + * mask before writing. This allows driver-specific logic + * to append additional bits (like write-enable masks) + * dynamically based on the current operation. * @drvdata: (Optional) Pointer to driver specific data which is * not used by gpio-remap but is provided "as is" to the * driver callback(s). @@ -146,6 +150,10 @@ struct gpio_regmap_config { unsigned long *valid_mask, unsigned int ngpios); =20 + int (*value_xlate)(struct gpio_regmap *gpio, enum gpio_regmap_operation, + unsigned int base, unsigned int offset, unsigned int reg, + unsigned int *mask, unsigned int *val); + void *drvdata; }; =20 --=20 2.43.0 From nobody Fri Jul 24 05:22:04 2026 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7B83A3546C0; Thu, 23 Jul 2026 03:43:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.75.126.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784778202; cv=none; b=byk5WVvj8WsQA/qr5kVNJXFjsLcPPBsJDeCqYGurtI+cNoP/CMNVBmBK66VugBnZbp0o/y4AQFDNMKRHLaGiHZSb4JH3ULYLGwPdyjh71p53/Z8JVqTFw+BpsohobJIpXZD5MkBxtolE/WeA56DXepc4iZUx45Eck8xdabM9sBE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784778202; c=relaxed/simple; bh=tfL44FI3uxStwiuVBSv7nfPKODjjXXRvWgd50ghsYP4=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=uCyo0wDAwhfIUrLtnIa0TN798voLvGAWx03Jk0bJf1n+wqQPbNMo3fEvzgSFopR/5hXERvABrDeDcAAHARhhehYenuUWfe4TtH1j0/aj4f8P3gt2t1gy05629k7vD375ALnFTP4D5awd8iz3qddRD1D0tKIBjJGaL/ng7xCJtQg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com; spf=pass smtp.mailfrom=realtek.com; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b=reQ37FOE; arc=none smtp.client-ip=211.75.126.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=realtek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b="reQ37FOE" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 66N3gwVU3179527, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realtek.com; s=dkim; t=1784778178; bh=mIpaTj+W0WSXdR2s6Ydth9yG4/Te14E0JihGrEBRZvk=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=reQ37FOE6mwL7G8Duhqyc/seRFvjWgE8F/N9m45/z4YNHP11j4H/LKiJZuzj3iViJ 3QgHmCIDTVv1BVxiwwtNt9Uhn6bz3UYi2uRalZn7e24+tSYUokH7Z/4WwZE2XscZ7z H03RcgPyrOtuoUpyhGSgYuXNa+QrePm4wSAtqOC3ZLI2yVTtzVFFVZm61i9ZVSyxen uF6mUw4tKRUnMeDkfX6uqaeAgw/l9n5BkCnH9umS5pbm861LX9MMO5k6h4OUFSiRh9 t1gKimawI326OFupxFO9Bs+WnTvPF7U0ab6Zz1T0g6xGtDSbLN+uv7GO/MUVUvIIEB igdMx7ddary2Q== Received: from mail.realtek.com (rtkexhmbs04.realtek.com.tw[10.21.1.54]) by rtits2.realtek.com.tw (8.15.2/3.29/5.94) with ESMTPS id 66N3gwVU3179527 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 23 Jul 2026 11:42:58 +0800 Received: from RTKEXHMBS06.realtek.com.tw (10.21.1.56) by RTKEXHMBS04.realtek.com.tw (10.21.1.54) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Thu, 23 Jul 2026 11:42:59 +0800 Received: from RTKEXHMBS06.realtek.com.tw (10.21.1.56) by RTKEXHMBS06.realtek.com.tw (10.21.1.56) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Thu, 23 Jul 2026 11:42:58 +0800 Received: from cn1dhc-k02 (172.21.252.101) by RTKEXHMBS06.realtek.com.tw (10.21.1.56) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Thu, 23 Jul 2026 11:42:58 +0800 From: Yu-Chun Lin To: , , , , , , , , , , , , , , CC: , , , , , , , Subject: [PATCH v7 7/9] gpio: regmap: Add set_config callback Date: Thu, 23 Jul 2026 11:42:24 +0800 Message-ID: <20260723034237.2501507-8-eleanor.lin@realtek.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260723034237.2501507-1-eleanor.lin@realtek.com> References: <20260723034237.2501507-1-eleanor.lin@realtek.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a new set_config callback to allow drivers to implement hardware-specific configuration such as debounce settings, or other platform-specific GPIO properties. Signed-off-by: Yu-Chun Lin Reviewed-by: Linus Walleij Reviewed-by: Michael Walle --- Changes in v7: - Drop the reviewed by tag from Andy due to the signature changes. - Add 'struct gpio_regmap' as the first parameter to the set_config callbac= k. - Add wrapper to bridge gpio_chip to gpio_regmap. --- drivers/gpio/gpio-regmap.c | 16 ++++++++++++++++ include/linux/gpio/regmap.h | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c index 8f58b272b870..98cfdd890069 100644 --- a/drivers/gpio/gpio-regmap.c +++ b/drivers/gpio/gpio-regmap.c @@ -51,6 +51,9 @@ struct gpio_regmap { unsigned int reg, unsigned int *mask, unsigned int *val); =20 + int (*set_config)(struct gpio_regmap *gpio, struct gpio_chip *chip, + unsigned int offset, unsigned long config); + void *driver_data; }; =20 @@ -317,6 +320,15 @@ static int gpio_regmap_direction_output(struct gpio_ch= ip *chip, return gpio_regmap_set_direction(chip, offset, true); } =20 +static int gpio_regmap_set_config(struct gpio_chip *chip, + unsigned int offset, + unsigned long cfg) +{ + struct gpio_regmap *gpio =3D gpiochip_get_data(chip); + + return gpio->set_config(gpio, chip, offset, cfg); +} + int gpio_regmap_reqres_irq(struct gpio_regmap *gpio, unsigned int offset) { return gpiochip_reqres_irq(&gpio->gpio_chip, offset); @@ -386,6 +398,7 @@ struct gpio_regmap *gpio_regmap_register(const struct g= pio_regmap_config *config gpio->reg_clr_base =3D config->reg_clr_base; gpio->reg_dir_in_base =3D config->reg_dir_in_base; gpio->reg_dir_out_base =3D config->reg_dir_out_base; + gpio->set_config =3D config->set_config; =20 chip =3D &gpio->gpio_chip; chip->parent =3D config->parent; @@ -455,6 +468,9 @@ struct gpio_regmap *gpio_regmap_register(const struct g= pio_regmap_config *config =20 gpio->value_xlate =3D config->value_xlate; =20 + if (config->set_config) + chip->set_config =3D gpio_regmap_set_config; + ret =3D gpiochip_add_data(chip, gpio); if (ret < 0) goto err_free_bitmap_output; diff --git a/include/linux/gpio/regmap.h b/include/linux/gpio/regmap.h index b77d6371cd9c..4bf4319ec12e 100644 --- a/include/linux/gpio/regmap.h +++ b/include/linux/gpio/regmap.h @@ -93,6 +93,9 @@ enum gpio_regmap_operation { * mask before writing. This allows driver-specific logic * to append additional bits (like write-enable masks) * dynamically based on the current operation. + * @set_config: (Optional) Callback for setting GPIO configuration such + * as debounce, drive strength, or other hardware specific + * settings. * @drvdata: (Optional) Pointer to driver specific data which is * not used by gpio-remap but is provided "as is" to the * driver callback(s). @@ -154,6 +157,9 @@ struct gpio_regmap_config { unsigned int base, unsigned int offset, unsigned int reg, unsigned int *mask, unsigned int *val); =20 + int (*set_config)(struct gpio_regmap *gpio, struct gpio_chip *chip, + unsigned int offset, unsigned long config); + void *drvdata; }; =20 --=20 2.43.0 From nobody Fri Jul 24 05:22:04 2026 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3CEE8361DB8; Thu, 23 Jul 2026 03:43:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.75.126.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784778209; cv=none; b=LjUPIDWScVQWdgbh6GOTFicMhW2GaCOQEHXgzdYIn/MvlnM9LyFDIrnMmYPLmTHXEAHR0MjB2Lrgl7McFsBFIrbC+Ifx7wcmEIfiHXtWzWjijARX6AadwUg60GkaZoBA6Iwvj13CjbkdMIOdUxfgwN4soxGEbUzy14+s2xbJav8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784778209; c=relaxed/simple; bh=Cm/RKXWnBXERGIbPA7j0nr4RNtwsj7QLUihqBUeTCTc=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=aq/psvP8fxnvLUVNkmhjyE3SB3Izqbzp7+MuzDmqWoL8v0NNikDoB5X4bBIcgDDSvBig0/SDitGYL+lbKGHzckuFaTUgeiea5Ddq68HlRpdTwa4Y94DtwjlncIb3QYO7VNn5l5q4eHEWA8QTCPzotzkfsr2zl6xpNYFUZHRqdBA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com; spf=pass smtp.mailfrom=realtek.com; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b=Kd/oKlx5; arc=none smtp.client-ip=211.75.126.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=realtek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b="Kd/oKlx5" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 66N3h0L71179581, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realtek.com; s=dkim; t=1784778180; bh=1+K3+yhdGwWiLaUt0U4utFuxXog7YaDwSauZcSSoHWo=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=Kd/oKlx5DnInV2We7JrAnD4879WOlRu4aWspCGA9fF9nm74Yjtjcw5J18/x4v+HBK ik31KxJvk3adpJrTDk+WaLucLSQnG7NsKvWrA4wmqB6iqdSA/SL41x8hmLgcxjtsxk L8N9isDQTvp6XsUzZ7/aBjN+39C5cdQpiP77AM5kB9elT4CU9vRyLTl2sZKynVT4li 687GnacjNYcTddKkJswUZQqNNmIg59zccjnLtFRgAMCCkJaVS76Zfbpsd7UE6RiPPN 9sDMz3P564Nehm3i8R3wus+Fu3tZY1o+8hYUj0kU/oLpPmisZgc3tajIKhk0nnUCr5 wKDX7w+BGBSjQ== Received: from mail.realtek.com (rtkexhmbs02.realtek.com.tw[172.21.6.41]) by rtits2.realtek.com.tw (8.15.2/3.29/5.94) with ESMTPS id 66N3h0L71179581 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 23 Jul 2026 11:43:00 +0800 Received: from RTKEXHMBS05.realtek.com.tw (10.21.1.55) by RTKEXHMBS02.realtek.com.tw (172.21.6.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Thu, 23 Jul 2026 11:43:01 +0800 Received: from RTKEXHMBS06.realtek.com.tw (10.21.1.56) by RTKEXHMBS05.realtek.com.tw (10.21.1.55) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Thu, 23 Jul 2026 11:42:59 +0800 Received: from cn1dhc-k02 (172.21.252.101) by RTKEXHMBS06.realtek.com.tw (10.21.1.56) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Thu, 23 Jul 2026 11:42:59 +0800 From: Yu-Chun Lin To: , , , , , , , , , , , , , , CC: , , , , , , , , Andy Shevchenko Subject: [PATCH v7 8/9] gpio: regmap: Add IRQ enable/disable helpers Date: Thu, 23 Jul 2026 11:42:25 +0800 Message-ID: <20260723034237.2501507-9-eleanor.lin@realtek.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260723034237.2501507-1-eleanor.lin@realtek.com> References: <20260723034237.2501507-1-eleanor.lin@realtek.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add gpio_regmap_enable_irq() and gpio_regmap_disable_irq(). Since struct gpio_regmap is opaque, drivers cannot access the embedded gpio_chip directl= y. Reviewed-by: Michael Walle Reviewed-by: Andy Shevchenko Suggested-by: Andy Shevchenko Signed-off-by: Yu-Chun Lin --- Changes in v7: - Add Reviewed-by tags from Michael and Andy. --- drivers/gpio/gpio-regmap.c | 12 ++++++++++++ include/linux/gpio/regmap.h | 5 +++++ 2 files changed, 17 insertions(+) diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c index 98cfdd890069..75b70aa1eb5b 100644 --- a/drivers/gpio/gpio-regmap.c +++ b/drivers/gpio/gpio-regmap.c @@ -357,6 +357,18 @@ void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio) } EXPORT_SYMBOL_GPL(gpio_regmap_get_drvdata); =20 +void gpio_regmap_enable_irq(struct gpio_regmap *gpio, irq_hw_number_t hwir= q) +{ + gpiochip_enable_irq(&gpio->gpio_chip, hwirq); +} +EXPORT_SYMBOL_GPL(gpio_regmap_enable_irq); + +void gpio_regmap_disable_irq(struct gpio_regmap *gpio, irq_hw_number_t hwi= rq) +{ + gpiochip_disable_irq(&gpio->gpio_chip, hwirq); +} +EXPORT_SYMBOL_GPL(gpio_regmap_disable_irq); + /** * gpio_regmap_register() - Register a generic regmap GPIO controller * @config: configuration for gpio_regmap diff --git a/include/linux/gpio/regmap.h b/include/linux/gpio/regmap.h index 4bf4319ec12e..483b5deadda9 100644 --- a/include/linux/gpio/regmap.h +++ b/include/linux/gpio/regmap.h @@ -3,6 +3,8 @@ #ifndef _LINUX_GPIO_REGMAP_H #define _LINUX_GPIO_REGMAP_H =20 +#include + struct device; struct fwnode_handle; struct gpio_regmap; @@ -172,4 +174,7 @@ void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio); int gpio_regmap_reqres_irq(struct gpio_regmap *gpio, unsigned int offset); void gpio_regmap_relres_irq(struct gpio_regmap *gpio, unsigned int offset); =20 +void gpio_regmap_enable_irq(struct gpio_regmap *gpio, irq_hw_number_t hwir= q); +void gpio_regmap_disable_irq(struct gpio_regmap *gpio, irq_hw_number_t hwi= rq); + #endif /* _LINUX_GPIO_REGMAP_H */ --=20 2.43.0 From nobody Fri Jul 24 05:22:04 2026 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3CE243603F7; Thu, 23 Jul 2026 03:43:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.75.126.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784778210; cv=none; b=T1ZUzL+1ke16n2QLybtFe0Y5dprhNhX6n9Vy9CgeYWFkF6+yFyDcEELNyIwUICoF+n4zq2xcjx4MCopT+hENKbyFZp1arxQg4HeozNGNdI+8UefjySZrHexwe/zvwEgzfAG//le8rXtkY0T1wHGl5iOU4+R5GZlUn1BLLG7/ap8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784778210; c=relaxed/simple; bh=lONco79yVIqhaNK5BuyksPdJ8FLmobNK8TnIVKTe7c8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=PFSToB1WDJ8KP0ybH+1p9s2lJIB7QNPV0GE59XywtU2rPvZRdIsOt81SKRsd16nALUyCMf+2HbFBejExV0LmW+6wrIYNp8Tp/UT2wJT3bD2EPygmAPJosyW1rKSbZXHSv/zB9CxlXJUNHPQk52NX7CZuZujXZHynhL97yq1Z5Ms= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com; spf=pass smtp.mailfrom=realtek.com; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b=HjzdOOqp; arc=none smtp.client-ip=211.75.126.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=realtek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b="HjzdOOqp" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 66N3h3njD179846, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realtek.com; s=dkim; t=1784778183; bh=+oXi6xpu3Bp0JTaZnzlVJTHhCpkBsjVyaNuCaZ8f8Ao=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=HjzdOOqpnssn/HxwC5nhEBwQ6MhEB6m6BCvKc7FGQoWiCiGF8mlnk4GSDDlFmJHtM AIhmYOnUE11UMiq3BNwTgwLyXFxEWM4AL9171aF4sIjVoSa7HdQ/ZBNhhmhIStZdw8 0/YGmD6QzwVfocHXBsxdy5Xn2lEVkkET1PNrwzT5nglpk2BcyBKjaXehVU9/Pd1IWn 7enzadfv7G2TspmywEqp2HyHjBFzZi3+fC4X5igf7AUJ8bJ5GD+KWaMancgdpsTvgL JajLOLsF/zw6BAty9rbpEgiPP2Y/DRVBGUC7iynbPdaPCYKuqfquB/XXCGG6o4ubt1 eIuSiufPyt8xQ== Received: from mail.realtek.com (rtkexhmbs04.realtek.com.tw[10.21.1.54]) by rtits2.realtek.com.tw (8.15.2/3.29/5.94) with ESMTPS id 66N3h3njD179846 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 23 Jul 2026 11:43:03 +0800 Received: from RTKEXHMBS05.realtek.com.tw (10.21.1.55) by RTKEXHMBS04.realtek.com.tw (10.21.1.54) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Thu, 23 Jul 2026 11:43:04 +0800 Received: from RTKEXHMBS06.realtek.com.tw (10.21.1.56) by RTKEXHMBS05.realtek.com.tw (10.21.1.55) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Thu, 23 Jul 2026 11:42:59 +0800 Received: from cn1dhc-k02 (172.21.252.101) by RTKEXHMBS06.realtek.com.tw (10.21.1.56) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Thu, 23 Jul 2026 11:42:59 +0800 From: Yu-Chun Lin To: , , , , , , , , , , , , , , CC: , , , , , , , Subject: [PATCH v7 9/9] gpio: realtek: Add driver for Realtek DHC RTD1625 SoC Date: Thu, 23 Jul 2026 11:42:26 +0800 Message-ID: <20260723034237.2501507-10-eleanor.lin@realtek.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260723034237.2501507-1-eleanor.lin@realtek.com> References: <20260723034237.2501507-1-eleanor.lin@realtek.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Tzuyi Chang Add support for the GPIO controller found on Realtek DHC RTD1625 SoCs. Unlike the existing Realtek GPIO driver (drivers/gpio/gpio-rtd.c), which manages pins via shared bank registers, the RTD1625 introduces a per-pin register architecture. Each GPIO line now has its own dedicated 32-bit control register to manage configuration independently, including direction, output value, input value, interrupt enable, and debounce. Therefore, this distinct hardware design requires a separate driver. The RTD1625 GPIO controller has a hardware quirk where both 'assert' and 'de-assert' interrupts are fired simultaneously on any edge toggle. The driver works around this quirk to correctly handle edge interrupts. Interrupt support is optional for this device, matching the dt-bindings. If the interrupts property is not provided, the driver simply skips IRQ initialization and operates purely as a basic GPIO controller. Signed-off-by: Tzuyi Chang Co-developed-by: Yu-Chun Lin Signed-off-by: Yu-Chun Lin --- Changes in v7: - Replace break with return 0 in functions that only consist of a switch-ca= se statement. - Add a comment for 'platform_get_irq_optional()'. - Update rtd1625_gpio_set_config() to align with the newly revised set_conf= ig signature. - Replace 'irq_domain_create_linear()' and 'devm_add_action_or_reset' with 'devm_irq_domain_instantiate()'. --- drivers/gpio/Kconfig | 14 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-rtd1625.c | 662 ++++++++++++++++++++++++++++++++++++ 3 files changed, 677 insertions(+) create mode 100644 drivers/gpio/gpio-rtd1625.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index ed2bc3113374..3b402ac505f1 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -656,6 +656,20 @@ config GPIO_RTD Say yes here to support GPIO functionality and GPIO interrupt on Realtek DHC SoCs. =20 +config GPIO_RTD1625 + tristate "Realtek DHC RTD1625 GPIO support" + depends on ARCH_REALTEK || COMPILE_TEST + default ARCH_REALTEK + select GPIOLIB_IRQCHIP + select GPIO_REGMAP + select REGMAP_MMIO + help + This option enables support for the GPIO controller on Realtek + DHC (Digital Home Center) RTD1625 SoC. + + Say yes here to support both basic GPIO line functionality + and GPIO interrupt handling capabilities for this platform. + config GPIO_SAMA5D2_PIOBU tristate "SAMA5D2 PIOBU GPIO support" depends on OF diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 4d0e900402fc..fa14581e3995 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -160,6 +160,7 @@ obj-$(CONFIG_GPIO_REALTEK_OTTO) +=3D gpio-realtek-otto= .o obj-$(CONFIG_GPIO_REG) +=3D gpio-reg.o obj-$(CONFIG_GPIO_ROCKCHIP) +=3D gpio-rockchip.o obj-$(CONFIG_GPIO_RTD) +=3D gpio-rtd.o +obj-$(CONFIG_GPIO_RTD1625) +=3D gpio-rtd1625.o obj-$(CONFIG_ARCH_SA1100) +=3D gpio-sa1100.o obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) +=3D gpio-sama5d2-piobu.o obj-$(CONFIG_GPIO_SCH311X) +=3D gpio-sch311x.o diff --git a/drivers/gpio/gpio-rtd1625.c b/drivers/gpio/gpio-rtd1625.c new file mode 100644 index 000000000000..5bb4fc91b24e --- /dev/null +++ b/drivers/gpio/gpio-rtd1625.c @@ -0,0 +1,662 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Realtek DHC RTD1625 gpio driver + * + * Copyright (c) 2023-2026 Realtek Semiconductor Corp. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RTD1625_GPIO_DIR BIT(0) +#define RTD1625_GPIO_OUT BIT(2) +#define RTD1625_GPIO_IN BIT(4) +#define RTD1625_GPIO_EDGE_INT_DP BIT(6) +#define RTD1625_GPIO_EDGE_INT_EN BIT(8) +#define RTD1625_GPIO_LEVEL_INT_EN BIT(16) +#define RTD1625_GPIO_LEVEL_INT_DP BIT(18) +#define RTD1625_GPIO_DEBOUNCE GENMASK(30, 28) +#define RTD1625_GPIO_DEBOUNCE_WREN BIT(31) + +#define RTD1625_GPIO_WREN(x) ((x) << 1) + +/* Write-enable masks for all GPIO configs and reserved hardware bits */ +#define RTD1625_ISO_GPIO_WREN_ALL 0x8000aa8a +#define RTD1625_ISOM_GPIO_WREN_ALL 0x800aaa8a + +#define RTD1625_GPIO_DEBOUNCE_1US 0 +#define RTD1625_GPIO_DEBOUNCE_10US 1 +#define RTD1625_GPIO_DEBOUNCE_100US 2 +#define RTD1625_GPIO_DEBOUNCE_1MS 3 +#define RTD1625_GPIO_DEBOUNCE_10MS 4 +#define RTD1625_GPIO_DEBOUNCE_20MS 5 +#define RTD1625_GPIO_DEBOUNCE_30MS 6 +#define RTD1625_GPIO_DEBOUNCE_50MS 7 + +#define GPIO_CONTROL(gpio) ((gpio) * 4) + +static struct lock_class_key rtd1625_gpio_irq_lock_class; +static struct lock_class_key rtd1625_gpio_irq_request_class; + +enum rtd1625_irq_index { + RTD1625_IRQ_ASSERT, + RTD1625_IRQ_DEASSERT, + RTD1625_IRQ_LEVEL, + RTD1625_MAX_IRQS +}; + +/** + * struct rtd1625_gpio_info - Specific GPIO register information + * @num_gpios: The number of GPIOs + * @irq_type_support: Supported IRQ types + * @base_offset: Offset for GPIO controller register + * @gpa_offset: Offset for GPIO assert interrupt status register + * @gpda_offset: Offset for GPIO deassert interrupt status register + * @level_offset: Offset of level interrupt status register + * @write_en_all: Write-enable mask for all configurable bits + */ +struct rtd1625_gpio_info { + unsigned int num_gpios; + unsigned int irq_type_support; + unsigned int base_offset; + unsigned int gpa_offset; + unsigned int gpda_offset; + unsigned int level_offset; + unsigned int write_en_all; +}; + +struct rtd1625_gpio { + struct gpio_regmap *gpio_reg; + const struct rtd1625_gpio_info *info; + struct regmap *regmap; + unsigned int irqs[RTD1625_MAX_IRQS]; + raw_spinlock_t lock; + struct irq_domain *domain; + unsigned int *save_regs; +}; + +static unsigned int rtd1625_gpio_gpa_offset(struct rtd1625_gpio *data, uns= igned int offset) +{ + return data->info->gpa_offset + ((offset / 32) * 4); +} + +static unsigned int rtd1625_gpio_gpda_offset(struct rtd1625_gpio *data, un= signed int offset) +{ + return data->info->gpda_offset + ((offset / 32) * 4); +} + +static unsigned int rtd1625_gpio_level_offset(struct rtd1625_gpio *data, u= nsigned int offset) +{ + return data->info->level_offset + ((offset / 32) * 4); +} + +static int rtd1625_reg_mask_xlate(struct gpio_regmap *gpio, enum gpio_regm= ap_operation op, + unsigned int base, unsigned int offset, unsigned int *reg, + unsigned int *mask) +{ + /* Each GPIO has its own dedicated 32-bit register */ + *reg =3D base + offset * 4; + + switch (op) { + case GPIO_REGMAP_IN: + *mask =3D RTD1625_GPIO_IN; + return 0; + + case GPIO_REGMAP_OUT: + *mask =3D RTD1625_GPIO_OUT; + return 0; + + case GPIO_REGMAP_SET_OP: + *mask =3D RTD1625_GPIO_OUT; + return 0; + + case GPIO_REGMAP_GET_OP: + case GPIO_REGMAP_GET_DIR_OP: + case GPIO_REGMAP_SET_DIR_OP: + *mask =3D RTD1625_GPIO_DIR; + return 0; + + default: + return -ENOTSUPP; + } +} + +static int rtd1625_value_xlate(struct gpio_regmap *gpio, + enum gpio_regmap_operation op, + unsigned int base, unsigned int offset, + unsigned int reg, unsigned int *mask, + unsigned int *val) +{ + switch (op) { + case GPIO_REGMAP_SET_OP: + *val |=3D RTD1625_GPIO_WREN(RTD1625_GPIO_OUT); + *mask |=3D RTD1625_GPIO_WREN(RTD1625_GPIO_OUT); + return 0; + + case GPIO_REGMAP_SET_DIR_OP: + *val |=3D RTD1625_GPIO_WREN(RTD1625_GPIO_DIR); + *mask |=3D RTD1625_GPIO_WREN(RTD1625_GPIO_DIR); + return 0; + + default: + return -ENOTSUPP; + } +} + +static int rtd1625_gpio_set_debounce(struct rtd1625_gpio *data, unsigned i= nt offset, + unsigned int debounce) +{ + u8 deb_val; + u32 val; + + switch (debounce) { + case 1: + deb_val =3D RTD1625_GPIO_DEBOUNCE_1US; + break; + case 10: + deb_val =3D RTD1625_GPIO_DEBOUNCE_10US; + break; + case 100: + deb_val =3D RTD1625_GPIO_DEBOUNCE_100US; + break; + case 1000: + deb_val =3D RTD1625_GPIO_DEBOUNCE_1MS; + break; + case 10000: + deb_val =3D RTD1625_GPIO_DEBOUNCE_10MS; + break; + case 20000: + deb_val =3D RTD1625_GPIO_DEBOUNCE_20MS; + break; + case 30000: + deb_val =3D RTD1625_GPIO_DEBOUNCE_30MS; + break; + case 50000: + deb_val =3D RTD1625_GPIO_DEBOUNCE_50MS; + break; + default: + return -ENOTSUPP; + } + + val =3D FIELD_PREP(RTD1625_GPIO_DEBOUNCE, deb_val) | RTD1625_GPIO_DEBOUNC= E_WREN; + + guard(raw_spinlock_irqsave)(&data->lock); + + return regmap_write(data->regmap, data->info->base_offset + GPIO_CONTROL(= offset), val); +} + +static int rtd1625_gpio_set_config(struct gpio_regmap *gpio, struct gpio_c= hip *chip, + unsigned int offset, unsigned long config) +{ + struct rtd1625_gpio *data =3D gpio_regmap_get_drvdata(gpio); + u32 debounce; + + if (pinconf_to_config_param(config) =3D=3D PIN_CONFIG_INPUT_DEBOUNCE) { + debounce =3D pinconf_to_config_argument(config); + return rtd1625_gpio_set_debounce(data, offset, debounce); + } + + return gpiochip_generic_config(chip, offset, config); +} + +static void rtd1625_gpio_irq_handle(struct irq_desc *desc) +{ + unsigned int (*get_reg_offset)(struct rtd1625_gpio *gpio, unsigned int of= fset); + struct rtd1625_gpio *data =3D irq_desc_get_handler_data(desc); + struct irq_chip *chip =3D irq_desc_get_chip(desc); + unsigned int irq =3D irq_desc_get_irq(desc); + struct irq_domain *domain =3D data->domain; + unsigned int reg_offset, i, j, val; + irq_hw_number_t hwirq; + unsigned long status; + u32 irq_type; + + if (irq =3D=3D data->irqs[RTD1625_IRQ_ASSERT]) + get_reg_offset =3D &rtd1625_gpio_gpa_offset; + else if (irq =3D=3D data->irqs[RTD1625_IRQ_DEASSERT]) + get_reg_offset =3D &rtd1625_gpio_gpda_offset; + else if (irq =3D=3D data->irqs[RTD1625_IRQ_LEVEL]) + get_reg_offset =3D &rtd1625_gpio_level_offset; + else + return; + + chained_irq_enter(chip, desc); + + for (i =3D 0; i < data->info->num_gpios; i +=3D 32) { + reg_offset =3D get_reg_offset(data, i); + regmap_read(data->regmap, reg_offset, &val); + + status =3D val; + + /* + * Hardware quirk: The controller fires both "assert" and "de-assert" + * interrupts simultaneously on any edge toggle. + * We must pre-clear edge interrupts here. If we drop an unwanted + * de-assert interrupt below, it will never reach the IRQ core + * (generic_handle_domain_irq), meaning ->irq_ack() won't be called. + * Failing to clear it here leads to an interrupt storm. + */ + if (irq !=3D data->irqs[RTD1625_IRQ_LEVEL]) + regmap_write(data->regmap, reg_offset, status); + + for_each_set_bit(j, &status, 32) { + hwirq =3D i + j; + irq_type =3D irq_get_trigger_type(irq_find_mapping(domain, hwirq)); + + /* + * Filter out the hardware-forced de-assert interrupt unless + * the user explicitly requested IRQ_TYPE_EDGE_BOTH. + */ + if (irq =3D=3D data->irqs[RTD1625_IRQ_DEASSERT] && + irq_type !=3D IRQ_TYPE_EDGE_BOTH) + continue; + + generic_handle_domain_irq(domain, hwirq); + } + } + + chained_irq_exit(chip, desc); +} + +static void rtd1625_gpio_ack_irq(struct irq_data *d) +{ + struct rtd1625_gpio *data =3D irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq =3D irqd_to_hwirq(d); + u32 irq_type =3D irqd_get_trigger_type(d); + u32 bit_mask =3D BIT(hwirq % 32); + int reg_offset; + + if (irq_type & IRQ_TYPE_LEVEL_MASK) { + reg_offset =3D rtd1625_gpio_level_offset(data, hwirq); + regmap_write(data->regmap, reg_offset, bit_mask); + } +} + +static void rtd1625_gpio_enable_edge_irq(struct rtd1625_gpio *data, irq_hw= _number_t hwirq) +{ + int gpda_reg_offset =3D rtd1625_gpio_gpda_offset(data, hwirq); + int gpa_reg_offset =3D rtd1625_gpio_gpa_offset(data, hwirq); + u32 clr_mask =3D BIT(hwirq % 32); + u32 val; + + guard(raw_spinlock_irqsave)(&data->lock); + + regmap_write(data->regmap, gpa_reg_offset, clr_mask); + regmap_write(data->regmap, gpda_reg_offset, clr_mask); + val =3D RTD1625_GPIO_EDGE_INT_EN | RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_IN= T_EN); + regmap_write(data->regmap, data->info->base_offset + GPIO_CONTROL(hwirq),= val); +} + +static void rtd1625_gpio_disable_edge_irq(struct rtd1625_gpio *data, irq_h= w_number_t hwirq) +{ + u32 val; + + guard(raw_spinlock_irqsave)(&data->lock); + + val =3D RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_INT_EN); + regmap_write(data->regmap, data->info->base_offset + GPIO_CONTROL(hwirq),= val); +} + +static void rtd1625_gpio_enable_level_irq(struct rtd1625_gpio *data, irq_h= w_number_t hwirq) +{ + int level_reg_offset =3D rtd1625_gpio_level_offset(data, hwirq); + u32 clr_mask =3D BIT(hwirq % 32); + u32 val; + + guard(raw_spinlock_irqsave)(&data->lock); + + regmap_write(data->regmap, level_reg_offset, clr_mask); + val =3D RTD1625_GPIO_LEVEL_INT_EN | RTD1625_GPIO_WREN(RTD1625_GPIO_LEVEL_= INT_EN); + regmap_write(data->regmap, data->info->base_offset + GPIO_CONTROL(hwirq),= val); +} + +static void rtd1625_gpio_disable_level_irq(struct rtd1625_gpio *data, irq_= hw_number_t hwirq) +{ + u32 val; + + guard(raw_spinlock_irqsave)(&data->lock); + + val =3D RTD1625_GPIO_WREN(RTD1625_GPIO_LEVEL_INT_EN); + regmap_write(data->regmap, data->info->base_offset + GPIO_CONTROL(hwirq),= val); +} + +static void rtd1625_gpio_enable_irq(struct irq_data *d) +{ + struct rtd1625_gpio *data =3D irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq =3D irqd_to_hwirq(d); + u32 irq_type =3D irqd_get_trigger_type(d); + + gpio_regmap_enable_irq(data->gpio_reg, hwirq); + + if (irq_type & IRQ_TYPE_EDGE_BOTH) + rtd1625_gpio_enable_edge_irq(data, hwirq); + else if (irq_type & IRQ_TYPE_LEVEL_MASK) + rtd1625_gpio_enable_level_irq(data, hwirq); +} + +static void rtd1625_gpio_disable_irq(struct irq_data *d) +{ + struct rtd1625_gpio *data =3D irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq =3D irqd_to_hwirq(d); + u32 irq_type =3D irqd_get_trigger_type(d); + + if (irq_type & IRQ_TYPE_EDGE_BOTH) + rtd1625_gpio_disable_edge_irq(data, hwirq); + else if (irq_type & IRQ_TYPE_LEVEL_MASK) + rtd1625_gpio_disable_level_irq(data, hwirq); + + gpio_regmap_disable_irq(data->gpio_reg, hwirq); +} + +static int rtd1625_gpio_irq_set_level_type(struct irq_data *d, bool level) +{ + u32 val =3D RTD1625_GPIO_WREN(RTD1625_GPIO_LEVEL_INT_DP); + irq_hw_number_t hwirq =3D irqd_to_hwirq(d); + struct rtd1625_gpio *data; + int ret; + + data =3D irq_data_get_irq_chip_data(d); + if (!(data->info->irq_type_support & IRQ_TYPE_LEVEL_MASK)) + return -EINVAL; + + if (level) + val |=3D RTD1625_GPIO_LEVEL_INT_DP; + + scoped_guard(raw_spinlock_irqsave, &data->lock) { + ret =3D regmap_write(data->regmap, data->info->base_offset + GPIO_CONTRO= L(hwirq), val); + if (ret) + return ret; + } + + irq_set_handler_locked(d, handle_level_irq); + + return 0; +} + +static int rtd1625_gpio_irq_set_edge_type(struct irq_data *d, bool polarit= y) +{ + struct rtd1625_gpio *data =3D irq_data_get_irq_chip_data(d); + u32 val =3D RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_INT_DP); + irq_hw_number_t hwirq =3D irqd_to_hwirq(d); + int ret; + + if (!(data->info->irq_type_support & IRQ_TYPE_EDGE_BOTH)) + return -EINVAL; + + if (polarity) + val |=3D RTD1625_GPIO_EDGE_INT_DP; + + scoped_guard(raw_spinlock_irqsave, &data->lock) + ret =3D regmap_write(data->regmap, data->info->base_offset + GPIO_CONTRO= L(hwirq), val); + + if (ret) + return ret; + + irq_set_handler_locked(d, handle_edge_irq); + + return 0; +} + +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); + + case IRQ_TYPE_LEVEL_HIGH: + return rtd1625_gpio_irq_set_level_type(d, 0); + + case IRQ_TYPE_LEVEL_LOW: + return rtd1625_gpio_irq_set_level_type(d, 1); + + default: + return -EINVAL; + } +} + +static int rtd1625_gpio_irq_request_resources(struct irq_data *d) +{ + struct rtd1625_gpio *data =3D irq_data_get_irq_chip_data(d); + + return gpio_regmap_reqres_irq(data->gpio_reg, d->hwirq); +} + +static void rtd1625_gpio_irq_release_resources(struct irq_data *d) +{ + struct rtd1625_gpio *data =3D irq_data_get_irq_chip_data(d); + + gpio_regmap_relres_irq(data->gpio_reg, d->hwirq); +} + +static struct irq_chip rtd1625_iso_gpio_irq_chip =3D { + .name =3D "rtd1625-gpio", + .irq_ack =3D rtd1625_gpio_ack_irq, + .irq_mask =3D rtd1625_gpio_disable_irq, + .irq_unmask =3D rtd1625_gpio_enable_irq, + .irq_set_type =3D rtd1625_gpio_irq_set_type, + .flags =3D IRQCHIP_IMMUTABLE | IRQCHIP_SKIP_SET_WAKE, + .irq_request_resources =3D rtd1625_gpio_irq_request_resources, + .irq_release_resources =3D rtd1625_gpio_irq_release_resources, +}; + +static int rtd1625_gpio_setup_irq(struct platform_device *pdev, struct rtd= 1625_gpio *data) +{ + unsigned int num_irqs; + int irq; + + /* IRQ is optional; operate as basic GPIO if absent */ + irq =3D platform_get_irq_optional(pdev, 0); + if (irq =3D=3D -ENXIO) + return 0; + if (irq < 0) + return irq; + + num_irqs =3D (data->info->irq_type_support & IRQ_TYPE_LEVEL_MASK) ? 3 : 2; + + for (unsigned int i =3D 0; i < num_irqs; i++) { + irq =3D platform_get_irq(pdev, i); + if (irq < 0) + return irq; + + data->irqs[i] =3D irq; + irq_set_chained_handler_and_data(data->irqs[i], rtd1625_gpio_irq_handle,= data); + } + + return 0; +} + +static int rtd1625_gpio_irq_map(struct irq_domain *domain, unsigned int ir= q, + irq_hw_number_t hwirq) +{ + struct rtd1625_gpio *data =3D domain->host_data; + + irq_set_chip_data(irq, data); + + irq_set_chip_and_handler(irq, &rtd1625_iso_gpio_irq_chip, handle_bad_irq); + + irq_set_noprobe(irq); + + irq_set_lockdep_class(irq, &rtd1625_gpio_irq_lock_class, + &rtd1625_gpio_irq_request_class); + + return 0; +} + +static const struct irq_domain_ops rtd1625_gpio_irq_domain_ops =3D { + .map =3D rtd1625_gpio_irq_map, + .xlate =3D irq_domain_xlate_twocell, +}; + +static const struct regmap_config rtd1625_gpio_regmap_config =3D { + .reg_bits =3D 32, + .reg_stride =3D 4, + .val_bits =3D 32, +#ifndef CONFIG_DEBUG_GPIO + .disable_locking =3D true, +#endif +}; + +static int rtd1625_gpio_probe(struct platform_device *pdev) +{ + struct gpio_regmap_config config =3D {}; + struct irq_domain_info d_info =3D {}; + struct device *dev =3D &pdev->dev; + struct gpio_regmap *gpio_reg; + struct rtd1625_gpio *data; + void __iomem *irq_base; + int ret; + + data =3D devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->info =3D device_get_match_data(dev); + if (!data->info) + return -ENODATA; + + irq_base =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(irq_base)) + return PTR_ERR(irq_base); + + data->regmap =3D devm_regmap_init_mmio(dev, irq_base, &rtd1625_gpio_regma= p_config); + if (IS_ERR(data->regmap)) + return PTR_ERR(data->regmap); + + raw_spin_lock_init(&data->lock); + platform_set_drvdata(pdev, data); + + data->save_regs =3D devm_kcalloc(dev, data->info->num_gpios, sizeof(*data= ->save_regs), + GFP_KERNEL); + if (!data->save_regs) + return -ENOMEM; + + config.parent =3D dev; + config.regmap =3D data->regmap; + config.ngpio =3D data->info->num_gpios; + config.reg_dat_base =3D data->info->base_offset; + config.reg_set_base =3D data->info->base_offset; + config.reg_dir_out_base =3D data->info->base_offset; + + config.reg_mask_xlate =3D rtd1625_reg_mask_xlate; + config.set_config =3D rtd1625_gpio_set_config; + config.value_xlate =3D rtd1625_value_xlate; + + d_info.fwnode =3D dev_fwnode(&pdev->dev); + d_info.size =3D data->info->num_gpios; + d_info.hwirq_max =3D data->info->num_gpios; + d_info.ops =3D &rtd1625_gpio_irq_domain_ops; + d_info.host_data =3D data; + + data->domain =3D devm_irq_domain_instantiate(dev, &d_info); + if (IS_ERR(data->domain)) + return PTR_ERR(data->domain); + + ret =3D rtd1625_gpio_setup_irq(pdev, data); + if (ret) + return ret; + + config.irq_domain =3D data->domain; + config.drvdata =3D data; + + gpio_reg =3D devm_gpio_regmap_register(dev, &config); + if (IS_ERR(gpio_reg)) + return PTR_ERR(gpio_reg); + + data->gpio_reg =3D gpio_reg; + + return 0; +} + +static const struct rtd1625_gpio_info rtd1625_iso_gpio_info =3D { + .num_gpios =3D 166, + .irq_type_support =3D IRQ_TYPE_EDGE_BOTH, + .base_offset =3D 0x100, + .gpa_offset =3D 0x000, + .gpda_offset =3D 0x020, + .write_en_all =3D RTD1625_ISO_GPIO_WREN_ALL, +}; + +static const struct rtd1625_gpio_info rtd1625_isom_gpio_info =3D { + .num_gpios =3D 4, + .irq_type_support =3D IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_LEVEL_LOW | + IRQ_TYPE_LEVEL_HIGH, + .base_offset =3D 0x20, + .gpa_offset =3D 0x00, + .gpda_offset =3D 0x04, + .level_offset =3D 0x18, + .write_en_all =3D RTD1625_ISOM_GPIO_WREN_ALL, +}; + +static int rtd1625_gpio_suspend(struct device *dev) +{ + struct rtd1625_gpio *data =3D dev_get_drvdata(dev); + const struct rtd1625_gpio_info *info =3D data->info; + int ret; + + for (unsigned int i =3D 0; i < info->num_gpios; i++) { + ret =3D regmap_read(data->regmap, data->info->base_offset + GPIO_CONTROL= (i), + &data->save_regs[i]); + if (ret) + return ret; + } + + return 0; +} + +static int rtd1625_gpio_resume(struct device *dev) +{ + struct rtd1625_gpio *data =3D dev_get_drvdata(dev); + const struct rtd1625_gpio_info *info =3D data->info; + int ret; + + for (unsigned int i =3D 0; i < info->num_gpios; i++) { + ret =3D regmap_write(data->regmap, data->info->base_offset + GPIO_CONTRO= L(i), + data->save_regs[i] | info->write_en_all); + if (ret) + return ret; + } + + return 0; +} + +static DEFINE_NOIRQ_DEV_PM_OPS(rtd1625_gpio_pm_ops, rtd1625_gpio_suspend, = rtd1625_gpio_resume); + +static const struct of_device_id rtd1625_gpio_of_matches[] =3D { + { .compatible =3D "realtek,rtd1625-iso-gpio", .data =3D &rtd1625_iso_gpio= _info }, + { .compatible =3D "realtek,rtd1625-isom-gpio", .data =3D &rtd1625_isom_gp= io_info }, + { } +}; +MODULE_DEVICE_TABLE(of, rtd1625_gpio_of_matches); + +static struct platform_driver rtd1625_gpio_platform_driver =3D { + .driver =3D { + .name =3D "gpio-rtd1625", + .of_match_table =3D rtd1625_gpio_of_matches, + .pm =3D pm_sleep_ptr(&rtd1625_gpio_pm_ops), + }, + .probe =3D rtd1625_gpio_probe, +}; +module_platform_driver(rtd1625_gpio_platform_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Realtek Semiconductor Corporation"); +MODULE_DESCRIPTION("Realtek DHC SoC RTD1625 gpio driver"); --=20 2.43.0