Message ID | 1380971830-21492-4-git-send-email-afenkart@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Thanks Andreas for the patch, On Saturday 05 October 2013 04:47 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, while in runtime > suspend, standard detection of the module block otherwise. > > Signed-off-by: Andreas Fenkart <afenkart@gmail.com> > > @@ -2293,23 +2440,66 @@ static int omap_hsmmc_resume(struct device *dev) > static int omap_hsmmc_runtime_suspend(struct device *dev) > { > struct omap_hsmmc_host *host; > + unsigned long flags; > + int ret = 0; > > host = platform_get_drvdata(to_platform_device(dev)); > omap_hsmmc_context_save(host); > dev_dbg(dev, "disabled\n"); > > - return 0; > + if (host->flags & HSMMC_SWAKEUP_QUIRK) { > + spin_lock_irqsave(&host->irq_lock, flags); > + OMAP_HSMMC_WRITE(host->base, ISE, 0); > + OMAP_HSMMC_WRITE(host->base, IE, 0); > + OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); > + spin_unlock_irqrestore(&host->irq_lock, flags); > + > + ret = pinctrl_select_state(host->pinctrl, host->idle); > + if (ret < 0) > + dev_warn(mmc_dev(host->mmc), "Unable to select idle pinmux\n"); > + > + enable_irq(mmc_slot(host).sdio_irq); > + } > + > + spin_lock_irqsave(&host->irq_lock, flags); > + /* infinite loop, if irq not cleared in omap_hsmmc_enable_sdio_irq */ > + host->flags |= HSMMC_RUNTIME_SUSPENDED; Can you provide more details about the infinite loop and how it will get recovered. > + spin_unlock_irqrestore(&host->irq_lock, flags); > + > + return ret; > } > > static int omap_hsmmc_runtime_resume(struct device *dev) > { > struct omap_hsmmc_host *host; > + unsigned long flags; > + int ret = 0; > > host = platform_get_drvdata(to_platform_device(dev)); > omap_hsmmc_context_restore(host); > dev_dbg(dev, "enabled\n"); > > - return 0; > + spin_lock_irqsave(&host->irq_lock, flags); > + /* infinite loop, if irq not cleared in omap_hsmmc_enable_sdio_irq */ > + host->flags &= ~HSMMC_RUNTIME_SUSPENDED; > + spin_unlock_irqrestore(&host->irq_lock, flags); > + > + if (host->flags & HSMMC_SWAKEUP_QUIRK) { > + disable_irq(mmc_slot(host).sdio_irq); > + > + ret = pinctrl_select_state(host->pinctrl, host->active); > + if (ret < 0) > + dev_warn(mmc_dev(host->mmc), "Unable to select active pinmux\n"); > + > + spin_lock_irqsave(&host->irq_lock, flags); > + if (host->flags & HSMMC_SDIO_IRQ_ENABLED) { > + OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); > + OMAP_HSMMC_WRITE(host->base, ISE, CIRQ_EN); > + OMAP_HSMMC_WRITE(host->base, IE, CIRQ_EN); > + } > + spin_unlock_irqrestore(&host->irq_lock, flags); > + } > + return ret; > } > > static struct dev_pm_ops omap_hsmmc_dev_pm_ops = { > diff --git a/include/linux/platform_data/mmc-omap.h b/include/linux/platform_data/mmc-omap.h > index 2bf1b30..fd5fff5 100644 > --- a/include/linux/platform_data/mmc-omap.h > +++ b/include/linux/platform_data/mmc-omap.h > @@ -115,6 +115,7 @@ struct omap_mmc_platform_data { > > int switch_pin; /* gpio (card detect) */ > int gpio_wp; /* gpio (write protect) */ > + int gpio_cirq; /* gpio (card irq) */ > > int (*set_bus_mode)(struct device *dev, int slot, int bus_mode); > int (*set_power)(struct device *dev, int slot, > @@ -145,6 +146,9 @@ struct omap_mmc_platform_data { > int card_detect_irq; > int (*card_detect)(struct device *dev, int slot); > > + /* SDIO IRQs */ > + int sdio_irq; > + > unsigned int ban_openended:1; > > } slots[OMAP_MMC_MAX_SLOTS]; > -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Sat, 5 Oct 2013 13:17:09 +0200 Andreas Fenkart <afenkart@gmail.com> 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, while in runtime > suspend, standard detection of the module block otherwise. > > Signed-off-by: Andreas Fenkart <afenkart@gmail.com> > > 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@48060000 { > + 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>; > + }; hi, I've been trying to get SD irq to work on my OMAP3 DM3730. I seems to need the magic to catch interrupts while FCLK is off, as the only way I can get it to work at the moment is to keep FCLK on. I discovered your patch and tried it out, but it doesn't seem to work for me. I have a Libertas WIFI chip attached to the second mmc (which is sometimes called mmc1, and sometimes mmc2 - very confusing!). I added: mmc2_cirq_pin: pinmux_cirq_pin { pinctrl-single,pins = < 0x012e (PIN_INPUT_PULLUP | MUX_MODE4) /* MMC2_DAT1 as GPIO5_5 */ >; }; and &mmc2 { ti,quirk-swakeup-missing; pinctrl-names = "default", "active", "idle"; pinctrl-0 = <&mmc2_pins>; pinctrl-1 = <&mmc2_pins>; pinctrl-2 = <&mmc2_cirq_pin>; ti,cirq-gpio = <&gpio5 5 0>; /* GPIO133 = 128+5 */ }; to my dts file but it doesn't make any apparent difference. Any idea what I might be doing wrong? (the base kernel I am applying patches to is from 8th Oct, commit 0e7a3ed04f0cd4311096d691888f88569310ee6c) BTW, - with the default polling, I get about 1Mb/sec with iperf - with sd-irq enabled and FCLK kept on the whole time, I get 4Mb/sec - with sd-irq enable, FCLK kept on, and the 5ms polling also running, I get over 5Mb/sec! Still much less than the 40Mb/sec that I would like to get... Thanks, NeilBrown
On Friday 18 October 2013 11:50 AM, NeilBrown wrote: > On Sat, 5 Oct 2013 13:17:09 +0200 Andreas Fenkart <afenkart@gmail.com> 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, while in runtime >> suspend, standard detection of the module block otherwise. >> >> Signed-off-by: Andreas Fenkart <afenkart@gmail.com> >> >> 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@48060000 { >> + 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>; >> + }; > > > hi, > I've been trying to get SD irq to work on my OMAP3 DM3730. > I seems to need the magic to catch interrupts while FCLK is off, as > the only way I can get it to work at the moment is to keep FCLK on. > > I discovered your patch and tried it out, but it doesn't seem to work for me. > > I have a Libertas WIFI chip attached to the second mmc (which is sometimes > called mmc1, and sometimes mmc2 - very confusing!). > I added: > mmc2_cirq_pin: pinmux_cirq_pin { > pinctrl-single,pins = < > 0x012e (PIN_INPUT_PULLUP | MUX_MODE4) /* MMC2_DAT1 as GPIO5_5 */ > >; > }; > > and > > &mmc2 { > ti,quirk-swakeup-missing; > pinctrl-names = "default", "active", "idle"; > pinctrl-0 = <&mmc2_pins>; > pinctrl-1 = <&mmc2_pins>; > pinctrl-2 = <&mmc2_cirq_pin>; > ti,cirq-gpio = <&gpio5 5 0>; /* GPIO133 = 128+5 */ > }; > > to my dts file but it doesn't make any apparent difference. > > Any idea what I might be doing wrong? > (the base kernel I am applying patches to is from 8th Oct, > commit 0e7a3ed04f0cd4311096d691888f88569310ee6c) > > BTW, > - with the default polling, I get about 1Mb/sec with iperf > - with sd-irq enabled and FCLK kept on the whole time, I get 4Mb/sec > - with sd-irq enable, FCLK kept on, and the 5ms polling also > running, I get over 5Mb/sec! > Still much less than the 40Mb/sec that I would like to get... > (removing svenkatr@ti.com) Hi, Can you check if you have bus-width property set ? bus-width = <4>; Thanks and Regards, Balaji T K > Thanks, > NeilBrown > -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, 18 Oct 2013 12:59:56 +0530 Balaji T K <balajitk@ti.com> wrote: > On Friday 18 October 2013 11:50 AM, NeilBrown wrote: > > On Sat, 5 Oct 2013 13:17:09 +0200 Andreas Fenkart <afenkart@gmail.com> 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, while in runtime > >> suspend, standard detection of the module block otherwise. > >> > >> Signed-off-by: Andreas Fenkart <afenkart@gmail.com> > >> > >> 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@48060000 { > >> + 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>; > >> + }; > > > > > > hi, > > I've been trying to get SD irq to work on my OMAP3 DM3730. > > I seems to need the magic to catch interrupts while FCLK is off, as > > the only way I can get it to work at the moment is to keep FCLK on. > > > > I discovered your patch and tried it out, but it doesn't seem to work for me. > > > > I have a Libertas WIFI chip attached to the second mmc (which is sometimes > > called mmc1, and sometimes mmc2 - very confusing!). > > I added: > > mmc2_cirq_pin: pinmux_cirq_pin { > > pinctrl-single,pins = < > > 0x012e (PIN_INPUT_PULLUP | MUX_MODE4) /* MMC2_DAT1 as GPIO5_5 */ > > >; > > }; > > > > and > > > > &mmc2 { > > ti,quirk-swakeup-missing; > > pinctrl-names = "default", "active", "idle"; > > pinctrl-0 = <&mmc2_pins>; > > pinctrl-1 = <&mmc2_pins>; > > pinctrl-2 = <&mmc2_cirq_pin>; > > ti,cirq-gpio = <&gpio5 5 0>; /* GPIO133 = 128+5 */ > > }; > > > > to my dts file but it doesn't make any apparent difference. > > > > Any idea what I might be doing wrong? > > (the base kernel I am applying patches to is from 8th Oct, > > commit 0e7a3ed04f0cd4311096d691888f88569310ee6c) > > > > BTW, > > - with the default polling, I get about 1Mb/sec with iperf > > - with sd-irq enabled and FCLK kept on the whole time, I get 4Mb/sec > > - with sd-irq enable, FCLK kept on, and the 5ms polling also > > running, I get over 5Mb/sec! > > Still much less than the 40Mb/sec that I would like to get... > > > (removing svenkatr@ti.com) > > Hi, > > Can you check if you have bus-width property set ? > bus-width = <4>; > > Yes I do. as well as the settings above I have: vmmc-supply = <&vaux4>; bus-width = <4>; ti,non-removable; cap-power-off-card; vaux4 is from a twl4030 and powers the wifi chip. 'cap-power-off-card' I added support for myself to so the card would power off when not in use. Thanks, NeilBrown
On Fri, Oct 18, 2013 at 8:20 AM, NeilBrown <neilb@suse.de> wrote: > On Sat, 5 Oct 2013 13:17:09 +0200 Andreas Fenkart <afenkart@gmail.com> 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, while in runtime >> suspend, standard detection of the module block otherwise. >> >> Signed-off-by: Andreas Fenkart <afenkart@gmail.com> >> >> 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@48060000 { >> + 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>; >> + }; > > > hi, > I've been trying to get SD irq to work on my OMAP3 DM3730. > I seems to need the magic to catch interrupts while FCLK is off, as > the only way I can get it to work at the moment is to keep FCLK on. > > I discovered your patch and tried it out, but it doesn't seem to work for me. > > I have a Libertas WIFI chip attached to the second mmc (which is sometimes > called mmc1, and sometimes mmc2 - very confusing!). Hi Neil, I have a DM3730 board with the same setup, Libertas (Marvell SD8686) wifi + bt chip attached to mmc2. I was going to try to add support for this to the DTS but it would be great if I can use your as a reference. Would you be so kind to share your DTS? Thanks a lot and best regards, Javier > I added: > mmc2_cirq_pin: pinmux_cirq_pin { > pinctrl-single,pins = < > 0x012e (PIN_INPUT_PULLUP | MUX_MODE4) /* MMC2_DAT1 as GPIO5_5 */ > >; > }; > > and > > &mmc2 { > ti,quirk-swakeup-missing; > pinctrl-names = "default", "active", "idle"; > pinctrl-0 = <&mmc2_pins>; > pinctrl-1 = <&mmc2_pins>; > pinctrl-2 = <&mmc2_cirq_pin>; > ti,cirq-gpio = <&gpio5 5 0>; /* GPIO133 = 128+5 */ > }; > > to my dts file but it doesn't make any apparent difference. > > Any idea what I might be doing wrong? > (the base kernel I am applying patches to is from 8th Oct, > commit 0e7a3ed04f0cd4311096d691888f88569310ee6c) > > BTW, > - with the default polling, I get about 1Mb/sec with iperf > - with sd-irq enabled and FCLK kept on the whole time, I get 4Mb/sec > - with sd-irq enable, FCLK kept on, and the 5ms polling also > running, I get over 5Mb/sec! > Still much less than the 40Mb/sec that I would like to get... > > Thanks, > NeilBrown -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, 18 Oct 2013 12:12:48 +0200 Javier Martinez Canillas <martinez.javier@gmail.com> wrote: > On Fri, Oct 18, 2013 at 8:20 AM, NeilBrown <neilb@suse.de> wrote: > > On Sat, 5 Oct 2013 13:17:09 +0200 Andreas Fenkart <afenkart@gmail.com> 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, while in runtime > >> suspend, standard detection of the module block otherwise. > >> > >> Signed-off-by: Andreas Fenkart <afenkart@gmail.com> > >> > >> 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@48060000 { > >> + 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>; > >> + }; > > > > > > hi, > > I've been trying to get SD irq to work on my OMAP3 DM3730. > > I seems to need the magic to catch interrupts while FCLK is off, as > > the only way I can get it to work at the moment is to keep FCLK on. > > > > I discovered your patch and tried it out, but it doesn't seem to work for me. > > > > I have a Libertas WIFI chip attached to the second mmc (which is sometimes > > called mmc1, and sometimes mmc2 - very confusing!). > > Hi Neil, > > I have a DM3730 board with the same setup, Libertas (Marvell SD8686) > wifi + bt chip attached to mmc2. > > I was going to try to add support for this to the DTS but it would be > great if I can use your as a reference. > > Would you be so kind to share your DTS? > My DTS is below. It contains an number of things that are not supported in mainline yet. Details can be found in git://neil.brown.name/gta04 mainline and http://git.neil.brown.name/?p=gta04.git;a=shortlog;h=refs/heads/mainline (this is my working tree and gets rebased and messed up regularly). NeilBrown /* * Copyright (C) 2013 Marek Belisko <marek@goldelico.com> * * Based on omap3-beagle-xm.dts * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ /dts-v1/; #define RFKILL_TYPE_GPS 6 #include "omap36xx.dtsi" / { model = "OMAP3 GTA04"; compatible = "ti,omap3-gta04", "ti,omap3"; chosen { bootargs = "console=ttyO2,115200n8 vram=12M omapfb.rotate_type=0 omapdss.def_disp=lcd root=/dev/mmcblk0p2 rw rootfstype=ext3 rootwait twl4030_charger.allow_usb=1 musb_hdrc.preserve_vbus=1 log_buf_len=8M ignore_loglevel no_console_suspend"; }; cpus { cpu@0 { cpu0-supply = <&vcc>; }; }; memory { device_type = "memory"; reg = <0x80000000 0x20000000>; /* 512 MB */ }; aux-keys { compatible = "gpio-keys"; aux-button { label = "aux"; linux,code = <169>; gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; gpio-key,wakeup; }; }; incoming-keys { compatible = "gpio-keys"; incoming-button { label = "Option"; linux,code = <240>; /* 176 for A3, 10 for A4 */ gpios = <&gpio6 16 GPIO_ACTIVE_HIGH>; gpio-key,wakeup; }; }; sound { compatible = "ti,omap-twl4030"; ti,model = "gta04"; ti,mcbsp = <&mcbsp2>; ti,codec = <&twl_audio>; }; panel { compatible = "tpo,td028ttec1"; display-name = "lcd"; source = "dpi.0"; data-lines = <24>; cs-gpio = <&gpio1 19 0>; scl-gpio = <&gpio1 12 0>; din-gpio = <&gpio1 18 0>; dout-gpio = <&gpio1 20 0>; }; backlight { compatible = "pwm-backlight"; label = "pwm-backlight"; pwms = <&pwm 0 2000000>; brightness-levels = <0 11 20 30 40 50 60 70 80 90 100>; default-brightness-level = <10>; }; pwm: omap-pwm { compatible = "ti,omap-pwm"; timers = <&timer11>; #pwm-cells = <2>; }; /* need to connect uart1 DTR line to vaux4 */ btdtr: gpio-reg.bt { compatible = "gpio_regulator"; vgpio-supply = <&vaux4>; microvolt = <3150000>; gpio-controller; #gpio-cells = <2>; }; gps-rfkill { compatible = "rfkill-regulator"; label = "GPS"; type = <RFKILL_TYPE_GPS>; vrfkill-supply = <&vsim>; }; gpsdtr: gps-onoff { compatible = "gpio-w2sg0004"; gpios = <&gpio5 17 0>, <&gpio5 19 0>; /* MODE0 PULL_ENA(8) INPUT_EN(256) PULL_UP(16) */ state-on = <280>; /* MODE4 PULL_ENA(8) INPUT_EN(256) PULL_UP(16) */ state-off = <284>; gpio-controller; #gpio-cells = <2>; }; }; &omap3_pmx_core { uart1_pins: pinmux_uart1_pins { pinctrl-single,pins = < 0x152 (PIN_INPUT | MUX_MODE0) /* uart1_rx.uart1_rx */ 0x14c (PIN_OUTPUT |MUX_MODE0) /* uart1_tx.uart1_tx */ >; }; uart2_pins: pinmux_uart2_pins { pinctrl-single,pins = < 0x14a (PIN_INPUT | MUX_MODE0) /* uart2_rx.uart2_rx */ 0x148 (PIN_OUTPUT | MUX_MODE0) /* uart2_tx.uart2_tx */ >; }; uart3_pins: pinmux_uart3_pins { pinctrl-single,pins = < 0x16e (PIN_INPUT | MUX_MODE0) /* uart3_rx.uart3_rx */ 0x170 (PIN_OUTPUT | MUX_MODE0) /* uart3_tx.uart3_tx */ >; }; mmc1_pins: pinmux_mmc1_pins { pinctrl-single,pins = < 0x114 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ 0x116 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ 0x118 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat0.sdmmc1_dat0 */ 0x11a (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat1.sdmmc1_dat1 */ 0x11c (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat2.sdmmc1_dat2 */ 0x11e (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat3.sdmmc1_dat3 */ >; }; mmc2_pins: pinmux_mmc2_pins { pinctrl-single,pins = < 0x128 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk.sdmmc2_clk */ 0x12a (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd.sdmmc2_cmd */ 0x12c (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat0.sdmmc2_dat0 */ 0x12e (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat1.sdmmc2_dat1 */ 0x130 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat2.sdmmc2_dat2 */ 0x132 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat3.sdmmc1_dat3 */ >; }; mmc2_cirq_pin: pinmux_cirq_pin { pinctrl-single,pins = < 0x012e (PIN_INPUT_PULLUP | MUX_MODE4) /* MMC2_DAT1 as GPIO5_5 */ >; }; }; &i2c1 { clock-frequency = <2600000>; twl: twl@48 { reg = <0x48>; interrupts = <7>; /* SYS_NIRQ cascaded to intc */ interrupt-parent = <&intc>; twl_audio: audio { compatible = "ti,twl4030-audio"; codec { }; }; vaux4: regulator-vaux4 { compatible = "ti,twl4030-vaux4"; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <3150000>; ti,allow_unsupported; }; }; }; #include "twl4030.dtsi" #include "twl4030_omap3.dtsi" &i2c2 { clock-frequency = <400000>; /* touch screen */ tsc2007: tsc2007@48 { compatible = "tsc2007"; reg = <0x48>; interrupt-parent = <&gpio6>; interrupts = <0 IRQ_TYPE_EDGE_FALLING>; model-number = <2007>; x-plate-ohms = <600>; pen-gpio = <&gpio6 0 GPIO_ACTIVE_LOW>; }; /* pressure sensor */ bmp085@77 { compatible = "bosch,bmp085"; reg = <0x77>; }; /* accelerometer */ bma180@41 { compatible = "bosch,bma180"; reg = <0x41>; interrupt-parent = <&gpio3>; interrupts = <19 IRQ_TYPE_LEVEL_HIGH>; }; /* leds */ tca: tca6507@45 { compatible = "ti,tca6507"; #address-cells = <1>; #size-cells = <0>; reg = <0x45>; gpio-controller; #gpio-cells = <2>; gta04_led0: red_aux@0 { label = "gta04:red:aux"; reg = <0x0>; }; gta04_led1: green_aux@1 { label = "gta04:green:aux"; reg = <0x1>; }; gta04_led3: red_power@3 { label = "gta04:red:power"; reg = <0x3>; linux,default-trigger = "default-on"; }; gta04_led4: green_power@4 { label = "gta04:green:power"; reg = <0x4>; }; wifi_reset@6 { label = "gta04:wlan:reset"; reg = <0x6>; make-gpio; }; }; /* gyroscope */ itg3200@68 { compatible = "invensense,itg3200"; reg = <0x68>; }; /* compass aka magnetometer */ hmc5843@1e { compatible = "honeywell,hmc5843"; reg = <0x1e>; }; }; &i2c3 { clock-frequency = <100000>; }; &usb_otg_hs { interface-type = <0>; usb-phy = <&usb2_phy>; mode = <3>; power = <50>; }; &mmc1 { pinctrl-names = "default"; pinctrl-0 = <&mmc1_pins>; vmmc-supply = <&vmmc1>; bus-width = <4>; ti,non-removable; cap-power-off-card; }; &mmc2 { vmmc-supply = <&vaux4>; bus-width = <4>; ti,non-removable; cap-power-off-card; reset-gpios = <&tca 0 GPIO_ACTIVE_HIGH>; ti,quirk-swakeup-missing; pinctrl-names = "default", "active", "idle"; pinctrl-0 = <&mmc2_pins>; pinctrl-1 = <&mmc2_pins>; pinctrl-2 = <&mmc2_cirq_pin>; ti,cirq-gpio = <&gpio5 5 0>; /* GPIO133 = 128+5 */ }; &mmc3 { status = "disabled"; }; &uart1 { pinctrl-names = "default"; pinctrl-0 = <&uart1_pins>; }; &uart2 { pinctrl-names = "default"; pinctrl-0 = <&uart2_pins>; }; &uart3 { pinctrl-names = "default"; pinctrl-0 = <&uart3_pins>; }; &charger { bb_uvolt = <3200000>; bb_uamp = <150>; }; &twl_power { ti,use_poweroff; }; &vpll2 { supply-dev = "omapdss_dpi.0"; supply = "vdds_dsi"; }; /* uart1 is bluetooth - need to connect DTR */ &uart1 { dtr = <&btdtr 0 GPIO_ACTIVE_HIGH>; }; &uart2 { dtr = <&gpsdtr 0 GPIO_ACTIVE_HIGH>; }; &vsim { regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; };
On Sat, Oct 19, 2013 at 1:14 AM, NeilBrown <neilb@suse.de> wrote: > On Fri, 18 Oct 2013 12:12:48 +0200 Javier Martinez Canillas > <martinez.javier@gmail.com> wrote: > >> On Fri, Oct 18, 2013 at 8:20 AM, NeilBrown <neilb@suse.de> wrote: >> > On Sat, 5 Oct 2013 13:17:09 +0200 Andreas Fenkart <afenkart@gmail.com> 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, while in runtime >> >> suspend, standard detection of the module block otherwise. >> >> >> >> Signed-off-by: Andreas Fenkart <afenkart@gmail.com> >> >> >> >> 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@48060000 { >> >> + 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>; >> >> + }; >> > >> > >> > hi, >> > I've been trying to get SD irq to work on my OMAP3 DM3730. >> > I seems to need the magic to catch interrupts while FCLK is off, as >> > the only way I can get it to work at the moment is to keep FCLK on. >> > >> > I discovered your patch and tried it out, but it doesn't seem to work for me. >> > >> > I have a Libertas WIFI chip attached to the second mmc (which is sometimes >> > called mmc1, and sometimes mmc2 - very confusing!). >> >> Hi Neil, >> >> I have a DM3730 board with the same setup, Libertas (Marvell SD8686) >> wifi + bt chip attached to mmc2. >> >> I was going to try to add support for this to the DTS but it would be >> great if I can use your as a reference. >> >> Would you be so kind to share your DTS? >> > > My DTS is below. It contains an number of things that are not supported in > mainline yet. Details can be found in > git://neil.brown.name/gta04 mainline > and > http://git.neil.brown.name/?p=gta04.git;a=shortlog;h=refs/heads/mainline > (this is my working tree and gets rebased and messed up regularly). > > NeilBrown > Hello Neil, Thanks a lot for your DTS and the pointers to your trees. Best regards, Javier > /* > * Copyright (C) 2013 Marek Belisko <marek@goldelico.com> > * > * Based on omap3-beagle-xm.dts > * > * This program is free software; you can redistribute it and/or modify > * it under the terms of the GNU General Public License version 2 as > * published by the Free Software Foundation. > */ > /dts-v1/; > #define RFKILL_TYPE_GPS 6 > #include "omap36xx.dtsi" > > / { > model = "OMAP3 GTA04"; > compatible = "ti,omap3-gta04", "ti,omap3"; > chosen { > bootargs = "console=ttyO2,115200n8 vram=12M omapfb.rotate_type=0 omapdss.def_disp=lcd root=/dev/mmcblk0p2 rw rootfstype=ext3 rootwait twl4030_charger.allow_usb=1 musb_hdrc.preserve_vbus=1 log_buf_len=8M ignore_loglevel no_console_suspend"; > }; > > cpus { > cpu@0 { > cpu0-supply = <&vcc>; > }; > }; > > memory { > device_type = "memory"; > reg = <0x80000000 0x20000000>; /* 512 MB */ > }; > > aux-keys { > compatible = "gpio-keys"; > > aux-button { > label = "aux"; > linux,code = <169>; > gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; > gpio-key,wakeup; > }; > }; > > incoming-keys { > compatible = "gpio-keys"; > > incoming-button { > label = "Option"; > linux,code = <240>; > /* 176 for A3, 10 for A4 */ > gpios = <&gpio6 16 GPIO_ACTIVE_HIGH>; > gpio-key,wakeup; > }; > }; > > sound { > compatible = "ti,omap-twl4030"; > ti,model = "gta04"; > > ti,mcbsp = <&mcbsp2>; > ti,codec = <&twl_audio>; > }; > > panel { > compatible = "tpo,td028ttec1"; > display-name = "lcd"; > source = "dpi.0"; > data-lines = <24>; > cs-gpio = <&gpio1 19 0>; > scl-gpio = <&gpio1 12 0>; > din-gpio = <&gpio1 18 0>; > dout-gpio = <&gpio1 20 0>; > }; > > backlight { > compatible = "pwm-backlight"; > label = "pwm-backlight"; > pwms = <&pwm 0 2000000>; > brightness-levels = <0 11 20 30 40 50 60 70 80 90 100>; > default-brightness-level = <10>; > }; > > pwm: omap-pwm { > compatible = "ti,omap-pwm"; > timers = <&timer11>; > #pwm-cells = <2>; > }; > > /* need to connect uart1 DTR line to vaux4 */ > btdtr: gpio-reg.bt { > compatible = "gpio_regulator"; > vgpio-supply = <&vaux4>; > microvolt = <3150000>; > gpio-controller; > #gpio-cells = <2>; > }; > > gps-rfkill { > compatible = "rfkill-regulator"; > label = "GPS"; > type = <RFKILL_TYPE_GPS>; > vrfkill-supply = <&vsim>; > }; > > gpsdtr: gps-onoff { > compatible = "gpio-w2sg0004"; > gpios = <&gpio5 17 0>, <&gpio5 19 0>; > /* MODE0 PULL_ENA(8) INPUT_EN(256) PULL_UP(16) */ > state-on = <280>; > /* MODE4 PULL_ENA(8) INPUT_EN(256) PULL_UP(16) */ > state-off = <284>; > gpio-controller; > #gpio-cells = <2>; > }; > }; > > &omap3_pmx_core { > uart1_pins: pinmux_uart1_pins { > pinctrl-single,pins = < > 0x152 (PIN_INPUT | MUX_MODE0) /* uart1_rx.uart1_rx */ > 0x14c (PIN_OUTPUT |MUX_MODE0) /* uart1_tx.uart1_tx */ > >; > }; > > uart2_pins: pinmux_uart2_pins { > pinctrl-single,pins = < > 0x14a (PIN_INPUT | MUX_MODE0) /* uart2_rx.uart2_rx */ > 0x148 (PIN_OUTPUT | MUX_MODE0) /* uart2_tx.uart2_tx */ > >; > }; > > uart3_pins: pinmux_uart3_pins { > pinctrl-single,pins = < > 0x16e (PIN_INPUT | MUX_MODE0) /* uart3_rx.uart3_rx */ > 0x170 (PIN_OUTPUT | MUX_MODE0) /* uart3_tx.uart3_tx */ > >; > }; > > mmc1_pins: pinmux_mmc1_pins { > pinctrl-single,pins = < > 0x114 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ > 0x116 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ > 0x118 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat0.sdmmc1_dat0 */ > 0x11a (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat1.sdmmc1_dat1 */ > 0x11c (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat2.sdmmc1_dat2 */ > 0x11e (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat3.sdmmc1_dat3 */ > >; > }; > mmc2_pins: pinmux_mmc2_pins { > pinctrl-single,pins = < > 0x128 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk.sdmmc2_clk */ > 0x12a (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd.sdmmc2_cmd */ > 0x12c (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat0.sdmmc2_dat0 */ > 0x12e (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat1.sdmmc2_dat1 */ > 0x130 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat2.sdmmc2_dat2 */ > 0x132 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat3.sdmmc1_dat3 */ > >; > }; > mmc2_cirq_pin: pinmux_cirq_pin { > pinctrl-single,pins = < > 0x012e (PIN_INPUT_PULLUP | MUX_MODE4) /* MMC2_DAT1 as GPIO5_5 */ > >; > }; > }; > > &i2c1 { > clock-frequency = <2600000>; > > twl: twl@48 { > reg = <0x48>; > interrupts = <7>; /* SYS_NIRQ cascaded to intc */ > interrupt-parent = <&intc>; > > twl_audio: audio { > compatible = "ti,twl4030-audio"; > codec { > }; > }; > vaux4: regulator-vaux4 { > compatible = "ti,twl4030-vaux4"; > regulator-min-microvolt = <2800000>; > regulator-max-microvolt = <3150000>; > ti,allow_unsupported; > }; > }; > }; > > #include "twl4030.dtsi" > #include "twl4030_omap3.dtsi" > > &i2c2 { > clock-frequency = <400000>; > > /* touch screen */ > tsc2007: tsc2007@48 { > compatible = "tsc2007"; > reg = <0x48>; > interrupt-parent = <&gpio6>; > interrupts = <0 IRQ_TYPE_EDGE_FALLING>; > model-number = <2007>; > x-plate-ohms = <600>; > pen-gpio = <&gpio6 0 GPIO_ACTIVE_LOW>; > }; > > /* pressure sensor */ > bmp085@77 { > compatible = "bosch,bmp085"; > reg = <0x77>; > }; > > /* accelerometer */ > bma180@41 { > compatible = "bosch,bma180"; > reg = <0x41>; > interrupt-parent = <&gpio3>; > interrupts = <19 IRQ_TYPE_LEVEL_HIGH>; > }; > > /* leds */ > tca: tca6507@45 { > compatible = "ti,tca6507"; > #address-cells = <1>; > #size-cells = <0>; > reg = <0x45>; > > gpio-controller; > #gpio-cells = <2>; > > gta04_led0: red_aux@0 { > label = "gta04:red:aux"; > reg = <0x0>; > }; > > gta04_led1: green_aux@1 { > label = "gta04:green:aux"; > reg = <0x1>; > }; > > gta04_led3: red_power@3 { > label = "gta04:red:power"; > reg = <0x3>; > linux,default-trigger = "default-on"; > }; > > gta04_led4: green_power@4 { > label = "gta04:green:power"; > reg = <0x4>; > }; > > wifi_reset@6 { > label = "gta04:wlan:reset"; > reg = <0x6>; > make-gpio; > }; > }; > > /* gyroscope */ > itg3200@68 { > compatible = "invensense,itg3200"; > reg = <0x68>; > }; > > /* compass aka magnetometer */ > hmc5843@1e { > compatible = "honeywell,hmc5843"; > reg = <0x1e>; > }; > }; > > &i2c3 { > clock-frequency = <100000>; > }; > > &usb_otg_hs { > interface-type = <0>; > usb-phy = <&usb2_phy>; > mode = <3>; > power = <50>; > }; > > &mmc1 { > pinctrl-names = "default"; > pinctrl-0 = <&mmc1_pins>; > vmmc-supply = <&vmmc1>; > bus-width = <4>; > ti,non-removable; > cap-power-off-card; > }; > > &mmc2 { > vmmc-supply = <&vaux4>; > bus-width = <4>; > ti,non-removable; > cap-power-off-card; > reset-gpios = <&tca 0 GPIO_ACTIVE_HIGH>; > > ti,quirk-swakeup-missing; > pinctrl-names = "default", "active", "idle"; > pinctrl-0 = <&mmc2_pins>; > pinctrl-1 = <&mmc2_pins>; > pinctrl-2 = <&mmc2_cirq_pin>; > ti,cirq-gpio = <&gpio5 5 0>; /* GPIO133 = 128+5 */ > }; > > &mmc3 { > status = "disabled"; > }; > > &uart1 { > pinctrl-names = "default"; > pinctrl-0 = <&uart1_pins>; > }; > > &uart2 { > pinctrl-names = "default"; > pinctrl-0 = <&uart2_pins>; > }; > > &uart3 { > pinctrl-names = "default"; > pinctrl-0 = <&uart3_pins>; > }; > > &charger { > bb_uvolt = <3200000>; > bb_uamp = <150>; > }; > > &twl_power { > ti,use_poweroff; > }; > > &vpll2 { > supply-dev = "omapdss_dpi.0"; > supply = "vdds_dsi"; > }; > > /* uart1 is bluetooth - need to connect DTR */ > &uart1 { > dtr = <&btdtr 0 GPIO_ACTIVE_HIGH>; > }; > &uart2 { > dtr = <&gpsdtr 0 GPIO_ACTIVE_HIGH>; > }; > > &vsim { > regulator-min-microvolt = <2800000>; > regulator-max-microvolt = <2800000>; > }; -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
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@48060000 { + 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 53beac4..a8894ee 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -36,6 +36,7 @@ #include <linux/mmc/core.h> #include <linux/mmc/mmc.h> #include <linux/io.h> +#include <linux/irq.h> #include <linux/gpio.h> #include <linux/regulator/consumer.h> #include <linux/pinctrl/consumer.h> @@ -214,11 +215,22 @@ struct omap_hsmmc_host { int flags; #define HSMMC_RUNTIME_SUSPENDED (1 << 0) /* Runtime suspended */ #define HSMMC_SDIO_IRQ_ENABLED (1 << 1) /* SDIO irq enabled */ +#define HSMMC_SWAKEUP_QUIRK (1 << 2) /* SDIO irq enabled */ 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; + + mmc_signal_sdio_irq(host->mmc); + return IRQ_HANDLED; +} + static int omap_hsmmc_card_detect(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); @@ -453,10 +465,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)) { + 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; + + } else { + pdata->slots[0].gpio_cirq = -EINVAL; + } + + return 0; +err_free_cirq: + gpio_free(pdata->slots[0].gpio_cirq); +err_free_ro: + if (gpio_is_valid(pdata->slots[0].gpio_wp)) err_free_wp: - gpio_free(pdata->slots[0].gpio_wp); + gpio_free(pdata->slots[0].gpio_wp); err_free_cd: if (gpio_is_valid(pdata->slots[0].switch_pin)) err_free_sp: @@ -470,6 +503,68 @@ static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata) gpio_free(pdata->slots[0].gpio_wp); if (gpio_is_valid(pdata->slots[0].switch_pin)) gpio_free(pdata->slots[0].switch_pin); + if (gpio_is_valid(pdata->slots[0].gpio_cirq)) + gpio_free(pdata->slots[0].gpio_cirq); +} + +static int omap_hsmmc_pin_init(struct omap_hsmmc_host *host) +{ + int ret; + + host->pinctrl = devm_pinctrl_get(host->dev); + if (IS_ERR(host->pinctrl)) { + dev_dbg(host->dev, "no pinctrl handle\n"); + ret = 0; + goto out; + } + + host->fixed = pinctrl_lookup_state(host->pinctrl, + PINCTRL_STATE_DEFAULT); + if (IS_ERR(host->fixed)) { + dev_dbg(host->dev, "pins are not configured from the driver\n"); + host->fixed = NULL; + ret = 0; + goto out; + } + + ret = pinctrl_select_state(host->pinctrl, host->fixed); + if (ret < 0) + goto err; + + /* For most cases we don't have wake-ups, and exit after this */ + host->active = pinctrl_lookup_state(host->pinctrl, "active"); + if (IS_ERR(host->active)) { + ret = PTR_ERR(host->active); + host->active = NULL; + return 0; + } + + host->idle = pinctrl_lookup_state(host->pinctrl, + PINCTRL_STATE_IDLE); + if (IS_ERR(host->idle)) { + ret = PTR_ERR(host->idle); + host->idle = NULL; + goto err; + } + + /* Let's make sure the active and idle states work */ + ret = pinctrl_select_state(host->pinctrl, host->idle); + if (ret < 0) + goto err; + + ret = pinctrl_select_state(host->pinctrl, host->active); + if (ret < 0) + goto err; + + dev_info(mmc_dev(host->mmc), "pins configured for wake-up events\n"); + + return 0; + +err: + dev_err(mmc_dev(host->mmc), "pins configuration error: %i\n", ret); + +out: + return ret; } /* @@ -1613,13 +1708,18 @@ static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable) spin_lock_irqsave(&host->irq_lock, flags); + if (!enable == !(host->flags & HSMMC_SDIO_IRQ_ENABLED)) { + /* sdio_irq is refcounted, keep in sync */ + goto out; + } + if (enable) host->flags |= HSMMC_SDIO_IRQ_ENABLED; else host->flags &= ~HSMMC_SDIO_IRQ_ENABLED; - /* if statement here with followup patch */ - { + if (!(host->flags & HSMMC_RUNTIME_SUSPENDED)) { + /* SIGBUS without without fclk */ irq_mask = OMAP_HSMMC_READ(host->base, ISE); if (enable) irq_mask |= CIRQ_EN; @@ -1638,6 +1738,16 @@ static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable) OMAP_HSMMC_READ(host->base, IE); } + if (host->flags & HSMMC_SWAKEUP_QUIRK) { + if (enable) { + enable_irq(mmc_slot(host).sdio_irq); + } else { + /* _nosync, see mmc_signal_sdio_irq */ + disable_irq_nosync(mmc_slot(host).sdio_irq); + } + } + +out: spin_unlock_irqrestore(&host->irq_lock, flags); } @@ -1797,6 +1907,7 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev) pdata->nr_slots = 1; pdata->slots[0].switch_pin = cd_gpio; pdata->slots[0].gpio_wp = wp_gpio; + pdata->slots[0].gpio_cirq = of_get_named_gpio(np, "ti,cirq-gpio", 0); if (of_find_property(np, "ti,non-removable", NULL)) { pdata->slots[0].nonremovable = true; @@ -1837,7 +1948,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) const struct of_device_id *match; dma_cap_mask_t mask; unsigned tx_req, rx_req; - struct pinctrl *pinctrl; match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev); if (match) { @@ -2075,12 +2185,35 @@ static int omap_hsmmc_probe(struct platform_device *pdev) pdata->resume = omap_hsmmc_resume_cdirq; } - omap_hsmmc_disable_irq(host); + if ((mmc_slot(host).sdio_irq)) { + /* prevent auto-enabling of IRQ */ + irq_set_status_flags(mmc_slot(host).sdio_irq, IRQ_NOAUTOEN); + ret = request_irq(mmc_slot(host).sdio_irq, omap_hsmmc_cirq, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + mmc_hostname(mmc), host); + if (ret) { + dev_dbg(mmc_dev(host->mmc), + "Unable to grab MMC SDIO IRQ\n"); + goto err_irq_sdio; + } - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) - dev_warn(&pdev->dev, - "pins are not configured from the driver\n"); + /* + * sdio_irq is managed with ref count + * - start with initial value of 2 + * - omap_hsmmc_enable_sdio_irq enable/disable will -1/+1 + * - pm_suspend/pm_resume will -1/+1 + * + * if sdio irq are enabled AND runtime suspend on, only then + * the ref count drops to zero and the gpio irq is armed + */ + disable_irq(mmc_slot(host).sdio_irq); /* -> ref cnt == 2 */ + } + + ret = omap_hsmmc_pin_init(host); + if (ret) + goto err_pinctrl_state; + + omap_hsmmc_disable_irq(host); /* * For now, only support SDIO interrupt if we are booted with @@ -2093,8 +2226,14 @@ static int omap_hsmmc_probe(struct platform_device *pdev) mmc->caps |= MMC_CAP_SDIO_IRQ; if (of_find_property(host->dev->of_node, "ti,quirk-swakeup-missing", NULL)) { - /* no wakeup from deeper power states, use polling */ - mmc->caps &= ~MMC_CAP_SDIO_IRQ; + /* no wakeup from deeper power states, use GPIO */ + if (!host->idle || !mmc_slot(host).sdio_irq) { + dev_err(mmc_dev(host->mmc), + "Missing GPIO config or pinctrl idle state\n"); + goto err_pinctrl_state; + } + + host->flags |= HSMMC_SWAKEUP_QUIRK; } } @@ -2122,7 +2261,13 @@ static int omap_hsmmc_probe(struct platform_device *pdev) err_slot_name: mmc_remove_host(mmc); - free_irq(mmc_slot(host).card_detect_irq, host); +err_pinctrl_state: + devm_pinctrl_put(host->pinctrl); + if ((mmc_slot(host).sdio_irq)) + free_irq(mmc_slot(host).sdio_irq, host); +err_irq_sdio: + if ((mmc_slot(host).card_detect_irq)) + free_irq(mmc_slot(host).card_detect_irq, host); err_irq_cd: if (host->use_reg) omap_hsmmc_reg_put(host); @@ -2167,13 +2312,15 @@ static int omap_hsmmc_remove(struct platform_device *pdev) if (host->pdata->cleanup) host->pdata->cleanup(&pdev->dev); free_irq(host->irq, host); + if ((mmc_slot(host).sdio_irq)) + free_irq(mmc_slot(host).sdio_irq, host); if (mmc_slot(host).card_detect_irq) free_irq(mmc_slot(host).card_detect_irq, host); - if (host->tx_chan) dma_release_channel(host->tx_chan); if (host->rx_chan) dma_release_channel(host->rx_chan); + devm_pinctrl_put(host->pinctrl); pm_runtime_put_sync(host->dev); pm_runtime_disable(host->dev); @@ -2293,23 +2440,66 @@ static int omap_hsmmc_resume(struct device *dev) static int omap_hsmmc_runtime_suspend(struct device *dev) { struct omap_hsmmc_host *host; + unsigned long flags; + int ret = 0; host = platform_get_drvdata(to_platform_device(dev)); omap_hsmmc_context_save(host); dev_dbg(dev, "disabled\n"); - return 0; + if (host->flags & HSMMC_SWAKEUP_QUIRK) { + spin_lock_irqsave(&host->irq_lock, flags); + OMAP_HSMMC_WRITE(host->base, ISE, 0); + OMAP_HSMMC_WRITE(host->base, IE, 0); + OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); + spin_unlock_irqrestore(&host->irq_lock, flags); + + ret = pinctrl_select_state(host->pinctrl, host->idle); + if (ret < 0) + dev_warn(mmc_dev(host->mmc), "Unable to select idle pinmux\n"); + + enable_irq(mmc_slot(host).sdio_irq); + } + + spin_lock_irqsave(&host->irq_lock, flags); + /* infinite loop, if irq not cleared in omap_hsmmc_enable_sdio_irq */ + host->flags |= HSMMC_RUNTIME_SUSPENDED; + spin_unlock_irqrestore(&host->irq_lock, flags); + + return ret; } static int omap_hsmmc_runtime_resume(struct device *dev) { struct omap_hsmmc_host *host; + unsigned long flags; + int ret = 0; host = platform_get_drvdata(to_platform_device(dev)); omap_hsmmc_context_restore(host); dev_dbg(dev, "enabled\n"); - return 0; + spin_lock_irqsave(&host->irq_lock, flags); + /* infinite loop, if irq not cleared in omap_hsmmc_enable_sdio_irq */ + host->flags &= ~HSMMC_RUNTIME_SUSPENDED; + spin_unlock_irqrestore(&host->irq_lock, flags); + + if (host->flags & HSMMC_SWAKEUP_QUIRK) { + disable_irq(mmc_slot(host).sdio_irq); + + ret = pinctrl_select_state(host->pinctrl, host->active); + if (ret < 0) + dev_warn(mmc_dev(host->mmc), "Unable to select active pinmux\n"); + + spin_lock_irqsave(&host->irq_lock, flags); + if (host->flags & HSMMC_SDIO_IRQ_ENABLED) { + OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); + OMAP_HSMMC_WRITE(host->base, ISE, CIRQ_EN); + OMAP_HSMMC_WRITE(host->base, IE, CIRQ_EN); + } + spin_unlock_irqrestore(&host->irq_lock, flags); + } + return ret; } static struct dev_pm_ops omap_hsmmc_dev_pm_ops = { diff --git a/include/linux/platform_data/mmc-omap.h b/include/linux/platform_data/mmc-omap.h index 2bf1b30..fd5fff5 100644 --- a/include/linux/platform_data/mmc-omap.h +++ b/include/linux/platform_data/mmc-omap.h @@ -115,6 +115,7 @@ struct omap_mmc_platform_data { int switch_pin; /* gpio (card detect) */ int gpio_wp; /* gpio (write protect) */ + int gpio_cirq; /* gpio (card irq) */ int (*set_bus_mode)(struct device *dev, int slot, int bus_mode); int (*set_power)(struct device *dev, int slot, @@ -145,6 +146,9 @@ struct omap_mmc_platform_data { int card_detect_irq; int (*card_detect)(struct device *dev, int slot); + /* SDIO IRQs */ + int sdio_irq; + unsigned int ban_openended:1; } slots[OMAP_MMC_MAX_SLOTS];
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, while in runtime suspend, standard detection of the module block otherwise. Signed-off-by: Andreas Fenkart <afenkart@gmail.com>