diff options
Diffstat (limited to 'drivers/gpio/gpio-vf610.c')
-rw-r--r-- | drivers/gpio/gpio-vf610.c | 95 |
1 files changed, 24 insertions, 71 deletions
diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 07e5e6323e86..7de0d5b53d56 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -15,10 +15,9 @@ #include <linux/io.h> #include <linux/ioport.h> #include <linux/irq.h> -#include <linux/platform_device.h> -#include <linux/of.h> -#include <linux/of_irq.h> #include <linux/pinctrl/consumer.h> +#include <linux/platform_device.h> +#include <linux/property.h> #define VF610_GPIO_PER_PORT 32 @@ -94,63 +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); - unsigned long 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); - unsigned long 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 gpio) -{ - struct vf610_gpio_port *port = gpiochip_get_data(chip); - unsigned long mask = BIT(gpio); - u32 val; - - if (port->sdata->have_paddr) { - 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 gpio, - int value) -{ - struct vf610_gpio_port *port = gpiochip_get_data(chip); - unsigned long mask = BIT(gpio); - u32 val; - - vf610_gpio_set(chip, gpio, value); - - if (port->sdata->have_paddr) { - 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 void vf610_gpio_irq_handler(struct irq_desc *desc) { struct vf610_gpio_port *port = @@ -276,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; @@ -284,7 +227,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) if (!port) return -ENOMEM; - port->sdata = of_device_get_match_data(dev); + port->sdata = device_get_match_data(dev); dual_base = port->sdata->have_dual_base; @@ -351,18 +294,26 @@ static int vf610_gpio_probe(struct platform_device *pdev) } gc = &port->gc; - gc->parent = dev; + flags = BGPIOF_PINCTRL_BACKEND; + /* + * 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) + 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->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; - /* Mask all GPIO interrupts */ for (i = 0; i < gc->ngpio; i++) vf610_gpio_writel(0, port->base + PORT_PCR(i)); @@ -394,4 +345,6 @@ static struct platform_driver vf610_gpio_driver = { .probe = vf610_gpio_probe, }; -builtin_platform_driver(vf610_gpio_driver); +module_platform_driver(vf610_gpio_driver); +MODULE_DESCRIPTION("VF610 GPIO driver"); +MODULE_LICENSE("GPL"); |