1dae5f0afSLinus Walleij // SPDX-License-Identifier: GPL-2.0+ 2e9f4d569SChristian Lamparter /* 3e9f4d569SChristian Lamparter * Generic driver for memory-mapped GPIO controllers. 4e9f4d569SChristian Lamparter * 5e9f4d569SChristian Lamparter * Copyright 2008 MontaVista Software, Inc. 6e9f4d569SChristian Lamparter * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com> 7e9f4d569SChristian Lamparter * 8e9f4d569SChristian Lamparter * ....``.```~~~~````.`.`.`.`.```````'',,,.........`````......`....... 9e9f4d569SChristian Lamparter * ...`` ```````.. 10e9f4d569SChristian Lamparter * ..The simplest form of a GPIO controller that the driver supports is`` 11e9f4d569SChristian Lamparter * `.just a single "data" register, where GPIO state can be read and/or ` 12e9f4d569SChristian Lamparter * `,..written. ,,..``~~~~ .....``.`.`.~~.```.`.........``````.``````` 13e9f4d569SChristian Lamparter * ````````` 14e9f4d569SChristian Lamparter ___ 15e9f4d569SChristian Lamparter _/~~|___/~| . ```~~~~~~ ___/___\___ ,~.`.`.`.`````.~~...,,,,... 16e9f4d569SChristian Lamparter __________|~$@~~~ %~ /o*o*o*o*o*o\ .. Implementing such a GPIO . 17e9f4d569SChristian Lamparter o ` ~~~~\___/~~~~ ` controller in FPGA is ,.` 18e9f4d569SChristian Lamparter `....trivial..'~`.```.``` 19e9f4d569SChristian Lamparter * ``````` 20e9f4d569SChristian Lamparter * .```````~~~~`..`.``.``. 21e9f4d569SChristian Lamparter * . The driver supports `... ,..```.`~~~```````````````....````.``,, 22e9f4d569SChristian Lamparter * . big-endian notation, just`. .. A bit more sophisticated controllers , 23e9f4d569SChristian Lamparter * . register the device with -be`. .with a pair of set/clear-bit registers , 24e9f4d569SChristian Lamparter * `.. suffix. ```~~`````....`.` . affecting the data register and the .` 25e9f4d569SChristian Lamparter * ``.`.``...``` ```.. output pins are also supported.` 26e9f4d569SChristian Lamparter * ^^ `````.`````````.,``~``~``~~`````` 27e9f4d569SChristian Lamparter * . ^^ 28e9f4d569SChristian Lamparter * ,..`.`.`...````````````......`.`.`.`.`.`..`.`.`.. 29e9f4d569SChristian Lamparter * .. The expectation is that in at least some cases . ,-~~~-, 30e9f4d569SChristian Lamparter * .this will be used with roll-your-own ASIC/FPGA .` \ / 31e9f4d569SChristian Lamparter * .logic in Verilog or VHDL. ~~~`````````..`````~~` \ / 32e9f4d569SChristian Lamparter * ..````````......``````````` \o_ 33e9f4d569SChristian Lamparter * | 34e9f4d569SChristian Lamparter * ^^ / \ 35e9f4d569SChristian Lamparter * 36e9f4d569SChristian Lamparter * ...`````~~`.....``.`..........``````.`.``.```........``. 37e9f4d569SChristian Lamparter * ` 8, 16, 32 and 64 bits registers are supported, and``. 38e9f4d569SChristian Lamparter * . the number of GPIOs is determined by the width of ~ 39e9f4d569SChristian Lamparter * .. the registers. ,............```.`.`..`.`.~~~.`.`.`~ 40e9f4d569SChristian Lamparter * `.......````.``` 41e9f4d569SChristian Lamparter */ 42e9f4d569SChristian Lamparter 43e9f4d569SChristian Lamparter #include <linux/init.h> 44e9f4d569SChristian Lamparter #include <linux/err.h> 45e9f4d569SChristian Lamparter #include <linux/bug.h> 46e9f4d569SChristian Lamparter #include <linux/kernel.h> 47e9f4d569SChristian Lamparter #include <linux/module.h> 48e9f4d569SChristian Lamparter #include <linux/spinlock.h> 49e9f4d569SChristian Lamparter #include <linux/compiler.h> 50e9f4d569SChristian Lamparter #include <linux/types.h> 51e9f4d569SChristian Lamparter #include <linux/errno.h> 52e9f4d569SChristian Lamparter #include <linux/log2.h> 53e9f4d569SChristian Lamparter #include <linux/ioport.h> 54e9f4d569SChristian Lamparter #include <linux/io.h> 55e9f4d569SChristian Lamparter #include <linux/gpio/driver.h> 56e9f4d569SChristian Lamparter #include <linux/slab.h> 57e9f4d569SChristian Lamparter #include <linux/bitops.h> 58e9f4d569SChristian Lamparter #include <linux/platform_device.h> 59e9f4d569SChristian Lamparter #include <linux/mod_devicetable.h> 60e698613aSÁlvaro Fernández Rojas #include <linux/of.h> 61e698613aSÁlvaro Fernández Rojas #include <linux/of_device.h> 62e9f4d569SChristian Lamparter 63e9f4d569SChristian Lamparter static void bgpio_write8(void __iomem *reg, unsigned long data) 64e9f4d569SChristian Lamparter { 65e9f4d569SChristian Lamparter writeb(data, reg); 66e9f4d569SChristian Lamparter } 67e9f4d569SChristian Lamparter 68e9f4d569SChristian Lamparter static unsigned long bgpio_read8(void __iomem *reg) 69e9f4d569SChristian Lamparter { 70e9f4d569SChristian Lamparter return readb(reg); 71e9f4d569SChristian Lamparter } 72e9f4d569SChristian Lamparter 73e9f4d569SChristian Lamparter static void bgpio_write16(void __iomem *reg, unsigned long data) 74e9f4d569SChristian Lamparter { 75e9f4d569SChristian Lamparter writew(data, reg); 76e9f4d569SChristian Lamparter } 77e9f4d569SChristian Lamparter 78e9f4d569SChristian Lamparter static unsigned long bgpio_read16(void __iomem *reg) 79e9f4d569SChristian Lamparter { 80e9f4d569SChristian Lamparter return readw(reg); 81e9f4d569SChristian Lamparter } 82e9f4d569SChristian Lamparter 83e9f4d569SChristian Lamparter static void bgpio_write32(void __iomem *reg, unsigned long data) 84e9f4d569SChristian Lamparter { 85e9f4d569SChristian Lamparter writel(data, reg); 86e9f4d569SChristian Lamparter } 87e9f4d569SChristian Lamparter 88e9f4d569SChristian Lamparter static unsigned long bgpio_read32(void __iomem *reg) 89e9f4d569SChristian Lamparter { 90e9f4d569SChristian Lamparter return readl(reg); 91e9f4d569SChristian Lamparter } 92e9f4d569SChristian Lamparter 93e9f4d569SChristian Lamparter #if BITS_PER_LONG >= 64 94e9f4d569SChristian Lamparter static void bgpio_write64(void __iomem *reg, unsigned long data) 95e9f4d569SChristian Lamparter { 96e9f4d569SChristian Lamparter writeq(data, reg); 97e9f4d569SChristian Lamparter } 98e9f4d569SChristian Lamparter 99e9f4d569SChristian Lamparter static unsigned long bgpio_read64(void __iomem *reg) 100e9f4d569SChristian Lamparter { 101e9f4d569SChristian Lamparter return readq(reg); 102e9f4d569SChristian Lamparter } 103e9f4d569SChristian Lamparter #endif /* BITS_PER_LONG >= 64 */ 104e9f4d569SChristian Lamparter 105e9f4d569SChristian Lamparter static void bgpio_write16be(void __iomem *reg, unsigned long data) 106e9f4d569SChristian Lamparter { 107e9f4d569SChristian Lamparter iowrite16be(data, reg); 108e9f4d569SChristian Lamparter } 109e9f4d569SChristian Lamparter 110e9f4d569SChristian Lamparter static unsigned long bgpio_read16be(void __iomem *reg) 111e9f4d569SChristian Lamparter { 112e9f4d569SChristian Lamparter return ioread16be(reg); 113e9f4d569SChristian Lamparter } 114e9f4d569SChristian Lamparter 115e9f4d569SChristian Lamparter static void bgpio_write32be(void __iomem *reg, unsigned long data) 116e9f4d569SChristian Lamparter { 117e9f4d569SChristian Lamparter iowrite32be(data, reg); 118e9f4d569SChristian Lamparter } 119e9f4d569SChristian Lamparter 120e9f4d569SChristian Lamparter static unsigned long bgpio_read32be(void __iomem *reg) 121e9f4d569SChristian Lamparter { 122e9f4d569SChristian Lamparter return ioread32be(reg); 123e9f4d569SChristian Lamparter } 124e9f4d569SChristian Lamparter 12524efd94bSLinus Walleij static unsigned long bgpio_line2mask(struct gpio_chip *gc, unsigned int line) 126e9f4d569SChristian Lamparter { 12724efd94bSLinus Walleij if (gc->be_bits) 12824efd94bSLinus Walleij return BIT(gc->bgpio_bits - 1 - line); 12924efd94bSLinus Walleij return BIT(line); 130e9f4d569SChristian Lamparter } 131e9f4d569SChristian Lamparter 132e9f4d569SChristian Lamparter static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio) 133e9f4d569SChristian Lamparter { 13424efd94bSLinus Walleij unsigned long pinmask = bgpio_line2mask(gc, gpio); 135d799a4deSLinus Walleij bool dir = !!(gc->bgpio_dir & pinmask); 136e9f4d569SChristian Lamparter 137d799a4deSLinus Walleij /* 138d799a4deSLinus Walleij * If the direction is OUT we read the value from the SET 139d799a4deSLinus Walleij * register, and if the direction is IN we read the value 140d799a4deSLinus Walleij * from the DAT register. 141d799a4deSLinus Walleij * 142d799a4deSLinus Walleij * If the direction bits are inverted, naturally this gets 143d799a4deSLinus Walleij * inverted too. 144d799a4deSLinus Walleij */ 145d799a4deSLinus Walleij if (gc->bgpio_dir_inverted) 146d799a4deSLinus Walleij dir = !dir; 147d799a4deSLinus Walleij 148d799a4deSLinus Walleij if (dir) 149e9f4d569SChristian Lamparter return !!(gc->read_reg(gc->reg_set) & pinmask); 150e9f4d569SChristian Lamparter else 151e9f4d569SChristian Lamparter return !!(gc->read_reg(gc->reg_dat) & pinmask); 152e9f4d569SChristian Lamparter } 153e9f4d569SChristian Lamparter 15480057cb4SLinus Walleij /* 15580057cb4SLinus Walleij * This assumes that the bits in the GPIO register are in native endianness. 15680057cb4SLinus Walleij * We only assign the function pointer if we have that. 15780057cb4SLinus Walleij */ 15880057cb4SLinus Walleij static int bgpio_get_set_multiple(struct gpio_chip *gc, unsigned long *mask, 15980057cb4SLinus Walleij unsigned long *bits) 16080057cb4SLinus Walleij { 16180057cb4SLinus Walleij unsigned long get_mask = 0; 16280057cb4SLinus Walleij unsigned long set_mask = 0; 16380057cb4SLinus Walleij 16407c7b6a5SLinus Walleij /* Make sure we first clear any bits that are zero when we read the register */ 16507c7b6a5SLinus Walleij *bits &= ~*mask; 16607c7b6a5SLinus Walleij 16707c7b6a5SLinus Walleij /* Exploit the fact that we know which directions are set */ 168d799a4deSLinus Walleij if (gc->bgpio_dir_inverted) { 169d799a4deSLinus Walleij set_mask = *mask & ~gc->bgpio_dir; 170d799a4deSLinus Walleij get_mask = *mask & gc->bgpio_dir; 171d799a4deSLinus Walleij } else { 17207c7b6a5SLinus Walleij set_mask = *mask & gc->bgpio_dir; 17307c7b6a5SLinus Walleij get_mask = *mask & ~gc->bgpio_dir; 174d799a4deSLinus Walleij } 17580057cb4SLinus Walleij 17680057cb4SLinus Walleij if (set_mask) 17780057cb4SLinus Walleij *bits |= gc->read_reg(gc->reg_set) & set_mask; 17880057cb4SLinus Walleij if (get_mask) 17980057cb4SLinus Walleij *bits |= gc->read_reg(gc->reg_dat) & get_mask; 18080057cb4SLinus Walleij 18180057cb4SLinus Walleij return 0; 18280057cb4SLinus Walleij } 18380057cb4SLinus Walleij 184e9f4d569SChristian Lamparter static int bgpio_get(struct gpio_chip *gc, unsigned int gpio) 185e9f4d569SChristian Lamparter { 18624efd94bSLinus Walleij return !!(gc->read_reg(gc->reg_dat) & bgpio_line2mask(gc, gpio)); 187e9f4d569SChristian Lamparter } 188e9f4d569SChristian Lamparter 18980057cb4SLinus Walleij /* 19080057cb4SLinus Walleij * This only works if the bits in the GPIO register are in native endianness. 19180057cb4SLinus Walleij */ 19280057cb4SLinus Walleij static int bgpio_get_multiple(struct gpio_chip *gc, unsigned long *mask, 19380057cb4SLinus Walleij unsigned long *bits) 19480057cb4SLinus Walleij { 19507c7b6a5SLinus Walleij /* Make sure we first clear any bits that are zero when we read the register */ 19607c7b6a5SLinus Walleij *bits &= ~*mask; 19707c7b6a5SLinus Walleij *bits |= gc->read_reg(gc->reg_dat) & *mask; 19880057cb4SLinus Walleij return 0; 19980057cb4SLinus Walleij } 20080057cb4SLinus Walleij 20180057cb4SLinus Walleij /* 20280057cb4SLinus Walleij * With big endian mirrored bit order it becomes more tedious. 20380057cb4SLinus Walleij */ 20480057cb4SLinus Walleij static int bgpio_get_multiple_be(struct gpio_chip *gc, unsigned long *mask, 20580057cb4SLinus Walleij unsigned long *bits) 20680057cb4SLinus Walleij { 20780057cb4SLinus Walleij unsigned long readmask = 0; 20880057cb4SLinus Walleij unsigned long val; 20980057cb4SLinus Walleij int bit; 21080057cb4SLinus Walleij 21107c7b6a5SLinus Walleij /* Make sure we first clear any bits that are zero when we read the register */ 21207c7b6a5SLinus Walleij *bits &= ~*mask; 21307c7b6a5SLinus Walleij 21480057cb4SLinus Walleij /* Create a mirrored mask */ 21507c7b6a5SLinus Walleij bit = -1; 21607c7b6a5SLinus Walleij while ((bit = find_next_bit(mask, gc->ngpio, bit + 1)) < gc->ngpio) 21780057cb4SLinus Walleij readmask |= bgpio_line2mask(gc, bit); 21880057cb4SLinus Walleij 21980057cb4SLinus Walleij /* Read the register */ 22080057cb4SLinus Walleij val = gc->read_reg(gc->reg_dat) & readmask; 22180057cb4SLinus Walleij 22280057cb4SLinus Walleij /* 22380057cb4SLinus Walleij * Mirror the result into the "bits" result, this will give line 0 22480057cb4SLinus Walleij * in bit 0 ... line 31 in bit 31 for a 32bit register. 22580057cb4SLinus Walleij */ 22607c7b6a5SLinus Walleij bit = -1; 22707c7b6a5SLinus Walleij while ((bit = find_next_bit(&val, gc->ngpio, bit + 1)) < gc->ngpio) 22880057cb4SLinus Walleij *bits |= bgpio_line2mask(gc, bit); 22980057cb4SLinus Walleij 23080057cb4SLinus Walleij return 0; 23180057cb4SLinus Walleij } 23280057cb4SLinus Walleij 233e9f4d569SChristian Lamparter static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val) 234e9f4d569SChristian Lamparter { 235e9f4d569SChristian Lamparter } 236e9f4d569SChristian Lamparter 237e9f4d569SChristian Lamparter static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) 238e9f4d569SChristian Lamparter { 23924efd94bSLinus Walleij unsigned long mask = bgpio_line2mask(gc, gpio); 240e9f4d569SChristian Lamparter unsigned long flags; 241e9f4d569SChristian Lamparter 242e9f4d569SChristian Lamparter spin_lock_irqsave(&gc->bgpio_lock, flags); 243e9f4d569SChristian Lamparter 244e9f4d569SChristian Lamparter if (val) 245e9f4d569SChristian Lamparter gc->bgpio_data |= mask; 246e9f4d569SChristian Lamparter else 247e9f4d569SChristian Lamparter gc->bgpio_data &= ~mask; 248e9f4d569SChristian Lamparter 249e9f4d569SChristian Lamparter gc->write_reg(gc->reg_dat, gc->bgpio_data); 250e9f4d569SChristian Lamparter 251e9f4d569SChristian Lamparter spin_unlock_irqrestore(&gc->bgpio_lock, flags); 252e9f4d569SChristian Lamparter } 253e9f4d569SChristian Lamparter 254e9f4d569SChristian Lamparter static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio, 255e9f4d569SChristian Lamparter int val) 256e9f4d569SChristian Lamparter { 25724efd94bSLinus Walleij unsigned long mask = bgpio_line2mask(gc, gpio); 258e9f4d569SChristian Lamparter 259e9f4d569SChristian Lamparter if (val) 260e9f4d569SChristian Lamparter gc->write_reg(gc->reg_set, mask); 261e9f4d569SChristian Lamparter else 262e9f4d569SChristian Lamparter gc->write_reg(gc->reg_clr, mask); 263e9f4d569SChristian Lamparter } 264e9f4d569SChristian Lamparter 265e9f4d569SChristian Lamparter static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) 266e9f4d569SChristian Lamparter { 26724efd94bSLinus Walleij unsigned long mask = bgpio_line2mask(gc, gpio); 268e9f4d569SChristian Lamparter unsigned long flags; 269e9f4d569SChristian Lamparter 270e9f4d569SChristian Lamparter spin_lock_irqsave(&gc->bgpio_lock, flags); 271e9f4d569SChristian Lamparter 272e9f4d569SChristian Lamparter if (val) 273e9f4d569SChristian Lamparter gc->bgpio_data |= mask; 274e9f4d569SChristian Lamparter else 275e9f4d569SChristian Lamparter gc->bgpio_data &= ~mask; 276e9f4d569SChristian Lamparter 277e9f4d569SChristian Lamparter gc->write_reg(gc->reg_set, gc->bgpio_data); 278e9f4d569SChristian Lamparter 279e9f4d569SChristian Lamparter spin_unlock_irqrestore(&gc->bgpio_lock, flags); 280e9f4d569SChristian Lamparter } 281e9f4d569SChristian Lamparter 282e9f4d569SChristian Lamparter static void bgpio_multiple_get_masks(struct gpio_chip *gc, 283e9f4d569SChristian Lamparter unsigned long *mask, unsigned long *bits, 284e9f4d569SChristian Lamparter unsigned long *set_mask, 285e9f4d569SChristian Lamparter unsigned long *clear_mask) 286e9f4d569SChristian Lamparter { 287e9f4d569SChristian Lamparter int i; 288e9f4d569SChristian Lamparter 289e9f4d569SChristian Lamparter *set_mask = 0; 290e9f4d569SChristian Lamparter *clear_mask = 0; 291e9f4d569SChristian Lamparter 292e9f4d569SChristian Lamparter for (i = 0; i < gc->bgpio_bits; i++) { 293e9f4d569SChristian Lamparter if (*mask == 0) 294e9f4d569SChristian Lamparter break; 295e9f4d569SChristian Lamparter if (__test_and_clear_bit(i, mask)) { 296e9f4d569SChristian Lamparter if (test_bit(i, bits)) 29724efd94bSLinus Walleij *set_mask |= bgpio_line2mask(gc, i); 298e9f4d569SChristian Lamparter else 29924efd94bSLinus Walleij *clear_mask |= bgpio_line2mask(gc, i); 300e9f4d569SChristian Lamparter } 301e9f4d569SChristian Lamparter } 302e9f4d569SChristian Lamparter } 303e9f4d569SChristian Lamparter 304e9f4d569SChristian Lamparter static void bgpio_set_multiple_single_reg(struct gpio_chip *gc, 305e9f4d569SChristian Lamparter unsigned long *mask, 306e9f4d569SChristian Lamparter unsigned long *bits, 307e9f4d569SChristian Lamparter void __iomem *reg) 308e9f4d569SChristian Lamparter { 309e9f4d569SChristian Lamparter unsigned long flags; 310e9f4d569SChristian Lamparter unsigned long set_mask, clear_mask; 311e9f4d569SChristian Lamparter 312e9f4d569SChristian Lamparter spin_lock_irqsave(&gc->bgpio_lock, flags); 313e9f4d569SChristian Lamparter 314e9f4d569SChristian Lamparter bgpio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask); 315e9f4d569SChristian Lamparter 316e9f4d569SChristian Lamparter gc->bgpio_data |= set_mask; 317e9f4d569SChristian Lamparter gc->bgpio_data &= ~clear_mask; 318e9f4d569SChristian Lamparter 319e9f4d569SChristian Lamparter gc->write_reg(reg, gc->bgpio_data); 320e9f4d569SChristian Lamparter 321e9f4d569SChristian Lamparter spin_unlock_irqrestore(&gc->bgpio_lock, flags); 322e9f4d569SChristian Lamparter } 323e9f4d569SChristian Lamparter 324e9f4d569SChristian Lamparter static void bgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, 325e9f4d569SChristian Lamparter unsigned long *bits) 326e9f4d569SChristian Lamparter { 327e9f4d569SChristian Lamparter bgpio_set_multiple_single_reg(gc, mask, bits, gc->reg_dat); 328e9f4d569SChristian Lamparter } 329e9f4d569SChristian Lamparter 330e9f4d569SChristian Lamparter static void bgpio_set_multiple_set(struct gpio_chip *gc, unsigned long *mask, 331e9f4d569SChristian Lamparter unsigned long *bits) 332e9f4d569SChristian Lamparter { 333e9f4d569SChristian Lamparter bgpio_set_multiple_single_reg(gc, mask, bits, gc->reg_set); 334e9f4d569SChristian Lamparter } 335e9f4d569SChristian Lamparter 336e9f4d569SChristian Lamparter static void bgpio_set_multiple_with_clear(struct gpio_chip *gc, 337e9f4d569SChristian Lamparter unsigned long *mask, 338e9f4d569SChristian Lamparter unsigned long *bits) 339e9f4d569SChristian Lamparter { 340e9f4d569SChristian Lamparter unsigned long set_mask, clear_mask; 341e9f4d569SChristian Lamparter 342e9f4d569SChristian Lamparter bgpio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask); 343e9f4d569SChristian Lamparter 344e9f4d569SChristian Lamparter if (set_mask) 345e9f4d569SChristian Lamparter gc->write_reg(gc->reg_set, set_mask); 346e9f4d569SChristian Lamparter if (clear_mask) 347e9f4d569SChristian Lamparter gc->write_reg(gc->reg_clr, clear_mask); 348e9f4d569SChristian Lamparter } 349e9f4d569SChristian Lamparter 350e9f4d569SChristian Lamparter static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio) 351e9f4d569SChristian Lamparter { 352e9f4d569SChristian Lamparter return 0; 353e9f4d569SChristian Lamparter } 354e9f4d569SChristian Lamparter 355e9f4d569SChristian Lamparter static int bgpio_dir_out_err(struct gpio_chip *gc, unsigned int gpio, 356e9f4d569SChristian Lamparter int val) 357e9f4d569SChristian Lamparter { 358e9f4d569SChristian Lamparter return -EINVAL; 359e9f4d569SChristian Lamparter } 360e9f4d569SChristian Lamparter 361e9f4d569SChristian Lamparter static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio, 362e9f4d569SChristian Lamparter int val) 363e9f4d569SChristian Lamparter { 364e9f4d569SChristian Lamparter gc->set(gc, gpio, val); 365e9f4d569SChristian Lamparter 366e9f4d569SChristian Lamparter return 0; 367e9f4d569SChristian Lamparter } 368e9f4d569SChristian Lamparter 369e9f4d569SChristian Lamparter static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) 370e9f4d569SChristian Lamparter { 371e9f4d569SChristian Lamparter unsigned long flags; 372e9f4d569SChristian Lamparter 373e9f4d569SChristian Lamparter spin_lock_irqsave(&gc->bgpio_lock, flags); 374e9f4d569SChristian Lamparter 37524efd94bSLinus Walleij gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio); 376*f69e00bdSLinus Walleij 377*f69e00bdSLinus Walleij if (gc->reg_dir_in) 378*f69e00bdSLinus Walleij gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir); 379*f69e00bdSLinus Walleij if (gc->reg_dir_out) 380*f69e00bdSLinus Walleij gc->write_reg(gc->reg_dir_out, gc->bgpio_dir); 381e9f4d569SChristian Lamparter 382e9f4d569SChristian Lamparter spin_unlock_irqrestore(&gc->bgpio_lock, flags); 383e9f4d569SChristian Lamparter 384e9f4d569SChristian Lamparter return 0; 385e9f4d569SChristian Lamparter } 386e9f4d569SChristian Lamparter 387e9f4d569SChristian Lamparter static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio) 388e9f4d569SChristian Lamparter { 389*f69e00bdSLinus Walleij /* Return 0 if output, 1 if input */ 390*f69e00bdSLinus Walleij if (gc->bgpio_dir_unreadable) 391*f69e00bdSLinus Walleij return !(gc->bgpio_dir & bgpio_line2mask(gc, gpio)); 392*f69e00bdSLinus Walleij if (gc->reg_dir_out) 393*f69e00bdSLinus Walleij return !(gc->read_reg(gc->reg_dir_out) & bgpio_line2mask(gc, gpio)); 394*f69e00bdSLinus Walleij if (gc->reg_dir_in) 395*f69e00bdSLinus Walleij return !!(gc->read_reg(gc->reg_dir_in) & bgpio_line2mask(gc, gpio)); 396*f69e00bdSLinus Walleij 397*f69e00bdSLinus Walleij /* This should not happen */ 398*f69e00bdSLinus Walleij return 1; 399e9f4d569SChristian Lamparter } 400e9f4d569SChristian Lamparter 401e9f4d569SChristian Lamparter static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) 402e9f4d569SChristian Lamparter { 403e9f4d569SChristian Lamparter unsigned long flags; 404e9f4d569SChristian Lamparter 405e9f4d569SChristian Lamparter gc->set(gc, gpio, val); 406e9f4d569SChristian Lamparter 407e9f4d569SChristian Lamparter spin_lock_irqsave(&gc->bgpio_lock, flags); 408e9f4d569SChristian Lamparter 409d799a4deSLinus Walleij gc->bgpio_dir |= bgpio_line2mask(gc, gpio); 410*f69e00bdSLinus Walleij 411*f69e00bdSLinus Walleij if (gc->reg_dir_in) 412*f69e00bdSLinus Walleij gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir); 413*f69e00bdSLinus Walleij if (gc->reg_dir_out) 414*f69e00bdSLinus Walleij gc->write_reg(gc->reg_dir_out, gc->bgpio_dir); 415e9f4d569SChristian Lamparter 416e9f4d569SChristian Lamparter spin_unlock_irqrestore(&gc->bgpio_lock, flags); 417e9f4d569SChristian Lamparter 418e9f4d569SChristian Lamparter return 0; 419e9f4d569SChristian Lamparter } 420e9f4d569SChristian Lamparter 421e9f4d569SChristian Lamparter static int bgpio_setup_accessors(struct device *dev, 422e9f4d569SChristian Lamparter struct gpio_chip *gc, 423e9f4d569SChristian Lamparter bool byte_be) 424e9f4d569SChristian Lamparter { 425e9f4d569SChristian Lamparter 426e9f4d569SChristian Lamparter switch (gc->bgpio_bits) { 427e9f4d569SChristian Lamparter case 8: 428e9f4d569SChristian Lamparter gc->read_reg = bgpio_read8; 429e9f4d569SChristian Lamparter gc->write_reg = bgpio_write8; 430e9f4d569SChristian Lamparter break; 431e9f4d569SChristian Lamparter case 16: 432e9f4d569SChristian Lamparter if (byte_be) { 433e9f4d569SChristian Lamparter gc->read_reg = bgpio_read16be; 434e9f4d569SChristian Lamparter gc->write_reg = bgpio_write16be; 435e9f4d569SChristian Lamparter } else { 436e9f4d569SChristian Lamparter gc->read_reg = bgpio_read16; 437e9f4d569SChristian Lamparter gc->write_reg = bgpio_write16; 438e9f4d569SChristian Lamparter } 439e9f4d569SChristian Lamparter break; 440e9f4d569SChristian Lamparter case 32: 441e9f4d569SChristian Lamparter if (byte_be) { 442e9f4d569SChristian Lamparter gc->read_reg = bgpio_read32be; 443e9f4d569SChristian Lamparter gc->write_reg = bgpio_write32be; 444e9f4d569SChristian Lamparter } else { 445e9f4d569SChristian Lamparter gc->read_reg = bgpio_read32; 446e9f4d569SChristian Lamparter gc->write_reg = bgpio_write32; 447e9f4d569SChristian Lamparter } 448e9f4d569SChristian Lamparter break; 449e9f4d569SChristian Lamparter #if BITS_PER_LONG >= 64 450e9f4d569SChristian Lamparter case 64: 451e9f4d569SChristian Lamparter if (byte_be) { 452e9f4d569SChristian Lamparter dev_err(dev, 453e9f4d569SChristian Lamparter "64 bit big endian byte order unsupported\n"); 454e9f4d569SChristian Lamparter return -EINVAL; 455e9f4d569SChristian Lamparter } else { 456e9f4d569SChristian Lamparter gc->read_reg = bgpio_read64; 457e9f4d569SChristian Lamparter gc->write_reg = bgpio_write64; 458e9f4d569SChristian Lamparter } 459e9f4d569SChristian Lamparter break; 460e9f4d569SChristian Lamparter #endif /* BITS_PER_LONG >= 64 */ 461e9f4d569SChristian Lamparter default: 462e9f4d569SChristian Lamparter dev_err(dev, "unsupported data width %u bits\n", gc->bgpio_bits); 463e9f4d569SChristian Lamparter return -EINVAL; 464e9f4d569SChristian Lamparter } 465e9f4d569SChristian Lamparter 466e9f4d569SChristian Lamparter return 0; 467e9f4d569SChristian Lamparter } 468e9f4d569SChristian Lamparter 469e9f4d569SChristian Lamparter /* 470e9f4d569SChristian Lamparter * Create the device and allocate the resources. For setting GPIO's there are 471e9f4d569SChristian Lamparter * three supported configurations: 472e9f4d569SChristian Lamparter * 473e9f4d569SChristian Lamparter * - single input/output register resource (named "dat"). 474e9f4d569SChristian Lamparter * - set/clear pair (named "set" and "clr"). 475e9f4d569SChristian Lamparter * - single output register resource and single input resource ("set" and 476e9f4d569SChristian Lamparter * dat"). 477e9f4d569SChristian Lamparter * 478e9f4d569SChristian Lamparter * For the single output register, this drives a 1 by setting a bit and a zero 479e9f4d569SChristian Lamparter * by clearing a bit. For the set clr pair, this drives a 1 by setting a bit 480e9f4d569SChristian Lamparter * in the set register and clears it by setting a bit in the clear register. 481e9f4d569SChristian Lamparter * The configuration is detected by which resources are present. 482e9f4d569SChristian Lamparter * 483e9f4d569SChristian Lamparter * For setting the GPIO direction, there are three supported configurations: 484e9f4d569SChristian Lamparter * 485e9f4d569SChristian Lamparter * - simple bidirection GPIO that requires no configuration. 486e9f4d569SChristian Lamparter * - an output direction register (named "dirout") where a 1 bit 487e9f4d569SChristian Lamparter * indicates the GPIO is an output. 488e9f4d569SChristian Lamparter * - an input direction register (named "dirin") where a 1 bit indicates 489e9f4d569SChristian Lamparter * the GPIO is an input. 490e9f4d569SChristian Lamparter */ 491e9f4d569SChristian Lamparter static int bgpio_setup_io(struct gpio_chip *gc, 492e9f4d569SChristian Lamparter void __iomem *dat, 493e9f4d569SChristian Lamparter void __iomem *set, 494e9f4d569SChristian Lamparter void __iomem *clr, 495e9f4d569SChristian Lamparter unsigned long flags) 496e9f4d569SChristian Lamparter { 497e9f4d569SChristian Lamparter 498e9f4d569SChristian Lamparter gc->reg_dat = dat; 499e9f4d569SChristian Lamparter if (!gc->reg_dat) 500e9f4d569SChristian Lamparter return -EINVAL; 501e9f4d569SChristian Lamparter 502e9f4d569SChristian Lamparter if (set && clr) { 503e9f4d569SChristian Lamparter gc->reg_set = set; 504e9f4d569SChristian Lamparter gc->reg_clr = clr; 505e9f4d569SChristian Lamparter gc->set = bgpio_set_with_clear; 506e9f4d569SChristian Lamparter gc->set_multiple = bgpio_set_multiple_with_clear; 507e9f4d569SChristian Lamparter } else if (set && !clr) { 508e9f4d569SChristian Lamparter gc->reg_set = set; 509e9f4d569SChristian Lamparter gc->set = bgpio_set_set; 510e9f4d569SChristian Lamparter gc->set_multiple = bgpio_set_multiple_set; 511e9f4d569SChristian Lamparter } else if (flags & BGPIOF_NO_OUTPUT) { 512e9f4d569SChristian Lamparter gc->set = bgpio_set_none; 513e9f4d569SChristian Lamparter gc->set_multiple = NULL; 514e9f4d569SChristian Lamparter } else { 515e9f4d569SChristian Lamparter gc->set = bgpio_set; 516e9f4d569SChristian Lamparter gc->set_multiple = bgpio_set_multiple; 517e9f4d569SChristian Lamparter } 518e9f4d569SChristian Lamparter 519e9f4d569SChristian Lamparter if (!(flags & BGPIOF_UNREADABLE_REG_SET) && 52080057cb4SLinus Walleij (flags & BGPIOF_READ_OUTPUT_REG_SET)) { 521e9f4d569SChristian Lamparter gc->get = bgpio_get_set; 52280057cb4SLinus Walleij if (!gc->be_bits) 52380057cb4SLinus Walleij gc->get_multiple = bgpio_get_set_multiple; 52480057cb4SLinus Walleij /* 52580057cb4SLinus Walleij * We deliberately avoid assigning the ->get_multiple() call 52680057cb4SLinus Walleij * for big endian mirrored registers which are ALSO reflecting 52780057cb4SLinus Walleij * their value in the set register when used as output. It is 52880057cb4SLinus Walleij * simply too much complexity, let the GPIO core fall back to 52980057cb4SLinus Walleij * reading each line individually in that fringe case. 53080057cb4SLinus Walleij */ 53180057cb4SLinus Walleij } else { 532e9f4d569SChristian Lamparter gc->get = bgpio_get; 53380057cb4SLinus Walleij if (gc->be_bits) 53480057cb4SLinus Walleij gc->get_multiple = bgpio_get_multiple_be; 53580057cb4SLinus Walleij else 53680057cb4SLinus Walleij gc->get_multiple = bgpio_get_multiple; 53780057cb4SLinus Walleij } 538e9f4d569SChristian Lamparter 539e9f4d569SChristian Lamparter return 0; 540e9f4d569SChristian Lamparter } 541e9f4d569SChristian Lamparter 542e9f4d569SChristian Lamparter static int bgpio_setup_direction(struct gpio_chip *gc, 543e9f4d569SChristian Lamparter void __iomem *dirout, 544e9f4d569SChristian Lamparter void __iomem *dirin, 545e9f4d569SChristian Lamparter unsigned long flags) 546e9f4d569SChristian Lamparter { 547*f69e00bdSLinus Walleij if (dirout || dirin) { 548*f69e00bdSLinus Walleij gc->reg_dir_out = dirout; 549*f69e00bdSLinus Walleij gc->reg_dir_in = dirin; 550e9f4d569SChristian Lamparter gc->direction_output = bgpio_dir_out; 551e9f4d569SChristian Lamparter gc->direction_input = bgpio_dir_in; 552e9f4d569SChristian Lamparter gc->get_direction = bgpio_get_dir; 553*f69e00bdSLinus Walleij /* 554*f69e00bdSLinus Walleij * If only dirin is available, this means we need 555*f69e00bdSLinus Walleij * inverted semantics when handling get/set registers 556*f69e00bdSLinus Walleij * so detect this here. 557*f69e00bdSLinus Walleij */ 558*f69e00bdSLinus Walleij if (dirin && !dirout) 559d799a4deSLinus Walleij gc->bgpio_dir_inverted = true; 560e9f4d569SChristian Lamparter } else { 561e9f4d569SChristian Lamparter if (flags & BGPIOF_NO_OUTPUT) 562e9f4d569SChristian Lamparter gc->direction_output = bgpio_dir_out_err; 563e9f4d569SChristian Lamparter else 564e9f4d569SChristian Lamparter gc->direction_output = bgpio_simple_dir_out; 565e9f4d569SChristian Lamparter gc->direction_input = bgpio_simple_dir_in; 566e9f4d569SChristian Lamparter } 567e9f4d569SChristian Lamparter 568e9f4d569SChristian Lamparter return 0; 569e9f4d569SChristian Lamparter } 570e9f4d569SChristian Lamparter 571e9f4d569SChristian Lamparter static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin) 572e9f4d569SChristian Lamparter { 573e9f4d569SChristian Lamparter if (gpio_pin < chip->ngpio) 574e9f4d569SChristian Lamparter return 0; 575e9f4d569SChristian Lamparter 576e9f4d569SChristian Lamparter return -EINVAL; 577e9f4d569SChristian Lamparter } 578e9f4d569SChristian Lamparter 579d799a4deSLinus Walleij /** 580d799a4deSLinus Walleij * bgpio_init() - Initialize generic GPIO accessor functions 581d799a4deSLinus Walleij * @gc: the GPIO chip to set up 582d799a4deSLinus Walleij * @dev: the parent device of the new GPIO chip (compulsory) 583d799a4deSLinus Walleij * @sz: the size (width) of the MMIO registers in bytes, typically 1, 2 or 4 584d799a4deSLinus Walleij * @dat: MMIO address for the register to READ the value of the GPIO lines, it 585d799a4deSLinus Walleij * is expected that a 1 in the corresponding bit in this register means the 586d799a4deSLinus Walleij * line is asserted 587d799a4deSLinus Walleij * @set: MMIO address for the register to SET the value of the GPIO lines, it is 588d799a4deSLinus Walleij * expected that we write the line with 1 in this register to drive the GPIO line 589d799a4deSLinus Walleij * high. 590d799a4deSLinus Walleij * @clr: MMIO address for the register to CLEAR the value of the GPIO lines, it is 591d799a4deSLinus Walleij * expected that we write the line with 1 in this register to drive the GPIO line 592d799a4deSLinus Walleij * low. It is allowed to leave this address as NULL, in that case the SET register 593d799a4deSLinus Walleij * will be assumed to also clear the GPIO lines, by actively writing the line 594d799a4deSLinus Walleij * with 0. 595d799a4deSLinus Walleij * @dirout: MMIO address for the register to set the line as OUTPUT. It is assumed 596d799a4deSLinus Walleij * that setting a line to 1 in this register will turn that line into an 597d799a4deSLinus Walleij * output line. Conversely, setting the line to 0 will turn that line into 598*f69e00bdSLinus Walleij * an input. 599d799a4deSLinus Walleij * @dirin: MMIO address for the register to set this line as INPUT. It is assumed 600d799a4deSLinus Walleij * that setting a line to 1 in this register will turn that line into an 601d799a4deSLinus Walleij * input line. Conversely, setting the line to 0 will turn that line into 602*f69e00bdSLinus Walleij * an output. 603d799a4deSLinus Walleij * @flags: Different flags that will affect the behaviour of the device, such as 604d799a4deSLinus Walleij * endianness etc. 605d799a4deSLinus Walleij */ 606e9f4d569SChristian Lamparter int bgpio_init(struct gpio_chip *gc, struct device *dev, 607e9f4d569SChristian Lamparter unsigned long sz, void __iomem *dat, void __iomem *set, 608e9f4d569SChristian Lamparter void __iomem *clr, void __iomem *dirout, void __iomem *dirin, 609e9f4d569SChristian Lamparter unsigned long flags) 610e9f4d569SChristian Lamparter { 611e9f4d569SChristian Lamparter int ret; 612e9f4d569SChristian Lamparter 613e9f4d569SChristian Lamparter if (!is_power_of_2(sz)) 614e9f4d569SChristian Lamparter return -EINVAL; 615e9f4d569SChristian Lamparter 616e9f4d569SChristian Lamparter gc->bgpio_bits = sz * 8; 617e9f4d569SChristian Lamparter if (gc->bgpio_bits > BITS_PER_LONG) 618e9f4d569SChristian Lamparter return -EINVAL; 619e9f4d569SChristian Lamparter 620e9f4d569SChristian Lamparter spin_lock_init(&gc->bgpio_lock); 621e9f4d569SChristian Lamparter gc->parent = dev; 622e9f4d569SChristian Lamparter gc->label = dev_name(dev); 623e9f4d569SChristian Lamparter gc->base = -1; 624e9f4d569SChristian Lamparter gc->ngpio = gc->bgpio_bits; 625e9f4d569SChristian Lamparter gc->request = bgpio_request; 62680057cb4SLinus Walleij gc->be_bits = !!(flags & BGPIOF_BIG_ENDIAN); 627e9f4d569SChristian Lamparter 628e9f4d569SChristian Lamparter ret = bgpio_setup_io(gc, dat, set, clr, flags); 629e9f4d569SChristian Lamparter if (ret) 630e9f4d569SChristian Lamparter return ret; 631e9f4d569SChristian Lamparter 63224efd94bSLinus Walleij ret = bgpio_setup_accessors(dev, gc, flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER); 633e9f4d569SChristian Lamparter if (ret) 634e9f4d569SChristian Lamparter return ret; 635e9f4d569SChristian Lamparter 636e9f4d569SChristian Lamparter ret = bgpio_setup_direction(gc, dirout, dirin, flags); 637e9f4d569SChristian Lamparter if (ret) 638e9f4d569SChristian Lamparter return ret; 639e9f4d569SChristian Lamparter 640e9f4d569SChristian Lamparter gc->bgpio_data = gc->read_reg(gc->reg_dat); 641e9f4d569SChristian Lamparter if (gc->set == bgpio_set_set && 642e9f4d569SChristian Lamparter !(flags & BGPIOF_UNREADABLE_REG_SET)) 643e9f4d569SChristian Lamparter gc->bgpio_data = gc->read_reg(gc->reg_set); 644*f69e00bdSLinus Walleij 645*f69e00bdSLinus Walleij if (flags & BGPIOF_UNREADABLE_REG_DIR) 646*f69e00bdSLinus Walleij gc->bgpio_dir_unreadable = true; 647*f69e00bdSLinus Walleij 648*f69e00bdSLinus Walleij /* 649*f69e00bdSLinus Walleij * Inspect hardware to find initial direction setting. 650*f69e00bdSLinus Walleij */ 651*f69e00bdSLinus Walleij if ((gc->reg_dir_out || gc->reg_dir_in) && 652*f69e00bdSLinus Walleij !(flags & BGPIOF_UNREADABLE_REG_DIR)) { 653*f69e00bdSLinus Walleij if (gc->reg_dir_out) 654*f69e00bdSLinus Walleij gc->bgpio_dir = gc->read_reg(gc->reg_dir_out); 655*f69e00bdSLinus Walleij else if (gc->reg_dir_in) 656*f69e00bdSLinus Walleij gc->bgpio_dir = ~gc->read_reg(gc->reg_dir_in); 657*f69e00bdSLinus Walleij /* 658*f69e00bdSLinus Walleij * If we have two direction registers, synchronise 659*f69e00bdSLinus Walleij * input setting to output setting, the library 660*f69e00bdSLinus Walleij * can not handle a line being input and output at 661*f69e00bdSLinus Walleij * the same time. 662*f69e00bdSLinus Walleij */ 663*f69e00bdSLinus Walleij if (gc->reg_dir_out && gc->reg_dir_in) 664*f69e00bdSLinus Walleij gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir); 665*f69e00bdSLinus Walleij } 666e9f4d569SChristian Lamparter 667e9f4d569SChristian Lamparter return ret; 668e9f4d569SChristian Lamparter } 669e9f4d569SChristian Lamparter EXPORT_SYMBOL_GPL(bgpio_init); 670e9f4d569SChristian Lamparter 671e9f4d569SChristian Lamparter #if IS_ENABLED(CONFIG_GPIO_GENERIC_PLATFORM) 672e9f4d569SChristian Lamparter 673e9f4d569SChristian Lamparter static void __iomem *bgpio_map(struct platform_device *pdev, 674e9f4d569SChristian Lamparter const char *name, 675e9f4d569SChristian Lamparter resource_size_t sane_sz) 676e9f4d569SChristian Lamparter { 677e9f4d569SChristian Lamparter struct resource *r; 678e9f4d569SChristian Lamparter resource_size_t sz; 679e9f4d569SChristian Lamparter 680e9f4d569SChristian Lamparter r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); 681e9f4d569SChristian Lamparter if (!r) 682e9f4d569SChristian Lamparter return NULL; 683e9f4d569SChristian Lamparter 684e9f4d569SChristian Lamparter sz = resource_size(r); 685e9f4d569SChristian Lamparter if (sz != sane_sz) 686e9f4d569SChristian Lamparter return IOMEM_ERR_PTR(-EINVAL); 687e9f4d569SChristian Lamparter 688e9f4d569SChristian Lamparter return devm_ioremap_resource(&pdev->dev, r); 689e9f4d569SChristian Lamparter } 690e9f4d569SChristian Lamparter 691e698613aSÁlvaro Fernández Rojas #ifdef CONFIG_OF 692e698613aSÁlvaro Fernández Rojas static const struct of_device_id bgpio_of_match[] = { 69305cc995fSChristian Lamparter { .compatible = "brcm,bcm6345-gpio" }, 694c0d30ecfSChristian Lamparter { .compatible = "wd,mbl-gpio" }, 695b8c90199SNathan Sullivan { .compatible = "ni,169445-nand-gpio" }, 696e698613aSÁlvaro Fernández Rojas { } 697e698613aSÁlvaro Fernández Rojas }; 698e698613aSÁlvaro Fernández Rojas MODULE_DEVICE_TABLE(of, bgpio_of_match); 699e698613aSÁlvaro Fernández Rojas 700e698613aSÁlvaro Fernández Rojas static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev, 701e698613aSÁlvaro Fernández Rojas unsigned long *flags) 702e698613aSÁlvaro Fernández Rojas { 703e698613aSÁlvaro Fernández Rojas struct bgpio_pdata *pdata; 704e698613aSÁlvaro Fernández Rojas 705e698613aSÁlvaro Fernández Rojas if (!of_match_device(bgpio_of_match, &pdev->dev)) 706e698613aSÁlvaro Fernández Rojas return NULL; 707e698613aSÁlvaro Fernández Rojas 708e698613aSÁlvaro Fernández Rojas pdata = devm_kzalloc(&pdev->dev, sizeof(struct bgpio_pdata), 709e698613aSÁlvaro Fernández Rojas GFP_KERNEL); 710e698613aSÁlvaro Fernández Rojas if (!pdata) 711e698613aSÁlvaro Fernández Rojas return ERR_PTR(-ENOMEM); 712e698613aSÁlvaro Fernández Rojas 713e698613aSÁlvaro Fernández Rojas pdata->base = -1; 714e698613aSÁlvaro Fernández Rojas 71505cc995fSChristian Lamparter if (of_device_is_big_endian(pdev->dev.of_node)) 71605cc995fSChristian Lamparter *flags |= BGPIOF_BIG_ENDIAN_BYTE_ORDER; 71705cc995fSChristian Lamparter 718c0d30ecfSChristian Lamparter if (of_property_read_bool(pdev->dev.of_node, "no-output")) 719c0d30ecfSChristian Lamparter *flags |= BGPIOF_NO_OUTPUT; 720c0d30ecfSChristian Lamparter 721e698613aSÁlvaro Fernández Rojas return pdata; 722e698613aSÁlvaro Fernández Rojas } 723e698613aSÁlvaro Fernández Rojas #else 724e698613aSÁlvaro Fernández Rojas static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev, 725e698613aSÁlvaro Fernández Rojas unsigned long *flags) 726e698613aSÁlvaro Fernández Rojas { 727e698613aSÁlvaro Fernández Rojas return NULL; 728e698613aSÁlvaro Fernández Rojas } 729e698613aSÁlvaro Fernández Rojas #endif /* CONFIG_OF */ 730e698613aSÁlvaro Fernández Rojas 731e9f4d569SChristian Lamparter static int bgpio_pdev_probe(struct platform_device *pdev) 732e9f4d569SChristian Lamparter { 733e9f4d569SChristian Lamparter struct device *dev = &pdev->dev; 734e9f4d569SChristian Lamparter struct resource *r; 735e9f4d569SChristian Lamparter void __iomem *dat; 736e9f4d569SChristian Lamparter void __iomem *set; 737e9f4d569SChristian Lamparter void __iomem *clr; 738e9f4d569SChristian Lamparter void __iomem *dirout; 739e9f4d569SChristian Lamparter void __iomem *dirin; 740e9f4d569SChristian Lamparter unsigned long sz; 741e698613aSÁlvaro Fernández Rojas unsigned long flags = 0; 742e9f4d569SChristian Lamparter int err; 743e9f4d569SChristian Lamparter struct gpio_chip *gc; 744e698613aSÁlvaro Fernández Rojas struct bgpio_pdata *pdata; 745e698613aSÁlvaro Fernández Rojas 746e698613aSÁlvaro Fernández Rojas pdata = bgpio_parse_dt(pdev, &flags); 747e698613aSÁlvaro Fernández Rojas if (IS_ERR(pdata)) 748e698613aSÁlvaro Fernández Rojas return PTR_ERR(pdata); 749e698613aSÁlvaro Fernández Rojas 750e698613aSÁlvaro Fernández Rojas if (!pdata) { 751e698613aSÁlvaro Fernández Rojas pdata = dev_get_platdata(dev); 752e698613aSÁlvaro Fernández Rojas flags = pdev->id_entry->driver_data; 753e698613aSÁlvaro Fernández Rojas } 754e9f4d569SChristian Lamparter 755e9f4d569SChristian Lamparter r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); 756e9f4d569SChristian Lamparter if (!r) 757e9f4d569SChristian Lamparter return -EINVAL; 758e9f4d569SChristian Lamparter 759e9f4d569SChristian Lamparter sz = resource_size(r); 760e9f4d569SChristian Lamparter 761e9f4d569SChristian Lamparter dat = bgpio_map(pdev, "dat", sz); 762e9f4d569SChristian Lamparter if (IS_ERR(dat)) 763e9f4d569SChristian Lamparter return PTR_ERR(dat); 764e9f4d569SChristian Lamparter 765e9f4d569SChristian Lamparter set = bgpio_map(pdev, "set", sz); 766e9f4d569SChristian Lamparter if (IS_ERR(set)) 767e9f4d569SChristian Lamparter return PTR_ERR(set); 768e9f4d569SChristian Lamparter 769e9f4d569SChristian Lamparter clr = bgpio_map(pdev, "clr", sz); 770e9f4d569SChristian Lamparter if (IS_ERR(clr)) 771e9f4d569SChristian Lamparter return PTR_ERR(clr); 772e9f4d569SChristian Lamparter 773e9f4d569SChristian Lamparter dirout = bgpio_map(pdev, "dirout", sz); 774e9f4d569SChristian Lamparter if (IS_ERR(dirout)) 775e9f4d569SChristian Lamparter return PTR_ERR(dirout); 776e9f4d569SChristian Lamparter 777e9f4d569SChristian Lamparter dirin = bgpio_map(pdev, "dirin", sz); 778e9f4d569SChristian Lamparter if (IS_ERR(dirin)) 779e9f4d569SChristian Lamparter return PTR_ERR(dirin); 780e9f4d569SChristian Lamparter 781e9f4d569SChristian Lamparter gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL); 782e9f4d569SChristian Lamparter if (!gc) 783e9f4d569SChristian Lamparter return -ENOMEM; 784e9f4d569SChristian Lamparter 785e9f4d569SChristian Lamparter err = bgpio_init(gc, dev, sz, dat, set, clr, dirout, dirin, flags); 786e9f4d569SChristian Lamparter if (err) 787e9f4d569SChristian Lamparter return err; 788e9f4d569SChristian Lamparter 789e9f4d569SChristian Lamparter if (pdata) { 790e9f4d569SChristian Lamparter if (pdata->label) 791e9f4d569SChristian Lamparter gc->label = pdata->label; 792e9f4d569SChristian Lamparter gc->base = pdata->base; 793e9f4d569SChristian Lamparter if (pdata->ngpio > 0) 794e9f4d569SChristian Lamparter gc->ngpio = pdata->ngpio; 795e9f4d569SChristian Lamparter } 796e9f4d569SChristian Lamparter 797e9f4d569SChristian Lamparter platform_set_drvdata(pdev, gc); 798e9f4d569SChristian Lamparter 799e9f4d569SChristian Lamparter return devm_gpiochip_add_data(&pdev->dev, gc, NULL); 800e9f4d569SChristian Lamparter } 801e9f4d569SChristian Lamparter 802e9f4d569SChristian Lamparter static const struct platform_device_id bgpio_id_table[] = { 803e9f4d569SChristian Lamparter { 804e9f4d569SChristian Lamparter .name = "basic-mmio-gpio", 805e9f4d569SChristian Lamparter .driver_data = 0, 806e9f4d569SChristian Lamparter }, { 807e9f4d569SChristian Lamparter .name = "basic-mmio-gpio-be", 808e9f4d569SChristian Lamparter .driver_data = BGPIOF_BIG_ENDIAN, 809e9f4d569SChristian Lamparter }, 810e9f4d569SChristian Lamparter { } 811e9f4d569SChristian Lamparter }; 812e9f4d569SChristian Lamparter MODULE_DEVICE_TABLE(platform, bgpio_id_table); 813e9f4d569SChristian Lamparter 814e9f4d569SChristian Lamparter static struct platform_driver bgpio_driver = { 815e9f4d569SChristian Lamparter .driver = { 816e9f4d569SChristian Lamparter .name = "basic-mmio-gpio", 817e698613aSÁlvaro Fernández Rojas .of_match_table = of_match_ptr(bgpio_of_match), 818e9f4d569SChristian Lamparter }, 819e9f4d569SChristian Lamparter .id_table = bgpio_id_table, 820e9f4d569SChristian Lamparter .probe = bgpio_pdev_probe, 821e9f4d569SChristian Lamparter }; 822e9f4d569SChristian Lamparter 823e9f4d569SChristian Lamparter module_platform_driver(bgpio_driver); 824e9f4d569SChristian Lamparter 825e9f4d569SChristian Lamparter #endif /* CONFIG_GPIO_GENERIC_PLATFORM */ 826e9f4d569SChristian Lamparter 827e9f4d569SChristian Lamparter MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers"); 828e9f4d569SChristian Lamparter MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>"); 829e9f4d569SChristian Lamparter MODULE_LICENSE("GPL"); 830