gpio: tb10x: Use GENERIC_GPIO
authorLinus Walleij <linus.walleij@linaro.org>
Mon, 6 Aug 2018 14:59:42 +0000 (16:59 +0200)
committerLinus Walleij <linus.walleij@linaro.org>
Wed, 29 Aug 2018 06:53:37 +0000 (08:53 +0200)
Instead of open coding logic for reading and writing GPIO lines,
use the generic GPIO library. Also switch to using the spinlock
from the generic GPIO to protect the registers.

Cc: linux-snps-arc@lists.infradead.org
Acked-by: Christian Ruppert <christian.ruppert@alitech.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/gpio/Kconfig
drivers/gpio/gpio-tb10x.c

index 4f52c3a8ec99bf0801ac1a2a3c7e01a9b9be1453..05cf02e46bef3989c7c71a83f725d623e0f0ca88 100644 (file)
@@ -480,6 +480,7 @@ config GPIO_SYSCON
 
 config GPIO_TB10X
        bool
+       select GPIO_GENERIC
        select GENERIC_IRQ_CHIP
        select OF_GPIO
 
index 422b0ac5a9de332f00d90371129e9d47840825c4..d5e5d19f4c0ad3a051802d3f2c832812b0834eaf 100644 (file)
 
 
 /**
- * @spinlock: used for atomic read/modify/write of registers
  * @base: register base address
  * @domain: IRQ domain of GPIO generated interrupts managed by this controller
  * @irq: Interrupt line of parent interrupt controller
  * @gc: gpio_chip structure associated to this GPIO controller
  */
 struct tb10x_gpio {
-       spinlock_t spinlock;
        void __iomem *base;
        struct irq_domain *domain;
        int irq;
@@ -76,60 +74,14 @@ static inline void tb10x_set_bits(struct tb10x_gpio *gpio, unsigned int offs,
        u32 r;
        unsigned long flags;
 
-       spin_lock_irqsave(&gpio->spinlock, flags);
+       spin_lock_irqsave(&gpio->gc.bgpio_lock, flags);
 
        r = tb10x_reg_read(gpio, offs);
        r = (r & ~mask) | (val & mask);
 
        tb10x_reg_write(gpio, offs, r);
 
-       spin_unlock_irqrestore(&gpio->spinlock, flags);
-}
-
-static int tb10x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
-{
-       struct tb10x_gpio *tb10x_gpio = gpiochip_get_data(chip);
-       int mask = BIT(offset);
-       int val = TB10X_GPIO_DIR_IN << offset;
-
-       tb10x_set_bits(tb10x_gpio, OFFSET_TO_REG_DDR, mask, val);
-
-       return 0;
-}
-
-static int tb10x_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct tb10x_gpio *tb10x_gpio = gpiochip_get_data(chip);
-       int val;
-
-       val = tb10x_reg_read(tb10x_gpio, OFFSET_TO_REG_DATA);
-
-       if (val & BIT(offset))
-               return 1;
-       else
-               return 0;
-}
-
-static void tb10x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct tb10x_gpio *tb10x_gpio = gpiochip_get_data(chip);
-       int mask = BIT(offset);
-       int val = value << offset;
-
-       tb10x_set_bits(tb10x_gpio, OFFSET_TO_REG_DATA, mask, val);
-}
-
-static int tb10x_gpio_direction_out(struct gpio_chip *chip,
-                                       unsigned offset, int value)
-{
-       struct tb10x_gpio *tb10x_gpio = gpiochip_get_data(chip);
-       int mask = BIT(offset);
-       int val = TB10X_GPIO_DIR_OUT << offset;
-
-       tb10x_gpio_set(chip, offset, value);
-       tb10x_set_bits(tb10x_gpio, OFFSET_TO_REG_DDR, mask, val);
-
-       return 0;
+       spin_unlock_irqrestore(&gpio->gc.bgpio_lock, flags);
 }
 
 static int tb10x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
@@ -184,8 +136,6 @@ static int tb10x_gpio_probe(struct platform_device *pdev)
        if (tb10x_gpio == NULL)
                return -ENOMEM;
 
-       spin_lock_init(&tb10x_gpio->spinlock);
-
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        tb10x_gpio->base = devm_ioremap_resource(dev, mem);
        if (IS_ERR(tb10x_gpio->base))
@@ -196,20 +146,34 @@ static int tb10x_gpio_probe(struct platform_device *pdev)
        if (!tb10x_gpio->gc.label)
                return -ENOMEM;
 
-       tb10x_gpio->gc.parent           = &pdev->dev;
-       tb10x_gpio->gc.owner            = THIS_MODULE;
-       tb10x_gpio->gc.direction_input  = tb10x_gpio_direction_in;
-       tb10x_gpio->gc.get              = tb10x_gpio_get;
-       tb10x_gpio->gc.direction_output = tb10x_gpio_direction_out;
-       tb10x_gpio->gc.set              = tb10x_gpio_set;
-       tb10x_gpio->gc.request          = gpiochip_generic_request;
-       tb10x_gpio->gc.free             = gpiochip_generic_free;
-       tb10x_gpio->gc.base             = -1;
-       tb10x_gpio->gc.ngpio            = ngpio;
-       tb10x_gpio->gc.can_sleep        = false;
-
-
-       ret = devm_gpiochip_add_data(&pdev->dev, &tb10x_gpio->gc, tb10x_gpio);
+       /*
+        * Initialize generic GPIO with one single register for reading and setting
+        * the lines, no special set or clear registers and a data direction register
+        * wher 1 means "output".
+        */
+       ret = bgpio_init(&tb10x_gpio->gc, dev, 4,
+                        tb10x_gpio->base + OFFSET_TO_REG_DATA,
+                        NULL,
+                        NULL,
+                        tb10x_gpio->base + OFFSET_TO_REG_DDR,
+                        NULL,
+                        0);
+       if (ret) {
+               dev_err(dev, "unable to init generic GPIO\n");
+               return ret;
+       }
+       tb10x_gpio->gc.base = -1;
+       tb10x_gpio->gc.parent = dev;
+       tb10x_gpio->gc.owner = THIS_MODULE;
+       /*
+        * ngpio is set by bgpio_init() but we override it, this .request()
+        * callback also overrides the one set up by generic GPIO.
+        */
+       tb10x_gpio->gc.ngpio = ngpio;
+       tb10x_gpio->gc.request = gpiochip_generic_request;
+       tb10x_gpio->gc.free = gpiochip_generic_free;
+
+       ret = devm_gpiochip_add_data(dev, &tb10x_gpio->gc, tb10x_gpio);
        if (ret < 0) {
                dev_err(dev, "Could not add gpiochip.\n");
                return ret;