diff options
author | Semen Protsenko <semen.protsenko@globallogic.com> | 2015-01-13 08:41:43 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2015-01-15 11:53:56 -0500 |
commit | 479f8a5744d8141e95ef40ab364ae2d3648848ef (patch) | |
tree | f0c06f8e2492517c6bb303a56351916fe61ccf13 /drivers/gpio | |
parent | 43c4bcf9425ef596f9651bd0c647065dc5e9ad50 (diff) |
gpio: max732x: Rewrite IRQ code to use irq_domain API
Signed-off-by: Semen Protsenko <semen.protsenko@globallogic.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/Kconfig | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-max732x.c | 100 |
2 files changed, 66 insertions, 35 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 192f97396d12..d24492c59bf9 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -528,6 +528,7 @@ config GPIO_MAX7300 | |||
528 | config GPIO_MAX732X | 528 | config GPIO_MAX732X |
529 | tristate "MAX7319, MAX7320-7327 I2C Port Expanders" | 529 | tristate "MAX7319, MAX7320-7327 I2C Port Expanders" |
530 | depends on I2C | 530 | depends on I2C |
531 | select IRQ_DOMAIN | ||
531 | help | 532 | help |
532 | Say yes here to support the MAX7319, MAX7320-7327 series of I2C | 533 | Say yes here to support the MAX7319, MAX7320-7327 series of I2C |
533 | Port Expanders. Each IO port on these chips has a fixed role of | 534 | Port Expanders. Each IO port on these chips has a fixed role of |
diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c index a642f780901d..f8f3e8081a89 100644 --- a/drivers/gpio/gpio-max732x.c +++ b/drivers/gpio/gpio-max732x.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/gpio.h> | 19 | #include <linux/gpio.h> |
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
22 | #include <linux/irqdomain.h> | ||
22 | #include <linux/i2c.h> | 23 | #include <linux/i2c.h> |
23 | #include <linux/i2c/max732x.h> | 24 | #include <linux/i2c/max732x.h> |
24 | #include <linux/of.h> | 25 | #include <linux/of.h> |
@@ -149,13 +150,14 @@ struct max732x_chip { | |||
149 | uint8_t reg_out[2]; | 150 | uint8_t reg_out[2]; |
150 | 151 | ||
151 | #ifdef CONFIG_GPIO_MAX732X_IRQ | 152 | #ifdef CONFIG_GPIO_MAX732X_IRQ |
152 | struct mutex irq_lock; | 153 | struct irq_domain *irq_domain; |
153 | int irq_base; | 154 | struct mutex irq_lock; |
154 | uint8_t irq_mask; | 155 | int irq_base; |
155 | uint8_t irq_mask_cur; | 156 | uint8_t irq_mask; |
156 | uint8_t irq_trig_raise; | 157 | uint8_t irq_mask_cur; |
157 | uint8_t irq_trig_fall; | 158 | uint8_t irq_trig_raise; |
158 | uint8_t irq_features; | 159 | uint8_t irq_trig_fall; |
160 | uint8_t irq_features; | ||
159 | #endif | 161 | #endif |
160 | }; | 162 | }; |
161 | 163 | ||
@@ -341,21 +343,27 @@ static int max732x_gpio_to_irq(struct gpio_chip *gc, unsigned off) | |||
341 | struct max732x_chip *chip; | 343 | struct max732x_chip *chip; |
342 | 344 | ||
343 | chip = container_of(gc, struct max732x_chip, gpio_chip); | 345 | chip = container_of(gc, struct max732x_chip, gpio_chip); |
344 | return chip->irq_base + off; | 346 | |
347 | if (chip->irq_domain) { | ||
348 | return irq_create_mapping(chip->irq_domain, | ||
349 | chip->irq_base + off); | ||
350 | } else { | ||
351 | return -ENXIO; | ||
352 | } | ||
345 | } | 353 | } |
346 | 354 | ||
347 | static void max732x_irq_mask(struct irq_data *d) | 355 | static void max732x_irq_mask(struct irq_data *d) |
348 | { | 356 | { |
349 | struct max732x_chip *chip = irq_data_get_irq_chip_data(d); | 357 | struct max732x_chip *chip = irq_data_get_irq_chip_data(d); |
350 | 358 | ||
351 | chip->irq_mask_cur &= ~(1 << (d->irq - chip->irq_base)); | 359 | chip->irq_mask_cur &= ~(1 << d->hwirq); |
352 | } | 360 | } |
353 | 361 | ||
354 | static void max732x_irq_unmask(struct irq_data *d) | 362 | static void max732x_irq_unmask(struct irq_data *d) |
355 | { | 363 | { |
356 | struct max732x_chip *chip = irq_data_get_irq_chip_data(d); | 364 | struct max732x_chip *chip = irq_data_get_irq_chip_data(d); |
357 | 365 | ||
358 | chip->irq_mask_cur |= 1 << (d->irq - chip->irq_base); | 366 | chip->irq_mask_cur |= 1 << d->hwirq; |
359 | } | 367 | } |
360 | 368 | ||
361 | static void max732x_irq_bus_lock(struct irq_data *d) | 369 | static void max732x_irq_bus_lock(struct irq_data *d) |
@@ -377,7 +385,7 @@ static void max732x_irq_bus_sync_unlock(struct irq_data *d) | |||
377 | static int max732x_irq_set_type(struct irq_data *d, unsigned int type) | 385 | static int max732x_irq_set_type(struct irq_data *d, unsigned int type) |
378 | { | 386 | { |
379 | struct max732x_chip *chip = irq_data_get_irq_chip_data(d); | 387 | struct max732x_chip *chip = irq_data_get_irq_chip_data(d); |
380 | uint16_t off = d->irq - chip->irq_base; | 388 | uint16_t off = d->hwirq; |
381 | uint16_t mask = 1 << off; | 389 | uint16_t mask = 1 << off; |
382 | 390 | ||
383 | if (!(mask & chip->dir_input)) { | 391 | if (!(mask & chip->dir_input)) { |
@@ -458,7 +466,7 @@ static irqreturn_t max732x_irq_handler(int irq, void *devid) | |||
458 | 466 | ||
459 | do { | 467 | do { |
460 | level = __ffs(pending); | 468 | level = __ffs(pending); |
461 | handle_nested_irq(level + chip->irq_base); | 469 | handle_nested_irq(irq_find_mapping(chip->irq_domain, level)); |
462 | 470 | ||
463 | pending &= ~(1 << level); | 471 | pending &= ~(1 << level); |
464 | } while (pending); | 472 | } while (pending); |
@@ -466,6 +474,44 @@ static irqreturn_t max732x_irq_handler(int irq, void *devid) | |||
466 | return IRQ_HANDLED; | 474 | return IRQ_HANDLED; |
467 | } | 475 | } |
468 | 476 | ||
477 | static int max732x_irq_map(struct irq_domain *h, unsigned int virq, | ||
478 | irq_hw_number_t hw) | ||
479 | { | ||
480 | struct max732x_chip *chip = h->host_data; | ||
481 | |||
482 | if (!(chip->dir_input & (1 << hw))) { | ||
483 | dev_err(&chip->client->dev, | ||
484 | "Attempt to map output line as IRQ line: %lu\n", | ||
485 | hw); | ||
486 | return -EPERM; | ||
487 | } | ||
488 | |||
489 | irq_set_chip_data(virq, chip); | ||
490 | irq_set_chip_and_handler(virq, &max732x_irq_chip, | ||
491 | handle_edge_irq); | ||
492 | irq_set_nested_thread(virq, 1); | ||
493 | #ifdef CONFIG_ARM | ||
494 | /* ARM needs us to explicitly flag the IRQ as valid | ||
495 | * and will set them noprobe when we do so. */ | ||
496 | set_irq_flags(virq, IRQF_VALID); | ||
497 | #else | ||
498 | irq_set_noprobe(virq); | ||
499 | #endif | ||
500 | |||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | static struct irq_domain_ops max732x_irq_domain_ops = { | ||
505 | .map = max732x_irq_map, | ||
506 | .xlate = irq_domain_xlate_twocell, | ||
507 | }; | ||
508 | |||
509 | static void max732x_irq_teardown(struct max732x_chip *chip) | ||
510 | { | ||
511 | if (chip->client->irq && chip->irq_domain) | ||
512 | irq_domain_remove(chip->irq_domain); | ||
513 | } | ||
514 | |||
469 | static int max732x_irq_setup(struct max732x_chip *chip, | 515 | static int max732x_irq_setup(struct max732x_chip *chip, |
470 | const struct i2c_device_id *id) | 516 | const struct i2c_device_id *id) |
471 | { | 517 | { |
@@ -476,28 +522,17 @@ static int max732x_irq_setup(struct max732x_chip *chip, | |||
476 | 522 | ||
477 | if (((pdata && pdata->irq_base) || client->irq) | 523 | if (((pdata && pdata->irq_base) || client->irq) |
478 | && has_irq != INT_NONE) { | 524 | && has_irq != INT_NONE) { |
479 | int lvl; | ||
480 | |||
481 | if (pdata) | 525 | if (pdata) |
482 | chip->irq_base = pdata->irq_base; | 526 | chip->irq_base = pdata->irq_base; |
483 | chip->irq_features = has_irq; | 527 | chip->irq_features = has_irq; |
484 | mutex_init(&chip->irq_lock); | 528 | mutex_init(&chip->irq_lock); |
485 | 529 | ||
486 | for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) { | 530 | chip->irq_domain = irq_domain_add_simple(client->dev.of_node, |
487 | int irq = lvl + chip->irq_base; | 531 | chip->gpio_chip.ngpio, chip->irq_base, |
488 | 532 | &max732x_irq_domain_ops, chip); | |
489 | if (!(chip->dir_input & (1 << lvl))) | 533 | if (!chip->irq_domain) { |
490 | continue; | 534 | dev_err(&client->dev, "Failed to create IRQ domain\n"); |
491 | 535 | return -ENOMEM; | |
492 | irq_set_chip_data(irq, chip); | ||
493 | irq_set_chip_and_handler(irq, &max732x_irq_chip, | ||
494 | handle_edge_irq); | ||
495 | irq_set_nested_thread(irq, 1); | ||
496 | #ifdef CONFIG_ARM | ||
497 | set_irq_flags(irq, IRQF_VALID); | ||
498 | #else | ||
499 | irq_set_noprobe(irq); | ||
500 | #endif | ||
501 | } | 536 | } |
502 | 537 | ||
503 | ret = request_threaded_irq(client->irq, | 538 | ret = request_threaded_irq(client->irq, |
@@ -517,15 +552,10 @@ static int max732x_irq_setup(struct max732x_chip *chip, | |||
517 | return 0; | 552 | return 0; |
518 | 553 | ||
519 | out_failed: | 554 | out_failed: |
520 | chip->irq_base = 0; | 555 | max732x_irq_teardown(chip); |
521 | return ret; | 556 | return ret; |
522 | } | 557 | } |
523 | 558 | ||
524 | static void max732x_irq_teardown(struct max732x_chip *chip) | ||
525 | { | ||
526 | if (chip->irq_base) | ||
527 | free_irq(chip->client->irq, chip); | ||
528 | } | ||
529 | #else /* CONFIG_GPIO_MAX732X_IRQ */ | 559 | #else /* CONFIG_GPIO_MAX732X_IRQ */ |
530 | static int max732x_irq_setup(struct max732x_chip *chip, | 560 | static int max732x_irq_setup(struct max732x_chip *chip, |
531 | const struct i2c_device_id *id) | 561 | const struct i2c_device_id *id) |