aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2017-11-07 13:15:54 -0500
committerLinus Walleij <linus.walleij@linaro.org>2017-11-08 08:12:01 -0500
commite0d89728981393b7d694bd3419b7794b9882c92d (patch)
tree4e8a009a3d71898f3ba4db28b32425cac190b883
parentca9df053fb2bb2fcc64f37a1668321c7e19edd04 (diff)
gpio: Implement tighter IRQ chip integration
Currently GPIO drivers are required to add the GPIO chip and its corresponding IRQ chip separately, which can result in a lot of boilerplate. Use the newly introduced struct gpio_irq_chip, embedded in struct gpio_chip, that drivers can fill in if they want the GPIO core to automatically register the IRQ chip associated with a GPIO chip. Signed-off-by: Thierry Reding <treding@nvidia.com> Acked-by: Grygorii Strashko <grygorii.strashko@ti.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--drivers/gpio/gpiolib.c108
-rw-r--r--include/linux/gpio/driver.h7
2 files changed, 114 insertions, 1 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 685a05caf1ba..003d1bb85165 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -72,6 +72,7 @@ static LIST_HEAD(gpio_lookup_list);
72LIST_HEAD(gpio_devices); 72LIST_HEAD(gpio_devices);
73 73
74static void gpiochip_free_hogs(struct gpio_chip *chip); 74static void gpiochip_free_hogs(struct gpio_chip *chip);
75static int gpiochip_add_irqchip(struct gpio_chip *gpiochip);
75static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip); 76static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip);
76static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip); 77static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip);
77static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip); 78static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip);
@@ -1266,6 +1267,10 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
1266 if (status) 1267 if (status)
1267 goto err_remove_from_list; 1268 goto err_remove_from_list;
1268 1269
1270 status = gpiochip_add_irqchip(chip);
1271 if (status)
1272 goto err_remove_chip;
1273
1269 status = of_gpiochip_add(chip); 1274 status = of_gpiochip_add(chip);
1270 if (status) 1275 if (status)
1271 goto err_remove_chip; 1276 goto err_remove_chip;
@@ -1637,6 +1642,7 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
1637 irq_hw_number_t hwirq) 1642 irq_hw_number_t hwirq)
1638{ 1643{
1639 struct gpio_chip *chip = d->host_data; 1644 struct gpio_chip *chip = d->host_data;
1645 int err = 0;
1640 1646
1641 if (!gpiochip_irqchip_irq_valid(chip, hwirq)) 1647 if (!gpiochip_irqchip_irq_valid(chip, hwirq))
1642 return -ENXIO; 1648 return -ENXIO;
@@ -1653,6 +1659,14 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
1653 irq_set_nested_thread(irq, 1); 1659 irq_set_nested_thread(irq, 1);
1654 irq_set_noprobe(irq); 1660 irq_set_noprobe(irq);
1655 1661
1662 if (chip->irq.num_parents == 1)
1663 err = irq_set_parent(irq, chip->irq.parents[0]);
1664 else if (chip->irq.map)
1665 err = irq_set_parent(irq, chip->irq.map[hwirq]);
1666
1667 if (err < 0)
1668 return err;
1669
1656 /* 1670 /*
1657 * No set-up of the hardware will happen if IRQ_TYPE_NONE 1671 * No set-up of the hardware will happen if IRQ_TYPE_NONE
1658 * is passed as default type. 1672 * is passed as default type.
@@ -1709,10 +1723,97 @@ static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset)
1709{ 1723{
1710 if (!gpiochip_irqchip_irq_valid(chip, offset)) 1724 if (!gpiochip_irqchip_irq_valid(chip, offset))
1711 return -ENXIO; 1725 return -ENXIO;
1726
1712 return irq_create_mapping(chip->irq.domain, offset); 1727 return irq_create_mapping(chip->irq.domain, offset);
1713} 1728}
1714 1729
1715/** 1730/**
1731 * gpiochip_add_irqchip() - adds an IRQ chip to a GPIO chip
1732 * @gpiochip: the GPIO chip to add the IRQ chip to
1733 */
1734static int gpiochip_add_irqchip(struct gpio_chip *gpiochip)
1735{
1736 struct irq_chip *irqchip = gpiochip->irq.chip;
1737 const struct irq_domain_ops *ops;
1738 struct device_node *np;
1739 unsigned int type;
1740 unsigned int i;
1741
1742 if (!irqchip)
1743 return 0;
1744
1745 if (gpiochip->irq.parent_handler && gpiochip->can_sleep) {
1746 chip_err(gpiochip, "you cannot have chained interrupts on a "
1747 "chip that may sleep\n");
1748 return -EINVAL;
1749 }
1750
1751 np = gpiochip->gpiodev->dev.of_node;
1752 type = gpiochip->irq.default_type;
1753
1754 /*
1755 * Specifying a default trigger is a terrible idea if DT or ACPI is
1756 * used to configure the interrupts, as you may end up with
1757 * conflicting triggers. Tell the user, and reset to NONE.
1758 */
1759 if (WARN(np && type != IRQ_TYPE_NONE,
1760 "%s: Ignoring %u default trigger\n", np->full_name, type))
1761 type = IRQ_TYPE_NONE;
1762
1763 if (has_acpi_companion(gpiochip->parent) && type != IRQ_TYPE_NONE) {
1764 acpi_handle_warn(ACPI_HANDLE(gpiochip->parent),
1765 "Ignoring %u default trigger\n", type);
1766 type = IRQ_TYPE_NONE;
1767 }
1768
1769 gpiochip->to_irq = gpiochip_to_irq;
1770 gpiochip->irq.default_type = type;
1771
1772 if (gpiochip->irq.domain_ops)
1773 ops = gpiochip->irq.domain_ops;
1774 else
1775 ops = &gpiochip_domain_ops;
1776
1777 gpiochip->irq.domain = irq_domain_add_simple(np, gpiochip->ngpio,
1778 0, ops, gpiochip);
1779 if (!gpiochip->irq.domain)
1780 return -EINVAL;
1781
1782 /*
1783 * It is possible for a driver to override this, but only if the
1784 * alternative functions are both implemented.
1785 */
1786 if (!irqchip->irq_request_resources &&
1787 !irqchip->irq_release_resources) {
1788 irqchip->irq_request_resources = gpiochip_irq_reqres;
1789 irqchip->irq_release_resources = gpiochip_irq_relres;
1790 }
1791
1792 if (gpiochip->irq.parent_handler) {
1793 void *data = gpiochip->irq.parent_handler_data ?: gpiochip;
1794
1795 for (i = 0; i < gpiochip->irq.num_parents; i++) {
1796 /*
1797 * The parent IRQ chip is already using the chip_data
1798 * for this IRQ chip, so our callbacks simply use the
1799 * handler_data.
1800 */
1801 irq_set_chained_handler_and_data(gpiochip->irq.parents[i],
1802 gpiochip->irq.parent_handler,
1803 data);
1804 }
1805
1806 gpiochip->irq.nested = false;
1807 } else {
1808 gpiochip->irq.nested = true;
1809 }
1810
1811 acpi_gpiochip_request_interrupts(gpiochip);
1812
1813 return 0;
1814}
1815
1816/**
1716 * gpiochip_irqchip_remove() - removes an irqchip added to a gpiochip 1817 * gpiochip_irqchip_remove() - removes an irqchip added to a gpiochip
1717 * @gpiochip: the gpiochip to remove the irqchip from 1818 * @gpiochip: the gpiochip to remove the irqchip from
1718 * 1819 *
@@ -1724,7 +1825,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
1724 1825
1725 acpi_gpiochip_free_interrupts(gpiochip); 1826 acpi_gpiochip_free_interrupts(gpiochip);
1726 1827
1727 if (gpiochip->irq.num_parents > 0) { 1828 if (gpiochip->irq.chip && gpiochip->irq.parent_handler) {
1728 struct gpio_irq_chip *irq = &gpiochip->irq; 1829 struct gpio_irq_chip *irq = &gpiochip->irq;
1729 unsigned int i; 1830 unsigned int i;
1730 1831
@@ -1857,6 +1958,11 @@ EXPORT_SYMBOL_GPL(gpiochip_irqchip_add_key);
1857 1958
1858#else /* CONFIG_GPIOLIB_IRQCHIP */ 1959#else /* CONFIG_GPIOLIB_IRQCHIP */
1859 1960
1961static inline int gpiochip_add_irqchip(struct gpio_chip *gpiochip)
1962{
1963 return 0;
1964}
1965
1860static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {} 1966static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {}
1861static inline int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip) 1967static inline int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip)
1862{ 1968{
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index c363ee198ff9..51fc7b023364 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -101,6 +101,13 @@ struct gpio_irq_chip {
101 unsigned int *parents; 101 unsigned int *parents;
102 102
103 /** 103 /**
104 * @map:
105 *
106 * A list of interrupt parents for each line of a GPIO chip.
107 */
108 unsigned int *map;
109
110 /**
104 * @nested: 111 * @nested:
105 * 112 *
106 * True if set the interrupt handling is nested. 113 * True if set the interrupt handling is nested.