diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2016-09-23 08:51:18 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2016-09-23 08:51:18 -0400 |
commit | 22a5db98a30ea734c29056b0d59cb4fe2a383bc2 (patch) | |
tree | d1d5b3ee914e95f00b917ebf48b59fe8331a5734 /drivers/gpio/gpiolib.c | |
parent | 9132ce450bd141cd8c5776b41e90f146cae4bc3b (diff) | |
parent | 79b804cb6af4f128b2c53f0887c02537a7eb5824 (diff) |
Merge branch 'gpio-irq-validmask' of /home/linus/linux-pinctrl into devel
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r-- | drivers/gpio/gpiolib.c | 66 |
1 files changed, 63 insertions, 3 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 043128d3e831..19a665f8d455 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -71,6 +71,8 @@ LIST_HEAD(gpio_devices); | |||
71 | 71 | ||
72 | static void gpiochip_free_hogs(struct gpio_chip *chip); | 72 | static void gpiochip_free_hogs(struct gpio_chip *chip); |
73 | static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip); | 73 | static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip); |
74 | static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip); | ||
75 | static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip); | ||
74 | 76 | ||
75 | static bool gpiolib_initialized; | 77 | static bool gpiolib_initialized; |
76 | 78 | ||
@@ -1167,6 +1169,10 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) | |||
1167 | if (status) | 1169 | if (status) |
1168 | goto err_remove_from_list; | 1170 | goto err_remove_from_list; |
1169 | 1171 | ||
1172 | status = gpiochip_irqchip_init_valid_mask(chip); | ||
1173 | if (status) | ||
1174 | goto err_remove_from_list; | ||
1175 | |||
1170 | status = of_gpiochip_add(chip); | 1176 | status = of_gpiochip_add(chip); |
1171 | if (status) | 1177 | if (status) |
1172 | goto err_remove_chip; | 1178 | goto err_remove_chip; |
@@ -1192,6 +1198,7 @@ err_remove_chip: | |||
1192 | acpi_gpiochip_remove(chip); | 1198 | acpi_gpiochip_remove(chip); |
1193 | gpiochip_free_hogs(chip); | 1199 | gpiochip_free_hogs(chip); |
1194 | of_gpiochip_remove(chip); | 1200 | of_gpiochip_remove(chip); |
1201 | gpiochip_irqchip_free_valid_mask(chip); | ||
1195 | err_remove_from_list: | 1202 | err_remove_from_list: |
1196 | spin_lock_irqsave(&gpio_lock, flags); | 1203 | spin_lock_irqsave(&gpio_lock, flags); |
1197 | list_del(&gdev->list); | 1204 | list_del(&gdev->list); |
@@ -1397,6 +1404,40 @@ static struct gpio_chip *find_chip_by_name(const char *name) | |||
1397 | * The following is irqchip helper code for gpiochips. | 1404 | * The following is irqchip helper code for gpiochips. |
1398 | */ | 1405 | */ |
1399 | 1406 | ||
1407 | static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip) | ||
1408 | { | ||
1409 | int i; | ||
1410 | |||
1411 | if (!gpiochip->irq_need_valid_mask) | ||
1412 | return 0; | ||
1413 | |||
1414 | gpiochip->irq_valid_mask = kcalloc(BITS_TO_LONGS(gpiochip->ngpio), | ||
1415 | sizeof(long), GFP_KERNEL); | ||
1416 | if (!gpiochip->irq_valid_mask) | ||
1417 | return -ENOMEM; | ||
1418 | |||
1419 | /* Assume by default all GPIOs are valid */ | ||
1420 | for (i = 0; i < gpiochip->ngpio; i++) | ||
1421 | set_bit(i, gpiochip->irq_valid_mask); | ||
1422 | |||
1423 | return 0; | ||
1424 | } | ||
1425 | |||
1426 | static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip) | ||
1427 | { | ||
1428 | kfree(gpiochip->irq_valid_mask); | ||
1429 | gpiochip->irq_valid_mask = NULL; | ||
1430 | } | ||
1431 | |||
1432 | static bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip, | ||
1433 | unsigned int offset) | ||
1434 | { | ||
1435 | /* No mask means all valid */ | ||
1436 | if (likely(!gpiochip->irq_valid_mask)) | ||
1437 | return true; | ||
1438 | return test_bit(offset, gpiochip->irq_valid_mask); | ||
1439 | } | ||
1440 | |||
1400 | /** | 1441 | /** |
1401 | * gpiochip_set_chained_irqchip() - sets a chained irqchip to a gpiochip | 1442 | * gpiochip_set_chained_irqchip() - sets a chained irqchip to a gpiochip |
1402 | * @gpiochip: the gpiochip to set the irqchip chain to | 1443 | * @gpiochip: the gpiochip to set the irqchip chain to |
@@ -1438,9 +1479,12 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, | |||
1438 | } | 1479 | } |
1439 | 1480 | ||
1440 | /* Set the parent IRQ for all affected IRQs */ | 1481 | /* Set the parent IRQ for all affected IRQs */ |
1441 | for (offset = 0; offset < gpiochip->ngpio; offset++) | 1482 | for (offset = 0; offset < gpiochip->ngpio; offset++) { |
1483 | if (!gpiochip_irqchip_irq_valid(gpiochip, offset)) | ||
1484 | continue; | ||
1442 | irq_set_parent(irq_find_mapping(gpiochip->irqdomain, offset), | 1485 | irq_set_parent(irq_find_mapping(gpiochip->irqdomain, offset), |
1443 | parent_irq); | 1486 | parent_irq); |
1487 | } | ||
1444 | } | 1488 | } |
1445 | EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip); | 1489 | EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip); |
1446 | 1490 | ||
@@ -1547,9 +1591,12 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) | |||
1547 | 1591 | ||
1548 | /* Remove all IRQ mappings and delete the domain */ | 1592 | /* Remove all IRQ mappings and delete the domain */ |
1549 | if (gpiochip->irqdomain) { | 1593 | if (gpiochip->irqdomain) { |
1550 | for (offset = 0; offset < gpiochip->ngpio; offset++) | 1594 | for (offset = 0; offset < gpiochip->ngpio; offset++) { |
1595 | if (!gpiochip_irqchip_irq_valid(gpiochip, offset)) | ||
1596 | continue; | ||
1551 | irq_dispose_mapping( | 1597 | irq_dispose_mapping( |
1552 | irq_find_mapping(gpiochip->irqdomain, offset)); | 1598 | irq_find_mapping(gpiochip->irqdomain, offset)); |
1599 | } | ||
1553 | irq_domain_remove(gpiochip->irqdomain); | 1600 | irq_domain_remove(gpiochip->irqdomain); |
1554 | } | 1601 | } |
1555 | 1602 | ||
@@ -1558,6 +1605,8 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) | |||
1558 | gpiochip->irqchip->irq_release_resources = NULL; | 1605 | gpiochip->irqchip->irq_release_resources = NULL; |
1559 | gpiochip->irqchip = NULL; | 1606 | gpiochip->irqchip = NULL; |
1560 | } | 1607 | } |
1608 | |||
1609 | gpiochip_irqchip_free_valid_mask(gpiochip); | ||
1561 | } | 1610 | } |
1562 | 1611 | ||
1563 | /** | 1612 | /** |
@@ -1593,6 +1642,7 @@ int _gpiochip_irqchip_add(struct gpio_chip *gpiochip, | |||
1593 | struct lock_class_key *lock_key) | 1642 | struct lock_class_key *lock_key) |
1594 | { | 1643 | { |
1595 | struct device_node *of_node; | 1644 | struct device_node *of_node; |
1645 | bool irq_base_set = false; | ||
1596 | unsigned int offset; | 1646 | unsigned int offset; |
1597 | unsigned irq_base = 0; | 1647 | unsigned irq_base = 0; |
1598 | 1648 | ||
@@ -1656,13 +1706,17 @@ int _gpiochip_irqchip_add(struct gpio_chip *gpiochip, | |||
1656 | * necessary to allocate descriptors for all IRQs. | 1706 | * necessary to allocate descriptors for all IRQs. |
1657 | */ | 1707 | */ |
1658 | for (offset = 0; offset < gpiochip->ngpio; offset++) { | 1708 | for (offset = 0; offset < gpiochip->ngpio; offset++) { |
1709 | if (!gpiochip_irqchip_irq_valid(gpiochip, offset)) | ||
1710 | continue; | ||
1659 | irq_base = irq_create_mapping(gpiochip->irqdomain, offset); | 1711 | irq_base = irq_create_mapping(gpiochip->irqdomain, offset); |
1660 | if (offset == 0) | 1712 | if (!irq_base_set) { |
1661 | /* | 1713 | /* |
1662 | * Store the base into the gpiochip to be used when | 1714 | * Store the base into the gpiochip to be used when |
1663 | * unmapping the irqs. | 1715 | * unmapping the irqs. |
1664 | */ | 1716 | */ |
1665 | gpiochip->irq_base = irq_base; | 1717 | gpiochip->irq_base = irq_base; |
1718 | irq_base_set = true; | ||
1719 | } | ||
1666 | } | 1720 | } |
1667 | 1721 | ||
1668 | acpi_gpiochip_request_interrupts(gpiochip); | 1722 | acpi_gpiochip_request_interrupts(gpiochip); |
@@ -1674,6 +1728,12 @@ EXPORT_SYMBOL_GPL(_gpiochip_irqchip_add); | |||
1674 | #else /* CONFIG_GPIOLIB_IRQCHIP */ | 1728 | #else /* CONFIG_GPIOLIB_IRQCHIP */ |
1675 | 1729 | ||
1676 | static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {} | 1730 | static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {} |
1731 | static inline int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip) | ||
1732 | { | ||
1733 | return 0; | ||
1734 | } | ||
1735 | static inline void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip) | ||
1736 | { } | ||
1677 | 1737 | ||
1678 | #endif /* CONFIG_GPIOLIB_IRQCHIP */ | 1738 | #endif /* CONFIG_GPIOLIB_IRQCHIP */ |
1679 | 1739 | ||