linux/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
Andreas Fenkart 455e5cd6f7 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>
2014-07-09 11:26:06 +02:00

113 lines
3.8 KiB
Plaintext

* TI Highspeed MMC host controller for OMAP
The Highspeed MMC Host Controller on TI OMAP family
provides an interface for MMC, SD, and SDIO types of memory cards.
This file documents differences between the core properties described
by mmc.txt and the properties used by the omap_hsmmc driver.
Required properties:
- compatible:
Should be "ti,omap2-hsmmc", for OMAP2 controllers
Should be "ti,omap3-hsmmc", for OMAP3 controllers
Should be "ti,omap3-pre-es3-hsmmc" for OMAP3 controllers pre ES3.0
Should be "ti,omap4-hsmmc", for OMAP4 controllers
Should be "ti,am33xx-hsmmc", for AM335x controllers
- ti,hwmods: Must be "mmc<n>", n is controller instance starting 1
Optional properties:
ti,dual-volt: boolean, supports dual voltage cards
<supply-name>-supply: phandle to the regulator device tree node
"supply-name" examples are "vmmc", "vmmc_aux" etc
ti,non-removable: non-removable slot (like eMMC)
ti,needs-special-reset: Requires a special softreset sequence
ti,needs-special-hs-handling: HSMMC IP needs special setting for handling High Speed
dmas: List of DMA specifiers with the controller specific format
as described in the generic DMA client binding. A tx and rx
specifier is required.
dma-names: List of DMA request names. These strings correspond
1:1 with the DMA specifiers listed in dmas. The string naming is
to be "rx" and "tx" for RX and TX DMA requests, respectively.
Examples:
[hwmod populated DMA resources]
mmc1: mmc@0x4809c000 {
compatible = "ti,omap4-hsmmc";
reg = <0x4809c000 0x400>;
ti,hwmods = "mmc1";
ti,dual-volt;
bus-width = <4>;
vmmc-supply = <&vmmc>; /* phandle to regulator node */
ti,non-removable;
};
[generic DMA request binding]
mmc1: mmc@0x4809c000 {
compatible = "ti,omap4-hsmmc";
reg = <0x4809c000 0x400>;
ti,hwmods = "mmc1";
ti,dual-volt;
bus-width = <4>;
vmmc-supply = <&vmmc>; /* phandle to regulator node */
ti,non-removable;
dmas = <&edma 24
&edma 25>;
dma-names = "tx", "rx";
};
[workaround for missing swakeup on am33xx]
This SOC is missing the swakeup line, it will not detect SDIO irq
while in suspend.
------
| PRCM |
------
^ |
swakeup | | fclk
| v
------ ------- -----
| card | -- CIRQ --> | hsmmc | -- IRQ --> | CPU |
------ ------- -----
In suspend the fclk is off and the module is disfunctional. Even register reads
will fail. A small logic in the host will request fclk restore, when an
external event is detected. Once the clock is restored, the host detects the
event normally. Since am33xx doesn't have this line it never wakes from
suspend.
The workaround is to reconfigure the dat1 line as a GPIO upon suspend. To make
this work, we need to set the named pinctrl states "default" and "idle".
Prepare idle to remux dat1 as a gpio, and default to remux it back as sdio
dat1. The MMC driver will then toggle between idle and default state during
runtime.
In summary:
1. select matching 'compatible' section, see example below.
2. specify pinctrl states "default" and "idle", "sleep" is optional.
3. specify the gpio irq used for detecting sdio irq in suspend
If configuration is incomplete, a warning message is emitted "falling back to
polling". Also check the "sdio irq mode" in /sys/kernel/debug/mmc0/regs. Mind
not every application needs SDIO irq, e.g. MMC cards.
mmc1: mmc@48060100 {
compatible = "ti,am33xx-hsmmc";
...
pinctrl-names = "default", "idle", "sleep"
pinctrl-0 = <&mmc1_pins>;
pinctrl-1 = <&mmc1_idle>;
pinctrl-2 = <&mmc1_sleep>;
...
interrupts-extended = <&intc 64 &gpio2 28 0>;
};
mmc1_idle : pinmux_cirq_pin {
pinctrl-single,pins = <
0x0f8 0x3f /* GPIO2_28 */
>;
};