gpio: mxc: use new generic GPIO chip API

Convert the driver to using the new generic GPIO chip interfaces from
linux/gpio/generic.h.

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20250702-gpio-mmio-rework-v2-3-6b77aab684d8@linaro.org
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
This commit is contained in:
Bartosz Golaszewski 2025-07-02 11:22:10 +02:00
parent ba441322c7
commit 1f129b15c2

View file

@ -23,6 +23,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/syscore_ops.h> #include <linux/syscore_ops.h>
#include <linux/gpio/driver.h> #include <linux/gpio/driver.h>
#include <linux/gpio/generic.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/bug.h> #include <linux/bug.h>
@ -65,7 +66,7 @@ struct mxc_gpio_port {
int irq_high; int irq_high;
void (*mx_irq_handler)(struct irq_desc *desc); void (*mx_irq_handler)(struct irq_desc *desc);
struct irq_domain *domain; struct irq_domain *domain;
struct gpio_chip gc; struct gpio_generic_chip gen_gc;
struct device *dev; struct device *dev;
u32 both_edges; u32 both_edges;
struct mxc_gpio_reg_saved gpio_saved_reg; struct mxc_gpio_reg_saved gpio_saved_reg;
@ -179,7 +180,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
if (GPIO_EDGE_SEL >= 0) { if (GPIO_EDGE_SEL >= 0) {
edge = GPIO_INT_BOTH_EDGES; edge = GPIO_INT_BOTH_EDGES;
} else { } else {
val = port->gc.get(&port->gc, gpio_idx); val = port->gen_gc.gc.get(&port->gen_gc.gc, gpio_idx);
if (val) { if (val) {
edge = GPIO_INT_LOW_LEV; edge = GPIO_INT_LOW_LEV;
pr_debug("mxc: set GPIO %d to low trigger\n", gpio_idx); pr_debug("mxc: set GPIO %d to low trigger\n", gpio_idx);
@ -200,7 +201,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
return -EINVAL; return -EINVAL;
} }
scoped_guard(raw_spinlock_irqsave, &port->gc.bgpio_lock) { scoped_guard(gpio_generic_lock_irqsave, &port->gen_gc) {
if (GPIO_EDGE_SEL >= 0) { if (GPIO_EDGE_SEL >= 0) {
val = readl(port->base + GPIO_EDGE_SEL); val = readl(port->base + GPIO_EDGE_SEL);
if (edge == GPIO_INT_BOTH_EDGES) if (edge == GPIO_INT_BOTH_EDGES)
@ -222,7 +223,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
port->pad_type[gpio_idx] = type; port->pad_type[gpio_idx] = type;
} }
return port->gc.direction_input(&port->gc, gpio_idx); return port->gen_gc.gc.direction_input(&port->gen_gc.gc, gpio_idx);
} }
static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio) static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
@ -231,7 +232,7 @@ static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
u32 bit, val; u32 bit, val;
int edge; int edge;
guard(raw_spinlock_irqsave)(&port->gc.bgpio_lock); guard(gpio_generic_lock_irqsave)(&port->gen_gc);
reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */ reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
bit = gpio & 0xf; bit = gpio & 0xf;
@ -414,6 +415,7 @@ static void mxc_update_irq_chained_handler(struct mxc_gpio_port *port, bool enab
static int mxc_gpio_probe(struct platform_device *pdev) static int mxc_gpio_probe(struct platform_device *pdev)
{ {
struct gpio_generic_chip_config config = { };
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct mxc_gpio_port *port; struct mxc_gpio_port *port;
int irq_count; int irq_count;
@ -473,27 +475,31 @@ static int mxc_gpio_probe(struct platform_device *pdev)
port->mx_irq_handler = mx3_gpio_irq_handler; port->mx_irq_handler = mx3_gpio_irq_handler;
mxc_update_irq_chained_handler(port, true); mxc_update_irq_chained_handler(port, true);
err = bgpio_init(&port->gc, &pdev->dev, 4,
port->base + GPIO_PSR, config.dev = &pdev->dev;
port->base + GPIO_DR, NULL, config.sz = 4;
port->base + GPIO_GDIR, NULL, config.dat = port->base + GPIO_PSR;
BGPIOF_READ_OUTPUT_REG_SET); config.set = port->base + GPIO_DR;
config.dirout = port->base + GPIO_GDIR;
config.flags = BGPIOF_READ_OUTPUT_REG_SET;
err = gpio_generic_chip_init(&port->gen_gc, &config);
if (err) if (err)
goto out_bgio; goto out_bgio;
port->gc.request = mxc_gpio_request; port->gen_gc.gc.request = mxc_gpio_request;
port->gc.free = mxc_gpio_free; port->gen_gc.gc.free = mxc_gpio_free;
port->gc.to_irq = mxc_gpio_to_irq; port->gen_gc.gc.to_irq = mxc_gpio_to_irq;
/* /*
* Driver is DT-only, so a fixed base needs only be maintained for legacy * Driver is DT-only, so a fixed base needs only be maintained for legacy
* userspace with sysfs interface. * userspace with sysfs interface.
*/ */
if (IS_ENABLED(CONFIG_GPIO_SYSFS)) if (IS_ENABLED(CONFIG_GPIO_SYSFS))
port->gc.base = of_alias_get_id(np, "gpio") * 32; port->gen_gc.gc.base = of_alias_get_id(np, "gpio") * 32;
else /* silence boot time warning */ else /* silence boot time warning */
port->gc.base = -1; port->gen_gc.gc.base = -1;
err = devm_gpiochip_add_data(&pdev->dev, &port->gc, port); err = devm_gpiochip_add_data(&pdev->dev, &port->gen_gc.gc, port);
if (err) if (err)
goto out_bgio; goto out_bgio;
@ -567,7 +573,8 @@ static bool mxc_gpio_generic_config(struct mxc_gpio_port *port,
if (of_device_is_compatible(np, "fsl,imx8dxl-gpio") || if (of_device_is_compatible(np, "fsl,imx8dxl-gpio") ||
of_device_is_compatible(np, "fsl,imx8qxp-gpio") || of_device_is_compatible(np, "fsl,imx8qxp-gpio") ||
of_device_is_compatible(np, "fsl,imx8qm-gpio")) of_device_is_compatible(np, "fsl,imx8qm-gpio"))
return (gpiochip_generic_config(&port->gc, offset, conf) == 0); return (gpiochip_generic_config(&port->gen_gc.gc,
offset, conf) == 0);
return false; return false;
} }