diff options
| -rw-r--r-- | drivers/gpio/gpiolib.c | 33 | ||||
| -rw-r--r-- | include/linux/gpio/driver.h | 1 |
2 files changed, 30 insertions, 4 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index f41cb4f3d715..761013f8b82f 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
| @@ -1399,8 +1399,18 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, | |||
| 1399 | return 0; | 1399 | return 0; |
| 1400 | } | 1400 | } |
| 1401 | 1401 | ||
| 1402 | static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq) | ||
| 1403 | { | ||
| 1404 | #ifdef CONFIG_ARM | ||
| 1405 | set_irq_flags(irq, 0); | ||
| 1406 | #endif | ||
| 1407 | irq_set_chip_and_handler(irq, NULL, NULL); | ||
| 1408 | irq_set_chip_data(irq, NULL); | ||
| 1409 | } | ||
| 1410 | |||
| 1402 | static const struct irq_domain_ops gpiochip_domain_ops = { | 1411 | static const struct irq_domain_ops gpiochip_domain_ops = { |
| 1403 | .map = gpiochip_irq_map, | 1412 | .map = gpiochip_irq_map, |
| 1413 | .unmap = gpiochip_irq_unmap, | ||
| 1404 | /* Virtually all GPIO irqchips are twocell:ed */ | 1414 | /* Virtually all GPIO irqchips are twocell:ed */ |
| 1405 | .xlate = irq_domain_xlate_twocell, | 1415 | .xlate = irq_domain_xlate_twocell, |
| 1406 | }; | 1416 | }; |
| @@ -1438,8 +1448,14 @@ static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset) | |||
| 1438 | */ | 1448 | */ |
| 1439 | static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) | 1449 | static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) |
| 1440 | { | 1450 | { |
| 1441 | if (gpiochip->irqdomain) | 1451 | unsigned int offset; |
| 1452 | |||
| 1453 | /* Remove all IRQ mappings and delete the domain */ | ||
| 1454 | if (gpiochip->irqdomain) { | ||
| 1455 | for (offset = 0; offset < gpiochip->ngpio; offset++) | ||
| 1456 | irq_dispose_mapping(gpiochip->irq_base + offset); | ||
| 1442 | irq_domain_remove(gpiochip->irqdomain); | 1457 | irq_domain_remove(gpiochip->irqdomain); |
| 1458 | } | ||
| 1443 | 1459 | ||
| 1444 | if (gpiochip->irqchip) { | 1460 | if (gpiochip->irqchip) { |
| 1445 | gpiochip->irqchip->irq_request_resources = NULL; | 1461 | gpiochip->irqchip->irq_request_resources = NULL; |
| @@ -1467,7 +1483,8 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) | |||
| 1467 | * translation. The gpiochip will need to be initialized and registered | 1483 | * translation. The gpiochip will need to be initialized and registered |
| 1468 | * before calling this function. | 1484 | * before calling this function. |
| 1469 | * | 1485 | * |
| 1470 | * This function will handle two cell:ed simple IRQs. Everything else | 1486 | * This function will handle two cell:ed simple IRQs and assumes all |
| 1487 | * the pins on the gpiochip can generate a unique IRQ. Everything else | ||
| 1471 | * need to be open coded. | 1488 | * need to be open coded. |
| 1472 | */ | 1489 | */ |
| 1473 | int gpiochip_irqchip_add(struct gpio_chip *gpiochip, | 1490 | int gpiochip_irqchip_add(struct gpio_chip *gpiochip, |
| @@ -1478,6 +1495,7 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip, | |||
| 1478 | { | 1495 | { |
| 1479 | struct device_node *of_node; | 1496 | struct device_node *of_node; |
| 1480 | unsigned int offset; | 1497 | unsigned int offset; |
| 1498 | unsigned irq_base = 0; | ||
| 1481 | 1499 | ||
| 1482 | if (!gpiochip || !irqchip) | 1500 | if (!gpiochip || !irqchip) |
| 1483 | return -EINVAL; | 1501 | return -EINVAL; |
| @@ -1514,8 +1532,15 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip, | |||
| 1514 | * any gpiochip calls. If the first_irq was zero, this is | 1532 | * any gpiochip calls. If the first_irq was zero, this is |
| 1515 | * necessary to allocate descriptors for all IRQs. | 1533 | * necessary to allocate descriptors for all IRQs. |
| 1516 | */ | 1534 | */ |
| 1517 | for (offset = 0; offset < gpiochip->ngpio; offset++) | 1535 | for (offset = 0; offset < gpiochip->ngpio; offset++) { |
| 1518 | irq_create_mapping(gpiochip->irqdomain, offset); | 1536 | irq_base = irq_create_mapping(gpiochip->irqdomain, offset); |
| 1537 | if (offset == 0) | ||
| 1538 | /* | ||
| 1539 | * Store the base into the gpiochip to be used when | ||
| 1540 | * unmapping the irqs. | ||
| 1541 | */ | ||
| 1542 | gpiochip->irq_base = irq_base; | ||
| 1543 | } | ||
| 1519 | 1544 | ||
| 1520 | return 0; | 1545 | return 0; |
| 1521 | } | 1546 | } |
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index c1c5c2368fc8..1827b43966d9 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h | |||
| @@ -107,6 +107,7 @@ struct gpio_chip { | |||
| 107 | */ | 107 | */ |
| 108 | struct irq_chip *irqchip; | 108 | struct irq_chip *irqchip; |
| 109 | struct irq_domain *irqdomain; | 109 | struct irq_domain *irqdomain; |
| 110 | unsigned int irq_base; | ||
| 110 | irq_flow_handler_t irq_handler; | 111 | irq_flow_handler_t irq_handler; |
| 111 | unsigned int irq_default_type; | 112 | unsigned int irq_default_type; |
| 112 | #endif | 113 | #endif |
