mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
gpio: vf610: Switch to gpio-mmio
After adding a pinctrl flag to gpio-mmio we can use it for driving gpio-vf610. The existing code has the same semantics and the generic gpio-mmio, including reading from the data out register when the direction is set to input, and it can also handle the absence of the direction register better than the current driver: we get the direction from the shadow direction registers in gpio-mmio instead. Since gpio-mmio has an internal spinlock we can drop the direction-protecting spinlock from the driver. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Reviewed-by: Haibo Chen <haibo.chen@nxp.com> Tested-by: Haibo Chen <haibo.chen@nxp.com> Link: https://lore.kernel.org/r/20250219-vf610-mmio-v3-2-588b64f0b689@linaro.org Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
This commit is contained in:
parent
2145ba3740
commit
da5dd31efd
2 changed files with 18 additions and 88 deletions
|
@ -757,6 +757,7 @@ config GPIO_VF610
|
|||
default y if SOC_VF610
|
||||
depends on ARCH_MXC || COMPILE_TEST
|
||||
select GPIOLIB_IRQCHIP
|
||||
select GPIO_GENERIC
|
||||
help
|
||||
Say yes here to support i.MX or Vybrid vf610 GPIOs.
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@ struct vf610_gpio_port {
|
|||
struct clk *clk_port;
|
||||
struct clk *clk_gpio;
|
||||
int irq;
|
||||
spinlock_t lock; /* protect gpio direction registers */
|
||||
};
|
||||
|
||||
#define GPIO_PDOR 0x00
|
||||
|
@ -94,78 +93,6 @@ static inline u32 vf610_gpio_readl(void __iomem *reg)
|
|||
return readl_relaxed(reg);
|
||||
}
|
||||
|
||||
static int vf610_gpio_get(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct vf610_gpio_port *port = gpiochip_get_data(gc);
|
||||
u32 mask = BIT(gpio);
|
||||
unsigned long offset = GPIO_PDIR;
|
||||
|
||||
if (port->sdata->have_paddr) {
|
||||
mask &= vf610_gpio_readl(port->gpio_base + GPIO_PDDR);
|
||||
if (mask)
|
||||
offset = GPIO_PDOR;
|
||||
}
|
||||
|
||||
return !!(vf610_gpio_readl(port->gpio_base + offset) & BIT(gpio));
|
||||
}
|
||||
|
||||
static void vf610_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
{
|
||||
struct vf610_gpio_port *port = gpiochip_get_data(gc);
|
||||
u32 mask = BIT(gpio);
|
||||
unsigned long offset = val ? GPIO_PSOR : GPIO_PCOR;
|
||||
|
||||
vf610_gpio_writel(mask, port->gpio_base + offset);
|
||||
}
|
||||
|
||||
static int vf610_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio)
|
||||
{
|
||||
struct vf610_gpio_port *port = gpiochip_get_data(chip);
|
||||
u32 mask = BIT(gpio);
|
||||
u32 val;
|
||||
|
||||
if (port->sdata->have_paddr) {
|
||||
guard(spinlock_irqsave)(&port->lock);
|
||||
val = vf610_gpio_readl(port->gpio_base + GPIO_PDDR);
|
||||
val &= ~mask;
|
||||
vf610_gpio_writel(val, port->gpio_base + GPIO_PDDR);
|
||||
}
|
||||
|
||||
return pinctrl_gpio_direction_input(chip, gpio);
|
||||
}
|
||||
|
||||
static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio,
|
||||
int value)
|
||||
{
|
||||
struct vf610_gpio_port *port = gpiochip_get_data(chip);
|
||||
u32 mask = BIT(gpio);
|
||||
u32 val;
|
||||
|
||||
vf610_gpio_set(chip, gpio, value);
|
||||
|
||||
if (port->sdata->have_paddr) {
|
||||
guard(spinlock_irqsave)(&port->lock);
|
||||
val = vf610_gpio_readl(port->gpio_base + GPIO_PDDR);
|
||||
val |= mask;
|
||||
vf610_gpio_writel(val, port->gpio_base + GPIO_PDDR);
|
||||
}
|
||||
|
||||
return pinctrl_gpio_direction_output(chip, gpio);
|
||||
}
|
||||
|
||||
static int vf610_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct vf610_gpio_port *port = gpiochip_get_data(gc);
|
||||
u32 mask = BIT(gpio);
|
||||
|
||||
mask &= vf610_gpio_readl(port->gpio_base + GPIO_PDDR);
|
||||
|
||||
if (mask)
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static void vf610_gpio_irq_handler(struct irq_desc *desc)
|
||||
{
|
||||
struct vf610_gpio_port *port =
|
||||
|
@ -291,6 +218,7 @@ static int vf610_gpio_probe(struct platform_device *pdev)
|
|||
struct vf610_gpio_port *port;
|
||||
struct gpio_chip *gc;
|
||||
struct gpio_irq_chip *girq;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
int ret;
|
||||
bool dual_base;
|
||||
|
@ -300,7 +228,6 @@ static int vf610_gpio_probe(struct platform_device *pdev)
|
|||
return -ENOMEM;
|
||||
|
||||
port->sdata = device_get_match_data(dev);
|
||||
spin_lock_init(&port->lock);
|
||||
|
||||
dual_base = port->sdata->have_dual_base;
|
||||
|
||||
|
@ -367,23 +294,25 @@ static int vf610_gpio_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
gc = &port->gc;
|
||||
gc->parent = dev;
|
||||
gc->label = dev_name(dev);
|
||||
gc->ngpio = VF610_GPIO_PER_PORT;
|
||||
gc->base = -1;
|
||||
|
||||
gc->request = gpiochip_generic_request;
|
||||
gc->free = gpiochip_generic_free;
|
||||
gc->direction_input = vf610_gpio_direction_input;
|
||||
gc->get = vf610_gpio_get;
|
||||
gc->direction_output = vf610_gpio_direction_output;
|
||||
gc->set = vf610_gpio_set;
|
||||
flags = BGPIOF_PINCTRL_BACKEND;
|
||||
/*
|
||||
* only IP has Port Data Direction Register(PDDR) can
|
||||
* support get direction
|
||||
* We only read the output register for current value on output
|
||||
* lines if the direction register is available so we can switch
|
||||
* direction.
|
||||
*/
|
||||
if (port->sdata->have_paddr)
|
||||
gc->get_direction = vf610_gpio_get_direction;
|
||||
flags |= BGPIOF_READ_OUTPUT_REG_SET;
|
||||
ret = bgpio_init(gc, dev, 4,
|
||||
port->gpio_base + GPIO_PDIR,
|
||||
port->gpio_base + GPIO_PDOR,
|
||||
NULL,
|
||||
port->sdata->have_paddr ? port->gpio_base + GPIO_PDDR : NULL,
|
||||
NULL,
|
||||
flags);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "unable to init generic GPIO\n");
|
||||
gc->label = dev_name(dev);
|
||||
gc->base = -1;
|
||||
|
||||
/* Mask all GPIO interrupts */
|
||||
for (i = 0; i < gc->ngpio; i++)
|
||||
|
|
Loading…
Add table
Reference in a new issue