Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: tb10x: Use GENERIC_GPIO

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>

+30 -65
+1
drivers/gpio/Kconfig
··· 480 480 481 481 config GPIO_TB10X 482 482 bool 483 + select GPIO_GENERIC 483 484 select GENERIC_IRQ_CHIP 484 485 select OF_GPIO 485 486
+29 -65
drivers/gpio/gpio-tb10x.c
··· 45 45 46 46 47 47 /** 48 - * @spinlock: used for atomic read/modify/write of registers 49 48 * @base: register base address 50 49 * @domain: IRQ domain of GPIO generated interrupts managed by this controller 51 50 * @irq: Interrupt line of parent interrupt controller 52 51 * @gc: gpio_chip structure associated to this GPIO controller 53 52 */ 54 53 struct tb10x_gpio { 55 - spinlock_t spinlock; 56 54 void __iomem *base; 57 55 struct irq_domain *domain; 58 56 int irq; ··· 74 76 u32 r; 75 77 unsigned long flags; 76 78 77 - spin_lock_irqsave(&gpio->spinlock, flags); 79 + spin_lock_irqsave(&gpio->gc.bgpio_lock, flags); 78 80 79 81 r = tb10x_reg_read(gpio, offs); 80 82 r = (r & ~mask) | (val & mask); 81 83 82 84 tb10x_reg_write(gpio, offs, r); 83 85 84 - spin_unlock_irqrestore(&gpio->spinlock, flags); 85 - } 86 - 87 - static int tb10x_gpio_direction_in(struct gpio_chip *chip, unsigned offset) 88 - { 89 - struct tb10x_gpio *tb10x_gpio = gpiochip_get_data(chip); 90 - int mask = BIT(offset); 91 - int val = TB10X_GPIO_DIR_IN << offset; 92 - 93 - tb10x_set_bits(tb10x_gpio, OFFSET_TO_REG_DDR, mask, val); 94 - 95 - return 0; 96 - } 97 - 98 - static int tb10x_gpio_get(struct gpio_chip *chip, unsigned offset) 99 - { 100 - struct tb10x_gpio *tb10x_gpio = gpiochip_get_data(chip); 101 - int val; 102 - 103 - val = tb10x_reg_read(tb10x_gpio, OFFSET_TO_REG_DATA); 104 - 105 - if (val & BIT(offset)) 106 - return 1; 107 - else 108 - return 0; 109 - } 110 - 111 - static void tb10x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 112 - { 113 - struct tb10x_gpio *tb10x_gpio = gpiochip_get_data(chip); 114 - int mask = BIT(offset); 115 - int val = value << offset; 116 - 117 - tb10x_set_bits(tb10x_gpio, OFFSET_TO_REG_DATA, mask, val); 118 - } 119 - 120 - static int tb10x_gpio_direction_out(struct gpio_chip *chip, 121 - unsigned offset, int value) 122 - { 123 - struct tb10x_gpio *tb10x_gpio = gpiochip_get_data(chip); 124 - int mask = BIT(offset); 125 - int val = TB10X_GPIO_DIR_OUT << offset; 126 - 127 - tb10x_gpio_set(chip, offset, value); 128 - tb10x_set_bits(tb10x_gpio, OFFSET_TO_REG_DDR, mask, val); 129 - 130 - return 0; 86 + spin_unlock_irqrestore(&gpio->gc.bgpio_lock, flags); 131 87 } 132 88 133 89 static int tb10x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) ··· 136 184 if (tb10x_gpio == NULL) 137 185 return -ENOMEM; 138 186 139 - spin_lock_init(&tb10x_gpio->spinlock); 140 - 141 187 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 142 188 tb10x_gpio->base = devm_ioremap_resource(dev, mem); 143 189 if (IS_ERR(tb10x_gpio->base)) ··· 146 196 if (!tb10x_gpio->gc.label) 147 197 return -ENOMEM; 148 198 149 - tb10x_gpio->gc.parent = &pdev->dev; 150 - tb10x_gpio->gc.owner = THIS_MODULE; 151 - tb10x_gpio->gc.direction_input = tb10x_gpio_direction_in; 152 - tb10x_gpio->gc.get = tb10x_gpio_get; 153 - tb10x_gpio->gc.direction_output = tb10x_gpio_direction_out; 154 - tb10x_gpio->gc.set = tb10x_gpio_set; 155 - tb10x_gpio->gc.request = gpiochip_generic_request; 156 - tb10x_gpio->gc.free = gpiochip_generic_free; 157 - tb10x_gpio->gc.base = -1; 158 - tb10x_gpio->gc.ngpio = ngpio; 159 - tb10x_gpio->gc.can_sleep = false; 199 + /* 200 + * Initialize generic GPIO with one single register for reading and setting 201 + * the lines, no special set or clear registers and a data direction register 202 + * wher 1 means "output". 203 + */ 204 + ret = bgpio_init(&tb10x_gpio->gc, dev, 4, 205 + tb10x_gpio->base + OFFSET_TO_REG_DATA, 206 + NULL, 207 + NULL, 208 + tb10x_gpio->base + OFFSET_TO_REG_DDR, 209 + NULL, 210 + 0); 211 + if (ret) { 212 + dev_err(dev, "unable to init generic GPIO\n"); 213 + return ret; 214 + } 215 + tb10x_gpio->gc.base = -1; 216 + tb10x_gpio->gc.parent = dev; 217 + tb10x_gpio->gc.owner = THIS_MODULE; 218 + /* 219 + * ngpio is set by bgpio_init() but we override it, this .request() 220 + * callback also overrides the one set up by generic GPIO. 221 + */ 222 + tb10x_gpio->gc.ngpio = ngpio; 223 + tb10x_gpio->gc.request = gpiochip_generic_request; 224 + tb10x_gpio->gc.free = gpiochip_generic_free; 160 225 161 - 162 - ret = devm_gpiochip_add_data(&pdev->dev, &tb10x_gpio->gc, tb10x_gpio); 226 + ret = devm_gpiochip_add_data(dev, &tb10x_gpio->gc, tb10x_gpio); 163 227 if (ret < 0) { 164 228 dev_err(dev, "Could not add gpiochip.\n"); 165 229 return ret;