diff mbox

[v14,6/6] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x

Message ID 1401352085-22781-7-git-send-email-afenkart@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Andreas Fenkart May 29, 2014, 8:28 a.m. UTC
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>

Comments

Balaji T K May 29, 2014, 1:41 p.m. UTC | #1
On Thursday 29 May 2014 01:58 PM, Andreas Fenkart wrote:
> 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>

Hi Chris/Ulf,

Can you please queue this series for 3.16

Thanks and Regards,
Balaji T K

>
> diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> index 0233ba7..76bf087 100644
> --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> @@ -57,3 +57,56 @@ Examples:
>   			&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 */
> +		>;
> +	};
> diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
> index 0febb17..35ac2e4 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)
>   	 * and need to remux SDIO DAT1 to GPIO for wake-up from idle.
>   	 */
>   	if (host->pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING) {
> -		ret = -ENODEV;
> -		devm_free_irq(host->dev, host->wake_irq, host);
> -		goto err;
> +		struct pinctrl *p = devm_pinctrl_get(host->dev);
> +		if (!p) {
> +			ret = -ENODEV;
> +			goto err_free_irq;
> +		}
> +		if (IS_ERR(pinctrl_lookup_state(p, PINCTRL_STATE_DEFAULT))) {
> +			dev_info(host->dev, "missing default pinctrl state\n");
> +			devm_pinctrl_put(p);
> +			ret = -EINVAL;
> +			goto err_free_irq;
> +		}
> +
> +		if (IS_ERR(pinctrl_lookup_state(p, PINCTRL_STATE_IDLE))) {
> +			dev_info(host->dev, "missing idle pinctrl state\n");
> +			devm_pinctrl_put(p);
> +			ret = -EINVAL;
> +			goto err_free_irq;
> +		}
> +		devm_pinctrl_put(p);
>   	}
>
>   	OMAP_HSMMC_WRITE(host->base, HCTL,
>   			 OMAP_HSMMC_READ(host->base, HCTL) | IWE);
>   	return 0;
>
> +err_free_irq:
> +	devm_free_irq(host->dev, host->wake_irq, host);
>   err:
>   	dev_warn(host->dev, "no SDIO IRQ support, falling back to polling\n");
>   	host->wake_irq = 0;
>

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tony Lindgren June 2, 2014, 10:38 p.m. UTC | #2
* Balaji T K <balajitk@ti.com> [140529 06:42]:
> On Thursday 29 May 2014 01:58 PM, Andreas Fenkart wrote:
> >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>
> 
> Hi Chris/Ulf,
> 
> Can you please queue this series for 3.16

Yes please, not seeing these in linux next yet.

Regards,

Tony
 
> >diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> >index 0233ba7..76bf087 100644
> >--- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> >+++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> >@@ -57,3 +57,56 @@ Examples:
> >  			&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 */
> >+		>;
> >+	};
> >diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
> >index 0febb17..35ac2e4 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)
> >  	 * and need to remux SDIO DAT1 to GPIO for wake-up from idle.
> >  	 */
> >  	if (host->pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING) {
> >-		ret = -ENODEV;
> >-		devm_free_irq(host->dev, host->wake_irq, host);
> >-		goto err;
> >+		struct pinctrl *p = devm_pinctrl_get(host->dev);
> >+		if (!p) {
> >+			ret = -ENODEV;
> >+			goto err_free_irq;
> >+		}
> >+		if (IS_ERR(pinctrl_lookup_state(p, PINCTRL_STATE_DEFAULT))) {
> >+			dev_info(host->dev, "missing default pinctrl state\n");
> >+			devm_pinctrl_put(p);
> >+			ret = -EINVAL;
> >+			goto err_free_irq;
> >+		}
> >+
> >+		if (IS_ERR(pinctrl_lookup_state(p, PINCTRL_STATE_IDLE))) {
> >+			dev_info(host->dev, "missing idle pinctrl state\n");
> >+			devm_pinctrl_put(p);
> >+			ret = -EINVAL;
> >+			goto err_free_irq;
> >+		}
> >+		devm_pinctrl_put(p);
> >  	}
> >
> >  	OMAP_HSMMC_WRITE(host->base, HCTL,
> >  			 OMAP_HSMMC_READ(host->base, HCTL) | IWE);
> >  	return 0;
> >
> >+err_free_irq:
> >+	devm_free_irq(host->dev, host->wake_irq, host);
> >  err:
> >  	dev_warn(host->dev, "no SDIO IRQ support, falling back to polling\n");
> >  	host->wake_irq = 0;
> >
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
index 0233ba7..76bf087 100644
--- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
+++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
@@ -57,3 +57,56 @@  Examples:
 			&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 */
+		>;
+	};
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 0febb17..35ac2e4 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)
 	 * and need to remux SDIO DAT1 to GPIO for wake-up from idle.
 	 */
 	if (host->pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING) {
-		ret = -ENODEV;
-		devm_free_irq(host->dev, host->wake_irq, host);
-		goto err;
+		struct pinctrl *p = devm_pinctrl_get(host->dev);
+		if (!p) {
+			ret = -ENODEV;
+			goto err_free_irq;
+		}
+		if (IS_ERR(pinctrl_lookup_state(p, PINCTRL_STATE_DEFAULT))) {
+			dev_info(host->dev, "missing default pinctrl state\n");
+			devm_pinctrl_put(p);
+			ret = -EINVAL;
+			goto err_free_irq;
+		}
+
+		if (IS_ERR(pinctrl_lookup_state(p, PINCTRL_STATE_IDLE))) {
+			dev_info(host->dev, "missing idle pinctrl state\n");
+			devm_pinctrl_put(p);
+			ret = -EINVAL;
+			goto err_free_irq;
+		}
+		devm_pinctrl_put(p);
 	}
 
 	OMAP_HSMMC_WRITE(host->base, HCTL,
 			 OMAP_HSMMC_READ(host->base, HCTL) | IWE);
 	return 0;
 
+err_free_irq:
+	devm_free_irq(host->dev, host->wake_irq, host);
 err:
 	dev_warn(host->dev, "no SDIO IRQ support, falling back to polling\n");
 	host->wake_irq = 0;