* [PATCH 0/2] gpio: Add the Siflower SF19A2890 GPIO controller
@ 2026-11-04 7:21 Joseph Telaak via B4 Relay
2026-11-04 7:21 ` [PATCH 1/2] dt-bindings: gpio: Add " Joseph Telaak via B4 Relay
2026-11-04 7:21 ` [PATCH 2/2] gpio: Add Siflower GPIO controller driver Joseph Telaak via B4 Relay
0 siblings, 2 replies; 10+ messages in thread
From: Joseph Telaak via B4 Relay @ 2026-11-04 7:21 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: Chuanhong Guo, Qingfang Deng, linux-mips, linux-gpio, devicetree,
linux-kernel, Joseph Telaak, Qingfang Deng
This series adds a binding and a driver for the GPIO controller of the
Siflower SoCs, starting with the SF19A2890, a MIPS SoC for home routers.
Each line has a register block of its own, and each group of 16 lines an
interrupt.
The binding is Chuanhong Guo's and the driver Qingfang Deng's, both from
Chuanhong's SF19A2890 branch [1], with my changes noted in each. The
same controller is in Siflower's SF21 RISC-V SoCs; the binding has only
the SF19A2890's compatible, the one I can test.
The SoC support itself (MACH_SIFLOWER_MIPS) goes through the MIPS tree;
until then the driver builds with COMPILE_TEST.
The MAINTAINERS entry that covers these files comes with the MIPS series
"MIPS: Add support for the Siflower SF19A2890"; this series applies on
its own. That entry is also why checkpatch's question about updating
MAINTAINERS for the new files is left unanswered here.
Tested on a GL.iNet GL-SFT1200: gpio-keys sees both buttons on both
edges (the reset button on GPIO 27 as KEY_RESTART, the mode slide switch
on GPIO 1 as BTN_0, 1 and 0 per slide); /sys/kernel/debug/gpio lists the
49 lines; the GSW150 switch comes out of reset through GPIO 0 and the
SPI NAND uses GPIO 8 as its chip select.
[1] https://github.com/981213/linux/commits/siflower-7.1
---
Chuanhong Guo (1):
dt-bindings: gpio: Add Siflower SF19A2890 GPIO controller
Qingfang Deng (1):
gpio: Add Siflower GPIO controller driver
.../bindings/gpio/siflower,sf19a2890-gpio.yaml | 84 ++++++
drivers/gpio/Kconfig | 11 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-siflower.c | 325 +++++++++++++++++++++
4 files changed, 421 insertions(+)
---
base-commit: d66b6b86d5a6278ca930112c634d03725beb7d9a
change-id: 20261102-sf19a2890-gpio-b21562e52f88
Best regards,
--
Joseph Telaak <joseph@telaak.dev>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/2] dt-bindings: gpio: Add Siflower SF19A2890 GPIO controller
2026-11-04 7:21 [PATCH 0/2] gpio: Add the Siflower SF19A2890 GPIO controller Joseph Telaak via B4 Relay
@ 2026-11-04 7:21 ` Joseph Telaak via B4 Relay
2026-11-04 8:12 ` Bartosz Golaszewski
2026-11-04 7:21 ` [PATCH 2/2] gpio: Add Siflower GPIO controller driver Joseph Telaak via B4 Relay
1 sibling, 1 reply; 10+ messages in thread
From: Joseph Telaak via B4 Relay @ 2026-11-04 7:21 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: Chuanhong Guo, Qingfang Deng, linux-mips, linux-gpio, devicetree,
linux-kernel, Joseph Telaak
From: Chuanhong Guo <gch981213@gmail.com>
Document the GPIO controller found on the Siflower SF19A2890 and other
Siflower MIPS and RISC-V SoCs.
Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
[jt: from Chuanhong's siflower-7.1 branch; Joseph Telaak as the binding's
maintainer, GPL-2.0-only for the deprecated GPL-2.0 SPDX identifier,
example indented by four spaces, commit message, subject]
Signed-off-by: Joseph Telaak <joseph@telaak.dev>
---
.../bindings/gpio/siflower,sf19a2890-gpio.yaml | 84 ++++++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/Documentation/devicetree/bindings/gpio/siflower,sf19a2890-gpio.yaml b/Documentation/devicetree/bindings/gpio/siflower,sf19a2890-gpio.yaml
new file mode 100644
index 000000000..6708d92fe
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/siflower,sf19a2890-gpio.yaml
@@ -0,0 +1,84 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpio/siflower,sf19a2890-gpio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Siflower SF19A2890 GPIO controller
+
+maintainers:
+ - Joseph Telaak <joseph@telaak.dev>
+
+properties:
+ compatible:
+ const: siflower,sf19a2890-gpio
+
+ gpio-controller: true
+ "#gpio-cells":
+ const: 2
+
+ gpio-ranges: true
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ description:
+ Interrupt mapping, one interrupt per 16 GPIOs.
+ minItems: 1
+ maxItems: 10
+
+ clocks:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ "#interrupt-cells":
+ const: 2
+
+ ngpios:
+ description:
+ The number of GPIOs available on the controller implementation.
+ minimum: 1
+
+required:
+ - compatible
+ - clocks
+ - gpio-controller
+ - gpio-ranges
+ - interrupt-controller
+ - interrupts
+ - ngpios
+ - reg
+ - resets
+ - "#gpio-cells"
+ - "#interrupt-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/interrupt-controller/mips-gic.h>
+
+ gpio@19d00000 {
+ compatible = "siflower,sf19a2890-gpio";
+ reg = <0x19d00000 0x100000>;
+ interrupts = <GIC_SHARED 246 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SHARED 247 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SHARED 248 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SHARED 249 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gpioclk 0>;
+ resets = <&gpiorst 0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <49>;
+ gpio-ranges = <&pinctrl 0 0 49>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
--
Git-155)
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/2] gpio: Add Siflower GPIO controller driver
2026-11-04 7:21 [PATCH 0/2] gpio: Add the Siflower SF19A2890 GPIO controller Joseph Telaak via B4 Relay
2026-11-04 7:21 ` [PATCH 1/2] dt-bindings: gpio: Add " Joseph Telaak via B4 Relay
@ 2026-11-04 7:21 ` Joseph Telaak via B4 Relay
2026-11-04 7:38 ` sashiko-bot
` (2 more replies)
1 sibling, 3 replies; 10+ messages in thread
From: Joseph Telaak via B4 Relay @ 2026-11-04 7:21 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: Chuanhong Guo, Qingfang Deng, linux-mips, linux-gpio, devicetree,
linux-kernel, Qingfang Deng, Joseph Telaak
From: Qingfang Deng <qingfang.deng@siflower.com.cn>
Add a driver for the GPIO controller on Siflower SoCs.
This controller is found on all current Siflower MIPS and RISC-V
chips including SF19A2890, SF21A6826 and SF21H8898.
Signed-off-by: Qingfang Deng <qingfang.deng@siflower.com.cn>
Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
[jt: from Chuanhong's siflower-7.1 branch; depend on MACH_SIFLOWER_MIPS,
longer Kconfig help, assert the reset through a devm action instead of in
.remove, which ran before the GPIO chip was removed, drop .owner and the
unused drvdata, drop the irq_set_affinity callback, which reached the
parent through irq_to_desc() (not exported with SPARSE_IRQ), call
gpiochip_disable_irq() and gpiochip_enable_irq() from mask and unmask as
an immutable irqchip must, find the group by its parent IRQ instead of
assuming consecutive numbers, return 0 or 1 from .get, read ngpios with
device_property_read_u32(), linux/math64.h and sorted includes, "Siflower"
spelling, subject]
Signed-off-by: Joseph Telaak <joseph@telaak.dev>
---
drivers/gpio/Kconfig | 11 ++
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-siflower.c | 325 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 337 insertions(+)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 55e428002..6125a8452 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -721,6 +721,17 @@ config GPIO_SIFIVE
help
Say yes here to support the GPIO device on SiFive SoCs.
+config GPIO_SIFLOWER
+ tristate "Siflower GPIO support"
+ depends on OF_GPIO
+ depends on MACH_SIFLOWER_MIPS || COMPILE_TEST
+ select GPIOLIB_IRQCHIP
+ help
+ GPIO controller driver for Siflower MIPS and RISC-V SoCs
+ including SF19A2890, SF21A6826 and SF21H8898. Each line can be an
+ input or an output and raise an interrupt on either edge or level,
+ and inputs can be debounced in hardware.
+
config GPIO_SIOX
tristate "SIOX GPIO support"
depends on SIOX
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 88f748846..bde618108 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -171,6 +171,7 @@ obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o
obj-$(CONFIG_GPIO_SCH) += gpio-sch.o
obj-$(CONFIG_GPIO_SHARED_PROXY) += gpio-shared-proxy.o
obj-$(CONFIG_GPIO_SIFIVE) += gpio-sifive.o
+obj-$(CONFIG_GPIO_SIFLOWER) += gpio-siflower.o
obj-$(CONFIG_GPIO_SIM) += gpio-sim.o
obj-$(CONFIG_GPIO_SIOX) += gpio-siox.o
obj-$(CONFIG_GPIO_SL28CPLD) += gpio-sl28cpld.o
diff --git a/drivers/gpio/gpio-siflower.c b/drivers/gpio/gpio-siflower.c
new file mode 100644
index 000000000..6eb560da7
--- /dev/null
+++ b/drivers/gpio/gpio-siflower.c
@@ -0,0 +1,325 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * GPIO controller driver for Siflower MIPS and RISC-V SoCs including:
+ * Siflower SF19A2890
+ * Siflower SF21A6826
+ * Siflower SF21H8898
+ *
+ */
+#include <linux/clk.h>
+#include <linux/gpio/driver.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/reset.h>
+
+#define GPIO_IR(n) (0x40 * (n) + 0x00)
+#define GPIO_OR(n) (0x40 * (n) + 0x04)
+#define GPIO_OEN(n) (0x40 * (n) + 0x08)
+#define GPIO_IMR(n) (0x40 * (n) + 0x0c)
+#define GPIO_GPIMR(n) (0x40 * (n) + 0x10)
+#define GPIO_PIR(n) (0x40 * (n) + 0x14)
+#define GPIO_ITR(n) (0x40 * (n) + 0x18)
+#define GPIO_IFR(n) (0x40 * (n) + 0x1c)
+#define GPIO_ICR(n) (0x40 * (n) + 0x20)
+#define GPIO_GPxIR(n) (0x4 * (n) + 0x4000)
+
+#define GPIOS_PER_GROUP 16
+
+struct sf_gpio_priv {
+ struct gpio_chip gc;
+ void __iomem *base;
+ struct clk *clk;
+ struct reset_control *rstc;
+ unsigned int irq[];
+};
+
+#define to_sf_gpio(x) container_of(x, struct sf_gpio_priv, gc)
+
+static u32 sf_gpio_rd(struct sf_gpio_priv *priv, unsigned long reg)
+{
+ return readl_relaxed(priv->base + reg);
+}
+
+static void sf_gpio_wr(struct sf_gpio_priv *priv, unsigned long reg,
+ u32 val)
+{
+ writel_relaxed(val, priv->base + reg);
+}
+
+static int sf_gpio_get_value(struct gpio_chip *gc, unsigned int offset)
+{
+ struct sf_gpio_priv *priv = to_sf_gpio(gc);
+
+ return !!sf_gpio_rd(priv, GPIO_IR(offset));
+}
+
+static int sf_gpio_set_value(struct gpio_chip *gc, unsigned int offset,
+ int value)
+{
+ struct sf_gpio_priv *priv = to_sf_gpio(gc);
+
+ sf_gpio_wr(priv, GPIO_OR(offset), value);
+ return 0;
+}
+
+static int sf_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
+{
+ struct sf_gpio_priv *priv = to_sf_gpio(gc);
+
+ if (sf_gpio_rd(priv, GPIO_OEN(offset)))
+ return GPIO_LINE_DIRECTION_IN;
+ else
+ return GPIO_LINE_DIRECTION_OUT;
+}
+
+static int sf_gpio_direction_input(struct gpio_chip *gc, unsigned int offset)
+{
+ struct sf_gpio_priv *priv = to_sf_gpio(gc);
+
+ sf_gpio_wr(priv, GPIO_OEN(offset), 1);
+ return 0;
+}
+
+static int sf_gpio_direction_output(struct gpio_chip *gc, unsigned int offset,
+ int value)
+{
+ struct sf_gpio_priv *priv = to_sf_gpio(gc);
+
+ sf_gpio_wr(priv, GPIO_OR(offset), value);
+ sf_gpio_wr(priv, GPIO_OEN(offset), 0);
+ return 0;
+}
+
+static int sf_gpio_set_debounce(struct gpio_chip *gc, unsigned int offset,
+ u32 debounce)
+{
+ struct sf_gpio_priv *priv = to_sf_gpio(gc);
+ unsigned long freq = clk_get_rate(priv->clk);
+ u64 mul;
+
+ /* (ICR + 1) * IFR = debounce_us * clkfreq_mhz / 4 */
+ mul = (u64)debounce * freq;
+ do_div(mul, 1000000 * 4);
+ if (mul > 0xff00)
+ return -EINVAL;
+
+ sf_gpio_wr(priv, GPIO_ICR(offset), 0xff);
+ sf_gpio_wr(priv, GPIO_IFR(offset), DIV_ROUND_UP(mul, 0x100));
+
+ return 0;
+}
+
+static int sf_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
+ unsigned long config)
+{
+ switch (pinconf_to_config_param(config)) {
+ case PIN_CONFIG_INPUT_DEBOUNCE:
+ return sf_gpio_set_debounce(gc, offset,
+ pinconf_to_config_argument(config));
+ default:
+ return gpiochip_generic_config(gc, offset, config);
+ }
+}
+
+static void sf_gpio_irq_ack(struct irq_data *data)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+ struct sf_gpio_priv *priv = to_sf_gpio(gc);
+ unsigned long offset = irqd_to_hwirq(data);
+
+ sf_gpio_wr(priv, GPIO_PIR(offset), 0);
+}
+
+static void sf_gpio_irq_mask(struct irq_data *data)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+ struct sf_gpio_priv *priv = to_sf_gpio(gc);
+ unsigned long offset = irqd_to_hwirq(data);
+
+ sf_gpio_wr(priv, GPIO_IMR(offset), 1);
+ sf_gpio_wr(priv, GPIO_GPIMR(offset), 1);
+ gpiochip_disable_irq(gc, offset);
+}
+
+static void sf_gpio_irq_unmask(struct irq_data *data)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+ struct sf_gpio_priv *priv = to_sf_gpio(gc);
+ unsigned long offset = irqd_to_hwirq(data);
+
+ gpiochip_enable_irq(gc, offset);
+ sf_gpio_wr(priv, GPIO_IMR(offset), 0);
+ sf_gpio_wr(priv, GPIO_GPIMR(offset), 0);
+}
+
+static int sf_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+ struct sf_gpio_priv *priv = to_sf_gpio(gc);
+ unsigned long offset = irqd_to_hwirq(data);
+ u32 val;
+
+ switch (flow_type) {
+ case IRQ_TYPE_EDGE_RISING:
+ val = 4;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ val = 2;
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ val = 6;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ val = 1;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ val = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ sf_gpio_wr(priv, GPIO_ITR(offset), val);
+
+ if (flow_type & IRQ_TYPE_LEVEL_MASK)
+ irq_set_handler_locked(data, handle_level_irq);
+ else
+ irq_set_handler_locked(data, handle_edge_irq);
+
+ return 0;
+}
+
+static const struct irq_chip sf_gpio_irqchip = {
+ .name = KBUILD_MODNAME,
+ .irq_ack = sf_gpio_irq_ack,
+ .irq_mask = sf_gpio_irq_mask,
+ .irq_unmask = sf_gpio_irq_unmask,
+ .irq_set_type = sf_gpio_irq_set_type,
+ .flags = IRQCHIP_IMMUTABLE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
+static void sf_gpio_irq_handler(struct irq_desc *desc)
+{
+ struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+ struct irq_chip *ic = irq_desc_get_chip(desc);
+ struct sf_gpio_priv *priv = to_sf_gpio(gc);
+ unsigned int irq = irq_desc_get_irq(desc);
+ unsigned long pending;
+ unsigned int group, n;
+
+ for (group = 0; group < gc->irq.num_parents; group++)
+ if (priv->irq[group] == irq)
+ break;
+ if (WARN_ON_ONCE(group == gc->irq.num_parents))
+ return;
+
+ chained_irq_enter(ic, desc);
+
+ pending = sf_gpio_rd(priv, GPIO_GPxIR(group));
+ for_each_set_bit(n, &pending, GPIOS_PER_GROUP) {
+ generic_handle_domain_irq(gc->irq.domain,
+ n + group * GPIOS_PER_GROUP);
+ }
+
+ chained_irq_exit(ic, desc);
+}
+
+static void sf_gpio_reset_assert(void *data)
+{
+ reset_control_assert(data);
+}
+
+static int sf_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct sf_gpio_priv *priv;
+ struct gpio_irq_chip *girq;
+ struct gpio_chip *gc;
+ u32 ngpios, ngroups;
+ int ret, i;
+
+ ret = device_property_read_u32(dev, "ngpios", &ngpios);
+ if (ret)
+ return ret;
+
+ ngroups = DIV_ROUND_UP(ngpios, GPIOS_PER_GROUP);
+ priv = devm_kzalloc(dev, struct_size(priv, irq, ngroups), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ priv->clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(priv->clk))
+ return PTR_ERR(priv->clk);
+
+ priv->rstc = devm_reset_control_get_optional(&pdev->dev, NULL);
+ if (IS_ERR(priv->rstc))
+ return PTR_ERR(priv->rstc);
+
+ ret = reset_control_deassert(priv->rstc);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, sf_gpio_reset_assert, priv->rstc);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < ngroups; i++) {
+ ret = platform_get_irq(pdev, i);
+ if (ret < 0)
+ return ret;
+
+ priv->irq[i] = ret;
+ }
+
+ gc = &priv->gc;
+ gc->label = KBUILD_MODNAME;
+ gc->parent = dev;
+ gc->owner = THIS_MODULE;
+ gc->request = gpiochip_generic_request;
+ gc->free = gpiochip_generic_free;
+ gc->get_direction = sf_gpio_get_direction;
+ gc->direction_input = sf_gpio_direction_input;
+ gc->direction_output = sf_gpio_direction_output;
+ gc->get = sf_gpio_get_value;
+ gc->set = sf_gpio_set_value;
+ gc->set_config = sf_gpio_set_config;
+ gc->base = -1;
+ gc->ngpio = ngpios;
+
+ girq = &gc->irq;
+ gpio_irq_chip_set_chip(girq, &sf_gpio_irqchip);
+ girq->num_parents = ngroups;
+ girq->parents = priv->irq;
+ girq->parent_handler = sf_gpio_irq_handler;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_bad_irq;
+
+ return devm_gpiochip_add_data(dev, gc, priv);
+}
+
+static const struct of_device_id sf_gpio_ids[] = {
+ { .compatible = "siflower,sf19a2890-gpio" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, sf_gpio_ids);
+
+static struct platform_driver sf_gpio_driver = {
+ .probe = sf_gpio_probe,
+ .driver = {
+ .name = "siflower_gpio",
+ .of_match_table = sf_gpio_ids,
+ },
+};
+module_platform_driver(sf_gpio_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Qingfang Deng <qingfang.deng@siflower.com.cn>");
+MODULE_DESCRIPTION("GPIO driver for Siflower SoCs");
--
Git-155)
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] gpio: Add Siflower GPIO controller driver
2026-11-04 7:21 ` [PATCH 2/2] gpio: Add Siflower GPIO controller driver Joseph Telaak via B4 Relay
@ 2026-11-04 7:38 ` sashiko-bot
2026-11-04 8:16 ` Bartosz Golaszewski
2026-11-04 9:12 ` Philipp Zabel
2 siblings, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-11-04 7:38 UTC (permalink / raw)
To: Joseph Telaak; +Cc: linux-gpio, devicetree, robh, conor+dt
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] gpio: siflower: Kconfig depends on undefined MACH_SIFLOWER_MIPS
- [Low] gpio: siflower: sf_gpio_probe() open-codes deasserted reset helper
--
commit 22b6fa5e482223ae6c4b545f3ef7b8a0b9775f11
Author: Qingfang Deng <qingfang.deng@siflower.com.cn>
gpio: Add Siflower GPIO controller driver
This commit adds a GPIO and interrupt controller driver for Siflower MIPS
and RISC-V SoCs, including SF19A2890, SF21A6826, and SF21H8898.
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index 55e4280029d86..6125a8452a5bf 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -721,6 +721,17 @@ config GPIO_SIFIVE
> help
> Say yes here to support the GPIO device on SiFive SoCs.
>
> +config GPIO_SIFLOWER
> + tristate "Siflower GPIO support"
> + depends on OF_GPIO
> + depends on MACH_SIFLOWER_MIPS || COMPILE_TEST
[Severity: Medium]
Can CONFIG_GPIO_SIFLOWER be enabled without CONFIG_COMPILE_TEST?
MACH_SIFLOWER_MIPS is not defined anywhere in the kernel tree, so this
dependency always evaluates to n unless COMPILE_TEST is set, and causes
scripts/checkkconfigsymbols.py to report an undefined Kconfig symbol.
Additionally, the commit description, Kconfig help text, and driver header
state that this controller is also used on Siflower RISC-V SoCs, which would
be excluded by a MIPS-only machine dependency, and the driver only uses
generic device property and platform APIs rather than OF_GPIO internals.
> diff --git a/drivers/gpio/gpio-siflower.c b/drivers/gpio/gpio-siflower.c
> new file mode 100644
> index 0000000000000..6eb560da7ffd5
> --- /dev/null
> +++ b/drivers/gpio/gpio-siflower.c
[ ... ]
> +static void sf_gpio_reset_assert(void *data)
> +{
> + reset_control_assert(data);
> +}
> +
> +static int sf_gpio_probe(struct platform_device *pdev)
> +{
[ ... ]
> + priv->rstc = devm_reset_control_get_optional(&pdev->dev, NULL);
> + if (IS_ERR(priv->rstc))
> + return PTR_ERR(priv->rstc);
> +
> + ret = reset_control_deassert(priv->rstc);
> + if (ret)
> + return ret;
> +
> + ret = devm_add_action_or_reset(dev, sf_gpio_reset_assert, priv->rstc);
> + if (ret)
> + return ret;
[Severity: Low]
This isn't a bug, but could sf_gpio_probe() use
devm_reset_control_get_optional_exclusive_deasserted() (or
devm_reset_control_get_exclusive_deasserted(), since resets is required in
the devicetree binding) instead of open-coding the deassertion and custom
sf_gpio_reset_assert() devres action on top of the deprecated
devm_reset_control_get_optional() wrapper? That would also allow dropping
rstc from struct sf_gpio_priv.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261104-sf19a2890-gpio-v1-0-45e463c48728@telaak.dev?part=2
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] dt-bindings: gpio: Add Siflower SF19A2890 GPIO controller
2026-11-04 7:21 ` [PATCH 1/2] dt-bindings: gpio: Add " Joseph Telaak via B4 Relay
@ 2026-11-04 8:12 ` Bartosz Golaszewski
2026-11-04 8:32 ` Joseph Telaak
0 siblings, 1 reply; 10+ messages in thread
From: Bartosz Golaszewski @ 2026-11-04 8:12 UTC (permalink / raw)
To: joseph
Cc: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Philipp Zabel, Chuanhong Guo, Qingfang Deng, linux-mips,
linux-gpio, devicetree, linux-kernel
On Wed, Nov 04, 2026 at 02:21:37AM -0500, Joseph Telaak via B4 Relay wrote:
> From: Chuanhong Guo <gch981213@gmail.com>
>
> Document the GPIO controller found on the Siflower SF19A2890 and other
> Siflower MIPS and RISC-V SoCs.
>
> Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
> [jt: from Chuanhong's siflower-7.1 branch; Joseph Telaak as the binding's
> maintainer, GPL-2.0-only for the deprecated GPL-2.0 SPDX identifier,
> example indented by four spaces, commit message, subject]
> Signed-off-by: Joseph Telaak <joseph@telaak.dev>
> ---
If you're a co-developer, please add your Co-developed-by: prefixed with
a list that looks more like:
[Joseph Telaak:
- did foo
- did bar]
The above is completely unreadable.
Thanks,
Bartosz
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] gpio: Add Siflower GPIO controller driver
2026-11-04 7:21 ` [PATCH 2/2] gpio: Add Siflower GPIO controller driver Joseph Telaak via B4 Relay
2026-11-04 7:38 ` sashiko-bot
@ 2026-11-04 8:16 ` Bartosz Golaszewski
2026-11-04 8:38 ` Joseph Telaak
2026-11-04 9:12 ` Philipp Zabel
2 siblings, 1 reply; 10+ messages in thread
From: Bartosz Golaszewski @ 2026-11-04 8:16 UTC (permalink / raw)
To: joseph
Cc: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Philipp Zabel, Chuanhong Guo, Qingfang Deng, linux-mips,
linux-gpio, devicetree, linux-kernel, Qingfang Deng
On Wed, Nov 04, 2026 at 02:21:38AM -0500, Joseph Telaak via B4 Relay wrote:
> From: Qingfang Deng <qingfang.deng@siflower.com.cn>
>
> Add a driver for the GPIO controller on Siflower SoCs.
> This controller is found on all current Siflower MIPS and RISC-V
> chips including SF19A2890, SF21A6826 and SF21H8898.
>
> Signed-off-by: Qingfang Deng <qingfang.deng@siflower.com.cn>
> Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
> [jt: from Chuanhong's siflower-7.1 branch; depend on MACH_SIFLOWER_MIPS,
> longer Kconfig help, assert the reset through a devm action instead of in
> .remove, which ran before the GPIO chip was removed, drop .owner and the
> unused drvdata, drop the irq_set_affinity callback, which reached the
> parent through irq_to_desc() (not exported with SPARSE_IRQ), call
> gpiochip_disable_irq() and gpiochip_enable_irq() from mask and unmask as
> an immutable irqchip must, find the group by its parent IRQ instead of
> assuming consecutive numbers, return 0 or 1 from .get, read ngpios with
> device_property_read_u32(), linux/math64.h and sorted includes, "Siflower"
> spelling, subject]
Same comment as for the DT binding patch.
> Signed-off-by: Joseph Telaak <joseph@telaak.dev>
> ---
> drivers/gpio/Kconfig | 11 ++
> drivers/gpio/Makefile | 1 +
> drivers/gpio/gpio-siflower.c | 325 +++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 337 insertions(+)
>
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index 55e428002..6125a8452 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -721,6 +721,17 @@ config GPIO_SIFIVE
> help
> Say yes here to support the GPIO device on SiFive SoCs.
>
> +config GPIO_SIFLOWER
> + tristate "Siflower GPIO support"
> + depends on OF_GPIO
> + depends on MACH_SIFLOWER_MIPS || COMPILE_TEST
> + select GPIOLIB_IRQCHIP
> + help
> + GPIO controller driver for Siflower MIPS and RISC-V SoCs
> + including SF19A2890, SF21A6826 and SF21H8898. Each line can be an
> + input or an output and raise an interrupt on either edge or level,
> + and inputs can be debounced in hardware.
> +
> config GPIO_SIOX
> tristate "SIOX GPIO support"
> depends on SIOX
> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> index 88f748846..bde618108 100644
> --- a/drivers/gpio/Makefile
> +++ b/drivers/gpio/Makefile
> @@ -171,6 +171,7 @@ obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o
> obj-$(CONFIG_GPIO_SCH) += gpio-sch.o
> obj-$(CONFIG_GPIO_SHARED_PROXY) += gpio-shared-proxy.o
> obj-$(CONFIG_GPIO_SIFIVE) += gpio-sifive.o
> +obj-$(CONFIG_GPIO_SIFLOWER) += gpio-siflower.o
> obj-$(CONFIG_GPIO_SIM) += gpio-sim.o
> obj-$(CONFIG_GPIO_SIOX) += gpio-siox.o
> obj-$(CONFIG_GPIO_SL28CPLD) += gpio-sl28cpld.o
> diff --git a/drivers/gpio/gpio-siflower.c b/drivers/gpio/gpio-siflower.c
> new file mode 100644
> index 000000000..6eb560da7
> --- /dev/null
> +++ b/drivers/gpio/gpio-siflower.c
> @@ -0,0 +1,325 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * GPIO controller driver for Siflower MIPS and RISC-V SoCs including:
> + * Siflower SF19A2890
> + * Siflower SF21A6826
> + * Siflower SF21H8898
> + *
> + */
Newline.
> +#include <linux/clk.h>
> +#include <linux/gpio/driver.h>
> +#include <linux/irqchip/chained_irq.h>
> +#include <linux/math64.h>
> +#include <linux/module.h>
> +#include <linux/pinctrl/consumer.h>
> +#include <linux/platform_device.h>
> +#include <linux/property.h>
> +#include <linux/reset.h>
> +
> +#define GPIO_IR(n) (0x40 * (n) + 0x00)
> +#define GPIO_OR(n) (0x40 * (n) + 0x04)
> +#define GPIO_OEN(n) (0x40 * (n) + 0x08)
> +#define GPIO_IMR(n) (0x40 * (n) + 0x0c)
> +#define GPIO_GPIMR(n) (0x40 * (n) + 0x10)
> +#define GPIO_PIR(n) (0x40 * (n) + 0x14)
> +#define GPIO_ITR(n) (0x40 * (n) + 0x18)
> +#define GPIO_IFR(n) (0x40 * (n) + 0x1c)
> +#define GPIO_ICR(n) (0x40 * (n) + 0x20)
> +#define GPIO_GPxIR(n) (0x4 * (n) + 0x4000)
> +
> +#define GPIOS_PER_GROUP 16
> +
> +struct sf_gpio_priv {
> + struct gpio_chip gc;
> + void __iomem *base;
> + struct clk *clk;
> + struct reset_control *rstc;
> + unsigned int irq[];
> +};
> +
> +#define to_sf_gpio(x) container_of(x, struct sf_gpio_priv, gc)
> +
> +static u32 sf_gpio_rd(struct sf_gpio_priv *priv, unsigned long reg)
> +{
> + return readl_relaxed(priv->base + reg);
> +}
> +
> +static void sf_gpio_wr(struct sf_gpio_priv *priv, unsigned long reg,
> + u32 val)
> +{
> + writel_relaxed(val, priv->base + reg);
> +}
> +
> +static int sf_gpio_get_value(struct gpio_chip *gc, unsigned int offset)
> +{
> + struct sf_gpio_priv *priv = to_sf_gpio(gc);
More common pattern is to retrieve the address of priv with
gpiochip_get_data(). You already pass that address to
devm_gpiochip_add_data().
> +
> + return !!sf_gpio_rd(priv, GPIO_IR(offset));
> +}
> +
> +static int sf_gpio_set_value(struct gpio_chip *gc, unsigned int offset,
> + int value)
> +{
> + struct sf_gpio_priv *priv = to_sf_gpio(gc);
> +
> + sf_gpio_wr(priv, GPIO_OR(offset), value);
> + return 0;
> +}
> +
> +static int sf_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
> +{
> + struct sf_gpio_priv *priv = to_sf_gpio(gc);
> +
> + if (sf_gpio_rd(priv, GPIO_OEN(offset)))
> + return GPIO_LINE_DIRECTION_IN;
> + else
Drop the else. Or do:
return sf_gpio_rd(priv, GPIO_OEN(offset)) ? GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT;
> + return GPIO_LINE_DIRECTION_OUT;
> +}
> +
> +static int sf_gpio_direction_input(struct gpio_chip *gc, unsigned int offset)
> +{
> + struct sf_gpio_priv *priv = to_sf_gpio(gc);
> +
> + sf_gpio_wr(priv, GPIO_OEN(offset), 1);
> + return 0;
> +}
> +
> +static int sf_gpio_direction_output(struct gpio_chip *gc, unsigned int offset,
> + int value)
> +{
> + struct sf_gpio_priv *priv = to_sf_gpio(gc);
> +
> + sf_gpio_wr(priv, GPIO_OR(offset), value);
> + sf_gpio_wr(priv, GPIO_OEN(offset), 0);
> + return 0;
> +}
> +
> +static int sf_gpio_set_debounce(struct gpio_chip *gc, unsigned int offset,
> + u32 debounce)
> +{
> + struct sf_gpio_priv *priv = to_sf_gpio(gc);
> + unsigned long freq = clk_get_rate(priv->clk);
> + u64 mul;
> +
> + /* (ICR + 1) * IFR = debounce_us * clkfreq_mhz / 4 */
> + mul = (u64)debounce * freq;
> + do_div(mul, 1000000 * 4);
> + if (mul > 0xff00)
> + return -EINVAL;
> +
> + sf_gpio_wr(priv, GPIO_ICR(offset), 0xff);
> + sf_gpio_wr(priv, GPIO_IFR(offset), DIV_ROUND_UP(mul, 0x100));
> +
> + return 0;
> +}
> +
> +static int sf_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
> + unsigned long config)
> +{
> + switch (pinconf_to_config_param(config)) {
> + case PIN_CONFIG_INPUT_DEBOUNCE:
> + return sf_gpio_set_debounce(gc, offset,
> + pinconf_to_config_argument(config));
> + default:
> + return gpiochip_generic_config(gc, offset, config);
> + }
> +}
> +
> +static void sf_gpio_irq_ack(struct irq_data *data)
> +{
> + struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
> + struct sf_gpio_priv *priv = to_sf_gpio(gc);
> + unsigned long offset = irqd_to_hwirq(data);
> +
> + sf_gpio_wr(priv, GPIO_PIR(offset), 0);
> +}
> +
> +static void sf_gpio_irq_mask(struct irq_data *data)
> +{
> + struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
> + struct sf_gpio_priv *priv = to_sf_gpio(gc);
> + unsigned long offset = irqd_to_hwirq(data);
> +
> + sf_gpio_wr(priv, GPIO_IMR(offset), 1);
> + sf_gpio_wr(priv, GPIO_GPIMR(offset), 1);
> + gpiochip_disable_irq(gc, offset);
> +}
> +
> +static void sf_gpio_irq_unmask(struct irq_data *data)
> +{
> + struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
> + struct sf_gpio_priv *priv = to_sf_gpio(gc);
> + unsigned long offset = irqd_to_hwirq(data);
> +
> + gpiochip_enable_irq(gc, offset);
> + sf_gpio_wr(priv, GPIO_IMR(offset), 0);
> + sf_gpio_wr(priv, GPIO_GPIMR(offset), 0);
> +}
> +
> +static int sf_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
> +{
> + struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
> + struct sf_gpio_priv *priv = to_sf_gpio(gc);
> + unsigned long offset = irqd_to_hwirq(data);
> + u32 val;
> +
> + switch (flow_type) {
> + case IRQ_TYPE_EDGE_RISING:
> + val = 4;
> + break;
> + case IRQ_TYPE_EDGE_FALLING:
> + val = 2;
> + break;
> + case IRQ_TYPE_EDGE_BOTH:
> + val = 6;
> + break;
> + case IRQ_TYPE_LEVEL_HIGH:
> + val = 1;
> + break;
> + case IRQ_TYPE_LEVEL_LOW:
> + val = 0;
> + break;
> + default:
> + return -EINVAL;
> + }
> + sf_gpio_wr(priv, GPIO_ITR(offset), val);
> +
> + if (flow_type & IRQ_TYPE_LEVEL_MASK)
> + irq_set_handler_locked(data, handle_level_irq);
> + else
Drop else.
> + irq_set_handler_locked(data, handle_edge_irq);
> +
> + return 0;
> +}
> +
> +static const struct irq_chip sf_gpio_irqchip = {
> + .name = KBUILD_MODNAME,
> + .irq_ack = sf_gpio_irq_ack,
> + .irq_mask = sf_gpio_irq_mask,
> + .irq_unmask = sf_gpio_irq_unmask,
> + .irq_set_type = sf_gpio_irq_set_type,
> + .flags = IRQCHIP_IMMUTABLE,
> + GPIOCHIP_IRQ_RESOURCE_HELPERS,
> +};
> +
> +static void sf_gpio_irq_handler(struct irq_desc *desc)
> +{
> + struct gpio_chip *gc = irq_desc_get_handler_data(desc);
> + struct irq_chip *ic = irq_desc_get_chip(desc);
> + struct sf_gpio_priv *priv = to_sf_gpio(gc);
> + unsigned int irq = irq_desc_get_irq(desc);
> + unsigned long pending;
> + unsigned int group, n;
> +
> + for (group = 0; group < gc->irq.num_parents; group++)
> + if (priv->irq[group] == irq)
> + break;
> + if (WARN_ON_ONCE(group == gc->irq.num_parents))
> + return;
> +
> + chained_irq_enter(ic, desc);
> +
> + pending = sf_gpio_rd(priv, GPIO_GPxIR(group));
> + for_each_set_bit(n, &pending, GPIOS_PER_GROUP) {
> + generic_handle_domain_irq(gc->irq.domain,
> + n + group * GPIOS_PER_GROUP);
> + }
> +
> + chained_irq_exit(ic, desc);
> +}
> +
> +static void sf_gpio_reset_assert(void *data)
> +{
> + reset_control_assert(data);
> +}
> +
> +static int sf_gpio_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct sf_gpio_priv *priv;
> + struct gpio_irq_chip *girq;
> + struct gpio_chip *gc;
> + u32 ngpios, ngroups;
> + int ret, i;
> +
> + ret = device_property_read_u32(dev, "ngpios", &ngpios);
> + if (ret)
> + return ret;
> +
> + ngroups = DIV_ROUND_UP(ngpios, GPIOS_PER_GROUP);
> + priv = devm_kzalloc(dev, struct_size(priv, irq, ngroups), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + priv->base = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(priv->base))
> + return PTR_ERR(priv->base);
> +
> + priv->clk = devm_clk_get_enabled(dev, NULL);
> + if (IS_ERR(priv->clk))
> + return PTR_ERR(priv->clk);
> +
> + priv->rstc = devm_reset_control_get_optional(&pdev->dev, NULL);
> + if (IS_ERR(priv->rstc))
> + return PTR_ERR(priv->rstc);
> +
> + ret = reset_control_deassert(priv->rstc);
> + if (ret)
> + return ret;
> +
> + ret = devm_add_action_or_reset(dev, sf_gpio_reset_assert, priv->rstc);
> + if (ret)
> + return ret;
> +
> + for (i = 0; i < ngroups; i++) {
> + ret = platform_get_irq(pdev, i);
> + if (ret < 0)
> + return ret;
> +
> + priv->irq[i] = ret;
> + }
> +
> + gc = &priv->gc;
> + gc->label = KBUILD_MODNAME;
> + gc->parent = dev;
> + gc->owner = THIS_MODULE;
> + gc->request = gpiochip_generic_request;
> + gc->free = gpiochip_generic_free;
> + gc->get_direction = sf_gpio_get_direction;
> + gc->direction_input = sf_gpio_direction_input;
> + gc->direction_output = sf_gpio_direction_output;
> + gc->get = sf_gpio_get_value;
> + gc->set = sf_gpio_set_value;
> + gc->set_config = sf_gpio_set_config;
> + gc->base = -1;
> + gc->ngpio = ngpios;
> +
> + girq = &gc->irq;
> + gpio_irq_chip_set_chip(girq, &sf_gpio_irqchip);
> + girq->num_parents = ngroups;
> + girq->parents = priv->irq;
> + girq->parent_handler = sf_gpio_irq_handler;
> + girq->default_type = IRQ_TYPE_NONE;
> + girq->handler = handle_bad_irq;
> +
> + return devm_gpiochip_add_data(dev, gc, priv);
> +}
> +
> +static const struct of_device_id sf_gpio_ids[] = {
> + { .compatible = "siflower,sf19a2890-gpio" },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, sf_gpio_ids);
> +
> +static struct platform_driver sf_gpio_driver = {
> + .probe = sf_gpio_probe,
> + .driver = {
> + .name = "siflower_gpio",
> + .of_match_table = sf_gpio_ids,
> + },
> +};
> +module_platform_driver(sf_gpio_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Qingfang Deng <qingfang.deng@siflower.com.cn>");
> +MODULE_DESCRIPTION("GPIO driver for Siflower SoCs");
>
> --
> Git-155)
>
>
Thanks,
Bartosz
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] dt-bindings: gpio: Add Siflower SF19A2890 GPIO controller
2026-11-04 8:12 ` Bartosz Golaszewski
@ 2026-11-04 8:32 ` Joseph Telaak
0 siblings, 0 replies; 10+ messages in thread
From: Joseph Telaak @ 2026-11-04 8:32 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Philipp Zabel, Chuanhong Guo, Qingfang Deng, linux-mips,
linux-gpio, devicetree, linux-kernel
> If you're a co-developer, please add your Co-developed-by: prefixed with
> a list that looks more like:
> [...]
> The above is completely unreadable.
Thanks, v2 will use Co-developed-by with the changes listed that way.
On Wed, Nov 4, 2026 at 3:12 AM Bartosz Golaszewski <brgl@kernel.org> wrote:
>
> On Wed, Nov 04, 2026 at 02:21:37AM -0500, Joseph Telaak via B4 Relay wrote:
> > From: Chuanhong Guo <gch981213@gmail.com>
> >
> > Document the GPIO controller found on the Siflower SF19A2890 and other
> > Siflower MIPS and RISC-V SoCs.
> >
> > Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
> > [jt: from Chuanhong's siflower-7.1 branch; Joseph Telaak as the binding's
> > maintainer, GPL-2.0-only for the deprecated GPL-2.0 SPDX identifier,
> > example indented by four spaces, commit message, subject]
> > Signed-off-by: Joseph Telaak <joseph@telaak.dev>
> > ---
>
> If you're a co-developer, please add your Co-developed-by: prefixed with
> a list that looks more like:
>
> [Joseph Telaak:
> - did foo
> - did bar]
>
> The above is completely unreadable.
>
> Thanks,
> Bartosz
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] gpio: Add Siflower GPIO controller driver
2026-11-04 8:16 ` Bartosz Golaszewski
@ 2026-11-04 8:38 ` Joseph Telaak
0 siblings, 0 replies; 10+ messages in thread
From: Joseph Telaak @ 2026-11-04 8:38 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Philipp Zabel, Chuanhong Guo, Qingfang Deng, linux-mips,
linux-gpio, devicetree, linux-kernel, Qingfang Deng
> Same comment as for the DT binding patch.
Will do.
> More common pattern is to retrieve the address of priv with
> gpiochip_get_data(). You already pass that address to
> devm_gpiochip_add_data().
Thanks for the review. v2 will use gpiochip_get_data(), drop both else
branches and add the blank line after the header comment.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] gpio: Add Siflower GPIO controller driver
2026-11-04 7:21 ` [PATCH 2/2] gpio: Add Siflower GPIO controller driver Joseph Telaak via B4 Relay
2026-11-04 7:38 ` sashiko-bot
2026-11-04 8:16 ` Bartosz Golaszewski
@ 2026-11-04 9:12 ` Philipp Zabel
2026-11-04 20:16 ` Joseph Telaak
2 siblings, 1 reply; 10+ messages in thread
From: Philipp Zabel @ 2026-11-04 9:12 UTC (permalink / raw)
To: joseph, Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: Chuanhong Guo, Qingfang Deng, linux-mips, linux-gpio, devicetree,
linux-kernel, Qingfang Deng
On Mi, 2026-11-04 at 02:21 -0500, Joseph Telaak via B4 Relay wrote:
> From: Qingfang Deng <qingfang.deng@siflower.com.cn>
>
> Add a driver for the GPIO controller on Siflower SoCs.
> This controller is found on all current Siflower MIPS and RISC-V
> chips including SF19A2890, SF21A6826 and SF21H8898.
>
> Signed-off-by: Qingfang Deng <qingfang.deng@siflower.com.cn>
> Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
> [jt: from Chuanhong's siflower-7.1 branch; depend on MACH_SIFLOWER_MIPS,
> longer Kconfig help, assert the reset through a devm action instead of in
> .remove, which ran before the GPIO chip was removed, drop .owner and the
> unused drvdata, drop the irq_set_affinity callback, which reached the
> parent through irq_to_desc() (not exported with SPARSE_IRQ), call
> gpiochip_disable_irq() and gpiochip_enable_irq() from mask and unmask as
> an immutable irqchip must, find the group by its parent IRQ instead of
> assuming consecutive numbers, return 0 or 1 from .get, read ngpios with
> device_property_read_u32(), linux/math64.h and sorted includes, "Siflower"
> spelling, subject]
> Signed-off-by: Joseph Telaak <joseph@telaak.dev>
> ---
> drivers/gpio/Kconfig | 11 ++
> drivers/gpio/Makefile | 1 +
> drivers/gpio/gpio-siflower.c | 325 +++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 337 insertions(+)
>
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index 55e428002..6125a8452 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -721,6 +721,17 @@ config GPIO_SIFIVE
> help
> Say yes here to support the GPIO device on SiFive SoCs.
>
> +config GPIO_SIFLOWER
> + tristate "Siflower GPIO support"
> + depends on OF_GPIO
> + depends on MACH_SIFLOWER_MIPS || COMPILE_TEST
> + select GPIOLIB_IRQCHIP
> + help
> + GPIO controller driver for Siflower MIPS and RISC-V SoCs
> + including SF19A2890, SF21A6826 and SF21H8898. Each line can be an
> + input or an output and raise an interrupt on either edge or level,
> + and inputs can be debounced in hardware.
> +
> config GPIO_SIOX
> tristate "SIOX GPIO support"
> depends on SIOX
> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> index 88f748846..bde618108 100644
> --- a/drivers/gpio/Makefile
> +++ b/drivers/gpio/Makefile
> @@ -171,6 +171,7 @@ obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o
> obj-$(CONFIG_GPIO_SCH) += gpio-sch.o
> obj-$(CONFIG_GPIO_SHARED_PROXY) += gpio-shared-proxy.o
> obj-$(CONFIG_GPIO_SIFIVE) += gpio-sifive.o
> +obj-$(CONFIG_GPIO_SIFLOWER) += gpio-siflower.o
> obj-$(CONFIG_GPIO_SIM) += gpio-sim.o
> obj-$(CONFIG_GPIO_SIOX) += gpio-siox.o
> obj-$(CONFIG_GPIO_SL28CPLD) += gpio-sl28cpld.o
> diff --git a/drivers/gpio/gpio-siflower.c b/drivers/gpio/gpio-siflower.c
> new file mode 100644
> index 000000000..6eb560da7
> --- /dev/null
> +++ b/drivers/gpio/gpio-siflower.c
> @@ -0,0 +1,325 @@
[...]
> +struct sf_gpio_priv {
> + struct gpio_chip gc;
> + void __iomem *base;
> + struct clk *clk;
> + struct reset_control *rstc;
rstc seems to be unused outside of the probe function.
[...]
> +static void sf_gpio_reset_assert(void *data)
> +{
> + reset_control_assert(data);
> +}
> +
> +static int sf_gpio_probe(struct platform_device *pdev)
> +{
[...]
> + priv->rstc = devm_reset_control_get_optional(&pdev->dev, NULL);
> + if (IS_ERR(priv->rstc))
> + return PTR_ERR(priv->rstc);
> +
> + ret = reset_control_deassert(priv->rstc);
> + if (ret)
> + return ret;
> +
> + ret = devm_add_action_or_reset(dev, sf_gpio_reset_assert, priv->rstc);
> + if (ret)
> + return ret;
Consider replacing this with
devm_reset_control_get_optional_exclusive_deasserted().
rstc can be a local variable then.
Don't use devm_reset_control_get_optional().
regards
Philipp
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] gpio: Add Siflower GPIO controller driver
2026-11-04 9:12 ` Philipp Zabel
@ 2026-11-04 20:16 ` Joseph Telaak
0 siblings, 0 replies; 10+ messages in thread
From: Joseph Telaak @ 2026-11-04 20:16 UTC (permalink / raw)
To: Philipp Zabel
Cc: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chuanhong Guo, Qingfang Deng,
linux-mips, linux-gpio, devicetree, linux-kernel, Qingfang Deng
> Consider replacing this with
> devm_reset_control_get_optional_exclusive_deasserted().
> rstc can be a local variable then.
>
> Don't use devm_reset_control_get_optional().
Thanks, v2 will do this. The binding makes resets required, so it will
use devm_reset_control_get_exclusive_deasserted(), with rstc as a local
in probe.
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-11-04 20:16 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-04 7:21 [PATCH 0/2] gpio: Add the Siflower SF19A2890 GPIO controller Joseph Telaak via B4 Relay
2026-11-04 7:21 ` [PATCH 1/2] dt-bindings: gpio: Add " Joseph Telaak via B4 Relay
2026-11-04 8:12 ` Bartosz Golaszewski
2026-11-04 8:32 ` Joseph Telaak
2026-11-04 7:21 ` [PATCH 2/2] gpio: Add Siflower GPIO controller driver Joseph Telaak via B4 Relay
2026-11-04 7:38 ` sashiko-bot
2026-11-04 8:16 ` Bartosz Golaszewski
2026-11-04 8:38 ` Joseph Telaak
2026-11-04 9:12 ` Philipp Zabel
2026-11-04 20:16 ` Joseph Telaak
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox