aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpiolib.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2016-09-23 08:51:18 -0400
committerLinus Walleij <linus.walleij@linaro.org>2016-09-23 08:51:18 -0400
commit22a5db98a30ea734c29056b0d59cb4fe2a383bc2 (patch)
treed1d5b3ee914e95f00b917ebf48b59fe8331a5734 /drivers/gpio/gpiolib.c
parent9132ce450bd141cd8c5776b41e90f146cae4bc3b (diff)
parent79b804cb6af4f128b2c53f0887c02537a7eb5824 (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.c66
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
72static void gpiochip_free_hogs(struct gpio_chip *chip); 72static void gpiochip_free_hogs(struct gpio_chip *chip);
73static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip); 73static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip);
74static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip);
75static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip);
74 76
75static bool gpiolib_initialized; 77static 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);
1195err_remove_from_list: 1202err_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
1407static 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
1426static 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
1432static 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}
1445EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip); 1489EXPORT_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
1676static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {} 1730static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {}
1731static inline int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip)
1732{
1733 return 0;
1734}
1735static 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