aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Fenkart <afenkart@gmail.com>2014-05-29 04:28:05 -0400
committerUlf Hansson <ulf.hansson@linaro.org>2014-07-09 05:26:06 -0400
commit455e5cd6f736478d63a076086c732d287623e366 (patch)
tree6d1e4b37041d8d7a7f7ac983143663fa64fb1289
parent97978a4439fb49d05fbc1dfd075e3c5fb22ea956 (diff)
mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x
The am335x can't detect pending cirq in PM runtime suspend. This patch reconfigures dat1 as a GPIO before going to suspend. SDIO interrupts are detected with the GPIO, the GPIO will only wake the module from suspend, SDIO irq detection will still happen through the IP block. Idea of remuxing the pins by Tony Lindgren. Code contributions from Tony Lindgren and Balaji T K <balajitk@ti.com> Signed-off-by: Andreas Fenkart <afenkart@gmail.com> Signed-off-by: Tony Lindgren <tony@atomide.com> Acked-by: Balaji T K <balajitk@ti.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt53
-rw-r--r--drivers/mmc/host/omap_hsmmc.c24
2 files changed, 74 insertions, 3 deletions
diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
index 0233ba7951e5..76bf087bc889 100644
--- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
+++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
@@ -57,3 +57,56 @@ Examples:
57 &edma 25>; 57 &edma 25>;
58 dma-names = "tx", "rx"; 58 dma-names = "tx", "rx";
59 }; 59 };
60
61[workaround for missing swakeup on am33xx]
62
63This SOC is missing the swakeup line, it will not detect SDIO irq
64while in suspend.
65
66 ------
67 | PRCM |
68 ------
69 ^ |
70 swakeup | | fclk
71 | v
72 ------ ------- -----
73 | card | -- CIRQ --> | hsmmc | -- IRQ --> | CPU |
74 ------ ------- -----
75
76In suspend the fclk is off and the module is disfunctional. Even register reads
77will fail. A small logic in the host will request fclk restore, when an
78external event is detected. Once the clock is restored, the host detects the
79event normally. Since am33xx doesn't have this line it never wakes from
80suspend.
81
82The workaround is to reconfigure the dat1 line as a GPIO upon suspend. To make
83this work, we need to set the named pinctrl states "default" and "idle".
84Prepare idle to remux dat1 as a gpio, and default to remux it back as sdio
85dat1. The MMC driver will then toggle between idle and default state during
86runtime.
87
88In summary:
891. select matching 'compatible' section, see example below.
902. specify pinctrl states "default" and "idle", "sleep" is optional.
913. specify the gpio irq used for detecting sdio irq in suspend
92
93If configuration is incomplete, a warning message is emitted "falling back to
94polling". Also check the "sdio irq mode" in /sys/kernel/debug/mmc0/regs. Mind
95not every application needs SDIO irq, e.g. MMC cards.
96
97 mmc1: mmc@48060100 {
98 compatible = "ti,am33xx-hsmmc";
99 ...
100 pinctrl-names = "default", "idle", "sleep"
101 pinctrl-0 = <&mmc1_pins>;
102 pinctrl-1 = <&mmc1_idle>;
103 pinctrl-2 = <&mmc1_sleep>;
104 ...
105 interrupts-extended = <&intc 64 &gpio2 28 0>;
106 };
107
108 mmc1_idle : pinmux_cirq_pin {
109 pinctrl-single,pins = <
110 0x0f8 0x3f /* GPIO2_28 */
111 >;
112 };
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 5167e55c0849..965672663ef0 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1754,15 +1754,33 @@ static int omap_hsmmc_configure_wake_irq(struct omap_hsmmc_host *host)
1754 * and need to remux SDIO DAT1 to GPIO for wake-up from idle. 1754 * and need to remux SDIO DAT1 to GPIO for wake-up from idle.
1755 */ 1755 */
1756 if (host->pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING) { 1756 if (host->pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING) {
1757 ret = -ENODEV; 1757 struct pinctrl *p = devm_pinctrl_get(host->dev);
1758 devm_free_irq(host->dev, host->wake_irq, host); 1758 if (!p) {
1759 goto err; 1759 ret = -ENODEV;
1760 goto err_free_irq;
1761 }
1762 if (IS_ERR(pinctrl_lookup_state(p, PINCTRL_STATE_DEFAULT))) {
1763 dev_info(host->dev, "missing default pinctrl state\n");
1764 devm_pinctrl_put(p);
1765 ret = -EINVAL;
1766 goto err_free_irq;
1767 }
1768
1769 if (IS_ERR(pinctrl_lookup_state(p, PINCTRL_STATE_IDLE))) {
1770 dev_info(host->dev, "missing idle pinctrl state\n");
1771 devm_pinctrl_put(p);
1772 ret = -EINVAL;
1773 goto err_free_irq;
1774 }
1775 devm_pinctrl_put(p);
1760 } 1776 }
1761 1777
1762 OMAP_HSMMC_WRITE(host->base, HCTL, 1778 OMAP_HSMMC_WRITE(host->base, HCTL,
1763 OMAP_HSMMC_READ(host->base, HCTL) | IWE); 1779 OMAP_HSMMC_READ(host->base, HCTL) | IWE);
1764 return 0; 1780 return 0;
1765 1781
1782err_free_irq:
1783 devm_free_irq(host->dev, host->wake_irq, host);
1766err: 1784err:
1767 dev_warn(host->dev, "no SDIO IRQ support, falling back to polling\n"); 1785 dev_warn(host->dev, "no SDIO IRQ support, falling back to polling\n");
1768 host->wake_irq = 0; 1786 host->wake_irq = 0;