Re: [PATCH 2/3] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x.

2013-11-12 Thread Michael Trimarchi
Hi

On Mon, Nov 11, 2013 at 9:06 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 as well as the implementation
> of omap_hsmmc_pin_init.
>
> Signed-off-by: Andreas Fenkart 
> ---
>  .../devicetree/bindings/mmc/ti-omap-hsmmc.txt  |   28 ++-
>  drivers/mmc/host/omap_hsmmc.c  |  189 
> ++--
>  include/linux/platform_data/mmc-omap.h |4 +
>  3 files changed, 207 insertions(+), 14 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt 
> b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> index 1136e6b..146f3ad 100644
> --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> @@ -21,8 +21,11 @@ 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
>  ti,quirk-swakup-missing: SOC missing the swakeup line, will not detect
> -SDIO irq while in suspend. Fallback to polling. Affected chips are
> -am335x,
> +SDIO irq while in suspend. The workaround is to reconfigure the dat1 line as 
> a
> +GPIO upon suspend. Beyond this option and the GPIO config, you also need to 
> set
> +named pinctrl states "default", "active" and "idle ", see example below.  The
> +MMC driver will then then toggle between default and idle during the runtime
> +Affected chips are am335x,
>
>  --
>  | PRCM |
> @@ -49,3 +52,24 @@ Example:
> vmmc-supply = <&vmmc>; /* phandle to regulator node */
> ti,non-removable;
> };
> +
> +[am335x with with gpio for sdio irq]
> +
> +   mmc1_cirq_pin: pinmux_cirq_pin {
> +   pinctrl-single,pins = <
> +   0x0f8 0x3f  /* MMC0_DAT1 as GPIO2_28 */
> +   >;
> +   };
> +
> +   mmc1: mmc@4806 {
> +   ti,non-removable;
> +   bus-width = <4>;
> +   vmmc-supply = <&ldo2_reg>;
> +   vmmc_aux-supply = <&vmmc>;
> +   ti,quirk-swakeup-missing;
> +   pinctrl-names = "default", "active", "idle";
> +   pinctrl-0 = <&mmc1_pins>;
> +   pinctrl-1 = <&mmc1_pins>;
> +   pinctrl-2 = <&mmc1_cirq_pin>;
> +   ti,cirq-gpio = <&gpio3 28 0>;
> +   };
> diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
> index 6b0ec55..5a7fb4b 100644
> --- a/drivers/mmc/host/omap_hsmmc.c
> +++ b/drivers/mmc/host/omap_hsmmc.c
> @@ -36,6 +36,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -213,11 +214,30 @@ struct omap_hsmmc_host {
> int req_in_progress;
> int flags;
>  #define HSMMC_SDIO_IRQ_ENABLED (1 << 0)/* SDIO irq enabled */
> +#define HSMMC_SWAKEUP_QUIRK(1 << 1)
> +#define HSMMC_CIRQ_GPIO_FIRED  (1 << 2)
>
> struct omap_hsmmc_next  next_data;
> +   struct pinctrl  *pinctrl;
> +   struct pinctrl_state*fixed, *active, *idle;
> struct  omap_mmc_platform_data  *pdata;
>  };
>
> +static irqreturn_t omap_hsmmc_cirq(int irq, void *dev_id)
> +{
> +   struct omap_hsmmc_host *host = dev_id;
> +   unsigned long flags;
> +
> +   spin_lock_irqsave(&host->irq_lock, flags);
> +   host->flags |= HSMMC_CIRQ_GPIO_FIRED;
> +   disable_irq_nosync(mmc_slot(host).sdio_irq);
> +   spin_unlock_irqrestore(&host->irq_lock, flags);
> +
> +   pm_request_resume(host->dev); /* no use counter */
> +
> +   return IRQ_HANDLED;
> +}
> +
>  static int omap_hsmmc_card_detect(struct device *dev, int slot)
>  {
> struct omap_hsmmc_host *host = dev_get_drvdata(dev);
> @@ -452,10 +472,25 @@ static int omap_hsmmc_gpio_init(struct 
> omap_mmc_platform_data *pdata)
> } else
> pdata->slots[0].gpio_wp = -EINVAL;
>
> +   if (gpio_is_valid(pdata->slots[0].gpio_cirq)) {
> +   pdata->slots[0].sdio_irq =
> +   gpio_to_irq(pdata->slots[0].gpio_cirq);
> +   ret = gpio_request_one(pdata->slots[0].gpio_cirq, 
> GPIOF_DIR_IN,
> +  "sdio_cirq");
> +   if (ret)
> +   goto err_free_ro;
> +
> +   } else {
> +   pdata->slots[0].gpio_cirq = -EINVAL;
> +   }
> +
> +
> return 0;
>
> +err_free_ro:
> +   if (gpio_is_valid(pdata->slots[0].gpio_wp))
>  err_free_wp:
> -   gpio_free(pdata->slots[0].gpio_wp);
> +   

Re: [PATCH 2/3] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x.

2013-11-11 Thread Michael Trimarchi
Hi

On Mon, Nov 11, 2013 at 7:52 PM,   wrote:
> From: Andreas Fenkart 
>
> 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 as well as the implementation
> of omap_hsmmc_pin_init.
>
> Signed-off-by: Andreas Fenkart 
> ---
>  .../devicetree/bindings/mmc/ti-omap-hsmmc.txt  |   28 ++-
>  drivers/mmc/host/omap_hsmmc.c  |  195 
> ++--
>  include/linux/platform_data/mmc-omap.h |4 +
>  3 files changed, 213 insertions(+), 14 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt 
> b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> index 1136e6b..146f3ad 100644
> --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> @@ -21,8 +21,11 @@ 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
>  ti,quirk-swakup-missing: SOC missing the swakeup line, will not detect
> -SDIO irq while in suspend. Fallback to polling. Affected chips are
> -am335x,
> +SDIO irq while in suspend. The workaround is to reconfigure the dat1 line as 
> a
> +GPIO upon suspend. Beyond this option and the GPIO config, you also need to 
> set
> +named pinctrl states "default", "active" and "idle ", see example below.  The
> +MMC driver will then then toggle between default and idle during the runtime
> +Affected chips are am335x,
>
>  --
>  | PRCM |
> @@ -49,3 +52,24 @@ Example:
> vmmc-supply = <&vmmc>; /* phandle to regulator node */
> ti,non-removable;
> };
> +
> +[am335x with with gpio for sdio irq]
> +
> +   mmc1_cirq_pin: pinmux_cirq_pin {
> +   pinctrl-single,pins = <
> +   0x0f8 0x3f  /* MMC0_DAT1 as GPIO2_28 */
> +   >;
> +   };
> +
> +   mmc1: mmc@4806 {
> +   ti,non-removable;
> +   bus-width = <4>;
> +   vmmc-supply = <&ldo2_reg>;
> +   vmmc_aux-supply = <&vmmc>;
> +   ti,quirk-swakeup-missing;
> +   pinctrl-names = "default", "active", "idle";
> +   pinctrl-0 = <&mmc1_pins>;
> +   pinctrl-1 = <&mmc1_pins>;
> +   pinctrl-2 = <&mmc1_cirq_pin>;
> +   ti,cirq-gpio = <&gpio3 28 0>;
> +   };
> diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
> index 6b0ec55..e880b44 100644
> --- a/drivers/mmc/host/omap_hsmmc.c
> +++ b/drivers/mmc/host/omap_hsmmc.c
> @@ -36,6 +36,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -213,11 +214,30 @@ struct omap_hsmmc_host {
> int req_in_progress;
> int flags;
>  #define HSMMC_SDIO_IRQ_ENABLED (1 << 0)/* SDIO irq enabled */
> +#define HSMMC_SWAKEUP_QUIRK(1 << 1)
> +#define HSMMC_CIRQ_GPIO_FIRED  (1 << 2)
>
> struct omap_hsmmc_next  next_data;
> +   struct pinctrl  *pinctrl;
> +   struct pinctrl_state*fixed, *active, *idle;
> struct  omap_mmc_platform_data  *pdata;
>  };
>
> +static irqreturn_t omap_hsmmc_cirq(int irq, void *dev_id)
> +{
> +   struct omap_hsmmc_host *host = dev_id;
> +   unsigned long flags;
> +
> +   spin_lock_irqsave(&host->irq_lock, flags);
> +   host->flags |= HSMMC_CIRQ_GPIO_FIRED;
> +   disable_irq_nosync(mmc_slot(host).sdio_irq);
> +   spin_unlock_irqrestore(&host->irq_lock, flags);
> +
> +   pm_request_resume(host->dev); /* no use counter */
> +
> +   return IRQ_HANDLED;
> +}
> +
>  static int omap_hsmmc_card_detect(struct device *dev, int slot)
>  {
> struct omap_hsmmc_host *host = dev_get_drvdata(dev);
> @@ -452,10 +472,31 @@ static int omap_hsmmc_gpio_init(struct 
> omap_mmc_platform_data *pdata)
> } else
> pdata->slots[0].gpio_wp = -EINVAL;
>
> +   if (pdata->slots[0].gpio_cirq > 0 &&
> +   gpio_is_valid(pdata->slots[0].gpio_cirq)) {

Is ok only gpio_is_valid?

> +   pdata->slots[0].sdio_irq =
> +   gpio_to_irq(pdata->slots[0].gpio_cirq);
> +
> +   ret = gpio_request(pdata->slots[0].gpio_cirq, "sdio_cirq");
> +   if (ret)
> +   goto err_free_ro;
> +   ret = gpio_direction_input(pdata->slots[0].gpio_cirq);
> +   if (ret)
> +   goto err_free_cirq;

Can you use gpio_request_one?


Michael

> +
> +   } else {
> +   pdata->s