diff options
Diffstat (limited to 'drivers/gpio')
| -rw-r--r-- | drivers/gpio/Kconfig | 18 | ||||
| -rw-r--r-- | drivers/gpio/Makefile | 2 | ||||
| -rw-r--r-- | drivers/gpio/gpiolib.c | 96 | ||||
| -rw-r--r-- | drivers/gpio/max730x.c | 22 | ||||
| -rw-r--r-- | drivers/gpio/pcf857x.c | 9 | ||||
| -rw-r--r-- | drivers/gpio/stmpe-gpio.c | 399 | ||||
| -rw-r--r-- | drivers/gpio/sx150x.c | 645 | ||||
| -rw-r--r-- | drivers/gpio/wm831x-gpio.c | 32 |
8 files changed, 1150 insertions, 73 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 7face915b963..510aa2054544 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
| @@ -195,6 +195,24 @@ config GPIO_PCF857X | |||
| 195 | This driver provides an in-kernel interface to those GPIOs using | 195 | This driver provides an in-kernel interface to those GPIOs using |
| 196 | platform-neutral GPIO calls. | 196 | platform-neutral GPIO calls. |
| 197 | 197 | ||
| 198 | config GPIO_SX150X | ||
| 199 | bool "Semtech SX150x I2C GPIO expander" | ||
| 200 | depends on I2C=y | ||
| 201 | default n | ||
| 202 | help | ||
| 203 | Say yes here to provide support for Semtech SX150-series I2C | ||
| 204 | GPIO expanders. Compatible models include: | ||
| 205 | |||
| 206 | 8 bits: sx1508q | ||
| 207 | 16 bits: sx1509q | ||
| 208 | |||
| 209 | config GPIO_STMPE | ||
| 210 | bool "STMPE GPIOs" | ||
| 211 | depends on MFD_STMPE | ||
| 212 | help | ||
| 213 | This enables support for the GPIOs found on the STMPE I/O | ||
| 214 | Expanders. | ||
| 215 | |||
| 198 | config GPIO_TC35892 | 216 | config GPIO_TC35892 |
| 199 | bool "TC35892 GPIOs" | 217 | bool "TC35892 GPIOs" |
| 200 | depends on MFD_TC35892 | 218 | depends on MFD_TC35892 |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index e53dcff49b4f..fc6019d93720 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
| @@ -20,6 +20,7 @@ obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o | |||
| 20 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o | 20 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o |
| 21 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o | 21 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o |
| 22 | obj-$(CONFIG_GPIO_PL061) += pl061.o | 22 | obj-$(CONFIG_GPIO_PL061) += pl061.o |
| 23 | obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o | ||
| 23 | obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o | 24 | obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o |
| 24 | obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o | 25 | obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o |
| 25 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o | 26 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o |
| @@ -35,3 +36,4 @@ obj-$(CONFIG_GPIO_WM8994) += wm8994-gpio.o | |||
| 35 | obj-$(CONFIG_GPIO_SCH) += sch_gpio.o | 36 | obj-$(CONFIG_GPIO_SCH) += sch_gpio.o |
| 36 | obj-$(CONFIG_GPIO_RDC321X) += rdc321x-gpio.o | 37 | obj-$(CONFIG_GPIO_RDC321X) += rdc321x-gpio.o |
| 37 | obj-$(CONFIG_GPIO_JANZ_TTL) += janz-ttl.o | 38 | obj-$(CONFIG_GPIO_JANZ_TTL) += janz-ttl.o |
| 39 | obj-$(CONFIG_GPIO_SX150X) += sx150x.o | ||
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 6a6bd569e1f8..21da9c19a0cb 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
| @@ -57,9 +57,9 @@ struct gpio_desc { | |||
| 57 | #define FLAG_TRIG_RISE 6 /* trigger on rising edge */ | 57 | #define FLAG_TRIG_RISE 6 /* trigger on rising edge */ |
| 58 | #define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */ | 58 | #define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */ |
| 59 | 59 | ||
| 60 | #define PDESC_ID_SHIFT 16 /* add new flags before this one */ | 60 | #define ID_SHIFT 16 /* add new flags before this one */ |
| 61 | 61 | ||
| 62 | #define GPIO_FLAGS_MASK ((1 << PDESC_ID_SHIFT) - 1) | 62 | #define GPIO_FLAGS_MASK ((1 << ID_SHIFT) - 1) |
| 63 | #define GPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE)) | 63 | #define GPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE)) |
| 64 | 64 | ||
| 65 | #ifdef CONFIG_DEBUG_FS | 65 | #ifdef CONFIG_DEBUG_FS |
| @@ -69,12 +69,7 @@ struct gpio_desc { | |||
| 69 | static struct gpio_desc gpio_desc[ARCH_NR_GPIOS]; | 69 | static struct gpio_desc gpio_desc[ARCH_NR_GPIOS]; |
| 70 | 70 | ||
| 71 | #ifdef CONFIG_GPIO_SYSFS | 71 | #ifdef CONFIG_GPIO_SYSFS |
| 72 | struct poll_desc { | 72 | static DEFINE_IDR(dirent_idr); |
| 73 | struct work_struct work; | ||
| 74 | struct sysfs_dirent *value_sd; | ||
| 75 | }; | ||
| 76 | |||
| 77 | static struct idr pdesc_idr; | ||
| 78 | #endif | 73 | #endif |
| 79 | 74 | ||
| 80 | static inline void desc_set_label(struct gpio_desc *d, const char *label) | 75 | static inline void desc_set_label(struct gpio_desc *d, const char *label) |
| @@ -325,24 +320,16 @@ static const DEVICE_ATTR(value, 0644, | |||
| 325 | 320 | ||
| 326 | static irqreturn_t gpio_sysfs_irq(int irq, void *priv) | 321 | static irqreturn_t gpio_sysfs_irq(int irq, void *priv) |
| 327 | { | 322 | { |
| 328 | struct work_struct *work = priv; | 323 | struct sysfs_dirent *value_sd = priv; |
| 329 | 324 | ||
| 330 | schedule_work(work); | 325 | sysfs_notify_dirent(value_sd); |
| 331 | return IRQ_HANDLED; | 326 | return IRQ_HANDLED; |
| 332 | } | 327 | } |
| 333 | 328 | ||
| 334 | static void gpio_notify_sysfs(struct work_struct *work) | ||
| 335 | { | ||
| 336 | struct poll_desc *pdesc; | ||
| 337 | |||
| 338 | pdesc = container_of(work, struct poll_desc, work); | ||
| 339 | sysfs_notify_dirent(pdesc->value_sd); | ||
| 340 | } | ||
| 341 | |||
| 342 | static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, | 329 | static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, |
| 343 | unsigned long gpio_flags) | 330 | unsigned long gpio_flags) |
| 344 | { | 331 | { |
| 345 | struct poll_desc *pdesc; | 332 | struct sysfs_dirent *value_sd; |
| 346 | unsigned long irq_flags; | 333 | unsigned long irq_flags; |
| 347 | int ret, irq, id; | 334 | int ret, irq, id; |
| 348 | 335 | ||
| @@ -353,18 +340,16 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, | |||
| 353 | if (irq < 0) | 340 | if (irq < 0) |
| 354 | return -EIO; | 341 | return -EIO; |
| 355 | 342 | ||
| 356 | id = desc->flags >> PDESC_ID_SHIFT; | 343 | id = desc->flags >> ID_SHIFT; |
| 357 | pdesc = idr_find(&pdesc_idr, id); | 344 | value_sd = idr_find(&dirent_idr, id); |
| 358 | if (pdesc) { | 345 | if (value_sd) |
| 359 | free_irq(irq, &pdesc->work); | 346 | free_irq(irq, value_sd); |
| 360 | cancel_work_sync(&pdesc->work); | ||
| 361 | } | ||
| 362 | 347 | ||
| 363 | desc->flags &= ~GPIO_TRIGGER_MASK; | 348 | desc->flags &= ~GPIO_TRIGGER_MASK; |
| 364 | 349 | ||
| 365 | if (!gpio_flags) { | 350 | if (!gpio_flags) { |
| 366 | ret = 0; | 351 | ret = 0; |
| 367 | goto free_sd; | 352 | goto free_id; |
| 368 | } | 353 | } |
| 369 | 354 | ||
| 370 | irq_flags = IRQF_SHARED; | 355 | irq_flags = IRQF_SHARED; |
| @@ -375,55 +360,46 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, | |||
| 375 | irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? | 360 | irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? |
| 376 | IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; | 361 | IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; |
| 377 | 362 | ||
| 378 | if (!pdesc) { | 363 | if (!value_sd) { |
| 379 | pdesc = kmalloc(sizeof(*pdesc), GFP_KERNEL); | 364 | value_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value"); |
| 380 | if (!pdesc) { | 365 | if (!value_sd) { |
| 381 | ret = -ENOMEM; | 366 | ret = -ENODEV; |
| 382 | goto err_out; | 367 | goto err_out; |
| 383 | } | 368 | } |
| 384 | 369 | ||
| 385 | do { | 370 | do { |
| 386 | ret = -ENOMEM; | 371 | ret = -ENOMEM; |
| 387 | if (idr_pre_get(&pdesc_idr, GFP_KERNEL)) | 372 | if (idr_pre_get(&dirent_idr, GFP_KERNEL)) |
| 388 | ret = idr_get_new_above(&pdesc_idr, | 373 | ret = idr_get_new_above(&dirent_idr, value_sd, |
| 389 | pdesc, 1, &id); | 374 | 1, &id); |
| 390 | } while (ret == -EAGAIN); | 375 | } while (ret == -EAGAIN); |
| 391 | 376 | ||
| 392 | if (ret) | 377 | if (ret) |
| 393 | goto free_mem; | 378 | goto free_sd; |
| 394 | 379 | ||
| 395 | desc->flags &= GPIO_FLAGS_MASK; | 380 | desc->flags &= GPIO_FLAGS_MASK; |
| 396 | desc->flags |= (unsigned long)id << PDESC_ID_SHIFT; | 381 | desc->flags |= (unsigned long)id << ID_SHIFT; |
| 397 | 382 | ||
| 398 | if (desc->flags >> PDESC_ID_SHIFT != id) { | 383 | if (desc->flags >> ID_SHIFT != id) { |
| 399 | ret = -ERANGE; | 384 | ret = -ERANGE; |
| 400 | goto free_id; | 385 | goto free_id; |
| 401 | } | 386 | } |
| 402 | |||
| 403 | pdesc->value_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value"); | ||
| 404 | if (!pdesc->value_sd) { | ||
| 405 | ret = -ENODEV; | ||
| 406 | goto free_id; | ||
| 407 | } | ||
| 408 | INIT_WORK(&pdesc->work, gpio_notify_sysfs); | ||
| 409 | } | 387 | } |
| 410 | 388 | ||
| 411 | ret = request_irq(irq, gpio_sysfs_irq, irq_flags, | 389 | ret = request_any_context_irq(irq, gpio_sysfs_irq, irq_flags, |
| 412 | "gpiolib", &pdesc->work); | 390 | "gpiolib", value_sd); |
| 413 | if (ret) | 391 | if (ret < 0) |
| 414 | goto free_sd; | 392 | goto free_id; |
| 415 | 393 | ||
| 416 | desc->flags |= gpio_flags; | 394 | desc->flags |= gpio_flags; |
| 417 | return 0; | 395 | return 0; |
| 418 | 396 | ||
| 419 | free_sd: | ||
| 420 | if (pdesc) | ||
| 421 | sysfs_put(pdesc->value_sd); | ||
| 422 | free_id: | 397 | free_id: |
| 423 | idr_remove(&pdesc_idr, id); | 398 | idr_remove(&dirent_idr, id); |
| 424 | desc->flags &= GPIO_FLAGS_MASK; | 399 | desc->flags &= GPIO_FLAGS_MASK; |
| 425 | free_mem: | 400 | free_sd: |
| 426 | kfree(pdesc); | 401 | if (value_sd) |
| 402 | sysfs_put(value_sd); | ||
| 427 | err_out: | 403 | err_out: |
| 428 | return ret; | 404 | return ret; |
| 429 | } | 405 | } |
| @@ -994,8 +970,6 @@ static int __init gpiolib_sysfs_init(void) | |||
| 994 | unsigned long flags; | 970 | unsigned long flags; |
| 995 | unsigned gpio; | 971 | unsigned gpio; |
| 996 | 972 | ||
| 997 | idr_init(&pdesc_idr); | ||
| 998 | |||
| 999 | status = class_register(&gpio_class); | 973 | status = class_register(&gpio_class); |
| 1000 | if (status < 0) | 974 | if (status < 0) |
| 1001 | return status; | 975 | return status; |
| @@ -1272,7 +1246,7 @@ void gpio_free(unsigned gpio) | |||
| 1272 | if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) { | 1246 | if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) { |
| 1273 | if (chip->free) { | 1247 | if (chip->free) { |
| 1274 | spin_unlock_irqrestore(&gpio_lock, flags); | 1248 | spin_unlock_irqrestore(&gpio_lock, flags); |
| 1275 | might_sleep_if(extra_checks && chip->can_sleep); | 1249 | might_sleep_if(chip->can_sleep); |
| 1276 | chip->free(chip, gpio - chip->base); | 1250 | chip->free(chip, gpio - chip->base); |
| 1277 | spin_lock_irqsave(&gpio_lock, flags); | 1251 | spin_lock_irqsave(&gpio_lock, flags); |
| 1278 | } | 1252 | } |
| @@ -1410,7 +1384,7 @@ int gpio_direction_input(unsigned gpio) | |||
| 1410 | 1384 | ||
| 1411 | spin_unlock_irqrestore(&gpio_lock, flags); | 1385 | spin_unlock_irqrestore(&gpio_lock, flags); |
| 1412 | 1386 | ||
| 1413 | might_sleep_if(extra_checks && chip->can_sleep); | 1387 | might_sleep_if(chip->can_sleep); |
| 1414 | 1388 | ||
| 1415 | if (status) { | 1389 | if (status) { |
| 1416 | status = chip->request(chip, gpio); | 1390 | status = chip->request(chip, gpio); |
| @@ -1463,7 +1437,7 @@ int gpio_direction_output(unsigned gpio, int value) | |||
| 1463 | 1437 | ||
| 1464 | spin_unlock_irqrestore(&gpio_lock, flags); | 1438 | spin_unlock_irqrestore(&gpio_lock, flags); |
| 1465 | 1439 | ||
| 1466 | might_sleep_if(extra_checks && chip->can_sleep); | 1440 | might_sleep_if(chip->can_sleep); |
| 1467 | 1441 | ||
| 1468 | if (status) { | 1442 | if (status) { |
| 1469 | status = chip->request(chip, gpio); | 1443 | status = chip->request(chip, gpio); |
| @@ -1521,7 +1495,7 @@ int gpio_set_debounce(unsigned gpio, unsigned debounce) | |||
| 1521 | 1495 | ||
| 1522 | spin_unlock_irqrestore(&gpio_lock, flags); | 1496 | spin_unlock_irqrestore(&gpio_lock, flags); |
| 1523 | 1497 | ||
| 1524 | might_sleep_if(extra_checks && chip->can_sleep); | 1498 | might_sleep_if(chip->can_sleep); |
| 1525 | 1499 | ||
| 1526 | return chip->set_debounce(chip, gpio, debounce); | 1500 | return chip->set_debounce(chip, gpio, debounce); |
| 1527 | 1501 | ||
| @@ -1571,7 +1545,7 @@ int __gpio_get_value(unsigned gpio) | |||
| 1571 | struct gpio_chip *chip; | 1545 | struct gpio_chip *chip; |
| 1572 | 1546 | ||
| 1573 | chip = gpio_to_chip(gpio); | 1547 | chip = gpio_to_chip(gpio); |
| 1574 | WARN_ON(extra_checks && chip->can_sleep); | 1548 | WARN_ON(chip->can_sleep); |
| 1575 | return chip->get ? chip->get(chip, gpio - chip->base) : 0; | 1549 | return chip->get ? chip->get(chip, gpio - chip->base) : 0; |
| 1576 | } | 1550 | } |
| 1577 | EXPORT_SYMBOL_GPL(__gpio_get_value); | 1551 | EXPORT_SYMBOL_GPL(__gpio_get_value); |
| @@ -1590,7 +1564,7 @@ void __gpio_set_value(unsigned gpio, int value) | |||
| 1590 | struct gpio_chip *chip; | 1564 | struct gpio_chip *chip; |
| 1591 | 1565 | ||
| 1592 | chip = gpio_to_chip(gpio); | 1566 | chip = gpio_to_chip(gpio); |
| 1593 | WARN_ON(extra_checks && chip->can_sleep); | 1567 | WARN_ON(chip->can_sleep); |
| 1594 | chip->set(chip, gpio - chip->base, value); | 1568 | chip->set(chip, gpio - chip->base, value); |
| 1595 | } | 1569 | } |
| 1596 | EXPORT_SYMBOL_GPL(__gpio_set_value); | 1570 | EXPORT_SYMBOL_GPL(__gpio_set_value); |
diff --git a/drivers/gpio/max730x.c b/drivers/gpio/max730x.c index 7696a5625d58..94ce773f95f8 100644 --- a/drivers/gpio/max730x.c +++ b/drivers/gpio/max730x.c | |||
| @@ -54,7 +54,7 @@ static int max7301_direction_input(struct gpio_chip *chip, unsigned offset) | |||
| 54 | { | 54 | { |
| 55 | struct max7301 *ts = container_of(chip, struct max7301, chip); | 55 | struct max7301 *ts = container_of(chip, struct max7301, chip); |
| 56 | u8 *config; | 56 | u8 *config; |
| 57 | u8 offset_bits; | 57 | u8 offset_bits, pin_config; |
| 58 | int ret; | 58 | int ret; |
| 59 | 59 | ||
| 60 | /* First 4 pins are unused in the controller */ | 60 | /* First 4 pins are unused in the controller */ |
| @@ -63,12 +63,15 @@ static int max7301_direction_input(struct gpio_chip *chip, unsigned offset) | |||
| 63 | 63 | ||
| 64 | config = &ts->port_config[offset >> 2]; | 64 | config = &ts->port_config[offset >> 2]; |
| 65 | 65 | ||
| 66 | if (ts->input_pullup_active & BIT(offset)) | ||
| 67 | pin_config = PIN_CONFIG_IN_PULLUP; | ||
| 68 | else | ||
| 69 | pin_config = PIN_CONFIG_IN_WO_PULLUP; | ||
| 70 | |||
| 66 | mutex_lock(&ts->lock); | 71 | mutex_lock(&ts->lock); |
| 67 | 72 | ||
| 68 | /* Standard GPIO API doesn't support pull-ups, has to be extended. | ||
| 69 | * Hard-coding no pollup for now. */ | ||
| 70 | *config = (*config & ~(PIN_CONFIG_MASK << offset_bits)) | 73 | *config = (*config & ~(PIN_CONFIG_MASK << offset_bits)) |
| 71 | | (PIN_CONFIG_IN_WO_PULLUP << offset_bits); | 74 | | (pin_config << offset_bits); |
| 72 | 75 | ||
| 73 | ret = ts->write(ts->dev, 0x08 + (offset >> 2), *config); | 76 | ret = ts->write(ts->dev, 0x08 + (offset >> 2), *config); |
| 74 | 77 | ||
| @@ -177,6 +180,7 @@ int __devinit __max730x_probe(struct max7301 *ts) | |||
| 177 | /* Power up the chip and disable IRQ output */ | 180 | /* Power up the chip and disable IRQ output */ |
| 178 | ts->write(dev, 0x04, 0x01); | 181 | ts->write(dev, 0x04, 0x01); |
| 179 | 182 | ||
| 183 | ts->input_pullup_active = pdata->input_pullup_active; | ||
| 180 | ts->chip.label = dev->driver->name; | 184 | ts->chip.label = dev->driver->name; |
| 181 | 185 | ||
| 182 | ts->chip.direction_input = max7301_direction_input; | 186 | ts->chip.direction_input = max7301_direction_input; |
| @@ -191,13 +195,17 @@ int __devinit __max730x_probe(struct max7301 *ts) | |||
| 191 | ts->chip.owner = THIS_MODULE; | 195 | ts->chip.owner = THIS_MODULE; |
| 192 | 196 | ||
| 193 | /* | 197 | /* |
| 194 | * tristate all pins in hardware and cache the | 198 | * initialize pullups according to platform data and cache the |
| 195 | * register values for later use. | 199 | * register values for later use. |
| 196 | */ | 200 | */ |
| 197 | for (i = 1; i < 8; i++) { | 201 | for (i = 1; i < 8; i++) { |
| 198 | int j; | 202 | int j; |
| 199 | /* 0xAA means input with internal pullup disabled */ | 203 | /* |
| 200 | ts->write(dev, 0x08 + i, 0xAA); | 204 | * initialize port_config with "0xAA", which means |
| 205 | * input with internal pullup disabled. This is needed | ||
| 206 | * to avoid writing zeros (in the inner for loop), | ||
| 207 | * which is not allowed according to the datasheet. | ||
| 208 | */ | ||
| 201 | ts->port_config[i] = 0xAA; | 209 | ts->port_config[i] = 0xAA; |
| 202 | for (j = 0; j < 4; j++) { | 210 | for (j = 0; j < 4; j++) { |
| 203 | int offset = (i - 1) * 4 + j; | 211 | int offset = (i - 1) * 4 + j; |
diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c index 29f19ce3e80f..879b473aab5a 100644 --- a/drivers/gpio/pcf857x.c +++ b/drivers/gpio/pcf857x.c | |||
| @@ -190,7 +190,6 @@ static int pcf857x_probe(struct i2c_client *client, | |||
| 190 | pdata = client->dev.platform_data; | 190 | pdata = client->dev.platform_data; |
| 191 | if (!pdata) { | 191 | if (!pdata) { |
| 192 | dev_dbg(&client->dev, "no platform data\n"); | 192 | dev_dbg(&client->dev, "no platform data\n"); |
| 193 | return -EINVAL; | ||
| 194 | } | 193 | } |
| 195 | 194 | ||
| 196 | /* Allocate, initialize, and register this gpio_chip. */ | 195 | /* Allocate, initialize, and register this gpio_chip. */ |
| @@ -200,7 +199,7 @@ static int pcf857x_probe(struct i2c_client *client, | |||
| 200 | 199 | ||
| 201 | mutex_init(&gpio->lock); | 200 | mutex_init(&gpio->lock); |
| 202 | 201 | ||
| 203 | gpio->chip.base = pdata->gpio_base; | 202 | gpio->chip.base = pdata ? pdata->gpio_base : -1; |
| 204 | gpio->chip.can_sleep = 1; | 203 | gpio->chip.can_sleep = 1; |
| 205 | gpio->chip.dev = &client->dev; | 204 | gpio->chip.dev = &client->dev; |
| 206 | gpio->chip.owner = THIS_MODULE; | 205 | gpio->chip.owner = THIS_MODULE; |
| @@ -278,7 +277,7 @@ static int pcf857x_probe(struct i2c_client *client, | |||
| 278 | * to zero, our software copy of the "latch" then matches the chip's | 277 | * to zero, our software copy of the "latch" then matches the chip's |
| 279 | * all-ones reset state. Otherwise it flags pins to be driven low. | 278 | * all-ones reset state. Otherwise it flags pins to be driven low. |
| 280 | */ | 279 | */ |
| 281 | gpio->out = ~pdata->n_latch; | 280 | gpio->out = pdata ? ~pdata->n_latch : ~0; |
| 282 | 281 | ||
| 283 | status = gpiochip_add(&gpio->chip); | 282 | status = gpiochip_add(&gpio->chip); |
| 284 | if (status < 0) | 283 | if (status < 0) |
| @@ -299,7 +298,7 @@ static int pcf857x_probe(struct i2c_client *client, | |||
| 299 | /* Let platform code set up the GPIOs and their users. | 298 | /* Let platform code set up the GPIOs and their users. |
| 300 | * Now is the first time anyone could use them. | 299 | * Now is the first time anyone could use them. |
| 301 | */ | 300 | */ |
| 302 | if (pdata->setup) { | 301 | if (pdata && pdata->setup) { |
| 303 | status = pdata->setup(client, | 302 | status = pdata->setup(client, |
| 304 | gpio->chip.base, gpio->chip.ngpio, | 303 | gpio->chip.base, gpio->chip.ngpio, |
| 305 | pdata->context); | 304 | pdata->context); |
| @@ -322,7 +321,7 @@ static int pcf857x_remove(struct i2c_client *client) | |||
| 322 | struct pcf857x *gpio = i2c_get_clientdata(client); | 321 | struct pcf857x *gpio = i2c_get_clientdata(client); |
| 323 | int status = 0; | 322 | int status = 0; |
| 324 | 323 | ||
| 325 | if (pdata->teardown) { | 324 | if (pdata && pdata->teardown) { |
| 326 | status = pdata->teardown(client, | 325 | status = pdata->teardown(client, |
| 327 | gpio->chip.base, gpio->chip.ngpio, | 326 | gpio->chip.base, gpio->chip.ngpio, |
| 328 | pdata->context); | 327 | pdata->context); |
diff --git a/drivers/gpio/stmpe-gpio.c b/drivers/gpio/stmpe-gpio.c new file mode 100644 index 000000000000..4e1f1b9d5e67 --- /dev/null +++ b/drivers/gpio/stmpe-gpio.c | |||
| @@ -0,0 +1,399 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) ST-Ericsson SA 2010 | ||
| 3 | * | ||
| 4 | * License Terms: GNU General Public License, version 2 | ||
| 5 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/module.h> | ||
| 9 | #include <linux/init.h> | ||
| 10 | #include <linux/platform_device.h> | ||
| 11 | #include <linux/slab.h> | ||
| 12 | #include <linux/gpio.h> | ||
| 13 | #include <linux/irq.h> | ||
| 14 | #include <linux/interrupt.h> | ||
| 15 | #include <linux/mfd/stmpe.h> | ||
| 16 | |||
| 17 | /* | ||
| 18 | * These registers are modified under the irq bus lock and cached to avoid | ||
| 19 | * unnecessary writes in bus_sync_unlock. | ||
| 20 | */ | ||
| 21 | enum { REG_RE, REG_FE, REG_IE }; | ||
| 22 | |||
| 23 | #define CACHE_NR_REGS 3 | ||
| 24 | #define CACHE_NR_BANKS (STMPE_NR_GPIOS / 8) | ||
| 25 | |||
| 26 | struct stmpe_gpio { | ||
| 27 | struct gpio_chip chip; | ||
| 28 | struct stmpe *stmpe; | ||
| 29 | struct device *dev; | ||
| 30 | struct mutex irq_lock; | ||
| 31 | |||
| 32 | int irq_base; | ||
| 33 | |||
| 34 | /* Caches of interrupt control registers for bus_lock */ | ||
| 35 | u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS]; | ||
| 36 | u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS]; | ||
| 37 | }; | ||
| 38 | |||
| 39 | static inline struct stmpe_gpio *to_stmpe_gpio(struct gpio_chip *chip) | ||
| 40 | { | ||
| 41 | return container_of(chip, struct stmpe_gpio, chip); | ||
| 42 | } | ||
| 43 | |||
| 44 | static int stmpe_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
| 45 | { | ||
| 46 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
| 47 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
| 48 | u8 reg = stmpe->regs[STMPE_IDX_GPMR_LSB] - (offset / 8); | ||
| 49 | u8 mask = 1 << (offset % 8); | ||
| 50 | int ret; | ||
| 51 | |||
| 52 | ret = stmpe_reg_read(stmpe, reg); | ||
| 53 | if (ret < 0) | ||
| 54 | return ret; | ||
| 55 | |||
| 56 | return ret & mask; | ||
| 57 | } | ||
| 58 | |||
| 59 | static void stmpe_gpio_set(struct gpio_chip *chip, unsigned offset, int val) | ||
| 60 | { | ||
| 61 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
| 62 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
| 63 | int which = val ? STMPE_IDX_GPSR_LSB : STMPE_IDX_GPCR_LSB; | ||
| 64 | u8 reg = stmpe->regs[which] - (offset / 8); | ||
| 65 | u8 mask = 1 << (offset % 8); | ||
| 66 | |||
| 67 | stmpe_reg_write(stmpe, reg, mask); | ||
| 68 | } | ||
| 69 | |||
| 70 | static int stmpe_gpio_direction_output(struct gpio_chip *chip, | ||
| 71 | unsigned offset, int val) | ||
| 72 | { | ||
| 73 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
| 74 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
| 75 | u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8); | ||
| 76 | u8 mask = 1 << (offset % 8); | ||
| 77 | |||
| 78 | stmpe_gpio_set(chip, offset, val); | ||
| 79 | |||
| 80 | return stmpe_set_bits(stmpe, reg, mask, mask); | ||
| 81 | } | ||
| 82 | |||
| 83 | static int stmpe_gpio_direction_input(struct gpio_chip *chip, | ||
| 84 | unsigned offset) | ||
| 85 | { | ||
| 86 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
| 87 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
| 88 | u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8); | ||
| 89 | u8 mask = 1 << (offset % 8); | ||
| 90 | |||
| 91 | return stmpe_set_bits(stmpe, reg, mask, 0); | ||
| 92 | } | ||
| 93 | |||
| 94 | static int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
| 95 | { | ||
| 96 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
| 97 | |||
| 98 | return stmpe_gpio->irq_base + offset; | ||
| 99 | } | ||
| 100 | |||
| 101 | static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset) | ||
| 102 | { | ||
| 103 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
| 104 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
| 105 | |||
| 106 | return stmpe_set_altfunc(stmpe, 1 << offset, STMPE_BLOCK_GPIO); | ||
| 107 | } | ||
| 108 | |||
| 109 | static struct gpio_chip template_chip = { | ||
| 110 | .label = "stmpe", | ||
| 111 | .owner = THIS_MODULE, | ||
| 112 | .direction_input = stmpe_gpio_direction_input, | ||
| 113 | .get = stmpe_gpio_get, | ||
| 114 | .direction_output = stmpe_gpio_direction_output, | ||
| 115 | .set = stmpe_gpio_set, | ||
| 116 | .to_irq = stmpe_gpio_to_irq, | ||
| 117 | .request = stmpe_gpio_request, | ||
| 118 | .can_sleep = 1, | ||
| 119 | }; | ||
| 120 | |||
| 121 | static int stmpe_gpio_irq_set_type(unsigned int irq, unsigned int type) | ||
| 122 | { | ||
| 123 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
| 124 | int offset = irq - stmpe_gpio->irq_base; | ||
| 125 | int regoffset = offset / 8; | ||
| 126 | int mask = 1 << (offset % 8); | ||
| 127 | |||
| 128 | if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH) | ||
| 129 | return -EINVAL; | ||
| 130 | |||
| 131 | if (type == IRQ_TYPE_EDGE_RISING) | ||
| 132 | stmpe_gpio->regs[REG_RE][regoffset] |= mask; | ||
| 133 | else | ||
| 134 | stmpe_gpio->regs[REG_RE][regoffset] &= ~mask; | ||
| 135 | |||
| 136 | if (type == IRQ_TYPE_EDGE_FALLING) | ||
| 137 | stmpe_gpio->regs[REG_FE][regoffset] |= mask; | ||
| 138 | else | ||
| 139 | stmpe_gpio->regs[REG_FE][regoffset] &= ~mask; | ||
| 140 | |||
| 141 | return 0; | ||
| 142 | } | ||
| 143 | |||
| 144 | static void stmpe_gpio_irq_lock(unsigned int irq) | ||
| 145 | { | ||
| 146 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
| 147 | |||
| 148 | mutex_lock(&stmpe_gpio->irq_lock); | ||
| 149 | } | ||
| 150 | |||
| 151 | static void stmpe_gpio_irq_sync_unlock(unsigned int irq) | ||
| 152 | { | ||
| 153 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
| 154 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
| 155 | int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8); | ||
| 156 | static const u8 regmap[] = { | ||
| 157 | [REG_RE] = STMPE_IDX_GPRER_LSB, | ||
| 158 | [REG_FE] = STMPE_IDX_GPFER_LSB, | ||
| 159 | [REG_IE] = STMPE_IDX_IEGPIOR_LSB, | ||
| 160 | }; | ||
| 161 | int i, j; | ||
| 162 | |||
| 163 | for (i = 0; i < CACHE_NR_REGS; i++) { | ||
| 164 | for (j = 0; j < num_banks; j++) { | ||
| 165 | u8 old = stmpe_gpio->oldregs[i][j]; | ||
| 166 | u8 new = stmpe_gpio->regs[i][j]; | ||
| 167 | |||
| 168 | if (new == old) | ||
| 169 | continue; | ||
| 170 | |||
| 171 | stmpe_gpio->oldregs[i][j] = new; | ||
| 172 | stmpe_reg_write(stmpe, stmpe->regs[regmap[i]] - j, new); | ||
| 173 | } | ||
| 174 | } | ||
| 175 | |||
| 176 | mutex_unlock(&stmpe_gpio->irq_lock); | ||
| 177 | } | ||
| 178 | |||
| 179 | static void stmpe_gpio_irq_mask(unsigned int irq) | ||
| 180 | { | ||
| 181 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
| 182 | int offset = irq - stmpe_gpio->irq_base; | ||
| 183 | int regoffset = offset / 8; | ||
| 184 | int mask = 1 << (offset % 8); | ||
| 185 | |||
| 186 | stmpe_gpio->regs[REG_IE][regoffset] &= ~mask; | ||
| 187 | } | ||
| 188 | |||
| 189 | static void stmpe_gpio_irq_unmask(unsigned int irq) | ||
| 190 | { | ||
| 191 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
| 192 | int offset = irq - stmpe_gpio->irq_base; | ||
| 193 | int regoffset = offset / 8; | ||
| 194 | int mask = 1 << (offset % 8); | ||
| 195 | |||
| 196 | stmpe_gpio->regs[REG_IE][regoffset] |= mask; | ||
| 197 | } | ||
| 198 | |||
| 199 | static struct irq_chip stmpe_gpio_irq_chip = { | ||
| 200 | .name = "stmpe-gpio", | ||
| 201 | .bus_lock = stmpe_gpio_irq_lock, | ||
| 202 | .bus_sync_unlock = stmpe_gpio_irq_sync_unlock, | ||
| 203 | .mask = stmpe_gpio_irq_mask, | ||
| 204 | .unmask = stmpe_gpio_irq_unmask, | ||
| 205 | .set_type = stmpe_gpio_irq_set_type, | ||
| 206 | }; | ||
| 207 | |||
| 208 | static irqreturn_t stmpe_gpio_irq(int irq, void *dev) | ||
| 209 | { | ||
| 210 | struct stmpe_gpio *stmpe_gpio = dev; | ||
| 211 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
| 212 | u8 statmsbreg = stmpe->regs[STMPE_IDX_ISGPIOR_MSB]; | ||
| 213 | int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8); | ||
| 214 | u8 status[num_banks]; | ||
| 215 | int ret; | ||
| 216 | int i; | ||
| 217 | |||
| 218 | ret = stmpe_block_read(stmpe, statmsbreg, num_banks, status); | ||
| 219 | if (ret < 0) | ||
| 220 | return IRQ_NONE; | ||
| 221 | |||
| 222 | for (i = 0; i < num_banks; i++) { | ||
| 223 | int bank = num_banks - i - 1; | ||
| 224 | unsigned int enabled = stmpe_gpio->regs[REG_IE][bank]; | ||
| 225 | unsigned int stat = status[i]; | ||
| 226 | |||
| 227 | stat &= enabled; | ||
| 228 | if (!stat) | ||
| 229 | continue; | ||
| 230 | |||
| 231 | while (stat) { | ||
| 232 | int bit = __ffs(stat); | ||
| 233 | int line = bank * 8 + bit; | ||
| 234 | |||
| 235 | handle_nested_irq(stmpe_gpio->irq_base + line); | ||
| 236 | stat &= ~(1 << bit); | ||
| 237 | } | ||
| 238 | |||
| 239 | stmpe_reg_write(stmpe, statmsbreg + i, status[i]); | ||
| 240 | stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_GPEDR_MSB] + i, | ||
| 241 | status[i]); | ||
| 242 | } | ||
| 243 | |||
| 244 | return IRQ_HANDLED; | ||
| 245 | } | ||
| 246 | |||
| 247 | static int __devinit stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio) | ||
| 248 | { | ||
| 249 | int base = stmpe_gpio->irq_base; | ||
| 250 | int irq; | ||
| 251 | |||
| 252 | for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) { | ||
| 253 | set_irq_chip_data(irq, stmpe_gpio); | ||
| 254 | set_irq_chip_and_handler(irq, &stmpe_gpio_irq_chip, | ||
| 255 | handle_simple_irq); | ||
| 256 | set_irq_nested_thread(irq, 1); | ||
| 257 | #ifdef CONFIG_ARM | ||
| 258 | set_irq_flags(irq, IRQF_VALID); | ||
| 259 | #else | ||
| 260 | set_irq_noprobe(irq); | ||
| 261 | #endif | ||
| 262 | } | ||
| 263 | |||
| 264 | return 0; | ||
| 265 | } | ||
| 266 | |||
| 267 | static void stmpe_gpio_irq_remove(struct stmpe_gpio *stmpe_gpio) | ||
| 268 | { | ||
| 269 | int base = stmpe_gpio->irq_base; | ||
| 270 | int irq; | ||
| 271 | |||
| 272 | for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) { | ||
| 273 | #ifdef CONFIG_ARM | ||
| 274 | set_irq_flags(irq, 0); | ||
| 275 | #endif | ||
| 276 | set_irq_chip_and_handler(irq, NULL, NULL); | ||
| 277 | set_irq_chip_data(irq, NULL); | ||
| 278 | } | ||
| 279 | } | ||
| 280 | |||
| 281 | static int __devinit stmpe_gpio_probe(struct platform_device *pdev) | ||
| 282 | { | ||
| 283 | struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); | ||
| 284 | struct stmpe_gpio_platform_data *pdata; | ||
| 285 | struct stmpe_gpio *stmpe_gpio; | ||
| 286 | int ret; | ||
| 287 | int irq; | ||
| 288 | |||
| 289 | pdata = stmpe->pdata->gpio; | ||
| 290 | if (!pdata) | ||
| 291 | return -ENODEV; | ||
| 292 | |||
| 293 | irq = platform_get_irq(pdev, 0); | ||
| 294 | if (irq < 0) | ||
| 295 | return irq; | ||
| 296 | |||
| 297 | stmpe_gpio = kzalloc(sizeof(struct stmpe_gpio), GFP_KERNEL); | ||
| 298 | if (!stmpe_gpio) | ||
| 299 | return -ENOMEM; | ||
| 300 | |||
| 301 | mutex_init(&stmpe_gpio->irq_lock); | ||
| 302 | |||
| 303 | stmpe_gpio->dev = &pdev->dev; | ||
| 304 | stmpe_gpio->stmpe = stmpe; | ||
| 305 | |||
| 306 | stmpe_gpio->chip = template_chip; | ||
| 307 | stmpe_gpio->chip.ngpio = stmpe->num_gpios; | ||
| 308 | stmpe_gpio->chip.dev = &pdev->dev; | ||
| 309 | stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1; | ||
| 310 | |||
| 311 | stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0); | ||
| 312 | |||
| 313 | ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO); | ||
| 314 | if (ret) | ||
| 315 | return ret; | ||
| 316 | |||
| 317 | ret = stmpe_gpio_irq_init(stmpe_gpio); | ||
| 318 | if (ret) | ||
| 319 | goto out_free; | ||
| 320 | |||
| 321 | ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq, IRQF_ONESHOT, | ||
| 322 | "stmpe-gpio", stmpe_gpio); | ||
| 323 | if (ret) { | ||
| 324 | dev_err(&pdev->dev, "unable to get irq: %d\n", ret); | ||
| 325 | goto out_removeirq; | ||
| 326 | } | ||
| 327 | |||
| 328 | ret = gpiochip_add(&stmpe_gpio->chip); | ||
| 329 | if (ret) { | ||
| 330 | dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); | ||
| 331 | goto out_freeirq; | ||
| 332 | } | ||
| 333 | |||
| 334 | if (pdata && pdata->setup) | ||
| 335 | pdata->setup(stmpe, stmpe_gpio->chip.base); | ||
| 336 | |||
| 337 | platform_set_drvdata(pdev, stmpe_gpio); | ||
| 338 | |||
| 339 | return 0; | ||
| 340 | |||
| 341 | out_freeirq: | ||
| 342 | free_irq(irq, stmpe_gpio); | ||
| 343 | out_removeirq: | ||
| 344 | stmpe_gpio_irq_remove(stmpe_gpio); | ||
| 345 | out_free: | ||
| 346 | kfree(stmpe_gpio); | ||
| 347 | return ret; | ||
| 348 | } | ||
| 349 | |||
| 350 | static int __devexit stmpe_gpio_remove(struct platform_device *pdev) | ||
| 351 | { | ||
| 352 | struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev); | ||
| 353 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
| 354 | struct stmpe_gpio_platform_data *pdata = stmpe->pdata->gpio; | ||
| 355 | int irq = platform_get_irq(pdev, 0); | ||
| 356 | int ret; | ||
| 357 | |||
| 358 | if (pdata && pdata->remove) | ||
| 359 | pdata->remove(stmpe, stmpe_gpio->chip.base); | ||
| 360 | |||
| 361 | ret = gpiochip_remove(&stmpe_gpio->chip); | ||
| 362 | if (ret < 0) { | ||
| 363 | dev_err(stmpe_gpio->dev, | ||
| 364 | "unable to remove gpiochip: %d\n", ret); | ||
| 365 | return ret; | ||
| 366 | } | ||
| 367 | |||
| 368 | stmpe_disable(stmpe, STMPE_BLOCK_GPIO); | ||
| 369 | |||
| 370 | free_irq(irq, stmpe_gpio); | ||
| 371 | stmpe_gpio_irq_remove(stmpe_gpio); | ||
| 372 | platform_set_drvdata(pdev, NULL); | ||
| 373 | kfree(stmpe_gpio); | ||
| 374 | |||
| 375 | return 0; | ||
| 376 | } | ||
| 377 | |||
| 378 | static struct platform_driver stmpe_gpio_driver = { | ||
| 379 | .driver.name = "stmpe-gpio", | ||
| 380 | .driver.owner = THIS_MODULE, | ||
| 381 | .probe = stmpe_gpio_probe, | ||
| 382 | .remove = __devexit_p(stmpe_gpio_remove), | ||
| 383 | }; | ||
| 384 | |||
| 385 | static int __init stmpe_gpio_init(void) | ||
| 386 | { | ||
| 387 | return platform_driver_register(&stmpe_gpio_driver); | ||
| 388 | } | ||
| 389 | subsys_initcall(stmpe_gpio_init); | ||
| 390 | |||
| 391 | static void __exit stmpe_gpio_exit(void) | ||
| 392 | { | ||
| 393 | platform_driver_unregister(&stmpe_gpio_driver); | ||
| 394 | } | ||
| 395 | module_exit(stmpe_gpio_exit); | ||
| 396 | |||
| 397 | MODULE_LICENSE("GPL v2"); | ||
| 398 | MODULE_DESCRIPTION("STMPExxxx GPIO driver"); | ||
| 399 | MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>"); | ||
diff --git a/drivers/gpio/sx150x.c b/drivers/gpio/sx150x.c new file mode 100644 index 000000000000..b42f42ca70c3 --- /dev/null +++ b/drivers/gpio/sx150x.c | |||
| @@ -0,0 +1,645 @@ | |||
| 1 | /* Copyright (c) 2010, Code Aurora Forum. All rights reserved. | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License version 2 and | ||
| 5 | * only version 2 as published by the Free Software Foundation. | ||
| 6 | * | ||
| 7 | * This program is distributed in the hope that it will be useful, | ||
| 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 10 | * GNU General Public License for more details. | ||
| 11 | * | ||
| 12 | * You should have received a copy of the GNU General Public License | ||
| 13 | * along with this program; if not, write to the Free Software | ||
| 14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
| 15 | * 02110-1301, USA. | ||
| 16 | */ | ||
| 17 | #include <linux/gpio.h> | ||
| 18 | #include <linux/i2c.h> | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/interrupt.h> | ||
| 21 | #include <linux/irq.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/mutex.h> | ||
| 24 | #include <linux/slab.h> | ||
| 25 | #include <linux/workqueue.h> | ||
| 26 | #include <linux/i2c/sx150x.h> | ||
| 27 | |||
| 28 | struct sx150x_device_data { | ||
| 29 | u8 reg_pullup; | ||
| 30 | u8 reg_pulldn; | ||
| 31 | u8 reg_drain; | ||
| 32 | u8 reg_polarity; | ||
| 33 | u8 reg_dir; | ||
| 34 | u8 reg_data; | ||
| 35 | u8 reg_irq_mask; | ||
| 36 | u8 reg_irq_src; | ||
| 37 | u8 reg_sense; | ||
| 38 | u8 reg_clock; | ||
| 39 | u8 reg_misc; | ||
| 40 | u8 reg_reset; | ||
| 41 | u8 ngpios; | ||
| 42 | }; | ||
| 43 | |||
| 44 | struct sx150x_chip { | ||
| 45 | struct gpio_chip gpio_chip; | ||
| 46 | struct i2c_client *client; | ||
| 47 | const struct sx150x_device_data *dev_cfg; | ||
| 48 | int irq_summary; | ||
| 49 | int irq_base; | ||
| 50 | u32 irq_sense; | ||
| 51 | unsigned long irq_set_type_pending; | ||
| 52 | struct irq_chip irq_chip; | ||
| 53 | struct mutex lock; | ||
| 54 | }; | ||
| 55 | |||
| 56 | static const struct sx150x_device_data sx150x_devices[] = { | ||
| 57 | [0] = { /* sx1508q */ | ||
| 58 | .reg_pullup = 0x03, | ||
| 59 | .reg_pulldn = 0x04, | ||
| 60 | .reg_drain = 0x05, | ||
| 61 | .reg_polarity = 0x06, | ||
| 62 | .reg_dir = 0x07, | ||
| 63 | .reg_data = 0x08, | ||
| 64 | .reg_irq_mask = 0x09, | ||
| 65 | .reg_irq_src = 0x0c, | ||
| 66 | .reg_sense = 0x0b, | ||
| 67 | .reg_clock = 0x0f, | ||
| 68 | .reg_misc = 0x10, | ||
| 69 | .reg_reset = 0x7d, | ||
| 70 | .ngpios = 8 | ||
| 71 | }, | ||
| 72 | [1] = { /* sx1509q */ | ||
| 73 | .reg_pullup = 0x07, | ||
| 74 | .reg_pulldn = 0x09, | ||
| 75 | .reg_drain = 0x0b, | ||
| 76 | .reg_polarity = 0x0d, | ||
| 77 | .reg_dir = 0x0f, | ||
| 78 | .reg_data = 0x11, | ||
| 79 | .reg_irq_mask = 0x13, | ||
| 80 | .reg_irq_src = 0x19, | ||
| 81 | .reg_sense = 0x17, | ||
| 82 | .reg_clock = 0x1e, | ||
| 83 | .reg_misc = 0x1f, | ||
| 84 | .reg_reset = 0x7d, | ||
| 85 | .ngpios = 16 | ||
| 86 | }, | ||
| 87 | }; | ||
| 88 | |||
| 89 | static const struct i2c_device_id sx150x_id[] = { | ||
| 90 | {"sx1508q", 0}, | ||
| 91 | {"sx1509q", 1}, | ||
| 92 | {} | ||
| 93 | }; | ||
| 94 | MODULE_DEVICE_TABLE(i2c, sx150x_id); | ||
| 95 | |||
| 96 | static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val) | ||
| 97 | { | ||
| 98 | s32 err = i2c_smbus_write_byte_data(client, reg, val); | ||
| 99 | |||
| 100 | if (err < 0) | ||
| 101 | dev_warn(&client->dev, | ||
| 102 | "i2c write fail: can't write %02x to %02x: %d\n", | ||
| 103 | val, reg, err); | ||
| 104 | return err; | ||
| 105 | } | ||
| 106 | |||
| 107 | static s32 sx150x_i2c_read(struct i2c_client *client, u8 reg, u8 *val) | ||
| 108 | { | ||
| 109 | s32 err = i2c_smbus_read_byte_data(client, reg); | ||
| 110 | |||
| 111 | if (err >= 0) | ||
| 112 | *val = err; | ||
| 113 | else | ||
| 114 | dev_warn(&client->dev, | ||
| 115 | "i2c read fail: can't read from %02x: %d\n", | ||
| 116 | reg, err); | ||
| 117 | return err; | ||
| 118 | } | ||
| 119 | |||
| 120 | static inline bool offset_is_oscio(struct sx150x_chip *chip, unsigned offset) | ||
| 121 | { | ||
| 122 | return (chip->dev_cfg->ngpios == offset); | ||
| 123 | } | ||
| 124 | |||
| 125 | /* | ||
| 126 | * These utility functions solve the common problem of locating and setting | ||
| 127 | * configuration bits. Configuration bits are grouped into registers | ||
| 128 | * whose indexes increase downwards. For example, with eight-bit registers, | ||
| 129 | * sixteen gpios would have their config bits grouped in the following order: | ||
| 130 | * REGISTER N-1 [ f e d c b a 9 8 ] | ||
| 131 | * N [ 7 6 5 4 3 2 1 0 ] | ||
| 132 | * | ||
| 133 | * For multi-bit configurations, the pattern gets wider: | ||
| 134 | * REGISTER N-3 [ f f e e d d c c ] | ||
| 135 | * N-2 [ b b a a 9 9 8 8 ] | ||
| 136 | * N-1 [ 7 7 6 6 5 5 4 4 ] | ||
| 137 | * N [ 3 3 2 2 1 1 0 0 ] | ||
| 138 | * | ||
| 139 | * Given the address of the starting register 'N', the index of the gpio | ||
| 140 | * whose configuration we seek to change, and the width in bits of that | ||
| 141 | * configuration, these functions allow us to locate the correct | ||
| 142 | * register and mask the correct bits. | ||
| 143 | */ | ||
| 144 | static inline void sx150x_find_cfg(u8 offset, u8 width, | ||
| 145 | u8 *reg, u8 *mask, u8 *shift) | ||
| 146 | { | ||
| 147 | *reg -= offset * width / 8; | ||
| 148 | *mask = (1 << width) - 1; | ||
| 149 | *shift = (offset * width) % 8; | ||
| 150 | *mask <<= *shift; | ||
| 151 | } | ||
| 152 | |||
| 153 | static s32 sx150x_write_cfg(struct sx150x_chip *chip, | ||
| 154 | u8 offset, u8 width, u8 reg, u8 val) | ||
| 155 | { | ||
| 156 | u8 mask; | ||
| 157 | u8 data; | ||
| 158 | u8 shift; | ||
| 159 | s32 err; | ||
| 160 | |||
| 161 | sx150x_find_cfg(offset, width, ®, &mask, &shift); | ||
| 162 | err = sx150x_i2c_read(chip->client, reg, &data); | ||
| 163 | if (err < 0) | ||
| 164 | return err; | ||
| 165 | |||
| 166 | data &= ~mask; | ||
| 167 | data |= (val << shift) & mask; | ||
| 168 | return sx150x_i2c_write(chip->client, reg, data); | ||
| 169 | } | ||
| 170 | |||
| 171 | static int sx150x_get_io(struct sx150x_chip *chip, unsigned offset) | ||
| 172 | { | ||
| 173 | u8 reg = chip->dev_cfg->reg_data; | ||
| 174 | u8 mask; | ||
| 175 | u8 data; | ||
| 176 | u8 shift; | ||
| 177 | s32 err; | ||
| 178 | |||
| 179 | sx150x_find_cfg(offset, 1, ®, &mask, &shift); | ||
| 180 | err = sx150x_i2c_read(chip->client, reg, &data); | ||
| 181 | if (err >= 0) | ||
| 182 | err = (data & mask) != 0 ? 1 : 0; | ||
| 183 | |||
| 184 | return err; | ||
| 185 | } | ||
| 186 | |||
| 187 | static void sx150x_set_oscio(struct sx150x_chip *chip, int val) | ||
| 188 | { | ||
| 189 | sx150x_i2c_write(chip->client, | ||
| 190 | chip->dev_cfg->reg_clock, | ||
| 191 | (val ? 0x1f : 0x10)); | ||
| 192 | } | ||
| 193 | |||
| 194 | static void sx150x_set_io(struct sx150x_chip *chip, unsigned offset, int val) | ||
| 195 | { | ||
| 196 | sx150x_write_cfg(chip, | ||
| 197 | offset, | ||
| 198 | 1, | ||
| 199 | chip->dev_cfg->reg_data, | ||
| 200 | (val ? 1 : 0)); | ||
| 201 | } | ||
| 202 | |||
| 203 | static int sx150x_io_input(struct sx150x_chip *chip, unsigned offset) | ||
| 204 | { | ||
| 205 | return sx150x_write_cfg(chip, | ||
| 206 | offset, | ||
| 207 | 1, | ||
| 208 | chip->dev_cfg->reg_dir, | ||
| 209 | 1); | ||
| 210 | } | ||
| 211 | |||
| 212 | static int sx150x_io_output(struct sx150x_chip *chip, unsigned offset, int val) | ||
| 213 | { | ||
| 214 | int err; | ||
| 215 | |||
| 216 | err = sx150x_write_cfg(chip, | ||
| 217 | offset, | ||
| 218 | 1, | ||
| 219 | chip->dev_cfg->reg_data, | ||
| 220 | (val ? 1 : 0)); | ||
| 221 | if (err >= 0) | ||
| 222 | err = sx150x_write_cfg(chip, | ||
| 223 | offset, | ||
| 224 | 1, | ||
| 225 | chip->dev_cfg->reg_dir, | ||
| 226 | 0); | ||
| 227 | return err; | ||
| 228 | } | ||
| 229 | |||
| 230 | static int sx150x_gpio_get(struct gpio_chip *gc, unsigned offset) | ||
| 231 | { | ||
| 232 | struct sx150x_chip *chip; | ||
| 233 | int status = -EINVAL; | ||
| 234 | |||
| 235 | chip = container_of(gc, struct sx150x_chip, gpio_chip); | ||
| 236 | |||
| 237 | if (!offset_is_oscio(chip, offset)) { | ||
| 238 | mutex_lock(&chip->lock); | ||
| 239 | status = sx150x_get_io(chip, offset); | ||
| 240 | mutex_unlock(&chip->lock); | ||
| 241 | } | ||
| 242 | |||
| 243 | return status; | ||
| 244 | } | ||
| 245 | |||
| 246 | static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val) | ||
| 247 | { | ||
| 248 | struct sx150x_chip *chip; | ||
| 249 | |||
| 250 | chip = container_of(gc, struct sx150x_chip, gpio_chip); | ||
| 251 | |||
| 252 | mutex_lock(&chip->lock); | ||
| 253 | if (offset_is_oscio(chip, offset)) | ||
| 254 | sx150x_set_oscio(chip, val); | ||
| 255 | else | ||
| 256 | sx150x_set_io(chip, offset, val); | ||
| 257 | mutex_unlock(&chip->lock); | ||
| 258 | } | ||
| 259 | |||
| 260 | static int sx150x_gpio_direction_input(struct gpio_chip *gc, unsigned offset) | ||
| 261 | { | ||
| 262 | struct sx150x_chip *chip; | ||
| 263 | int status = -EINVAL; | ||
| 264 | |||
| 265 | chip = container_of(gc, struct sx150x_chip, gpio_chip); | ||
| 266 | |||
| 267 | if (!offset_is_oscio(chip, offset)) { | ||
| 268 | mutex_lock(&chip->lock); | ||
| 269 | status = sx150x_io_input(chip, offset); | ||
| 270 | mutex_unlock(&chip->lock); | ||
| 271 | } | ||
| 272 | return status; | ||
| 273 | } | ||
| 274 | |||
| 275 | static int sx150x_gpio_direction_output(struct gpio_chip *gc, | ||
| 276 | unsigned offset, | ||
| 277 | int val) | ||
| 278 | { | ||
| 279 | struct sx150x_chip *chip; | ||
| 280 | int status = 0; | ||
| 281 | |||
| 282 | chip = container_of(gc, struct sx150x_chip, gpio_chip); | ||
| 283 | |||
| 284 | if (!offset_is_oscio(chip, offset)) { | ||
| 285 | mutex_lock(&chip->lock); | ||
| 286 | status = sx150x_io_output(chip, offset, val); | ||
| 287 | mutex_unlock(&chip->lock); | ||
| 288 | } | ||
| 289 | return status; | ||
| 290 | } | ||
| 291 | |||
| 292 | static int sx150x_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | ||
| 293 | { | ||
| 294 | struct sx150x_chip *chip; | ||
| 295 | |||
| 296 | chip = container_of(gc, struct sx150x_chip, gpio_chip); | ||
| 297 | |||
| 298 | if (offset >= chip->dev_cfg->ngpios) | ||
| 299 | return -EINVAL; | ||
| 300 | |||
| 301 | if (chip->irq_base < 0) | ||
| 302 | return -EINVAL; | ||
| 303 | |||
| 304 | return chip->irq_base + offset; | ||
| 305 | } | ||
| 306 | |||
| 307 | static void sx150x_irq_mask(unsigned int irq) | ||
| 308 | { | ||
| 309 | struct irq_chip *ic = get_irq_chip(irq); | ||
| 310 | struct sx150x_chip *chip; | ||
| 311 | unsigned n; | ||
| 312 | |||
| 313 | chip = container_of(ic, struct sx150x_chip, irq_chip); | ||
| 314 | n = irq - chip->irq_base; | ||
| 315 | |||
| 316 | sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1); | ||
| 317 | sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0); | ||
| 318 | } | ||
| 319 | |||
| 320 | static void sx150x_irq_unmask(unsigned int irq) | ||
| 321 | { | ||
| 322 | struct irq_chip *ic = get_irq_chip(irq); | ||
| 323 | struct sx150x_chip *chip; | ||
| 324 | unsigned n; | ||
| 325 | |||
| 326 | chip = container_of(ic, struct sx150x_chip, irq_chip); | ||
| 327 | n = irq - chip->irq_base; | ||
| 328 | |||
| 329 | sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0); | ||
| 330 | sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, | ||
| 331 | chip->irq_sense >> (n * 2)); | ||
| 332 | } | ||
| 333 | |||
| 334 | static int sx150x_irq_set_type(unsigned int irq, unsigned int flow_type) | ||
| 335 | { | ||
| 336 | struct irq_chip *ic = get_irq_chip(irq); | ||
| 337 | struct sx150x_chip *chip; | ||
| 338 | unsigned n, val = 0; | ||
| 339 | |||
| 340 | if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) | ||
| 341 | return -EINVAL; | ||
| 342 | |||
| 343 | chip = container_of(ic, struct sx150x_chip, irq_chip); | ||
| 344 | n = irq - chip->irq_base; | ||
| 345 | |||
| 346 | if (flow_type & IRQ_TYPE_EDGE_RISING) | ||
| 347 | val |= 0x1; | ||
| 348 | if (flow_type & IRQ_TYPE_EDGE_FALLING) | ||
| 349 | val |= 0x2; | ||
| 350 | |||
| 351 | chip->irq_sense &= ~(3UL << (n * 2)); | ||
| 352 | chip->irq_sense |= val << (n * 2); | ||
| 353 | chip->irq_set_type_pending |= BIT(n); | ||
| 354 | return 0; | ||
| 355 | } | ||
| 356 | |||
| 357 | static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id) | ||
| 358 | { | ||
| 359 | struct sx150x_chip *chip = (struct sx150x_chip *)dev_id; | ||
| 360 | unsigned nhandled = 0; | ||
| 361 | unsigned sub_irq; | ||
| 362 | unsigned n; | ||
| 363 | s32 err; | ||
| 364 | u8 val; | ||
| 365 | int i; | ||
| 366 | |||
| 367 | for (i = (chip->dev_cfg->ngpios / 8) - 1; i >= 0; --i) { | ||
| 368 | err = sx150x_i2c_read(chip->client, | ||
| 369 | chip->dev_cfg->reg_irq_src - i, | ||
| 370 | &val); | ||
| 371 | if (err < 0) | ||
| 372 | continue; | ||
| 373 | |||
| 374 | sx150x_i2c_write(chip->client, | ||
| 375 | chip->dev_cfg->reg_irq_src - i, | ||
| 376 | val); | ||
| 377 | for (n = 0; n < 8; ++n) { | ||
| 378 | if (val & (1 << n)) { | ||
| 379 | sub_irq = chip->irq_base + (i * 8) + n; | ||
| 380 | handle_nested_irq(sub_irq); | ||
| 381 | ++nhandled; | ||
| 382 | } | ||
| 383 | } | ||
| 384 | } | ||
| 385 | |||
| 386 | return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); | ||
| 387 | } | ||
| 388 | |||
| 389 | static void sx150x_irq_bus_lock(unsigned int irq) | ||
| 390 | { | ||
| 391 | struct irq_chip *ic = get_irq_chip(irq); | ||
| 392 | struct sx150x_chip *chip; | ||
| 393 | |||
| 394 | chip = container_of(ic, struct sx150x_chip, irq_chip); | ||
| 395 | |||
| 396 | mutex_lock(&chip->lock); | ||
| 397 | } | ||
| 398 | |||
| 399 | static void sx150x_irq_bus_sync_unlock(unsigned int irq) | ||
| 400 | { | ||
| 401 | struct irq_chip *ic = get_irq_chip(irq); | ||
| 402 | struct sx150x_chip *chip; | ||
| 403 | unsigned n; | ||
| 404 | |||
| 405 | chip = container_of(ic, struct sx150x_chip, irq_chip); | ||
| 406 | |||
| 407 | while (chip->irq_set_type_pending) { | ||
| 408 | n = __ffs(chip->irq_set_type_pending); | ||
| 409 | chip->irq_set_type_pending &= ~BIT(n); | ||
| 410 | if (!(irq_to_desc(n + chip->irq_base)->status & IRQ_MASKED)) | ||
| 411 | sx150x_write_cfg(chip, n, 2, | ||
| 412 | chip->dev_cfg->reg_sense, | ||
| 413 | chip->irq_sense >> (n * 2)); | ||
| 414 | } | ||
| 415 | |||
| 416 | mutex_unlock(&chip->lock); | ||
| 417 | } | ||
| 418 | |||
| 419 | static void sx150x_init_chip(struct sx150x_chip *chip, | ||
| 420 | struct i2c_client *client, | ||
| 421 | kernel_ulong_t driver_data, | ||
| 422 | struct sx150x_platform_data *pdata) | ||
| 423 | { | ||
| 424 | mutex_init(&chip->lock); | ||
| 425 | |||
| 426 | chip->client = client; | ||
| 427 | chip->dev_cfg = &sx150x_devices[driver_data]; | ||
| 428 | chip->gpio_chip.label = client->name; | ||
| 429 | chip->gpio_chip.direction_input = sx150x_gpio_direction_input; | ||
| 430 | chip->gpio_chip.direction_output = sx150x_gpio_direction_output; | ||
| 431 | chip->gpio_chip.get = sx150x_gpio_get; | ||
| 432 | chip->gpio_chip.set = sx150x_gpio_set; | ||
| 433 | chip->gpio_chip.to_irq = sx150x_gpio_to_irq; | ||
| 434 | chip->gpio_chip.base = pdata->gpio_base; | ||
| 435 | chip->gpio_chip.can_sleep = 1; | ||
| 436 | chip->gpio_chip.ngpio = chip->dev_cfg->ngpios; | ||
| 437 | if (pdata->oscio_is_gpo) | ||
| 438 | ++chip->gpio_chip.ngpio; | ||
| 439 | |||
| 440 | chip->irq_chip.name = client->name; | ||
| 441 | chip->irq_chip.mask = sx150x_irq_mask; | ||
| 442 | chip->irq_chip.unmask = sx150x_irq_unmask; | ||
| 443 | chip->irq_chip.set_type = sx150x_irq_set_type; | ||
| 444 | chip->irq_chip.bus_lock = sx150x_irq_bus_lock; | ||
| 445 | chip->irq_chip.bus_sync_unlock = sx150x_irq_bus_sync_unlock; | ||
| 446 | chip->irq_summary = -1; | ||
| 447 | chip->irq_base = -1; | ||
| 448 | chip->irq_sense = 0; | ||
| 449 | chip->irq_set_type_pending = 0; | ||
| 450 | } | ||
| 451 | |||
| 452 | static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg) | ||
| 453 | { | ||
| 454 | int err = 0; | ||
| 455 | unsigned n; | ||
| 456 | |||
| 457 | for (n = 0; err >= 0 && n < (chip->dev_cfg->ngpios / 8); ++n) | ||
| 458 | err = sx150x_i2c_write(chip->client, base - n, cfg >> (n * 8)); | ||
| 459 | return err; | ||
| 460 | } | ||
| 461 | |||
| 462 | static int sx150x_init_hw(struct sx150x_chip *chip, | ||
| 463 | struct sx150x_platform_data *pdata) | ||
| 464 | { | ||
| 465 | int err = 0; | ||
| 466 | |||
| 467 | err = i2c_smbus_write_word_data(chip->client, | ||
| 468 | chip->dev_cfg->reg_reset, | ||
| 469 | 0x3412); | ||
| 470 | if (err < 0) | ||
| 471 | return err; | ||
| 472 | |||
| 473 | err = sx150x_i2c_write(chip->client, | ||
| 474 | chip->dev_cfg->reg_misc, | ||
| 475 | 0x01); | ||
| 476 | if (err < 0) | ||
| 477 | return err; | ||
| 478 | |||
| 479 | err = sx150x_init_io(chip, chip->dev_cfg->reg_pullup, | ||
| 480 | pdata->io_pullup_ena); | ||
| 481 | if (err < 0) | ||
| 482 | return err; | ||
| 483 | |||
| 484 | err = sx150x_init_io(chip, chip->dev_cfg->reg_pulldn, | ||
| 485 | pdata->io_pulldn_ena); | ||
| 486 | if (err < 0) | ||
| 487 | return err; | ||
| 488 | |||
| 489 | err = sx150x_init_io(chip, chip->dev_cfg->reg_drain, | ||
| 490 | pdata->io_open_drain_ena); | ||
| 491 | if (err < 0) | ||
| 492 | return err; | ||
| 493 | |||
| 494 | err = sx150x_init_io(chip, chip->dev_cfg->reg_polarity, | ||
| 495 | pdata->io_polarity); | ||
| 496 | if (err < 0) | ||
| 497 | return err; | ||
| 498 | |||
| 499 | if (pdata->oscio_is_gpo) | ||
| 500 | sx150x_set_oscio(chip, 0); | ||
| 501 | |||
| 502 | return err; | ||
| 503 | } | ||
| 504 | |||
| 505 | static int sx150x_install_irq_chip(struct sx150x_chip *chip, | ||
| 506 | int irq_summary, | ||
| 507 | int irq_base) | ||
| 508 | { | ||
| 509 | int err; | ||
| 510 | unsigned n; | ||
| 511 | unsigned irq; | ||
| 512 | |||
| 513 | chip->irq_summary = irq_summary; | ||
| 514 | chip->irq_base = irq_base; | ||
| 515 | |||
| 516 | for (n = 0; n < chip->dev_cfg->ngpios; ++n) { | ||
| 517 | irq = irq_base + n; | ||
| 518 | set_irq_chip_and_handler(irq, &chip->irq_chip, handle_edge_irq); | ||
| 519 | set_irq_nested_thread(irq, 1); | ||
| 520 | #ifdef CONFIG_ARM | ||
| 521 | set_irq_flags(irq, IRQF_VALID); | ||
| 522 | #else | ||
| 523 | set_irq_noprobe(irq); | ||
| 524 | #endif | ||
| 525 | } | ||
| 526 | |||
| 527 | err = request_threaded_irq(irq_summary, | ||
| 528 | NULL, | ||
| 529 | sx150x_irq_thread_fn, | ||
| 530 | IRQF_SHARED | IRQF_TRIGGER_FALLING, | ||
| 531 | chip->irq_chip.name, | ||
| 532 | chip); | ||
| 533 | if (err < 0) { | ||
| 534 | chip->irq_summary = -1; | ||
| 535 | chip->irq_base = -1; | ||
| 536 | } | ||
| 537 | |||
| 538 | return err; | ||
| 539 | } | ||
| 540 | |||
| 541 | static void sx150x_remove_irq_chip(struct sx150x_chip *chip) | ||
| 542 | { | ||
| 543 | unsigned n; | ||
| 544 | unsigned irq; | ||
| 545 | |||
| 546 | free_irq(chip->irq_summary, chip); | ||
| 547 | |||
| 548 | for (n = 0; n < chip->dev_cfg->ngpios; ++n) { | ||
| 549 | irq = chip->irq_base + n; | ||
| 550 | set_irq_handler(irq, NULL); | ||
| 551 | set_irq_chip(irq, NULL); | ||
| 552 | } | ||
| 553 | } | ||
| 554 | |||
| 555 | static int __devinit sx150x_probe(struct i2c_client *client, | ||
| 556 | const struct i2c_device_id *id) | ||
| 557 | { | ||
| 558 | static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA | | ||
| 559 | I2C_FUNC_SMBUS_WRITE_WORD_DATA; | ||
| 560 | struct sx150x_platform_data *pdata; | ||
| 561 | struct sx150x_chip *chip; | ||
| 562 | int rc; | ||
| 563 | |||
| 564 | pdata = client->dev.platform_data; | ||
| 565 | if (!pdata) | ||
| 566 | return -EINVAL; | ||
| 567 | |||
| 568 | if (!i2c_check_functionality(client->adapter, i2c_funcs)) | ||
| 569 | return -ENOSYS; | ||
| 570 | |||
| 571 | chip = kzalloc(sizeof(struct sx150x_chip), GFP_KERNEL); | ||
| 572 | if (!chip) | ||
| 573 | return -ENOMEM; | ||
| 574 | |||
| 575 | sx150x_init_chip(chip, client, id->driver_data, pdata); | ||
| 576 | rc = sx150x_init_hw(chip, pdata); | ||
| 577 | if (rc < 0) | ||
| 578 | goto probe_fail_pre_gpiochip_add; | ||
| 579 | |||
| 580 | rc = gpiochip_add(&chip->gpio_chip); | ||
| 581 | if (rc < 0) | ||
| 582 | goto probe_fail_pre_gpiochip_add; | ||
| 583 | |||
| 584 | if (pdata->irq_summary >= 0) { | ||
| 585 | rc = sx150x_install_irq_chip(chip, | ||
| 586 | pdata->irq_summary, | ||
| 587 | pdata->irq_base); | ||
| 588 | if (rc < 0) | ||
| 589 | goto probe_fail_post_gpiochip_add; | ||
| 590 | } | ||
| 591 | |||
| 592 | i2c_set_clientdata(client, chip); | ||
| 593 | |||
| 594 | return 0; | ||
| 595 | probe_fail_post_gpiochip_add: | ||
| 596 | WARN_ON(gpiochip_remove(&chip->gpio_chip) < 0); | ||
| 597 | probe_fail_pre_gpiochip_add: | ||
| 598 | kfree(chip); | ||
| 599 | return rc; | ||
| 600 | } | ||
| 601 | |||
| 602 | static int __devexit sx150x_remove(struct i2c_client *client) | ||
| 603 | { | ||
| 604 | struct sx150x_chip *chip; | ||
| 605 | int rc; | ||
| 606 | |||
| 607 | chip = i2c_get_clientdata(client); | ||
| 608 | rc = gpiochip_remove(&chip->gpio_chip); | ||
| 609 | if (rc < 0) | ||
| 610 | return rc; | ||
| 611 | |||
| 612 | if (chip->irq_summary >= 0) | ||
| 613 | sx150x_remove_irq_chip(chip); | ||
| 614 | |||
| 615 | kfree(chip); | ||
| 616 | |||
| 617 | return 0; | ||
| 618 | } | ||
| 619 | |||
| 620 | static struct i2c_driver sx150x_driver = { | ||
| 621 | .driver = { | ||
| 622 | .name = "sx150x", | ||
| 623 | .owner = THIS_MODULE | ||
| 624 | }, | ||
| 625 | .probe = sx150x_probe, | ||
| 626 | .remove = __devexit_p(sx150x_remove), | ||
| 627 | .id_table = sx150x_id, | ||
| 628 | }; | ||
| 629 | |||
| 630 | static int __init sx150x_init(void) | ||
| 631 | { | ||
| 632 | return i2c_add_driver(&sx150x_driver); | ||
| 633 | } | ||
| 634 | subsys_initcall(sx150x_init); | ||
| 635 | |||
| 636 | static void __exit sx150x_exit(void) | ||
| 637 | { | ||
| 638 | return i2c_del_driver(&sx150x_driver); | ||
| 639 | } | ||
| 640 | module_exit(sx150x_exit); | ||
| 641 | |||
| 642 | MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>"); | ||
| 643 | MODULE_DESCRIPTION("Driver for Semtech SX150X I2C GPIO Expanders"); | ||
| 644 | MODULE_LICENSE("GPL v2"); | ||
| 645 | MODULE_ALIAS("i2c:sx150x"); | ||
diff --git a/drivers/gpio/wm831x-gpio.c b/drivers/gpio/wm831x-gpio.c index 1fa449a1a4cb..309644cf4d9b 100644 --- a/drivers/gpio/wm831x-gpio.c +++ b/drivers/gpio/wm831x-gpio.c | |||
| @@ -108,6 +108,37 @@ static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | |||
| 108 | return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset; | 108 | return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset; |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, | ||
| 112 | unsigned debounce) | ||
| 113 | { | ||
| 114 | struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); | ||
| 115 | struct wm831x *wm831x = wm831x_gpio->wm831x; | ||
| 116 | int reg = WM831X_GPIO1_CONTROL + offset; | ||
| 117 | int ret, fn; | ||
| 118 | |||
| 119 | ret = wm831x_reg_read(wm831x, reg); | ||
| 120 | if (ret < 0) | ||
| 121 | return ret; | ||
| 122 | |||
| 123 | switch (ret & WM831X_GPN_FN_MASK) { | ||
| 124 | case 0: | ||
| 125 | case 1: | ||
| 126 | break; | ||
| 127 | default: | ||
| 128 | /* Not in GPIO mode */ | ||
| 129 | return -EBUSY; | ||
| 130 | } | ||
| 131 | |||
| 132 | if (debounce >= 32 && debounce <= 64) | ||
| 133 | fn = 0; | ||
| 134 | else if (debounce >= 4000 && debounce <= 8000) | ||
| 135 | fn = 1; | ||
| 136 | else | ||
| 137 | return -EINVAL; | ||
| 138 | |||
| 139 | return wm831x_set_bits(wm831x, reg, WM831X_GPN_FN_MASK, fn); | ||
| 140 | } | ||
| 141 | |||
| 111 | #ifdef CONFIG_DEBUG_FS | 142 | #ifdef CONFIG_DEBUG_FS |
| 112 | static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | 143 | static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) |
| 113 | { | 144 | { |
| @@ -208,6 +239,7 @@ static struct gpio_chip template_chip = { | |||
| 208 | .direction_output = wm831x_gpio_direction_out, | 239 | .direction_output = wm831x_gpio_direction_out, |
| 209 | .set = wm831x_gpio_set, | 240 | .set = wm831x_gpio_set, |
| 210 | .to_irq = wm831x_gpio_to_irq, | 241 | .to_irq = wm831x_gpio_to_irq, |
| 242 | .set_debounce = wm831x_gpio_set_debounce, | ||
| 211 | .dbg_show = wm831x_gpio_dbg_show, | 243 | .dbg_show = wm831x_gpio_dbg_show, |
| 212 | .can_sleep = 1, | 244 | .can_sleep = 1, |
| 213 | }; | 245 | }; |
