1*e9f4d569SChristian Lamparter /* 2*e9f4d569SChristian Lamparter * Generic driver for memory-mapped GPIO controllers. 3*e9f4d569SChristian Lamparter * 4*e9f4d569SChristian Lamparter * Copyright 2008 MontaVista Software, Inc. 5*e9f4d569SChristian Lamparter * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com> 6*e9f4d569SChristian Lamparter * 7*e9f4d569SChristian Lamparter * This program is free software; you can redistribute it and/or modify it 8*e9f4d569SChristian Lamparter * under the terms of the GNU General Public License as published by the 9*e9f4d569SChristian Lamparter * Free Software Foundation; either version 2 of the License, or (at your 10*e9f4d569SChristian Lamparter * option) any later version. 11*e9f4d569SChristian Lamparter * 12*e9f4d569SChristian Lamparter * ....``.```~~~~````.`.`.`.`.```````'',,,.........`````......`....... 13*e9f4d569SChristian Lamparter * ...`` ```````.. 14*e9f4d569SChristian Lamparter * ..The simplest form of a GPIO controller that the driver supports is`` 15*e9f4d569SChristian Lamparter * `.just a single "data" register, where GPIO state can be read and/or ` 16*e9f4d569SChristian Lamparter * `,..written. ,,..``~~~~ .....``.`.`.~~.```.`.........``````.``````` 17*e9f4d569SChristian Lamparter * ````````` 18*e9f4d569SChristian Lamparter ___ 19*e9f4d569SChristian Lamparter _/~~|___/~| . ```~~~~~~ ___/___\___ ,~.`.`.`.`````.~~...,,,,... 20*e9f4d569SChristian Lamparter __________|~$@~~~ %~ /o*o*o*o*o*o\ .. Implementing such a GPIO . 21*e9f4d569SChristian Lamparter o ` ~~~~\___/~~~~ ` controller in FPGA is ,.` 22*e9f4d569SChristian Lamparter `....trivial..'~`.```.``` 23*e9f4d569SChristian Lamparter * ``````` 24*e9f4d569SChristian Lamparter * .```````~~~~`..`.``.``. 25*e9f4d569SChristian Lamparter * . The driver supports `... ,..```.`~~~```````````````....````.``,, 26*e9f4d569SChristian Lamparter * . big-endian notation, just`. .. A bit more sophisticated controllers , 27*e9f4d569SChristian Lamparter * . register the device with -be`. .with a pair of set/clear-bit registers , 28*e9f4d569SChristian Lamparter * `.. suffix. ```~~`````....`.` . affecting the data register and the .` 29*e9f4d569SChristian Lamparter * ``.`.``...``` ```.. output pins are also supported.` 30*e9f4d569SChristian Lamparter * ^^ `````.`````````.,``~``~``~~`````` 31*e9f4d569SChristian Lamparter * . ^^ 32*e9f4d569SChristian Lamparter * ,..`.`.`...````````````......`.`.`.`.`.`..`.`.`.. 33*e9f4d569SChristian Lamparter * .. The expectation is that in at least some cases . ,-~~~-, 34*e9f4d569SChristian Lamparter * .this will be used with roll-your-own ASIC/FPGA .` \ / 35*e9f4d569SChristian Lamparter * .logic in Verilog or VHDL. ~~~`````````..`````~~` \ / 36*e9f4d569SChristian Lamparter * ..````````......``````````` \o_ 37*e9f4d569SChristian Lamparter * | 38*e9f4d569SChristian Lamparter * ^^ / \ 39*e9f4d569SChristian Lamparter * 40*e9f4d569SChristian Lamparter * ...`````~~`.....``.`..........``````.`.``.```........``. 41*e9f4d569SChristian Lamparter * ` 8, 16, 32 and 64 bits registers are supported, and``. 42*e9f4d569SChristian Lamparter * . the number of GPIOs is determined by the width of ~ 43*e9f4d569SChristian Lamparter * .. the registers. ,............```.`.`..`.`.~~~.`.`.`~ 44*e9f4d569SChristian Lamparter * `.......````.``` 45*e9f4d569SChristian Lamparter */ 46*e9f4d569SChristian Lamparter 47*e9f4d569SChristian Lamparter #include <linux/init.h> 48*e9f4d569SChristian Lamparter #include <linux/err.h> 49*e9f4d569SChristian Lamparter #include <linux/bug.h> 50*e9f4d569SChristian Lamparter #include <linux/kernel.h> 51*e9f4d569SChristian Lamparter #include <linux/module.h> 52*e9f4d569SChristian Lamparter #include <linux/spinlock.h> 53*e9f4d569SChristian Lamparter #include <linux/compiler.h> 54*e9f4d569SChristian Lamparter #include <linux/types.h> 55*e9f4d569SChristian Lamparter #include <linux/errno.h> 56*e9f4d569SChristian Lamparter #include <linux/log2.h> 57*e9f4d569SChristian Lamparter #include <linux/ioport.h> 58*e9f4d569SChristian Lamparter #include <linux/io.h> 59*e9f4d569SChristian Lamparter #include <linux/gpio/driver.h> 60*e9f4d569SChristian Lamparter #include <linux/slab.h> 61*e9f4d569SChristian Lamparter #include <linux/bitops.h> 62*e9f4d569SChristian Lamparter #include <linux/platform_device.h> 63*e9f4d569SChristian Lamparter #include <linux/mod_devicetable.h> 64*e9f4d569SChristian Lamparter 65*e9f4d569SChristian Lamparter static void bgpio_write8(void __iomem *reg, unsigned long data) 66*e9f4d569SChristian Lamparter { 67*e9f4d569SChristian Lamparter writeb(data, reg); 68*e9f4d569SChristian Lamparter } 69*e9f4d569SChristian Lamparter 70*e9f4d569SChristian Lamparter static unsigned long bgpio_read8(void __iomem *reg) 71*e9f4d569SChristian Lamparter { 72*e9f4d569SChristian Lamparter return readb(reg); 73*e9f4d569SChristian Lamparter } 74*e9f4d569SChristian Lamparter 75*e9f4d569SChristian Lamparter static void bgpio_write16(void __iomem *reg, unsigned long data) 76*e9f4d569SChristian Lamparter { 77*e9f4d569SChristian Lamparter writew(data, reg); 78*e9f4d569SChristian Lamparter } 79*e9f4d569SChristian Lamparter 80*e9f4d569SChristian Lamparter static unsigned long bgpio_read16(void __iomem *reg) 81*e9f4d569SChristian Lamparter { 82*e9f4d569SChristian Lamparter return readw(reg); 83*e9f4d569SChristian Lamparter } 84*e9f4d569SChristian Lamparter 85*e9f4d569SChristian Lamparter static void bgpio_write32(void __iomem *reg, unsigned long data) 86*e9f4d569SChristian Lamparter { 87*e9f4d569SChristian Lamparter writel(data, reg); 88*e9f4d569SChristian Lamparter } 89*e9f4d569SChristian Lamparter 90*e9f4d569SChristian Lamparter static unsigned long bgpio_read32(void __iomem *reg) 91*e9f4d569SChristian Lamparter { 92*e9f4d569SChristian Lamparter return readl(reg); 93*e9f4d569SChristian Lamparter } 94*e9f4d569SChristian Lamparter 95*e9f4d569SChristian Lamparter #if BITS_PER_LONG >= 64 96*e9f4d569SChristian Lamparter static void bgpio_write64(void __iomem *reg, unsigned long data) 97*e9f4d569SChristian Lamparter { 98*e9f4d569SChristian Lamparter writeq(data, reg); 99*e9f4d569SChristian Lamparter } 100*e9f4d569SChristian Lamparter 101*e9f4d569SChristian Lamparter static unsigned long bgpio_read64(void __iomem *reg) 102*e9f4d569SChristian Lamparter { 103*e9f4d569SChristian Lamparter return readq(reg); 104*e9f4d569SChristian Lamparter } 105*e9f4d569SChristian Lamparter #endif /* BITS_PER_LONG >= 64 */ 106*e9f4d569SChristian Lamparter 107*e9f4d569SChristian Lamparter static void bgpio_write16be(void __iomem *reg, unsigned long data) 108*e9f4d569SChristian Lamparter { 109*e9f4d569SChristian Lamparter iowrite16be(data, reg); 110*e9f4d569SChristian Lamparter } 111*e9f4d569SChristian Lamparter 112*e9f4d569SChristian Lamparter static unsigned long bgpio_read16be(void __iomem *reg) 113*e9f4d569SChristian Lamparter { 114*e9f4d569SChristian Lamparter return ioread16be(reg); 115*e9f4d569SChristian Lamparter } 116*e9f4d569SChristian Lamparter 117*e9f4d569SChristian Lamparter static void bgpio_write32be(void __iomem *reg, unsigned long data) 118*e9f4d569SChristian Lamparter { 119*e9f4d569SChristian Lamparter iowrite32be(data, reg); 120*e9f4d569SChristian Lamparter } 121*e9f4d569SChristian Lamparter 122*e9f4d569SChristian Lamparter static unsigned long bgpio_read32be(void __iomem *reg) 123*e9f4d569SChristian Lamparter { 124*e9f4d569SChristian Lamparter return ioread32be(reg); 125*e9f4d569SChristian Lamparter } 126*e9f4d569SChristian Lamparter 127*e9f4d569SChristian Lamparter static unsigned long bgpio_pin2mask(struct gpio_chip *gc, unsigned int pin) 128*e9f4d569SChristian Lamparter { 129*e9f4d569SChristian Lamparter return BIT(pin); 130*e9f4d569SChristian Lamparter } 131*e9f4d569SChristian Lamparter 132*e9f4d569SChristian Lamparter static unsigned long bgpio_pin2mask_be(struct gpio_chip *gc, 133*e9f4d569SChristian Lamparter unsigned int pin) 134*e9f4d569SChristian Lamparter { 135*e9f4d569SChristian Lamparter return BIT(gc->bgpio_bits - 1 - pin); 136*e9f4d569SChristian Lamparter } 137*e9f4d569SChristian Lamparter 138*e9f4d569SChristian Lamparter static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio) 139*e9f4d569SChristian Lamparter { 140*e9f4d569SChristian Lamparter unsigned long pinmask = gc->pin2mask(gc, gpio); 141*e9f4d569SChristian Lamparter 142*e9f4d569SChristian Lamparter if (gc->bgpio_dir & pinmask) 143*e9f4d569SChristian Lamparter return !!(gc->read_reg(gc->reg_set) & pinmask); 144*e9f4d569SChristian Lamparter else 145*e9f4d569SChristian Lamparter return !!(gc->read_reg(gc->reg_dat) & pinmask); 146*e9f4d569SChristian Lamparter } 147*e9f4d569SChristian Lamparter 148*e9f4d569SChristian Lamparter static int bgpio_get(struct gpio_chip *gc, unsigned int gpio) 149*e9f4d569SChristian Lamparter { 150*e9f4d569SChristian Lamparter return !!(gc->read_reg(gc->reg_dat) & gc->pin2mask(gc, gpio)); 151*e9f4d569SChristian Lamparter } 152*e9f4d569SChristian Lamparter 153*e9f4d569SChristian Lamparter static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val) 154*e9f4d569SChristian Lamparter { 155*e9f4d569SChristian Lamparter } 156*e9f4d569SChristian Lamparter 157*e9f4d569SChristian Lamparter static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) 158*e9f4d569SChristian Lamparter { 159*e9f4d569SChristian Lamparter unsigned long mask = gc->pin2mask(gc, gpio); 160*e9f4d569SChristian Lamparter unsigned long flags; 161*e9f4d569SChristian Lamparter 162*e9f4d569SChristian Lamparter spin_lock_irqsave(&gc->bgpio_lock, flags); 163*e9f4d569SChristian Lamparter 164*e9f4d569SChristian Lamparter if (val) 165*e9f4d569SChristian Lamparter gc->bgpio_data |= mask; 166*e9f4d569SChristian Lamparter else 167*e9f4d569SChristian Lamparter gc->bgpio_data &= ~mask; 168*e9f4d569SChristian Lamparter 169*e9f4d569SChristian Lamparter gc->write_reg(gc->reg_dat, gc->bgpio_data); 170*e9f4d569SChristian Lamparter 171*e9f4d569SChristian Lamparter spin_unlock_irqrestore(&gc->bgpio_lock, flags); 172*e9f4d569SChristian Lamparter } 173*e9f4d569SChristian Lamparter 174*e9f4d569SChristian Lamparter static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio, 175*e9f4d569SChristian Lamparter int val) 176*e9f4d569SChristian Lamparter { 177*e9f4d569SChristian Lamparter unsigned long mask = gc->pin2mask(gc, gpio); 178*e9f4d569SChristian Lamparter 179*e9f4d569SChristian Lamparter if (val) 180*e9f4d569SChristian Lamparter gc->write_reg(gc->reg_set, mask); 181*e9f4d569SChristian Lamparter else 182*e9f4d569SChristian Lamparter gc->write_reg(gc->reg_clr, mask); 183*e9f4d569SChristian Lamparter } 184*e9f4d569SChristian Lamparter 185*e9f4d569SChristian Lamparter static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) 186*e9f4d569SChristian Lamparter { 187*e9f4d569SChristian Lamparter unsigned long mask = gc->pin2mask(gc, gpio); 188*e9f4d569SChristian Lamparter unsigned long flags; 189*e9f4d569SChristian Lamparter 190*e9f4d569SChristian Lamparter spin_lock_irqsave(&gc->bgpio_lock, flags); 191*e9f4d569SChristian Lamparter 192*e9f4d569SChristian Lamparter if (val) 193*e9f4d569SChristian Lamparter gc->bgpio_data |= mask; 194*e9f4d569SChristian Lamparter else 195*e9f4d569SChristian Lamparter gc->bgpio_data &= ~mask; 196*e9f4d569SChristian Lamparter 197*e9f4d569SChristian Lamparter gc->write_reg(gc->reg_set, gc->bgpio_data); 198*e9f4d569SChristian Lamparter 199*e9f4d569SChristian Lamparter spin_unlock_irqrestore(&gc->bgpio_lock, flags); 200*e9f4d569SChristian Lamparter } 201*e9f4d569SChristian Lamparter 202*e9f4d569SChristian Lamparter static void bgpio_multiple_get_masks(struct gpio_chip *gc, 203*e9f4d569SChristian Lamparter unsigned long *mask, unsigned long *bits, 204*e9f4d569SChristian Lamparter unsigned long *set_mask, 205*e9f4d569SChristian Lamparter unsigned long *clear_mask) 206*e9f4d569SChristian Lamparter { 207*e9f4d569SChristian Lamparter int i; 208*e9f4d569SChristian Lamparter 209*e9f4d569SChristian Lamparter *set_mask = 0; 210*e9f4d569SChristian Lamparter *clear_mask = 0; 211*e9f4d569SChristian Lamparter 212*e9f4d569SChristian Lamparter for (i = 0; i < gc->bgpio_bits; i++) { 213*e9f4d569SChristian Lamparter if (*mask == 0) 214*e9f4d569SChristian Lamparter break; 215*e9f4d569SChristian Lamparter if (__test_and_clear_bit(i, mask)) { 216*e9f4d569SChristian Lamparter if (test_bit(i, bits)) 217*e9f4d569SChristian Lamparter *set_mask |= gc->pin2mask(gc, i); 218*e9f4d569SChristian Lamparter else 219*e9f4d569SChristian Lamparter *clear_mask |= gc->pin2mask(gc, i); 220*e9f4d569SChristian Lamparter } 221*e9f4d569SChristian Lamparter } 222*e9f4d569SChristian Lamparter } 223*e9f4d569SChristian Lamparter 224*e9f4d569SChristian Lamparter static void bgpio_set_multiple_single_reg(struct gpio_chip *gc, 225*e9f4d569SChristian Lamparter unsigned long *mask, 226*e9f4d569SChristian Lamparter unsigned long *bits, 227*e9f4d569SChristian Lamparter void __iomem *reg) 228*e9f4d569SChristian Lamparter { 229*e9f4d569SChristian Lamparter unsigned long flags; 230*e9f4d569SChristian Lamparter unsigned long set_mask, clear_mask; 231*e9f4d569SChristian Lamparter 232*e9f4d569SChristian Lamparter spin_lock_irqsave(&gc->bgpio_lock, flags); 233*e9f4d569SChristian Lamparter 234*e9f4d569SChristian Lamparter bgpio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask); 235*e9f4d569SChristian Lamparter 236*e9f4d569SChristian Lamparter gc->bgpio_data |= set_mask; 237*e9f4d569SChristian Lamparter gc->bgpio_data &= ~clear_mask; 238*e9f4d569SChristian Lamparter 239*e9f4d569SChristian Lamparter gc->write_reg(reg, gc->bgpio_data); 240*e9f4d569SChristian Lamparter 241*e9f4d569SChristian Lamparter spin_unlock_irqrestore(&gc->bgpio_lock, flags); 242*e9f4d569SChristian Lamparter } 243*e9f4d569SChristian Lamparter 244*e9f4d569SChristian Lamparter static void bgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, 245*e9f4d569SChristian Lamparter unsigned long *bits) 246*e9f4d569SChristian Lamparter { 247*e9f4d569SChristian Lamparter bgpio_set_multiple_single_reg(gc, mask, bits, gc->reg_dat); 248*e9f4d569SChristian Lamparter } 249*e9f4d569SChristian Lamparter 250*e9f4d569SChristian Lamparter static void bgpio_set_multiple_set(struct gpio_chip *gc, unsigned long *mask, 251*e9f4d569SChristian Lamparter unsigned long *bits) 252*e9f4d569SChristian Lamparter { 253*e9f4d569SChristian Lamparter bgpio_set_multiple_single_reg(gc, mask, bits, gc->reg_set); 254*e9f4d569SChristian Lamparter } 255*e9f4d569SChristian Lamparter 256*e9f4d569SChristian Lamparter static void bgpio_set_multiple_with_clear(struct gpio_chip *gc, 257*e9f4d569SChristian Lamparter unsigned long *mask, 258*e9f4d569SChristian Lamparter unsigned long *bits) 259*e9f4d569SChristian Lamparter { 260*e9f4d569SChristian Lamparter unsigned long set_mask, clear_mask; 261*e9f4d569SChristian Lamparter 262*e9f4d569SChristian Lamparter bgpio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask); 263*e9f4d569SChristian Lamparter 264*e9f4d569SChristian Lamparter if (set_mask) 265*e9f4d569SChristian Lamparter gc->write_reg(gc->reg_set, set_mask); 266*e9f4d569SChristian Lamparter if (clear_mask) 267*e9f4d569SChristian Lamparter gc->write_reg(gc->reg_clr, clear_mask); 268*e9f4d569SChristian Lamparter } 269*e9f4d569SChristian Lamparter 270*e9f4d569SChristian Lamparter static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio) 271*e9f4d569SChristian Lamparter { 272*e9f4d569SChristian Lamparter return 0; 273*e9f4d569SChristian Lamparter } 274*e9f4d569SChristian Lamparter 275*e9f4d569SChristian Lamparter static int bgpio_dir_out_err(struct gpio_chip *gc, unsigned int gpio, 276*e9f4d569SChristian Lamparter int val) 277*e9f4d569SChristian Lamparter { 278*e9f4d569SChristian Lamparter return -EINVAL; 279*e9f4d569SChristian Lamparter } 280*e9f4d569SChristian Lamparter 281*e9f4d569SChristian Lamparter static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio, 282*e9f4d569SChristian Lamparter int val) 283*e9f4d569SChristian Lamparter { 284*e9f4d569SChristian Lamparter gc->set(gc, gpio, val); 285*e9f4d569SChristian Lamparter 286*e9f4d569SChristian Lamparter return 0; 287*e9f4d569SChristian Lamparter } 288*e9f4d569SChristian Lamparter 289*e9f4d569SChristian Lamparter static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) 290*e9f4d569SChristian Lamparter { 291*e9f4d569SChristian Lamparter unsigned long flags; 292*e9f4d569SChristian Lamparter 293*e9f4d569SChristian Lamparter spin_lock_irqsave(&gc->bgpio_lock, flags); 294*e9f4d569SChristian Lamparter 295*e9f4d569SChristian Lamparter gc->bgpio_dir &= ~gc->pin2mask(gc, gpio); 296*e9f4d569SChristian Lamparter gc->write_reg(gc->reg_dir, gc->bgpio_dir); 297*e9f4d569SChristian Lamparter 298*e9f4d569SChristian Lamparter spin_unlock_irqrestore(&gc->bgpio_lock, flags); 299*e9f4d569SChristian Lamparter 300*e9f4d569SChristian Lamparter return 0; 301*e9f4d569SChristian Lamparter } 302*e9f4d569SChristian Lamparter 303*e9f4d569SChristian Lamparter static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio) 304*e9f4d569SChristian Lamparter { 305*e9f4d569SChristian Lamparter /* Return 0 if output, 1 of input */ 306*e9f4d569SChristian Lamparter return !(gc->read_reg(gc->reg_dir) & gc->pin2mask(gc, gpio)); 307*e9f4d569SChristian Lamparter } 308*e9f4d569SChristian Lamparter 309*e9f4d569SChristian Lamparter static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) 310*e9f4d569SChristian Lamparter { 311*e9f4d569SChristian Lamparter unsigned long flags; 312*e9f4d569SChristian Lamparter 313*e9f4d569SChristian Lamparter gc->set(gc, gpio, val); 314*e9f4d569SChristian Lamparter 315*e9f4d569SChristian Lamparter spin_lock_irqsave(&gc->bgpio_lock, flags); 316*e9f4d569SChristian Lamparter 317*e9f4d569SChristian Lamparter gc->bgpio_dir |= gc->pin2mask(gc, gpio); 318*e9f4d569SChristian Lamparter gc->write_reg(gc->reg_dir, gc->bgpio_dir); 319*e9f4d569SChristian Lamparter 320*e9f4d569SChristian Lamparter spin_unlock_irqrestore(&gc->bgpio_lock, flags); 321*e9f4d569SChristian Lamparter 322*e9f4d569SChristian Lamparter return 0; 323*e9f4d569SChristian Lamparter } 324*e9f4d569SChristian Lamparter 325*e9f4d569SChristian Lamparter static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio) 326*e9f4d569SChristian Lamparter { 327*e9f4d569SChristian Lamparter unsigned long flags; 328*e9f4d569SChristian Lamparter 329*e9f4d569SChristian Lamparter spin_lock_irqsave(&gc->bgpio_lock, flags); 330*e9f4d569SChristian Lamparter 331*e9f4d569SChristian Lamparter gc->bgpio_dir |= gc->pin2mask(gc, gpio); 332*e9f4d569SChristian Lamparter gc->write_reg(gc->reg_dir, gc->bgpio_dir); 333*e9f4d569SChristian Lamparter 334*e9f4d569SChristian Lamparter spin_unlock_irqrestore(&gc->bgpio_lock, flags); 335*e9f4d569SChristian Lamparter 336*e9f4d569SChristian Lamparter return 0; 337*e9f4d569SChristian Lamparter } 338*e9f4d569SChristian Lamparter 339*e9f4d569SChristian Lamparter static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val) 340*e9f4d569SChristian Lamparter { 341*e9f4d569SChristian Lamparter unsigned long flags; 342*e9f4d569SChristian Lamparter 343*e9f4d569SChristian Lamparter gc->set(gc, gpio, val); 344*e9f4d569SChristian Lamparter 345*e9f4d569SChristian Lamparter spin_lock_irqsave(&gc->bgpio_lock, flags); 346*e9f4d569SChristian Lamparter 347*e9f4d569SChristian Lamparter gc->bgpio_dir &= ~gc->pin2mask(gc, gpio); 348*e9f4d569SChristian Lamparter gc->write_reg(gc->reg_dir, gc->bgpio_dir); 349*e9f4d569SChristian Lamparter 350*e9f4d569SChristian Lamparter spin_unlock_irqrestore(&gc->bgpio_lock, flags); 351*e9f4d569SChristian Lamparter 352*e9f4d569SChristian Lamparter return 0; 353*e9f4d569SChristian Lamparter } 354*e9f4d569SChristian Lamparter 355*e9f4d569SChristian Lamparter static int bgpio_get_dir_inv(struct gpio_chip *gc, unsigned int gpio) 356*e9f4d569SChristian Lamparter { 357*e9f4d569SChristian Lamparter /* Return 0 if output, 1 if input */ 358*e9f4d569SChristian Lamparter return !!(gc->read_reg(gc->reg_dir) & gc->pin2mask(gc, gpio)); 359*e9f4d569SChristian Lamparter } 360*e9f4d569SChristian Lamparter 361*e9f4d569SChristian Lamparter static int bgpio_setup_accessors(struct device *dev, 362*e9f4d569SChristian Lamparter struct gpio_chip *gc, 363*e9f4d569SChristian Lamparter bool bit_be, 364*e9f4d569SChristian Lamparter bool byte_be) 365*e9f4d569SChristian Lamparter { 366*e9f4d569SChristian Lamparter 367*e9f4d569SChristian Lamparter switch (gc->bgpio_bits) { 368*e9f4d569SChristian Lamparter case 8: 369*e9f4d569SChristian Lamparter gc->read_reg = bgpio_read8; 370*e9f4d569SChristian Lamparter gc->write_reg = bgpio_write8; 371*e9f4d569SChristian Lamparter break; 372*e9f4d569SChristian Lamparter case 16: 373*e9f4d569SChristian Lamparter if (byte_be) { 374*e9f4d569SChristian Lamparter gc->read_reg = bgpio_read16be; 375*e9f4d569SChristian Lamparter gc->write_reg = bgpio_write16be; 376*e9f4d569SChristian Lamparter } else { 377*e9f4d569SChristian Lamparter gc->read_reg = bgpio_read16; 378*e9f4d569SChristian Lamparter gc->write_reg = bgpio_write16; 379*e9f4d569SChristian Lamparter } 380*e9f4d569SChristian Lamparter break; 381*e9f4d569SChristian Lamparter case 32: 382*e9f4d569SChristian Lamparter if (byte_be) { 383*e9f4d569SChristian Lamparter gc->read_reg = bgpio_read32be; 384*e9f4d569SChristian Lamparter gc->write_reg = bgpio_write32be; 385*e9f4d569SChristian Lamparter } else { 386*e9f4d569SChristian Lamparter gc->read_reg = bgpio_read32; 387*e9f4d569SChristian Lamparter gc->write_reg = bgpio_write32; 388*e9f4d569SChristian Lamparter } 389*e9f4d569SChristian Lamparter break; 390*e9f4d569SChristian Lamparter #if BITS_PER_LONG >= 64 391*e9f4d569SChristian Lamparter case 64: 392*e9f4d569SChristian Lamparter if (byte_be) { 393*e9f4d569SChristian Lamparter dev_err(dev, 394*e9f4d569SChristian Lamparter "64 bit big endian byte order unsupported\n"); 395*e9f4d569SChristian Lamparter return -EINVAL; 396*e9f4d569SChristian Lamparter } else { 397*e9f4d569SChristian Lamparter gc->read_reg = bgpio_read64; 398*e9f4d569SChristian Lamparter gc->write_reg = bgpio_write64; 399*e9f4d569SChristian Lamparter } 400*e9f4d569SChristian Lamparter break; 401*e9f4d569SChristian Lamparter #endif /* BITS_PER_LONG >= 64 */ 402*e9f4d569SChristian Lamparter default: 403*e9f4d569SChristian Lamparter dev_err(dev, "unsupported data width %u bits\n", gc->bgpio_bits); 404*e9f4d569SChristian Lamparter return -EINVAL; 405*e9f4d569SChristian Lamparter } 406*e9f4d569SChristian Lamparter 407*e9f4d569SChristian Lamparter gc->pin2mask = bit_be ? bgpio_pin2mask_be : bgpio_pin2mask; 408*e9f4d569SChristian Lamparter 409*e9f4d569SChristian Lamparter return 0; 410*e9f4d569SChristian Lamparter } 411*e9f4d569SChristian Lamparter 412*e9f4d569SChristian Lamparter /* 413*e9f4d569SChristian Lamparter * Create the device and allocate the resources. For setting GPIO's there are 414*e9f4d569SChristian Lamparter * three supported configurations: 415*e9f4d569SChristian Lamparter * 416*e9f4d569SChristian Lamparter * - single input/output register resource (named "dat"). 417*e9f4d569SChristian Lamparter * - set/clear pair (named "set" and "clr"). 418*e9f4d569SChristian Lamparter * - single output register resource and single input resource ("set" and 419*e9f4d569SChristian Lamparter * dat"). 420*e9f4d569SChristian Lamparter * 421*e9f4d569SChristian Lamparter * For the single output register, this drives a 1 by setting a bit and a zero 422*e9f4d569SChristian Lamparter * by clearing a bit. For the set clr pair, this drives a 1 by setting a bit 423*e9f4d569SChristian Lamparter * in the set register and clears it by setting a bit in the clear register. 424*e9f4d569SChristian Lamparter * The configuration is detected by which resources are present. 425*e9f4d569SChristian Lamparter * 426*e9f4d569SChristian Lamparter * For setting the GPIO direction, there are three supported configurations: 427*e9f4d569SChristian Lamparter * 428*e9f4d569SChristian Lamparter * - simple bidirection GPIO that requires no configuration. 429*e9f4d569SChristian Lamparter * - an output direction register (named "dirout") where a 1 bit 430*e9f4d569SChristian Lamparter * indicates the GPIO is an output. 431*e9f4d569SChristian Lamparter * - an input direction register (named "dirin") where a 1 bit indicates 432*e9f4d569SChristian Lamparter * the GPIO is an input. 433*e9f4d569SChristian Lamparter */ 434*e9f4d569SChristian Lamparter static int bgpio_setup_io(struct gpio_chip *gc, 435*e9f4d569SChristian Lamparter void __iomem *dat, 436*e9f4d569SChristian Lamparter void __iomem *set, 437*e9f4d569SChristian Lamparter void __iomem *clr, 438*e9f4d569SChristian Lamparter unsigned long flags) 439*e9f4d569SChristian Lamparter { 440*e9f4d569SChristian Lamparter 441*e9f4d569SChristian Lamparter gc->reg_dat = dat; 442*e9f4d569SChristian Lamparter if (!gc->reg_dat) 443*e9f4d569SChristian Lamparter return -EINVAL; 444*e9f4d569SChristian Lamparter 445*e9f4d569SChristian Lamparter if (set && clr) { 446*e9f4d569SChristian Lamparter gc->reg_set = set; 447*e9f4d569SChristian Lamparter gc->reg_clr = clr; 448*e9f4d569SChristian Lamparter gc->set = bgpio_set_with_clear; 449*e9f4d569SChristian Lamparter gc->set_multiple = bgpio_set_multiple_with_clear; 450*e9f4d569SChristian Lamparter } else if (set && !clr) { 451*e9f4d569SChristian Lamparter gc->reg_set = set; 452*e9f4d569SChristian Lamparter gc->set = bgpio_set_set; 453*e9f4d569SChristian Lamparter gc->set_multiple = bgpio_set_multiple_set; 454*e9f4d569SChristian Lamparter } else if (flags & BGPIOF_NO_OUTPUT) { 455*e9f4d569SChristian Lamparter gc->set = bgpio_set_none; 456*e9f4d569SChristian Lamparter gc->set_multiple = NULL; 457*e9f4d569SChristian Lamparter } else { 458*e9f4d569SChristian Lamparter gc->set = bgpio_set; 459*e9f4d569SChristian Lamparter gc->set_multiple = bgpio_set_multiple; 460*e9f4d569SChristian Lamparter } 461*e9f4d569SChristian Lamparter 462*e9f4d569SChristian Lamparter if (!(flags & BGPIOF_UNREADABLE_REG_SET) && 463*e9f4d569SChristian Lamparter (flags & BGPIOF_READ_OUTPUT_REG_SET)) 464*e9f4d569SChristian Lamparter gc->get = bgpio_get_set; 465*e9f4d569SChristian Lamparter else 466*e9f4d569SChristian Lamparter gc->get = bgpio_get; 467*e9f4d569SChristian Lamparter 468*e9f4d569SChristian Lamparter return 0; 469*e9f4d569SChristian Lamparter } 470*e9f4d569SChristian Lamparter 471*e9f4d569SChristian Lamparter static int bgpio_setup_direction(struct gpio_chip *gc, 472*e9f4d569SChristian Lamparter void __iomem *dirout, 473*e9f4d569SChristian Lamparter void __iomem *dirin, 474*e9f4d569SChristian Lamparter unsigned long flags) 475*e9f4d569SChristian Lamparter { 476*e9f4d569SChristian Lamparter if (dirout && dirin) { 477*e9f4d569SChristian Lamparter return -EINVAL; 478*e9f4d569SChristian Lamparter } else if (dirout) { 479*e9f4d569SChristian Lamparter gc->reg_dir = dirout; 480*e9f4d569SChristian Lamparter gc->direction_output = bgpio_dir_out; 481*e9f4d569SChristian Lamparter gc->direction_input = bgpio_dir_in; 482*e9f4d569SChristian Lamparter gc->get_direction = bgpio_get_dir; 483*e9f4d569SChristian Lamparter } else if (dirin) { 484*e9f4d569SChristian Lamparter gc->reg_dir = dirin; 485*e9f4d569SChristian Lamparter gc->direction_output = bgpio_dir_out_inv; 486*e9f4d569SChristian Lamparter gc->direction_input = bgpio_dir_in_inv; 487*e9f4d569SChristian Lamparter gc->get_direction = bgpio_get_dir_inv; 488*e9f4d569SChristian Lamparter } else { 489*e9f4d569SChristian Lamparter if (flags & BGPIOF_NO_OUTPUT) 490*e9f4d569SChristian Lamparter gc->direction_output = bgpio_dir_out_err; 491*e9f4d569SChristian Lamparter else 492*e9f4d569SChristian Lamparter gc->direction_output = bgpio_simple_dir_out; 493*e9f4d569SChristian Lamparter gc->direction_input = bgpio_simple_dir_in; 494*e9f4d569SChristian Lamparter } 495*e9f4d569SChristian Lamparter 496*e9f4d569SChristian Lamparter return 0; 497*e9f4d569SChristian Lamparter } 498*e9f4d569SChristian Lamparter 499*e9f4d569SChristian Lamparter static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin) 500*e9f4d569SChristian Lamparter { 501*e9f4d569SChristian Lamparter if (gpio_pin < chip->ngpio) 502*e9f4d569SChristian Lamparter return 0; 503*e9f4d569SChristian Lamparter 504*e9f4d569SChristian Lamparter return -EINVAL; 505*e9f4d569SChristian Lamparter } 506*e9f4d569SChristian Lamparter 507*e9f4d569SChristian Lamparter int bgpio_init(struct gpio_chip *gc, struct device *dev, 508*e9f4d569SChristian Lamparter unsigned long sz, void __iomem *dat, void __iomem *set, 509*e9f4d569SChristian Lamparter void __iomem *clr, void __iomem *dirout, void __iomem *dirin, 510*e9f4d569SChristian Lamparter unsigned long flags) 511*e9f4d569SChristian Lamparter { 512*e9f4d569SChristian Lamparter int ret; 513*e9f4d569SChristian Lamparter 514*e9f4d569SChristian Lamparter if (!is_power_of_2(sz)) 515*e9f4d569SChristian Lamparter return -EINVAL; 516*e9f4d569SChristian Lamparter 517*e9f4d569SChristian Lamparter gc->bgpio_bits = sz * 8; 518*e9f4d569SChristian Lamparter if (gc->bgpio_bits > BITS_PER_LONG) 519*e9f4d569SChristian Lamparter return -EINVAL; 520*e9f4d569SChristian Lamparter 521*e9f4d569SChristian Lamparter spin_lock_init(&gc->bgpio_lock); 522*e9f4d569SChristian Lamparter gc->parent = dev; 523*e9f4d569SChristian Lamparter gc->label = dev_name(dev); 524*e9f4d569SChristian Lamparter gc->base = -1; 525*e9f4d569SChristian Lamparter gc->ngpio = gc->bgpio_bits; 526*e9f4d569SChristian Lamparter gc->request = bgpio_request; 527*e9f4d569SChristian Lamparter 528*e9f4d569SChristian Lamparter ret = bgpio_setup_io(gc, dat, set, clr, flags); 529*e9f4d569SChristian Lamparter if (ret) 530*e9f4d569SChristian Lamparter return ret; 531*e9f4d569SChristian Lamparter 532*e9f4d569SChristian Lamparter ret = bgpio_setup_accessors(dev, gc, flags & BGPIOF_BIG_ENDIAN, 533*e9f4d569SChristian Lamparter flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER); 534*e9f4d569SChristian Lamparter if (ret) 535*e9f4d569SChristian Lamparter return ret; 536*e9f4d569SChristian Lamparter 537*e9f4d569SChristian Lamparter ret = bgpio_setup_direction(gc, dirout, dirin, flags); 538*e9f4d569SChristian Lamparter if (ret) 539*e9f4d569SChristian Lamparter return ret; 540*e9f4d569SChristian Lamparter 541*e9f4d569SChristian Lamparter gc->bgpio_data = gc->read_reg(gc->reg_dat); 542*e9f4d569SChristian Lamparter if (gc->set == bgpio_set_set && 543*e9f4d569SChristian Lamparter !(flags & BGPIOF_UNREADABLE_REG_SET)) 544*e9f4d569SChristian Lamparter gc->bgpio_data = gc->read_reg(gc->reg_set); 545*e9f4d569SChristian Lamparter if (gc->reg_dir && !(flags & BGPIOF_UNREADABLE_REG_DIR)) 546*e9f4d569SChristian Lamparter gc->bgpio_dir = gc->read_reg(gc->reg_dir); 547*e9f4d569SChristian Lamparter 548*e9f4d569SChristian Lamparter return ret; 549*e9f4d569SChristian Lamparter } 550*e9f4d569SChristian Lamparter EXPORT_SYMBOL_GPL(bgpio_init); 551*e9f4d569SChristian Lamparter 552*e9f4d569SChristian Lamparter #if IS_ENABLED(CONFIG_GPIO_GENERIC_PLATFORM) 553*e9f4d569SChristian Lamparter 554*e9f4d569SChristian Lamparter static void __iomem *bgpio_map(struct platform_device *pdev, 555*e9f4d569SChristian Lamparter const char *name, 556*e9f4d569SChristian Lamparter resource_size_t sane_sz) 557*e9f4d569SChristian Lamparter { 558*e9f4d569SChristian Lamparter struct resource *r; 559*e9f4d569SChristian Lamparter resource_size_t sz; 560*e9f4d569SChristian Lamparter 561*e9f4d569SChristian Lamparter r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); 562*e9f4d569SChristian Lamparter if (!r) 563*e9f4d569SChristian Lamparter return NULL; 564*e9f4d569SChristian Lamparter 565*e9f4d569SChristian Lamparter sz = resource_size(r); 566*e9f4d569SChristian Lamparter if (sz != sane_sz) 567*e9f4d569SChristian Lamparter return IOMEM_ERR_PTR(-EINVAL); 568*e9f4d569SChristian Lamparter 569*e9f4d569SChristian Lamparter return devm_ioremap_resource(&pdev->dev, r); 570*e9f4d569SChristian Lamparter } 571*e9f4d569SChristian Lamparter 572*e9f4d569SChristian Lamparter static int bgpio_pdev_probe(struct platform_device *pdev) 573*e9f4d569SChristian Lamparter { 574*e9f4d569SChristian Lamparter struct device *dev = &pdev->dev; 575*e9f4d569SChristian Lamparter struct resource *r; 576*e9f4d569SChristian Lamparter void __iomem *dat; 577*e9f4d569SChristian Lamparter void __iomem *set; 578*e9f4d569SChristian Lamparter void __iomem *clr; 579*e9f4d569SChristian Lamparter void __iomem *dirout; 580*e9f4d569SChristian Lamparter void __iomem *dirin; 581*e9f4d569SChristian Lamparter unsigned long sz; 582*e9f4d569SChristian Lamparter unsigned long flags = pdev->id_entry->driver_data; 583*e9f4d569SChristian Lamparter int err; 584*e9f4d569SChristian Lamparter struct gpio_chip *gc; 585*e9f4d569SChristian Lamparter struct bgpio_pdata *pdata = dev_get_platdata(dev); 586*e9f4d569SChristian Lamparter 587*e9f4d569SChristian Lamparter r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); 588*e9f4d569SChristian Lamparter if (!r) 589*e9f4d569SChristian Lamparter return -EINVAL; 590*e9f4d569SChristian Lamparter 591*e9f4d569SChristian Lamparter sz = resource_size(r); 592*e9f4d569SChristian Lamparter 593*e9f4d569SChristian Lamparter dat = bgpio_map(pdev, "dat", sz); 594*e9f4d569SChristian Lamparter if (IS_ERR(dat)) 595*e9f4d569SChristian Lamparter return PTR_ERR(dat); 596*e9f4d569SChristian Lamparter 597*e9f4d569SChristian Lamparter set = bgpio_map(pdev, "set", sz); 598*e9f4d569SChristian Lamparter if (IS_ERR(set)) 599*e9f4d569SChristian Lamparter return PTR_ERR(set); 600*e9f4d569SChristian Lamparter 601*e9f4d569SChristian Lamparter clr = bgpio_map(pdev, "clr", sz); 602*e9f4d569SChristian Lamparter if (IS_ERR(clr)) 603*e9f4d569SChristian Lamparter return PTR_ERR(clr); 604*e9f4d569SChristian Lamparter 605*e9f4d569SChristian Lamparter dirout = bgpio_map(pdev, "dirout", sz); 606*e9f4d569SChristian Lamparter if (IS_ERR(dirout)) 607*e9f4d569SChristian Lamparter return PTR_ERR(dirout); 608*e9f4d569SChristian Lamparter 609*e9f4d569SChristian Lamparter dirin = bgpio_map(pdev, "dirin", sz); 610*e9f4d569SChristian Lamparter if (IS_ERR(dirin)) 611*e9f4d569SChristian Lamparter return PTR_ERR(dirin); 612*e9f4d569SChristian Lamparter 613*e9f4d569SChristian Lamparter gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL); 614*e9f4d569SChristian Lamparter if (!gc) 615*e9f4d569SChristian Lamparter return -ENOMEM; 616*e9f4d569SChristian Lamparter 617*e9f4d569SChristian Lamparter err = bgpio_init(gc, dev, sz, dat, set, clr, dirout, dirin, flags); 618*e9f4d569SChristian Lamparter if (err) 619*e9f4d569SChristian Lamparter return err; 620*e9f4d569SChristian Lamparter 621*e9f4d569SChristian Lamparter if (pdata) { 622*e9f4d569SChristian Lamparter if (pdata->label) 623*e9f4d569SChristian Lamparter gc->label = pdata->label; 624*e9f4d569SChristian Lamparter gc->base = pdata->base; 625*e9f4d569SChristian Lamparter if (pdata->ngpio > 0) 626*e9f4d569SChristian Lamparter gc->ngpio = pdata->ngpio; 627*e9f4d569SChristian Lamparter } 628*e9f4d569SChristian Lamparter 629*e9f4d569SChristian Lamparter platform_set_drvdata(pdev, gc); 630*e9f4d569SChristian Lamparter 631*e9f4d569SChristian Lamparter return devm_gpiochip_add_data(&pdev->dev, gc, NULL); 632*e9f4d569SChristian Lamparter } 633*e9f4d569SChristian Lamparter 634*e9f4d569SChristian Lamparter static const struct platform_device_id bgpio_id_table[] = { 635*e9f4d569SChristian Lamparter { 636*e9f4d569SChristian Lamparter .name = "basic-mmio-gpio", 637*e9f4d569SChristian Lamparter .driver_data = 0, 638*e9f4d569SChristian Lamparter }, { 639*e9f4d569SChristian Lamparter .name = "basic-mmio-gpio-be", 640*e9f4d569SChristian Lamparter .driver_data = BGPIOF_BIG_ENDIAN, 641*e9f4d569SChristian Lamparter }, 642*e9f4d569SChristian Lamparter { } 643*e9f4d569SChristian Lamparter }; 644*e9f4d569SChristian Lamparter MODULE_DEVICE_TABLE(platform, bgpio_id_table); 645*e9f4d569SChristian Lamparter 646*e9f4d569SChristian Lamparter static struct platform_driver bgpio_driver = { 647*e9f4d569SChristian Lamparter .driver = { 648*e9f4d569SChristian Lamparter .name = "basic-mmio-gpio", 649*e9f4d569SChristian Lamparter }, 650*e9f4d569SChristian Lamparter .id_table = bgpio_id_table, 651*e9f4d569SChristian Lamparter .probe = bgpio_pdev_probe, 652*e9f4d569SChristian Lamparter }; 653*e9f4d569SChristian Lamparter 654*e9f4d569SChristian Lamparter module_platform_driver(bgpio_driver); 655*e9f4d569SChristian Lamparter 656*e9f4d569SChristian Lamparter #endif /* CONFIG_GPIO_GENERIC_PLATFORM */ 657*e9f4d569SChristian Lamparter 658*e9f4d569SChristian Lamparter MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers"); 659*e9f4d569SChristian Lamparter MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>"); 660*e9f4d569SChristian Lamparter MODULE_LICENSE("GPL"); 661