linux-mmc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v7 0/4] mmc: omap_hsmmc: SDIO IRQ.
@ 2014-02-25 12:37 Andreas Fenkart
  2014-02-25 12:37 ` [PATCH v7 1/4] mmc: omap_hsmmc: Enable " Andreas Fenkart
                   ` (2 more replies)
  0 siblings, 3 replies; 18+ messages in thread
From: Andreas Fenkart @ 2014-02-25 12:37 UTC (permalink / raw)
  To: Chris Ball
  Cc: Tony Lindgren, Grant Likely, Felipe Balbi, Balaji T K, zonque,
	galak, linux-doc, linux-mmc, linux-omap, Andreas Fenkart

v7
- rebase on 3.14.0-rc3-49726-g77e15ec
- split omap_hsmmc_pin_init due to regression on omap-3730 platform
@tony pls try if it still works after applying patch 2?

v6
- rebase on Linux 3.13-rc3
- reformatting debugfs

v5
- fix compile error introduced by last minute one line fix

v4:
- switch to interrupts-extended format
- drop ti,swakeup-missing flag convert to comaptible section

v3:
- removed gpio_irq from platform_data

v2:
- incorparated changes as suggested by reviewers
- simplified workaround for am335x, gpio will now only wake
  the module from runtime suspend, not handle the sdio irq
  itself 

Andreas Fenkart (4):
  mmc: omap_hsmmc: Enable SDIO IRQ.
  mmc: omap_hsmmc: Remux SDIO pins within driver.
  mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on
    AM335x.
  mmc: omap_hsmmc: Extend debugfs for SDIO IRQ, GPIO and pinmux.

 .../devicetree/bindings/mmc/ti-omap-hsmmc.txt      |   50 ++++
 drivers/mmc/host/omap_hsmmc.c                      |  315 ++++++++++++++++++--
 include/linux/platform_data/mmc-omap.h             |    1 +
 3 files changed, 341 insertions(+), 25 deletions(-)

-- 
1.7.10.4


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v7 1/4] mmc: omap_hsmmc: Enable SDIO IRQ.
  2014-02-25 12:37 [PATCH v7 0/4] mmc: omap_hsmmc: SDIO IRQ Andreas Fenkart
@ 2014-02-25 12:37 ` Andreas Fenkart
  2014-02-27 21:33   ` Tony Lindgren
  2014-02-28 17:04   ` Balaji T K
  2014-02-25 12:37 ` [PATCH v7 2/4] mmc: omap_hsmmc: Remux SDIO pins within driver Andreas Fenkart
  2014-02-25 12:37 ` [PATCH v7 3/4] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x Andreas Fenkart
  2 siblings, 2 replies; 18+ messages in thread
From: Andreas Fenkart @ 2014-02-25 12:37 UTC (permalink / raw)
  To: Chris Ball
  Cc: Tony Lindgren, Grant Likely, Felipe Balbi, Balaji T K, zonque,
	galak, linux-doc, linux-mmc, linux-omap, Andreas Fenkart

For now, only support SDIO interrupt if we are booted with
DT. This is because some platforms need special quirks. And
we don't want to add new legacy mux platform init code
callbacks any longer as we are moving to DT based booting
anyways.

Signed-off-by: Andreas Fenkart <afenkart@gmail.com>

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index a5a38cc..bd3bb0c 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -131,6 +131,7 @@ static void apply_clk_hack(struct device *dev)
 #define TC_EN			(1 << 1)
 #define BWR_EN			(1 << 4)
 #define BRR_EN			(1 << 5)
+#define CIRQ_EN			(1 << 8)
 #define ERR_EN			(1 << 15)
 #define CTO_EN			(1 << 16)
 #define CCRC_EN			(1 << 17)
@@ -215,6 +216,9 @@ struct omap_hsmmc_host {
 	int			reqs_blocked;
 	int			use_reg;
 	int			req_in_progress;
+	int                     flags;
+#define HSMMC_SDIO_IRQ_ENABLED	(1 << 0)        /* SDIO irq enabled */
+
 	struct omap_hsmmc_next	next_data;
 	struct	omap_mmc_platform_data	*pdata;
 };
@@ -495,27 +499,40 @@ static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host)
 static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host,
 				  struct mmc_command *cmd)
 {
-	unsigned int irq_mask;
+	u32 irq_mask = INT_EN_MASK;
+	unsigned long flags;
 
 	if (host->use_dma)
-		irq_mask = INT_EN_MASK & ~(BRR_EN | BWR_EN);
-	else
-		irq_mask = INT_EN_MASK;
+		irq_mask &= ~(BRR_EN | BWR_EN);
 
 	/* Disable timeout for erases */
 	if (cmd->opcode == MMC_ERASE)
 		irq_mask &= ~DTO_EN;
 
+	spin_lock_irqsave(&host->irq_lock, flags);
 	OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
 	OMAP_HSMMC_WRITE(host->base, ISE, irq_mask);
+
+	/* latch pending CIRQ, but don't signal */
+	if (host->flags & HSMMC_SDIO_IRQ_ENABLED)
+		irq_mask |= CIRQ_EN;
 	OMAP_HSMMC_WRITE(host->base, IE, irq_mask);
+	spin_unlock_irqrestore(&host->irq_lock, flags);
 }
 
 static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host)
 {
-	OMAP_HSMMC_WRITE(host->base, ISE, 0);
-	OMAP_HSMMC_WRITE(host->base, IE, 0);
+	u32 irq_mask = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->irq_lock, flags);
+	/* no transfer running, need to signal cirq if enabled */
+	if (host->flags & HSMMC_SDIO_IRQ_ENABLED)
+		irq_mask |= CIRQ_EN;
+	OMAP_HSMMC_WRITE(host->base, ISE, irq_mask);
+	OMAP_HSMMC_WRITE(host->base, IE, irq_mask);
 	OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
+	spin_unlock_irqrestore(&host->irq_lock, flags);
 }
 
 /* Calculate divisor for the given clock frequency */
@@ -1078,8 +1095,12 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
 	int status;
 
 	status = OMAP_HSMMC_READ(host->base, STAT);
-	while (status & INT_EN_MASK && host->req_in_progress) {
-		omap_hsmmc_do_irq(host, status);
+	while (status & (INT_EN_MASK | CIRQ_EN)) {
+		if (host->req_in_progress)
+			omap_hsmmc_do_irq(host, status);
+
+		if (status & CIRQ_EN)
+			mmc_signal_sdio_irq(host->mmc);
 
 		/* Flush posted write */
 		status = OMAP_HSMMC_READ(host->base, STAT);
@@ -1591,6 +1612,37 @@ static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card)
 		mmc_slot(host).init_card(card);
 }
 
+static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+	struct omap_hsmmc_host *host = mmc_priv(mmc);
+	u32 irq_mask;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->irq_lock, flags);
+
+	irq_mask = OMAP_HSMMC_READ(host->base, ISE);
+	if (enable) {
+		host->flags |= HSMMC_SDIO_IRQ_ENABLED;
+		irq_mask |= CIRQ_EN;
+	} else {
+		host->flags &= ~HSMMC_SDIO_IRQ_ENABLED;
+		irq_mask &= ~CIRQ_EN;
+	}
+	OMAP_HSMMC_WRITE(host->base, IE, irq_mask);
+
+	/*
+	 * if enable, piggy back detection on current request
+	 * but always disable immediately
+	 */
+	if (!host->req_in_progress || !enable)
+		OMAP_HSMMC_WRITE(host->base, ISE, irq_mask);
+
+	/* flush posted write */
+	OMAP_HSMMC_READ(host->base, IE);
+
+	spin_unlock_irqrestore(&host->irq_lock, flags);
+}
+
 static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host)
 {
 	u32 hctl, capa, value;
@@ -1643,7 +1695,7 @@ static const struct mmc_host_ops omap_hsmmc_ops = {
 	.get_cd = omap_hsmmc_get_cd,
 	.get_ro = omap_hsmmc_get_ro,
 	.init_card = omap_hsmmc_init_card,
-	/* NYET -- enable_sdio_irq */
+	.enable_sdio_irq = omap_hsmmc_enable_sdio_irq,
 };
 
 #ifdef CONFIG_DEBUG_FS
@@ -1705,7 +1757,18 @@ static void omap_hsmmc_debugfs(struct mmc_host *mmc)
 #endif
 
 #ifdef CONFIG_OF
-static u16 omap4_reg_offset = 0x100;
+struct of_data {
+	u16 offset;
+	int flags;
+};
+
+static struct of_data omap4_data = {
+	.offset	= 0x100,
+};
+static struct of_data am33xx_data = {
+	.offset	= 0x100,
+	.flags	= OMAP_HSMMC_SWAKEUP_MISSING,
+};
 
 static const struct of_device_id omap_mmc_of_match[] = {
 	{
@@ -1716,7 +1779,11 @@ static const struct of_device_id omap_mmc_of_match[] = {
 	},
 	{
 		.compatible = "ti,omap4-hsmmc",
-		.data = &omap4_reg_offset,
+		.data = &omap4_data,
+	},
+	{
+		.compatible = "ti,am33xx-hsmmc",
+		.data = &am33xx_data,
 	},
 	{},
 };
@@ -1803,8 +1870,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 			return PTR_ERR(pdata);
 
 		if (match->data) {
-			const u16 *offsetp = match->data;
-			pdata->reg_offset = *offsetp;
+			const struct of_data *d = match->data;
+			pdata->reg_offset = d->offset;
+			pdata->controller_flags |= d->flags;
 		}
 	}
 
@@ -2020,6 +2088,21 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 		dev_warn(&pdev->dev,
 			"pins are not configured from the driver\n");
 
+	/*
+	 * For now, only support SDIO interrupt if we are booted with
+	 * DT. This is because some platforms need special quirks. And
+	 * we don't want to add new legacy mux platform init code
+	 * callbacks any longer as we are moving to DT based booting
+	 * anyways.
+	 */
+	if (pdev->dev.of_node) {
+		mmc->caps |= MMC_CAP_SDIO_IRQ;
+		if (pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING) {
+			/* no wakeup from deeper power states, use polling */
+			mmc->caps &= ~MMC_CAP_SDIO_IRQ;
+		}
+	}
+
 	omap_hsmmc_protect_card(host);
 
 	mmc_add_host(mmc);
diff --git a/include/linux/platform_data/mmc-omap.h b/include/linux/platform_data/mmc-omap.h
index 2bf1b30..51e70cf 100644
--- a/include/linux/platform_data/mmc-omap.h
+++ b/include/linux/platform_data/mmc-omap.h
@@ -28,6 +28,7 @@
  */
 #define OMAP_HSMMC_SUPPORTS_DUAL_VOLT		BIT(0)
 #define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ	BIT(1)
+#define OMAP_HSMMC_SWAKEUP_MISSING		BIT(2)
 
 struct mmc_card;
 
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v7 2/4] mmc: omap_hsmmc: Remux SDIO pins within driver.
  2014-02-25 12:37 [PATCH v7 0/4] mmc: omap_hsmmc: SDIO IRQ Andreas Fenkart
  2014-02-25 12:37 ` [PATCH v7 1/4] mmc: omap_hsmmc: Enable " Andreas Fenkart
@ 2014-02-25 12:37 ` Andreas Fenkart
  2014-02-27 21:36   ` Tony Lindgren
  2014-02-25 12:37 ` [PATCH v7 3/4] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x Andreas Fenkart
  2 siblings, 1 reply; 18+ messages in thread
From: Andreas Fenkart @ 2014-02-25 12:37 UTC (permalink / raw)
  To: Chris Ball
  Cc: Tony Lindgren, Grant Likely, Felipe Balbi, Balaji T K, zonque,
	galak, linux-doc, linux-mmc, linux-omap, Andreas Fenkart

This is a preparation for the am335x workaround where we reconfigure
dat1 as GPIO before going to suspend. If you don't specify active/idle
pinctrl there should be no change.

Idea of remuxing the pins by Tony Lindgren as well as the intial
implementation of omap_hsmmc_pin_init. All bugs are mine.

Signed-off-by: Andreas Fenkart <afenkart@gmail.com>

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index bd3bb0c..5e60925 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -220,6 +220,8 @@ struct omap_hsmmc_host {
 #define HSMMC_SDIO_IRQ_ENABLED	(1 << 0)        /* SDIO irq enabled */
 
 	struct omap_hsmmc_next	next_data;
+	struct pinctrl		*pinctrl;
+	struct pinctrl_state	*fixed, *active, *idle;
 	struct	omap_mmc_platform_data	*pdata;
 };
 
@@ -476,6 +478,70 @@ static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata)
 		gpio_free(pdata->slots[0].switch_pin);
 }
 
+static int omap_hsmmc_pin_init(struct omap_hsmmc_host *host)
+{
+	struct pinctrl *_pinctrl;
+	int ret;
+
+	_pinctrl = devm_pinctrl_get(host->dev);
+	if (IS_ERR(_pinctrl)) {
+		/* okay, if the bootloader set it up right */
+		dev_warn(host->dev, "no pinctrl handle\n");
+		return 0;
+	}
+
+	host->fixed = pinctrl_lookup_state(_pinctrl,
+					   PINCTRL_STATE_DEFAULT);
+	if (IS_ERR(host->fixed)) {
+		dev_info(host->dev,
+			 "pins are not configured from the driver\n");
+		host->fixed = NULL;
+		devm_pinctrl_put(_pinctrl);
+		return 0;
+	}
+
+	ret = pinctrl_select_state(_pinctrl, host->fixed);
+	if (ret < 0) {
+		dev_warn(host->dev, "select fixed pinctrl state failed %d\n", ret);
+		goto err;
+	}
+
+	/* For most cases we don't have wake-ups, and exit after this */
+	host->active = pinctrl_lookup_state(_pinctrl, "active");
+	if (IS_ERR(host->active)) {
+		ret = PTR_ERR(host->active);
+		host->active = NULL;
+		goto done;
+	}
+
+	host->idle = pinctrl_lookup_state(_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(_pinctrl, host->idle);
+	if (ret < 0)
+		goto err;
+
+	ret = pinctrl_select_state(_pinctrl, host->active);
+	if (ret < 0)
+		goto err;
+
+	dev_info(mmc_dev(host->mmc), "pins configured for wake-up events\n");
+
+done:
+	host->pinctrl = _pinctrl;
+	return 0;
+
+err:
+	dev_err(mmc_dev(host->mmc), "pins configuration error: %i\n", ret);
+	devm_pinctrl_put(_pinctrl);
+	return ret;
+}
+
 /*
  * Start clock to the card
  */
@@ -1858,7 +1924,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;
 
 	apply_clk_hack(&pdev->dev);
 
@@ -2083,10 +2148,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 
 	omap_hsmmc_disable_irq(host);
 
-	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-	if (IS_ERR(pinctrl))
-		dev_warn(&pdev->dev,
-			"pins are not configured from the driver\n");
+	ret = omap_hsmmc_pin_init(host);
+	if (ret)
+		goto err_pinctrl_state;
 
 	/*
 	 * For now, only support SDIO interrupt if we are booted with
@@ -2127,7 +2191,11 @@ 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);
+	if (host->pinctrl)
+		devm_pinctrl_put(host->pinctrl);
+err_pinctrl_state:
+	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);
@@ -2179,6 +2247,8 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
 		dma_release_channel(host->tx_chan);
 	if (host->rx_chan)
 		dma_release_channel(host->rx_chan);
+	if (host->pinctrl)
+		devm_pinctrl_put(host->pinctrl);
 
 	pm_runtime_put_sync(host->dev);
 	pm_runtime_disable(host->dev);
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v7 3/4] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x.
  2014-02-25 12:37 [PATCH v7 0/4] mmc: omap_hsmmc: SDIO IRQ Andreas Fenkart
  2014-02-25 12:37 ` [PATCH v7 1/4] mmc: omap_hsmmc: Enable " Andreas Fenkart
  2014-02-25 12:37 ` [PATCH v7 2/4] mmc: omap_hsmmc: Remux SDIO pins within driver Andreas Fenkart
@ 2014-02-25 12:37 ` Andreas Fenkart
  2014-02-25 12:49   ` [PATCH v7 4/4] mmc: omap_hsmmc: Extend debugfs for SDIO IRQ, GPIO and pinmux Andreas Fenkart
  2014-02-27 21:37   ` [PATCH v7 3/4] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x Tony Lindgren
  2 siblings, 2 replies; 18+ messages in thread
From: Andreas Fenkart @ 2014-02-25 12:37 UTC (permalink / raw)
  To: Chris Ball
  Cc: Tony Lindgren, Grant Likely, Felipe Balbi, Balaji T K, zonque,
	galak, linux-doc, linux-mmc, linux-omap, 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, all bugs are mine.

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 8c8908a..8e1195e 100644
--- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
+++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
@@ -55,3 +55,53 @@ 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 1) the named pinctrl
+states "default", "active" and "idle", 2) the gpio detecting
+sdio irq in suspend and 3) compatibe section, see example below.
+The MMC driver will then toggle between active and idle during
+the runtime. If configuration is incomplete, a warning message is
+emitted "falling back to polling".  Mind not every application
+needs SDIO irq, e.g. MMC cards Affected chips are am335x,
+probably others
+
+
+	mmc1: mmc@48060100 {
+		compatible = "ti,am33xx-hsmmc";
+		...
+		interrupts-extended = <&intc 64 &gpio2 28 0>;
+		...
+		pinctrl-names = "default", "active", "idle"
+		pinctrl-0 = <&mmc1_pins>;
+		pinctrl-1 = <&mmc1_pins>;
+		pinctrl-2 = <&mmc1_cirq_pin>;
+		...
+	};
+
+	mmc1_cirq_pin: 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 5e60925..452c05a 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -29,6 +29,7 @@
 #include <linux/timer.h>
 #include <linux/clk.h>
 #include <linux/of.h>
+#include <linux/of_irq.h>
 #include <linux/of_gpio.h>
 #include <linux/of_device.h>
 #include <linux/omap-dma.h>
@@ -36,6 +37,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>
@@ -206,6 +208,7 @@ struct omap_hsmmc_host {
 	u32			sysctl;
 	u32			capa;
 	int			irq;
+	int			gpio_sdio_irq;
 	int			use_dma, dma_ch;
 	struct dma_chan		*tx_chan;
 	struct dma_chan		*rx_chan;
@@ -218,6 +221,8 @@ 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_ENABLED (1 << 2)
 
 	struct omap_hsmmc_next	next_data;
 	struct pinctrl		*pinctrl;
@@ -225,6 +230,23 @@ struct omap_hsmmc_host {
 	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);
+	if (host->flags & HSMMC_CIRQ_GPIO_ENABLED) {
+		disable_irq_nosync(host->gpio_sdio_irq);
+		host->flags &= ~HSMMC_CIRQ_GPIO_ENABLED;
+	}
+	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);
@@ -1920,7 +1942,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 	struct mmc_host *mmc;
 	struct omap_hsmmc_host *host = NULL;
 	struct resource *res;
-	int ret, irq;
+	int ret, irq, _gpio_cirq;
 	const struct of_device_id *match;
 	dma_cap_mask_t mask;
 	unsigned tx_req, rx_req;
@@ -1956,6 +1978,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 	if (res == NULL || irq < 0)
 		return -ENXIO;
 
+	_gpio_cirq = 0;
+	if (pdev->dev.of_node)
+		_gpio_cirq = irq_of_parse_and_map(pdev->dev.of_node, 1);
+
 	res = request_mem_region(res->start, resource_size(res), pdev->name);
 	if (res == NULL)
 		return -EBUSY;
@@ -1977,6 +2003,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 	host->use_dma	= 1;
 	host->dma_ch	= -1;
 	host->irq	= irq;
+	host->gpio_sdio_irq = _gpio_cirq;
 	host->slot_id	= 0;
 	host->mapbase	= res->start + pdata->reg_offset;
 	host->base	= ioremap(host->mapbase, SZ_4K);
@@ -2162,8 +2189,28 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 	if (pdev->dev.of_node) {
 		mmc->caps |= MMC_CAP_SDIO_IRQ;
 		if (pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING) {
-			/* no wakeup from deeper power states, use polling */
-			mmc->caps &= ~MMC_CAP_SDIO_IRQ;
+			/* use GPIO to wakeup from deeper power states */
+			if (!host->idle || !host->gpio_sdio_irq) {
+				dev_warn(mmc_dev(host->mmc),
+					 "Disable SDIO IRQ workaround, GPIO IRQ or pinctrl idle state missing, falling back to polling\n");
+				mmc->caps &= ~MMC_CAP_SDIO_IRQ;
+			} else {
+				host->flags |= HSMMC_SWAKEUP_QUIRK;
+
+			}
+		}
+
+		if (host->flags & HSMMC_SWAKEUP_QUIRK) {
+			/* prevent auto-enabling of IRQ */
+			irq_set_status_flags(host->gpio_sdio_irq, IRQ_NOAUTOEN);
+			ret = request_irq(host->gpio_sdio_irq, omap_hsmmc_cirq,
+					  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+					  mmc_hostname(mmc), host);
+			if (ret) {
+				dev_err(mmc_dev(host->mmc),
+					"Unable to grab GPIO SDIO IRQ\n");
+				goto err_irq_sdio;
+			}
 		}
 	}
 
@@ -2191,6 +2238,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 
 err_slot_name:
 	mmc_remove_host(mmc);
+	if (host->gpio_sdio_irq)
+		free_irq(host->gpio_sdio_irq, host);
+err_irq_sdio:
 	if (host->pinctrl)
 		devm_pinctrl_put(host->pinctrl);
 err_pinctrl_state:
@@ -2240,6 +2290,8 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
 	if (host->pdata->cleanup)
 		host->pdata->cleanup(&pdev->dev);
 	free_irq(host->irq, host);
+	if ((host->gpio_sdio_irq))
+		free_irq(host->gpio_sdio_irq, host);
 	if (mmc_slot(host).card_detect_irq)
 		free_irq(mmc_slot(host).card_detect_irq, host);
 
@@ -2304,6 +2356,8 @@ static int omap_hsmmc_suspend(struct device *dev)
 				OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
 	}
 
+	if (host->flags & HSMMC_SWAKEUP_QUIRK)
+		disable_irq(host->gpio_sdio_irq);
 	if (host->dbclk)
 		clk_disable_unprepare(host->dbclk);
 
@@ -2329,6 +2383,9 @@ static int omap_hsmmc_resume(struct device *dev)
 
 	omap_hsmmc_protect_card(host);
 
+	if (host->flags & HSMMC_SWAKEUP_QUIRK)
+		enable_irq(host->gpio_sdio_irq);
+
 	pm_runtime_mark_last_busy(host->dev);
 	pm_runtime_put_autosuspend(host->dev);
 	return 0;
@@ -2344,23 +2401,61 @@ 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) {
+		OMAP_HSMMC_WRITE(host->base, ISE, 0);
+		OMAP_HSMMC_WRITE(host->base, IE, 0);
+		OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
+
+		ret = pinctrl_select_state(host->pinctrl, host->idle);
+		if (ret < 0)
+			dev_warn(mmc_dev(host->mmc), "Unable to select idle pinmux\n");
+
+		spin_lock_irqsave(&host->irq_lock, flags);
+		if (host->flags & HSMMC_SDIO_IRQ_ENABLED) {
+			enable_irq(host->gpio_sdio_irq);
+			host->flags |= HSMMC_CIRQ_GPIO_ENABLED;
+		}
+		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;
+	if (host->flags & HSMMC_SWAKEUP_QUIRK) {
+
+		spin_lock_irqsave(&host->irq_lock, flags);
+		if (host->flags & HSMMC_CIRQ_GPIO_ENABLED) {
+			disable_irq_nosync(host->gpio_sdio_irq);
+			host->flags &= ~HSMMC_CIRQ_GPIO_ENABLED;
+		}
+		spin_unlock_irqrestore(&host->irq_lock, flags);
+
+		ret = pinctrl_select_state(host->pinctrl, host->active);
+		if (ret < 0)
+			dev_warn(mmc_dev(host->mmc), "Unable to select active pinmux\n");
+
+		OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
+		OMAP_HSMMC_WRITE(host->base, ISE, CIRQ_EN);
+		OMAP_HSMMC_WRITE(host->base, IE, CIRQ_EN);
+	}
+	return ret;
 }
 
 static struct dev_pm_ops omap_hsmmc_dev_pm_ops = {
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v7 4/4] mmc: omap_hsmmc: Extend debugfs for SDIO IRQ, GPIO and pinmux.
  2014-02-25 12:37 ` [PATCH v7 3/4] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x Andreas Fenkart
@ 2014-02-25 12:49   ` Andreas Fenkart
  2014-02-27 21:39     ` Tony Lindgren
  2014-02-27 21:37   ` [PATCH v7 3/4] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x Tony Lindgren
  1 sibling, 1 reply; 18+ messages in thread
From: Andreas Fenkart @ 2014-02-25 12:49 UTC (permalink / raw)
  To: Chris Ball
  Cc: Tony Lindgren, Grant Likely, Felipe Balbi, Balaji T K, zonque,
	galak, linux-doc, linux-mmc, linux-omap, Andreas Fenkart

Add SDIO IRQ entries to debugfs entry. Note that PSTATE shows current
state of data lines, incl. SDIO IRQ pending

Signed-off-by: Andreas Fenkart <afenkart@gmail.com>

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 452c05a..cf03481 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -82,6 +82,7 @@ static void apply_clk_hack(struct device *dev)
 #define OMAP_HSMMC_RSP54	0x0118
 #define OMAP_HSMMC_RSP76	0x011C
 #define OMAP_HSMMC_DATA		0x0120
+#define OMAP_HSMMC_PSTATE	0x0124
 #define OMAP_HSMMC_HCTL		0x0128
 #define OMAP_HSMMC_SYSCTL	0x012C
 #define OMAP_HSMMC_STAT		0x0130
@@ -1792,14 +1793,30 @@ static int omap_hsmmc_regs_show(struct seq_file *s, void *data)
 {
 	struct mmc_host *mmc = s->private;
 	struct omap_hsmmc_host *host = mmc_priv(mmc);
+	const char* cirq_state;
+	bool suspended;
 
-	seq_printf(s, "mmc%d:\n ctx_loss:\t%d\n\nregs:\n",
-			mmc->index, host->context_loss);
+	seq_printf(s, "mmc%d:\n", mmc->index);
+	if (mmc->caps & MMC_CAP_SDIO_IRQ)
+		cirq_state = (host->flags & HSMMC_SDIO_IRQ_ENABLED) ?
+			"enabled" : "disabled";
+	else
+		cirq_state = "polling";
+	seq_printf(s, "sdio irq\t%s\n", cirq_state);
 
-	pm_runtime_get_sync(host->dev);
+	if (host->flags & HSMMC_SWAKEUP_QUIRK) {
+		suspended = host->dev->power.runtime_status != RPM_ACTIVE;
+		seq_printf(s, "pinmux config\t%s\n", (suspended ?
+						      "gpio" : "sdio"));
+	}
+	seq_printf(s, "ctx_loss:\t%d\n", host->context_loss);
 
+	pm_runtime_get_sync(host->dev);
+	seq_puts(s, "\nregs:\n");
 	seq_printf(s, "CON:\t\t0x%08x\n",
 			OMAP_HSMMC_READ(host->base, CON));
+	seq_printf(s, "PSTATE:\t\t0x%08x\n",
+		   OMAP_HSMMC_READ(host->base, PSTATE));
 	seq_printf(s, "HCTL:\t\t0x%08x\n",
 			OMAP_HSMMC_READ(host->base, HCTL));
 	seq_printf(s, "SYSCTL:\t\t0x%08x\n",
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH v7 1/4] mmc: omap_hsmmc: Enable SDIO IRQ.
  2014-02-25 12:37 ` [PATCH v7 1/4] mmc: omap_hsmmc: Enable " Andreas Fenkart
@ 2014-02-27 21:33   ` Tony Lindgren
  2014-03-05  8:27     ` Andreas Fenkart
  2014-02-28 17:04   ` Balaji T K
  1 sibling, 1 reply; 18+ messages in thread
From: Tony Lindgren @ 2014-02-27 21:33 UTC (permalink / raw)
  To: Andreas Fenkart
  Cc: Chris Ball, Grant Likely, Felipe Balbi, Balaji T K, zonque, galak,
	linux-doc, linux-mmc, linux-omap

* Andreas Fenkart <afenkart@gmail.com> [140225 04:46]:
> For now, only support SDIO interrupt if we are booted with
> DT. This is because some platforms need special quirks. And
> we don't want to add new legacy mux platform init code
> callbacks any longer as we are moving to DT based booting
> anyways.

Thanks for updating this, I finally got around to spend some
time with it again. I've folded in your fixes and quirk support
into my earlier patch from [0] as that had a better changelog
describing the earlier work.

And I've also now made the SDIO support to depend on properly
configured wake-up irq from device tree as otherwise wake from
idle states won't work properly. I've also cleaned up the the
wake-up irq initialization a bit.

The wake-irq is needed for omaps with wake-up path and also
when doing GPIO remuxing. So the wake-up handling is pretty
much the same for both cases.

I've kept your Signed-off-by, can you please check if the patch
below works for you with the second patch I'll post shortly?

Regards,

Tony

[0] https://www.mail-archive.com/linux-mmc@vger.kernel.org/msg22290.html

8< ----------------------------------------------------------
From: Tony Lindgren <tony@atomide.com>
Date: Tue, 25 Feb 2014 13:37:43 +0100
Subject: [PATCH] mmc: omap_hsmmc: Enable SDIO interrupt

There have been various patches floating around for enabling
the SDIO IRQ for hsmmc, but none of them ever got merged.

Probably the reason for not merging the SDIO interrupt patches
has been the lack of wake-up path for SDIO on some omaps that
has also needed remuxing the SDIO DAT1 line to a GPIO making
the patches complex.

This patch adds the minimal SDIO IRQ support to hsmmc for
omaps that do have the wake-up path. For those omaps, the
DAT1 line need to have the wake-up enable bit set, and the
wake-up interrupt is the same as for the MMC controller.

This patch has been tested on am3730 es1.2 with mwifiex
connected to MMC3 with mwifiex waking to Ethernet traffic
from off-idle mode. Note that for omaps that do not have
the SDIO wake-up path, this patch will not work for idle
modes and further patches for remuxing DAT1 to GPIO are
needed.

Based on earlier patches [1][2] by David Vrabel
<david.vrabel@csr.com>, Steve Sakoman <steve@sakoman.com>
and Andreas Fenkart <afenkart@gmail.com> with the SDIO IRQ
handing improved following how sdhci.c is doing it.

For now, only support SDIO interrupt if we are booted with
a separate wake-irq configued via device tree. This is
because omaps need the wake-irq for idle states, and some
omaps need special quirks. And we don't want to add new
legacy mux platform init code callbacks any longer as we
are moving to DT based booting anyways.

To use it, you need to specify the wake-irq using the
interrupts-extended property.

[1] http://www.sakoman.com/cgi-bin/gitweb.cgi?p=linux.git;a=commitdiff_plain;h=010810d22f6f49ac03da4ba384969432e0320453
[2] http://comments.gmane.org/gmane.linux.kernel.mmc/20446

Cc: Balaji T K <balajitk@ti.com>
Signed-off-by: Andreas Fenkart <afenkart@gmail.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index dbd32ad..e945060 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -29,6 +29,7 @@
 #include <linux/timer.h>
 #include <linux/clk.h>
 #include <linux/of.h>
+#include <linux/of_irq.h>
 #include <linux/of_gpio.h>
 #include <linux/of_device.h>
 #include <linux/omap-dma.h>
@@ -36,6 +37,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>
@@ -104,6 +106,7 @@
 #define TC_EN			(1 << 1)
 #define BWR_EN			(1 << 4)
 #define BRR_EN			(1 << 5)
+#define CIRQ_EN			(1 << 8)
 #define ERR_EN			(1 << 15)
 #define CTO_EN			(1 << 16)
 #define CCRC_EN			(1 << 17)
@@ -178,6 +181,7 @@ struct omap_hsmmc_host {
 	u32			sysctl;
 	u32			capa;
 	int			irq;
+	int			wake_irq;
 	int			use_dma, dma_ch;
 	struct dma_chan		*tx_chan;
 	struct dma_chan		*rx_chan;
@@ -188,6 +192,9 @@ struct omap_hsmmc_host {
 	int			reqs_blocked;
 	int			use_reg;
 	int			req_in_progress;
+	int                     flags;
+#define HSMMC_SDIO_IRQ_ENABLED	(1 << 0)        /* SDIO irq enabled */
+#define HSMMC_SWAKEUP_QUIRK	(1 << 1)
 	struct omap_hsmmc_next	next_data;
 	struct	omap_mmc_platform_data	*pdata;
 };
@@ -468,27 +475,40 @@ static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host)
 static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host,
 				  struct mmc_command *cmd)
 {
-	unsigned int irq_mask;
+	u32 irq_mask = INT_EN_MASK;
+	unsigned long flags;
 
 	if (host->use_dma)
-		irq_mask = INT_EN_MASK & ~(BRR_EN | BWR_EN);
-	else
-		irq_mask = INT_EN_MASK;
+		irq_mask &= ~(BRR_EN | BWR_EN);
 
 	/* Disable timeout for erases */
 	if (cmd->opcode == MMC_ERASE)
 		irq_mask &= ~DTO_EN;
 
+	spin_lock_irqsave(&host->irq_lock, flags);
 	OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
 	OMAP_HSMMC_WRITE(host->base, ISE, irq_mask);
+
+	/* latch pending CIRQ, but don't signal MMC core */
+	if (host->flags & HSMMC_SDIO_IRQ_ENABLED)
+		irq_mask |= CIRQ_EN;
 	OMAP_HSMMC_WRITE(host->base, IE, irq_mask);
+	spin_unlock_irqrestore(&host->irq_lock, flags);
 }
 
 static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host)
 {
-	OMAP_HSMMC_WRITE(host->base, ISE, 0);
-	OMAP_HSMMC_WRITE(host->base, IE, 0);
+	u32 irq_mask = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->irq_lock, flags);
+	/* no transfer running but need to keep cirq if enabled */
+	if (host->flags & HSMMC_SDIO_IRQ_ENABLED)
+		irq_mask |= CIRQ_EN;
+	OMAP_HSMMC_WRITE(host->base, ISE, irq_mask);
+	OMAP_HSMMC_WRITE(host->base, IE, irq_mask);
 	OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
+	spin_unlock_irqrestore(&host->irq_lock, flags);
 }
 
 /* Calculate divisor for the given clock frequency */
@@ -1051,8 +1071,12 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
 	int status;
 
 	status = OMAP_HSMMC_READ(host->base, STAT);
-	while (status & INT_EN_MASK && host->req_in_progress) {
-		omap_hsmmc_do_irq(host, status);
+	while (status & (INT_EN_MASK | CIRQ_EN)) {
+		if (host->req_in_progress)
+			omap_hsmmc_do_irq(host, status);
+
+		if (status & CIRQ_EN)
+			mmc_signal_sdio_irq(host->mmc);
 
 		/* Flush posted write */
 		status = OMAP_HSMMC_READ(host->base, STAT);
@@ -1061,6 +1085,39 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static inline void hsmmc_enable_wake_irq(struct omap_hsmmc_host *host)
+{
+	unsigned long flags;
+
+	if (!host->wake_irq)
+		return;
+
+	spin_lock_irqsave(&host->irq_lock, flags);
+	enable_irq(host->wake_irq);
+	spin_unlock_irqrestore(&host->irq_lock, flags);
+}
+
+static inline void hsmmc_disable_wake_irq(struct omap_hsmmc_host *host)
+{
+	unsigned long flags;
+
+	if (!host->wake_irq)
+		return;
+
+	spin_lock_irqsave(&host->irq_lock, flags);
+	disable_irq_nosync(host->wake_irq);
+	spin_unlock_irqrestore(&host->irq_lock, flags);
+}
+
+static irqreturn_t omap_hsmmc_wake_irq(int irq, void *dev_id)
+{
+	struct omap_hsmmc_host *host = dev_id;
+
+	pm_request_resume(host->dev); /* no use counter */
+
+	return IRQ_HANDLED;
+}
+
 static void set_sd_bus_power(struct omap_hsmmc_host *host)
 {
 	unsigned long i;
@@ -1564,6 +1621,66 @@ static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card)
 		mmc_slot(host).init_card(card);
 }
 
+static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+	struct omap_hsmmc_host *host = mmc_priv(mmc);
+	u32 irq_mask;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->irq_lock, flags);
+
+	irq_mask = OMAP_HSMMC_READ(host->base, ISE);
+	if (enable) {
+		host->flags |= HSMMC_SDIO_IRQ_ENABLED;
+		irq_mask |= CIRQ_EN;
+	} else {
+		host->flags &= ~HSMMC_SDIO_IRQ_ENABLED;
+		irq_mask &= ~CIRQ_EN;
+	}
+	OMAP_HSMMC_WRITE(host->base, IE, irq_mask);
+
+	/*
+	 * if enable, piggy back detection on current request
+	 * but always disable immediately
+	 */
+	if (!host->req_in_progress || !enable)
+		OMAP_HSMMC_WRITE(host->base, ISE, irq_mask);
+
+	/* flush posted write */
+	OMAP_HSMMC_READ(host->base, IE);
+
+	spin_unlock_irqrestore(&host->irq_lock, flags);
+}
+
+static int omap_hscmm_configure_wake_irq(struct omap_hsmmc_host *host)
+{
+	struct mmc_host *mmc = host->mmc;
+	int ret;
+
+	if (!host->dev->of_node || !host->wake_irq)
+		return -ENODEV;
+
+	/* Prevent auto-enabling of IRQ */
+	irq_set_status_flags(host->wake_irq, IRQ_NOAUTOEN);
+	ret = request_irq(host->wake_irq, omap_hsmmc_wake_irq,
+			  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+			  mmc_hostname(mmc), host);
+	if (ret) {
+		dev_err(mmc_dev(host->mmc),
+			"Unable to request wake IRQ\n");
+		return ret;
+	}
+
+	/*
+	 * Some omaps don't have wake-up path from deeper idle states
+	 * and need to remux SDIO DAT1 to GPIO for wake-up from idle.
+	 */
+	if (host->pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING)
+		host->flags |= HSMMC_SWAKEUP_QUIRK;
+
+	return 0;
+}
+
 static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host)
 {
 	u32 hctl, capa, value;
@@ -1616,7 +1733,7 @@ static const struct mmc_host_ops omap_hsmmc_ops = {
 	.get_cd = omap_hsmmc_get_cd,
 	.get_ro = omap_hsmmc_get_ro,
 	.init_card = omap_hsmmc_init_card,
-	/* NYET -- enable_sdio_irq */
+	.enable_sdio_irq = omap_hsmmc_enable_sdio_irq,
 };
 
 #ifdef CONFIG_DEBUG_FS
@@ -1678,7 +1795,18 @@ static void omap_hsmmc_debugfs(struct mmc_host *mmc)
 #endif
 
 #ifdef CONFIG_OF
-static u16 omap4_reg_offset = 0x100;
+struct of_data {
+	u16 offset;
+	int flags;
+};
+
+static struct of_data omap4_data = {
+	.offset	= 0x100,
+};
+static struct of_data am33xx_data = {
+	.offset	= 0x100,
+	.flags	= OMAP_HSMMC_SWAKEUP_MISSING,
+};
 
 static const struct of_device_id omap_mmc_of_match[] = {
 	{
@@ -1689,7 +1817,11 @@ static const struct of_device_id omap_mmc_of_match[] = {
 	},
 	{
 		.compatible = "ti,omap4-hsmmc",
-		.data = &omap4_reg_offset,
+		.data = &omap4_data,
+	},
+	{
+		.compatible = "ti,am33xx-hsmmc",
+		.data = &am33xx_data,
 	},
 	{},
 };
@@ -1754,7 +1886,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 	struct mmc_host *mmc;
 	struct omap_hsmmc_host *host = NULL;
 	struct resource *res;
-	int ret, irq;
+	int ret, irq, _wake_irq = 0;
 	const struct of_device_id *match;
 	dma_cap_mask_t mask;
 	unsigned tx_req, rx_req;
@@ -1768,8 +1900,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 			return PTR_ERR(pdata);
 
 		if (match->data) {
-			const u16 *offsetp = match->data;
-			pdata->reg_offset = *offsetp;
+			const struct of_data *d = match->data;
+			pdata->reg_offset = d->offset;
+			pdata->controller_flags |= d->flags;
 		}
 	}
 
@@ -1788,6 +1921,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 	if (res == NULL || irq < 0)
 		return -ENXIO;
 
+	if (pdev->dev.of_node)
+		_wake_irq = irq_of_parse_and_map(pdev->dev.of_node, 1);
+
 	res = request_mem_region(res->start, resource_size(res), pdev->name);
 	if (res == NULL)
 		return -EBUSY;
@@ -1809,6 +1945,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 	host->use_dma	= 1;
 	host->dma_ch	= -1;
 	host->irq	= irq;
+	host->wake_irq = _wake_irq;
 	host->slot_id	= 0;
 	host->mapbase	= res->start + pdata->reg_offset;
 	host->base	= ioremap(host->mapbase, SZ_4K);
@@ -1975,6 +2112,18 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 		dev_warn(&pdev->dev,
 			"pins are not configured from the driver\n");
 
+	/*
+	 * For now, only support SDIO interrupt if we have a separate
+	 * wake-up interrupt configured from device tree. This is because
+	 * the wake-up interrupt is needed for idle state and some
+	 * platforms need special quirks. And we don't want to add new
+	 * legacy mux platform init code callbacks any longer as we
+	 * are moving to DT based bootinganyways.
+	 */
+	ret = omap_hscmm_configure_wake_irq(host);
+	if (!ret)
+		mmc->caps |= MMC_CAP_SDIO_IRQ;
+
 	omap_hsmmc_protect_card(host);
 
 	mmc_add_host(mmc);
@@ -1999,7 +2148,10 @@ 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);
+	if (host->wake_irq)
+		free_irq(host->wake_irq, host);
+	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);
@@ -2044,6 +2196,8 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
 	if (host->pdata->cleanup)
 		host->pdata->cleanup(&pdev->dev);
 	free_irq(host->irq, host);
+	if (host->wake_irq)
+		free_irq(host->wake_irq, host);
 	if (mmc_slot(host).card_detect_irq)
 		free_irq(mmc_slot(host).card_detect_irq, host);
 
@@ -2106,6 +2260,8 @@ static int omap_hsmmc_suspend(struct device *dev)
 				OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
 	}
 
+	hsmmc_disable_wake_irq(host);
+
 	if (host->dbclk)
 		clk_disable_unprepare(host->dbclk);
 
@@ -2131,6 +2287,8 @@ static int omap_hsmmc_resume(struct device *dev)
 
 	omap_hsmmc_protect_card(host);
 
+	hsmmc_enable_wake_irq(host);
+
 	pm_runtime_mark_last_busy(host->dev);
 	pm_runtime_put_autosuspend(host->dev);
 	return 0;
@@ -2146,23 +2304,38 @@ static int omap_hsmmc_resume(struct device *dev)
 static int omap_hsmmc_runtime_suspend(struct device *dev)
 {
 	struct omap_hsmmc_host *host;
+	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->mmc->caps & MMC_CAP_SDIO_IRQ) {
+		OMAP_HSMMC_WRITE(host->base, ISE, 0);
+		OMAP_HSMMC_WRITE(host->base, IE, 0);
+		OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
+		hsmmc_enable_wake_irq(host);
+	}
+
+	return ret;
 }
 
 static int omap_hsmmc_runtime_resume(struct device *dev)
 {
 	struct omap_hsmmc_host *host;
+	int ret = 0;
 
 	host = platform_get_drvdata(to_platform_device(dev));
 	omap_hsmmc_context_restore(host);
 	dev_dbg(dev, "enabled\n");
 
-	return 0;
+	if (host->mmc->caps & MMC_CAP_SDIO_IRQ) {
+		hsmmc_disable_wake_irq(host);
+		OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
+		OMAP_HSMMC_WRITE(host->base, ISE, CIRQ_EN);
+		OMAP_HSMMC_WRITE(host->base, IE, CIRQ_EN);
+	}
+	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..51e70cf 100644
--- a/include/linux/platform_data/mmc-omap.h
+++ b/include/linux/platform_data/mmc-omap.h
@@ -28,6 +28,7 @@
  */
 #define OMAP_HSMMC_SUPPORTS_DUAL_VOLT		BIT(0)
 #define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ	BIT(1)
+#define OMAP_HSMMC_SWAKEUP_MISSING		BIT(2)
 
 struct mmc_card;
 

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH v7 2/4] mmc: omap_hsmmc: Remux SDIO pins within driver.
  2014-02-25 12:37 ` [PATCH v7 2/4] mmc: omap_hsmmc: Remux SDIO pins within driver Andreas Fenkart
@ 2014-02-27 21:36   ` Tony Lindgren
  2014-02-27 21:42     ` Tony Lindgren
  0 siblings, 1 reply; 18+ messages in thread
From: Tony Lindgren @ 2014-02-27 21:36 UTC (permalink / raw)
  To: Andreas Fenkart
  Cc: Chris Ball, Grant Likely, Felipe Balbi, Balaji T K, zonque, galak,
	linux-doc, linux-mmc, linux-omap

* Andreas Fenkart <afenkart@gmail.com> [140225 04:49]:
> This is a preparation for the am335x workaround where we reconfigure
> dat1 as GPIO before going to suspend. If you don't specify active/idle
> pinctrl there should be no change.

I've updated this too, hope it still works for you. And there's no
need for patch 3/4, that's merged into this one as well.

Regards,

Tony

8< -----------------------------------------------------
From: Andreas Fenkart <afenkart@gmail.com>
Date: Tue, 25 Feb 2014 13:37:44 +0100
Subject: [PATCH] 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 and some minor changes by Tony Lindgren.

Signed-off-by: Andreas Fenkart <afenkart@gmail.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
index 8c8908a..8e1195e 100644
--- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
+++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
@@ -55,3 +55,53 @@ 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 1) the named pinctrl
+states "default", "active" and "idle", 2) the gpio detecting
+sdio irq in suspend and 3) compatibe section, see example below.
+The MMC driver will then toggle between active and idle during
+the runtime. If configuration is incomplete, a warning message is
+emitted "falling back to polling".  Mind not every application
+needs SDIO irq, e.g. MMC cards Affected chips are am335x,
+probably others
+
+
+	mmc1: mmc@48060100 {
+		compatible = "ti,am33xx-hsmmc";
+		...
+		interrupts-extended = <&intc 64 &gpio2 28 0>;
+		...
+		pinctrl-names = "default", "active", "idle"
+		pinctrl-0 = <&mmc1_pins>;
+		pinctrl-1 = <&mmc1_pins>;
+		pinctrl-2 = <&mmc1_cirq_pin>;
+		...
+	};
+
+	mmc1_cirq_pin: 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 e945060..17e602a 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -196,6 +196,8 @@ struct omap_hsmmc_host {
 #define HSMMC_SDIO_IRQ_ENABLED	(1 << 0)        /* SDIO irq enabled */
 #define HSMMC_SWAKEUP_QUIRK	(1 << 1)
 	struct omap_hsmmc_next	next_data;
+	struct pinctrl		*pinctrl;
+	struct pinctrl_state	*fixed, *active, *idle;
 	struct	omap_mmc_platform_data	*pdata;
 };
 
@@ -452,6 +454,70 @@ static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata)
 		gpio_free(pdata->slots[0].switch_pin);
 }
 
+static int omap_hsmmc_pin_init(struct omap_hsmmc_host *host)
+{
+	struct pinctrl *_pinctrl;
+	int ret;
+
+	_pinctrl = devm_pinctrl_get(host->dev);
+	if (IS_ERR(_pinctrl)) {
+		/* okay, if the bootloader set it up right */
+		dev_warn(host->dev, "no pinctrl handle\n");
+		return 0;
+	}
+
+	host->fixed = pinctrl_lookup_state(_pinctrl,
+					   PINCTRL_STATE_DEFAULT);
+	if (IS_ERR(host->fixed)) {
+		dev_info(host->dev,
+			 "pins are not configured from the driver\n");
+		host->fixed = NULL;
+		devm_pinctrl_put(_pinctrl);
+		return 0;
+	}
+
+	ret = pinctrl_select_state(_pinctrl, host->fixed);
+	if (ret < 0) {
+		dev_warn(host->dev, "fixed pinctrl state failed %d\n", ret);
+		goto err;
+	}
+
+	/* For most cases we don't have wake-ups, and exit after this */
+	host->active = pinctrl_lookup_state(_pinctrl, "active");
+	if (IS_ERR(host->active)) {
+		ret = PTR_ERR(host->active);
+		host->active = NULL;
+		goto done;
+	}
+
+	host->idle = pinctrl_lookup_state(_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(_pinctrl, host->idle);
+	if (ret < 0)
+		goto err;
+
+	ret = pinctrl_select_state(_pinctrl, host->active);
+	if (ret < 0)
+		goto err;
+
+	dev_info(mmc_dev(host->mmc), "pins configured for wake-up events\n");
+
+done:
+	host->pinctrl = _pinctrl;
+	return 0;
+
+err:
+	dev_err(mmc_dev(host->mmc), "pins configuration error: %i\n", ret);
+	devm_pinctrl_put(_pinctrl);
+	return ret;
+}
+
 /*
  * Start clock to the card
  */
@@ -1675,8 +1741,14 @@ static int omap_hscmm_configure_wake_irq(struct omap_hsmmc_host *host)
 	 * Some omaps don't have wake-up path from deeper idle states
 	 * and need to remux SDIO DAT1 to GPIO for wake-up from idle.
 	 */
-	if (host->pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING)
+	if (host->pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING) {
+		if (!host->idle) {
+			free_irq(host->wake_irq);
+			host->wake_irq = 0;
+			return -EINVAL;
+		}
 		host->flags |= HSMMC_SWAKEUP_QUIRK;
+	}
 
 	return 0;
 }
@@ -1890,7 +1962,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) {
@@ -2107,10 +2178,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 
 	omap_hsmmc_disable_irq(host);
 
-	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-	if (IS_ERR(pinctrl))
-		dev_warn(&pdev->dev,
-			"pins are not configured from the driver\n");
+	ret = omap_hsmmc_pin_init(host);
+	if (ret)
+		goto err_pinctrl_state;
 
 	/*
 	 * For now, only support SDIO interrupt if we have a separate
@@ -2150,7 +2220,9 @@ err_slot_name:
 	mmc_remove_host(mmc);
 	if (host->wake_irq)
 		free_irq(host->wake_irq, host);
-	if (mmc_slot(host).card_detect_irq)
+	if (host->pinctrl)
+		devm_pinctrl_put(host->pinctrl);
+	if ((mmc_slot(host).card_detect_irq))
 		free_irq(mmc_slot(host).card_detect_irq, host);
 err_irq_cd:
 	if (host->use_reg)
@@ -2205,6 +2277,8 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
 		dma_release_channel(host->tx_chan);
 	if (host->rx_chan)
 		dma_release_channel(host->rx_chan);
+	if (host->pinctrl)
+		devm_pinctrl_put(host->pinctrl);
 
 	pm_runtime_put_sync(host->dev);
 	pm_runtime_disable(host->dev);
@@ -2314,6 +2388,11 @@ static int omap_hsmmc_runtime_suspend(struct device *dev)
 		OMAP_HSMMC_WRITE(host->base, ISE, 0);
 		OMAP_HSMMC_WRITE(host->base, IE, 0);
 		OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
+		if (host->idle) {
+			ret = pinctrl_select_state(host->pinctrl, host->idle);
+			if (ret < 0)
+				dev_warn(mmc_dev(host->mmc), "Unable to select idle pinmux\n");
+		}
 		hsmmc_enable_wake_irq(host);
 	}
 
@@ -2331,6 +2410,11 @@ static int omap_hsmmc_runtime_resume(struct device *dev)
 
 	if (host->mmc->caps & MMC_CAP_SDIO_IRQ) {
 		hsmmc_disable_wake_irq(host);
+		if (host->active) {
+			ret = pinctrl_select_state(host->pinctrl, host->active);
+			if (ret < 0)
+				dev_warn(mmc_dev(host->mmc), "Unable to select active pinmux\n");
+		}
 		OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
 		OMAP_HSMMC_WRITE(host->base, ISE, CIRQ_EN);
 		OMAP_HSMMC_WRITE(host->base, IE, CIRQ_EN);

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH v7 3/4] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x.
  2014-02-25 12:37 ` [PATCH v7 3/4] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x Andreas Fenkart
  2014-02-25 12:49   ` [PATCH v7 4/4] mmc: omap_hsmmc: Extend debugfs for SDIO IRQ, GPIO and pinmux Andreas Fenkart
@ 2014-02-27 21:37   ` Tony Lindgren
  1 sibling, 0 replies; 18+ messages in thread
From: Tony Lindgren @ 2014-02-27 21:37 UTC (permalink / raw)
  To: Andreas Fenkart
  Cc: Chris Ball, Grant Likely, Felipe Balbi, Balaji T K, zonque, galak,
	linux-doc, linux-mmc, linux-omap

* Andreas Fenkart <afenkart@gmail.com> [140225 04:51]:
> 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.

So this patch should no longer be needed after my updated
patches 1 and 2. But please check :)

Tony

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v7 4/4] mmc: omap_hsmmc: Extend debugfs for SDIO IRQ, GPIO and pinmux.
  2014-02-25 12:49   ` [PATCH v7 4/4] mmc: omap_hsmmc: Extend debugfs for SDIO IRQ, GPIO and pinmux Andreas Fenkart
@ 2014-02-27 21:39     ` Tony Lindgren
  0 siblings, 0 replies; 18+ messages in thread
From: Tony Lindgren @ 2014-02-27 21:39 UTC (permalink / raw)
  To: Andreas Fenkart
  Cc: Chris Ball, Grant Likely, Felipe Balbi, Balaji T K, zonque, galak,
	linux-doc, linux-mmc, linux-omap

* Andreas Fenkart <afenkart@gmail.com> [140225 04:57]:
> Add SDIO IRQ entries to debugfs entry. Note that PSTATE shows current
> state of data lines, incl. SDIO IRQ pending
> 
> Signed-off-by: Andreas Fenkart <afenkart@gmail.com>

No changes to this one, so:

Acked-by: Tony Lindgren <tony@atomide.com>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v7 2/4] mmc: omap_hsmmc: Remux SDIO pins within driver.
  2014-02-27 21:36   ` Tony Lindgren
@ 2014-02-27 21:42     ` Tony Lindgren
  0 siblings, 0 replies; 18+ messages in thread
From: Tony Lindgren @ 2014-02-27 21:42 UTC (permalink / raw)
  To: Andreas Fenkart
  Cc: Chris Ball, Grant Likely, Felipe Balbi, Balaji T K, zonque, galak,
	linux-doc, linux-mmc, linux-omap

* Tony Lindgren <tony@atomide.com> [140227 13:40]:
> * Andreas Fenkart <afenkart@gmail.com> [140225 04:49]:
> > This is a preparation for the am335x workaround where we reconfigure
> > dat1 as GPIO before going to suspend. If you don't specify active/idle
> > pinctrl there should be no change.
> 
> I've updated this too, hope it still works for you. And there's no
> need for patch 3/4, that's merged into this one as well.

> -	if (host->pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING)
> +	if (host->pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING) {
> +		if (!host->idle) {
> +			free_irq(host->wake_irq);

Oops, this one was missing some uncommitted changes. Updated patch below.

Tony

8< ----------------------------------------------
From: Andreas Fenkart <afenkart@gmail.com>
Date: Tue, 25 Feb 2014 13:37:44 +0100
Subject: [PATCH] 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 and some minor changes by Tony Lindgren.

Signed-off-by: Andreas Fenkart <afenkart@gmail.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
index 8c8908a..8e1195e 100644
--- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
+++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
@@ -55,3 +55,53 @@ 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 1) the named pinctrl
+states "default", "active" and "idle", 2) the gpio detecting
+sdio irq in suspend and 3) compatibe section, see example below.
+The MMC driver will then toggle between active and idle during
+the runtime. If configuration is incomplete, a warning message is
+emitted "falling back to polling".  Mind not every application
+needs SDIO irq, e.g. MMC cards Affected chips are am335x,
+probably others
+
+
+	mmc1: mmc@48060100 {
+		compatible = "ti,am33xx-hsmmc";
+		...
+		interrupts-extended = <&intc 64 &gpio2 28 0>;
+		...
+		pinctrl-names = "default", "active", "idle"
+		pinctrl-0 = <&mmc1_pins>;
+		pinctrl-1 = <&mmc1_pins>;
+		pinctrl-2 = <&mmc1_cirq_pin>;
+		...
+	};
+
+	mmc1_cirq_pin: 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 e945060..2c1f128 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -196,6 +196,8 @@ struct omap_hsmmc_host {
 #define HSMMC_SDIO_IRQ_ENABLED	(1 << 0)        /* SDIO irq enabled */
 #define HSMMC_SWAKEUP_QUIRK	(1 << 1)
 	struct omap_hsmmc_next	next_data;
+	struct pinctrl		*pinctrl;
+	struct pinctrl_state	*fixed, *active, *idle;
 	struct	omap_mmc_platform_data	*pdata;
 };
 
@@ -452,6 +454,70 @@ static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata)
 		gpio_free(pdata->slots[0].switch_pin);
 }
 
+static int omap_hsmmc_pin_init(struct omap_hsmmc_host *host)
+{
+	struct pinctrl *_pinctrl;
+	int ret;
+
+	_pinctrl = devm_pinctrl_get(host->dev);
+	if (IS_ERR(_pinctrl)) {
+		/* okay, if the bootloader set it up right */
+		dev_warn(host->dev, "no pinctrl handle\n");
+		return 0;
+	}
+
+	host->fixed = pinctrl_lookup_state(_pinctrl,
+					   PINCTRL_STATE_DEFAULT);
+	if (IS_ERR(host->fixed)) {
+		dev_info(host->dev,
+			 "pins are not configured from the driver\n");
+		host->fixed = NULL;
+		devm_pinctrl_put(_pinctrl);
+		return 0;
+	}
+
+	ret = pinctrl_select_state(_pinctrl, host->fixed);
+	if (ret < 0) {
+		dev_warn(host->dev, "fixed pinctrl state failed %d\n", ret);
+		goto err;
+	}
+
+	/* For most cases we don't have wake-ups, and exit after this */
+	host->active = pinctrl_lookup_state(_pinctrl, "active");
+	if (IS_ERR(host->active)) {
+		ret = PTR_ERR(host->active);
+		host->active = NULL;
+		goto done;
+	}
+
+	host->idle = pinctrl_lookup_state(_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(_pinctrl, host->idle);
+	if (ret < 0)
+		goto err;
+
+	ret = pinctrl_select_state(_pinctrl, host->active);
+	if (ret < 0)
+		goto err;
+
+	dev_info(mmc_dev(host->mmc), "pins configured for wake-up events\n");
+
+done:
+	host->pinctrl = _pinctrl;
+	return 0;
+
+err:
+	dev_err(mmc_dev(host->mmc), "pins configuration error: %i\n", ret);
+	devm_pinctrl_put(_pinctrl);
+	return ret;
+}
+
 /*
  * Start clock to the card
  */
@@ -1675,8 +1741,14 @@ static int omap_hscmm_configure_wake_irq(struct omap_hsmmc_host *host)
 	 * Some omaps don't have wake-up path from deeper idle states
 	 * and need to remux SDIO DAT1 to GPIO for wake-up from idle.
 	 */
-	if (host->pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING)
+	if (host->pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING) {
+		if (!host->idle) {
+			free_irq(host->wake_irq, host);
+			host->wake_irq = 0;
+			return -EINVAL;
+		}
 		host->flags |= HSMMC_SWAKEUP_QUIRK;
+	}
 
 	return 0;
 }
@@ -1890,7 +1962,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) {
@@ -2107,10 +2178,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 
 	omap_hsmmc_disable_irq(host);
 
-	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-	if (IS_ERR(pinctrl))
-		dev_warn(&pdev->dev,
-			"pins are not configured from the driver\n");
+	ret = omap_hsmmc_pin_init(host);
+	if (ret)
+		goto err_pinctrl_state;
 
 	/*
 	 * For now, only support SDIO interrupt if we have a separate
@@ -2150,7 +2220,10 @@ err_slot_name:
 	mmc_remove_host(mmc);
 	if (host->wake_irq)
 		free_irq(host->wake_irq, host);
-	if (mmc_slot(host).card_detect_irq)
+	if (host->pinctrl)
+		devm_pinctrl_put(host->pinctrl);
+err_pinctrl_state:
+	if ((mmc_slot(host).card_detect_irq))
 		free_irq(mmc_slot(host).card_detect_irq, host);
 err_irq_cd:
 	if (host->use_reg)
@@ -2205,6 +2278,8 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
 		dma_release_channel(host->tx_chan);
 	if (host->rx_chan)
 		dma_release_channel(host->rx_chan);
+	if (host->pinctrl)
+		devm_pinctrl_put(host->pinctrl);
 
 	pm_runtime_put_sync(host->dev);
 	pm_runtime_disable(host->dev);
@@ -2314,6 +2389,11 @@ static int omap_hsmmc_runtime_suspend(struct device *dev)
 		OMAP_HSMMC_WRITE(host->base, ISE, 0);
 		OMAP_HSMMC_WRITE(host->base, IE, 0);
 		OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
+		if (host->idle) {
+			ret = pinctrl_select_state(host->pinctrl, host->idle);
+			if (ret < 0)
+				dev_warn(mmc_dev(host->mmc), "Unable to select idle pinmux\n");
+		}
 		hsmmc_enable_wake_irq(host);
 	}
 
@@ -2331,6 +2411,11 @@ static int omap_hsmmc_runtime_resume(struct device *dev)
 
 	if (host->mmc->caps & MMC_CAP_SDIO_IRQ) {
 		hsmmc_disable_wake_irq(host);
+		if (host->active) {
+			ret = pinctrl_select_state(host->pinctrl, host->active);
+			if (ret < 0)
+				dev_warn(mmc_dev(host->mmc), "Unable to select active pinmux\n");
+		}
 		OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
 		OMAP_HSMMC_WRITE(host->base, ISE, CIRQ_EN);
 		OMAP_HSMMC_WRITE(host->base, IE, CIRQ_EN);

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH v7 1/4] mmc: omap_hsmmc: Enable SDIO IRQ.
  2014-02-25 12:37 ` [PATCH v7 1/4] mmc: omap_hsmmc: Enable " Andreas Fenkart
  2014-02-27 21:33   ` Tony Lindgren
@ 2014-02-28 17:04   ` Balaji T K
  2014-03-05  8:30     ` Andreas Fenkart
  1 sibling, 1 reply; 18+ messages in thread
From: Balaji T K @ 2014-02-28 17:04 UTC (permalink / raw)
  To: Andreas Fenkart
  Cc: Chris Ball, Tony Lindgren, Grant Likely, Felipe Balbi, zonque,
	galak, linux-doc, linux-mmc, linux-omap

On Tuesday 25 February 2014 06:07 PM, Andreas Fenkart wrote:
> For now, only support SDIO interrupt if we are booted with
> DT. This is because some platforms need special quirks. And
> we don't want to add new legacy mux platform init code
> callbacks any longer as we are moving to DT based booting
> anyways.
>
> Signed-off-by: Andreas Fenkart <afenkart@gmail.com>
>
> diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
> index a5a38cc..bd3bb0c 100644
> --- a/drivers/mmc/host/omap_hsmmc.c
> +++ b/drivers/mmc/host/omap_hsmmc.c

<snip>

> @@ -1705,7 +1757,18 @@ static void omap_hsmmc_debugfs(struct mmc_host *mmc)
>   #endif
>
>   #ifdef CONFIG_OF
> -static u16 omap4_reg_offset = 0x100;
> +struct of_data {
> +	u16 offset;
> +	int flags;
> +};
> +
Hi Andreas,

struct of_data declaration needs to be moved out of #ifdef CONFIG_OF
for !CONFIG_OF build.

I tried testing this patch series on am335x, I see throughput in the
range of KBs. Will give another try with Tony's version.

Thanks and Regards,
Balaji T K

> +static struct of_data omap4_data = {
> +	.offset	= 0x100,
> +};
> +static struct of_data am33xx_data = {
> +	.offset	= 0x100,
> +	.flags	= OMAP_HSMMC_SWAKEUP_MISSING,
> +};
>
>   static const struct of_device_id omap_mmc_of_match[] = {
>   	{

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v7 1/4] mmc: omap_hsmmc: Enable SDIO IRQ.
  2014-02-27 21:33   ` Tony Lindgren
@ 2014-03-05  8:27     ` Andreas Fenkart
  2014-03-05 16:33       ` Tony Lindgren
  0 siblings, 1 reply; 18+ messages in thread
From: Andreas Fenkart @ 2014-03-05  8:27 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Chris Ball, Grant Likely, Felipe Balbi, Balaji T K, Daniel Mack,
	Kumar Gala, linux-doc, linux-mmc, linux-omap

Hi,

2014-02-27 22:33 GMT+01:00 Tony Lindgren <tony@atomide.com>:
>
> Thanks for updating this, I finally got around to spend some
> time with it again. I've folded in your fixes and quirk support
> into my earlier patch from [0] as that had a better changelog
> describing the earlier work.
thanks, always struggled with that

> And I've also now made the SDIO support to depend on properly
> configured wake-up irq from device tree as otherwise wake from
> idle states won't work properly. I've also cleaned up the the
> wake-up irq initialization a bit.
Looks much better now.

Mind that the sdio irq is level triggered. So we have to disable the
IRQ in the handler otherwise we enter an infinite loop.



> The wake-irq is needed for omaps with wake-up path and also
> when doing GPIO remuxing. So the wake-up handling is pretty
> much the same for both cases.
I added this comment to the patch, since I was puzzled that you need
a wake_irq even whithout remuxing.

>
> I've kept your Signed-off-by, can you please check if the patch
> below works for you with the second patch I'll post shortly?

Will send out another patch soon. Left your Signed-off as well, not
in the sense of your agreement, but didn't dare to remove it because
of your contributions.

>
> Regards,
>
> Tony
>
> [0] https://www.mail-archive.com/linux-mmc@vger.kernel.org/msg22290.html
>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v7 1/4] mmc: omap_hsmmc: Enable SDIO IRQ.
  2014-02-28 17:04   ` Balaji T K
@ 2014-03-05  8:30     ` Andreas Fenkart
  2014-03-07 15:12       ` Balaji T K
  0 siblings, 1 reply; 18+ messages in thread
From: Andreas Fenkart @ 2014-03-05  8:30 UTC (permalink / raw)
  To: Balaji T K
  Cc: Chris Ball, Tony Lindgren, Grant Likely, Felipe Balbi,
	Daniel Mack, Kumar Gala, linux-doc, linux-mmc, linux-omap

Hi,

2014-02-28 18:04 GMT+01:00 Balaji T K <balajitk@ti.com>:
> On Tuesday 25 February 2014 06:07 PM, Andreas Fenkart wrote:
>>
>> For now, only support SDIO interrupt if we are booted with
>> DT. This is because some platforms need special quirks. And
>> we don't want to add new legacy mux platform init code
>> callbacks any longer as we are moving to DT based booting
>> anyways.
>>
>> Signed-off-by: Andreas Fenkart <afenkart@gmail.com>
>>
>> diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
>> index a5a38cc..bd3bb0c 100644
>> --- a/drivers/mmc/host/omap_hsmmc.c
>> +++ b/drivers/mmc/host/omap_hsmmc.c
>
>
> <snip>
>
>
>> @@ -1705,7 +1757,18 @@ static void omap_hsmmc_debugfs(struct mmc_host
>> *mmc)
>>   #endif
>>
>>   #ifdef CONFIG_OF
>> -static u16 omap4_reg_offset = 0x100;
>> +struct of_data {
>> +       u16 offset;
>> +       int flags;
>> +};
>> +
>
> Hi Andreas,
>
> struct of_data declaration needs to be moved out of #ifdef CONFIG_OF
> for !CONFIG_OF build.
should be fixed with new version

>
> I tried testing this patch series on am335x, I see throughput in the
> range of KBs. Will give another try with Tony's version.
KB sounds really bad, even with polling I have > 5MBytes/s.

Could you pls paste
# cat /sys/kernel/debug/mmc0/regs

Thanks for testing.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v7 1/4] mmc: omap_hsmmc: Enable SDIO IRQ.
  2014-03-05  8:27     ` Andreas Fenkart
@ 2014-03-05 16:33       ` Tony Lindgren
  2014-03-11  9:42         ` Andreas Fenkart
  0 siblings, 1 reply; 18+ messages in thread
From: Tony Lindgren @ 2014-03-05 16:33 UTC (permalink / raw)
  To: Andreas Fenkart
  Cc: Chris Ball, Grant Likely, Felipe Balbi, Balaji T K, Daniel Mack,
	Kumar Gala, linux-doc, linux-mmc, linux-omap

* Andreas Fenkart <afenkart@gmail.com> [140305 00:30]:
> Hi,
> 
> 2014-02-27 22:33 GMT+01:00 Tony Lindgren <tony@atomide.com>:
> >
> > Thanks for updating this, I finally got around to spend some
> > time with it again. I've folded in your fixes and quirk support
> > into my earlier patch from [0] as that had a better changelog
> > describing the earlier work.
> thanks, always struggled with that
> 
> > And I've also now made the SDIO support to depend on properly
> > configured wake-up irq from device tree as otherwise wake from
> > idle states won't work properly. I've also cleaned up the the
> > wake-up irq initialization a bit.
> Looks much better now.
> 
> Mind that the sdio irq is level triggered. So we have to disable the
> IRQ in the handler otherwise we enter an infinite loop.
 
Oh OK, I was trying to get rid of all the extra flags. But it
seem we may still need the wake_irq enabled status bit then.
 
> > The wake-irq is needed for omaps with wake-up path and also
> > when doing GPIO remuxing. So the wake-up handling is pretty
> > much the same for both cases.
> I added this comment to the patch, since I was puzzled that you need
> a wake_irq even whithout remuxing.

Yeah we need it because omap_hsmmc is already doing runtime PM,
so there's nothing stopping from shutting it down. And there's
really no need to block runtime PM for it as it's working. 

> > I've kept your Signed-off-by, can you please check if the patch
> > below works for you with the second patch I'll post shortly?
> 
> Will send out another patch soon. Left your Signed-off as well, not
> in the sense of your agreement, but didn't dare to remove it because
> of your contributions.

Yeah thanks will try to test it today :)

Regards,

Tony

 
> > [0] https://www.mail-archive.com/linux-mmc@vger.kernel.org/msg22290.html

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v7 1/4] mmc: omap_hsmmc: Enable SDIO IRQ.
  2014-03-05  8:30     ` Andreas Fenkart
@ 2014-03-07 15:12       ` Balaji T K
  2014-03-07 16:04         ` Tony Lindgren
  0 siblings, 1 reply; 18+ messages in thread
From: Balaji T K @ 2014-03-07 15:12 UTC (permalink / raw)
  To: Andreas Fenkart
  Cc: Chris Ball, Tony Lindgren, Grant Likely, Felipe Balbi,
	Daniel Mack, Kumar Gala, linux-doc, linux-mmc, linux-omap

On Wednesday 05 March 2014 02:00 PM, Andreas Fenkart wrote:
> Hi,
>
> 2014-02-28 18:04 GMT+01:00 Balaji T K <balajitk@ti.com>:
>> On Tuesday 25 February 2014 06:07 PM, Andreas Fenkart wrote:
>>>
>>> For now, only support SDIO interrupt if we are booted with
>>> DT. This is because some platforms need special quirks. And
>>> we don't want to add new legacy mux platform init code
>>> callbacks any longer as we are moving to DT based booting
>>> anyways.
>>>
>>> Signed-off-by: Andreas Fenkart <afenkart@gmail.com>
>>>
>>> diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
>>> index a5a38cc..bd3bb0c 100644
>>> --- a/drivers/mmc/host/omap_hsmmc.c
>>> +++ b/drivers/mmc/host/omap_hsmmc.c
>>
>>
>> <snip>
>>
>>
>>> @@ -1705,7 +1757,18 @@ static void omap_hsmmc_debugfs(struct mmc_host
>>> *mmc)
>>>    #endif
>>>
>>>    #ifdef CONFIG_OF
>>> -static u16 omap4_reg_offset = 0x100;
>>> +struct of_data {
>>> +       u16 offset;
>>> +       int flags;
>>> +};
>>> +
>>
>> Hi Andreas,
>>
>> struct of_data declaration needs to be moved out of #ifdef CONFIG_OF
>> for !CONFIG_OF build.
> should be fixed with new version
>
>>
>> I tried testing this patch series on am335x, I see throughput in the
>> range of KBs. Will give another try with Tony's version.
> KB sounds really bad, even with polling I have > 5MBytes/s.
>
> Could you pls paste
> # cat /sys/kernel/debug/mmc0/regs
>
Hi,

Find below debug reg dump

mmc0:
sdio irq        enabled
pinmux config   sdio
ctx_loss:       1

regs:
CON:            0x00000600
PSTATE:         0x01f70000
HCTL:           0x00000d06
SYSCTL:         0x000d0087
IE:             0x00000100
ISE:            0x00000100
CAPA:           0x06e10080


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v7 1/4] mmc: omap_hsmmc: Enable SDIO IRQ.
  2014-03-07 15:12       ` Balaji T K
@ 2014-03-07 16:04         ` Tony Lindgren
  0 siblings, 0 replies; 18+ messages in thread
From: Tony Lindgren @ 2014-03-07 16:04 UTC (permalink / raw)
  To: Balaji T K
  Cc: Andreas Fenkart, Chris Ball, Grant Likely, Felipe Balbi,
	Daniel Mack, Kumar Gala, linux-doc, linux-mmc, linux-omap

* Balaji T K <balajitk@ti.com> [140307 07:15]:
> On Wednesday 05 March 2014 02:00 PM, Andreas Fenkart wrote:
> >2014-02-28 18:04 GMT+01:00 Balaji T K <balajitk@ti.com>:
> >>
> >>I tried testing this patch series on am335x, I see throughput in the
> >>range of KBs. Will give another try with Tony's version.
> >KB sounds really bad, even with polling I have > 5MBytes/s.
> >
> >Could you pls paste
> ># cat /sys/kernel/debug/mmc0/regs
> >
> Hi,
> 
> Find below debug reg dump
> 
> mmc0:
> sdio irq        enabled
> pinmux config   sdio
> ctx_loss:       1
> 
> regs:
> CON:            0x00000600
> PSTATE:         0x01f70000
> HCTL:           0x00000d06
> SYSCTL:         0x000d0087
> IE:             0x00000100
> ISE:            0x00000100
> CAPA:           0x06e10080

Is this with wl12xx? If so, wl12xx driver is missing calls to
sdio_claim_irq() and sdio_release_irq() so it probably won't
behave properly with the SDIO interrupt until those are added.

Regards,

Tony

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v7 1/4] mmc: omap_hsmmc: Enable SDIO IRQ.
  2014-03-05 16:33       ` Tony Lindgren
@ 2014-03-11  9:42         ` Andreas Fenkart
  2014-03-11 16:37           ` Tony Lindgren
  0 siblings, 1 reply; 18+ messages in thread
From: Andreas Fenkart @ 2014-03-11  9:42 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Chris Ball, Grant Likely, Felipe Balbi, Balaji T K, Daniel Mack,
	Kumar Gala, linux-doc, linux-mmc, linux-omap

Hi,

2014-03-05 17:33 GMT+01:00 Tony Lindgren <tony@atomide.com>:
> * Andreas Fenkart <afenkart@gmail.com> [140305 00:30]:
>> Hi,
>>
>> 2014-02-27 22:33 GMT+01:00 Tony Lindgren <tony@atomide.com>:
>> >
>> > The wake-irq is needed for omaps with wake-up path and also
>> > when doing GPIO remuxing. So the wake-up handling is pretty
>> > much the same for both cases.
>> I added this comment to the patch, since I was puzzled that you need
>> a wake_irq even whithout remuxing.
>
> Yeah we need it because omap_hsmmc is already doing runtime PM,
> so there's nothing stopping from shutting it down. And there's
> really no need to block runtime PM for it as it's working.
>
Also added this comment, since it really clarifies the issue.

FYI, just tried the patch without pin remuxing on am335x and
it actually works. Read: I'm always using the sdio pinmux never
reconfiguring the pin as a GPIO, but still get GPIO interrupts.
Yes, it fails if I comment out the pm_runtime_resume.

So it's not that the am335x suddenly has a swakeup line,
but looks like an implementation detail of the am335x GPIO
block.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v7 1/4] mmc: omap_hsmmc: Enable SDIO IRQ.
  2014-03-11  9:42         ` Andreas Fenkart
@ 2014-03-11 16:37           ` Tony Lindgren
  0 siblings, 0 replies; 18+ messages in thread
From: Tony Lindgren @ 2014-03-11 16:37 UTC (permalink / raw)
  To: Andreas Fenkart
  Cc: Chris Ball, Grant Likely, Felipe Balbi, Balaji T K, Daniel Mack,
	Kumar Gala, linux-doc, linux-mmc, linux-omap

* Andreas Fenkart <afenkart@gmail.com> [140311 02:45]:
> Hi,
> 
> 2014-03-05 17:33 GMT+01:00 Tony Lindgren <tony@atomide.com>:
> > * Andreas Fenkart <afenkart@gmail.com> [140305 00:30]:
> >> Hi,
> >>
> >> 2014-02-27 22:33 GMT+01:00 Tony Lindgren <tony@atomide.com>:
> >> >
> >> > The wake-irq is needed for omaps with wake-up path and also
> >> > when doing GPIO remuxing. So the wake-up handling is pretty
> >> > much the same for both cases.
> >> I added this comment to the patch, since I was puzzled that you need
> >> a wake_irq even whithout remuxing.
> >
> > Yeah we need it because omap_hsmmc is already doing runtime PM,
> > so there's nothing stopping from shutting it down. And there's
> > really no need to block runtime PM for it as it's working.
> >
> Also added this comment, since it really clarifies the issue.

OK thanks.
 
> FYI, just tried the patch without pin remuxing on am335x and
> it actually works. Read: I'm always using the sdio pinmux never
> reconfiguring the pin as a GPIO, but still get GPIO interrupts.
> Yes, it fails if I comment out the pm_runtime_resume.
> 
> So it's not that the am335x suddenly has a swakeup line,
> but looks like an implementation detail of the am335x GPIO
> block.

Oh OK, that's good to know. I think 2420 behaved that way too
for the serial wake-up. What also may affect things is if that
GPIO line is in the first GPIO bank, for the other banks
remuxing may still be needed for deeper idle states.

Regards,

Tony

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2014-03-11 16:37 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-02-25 12:37 [PATCH v7 0/4] mmc: omap_hsmmc: SDIO IRQ Andreas Fenkart
2014-02-25 12:37 ` [PATCH v7 1/4] mmc: omap_hsmmc: Enable " Andreas Fenkart
2014-02-27 21:33   ` Tony Lindgren
2014-03-05  8:27     ` Andreas Fenkart
2014-03-05 16:33       ` Tony Lindgren
2014-03-11  9:42         ` Andreas Fenkart
2014-03-11 16:37           ` Tony Lindgren
2014-02-28 17:04   ` Balaji T K
2014-03-05  8:30     ` Andreas Fenkart
2014-03-07 15:12       ` Balaji T K
2014-03-07 16:04         ` Tony Lindgren
2014-02-25 12:37 ` [PATCH v7 2/4] mmc: omap_hsmmc: Remux SDIO pins within driver Andreas Fenkart
2014-02-27 21:36   ` Tony Lindgren
2014-02-27 21:42     ` Tony Lindgren
2014-02-25 12:37 ` [PATCH v7 3/4] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x Andreas Fenkart
2014-02-25 12:49   ` [PATCH v7 4/4] mmc: omap_hsmmc: Extend debugfs for SDIO IRQ, GPIO and pinmux Andreas Fenkart
2014-02-27 21:39     ` Tony Lindgren
2014-02-27 21:37   ` [PATCH v7 3/4] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x Tony Lindgren

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).