Re: [PATCH 09/27] gpio: rockchip: Add RK3572 GPIO support

From: Bartosz Golaszewski

Date: Wed Oct 28 2026 - 06:17:54 EST


On Wed, 21 Oct 2026 18:11:06 +0200, Cunhao Lu via B4 Relay
<devnull+1579567540.qq.com@xxxxxxxxxx> said:
> From: Cunhao Lu <1579567540@xxxxxx>
>
> Support GPIO V2.7, four parent interrupts, and firmware-provided
> interrupt-group masks. Keep all pins on the primary interrupt when group
> queries are unavailable.
>
> Signed-off-by: Cunhao Lu <1579567540@xxxxxx>
> ---
> drivers/gpio/gpio-rockchip.c | 91 +++++++++++++++++++++++++++++++++----
> drivers/pinctrl/pinctrl-rockchip.h | 8 +++-
> include/soc/rockchip/rockchip_sip.h | 5 ++
> 3 files changed, 92 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
> index 77b239a9a601e..35894a68b5446 100644
> --- a/drivers/gpio/gpio-rockchip.c
> +++ b/drivers/gpio/gpio-rockchip.c
> @@ -6,6 +6,7 @@
> * Copyright (c) 2021 Rockchip Electronics Co. Ltd.
> */
>
> +#include <linux/arm-smccc.h>
> #include <linux/bitops.h>
> #include <linux/clk.h>
> #include <linux/device.h>
> @@ -21,6 +22,7 @@
> #include <linux/pinctrl/pinconf-generic.h>
> #include <linux/platform_device.h>
> #include <linux/regmap.h>
> +#include <soc/rockchip/rockchip_sip.h>
>
> #include "../pinctrl/core.h"
> #include "../pinctrl/pinctrl-rockchip.h"
> @@ -35,6 +37,7 @@
> #define GPIO_TYPE_V2 (0x01000C2B)
> #define GPIO_TYPE_V2_1 (0x0101157C)
> #define GPIO_TYPE_V2_2 (0x010219C8)
> +#define GPIO_TYPE_V2_7 (0x01074D2E)
>
> static const struct rockchip_gpio_regs gpio_regs_v1 = {
> .port_dr = 0x00,
> @@ -209,12 +212,27 @@ static int rockchip_gpio_set_debounce(struct gpio_chip *gc,
> if (bank->gpio_type == GPIO_TYPE_V2 && !IS_ERR(bank->db_clk)) {
> div_debounce_support = true;
> freq = clk_get_rate(bank->db_clk);
> - max_debounce = (GENMASK(23, 0) + 1) * 2 * 1000000 / freq;
> - if (debounce > max_debounce)
> - return -EINVAL;
>
> - div = debounce * freq;
> - div_reg = DIV_ROUND_CLOSEST_ULL(div, 2 * USEC_PER_SEC) - 1;
> + if (of_device_is_compatible(bank->of_node, "rockchip,rk3572-gpio-bank")) {
> + if (!freq)
> + return -EINVAL;
> +
> + div = (u64)(GENMASK(23, 0) + 1) * USEC_PER_SEC;
> + max_debounce = div_u64(div, 2 * freq);
> + if (debounce > max_debounce)
> + return -EINVAL;
> +
> + div = (u64)debounce * freq * 2;
> + div_reg = DIV_ROUND_CLOSEST_ULL(div, USEC_PER_SEC);
> + div_reg = div_reg ? div_reg - 1 : 0;
> + } else {
> + max_debounce = (GENMASK(23, 0) + 1) * 2 * 1000000 / freq;
> + if (debounce > max_debounce)
> + return -EINVAL;
> +
> + div = debounce * freq;
> + div_reg = DIV_ROUND_CLOSEST_ULL(div, 2 * USEC_PER_SEC) - 1;
> + }
> } else {
> div_debounce_support = false;
> }
> @@ -342,6 +360,12 @@ static void rockchip_irq_demux(struct irq_desc *desc)
> chained_irq_enter(chip, desc);
>
> pending = readl_relaxed(bank->reg_base + bank->gpio_regs->int_status);

Please sprinkle in some newlines for readability here...

> + for (unsigned int i = 0; i < bank->nr_irqs; i++) {
> + if (bank->irqs[i] == irq_desc_get_irq(desc)) {
> + pending &= bank->irq_masks[i];
> + break;
> + }
> + }

... here ...

> for_each_set_bit(irq, &pending, 32) {
> dev_dbg(bank->dev, "handling irq %d\n", irq);
>
> @@ -568,8 +592,9 @@ static int rockchip_interrupts_register(struct rockchip_pin_bank *bank)
> rockchip_gpio_writel(bank, 0xffffffff, bank->gpio_regs->int_en);
> gc->mask_cache = 0xffffffff;
>
> - irq_set_chained_handler_and_data(bank->irq,
> - rockchip_irq_demux, bank);
> + for (unsigned int i = 0; i < bank->nr_irqs; i++)
> + irq_set_chained_handler_and_data(bank->irqs[i],
> + rockchip_irq_demux, bank);
>
> return 0;
> }
> @@ -645,6 +670,36 @@ static void rockchip_clk_put(void *data)
> clk_put(clk);
> }
>
> +static int rockchip_gpio_read_irq_groups(struct rockchip_pin_bank *bank)
> +{
> + struct arm_smccc_res res;
> + u32 assigned = 0;
> + int status;
> +
> + for (unsigned int i = 1; i < bank->nr_irqs; i++) {
> + arm_smccc_smc(ROCKCHIP_SIP_GPIO_CONFIG, ROCKCHIP_SIP_GPIO_GET_GROUP,
> + bank->bank_num, i, 0, 0, 0, 0, &res);
> + status = (int)res.a0;
> + if (i == 1 && (status == SMCCC_RET_NOT_SUPPORTED ||
> + status == ROCKCHIP_SIP_RET_NOT_SUPPORTED)) {
> + /* Older firmware leaves all pins on the primary IRQ. */
> + dev_dbg(bank->dev, "GPIO group query unsupported: %d\n",
> + status);
> + break;
> + }
> + if (status)
> + return dev_err_probe(bank->dev, -EIO,
> + "cannot read interrupt group %u: %d\n",
> + i, status);
> + bank->irq_masks[i] = res.a1;
> + if (assigned & bank->irq_masks[i])
> + return -EINVAL;
> + assigned |= bank->irq_masks[i];
> + }

... here, etc.

> + bank->irq_masks[0] = ~assigned;
> + return 0;
> +}
> +
> static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
> {
> struct platform_device *pdev = to_platform_device(bank->dev);
> @@ -654,10 +709,23 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
> if (IS_ERR(bank->reg_base))
> return PTR_ERR(bank->reg_base);
>
> - ret = platform_get_irq(pdev, 0);
> + ret = platform_irq_count(pdev);
> if (ret < 0)
> return ret;
> - bank->irq = ret;
> + if (ret != (of_device_is_compatible(bank->of_node,
> + "rockchip,rk3572-gpio-bank") ? 4 : 1))
> + return -EINVAL;
> + bank->nr_irqs = ret;
> + for (unsigned int i = 0; i < bank->nr_irqs; i++) {
> + ret = platform_get_irq(pdev, i);
> + if (ret < 0)
> + return ret;
> + bank->irqs[i] = ret;
> + }
> +
> + ret = rockchip_gpio_read_irq_groups(bank);
> + if (ret)
> + return ret;
>
> bank->clk = devm_clk_get_enabled(bank->dev, NULL);
> if (IS_ERR(bank->clk))
> @@ -669,6 +737,7 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
> case GPIO_TYPE_V2:
> case GPIO_TYPE_V2_1:
> case GPIO_TYPE_V2_2:
> + case GPIO_TYPE_V2_7:
> bank->gpio_regs = &gpio_regs_v2;
> bank->gpio_type = GPIO_TYPE_V2;
> bank->db_clk = of_clk_get(bank->of_node, 1);
> @@ -797,7 +866,8 @@ static void rockchip_gpio_remove(struct platform_device *pdev)
> {
> struct rockchip_pin_bank *bank = platform_get_drvdata(pdev);
>
> - irq_set_chained_handler_and_data(bank->irq, NULL, NULL);
> + for (unsigned int i = 0; i < bank->nr_irqs; i++)
> + irq_set_chained_handler_and_data(bank->irqs[i], NULL, NULL);
> if (bank->domain) {
> irq_domain_remove_generic_chips(bank->domain);
> irq_domain_remove(bank->domain);
> @@ -807,6 +877,7 @@ static void rockchip_gpio_remove(struct platform_device *pdev)
>
> static const struct of_device_id rockchip_gpio_match[] = {
> { .compatible = "rockchip,gpio-bank", },
> + { .compatible = "rockchip,rk3572-gpio-bank" },
> { .compatible = "rockchip,rk3188-gpio-bank0" },
> { },
> };
> diff --git a/drivers/pinctrl/pinctrl-rockchip.h b/drivers/pinctrl/pinctrl-rockchip.h
> index 553197f6dc690..058b58dcde404 100644
> --- a/drivers/pinctrl/pinctrl-rockchip.h
> +++ b/drivers/pinctrl/pinctrl-rockchip.h
> @@ -302,7 +302,9 @@ struct rockchip_drv {
> * bank has its own IOC block
> * @clk: clock of the gpio bank
> * @db_clk: clock of the gpio debounce
> - * @irq: interrupt of the gpio bank
> + * @irqs: parent interrupts of the GPIO bank
> + * @irq_masks: pins assigned to each parent interrupt
> + * @nr_irqs: number of parent interrupts
> * @saved_masks: Saved content of GPIO_INTEN at suspend time.
> * @pin_base: first pin number
> * @nr_pins: number of pins in this bank
> @@ -331,7 +333,9 @@ struct rockchip_pin_bank {
> struct regmap *regmap_ioc;
> struct clk *clk;
> struct clk *db_clk;
> - int irq;
> + unsigned int irqs[4];
> + u32 irq_masks[4];
> + unsigned int nr_irqs;
> u32 saved_masks;
> u32 pin_base;
> u8 nr_pins;
> diff --git a/include/soc/rockchip/rockchip_sip.h b/include/soc/rockchip/rockchip_sip.h

The changes in headers in other subsystems should be in separate patches.

> index 501ad1fedb201..984272ede3baf 100644
> --- a/include/soc/rockchip/rockchip_sip.h
> +++ b/include/soc/rockchip/rockchip_sip.h
> @@ -20,4 +20,9 @@
> #define ROCKCHIP_SIP_CONFIG_DRAM_SET_PARAM 0x07
> #define ROCKCHIP_SIP_CONFIG_DRAM_SET_ODT_PD 0x08
>
> +#define ROCKCHIP_SIP_RET_NOT_SUPPORTED -2
> +
> +#define ROCKCHIP_SIP_GPIO_CONFIG 0x8200002c
> +#define ROCKCHIP_SIP_GPIO_GET_GROUP 0
> +
> #endif
>
> --
> 2.34.1
>
>
>

Bart