diff options
Diffstat (limited to 'drivers/gpio/gpio-generic.c')
| -rw-r--r-- | drivers/gpio/gpio-generic.c | 76 | 
1 files changed, 76 insertions, 0 deletions
| diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c index 16f6115e5bdb..b92a690f5765 100644 --- a/drivers/gpio/gpio-generic.c +++ b/drivers/gpio/gpio-generic.c | |||
| @@ -190,6 +190,79 @@ static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) | |||
| 190 | spin_unlock_irqrestore(&bgc->lock, flags); | 190 | spin_unlock_irqrestore(&bgc->lock, flags); | 
| 191 | } | 191 | } | 
| 192 | 192 | ||
| 193 | static void bgpio_multiple_get_masks(struct bgpio_chip *bgc, | ||
| 194 | unsigned long *mask, unsigned long *bits, | ||
| 195 | unsigned long *set_mask, | ||
| 196 | unsigned long *clear_mask) | ||
| 197 | { | ||
| 198 | int i; | ||
| 199 | |||
| 200 | *set_mask = 0; | ||
| 201 | *clear_mask = 0; | ||
| 202 | |||
| 203 | for (i = 0; i < bgc->bits; i++) { | ||
| 204 | if (*mask == 0) | ||
| 205 | break; | ||
| 206 | if (__test_and_clear_bit(i, mask)) { | ||
| 207 | if (test_bit(i, bits)) | ||
| 208 | *set_mask |= bgc->pin2mask(bgc, i); | ||
| 209 | else | ||
| 210 | *clear_mask |= bgc->pin2mask(bgc, i); | ||
| 211 | } | ||
| 212 | } | ||
| 213 | } | ||
| 214 | |||
| 215 | static void bgpio_set_multiple_single_reg(struct bgpio_chip *bgc, | ||
| 216 | unsigned long *mask, | ||
| 217 | unsigned long *bits, | ||
| 218 | void __iomem *reg) | ||
| 219 | { | ||
| 220 | unsigned long flags; | ||
| 221 | unsigned long set_mask, clear_mask; | ||
| 222 | |||
| 223 | spin_lock_irqsave(&bgc->lock, flags); | ||
| 224 | |||
| 225 | bgpio_multiple_get_masks(bgc, mask, bits, &set_mask, &clear_mask); | ||
| 226 | |||
| 227 | bgc->data |= set_mask; | ||
| 228 | bgc->data &= ~clear_mask; | ||
| 229 | |||
| 230 | bgc->write_reg(reg, bgc->data); | ||
| 231 | |||
| 232 | spin_unlock_irqrestore(&bgc->lock, flags); | ||
| 233 | } | ||
| 234 | |||
| 235 | static void bgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, | ||
| 236 | unsigned long *bits) | ||
| 237 | { | ||
| 238 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | ||
| 239 | |||
| 240 | bgpio_set_multiple_single_reg(bgc, mask, bits, bgc->reg_dat); | ||
| 241 | } | ||
| 242 | |||
| 243 | static void bgpio_set_multiple_set(struct gpio_chip *gc, unsigned long *mask, | ||
| 244 | unsigned long *bits) | ||
| 245 | { | ||
| 246 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | ||
| 247 | |||
| 248 | bgpio_set_multiple_single_reg(bgc, mask, bits, bgc->reg_set); | ||
| 249 | } | ||
| 250 | |||
| 251 | static void bgpio_set_multiple_with_clear(struct gpio_chip *gc, | ||
| 252 | unsigned long *mask, | ||
| 253 | unsigned long *bits) | ||
| 254 | { | ||
| 255 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | ||
| 256 | unsigned long set_mask, clear_mask; | ||
| 257 | |||
| 258 | bgpio_multiple_get_masks(bgc, mask, bits, &set_mask, &clear_mask); | ||
| 259 | |||
| 260 | if (set_mask) | ||
| 261 | bgc->write_reg(bgc->reg_set, set_mask); | ||
| 262 | if (clear_mask) | ||
| 263 | bgc->write_reg(bgc->reg_clr, clear_mask); | ||
| 264 | } | ||
| 265 | |||
| 193 | static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio) | 266 | static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio) | 
| 194 | { | 267 | { | 
| 195 | return 0; | 268 | return 0; | 
| @@ -354,11 +427,14 @@ static int bgpio_setup_io(struct bgpio_chip *bgc, | |||
| 354 | bgc->reg_set = set; | 427 | bgc->reg_set = set; | 
| 355 | bgc->reg_clr = clr; | 428 | bgc->reg_clr = clr; | 
| 356 | bgc->gc.set = bgpio_set_with_clear; | 429 | bgc->gc.set = bgpio_set_with_clear; | 
| 430 | bgc->gc.set_multiple = bgpio_set_multiple_with_clear; | ||
| 357 | } else if (set && !clr) { | 431 | } else if (set && !clr) { | 
| 358 | bgc->reg_set = set; | 432 | bgc->reg_set = set; | 
| 359 | bgc->gc.set = bgpio_set_set; | 433 | bgc->gc.set = bgpio_set_set; | 
| 434 | bgc->gc.set_multiple = bgpio_set_multiple_set; | ||
| 360 | } else { | 435 | } else { | 
| 361 | bgc->gc.set = bgpio_set; | 436 | bgc->gc.set = bgpio_set; | 
| 437 | bgc->gc.set_multiple = bgpio_set_multiple; | ||
| 362 | } | 438 | } | 
| 363 | 439 | ||
| 364 | bgc->gc.get = bgpio_get; | 440 | bgc->gc.get = bgpio_get; | 
