diff options
author | Tony Lindgren <tony@atomide.com> | 2013-10-03 00:39:40 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2013-10-10 18:30:30 -0400 |
commit | 3e6cee1786a13cb2308609b5f8c020e1754e37cf (patch) | |
tree | f76f85def8d2fd5654146ff9e612371590555573 | |
parent | 02e483f66deb6bd8df6af450726574614eb53be3 (diff) |
pinctrl: single: Add support for wake-up interrupts
The pin control registers can have interrupts for example
for device wake-up. These interrupts can be treated as a
chained interrupt controller as suggested earlier by
Linus Walleij <linus.walleij@linaro.org>.
This patch adds support for interrupts in a way that
should be pretty generic, and works for the omaps that
support wake-up interrupts. On omaps, there's an
interrupt enable and interrupt status bit for each pin.
The two pinctrl domains on omaps share a single interrupt
from the PRM chained interrupt handler. Support for
other similar hardware should be easy to add.
Note that this patch does not attempt to handle the
wake-up interrupts automatically unlike the earlier
patches. This patch allows the device drivers to do
a request_irq() on the wake-up pins as needed. I'll
try to do also a separate generic patch for handling
the wake-up events automatically.
Also note that as this patch makes the pinctrl-single
an irq controller, the current bindings need some
extra trickery to use interrupts from two different
interrupt controllers for the same driver. So it
might be worth waiting a little on the patches
enabling the wake-up interrupts from drivers as there
should be a generic way to handle it coming. And also
there's been discussion of interrupts-extended binding
for using interrupts from multiple interrupt controllers.
In any case, this patch should be ready to go allowing
handling the wake-up interrupts in a generic way, or
separately from the device drivers.
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: Grygorii Strashko <grygorii.strashko@ti.com>
Cc: Prakash Manjunathappa <prakash.pm@ti.com>
Cc: Roger Quadros <rogerq@ti.com>
Cc: linux-kernel@vger.kernel.org
Cc: BenoƮt Cousson <bcousson@baylibre.com>
Cc: devicetree@vger.kernel.org
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com>
Reviewed-by: Kevin Hilman <khilman@linaro.org>
Tested-by: Kevin Hilman <khilman@linaro.org>
Signed-off-by: Tony Lindgren <tony@atomide.com>
-rw-r--r-- | Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt | 11 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-single.c | 322 |
2 files changed, 333 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt index 5a02e30dd262..7069a0b84e3a 100644 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt | |||
@@ -72,6 +72,13 @@ Optional properties: | |||
72 | /* pin base, nr pins & gpio function */ | 72 | /* pin base, nr pins & gpio function */ |
73 | pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1>; | 73 | pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1>; |
74 | 74 | ||
75 | - interrupt-controller : standard interrupt controller binding if using | ||
76 | interrupts for wake-up events for example. In this case pinctrl-single | ||
77 | is set up as a chained interrupt controller and the wake-up interrupts | ||
78 | can be requested by the drivers using request_irq(). | ||
79 | |||
80 | - #interrupt-cells : standard interrupt binding if using interrupts | ||
81 | |||
75 | This driver assumes that there is only one register for each pin (unless the | 82 | This driver assumes that there is only one register for each pin (unless the |
76 | pinctrl-single,bit-per-mux is set), and uses the common pinctrl bindings as | 83 | pinctrl-single,bit-per-mux is set), and uses the common pinctrl bindings as |
77 | specified in the pinctrl-bindings.txt document in this directory. | 84 | specified in the pinctrl-bindings.txt document in this directory. |
@@ -121,6 +128,8 @@ pmx_core: pinmux@4a100040 { | |||
121 | reg = <0x4a100040 0x0196>; | 128 | reg = <0x4a100040 0x0196>; |
122 | #address-cells = <1>; | 129 | #address-cells = <1>; |
123 | #size-cells = <0>; | 130 | #size-cells = <0>; |
131 | #interrupt-cells = <1>; | ||
132 | interrupt-controller; | ||
124 | pinctrl-single,register-width = <16>; | 133 | pinctrl-single,register-width = <16>; |
125 | pinctrl-single,function-mask = <0xffff>; | 134 | pinctrl-single,function-mask = <0xffff>; |
126 | }; | 135 | }; |
@@ -131,6 +140,8 @@ pmx_wkup: pinmux@4a31e040 { | |||
131 | reg = <0x4a31e040 0x0038>; | 140 | reg = <0x4a31e040 0x0038>; |
132 | #address-cells = <1>; | 141 | #address-cells = <1>; |
133 | #size-cells = <0>; | 142 | #size-cells = <0>; |
143 | #interrupt-cells = <1>; | ||
144 | interrupt-controller; | ||
134 | pinctrl-single,register-width = <16>; | 145 | pinctrl-single,register-width = <16>; |
135 | pinctrl-single,function-mask = <0xffff>; | 146 | pinctrl-single,function-mask = <0xffff>; |
136 | }; | 147 | }; |
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index f88d3d1b2b99..dad65df36f4b 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c | |||
@@ -15,10 +15,14 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
17 | #include <linux/list.h> | 17 | #include <linux/list.h> |
18 | #include <linux/interrupt.h> | ||
19 | |||
20 | #include <linux/irqchip/chained_irq.h> | ||
18 | 21 | ||
19 | #include <linux/of.h> | 22 | #include <linux/of.h> |
20 | #include <linux/of_device.h> | 23 | #include <linux/of_device.h> |
21 | #include <linux/of_address.h> | 24 | #include <linux/of_address.h> |
25 | #include <linux/of_irq.h> | ||
22 | 26 | ||
23 | #include <linux/pinctrl/pinctrl.h> | 27 | #include <linux/pinctrl/pinctrl.h> |
24 | #include <linux/pinctrl/pinmux.h> | 28 | #include <linux/pinctrl/pinmux.h> |
@@ -152,9 +156,15 @@ struct pcs_name { | |||
152 | /** | 156 | /** |
153 | * struct pcs_soc_data - SoC specific settings | 157 | * struct pcs_soc_data - SoC specific settings |
154 | * @flags: initial SoC specific PCS_FEAT_xxx values | 158 | * @flags: initial SoC specific PCS_FEAT_xxx values |
159 | * @irq: optional interrupt for the controller | ||
160 | * @irq_enable_mask: optional SoC specific interrupt enable mask | ||
161 | * @irq_status_mask: optional SoC specific interrupt status mask | ||
155 | */ | 162 | */ |
156 | struct pcs_soc_data { | 163 | struct pcs_soc_data { |
157 | unsigned flags; | 164 | unsigned flags; |
165 | int irq; | ||
166 | unsigned irq_enable_mask; | ||
167 | unsigned irq_status_mask; | ||
158 | }; | 168 | }; |
159 | 169 | ||
160 | /** | 170 | /** |
@@ -165,6 +175,7 @@ struct pcs_soc_data { | |||
165 | * @dev: device entry | 175 | * @dev: device entry |
166 | * @pctl: pin controller device | 176 | * @pctl: pin controller device |
167 | * @flags: mask of PCS_FEAT_xxx values | 177 | * @flags: mask of PCS_FEAT_xxx values |
178 | * @lock: spinlock for register access | ||
168 | * @mutex: mutex protecting the lists | 179 | * @mutex: mutex protecting the lists |
169 | * @width: bits per mux register | 180 | * @width: bits per mux register |
170 | * @fmask: function register mask | 181 | * @fmask: function register mask |
@@ -179,6 +190,9 @@ struct pcs_soc_data { | |||
179 | * @pingroups: list of pingroups | 190 | * @pingroups: list of pingroups |
180 | * @functions: list of functions | 191 | * @functions: list of functions |
181 | * @gpiofuncs: list of gpio functions | 192 | * @gpiofuncs: list of gpio functions |
193 | * @irqs: list of interrupt registers | ||
194 | * @chip: chip container for this instance | ||
195 | * @domain: IRQ domain for this instance | ||
182 | * @ngroups: number of pingroups | 196 | * @ngroups: number of pingroups |
183 | * @nfuncs: number of functions | 197 | * @nfuncs: number of functions |
184 | * @desc: pin controller descriptor | 198 | * @desc: pin controller descriptor |
@@ -192,7 +206,11 @@ struct pcs_device { | |||
192 | struct device *dev; | 206 | struct device *dev; |
193 | struct pinctrl_dev *pctl; | 207 | struct pinctrl_dev *pctl; |
194 | unsigned flags; | 208 | unsigned flags; |
209 | #define PCS_QUIRK_SHARED_IRQ (1 << 2) | ||
210 | #define PCS_FEAT_IRQ (1 << 1) | ||
195 | #define PCS_FEAT_PINCONF (1 << 0) | 211 | #define PCS_FEAT_PINCONF (1 << 0) |
212 | struct pcs_soc_data socdata; | ||
213 | raw_spinlock_t lock; | ||
196 | struct mutex mutex; | 214 | struct mutex mutex; |
197 | unsigned width; | 215 | unsigned width; |
198 | unsigned fmask; | 216 | unsigned fmask; |
@@ -208,6 +226,9 @@ struct pcs_device { | |||
208 | struct list_head pingroups; | 226 | struct list_head pingroups; |
209 | struct list_head functions; | 227 | struct list_head functions; |
210 | struct list_head gpiofuncs; | 228 | struct list_head gpiofuncs; |
229 | struct list_head irqs; | ||
230 | struct irq_chip chip; | ||
231 | struct irq_domain *domain; | ||
211 | unsigned ngroups; | 232 | unsigned ngroups; |
212 | unsigned nfuncs; | 233 | unsigned nfuncs; |
213 | struct pinctrl_desc desc; | 234 | struct pinctrl_desc desc; |
@@ -215,6 +236,8 @@ struct pcs_device { | |||
215 | void (*write)(unsigned val, void __iomem *reg); | 236 | void (*write)(unsigned val, void __iomem *reg); |
216 | }; | 237 | }; |
217 | 238 | ||
239 | #define PCS_QUIRK_HAS_SHARED_IRQ (pcs->flags & PCS_QUIRK_SHARED_IRQ) | ||
240 | #define PCS_HAS_IRQ (pcs->flags & PCS_FEAT_IRQ) | ||
218 | #define PCS_HAS_PINCONF (pcs->flags & PCS_FEAT_PINCONF) | 241 | #define PCS_HAS_PINCONF (pcs->flags & PCS_FEAT_PINCONF) |
219 | 242 | ||
220 | static int pcs_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin, | 243 | static int pcs_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin, |
@@ -440,9 +463,11 @@ static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector, | |||
440 | 463 | ||
441 | for (i = 0; i < func->nvals; i++) { | 464 | for (i = 0; i < func->nvals; i++) { |
442 | struct pcs_func_vals *vals; | 465 | struct pcs_func_vals *vals; |
466 | unsigned long flags; | ||
443 | unsigned val, mask; | 467 | unsigned val, mask; |
444 | 468 | ||
445 | vals = &func->vals[i]; | 469 | vals = &func->vals[i]; |
470 | raw_spin_lock_irqsave(&pcs->lock, flags); | ||
446 | val = pcs->read(vals->reg); | 471 | val = pcs->read(vals->reg); |
447 | 472 | ||
448 | if (pcs->bits_per_mux) | 473 | if (pcs->bits_per_mux) |
@@ -453,6 +478,7 @@ static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector, | |||
453 | val &= ~mask; | 478 | val &= ~mask; |
454 | val |= (vals->val & mask); | 479 | val |= (vals->val & mask); |
455 | pcs->write(val, vals->reg); | 480 | pcs->write(val, vals->reg); |
481 | raw_spin_unlock_irqrestore(&pcs->lock, flags); | ||
456 | } | 482 | } |
457 | 483 | ||
458 | return 0; | 484 | return 0; |
@@ -494,13 +520,16 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector, | |||
494 | 520 | ||
495 | for (i = 0; i < func->nvals; i++) { | 521 | for (i = 0; i < func->nvals; i++) { |
496 | struct pcs_func_vals *vals; | 522 | struct pcs_func_vals *vals; |
523 | unsigned long flags; | ||
497 | unsigned val; | 524 | unsigned val; |
498 | 525 | ||
499 | vals = &func->vals[i]; | 526 | vals = &func->vals[i]; |
527 | raw_spin_lock_irqsave(&pcs->lock, flags); | ||
500 | val = pcs->read(vals->reg); | 528 | val = pcs->read(vals->reg); |
501 | val &= ~pcs->fmask; | 529 | val &= ~pcs->fmask; |
502 | val |= pcs->foff << pcs->fshift; | 530 | val |= pcs->foff << pcs->fshift; |
503 | pcs->write(val, vals->reg); | 531 | pcs->write(val, vals->reg); |
532 | raw_spin_unlock_irqrestore(&pcs->lock, flags); | ||
504 | } | 533 | } |
505 | } | 534 | } |
506 | 535 | ||
@@ -1451,11 +1480,33 @@ static void pcs_free_pingroups(struct pcs_device *pcs) | |||
1451 | } | 1480 | } |
1452 | 1481 | ||
1453 | /** | 1482 | /** |
1483 | * pcs_irq_free() - free interrupt | ||
1484 | * @pcs: pcs driver instance | ||
1485 | */ | ||
1486 | static void pcs_irq_free(struct pcs_device *pcs) | ||
1487 | { | ||
1488 | struct pcs_soc_data *pcs_soc = &pcs->socdata; | ||
1489 | |||
1490 | if (pcs_soc->irq < 0) | ||
1491 | return; | ||
1492 | |||
1493 | if (pcs->domain) | ||
1494 | irq_domain_remove(pcs->domain); | ||
1495 | |||
1496 | if (PCS_QUIRK_HAS_SHARED_IRQ) | ||
1497 | free_irq(pcs_soc->irq, pcs_soc); | ||
1498 | else | ||
1499 | irq_set_chained_handler(pcs_soc->irq, NULL); | ||
1500 | } | ||
1501 | |||
1502 | /** | ||
1454 | * pcs_free_resources() - free memory used by this driver | 1503 | * pcs_free_resources() - free memory used by this driver |
1455 | * @pcs: pcs driver instance | 1504 | * @pcs: pcs driver instance |
1456 | */ | 1505 | */ |
1457 | static void pcs_free_resources(struct pcs_device *pcs) | 1506 | static void pcs_free_resources(struct pcs_device *pcs) |
1458 | { | 1507 | { |
1508 | pcs_irq_free(pcs); | ||
1509 | |||
1459 | if (pcs->pctl) | 1510 | if (pcs->pctl) |
1460 | pinctrl_unregister(pcs->pctl); | 1511 | pinctrl_unregister(pcs->pctl); |
1461 | 1512 | ||
@@ -1504,6 +1555,256 @@ static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs) | |||
1504 | } | 1555 | } |
1505 | return ret; | 1556 | return ret; |
1506 | } | 1557 | } |
1558 | /** | ||
1559 | * @reg: virtual address of interrupt register | ||
1560 | * @hwirq: hardware irq number | ||
1561 | * @irq: virtual irq number | ||
1562 | * @node: list node | ||
1563 | */ | ||
1564 | struct pcs_interrupt { | ||
1565 | void __iomem *reg; | ||
1566 | irq_hw_number_t hwirq; | ||
1567 | unsigned int irq; | ||
1568 | struct list_head node; | ||
1569 | }; | ||
1570 | |||
1571 | /** | ||
1572 | * pcs_irq_set() - enables or disables an interrupt | ||
1573 | * | ||
1574 | * Note that this currently assumes one interrupt per pinctrl | ||
1575 | * register that is typically used for wake-up events. | ||
1576 | */ | ||
1577 | static inline void pcs_irq_set(struct pcs_soc_data *pcs_soc, | ||
1578 | int irq, const bool enable) | ||
1579 | { | ||
1580 | struct pcs_device *pcs; | ||
1581 | struct list_head *pos; | ||
1582 | unsigned mask; | ||
1583 | |||
1584 | pcs = container_of(pcs_soc, struct pcs_device, socdata); | ||
1585 | list_for_each(pos, &pcs->irqs) { | ||
1586 | struct pcs_interrupt *pcswi; | ||
1587 | unsigned soc_mask; | ||
1588 | |||
1589 | pcswi = list_entry(pos, struct pcs_interrupt, node); | ||
1590 | if (irq != pcswi->irq) | ||
1591 | continue; | ||
1592 | |||
1593 | soc_mask = pcs_soc->irq_enable_mask; | ||
1594 | raw_spin_lock(&pcs->lock); | ||
1595 | mask = pcs->read(pcswi->reg); | ||
1596 | if (enable) | ||
1597 | mask |= soc_mask; | ||
1598 | else | ||
1599 | mask &= ~soc_mask; | ||
1600 | pcs->write(mask, pcswi->reg); | ||
1601 | raw_spin_unlock(&pcs->lock); | ||
1602 | } | ||
1603 | } | ||
1604 | |||
1605 | /** | ||
1606 | * pcs_irq_mask() - mask pinctrl interrupt | ||
1607 | * @d: interrupt data | ||
1608 | */ | ||
1609 | static void pcs_irq_mask(struct irq_data *d) | ||
1610 | { | ||
1611 | struct pcs_soc_data *pcs_soc = irq_data_get_irq_chip_data(d); | ||
1612 | |||
1613 | pcs_irq_set(pcs_soc, d->irq, false); | ||
1614 | } | ||
1615 | |||
1616 | /** | ||
1617 | * pcs_irq_unmask() - unmask pinctrl interrupt | ||
1618 | * @d: interrupt data | ||
1619 | */ | ||
1620 | static void pcs_irq_unmask(struct irq_data *d) | ||
1621 | { | ||
1622 | struct pcs_soc_data *pcs_soc = irq_data_get_irq_chip_data(d); | ||
1623 | |||
1624 | pcs_irq_set(pcs_soc, d->irq, true); | ||
1625 | } | ||
1626 | |||
1627 | /** | ||
1628 | * pcs_irq_set_wake() - toggle the suspend and resume wake up | ||
1629 | * @d: interrupt data | ||
1630 | * @state: wake-up state | ||
1631 | * | ||
1632 | * Note that this should be called only for suspend and resume. | ||
1633 | * For runtime PM, the wake-up events should be enabled by default. | ||
1634 | */ | ||
1635 | static int pcs_irq_set_wake(struct irq_data *d, unsigned int state) | ||
1636 | { | ||
1637 | if (state) | ||
1638 | pcs_irq_unmask(d); | ||
1639 | else | ||
1640 | pcs_irq_mask(d); | ||
1641 | |||
1642 | return 0; | ||
1643 | } | ||
1644 | |||
1645 | /** | ||
1646 | * pcs_irq_handle() - common interrupt handler | ||
1647 | * @pcs_irq: interrupt data | ||
1648 | * | ||
1649 | * Note that this currently assumes we have one interrupt bit per | ||
1650 | * mux register. This interrupt is typically used for wake-up events. | ||
1651 | * For more complex interrupts different handlers can be specified. | ||
1652 | */ | ||
1653 | static int pcs_irq_handle(struct pcs_soc_data *pcs_soc) | ||
1654 | { | ||
1655 | struct pcs_device *pcs; | ||
1656 | struct list_head *pos; | ||
1657 | int count = 0; | ||
1658 | |||
1659 | pcs = container_of(pcs_soc, struct pcs_device, socdata); | ||
1660 | list_for_each(pos, &pcs->irqs) { | ||
1661 | struct pcs_interrupt *pcswi; | ||
1662 | unsigned mask; | ||
1663 | |||
1664 | pcswi = list_entry(pos, struct pcs_interrupt, node); | ||
1665 | raw_spin_lock(&pcs->lock); | ||
1666 | mask = pcs->read(pcswi->reg); | ||
1667 | raw_spin_unlock(&pcs->lock); | ||
1668 | if (mask & pcs_soc->irq_status_mask) { | ||
1669 | generic_handle_irq(irq_find_mapping(pcs->domain, | ||
1670 | pcswi->hwirq)); | ||
1671 | count++; | ||
1672 | } | ||
1673 | } | ||
1674 | |||
1675 | return count; | ||
1676 | } | ||
1677 | |||
1678 | /** | ||
1679 | * pcs_irq_handler() - handler for the shared interrupt case | ||
1680 | * @irq: interrupt | ||
1681 | * @d: data | ||
1682 | * | ||
1683 | * Use this for cases where multiple instances of | ||
1684 | * pinctrl-single share a single interrupt like on omaps. | ||
1685 | */ | ||
1686 | static irqreturn_t pcs_irq_handler(int irq, void *d) | ||
1687 | { | ||
1688 | struct pcs_soc_data *pcs_soc = d; | ||
1689 | |||
1690 | return pcs_irq_handle(pcs_soc) ? IRQ_HANDLED : IRQ_NONE; | ||
1691 | } | ||
1692 | |||
1693 | /** | ||
1694 | * pcs_irq_handle() - handler for the dedicated chained interrupt case | ||
1695 | * @irq: interrupt | ||
1696 | * @desc: interrupt descriptor | ||
1697 | * | ||
1698 | * Use this if you have a separate interrupt for each | ||
1699 | * pinctrl-single instance. | ||
1700 | */ | ||
1701 | static void pcs_irq_chain_handler(unsigned int irq, struct irq_desc *desc) | ||
1702 | { | ||
1703 | struct pcs_soc_data *pcs_soc = irq_desc_get_handler_data(desc); | ||
1704 | struct irq_chip *chip; | ||
1705 | int res; | ||
1706 | |||
1707 | chip = irq_get_chip(irq); | ||
1708 | chained_irq_enter(chip, desc); | ||
1709 | res = pcs_irq_handle(pcs_soc); | ||
1710 | /* REVISIT: export and add handle_bad_irq(irq, desc)? */ | ||
1711 | chained_irq_exit(chip, desc); | ||
1712 | |||
1713 | return; | ||
1714 | } | ||
1715 | |||
1716 | static int pcs_irqdomain_map(struct irq_domain *d, unsigned int irq, | ||
1717 | irq_hw_number_t hwirq) | ||
1718 | { | ||
1719 | struct pcs_soc_data *pcs_soc = d->host_data; | ||
1720 | struct pcs_device *pcs; | ||
1721 | struct pcs_interrupt *pcswi; | ||
1722 | |||
1723 | pcs = container_of(pcs_soc, struct pcs_device, socdata); | ||
1724 | pcswi = devm_kzalloc(pcs->dev, sizeof(*pcswi), GFP_KERNEL); | ||
1725 | if (!pcswi) | ||
1726 | return -ENOMEM; | ||
1727 | |||
1728 | pcswi->reg = pcs->base + hwirq; | ||
1729 | pcswi->hwirq = hwirq; | ||
1730 | pcswi->irq = irq; | ||
1731 | |||
1732 | mutex_lock(&pcs->mutex); | ||
1733 | list_add_tail(&pcswi->node, &pcs->irqs); | ||
1734 | mutex_unlock(&pcs->mutex); | ||
1735 | |||
1736 | irq_set_chip_data(irq, pcs_soc); | ||
1737 | irq_set_chip_and_handler(irq, &pcs->chip, | ||
1738 | handle_level_irq); | ||
1739 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
1740 | |||
1741 | return 0; | ||
1742 | } | ||
1743 | |||
1744 | static struct irq_domain_ops pcs_irqdomain_ops = { | ||
1745 | .map = pcs_irqdomain_map, | ||
1746 | .xlate = irq_domain_xlate_onecell, | ||
1747 | }; | ||
1748 | |||
1749 | /** | ||
1750 | * pcs_irq_init_chained_handler() - set up a chained interrupt handler | ||
1751 | * @pcs: pcs driver instance | ||
1752 | * @np: device node pointer | ||
1753 | */ | ||
1754 | static int pcs_irq_init_chained_handler(struct pcs_device *pcs, | ||
1755 | struct device_node *np) | ||
1756 | { | ||
1757 | struct pcs_soc_data *pcs_soc = &pcs->socdata; | ||
1758 | const char *name = "pinctrl"; | ||
1759 | int num_irqs; | ||
1760 | |||
1761 | if (!pcs_soc->irq_enable_mask || | ||
1762 | !pcs_soc->irq_status_mask) { | ||
1763 | pcs_soc->irq = -1; | ||
1764 | return -EINVAL; | ||
1765 | } | ||
1766 | |||
1767 | INIT_LIST_HEAD(&pcs->irqs); | ||
1768 | pcs->chip.name = name; | ||
1769 | pcs->chip.irq_ack = pcs_irq_mask; | ||
1770 | pcs->chip.irq_mask = pcs_irq_mask; | ||
1771 | pcs->chip.irq_unmask = pcs_irq_unmask; | ||
1772 | pcs->chip.irq_set_wake = pcs_irq_set_wake; | ||
1773 | |||
1774 | if (PCS_QUIRK_HAS_SHARED_IRQ) { | ||
1775 | int res; | ||
1776 | |||
1777 | res = request_irq(pcs_soc->irq, pcs_irq_handler, | ||
1778 | IRQF_SHARED | IRQF_NO_SUSPEND, | ||
1779 | name, pcs_soc); | ||
1780 | if (res) { | ||
1781 | pcs_soc->irq = -1; | ||
1782 | return res; | ||
1783 | } | ||
1784 | } else { | ||
1785 | irq_set_handler_data(pcs_soc->irq, pcs_soc); | ||
1786 | irq_set_chained_handler(pcs_soc->irq, | ||
1787 | pcs_irq_chain_handler); | ||
1788 | } | ||
1789 | |||
1790 | /* | ||
1791 | * We can use the register offset as the hardirq | ||
1792 | * number as irq_domain_add_simple maps them lazily. | ||
1793 | * This way we can easily support more than one | ||
1794 | * interrupt per function if needed. | ||
1795 | */ | ||
1796 | num_irqs = pcs->size; | ||
1797 | |||
1798 | pcs->domain = irq_domain_add_simple(np, num_irqs, 0, | ||
1799 | &pcs_irqdomain_ops, | ||
1800 | pcs_soc); | ||
1801 | if (!pcs->domain) { | ||
1802 | irq_set_chained_handler(pcs_soc->irq, NULL); | ||
1803 | return -EINVAL; | ||
1804 | } | ||
1805 | |||
1806 | return 0; | ||
1807 | } | ||
1507 | 1808 | ||
1508 | #ifdef CONFIG_PM | 1809 | #ifdef CONFIG_PM |
1509 | static int pinctrl_single_suspend(struct platform_device *pdev, | 1810 | static int pinctrl_single_suspend(struct platform_device *pdev, |
@@ -1549,12 +1850,14 @@ static int pcs_probe(struct platform_device *pdev) | |||
1549 | return -ENOMEM; | 1850 | return -ENOMEM; |
1550 | } | 1851 | } |
1551 | pcs->dev = &pdev->dev; | 1852 | pcs->dev = &pdev->dev; |
1853 | raw_spin_lock_init(&pcs->lock); | ||
1552 | mutex_init(&pcs->mutex); | 1854 | mutex_init(&pcs->mutex); |
1553 | INIT_LIST_HEAD(&pcs->pingroups); | 1855 | INIT_LIST_HEAD(&pcs->pingroups); |
1554 | INIT_LIST_HEAD(&pcs->functions); | 1856 | INIT_LIST_HEAD(&pcs->functions); |
1555 | INIT_LIST_HEAD(&pcs->gpiofuncs); | 1857 | INIT_LIST_HEAD(&pcs->gpiofuncs); |
1556 | soc = match->data; | 1858 | soc = match->data; |
1557 | pcs->flags = soc->flags; | 1859 | pcs->flags = soc->flags; |
1860 | memcpy(&pcs->socdata, soc, sizeof(*soc)); | ||
1558 | 1861 | ||
1559 | PCS_GET_PROP_U32("pinctrl-single,register-width", &pcs->width, | 1862 | PCS_GET_PROP_U32("pinctrl-single,register-width", &pcs->width, |
1560 | "register width not specified\n"); | 1863 | "register width not specified\n"); |
@@ -1642,6 +1945,16 @@ static int pcs_probe(struct platform_device *pdev) | |||
1642 | if (ret < 0) | 1945 | if (ret < 0) |
1643 | goto free; | 1946 | goto free; |
1644 | 1947 | ||
1948 | pcs->socdata.irq = irq_of_parse_and_map(np, 0); | ||
1949 | if (pcs->socdata.irq) | ||
1950 | pcs->flags |= PCS_FEAT_IRQ; | ||
1951 | |||
1952 | if (PCS_HAS_IRQ) { | ||
1953 | ret = pcs_irq_init_chained_handler(pcs, np); | ||
1954 | if (ret < 0) | ||
1955 | dev_warn(pcs->dev, "initialized with no interrupts\n"); | ||
1956 | } | ||
1957 | |||
1645 | dev_info(pcs->dev, "%i pins at pa %p size %u\n", | 1958 | dev_info(pcs->dev, "%i pins at pa %p size %u\n", |
1646 | pcs->desc.npins, pcs->base, pcs->size); | 1959 | pcs->desc.npins, pcs->base, pcs->size); |
1647 | 1960 | ||
@@ -1665,6 +1978,12 @@ static int pcs_remove(struct platform_device *pdev) | |||
1665 | return 0; | 1978 | return 0; |
1666 | } | 1979 | } |
1667 | 1980 | ||
1981 | static const struct pcs_soc_data pinctrl_single_omap_wkup = { | ||
1982 | .flags = PCS_QUIRK_SHARED_IRQ, | ||
1983 | .irq_enable_mask = (1 << 14), /* OMAP_WAKEUP_EN */ | ||
1984 | .irq_status_mask = (1 << 15), /* OMAP_WAKEUP_EVENT */ | ||
1985 | }; | ||
1986 | |||
1668 | static const struct pcs_soc_data pinctrl_single = { | 1987 | static const struct pcs_soc_data pinctrl_single = { |
1669 | }; | 1988 | }; |
1670 | 1989 | ||
@@ -1673,6 +1992,9 @@ static const struct pcs_soc_data pinconf_single = { | |||
1673 | }; | 1992 | }; |
1674 | 1993 | ||
1675 | static struct of_device_id pcs_of_match[] = { | 1994 | static struct of_device_id pcs_of_match[] = { |
1995 | { .compatible = "ti,omap3-padconf", .data = &pinctrl_single_omap_wkup }, | ||
1996 | { .compatible = "ti,omap4-padconf", .data = &pinctrl_single_omap_wkup }, | ||
1997 | { .compatible = "ti,omap5-padconf", .data = &pinctrl_single_omap_wkup }, | ||
1676 | { .compatible = "pinctrl-single", .data = &pinctrl_single }, | 1998 | { .compatible = "pinctrl-single", .data = &pinctrl_single }, |
1677 | { .compatible = "pinconf-single", .data = &pinconf_single }, | 1999 | { .compatible = "pinconf-single", .data = &pinconf_single }, |
1678 | { }, | 2000 | { }, |