Skip to contentSkip to conversation

MMC updates, plus CuBox-i WiFi support

PATCH New Russell King - ARM Linux 10 participants 94 messages Apr 23, 2014 – Jun 19, 2014

Subsystems (12)
lore
Share & tools
lore
#0 lore raw

cover MMC updates, plus CuBox-i WiFi support

All,

This is where I'm at with trying to clean up the SDHCI mess, and sort out issues I've noticed when trying to get UHS support working on CuBoxes. This is my full patch set, but I recommend not applying patch 37 as there appears to be a hardware issue preventing it working reliably.

In any case, patches 0-33 inclusive are the SDHCI clean up, based against v3.15-rc1. Patches 34 and 35 are Olof's Wifi support, 36 is my fix against those, and 38 adds the Broadcom Wifi and BT support for CuBox.

The questions over how to handle these devices were never properly settled, so I recommend against merging patch 34 onwards. As for the rest, I'm not planning on any further work, so it may be a good idea for people to consider testing them with a view to getting them merged.

 Documentation/devicetree/bindings/mmc/mmc.txt |  11 +
 arch/arm/boot/dts/imx6qdl-cubox-i.dtsi        |  34 +-
 arch/arm/boot/dts/imx6qdl-microsom.dtsi       |  98 ++++
 drivers/mmc/core/core.c                       |  42 ++
 drivers/mmc/core/host.c                       |  68 +++
 drivers/mmc/core/sdio_irq.c                   |  41 +-
 drivers/mmc/host/Kconfig                      |  63 +--
 drivers/mmc/host/dw_mmc.c                     |   2 +
 drivers/mmc/host/sdhci-acpi.c                 |   8 +
 drivers/mmc/host/sdhci-bcm-kona.c             |   4 +
 drivers/mmc/host/sdhci-bcm2835.c              |   4 +
 drivers/mmc/host/sdhci-cns3xxx.c              |  13 +-
 drivers/mmc/host/sdhci-dove.c                 |   4 +
 drivers/mmc/host/sdhci-esdhc-imx.c            |  82 +--
 drivers/mmc/host/sdhci-esdhc.h                |   4 +-
 drivers/mmc/host/sdhci-of-arasan.c            |   4 +
 drivers/mmc/host/sdhci-of-esdhc.c             |  70 ++-
 drivers/mmc/host/sdhci-of-hlwd.c              |   4 +
 drivers/mmc/host/sdhci-pci.c                  |   9 +-
 drivers/mmc/host/sdhci-pltfm.c                |   4 +
 drivers/mmc/host/sdhci-pxav2.c                |  14 +-
 drivers/mmc/host/sdhci-pxav3.c                |  13 +-
 drivers/mmc/host/sdhci-s3c.c                  |  36 +-
 drivers/mmc/host/sdhci-sirf.c                 |   4 +
 drivers/mmc/host/sdhci-spear.c                |   5 +-
 drivers/mmc/host/sdhci-tegra.c                |  27 +-
 drivers/mmc/host/sdhci.c                      | 728 +++++++++++++-------------
 drivers/mmc/host/sdhci.h                      |  20 +-
 include/linux/mmc/host.h                      |   8 +
 include/linux/mmc/sdhci.h                     |  15 +-
 30 files changed, 885 insertions(+), 554 deletions(-)
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#1 lore raw

PATCH 1/38 mmc: sdio_irq: rework sdio irq handling

Rather than the SDIO support spawning it's own thread for handling card interrupts, use the generic IRQ infrastructure for this, triggering it from the host interface's interrupt handling directly.

This avoids a race between the parent thread waiting to receive an interrupt response from the card, and the slow startup from the sdio irq thread, which can occur as a result of high system load (eg, while udev is running.)

---
 drivers/mmc/core/sdio_irq.c | 41 +++++++++++++++++++++++++++++++----------
 include/linux/mmc/host.h    |  3 +++
 2 files changed, 34 insertions(+), 10 deletions(-)
drivers/mmc/core/sdio_irq.c +31 -10
index aaa90460ed23..f23d73993dc6 100644
@@ -90,6 +90,15 @@ static int process_sdio_pending_irqs(struct mmc_host *host)
 	return ret;
 }
 
+void sdio_run_irqs(struct mmc_host *host)
+{
+	mmc_claim_host(host);
+	host->sdio_irq_pending = true;
+	process_sdio_pending_irqs(host);
+	mmc_release_host(host);
+}
+EXPORT_SYMBOL_GPL(sdio_run_irqs);
+
 static int sdio_irq_thread(void *_host)
 {
 	struct mmc_host *host = _host;
@@ -189,14 +198,20 @@ static int sdio_card_irq_get(struct mmc_card *card)
 	WARN_ON(!host->claimed);
 
 	if (!host->sdio_irqs++) {
-		atomic_set(&host->sdio_irq_thread_abort, 0);
-		host->sdio_irq_thread =
-			kthread_run(sdio_irq_thread, host, "ksdioirqd/%s",
-				mmc_hostname(host));
-		if (IS_ERR(host->sdio_irq_thread)) {
-			int err = PTR_ERR(host->sdio_irq_thread);
-			host->sdio_irqs--;
-			return err;
+		if (!(host->caps2 & MMC_CAP2_SDIO_NOTHREAD)) {
+			atomic_set(&host->sdio_irq_thread_abort, 0);
+			host->sdio_irq_thread =
+				kthread_run(sdio_irq_thread, host,
+					    "ksdioirqd/%s", mmc_hostname(host));
+			if (IS_ERR(host->sdio_irq_thread)) {
+				int err = PTR_ERR(host->sdio_irq_thread);
+				host->sdio_irqs--;
+				return err;
+			}
+		} else {
+			mmc_host_clk_hold(host);
+			host->ops->enable_sdio_irq(host, 1);
+			mmc_host_clk_release(host);
 		}
 	}
 
@@ -211,8 +226,14 @@ static int sdio_card_irq_put(struct mmc_card *card)
 	BUG_ON(host->sdio_irqs < 1);
 
 	if (!--host->sdio_irqs) {
-		atomic_set(&host->sdio_irq_thread_abort, 1);
-		kthread_stop(host->sdio_irq_thread);
+		if (!(host->caps2 & MMC_CAP2_SDIO_NOTHREAD)) {
+			atomic_set(&host->sdio_irq_thread_abort, 1);
+			kthread_stop(host->sdio_irq_thread);
+		} else {
+			mmc_host_clk_hold(host);
+			host->ops->enable_sdio_irq(host, 0);
+			mmc_host_clk_release(host);
+		}
 	}
 
 	return 0;
include/linux/mmc/host.h +3 -0
index cb61ea4d6945..28c5e796292f 100644
@@ -278,6 +278,7 @@ struct mmc_host {
 #define MMC_CAP2_PACKED_CMD	(MMC_CAP2_PACKED_RD | \
 				 MMC_CAP2_PACKED_WR)
 #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)	/* Don't power up before scan */
+#define MMC_CAP2_SDIO_NOTHREAD	(1 << 15)
 
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
 
@@ -391,6 +392,8 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host)
 	wake_up_process(host->sdio_irq_thread);
 }
 
+void sdio_run_irqs(struct mmc_host *host);
+
 #ifdef CONFIG_REGULATOR
 int mmc_regulator_get_ocrmask(struct regulator *supply);
 int mmc_regulator_set_ocr(struct mmc_host *mmc,
Signature · 1 line
1.8.3.1
#2 lore raw

PATCH 1/38 mmc: sdio_irq: rework sdio irq handling

Quoted 48 lines · Russell King

Rather than the SDIO support spawning it's own thread for handling card interrupts, use the generic IRQ infrastructure for this, triggering it from the host interface's interrupt handling directly.

This avoids a race between the parent thread waiting to receive an interrupt response from the card, and the slow startup from the sdio irq thread, which can occur as a result of high system load (eg, while udev is running.)

---
 drivers/mmc/core/sdio_irq.c | 41 +++++++++++++++++++++++++++++++----------
 include/linux/mmc/host.h    |  3 +++
 2 files changed, 34 insertions(+), 10 deletions(-)
drivers/mmc/core/sdio_irq.c +10 -8
index aaa90460ed23..f23d73993dc6 100644
@@ -90,6 +90,15 @@ static int process_sdio_pending_irqs(struct mmc_host *host)
        return ret;
 }
 
+void sdio_run_irqs(struct mmc_host *host)
+{
+       mmc_claim_host(host);
+       host->sdio_irq_pending = true;
+       process_sdio_pending_irqs(host);
+       mmc_release_host(host);
+}
+EXPORT_SYMBOL_GPL(sdio_run_irqs);
+
 static int sdio_irq_thread(void *_host)
 {
        struct mmc_host *host = _host;
@@ -189,14 +198,20 @@ static int sdio_card_irq_get(struct mmc_card *card)
        WARN_ON(!host->claimed);
 
        if (!host->sdio_irqs++) {
-               atomic_set(&host->sdio_irq_thread_abort, 0);
-               host->sdio_irq_thread =
-                       kthread_run(sdio_irq_thread, host, "ksdioirqd/%s",
-                               mmc_hostname(host));
-               if (IS_ERR(host->sdio_irq_thread)) {
-                       int err = PTR_ERR(host->sdio_irq_thread);
-                       host->sdio_irqs--;
-                       return err;
+               if (!(host->caps2 & MMC_CAP2_SDIO_NOTHREAD)) {

drivers/mmc/core/sdio_irq.c static int sdio_card_irq_get(struct mmc_card *card) · line 211

Quoted 10 lines
drivers/mmc/core/sdio_irq.c +10 -0
+                       atomic_set(&host->sdio_irq_thread_abort, 0);
+                       host->sdio_irq_thread =
+                               kthread_run(sdio_irq_thread, host,
+                                           "ksdioirqd/%s", mmc_hostname(host));
+                       if (IS_ERR(host->sdio_irq_thread)) {
+                               int err = PTR_ERR(host->sdio_irq_thread);
+                               host->sdio_irqs--;
+                               return err;
+                       }
+               } else {

I suppose you need to check for MMC_CAP_SDIO_IRQ here?

Quoted 7 lines
drivers/mmc/core/sdio_irq.c +3 -0
+                       mmc_host_clk_hold(host);
+                       host->ops->enable_sdio_irq(host, 1);
+                       mmc_host_clk_release(host);
                }
        }
 

drivers/mmc/core/sdio_irq.c static int sdio_card_irq_put(struct mmc_card *card) · line 232

Quoted 9 lines
drivers/mmc/core/sdio_irq.c +4 -2
@@ -211,8 +226,14 @@ static int sdio_card_irq_put(struct mmc_card *card)
        BUG_ON(host->sdio_irqs < 1);
 
        if (!--host->sdio_irqs) {
-               atomic_set(&host->sdio_irq_thread_abort, 1);
-               kthread_stop(host->sdio_irq_thread);
+               if (!(host->caps2 & MMC_CAP2_SDIO_NOTHREAD)) {
+                       atomic_set(&host->sdio_irq_thread_abort, 1);
+                       kthread_stop(host->sdio_irq_thread);
+               } else {

I suppose you need to check for MMC_CAP_SDIO_IRQ here?

Quoted 29 lines
drivers/mmc/core/sdio_irq.c +4 -0
+                       mmc_host_clk_hold(host);
+                       host->ops->enable_sdio_irq(host, 0);
+                       mmc_host_clk_release(host);
+               }
        }
 
        return 0;
include/linux/mmc/host.h +3 -1
index cb61ea4d6945..28c5e796292f 100644
@@ -278,6 +278,7 @@ struct mmc_host {
 #define MMC_CAP2_PACKED_CMD    (MMC_CAP2_PACKED_RD | \
                                 MMC_CAP2_PACKED_WR)
 #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)  /* Don't power up before scan */
+#define MMC_CAP2_SDIO_NOTHREAD (1 << 15)
 
        mmc_pm_flag_t           pm_caps;        /* supported pm features */
 
@@ -391,6 +392,8 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host)
        wake_up_process(host->sdio_irq_thread);
 }
 
+void sdio_run_irqs(struct mmc_host *host);
+
 #ifdef CONFIG_REGULATOR
 int mmc_regulator_get_ocrmask(struct regulator *supply);
 int mmc_regulator_set_ocr(struct mmc_host *mmc,
--
Quoted 1 line

1.8.3.1

Kind regards
Ulf Hansson

Quoted 5 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#3 lore raw

PATCH 1/38 mmc: sdio_irq: rework sdio irq handling

Quoted 13 lines · Ulf Hansson

drivers/mmc/core/sdio_irq.c static int sdio_card_irq_get(struct mmc_card *card) · line 211

Quoted 11 lines · Russell King
drivers/mmc/core/sdio_irq.c +11 -0
+               if (!(host->caps2 & MMC_CAP2_SDIO_NOTHREAD)) {
+                       atomic_set(&host->sdio_irq_thread_abort, 0);
+                       host->sdio_irq_thread =
+                               kthread_run(sdio_irq_thread, host,
+                                           "ksdioirqd/%s", mmc_hostname(host));
+                       if (IS_ERR(host->sdio_irq_thread)) {
+                               int err = PTR_ERR(host->sdio_irq_thread);
+                               host->sdio_irqs--;
+                               return err;
+                       }
+               } else {
Quoted 1 line

I suppose you need to check for MMC_CAP_SDIO_IRQ here?

Why would you set MMC_CAP2_SDIO_NOTHREAD if you didn't have MMC_CAP_SDIO_IRQ ?

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#4 lore raw

PATCH 1/38 mmc: sdio_irq: rework sdio irq handling

Quoted 14 lines · Russell King - ARM Linux
Quoted 13 lines · Ulf Hansson
Quoted 11 lines · Russell King
drivers/mmc/core/sdio_irq.c +11 -0
+               if (!(host->caps2 & MMC_CAP2_SDIO_NOTHREAD)) {
+                       atomic_set(&host->sdio_irq_thread_abort, 0);
+                       host->sdio_irq_thread =
+                               kthread_run(sdio_irq_thread, host,
+                                           "ksdioirqd/%s", mmc_hostname(host));
+                       if (IS_ERR(host->sdio_irq_thread)) {
+                               int err = PTR_ERR(host->sdio_irq_thread);
+                               host->sdio_irqs--;
+                               return err;
+                       }
+               } else {
Quoted 3 lines
Quoted 1 line

I suppose you need to check for MMC_CAP_SDIO_IRQ here?

Why would you set MMC_CAP2_SDIO_NOTHREAD if you didn't have MMC_CAP_SDIO_IRQ ?

You are right!

Maybe change the name to "MMC_CAP2_SDIO_IRQ_NOTHREAD", unless we think it becomes too long :-). Additionally, there are actually still some bits available in the MMC_CAP_* bits, instead of the MMC_CAP2_*.

No strong opinion though, feel free to keep as is.

Quoted 4 lines

--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.

#5 lore raw

PATCH 2/38 mmc: sdhci: clean up interrupt handling

In reply to Russell King - ARM Linux

sdhci interrupt handling is a mess; there is a lot of code doing very similar things. Let's clean this up a bit:

1. set's clear down cmd, data and bus power interrupts in one go - we're always going to handle these.
2. use a do { } while () loop for looping while there are pending interrupts.
3. group clearing of bits in intmask into one place.

This results in the code becoming simpler and easier to read.

---
 drivers/mmc/host/sdhci.c | 124 ++++++++++++++++++++++-------------------------
 1 file changed, 58 insertions(+), 66 deletions(-)
drivers/mmc/host/sdhci.c +58 -66
index 9a79fc4b60ca..79838de6b278 100644
@@ -2426,7 +2426,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 {
 	irqreturn_t result;
 	struct sdhci_host *host = dev_id;
-	u32 intmask, unexpected = 0;
+	u32 intmask, mask, unexpected = 0;
 	int cardint = 0, max_loops = 16;
 
 	spin_lock(&host->lock);
@@ -2437,88 +2437,80 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 	}
 
 	intmask = sdhci_readl(host, SDHCI_INT_STATUS);
-
 	if (!intmask || intmask == 0xffffffff) {
 		result = IRQ_NONE;
 		goto out;
 	}
 
-again:
-	DBG("*** %s got interrupt: 0x%08x\n",
-		mmc_hostname(host->mmc), intmask);
-
-	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
-		u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
-			      SDHCI_CARD_PRESENT;
-
-		/*
-		 * There is a observation on i.mx esdhc.  INSERT bit will be
-		 * immediately set again when it gets cleared, if a card is
-		 * inserted.  We have to mask the irq to prevent interrupt
-		 * storm which will freeze the system.  And the REMOVE gets
-		 * the same situation.
-		 *
-		 * More testing are needed here to ensure it works for other
-		 * platforms though.
-		 */
-		sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT :
-						SDHCI_INT_CARD_REMOVE);
-		sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE :
-						  SDHCI_INT_CARD_INSERT);
-
-		sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
-			     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
-		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
-		tasklet_schedule(&host->card_tasklet);
-	}
+	do {
+		/* Clear selected interrupts. */
+		mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
+				  SDHCI_INT_BUS_POWER);
+		sdhci_writel(host, mask, SDHCI_INT_STATUS);
 
-	if (intmask & SDHCI_INT_CMD_MASK) {
-		sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,
-			SDHCI_INT_STATUS);
-		sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
-	}
+		DBG("*** %s got interrupt: 0x%08x\n",
+			mmc_hostname(host->mmc), intmask);
 
-	if (intmask & SDHCI_INT_DATA_MASK) {
-		sdhci_writel(host, intmask & SDHCI_INT_DATA_MASK,
-			SDHCI_INT_STATUS);
-		sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
-	}
+		if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
+			u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
+				      SDHCI_CARD_PRESENT;
 
-	intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK);
+			/*
+			 * There is a observation on i.mx esdhc.  INSERT
+			 * bit will be immediately set again when it gets
+			 * cleared, if a card is inserted.  We have to mask
+			 * the irq to prevent interrupt storm which will
+			 * freeze the system.  And the REMOVE gets the
+			 * same situation.
+			 *
+			 * More testing are needed here to ensure it works
+			 * for other platforms though.
+			 */
+			sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT :
+							SDHCI_INT_CARD_REMOVE);
+			sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE :
+							  SDHCI_INT_CARD_INSERT);
+
+			sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
+				     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
+			tasklet_schedule(&host->card_tasklet);
+		}
 
-	intmask &= ~SDHCI_INT_ERROR;
+		if (intmask & SDHCI_INT_CMD_MASK)
+			sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
 
-	if (intmask & SDHCI_INT_BUS_POWER) {
-		pr_err("%s: Card is consuming too much power!\n",
-			mmc_hostname(host->mmc));
-		sdhci_writel(host, SDHCI_INT_BUS_POWER, SDHCI_INT_STATUS);
-	}
+		if (intmask & SDHCI_INT_DATA_MASK)
+			sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
 
-	intmask &= ~SDHCI_INT_BUS_POWER;
+		if (intmask & SDHCI_INT_BUS_POWER)
+			pr_err("%s: Card is consuming too much power!\n",
+				mmc_hostname(host->mmc));
 
-	if (intmask & SDHCI_INT_CARD_INT)
-		cardint = 1;
+		if (intmask & SDHCI_INT_CARD_INT)
+			cardint = 1;
 
-	intmask &= ~SDHCI_INT_CARD_INT;
+		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE |
+			     SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
+			     SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER |
+			     SDHCI_INT_CARD_INT);
 
-	if (intmask) {
-		unexpected |= intmask;
-		sdhci_writel(host, intmask, SDHCI_INT_STATUS);
-	}
+		if (intmask) {
+			unexpected |= intmask;
+			sdhci_writel(host, intmask, SDHCI_INT_STATUS);
+		}
 
-	result = IRQ_HANDLED;
+		result = IRQ_HANDLED;
 
-	intmask = sdhci_readl(host, SDHCI_INT_STATUS);
+		intmask = sdhci_readl(host, SDHCI_INT_STATUS);
 
-	/*
-	 * If we know we'll call the driver to signal SDIO IRQ, disregard
-	 * further indications of Card Interrupt in the status to avoid a
-	 * needless loop.
-	 */
-	if (cardint)
-		intmask &= ~SDHCI_INT_CARD_INT;
-	if (intmask && --max_loops)
-		goto again;
+		/*
+		 * If we know we'll call the driver to signal SDIO IRQ,
+		 * disregard further indications of Card Interrupt in
+		 * the status to avoid a needless loop.
+		 */
+		if (cardint)
+			intmask &= ~SDHCI_INT_CARD_INT;
+	} while (intmask && --max_loops);
 out:
 	spin_unlock(&host->lock);
 
Signature · 1 line
1.8.3.1
#6 lore raw

PATCH 3/38 mmc: sdhci: clean up sdio interrupt enable handling

In reply to Russell King - ARM Linux

We don't need to change the SDHCI_SDIO_IRQ_ENABLED flag when we're merely receiving an interrupt - IRQ handling thread in the MMC core will either re-enable or disable the interrupt via the enable_sdio_irq callback, which will update this status appropriately.

---
 drivers/mmc/host/sdhci.c | 35 +++++++++++++++++------------------
 1 file changed, 17 insertions(+), 18 deletions(-)
drivers/mmc/host/sdhci.c +17 -18
index 79838de6b278..239d90d77ac4 100644
@@ -1709,24 +1709,14 @@ static int sdhci_get_ro(struct mmc_host *mmc)
 
 static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
 {
-	if (host->flags & SDHCI_DEVICE_DEAD)
-		goto out;
-
-	if (enable)
-		host->flags |= SDHCI_SDIO_IRQ_ENABLED;
-	else
-		host->flags &= ~SDHCI_SDIO_IRQ_ENABLED;
-
 	/* SDIO IRQ will be enabled as appropriate in runtime resume */
-	if (host->runtime_suspended)
-		goto out;
-
-	if (enable)
-		sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT);
-	else
-		sdhci_mask_irqs(host, SDHCI_INT_CARD_INT);
-out:
-	mmiowb();
+	if (!(host->flags & SDHCI_DEVICE_DEAD) || host->runtime_suspended) {
+		if (enable)
+			sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT);
+		else
+			sdhci_mask_irqs(host, SDHCI_INT_CARD_INT);
+		mmiowb();
+	}
 }
 
 static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
@@ -1734,9 +1724,18 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
 	struct sdhci_host *host = mmc_priv(mmc);
 	unsigned long flags;
 
+	sdhci_runtime_pm_get(host);
+
 	spin_lock_irqsave(&host->lock, flags);
+	if (enable)
+		host->flags |= SDHCI_SDIO_IRQ_ENABLED;
+	else
+		host->flags &= ~SDHCI_SDIO_IRQ_ENABLED;
+
 	sdhci_enable_sdio_irq_nolock(host, enable);
 	spin_unlock_irqrestore(&host->lock, flags);
+
+	sdhci_runtime_pm_put(host);
 }
 
 static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
@@ -2721,7 +2720,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
 	host->runtime_suspended = false;
 
 	/* Enable SDIO IRQ */
-	if ((host->flags & SDHCI_SDIO_IRQ_ENABLED))
+	if (host->flags & SDHCI_SDIO_IRQ_ENABLED)
 		sdhci_enable_sdio_irq_nolock(host, true);
 
 	/* Enable Card Detection */
Signature · 1 line
1.8.3.1
#7 lore raw

PATCH 4/38 mmc: sdhci: convert to new SDIO IRQ handling

In reply to Russell King - ARM Linux

Use a generic threaded interrupt handler for SDIO interrupt handling, rather than allowing the SDIO core code to buggily spawn its own thread. This results in host drivers to be more in control of how SDIO interrupts are acknowledged in the hardware, rather than having the internals of the SDIO core placed upon them, possibly resulting in sub-standard handling.

At least one SDHCI implementation specifies a very specific sequence to deal with a card interrupt.

---
 drivers/mmc/host/sdhci.c  | 62 +++++++++++++++++++++++++++++------------------
 include/linux/mmc/sdhci.h |  2 ++
 2 files changed, 41 insertions(+), 23 deletions(-)
drivers/mmc/host/sdhci.c +39 -23
index 239d90d77ac4..a2b04cdc594d 100644
@@ -2423,10 +2423,10 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
 
 static irqreturn_t sdhci_irq(int irq, void *dev_id)
 {
-	irqreturn_t result;
+	irqreturn_t result = IRQ_NONE;
 	struct sdhci_host *host = dev_id;
 	u32 intmask, mask, unexpected = 0;
-	int cardint = 0, max_loops = 16;
+	int max_loops = 16;
 
 	spin_lock(&host->lock);
 
@@ -2485,8 +2485,11 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 			pr_err("%s: Card is consuming too much power!\n",
 				mmc_hostname(host->mmc));
 
-		if (intmask & SDHCI_INT_CARD_INT)
-			cardint = 1;
+		if (intmask & SDHCI_INT_CARD_INT) {
+			sdhci_enable_sdio_irq_nolock(host, false);
+			host->thread_isr |= SDHCI_INT_CARD_INT;
+			result = IRQ_WAKE_THREAD;
+		}
 
 		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE |
 			     SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
@@ -2498,17 +2501,10 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 			sdhci_writel(host, intmask, SDHCI_INT_STATUS);
 		}
 
-		result = IRQ_HANDLED;
+		if (result == IRQ_NONE)
+			result = IRQ_HANDLED;
 
 		intmask = sdhci_readl(host, SDHCI_INT_STATUS);
-
-		/*
-		 * If we know we'll call the driver to signal SDIO IRQ,
-		 * disregard further indications of Card Interrupt in
-		 * the status to avoid a needless loop.
-		 */
-		if (cardint)
-			intmask &= ~SDHCI_INT_CARD_INT;
 	} while (intmask && --max_loops);
 out:
 	spin_unlock(&host->lock);
@@ -2518,15 +2514,33 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 			   mmc_hostname(host->mmc), unexpected);
 		sdhci_dumpregs(host);
 	}
-	/*
-	 * We have to delay this as it calls back into the driver.
-	 */
-	if (cardint)
-		mmc_signal_sdio_irq(host->mmc);
 
 	return result;
 }
 
+static irqreturn_t sdhci_thread_irq(int irq, void *dev_id)
+{
+	struct sdhci_host *host = dev_id;
+	unsigned long flags;
+	u32 isr;
+
+	spin_lock_irqsave(&host->lock, flags);
+	isr = host->thread_isr;
+	host->thread_isr = 0;
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	if (isr & SDHCI_INT_CARD_INT) {
+		sdio_run_irqs(host->mmc);
+
+		spin_lock_irqsave(&host->lock, flags);
+		if (host->flags & SDHCI_SDIO_IRQ_ENABLED)
+			sdhci_enable_sdio_irq_nolock(host, true);
+		spin_unlock_irqrestore(&host->lock, flags);
+	}
+
+	return isr ? IRQ_HANDLED : IRQ_NONE;
+}
+
 /*****************************************************************************\
  *                                                                           *
  * Suspend/resume                                                            *
@@ -2596,8 +2610,9 @@ int sdhci_resume_host(struct sdhci_host *host)
 	}
 
 	if (!device_may_wakeup(mmc_dev(host->mmc))) {
-		ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
-				  mmc_hostname(host->mmc), host);
+		ret = request_threaded_irq(host->irq, sdhci_irq,
+					   sdhci_thread_irq, IRQF_SHARED,
+					   mmc_hostname(host->mmc), host);
 		if (ret)
 			return ret;
 	} else {
@@ -2676,7 +2691,7 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
 	sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
 	spin_unlock_irqrestore(&host->lock, flags);
 
-	synchronize_irq(host->irq);
+	synchronize_hardirq(host->irq);
 
 	spin_lock_irqsave(&host->lock, flags);
 	host->runtime_suspended = true;
@@ -2932,6 +2947,7 @@ int sdhci_add_host(struct sdhci_host *host)
 	mmc->max_busy_timeout = (1 << 27) / host->timeout_clk;
 
 	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
+	mmc->caps2 |= MMC_CAP2_SDIO_NOTHREAD;
 
 	if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
 		host->flags |= SDHCI_AUTO_CMD12;
@@ -3221,8 +3237,8 @@ int sdhci_add_host(struct sdhci_host *host)
 
 	sdhci_init(host, 0);
 
-	ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
-		mmc_hostname(mmc), host);
+	ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq,
+				   IRQF_SHARED,	mmc_hostname(mmc), host);
 	if (ret) {
 		pr_err("%s: Failed to request IRQ %d: %d\n",
 		       mmc_hostname(mmc), host->irq, ret);
include/linux/mmc/sdhci.h +2 -0
index 7be12b883485..d1aa97b77dd9 100644
@@ -177,6 +177,8 @@ struct sdhci_host {
 	unsigned int            ocr_avail_mmc;
 	u32 ocr_mask;		/* available voltages */
 
+	u32			thread_isr;
+
 	wait_queue_head_t	buf_ready_int;	/* Waitqueue for Buffer Read Ready interrupt */
 	unsigned int		tuning_done;	/* Condition flag set when CMD19 succeeds */
 
Signature · 1 line
1.8.3.1
#8 lore raw

PATCH 5/38 mmc: sdhci: push card_tasklet into threaded irq handler

In reply to Russell King - ARM Linux

There's no requirement to have the card tasklet separate now that we have a threaded interrupt handler, so kill this and move the called code into the threaded part of the handler.

---
 drivers/mmc/host/sdhci.c  | 23 +++++++++--------------
 include/linux/mmc/sdhci.h |  3 +--
 2 files changed, 10 insertions(+), 16 deletions(-)
drivers/mmc/host/sdhci.c +9 -14
index a2b04cdc594d..878c6eb5aa8b 100644
@@ -2123,15 +2123,6 @@ static const struct mmc_host_ops sdhci_ops = {
  *                                                                           *
 \*****************************************************************************/
 
-static void sdhci_tasklet_card(unsigned long param)
-{
-	struct sdhci_host *host = (struct sdhci_host*)param;
-
-	sdhci_card_event(host->mmc);
-
-	mmc_detect_change(host->mmc, msecs_to_jiffies(200));
-}
-
 static void sdhci_tasklet_finish(unsigned long param)
 {
 	struct sdhci_host *host;
@@ -2472,7 +2463,10 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 
 			sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
 				     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
-			tasklet_schedule(&host->card_tasklet);
+
+			host->thread_isr |= intmask & (SDHCI_INT_CARD_INSERT |
+						       SDHCI_INT_CARD_REMOVE);
+			result = IRQ_WAKE_THREAD;
 		}
 
 		if (intmask & SDHCI_INT_CMD_MASK)
@@ -2529,6 +2523,11 @@ static irqreturn_t sdhci_thread_irq(int irq, void *dev_id)
 	host->thread_isr = 0;
 	spin_unlock_irqrestore(&host->lock, flags);
 
+	if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
+		sdhci_card_event(host->mmc);
+		mmc_detect_change(host->mmc, msecs_to_jiffies(200));
+	}
+
 	if (isr & SDHCI_INT_CARD_INT) {
 		sdio_run_irqs(host->mmc);
 
@@ -3219,8 +3218,6 @@ int sdhci_add_host(struct sdhci_host *host)
 	/*
 	 * Init tasklets.
 	 */
-	tasklet_init(&host->card_tasklet,
-		sdhci_tasklet_card, (unsigned long)host);
 	tasklet_init(&host->finish_tasklet,
 		sdhci_tasklet_finish, (unsigned long)host);
 
@@ -3285,7 +3282,6 @@ int sdhci_add_host(struct sdhci_host *host)
 	free_irq(host->irq, host);
 #endif
 untasklet:
-	tasklet_kill(&host->card_tasklet);
 	tasklet_kill(&host->finish_tasklet);
 
 	return ret;
@@ -3329,7 +3325,6 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
 
 	del_timer_sync(&host->timer);
 
-	tasklet_kill(&host->card_tasklet);
 	tasklet_kill(&host->finish_tasklet);
 
 	if (host->vmmc) {
include/linux/mmc/sdhci.h +1 -2
index d1aa97b77dd9..f1c8e14e8751 100644
@@ -164,8 +164,7 @@ struct sdhci_host {
 	dma_addr_t adma_addr;	/* Mapped ADMA descr. table */
 	dma_addr_t align_addr;	/* Mapped bounce buffer */
 
-	struct tasklet_struct card_tasklet;	/* Tasklet structures */
-	struct tasklet_struct finish_tasklet;
+	struct tasklet_struct finish_tasklet;	/* Tasklet structures */
 
 	struct timer_list timer;	/* Timer for timeouts */
 
Signature · 1 line
1.8.3.1
#9 lore raw

PATCH 6/38 mmc: sdhci: allow sdio interrupts while sdhci runtime suspended

In reply to Russell King - ARM Linux

Allow SDIO interrupts to be received while the SDHCI host is runtime suspended. We do this by leaving the AHB clock enabled while the host is runtime suspended so we can access the SDHCI registers, and so read and raise the SDIO card interrupt.

---
 drivers/mmc/host/sdhci-esdhc-imx.c | 12 ++++++++----
 drivers/mmc/host/sdhci.c           |  7 +++----
 drivers/mmc/host/sdhci.h           |  5 +++++
 3 files changed, 16 insertions(+), 8 deletions(-)
drivers/mmc/host/sdhci-esdhc-imx.c +8 -4
index b841bb7cd371..b0b4eea8d232 100644
@@ -1170,8 +1170,10 @@ static int sdhci_esdhc_runtime_suspend(struct device *dev)
 
 	ret = sdhci_runtime_suspend_host(host);
 
-	clk_disable_unprepare(imx_data->clk_per);
-	clk_disable_unprepare(imx_data->clk_ipg);
+	if (!sdhci_sdio_irq_enabled(host)) {
+		clk_disable_unprepare(imx_data->clk_per);
+		clk_disable_unprepare(imx_data->clk_ipg);
+	}
 	clk_disable_unprepare(imx_data->clk_ahb);
 
 	return ret;
@@ -1183,8 +1185,10 @@ static int sdhci_esdhc_runtime_resume(struct device *dev)
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
 
-	clk_prepare_enable(imx_data->clk_per);
-	clk_prepare_enable(imx_data->clk_ipg);
+	if (!sdhci_sdio_irq_enabled(host)) {
+		clk_prepare_enable(imx_data->clk_per);
+		clk_prepare_enable(imx_data->clk_ipg);
+	}
 	clk_prepare_enable(imx_data->clk_ahb);
 
 	return sdhci_runtime_resume_host(host);
drivers/mmc/host/sdhci.c +3 -4
index 878c6eb5aa8b..3af58f3cc165 100644
@@ -1709,8 +1709,7 @@ static int sdhci_get_ro(struct mmc_host *mmc)
 
 static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
 {
-	/* SDIO IRQ will be enabled as appropriate in runtime resume */
-	if (!(host->flags & SDHCI_DEVICE_DEAD) || host->runtime_suspended) {
+	if (!(host->flags & SDHCI_DEVICE_DEAD)) {
 		if (enable)
 			sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT);
 		else
@@ -2421,7 +2420,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 
 	spin_lock(&host->lock);
 
-	if (host->runtime_suspended) {
+	if (host->runtime_suspended && !sdhci_sdio_irq_enabled(host)) {
 		spin_unlock(&host->lock);
 		return IRQ_NONE;
 	}
@@ -2687,7 +2686,7 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
 	}
 
 	spin_lock_irqsave(&host->lock, flags);
-	sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
+	sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK & ~SDHCI_INT_CARD_INT);
 	spin_unlock_irqrestore(&host->lock, flags);
 
 	synchronize_hardirq(host->irq);
drivers/mmc/host/sdhci.h +5 -0
index 0a3ed01887db..fc6f81d2f377 100644
@@ -397,6 +397,11 @@ extern void sdhci_remove_host(struct sdhci_host *host, int dead);
 extern void sdhci_send_command(struct sdhci_host *host,
 				struct mmc_command *cmd);
 
+static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host)
+{
+	return !!(host->flags & SDHCI_SDIO_IRQ_ENABLED);
+}
+
 #ifdef CONFIG_PM
 extern int sdhci_suspend_host(struct sdhci_host *host);
 extern int sdhci_resume_host(struct sdhci_host *host);
Signature · 1 line
1.8.3.1
#10 lore raw

PATCH 7/38 mmc: sdhci: more efficient interrupt enable register handling

In reply to Russell King - ARM Linux

Rather than wasting cycles read-modify-writing the interrupt enable registers, cache the value locally instead.

---
 drivers/mmc/host/sdhci.c  | 98 +++++++++++++++++++++++------------------------
 include/linux/mmc/sdhci.h |  3 ++
 2 files changed, 50 insertions(+), 51 deletions(-)
drivers/mmc/host/sdhci.c +47 -51
index 3af58f3cc165..d568c8e4ee33 100644
@@ -131,27 +131,6 @@ static void sdhci_dumpregs(struct sdhci_host *host)
  *                                                                           *
 \*****************************************************************************/
 
-static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set)
-{
-	u32 ier;
-
-	ier = sdhci_readl(host, SDHCI_INT_ENABLE);
-	ier &= ~clear;
-	ier |= set;
-	sdhci_writel(host, ier, SDHCI_INT_ENABLE);
-	sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE);
-}
-
-static void sdhci_unmask_irqs(struct sdhci_host *host, u32 irqs)
-{
-	sdhci_clear_set_irqs(host, 0, irqs);
-}
-
-static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs)
-{
-	sdhci_clear_set_irqs(host, irqs, 0);
-}
-
 static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
 {
 	u32 present, irqs;
@@ -165,9 +144,12 @@ static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
 	irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
 
 	if (enable)
-		sdhci_unmask_irqs(host, irqs);
+		host->ier |= irqs;
 	else
-		sdhci_mask_irqs(host, irqs);
+		host->ier &= ~irqs;
+
+	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
 }
 
 static void sdhci_enable_card_detection(struct sdhci_host *host)
@@ -183,17 +165,12 @@ static void sdhci_disable_card_detection(struct sdhci_host *host)
 static void sdhci_reset(struct sdhci_host *host, u8 mask)
 {
 	unsigned long timeout;
-	u32 uninitialized_var(ier);
-
 	if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
 		if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) &
 			SDHCI_CARD_PRESENT))
 			return;
 	}
 
-	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
-		ier = sdhci_readl(host, SDHCI_INT_ENABLE);
-
 	if (host->ops->platform_reset_enter)
 		host->ops->platform_reset_enter(host, mask);
 
@@ -224,8 +201,10 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
 	if (host->ops->platform_reset_exit)
 		host->ops->platform_reset_exit(host, mask);
 
-	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
-		sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier);
+	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) {
+		sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+		sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+	}
 
 	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
 		if ((host->ops->enable_dma) && (mask & SDHCI_RESET_ALL))
@@ -242,11 +221,14 @@ static void sdhci_init(struct sdhci_host *host, int soft)
 	else
 		sdhci_reset(host, SDHCI_RESET_ALL);
 
-	sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK,
-		SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
-		SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
-		SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
-		SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE);
+	host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
+		    SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT |
+		    SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC |
+		    SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END |
+		    SDHCI_INT_RESPONSE;
+
+	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
 
 	if (soft) {
 		/* force clock reconfiguration */
@@ -721,9 +703,12 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host)
 	u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR;
 
 	if (host->flags & SDHCI_REQ_USE_DMA)
-		sdhci_clear_set_irqs(host, pio_irqs, dma_irqs);
+		host->ier = (host->ier & ~pio_irqs) | dma_irqs;
 	else
-		sdhci_clear_set_irqs(host, dma_irqs, pio_irqs);
+		host->ier = (host->ier & ~dma_irqs) | pio_irqs;
+
+	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
 }
 
 static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
@@ -1711,9 +1696,12 @@ static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
 {
 	if (!(host->flags & SDHCI_DEVICE_DEAD)) {
 		if (enable)
-			sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT);
+			host->ier |= SDHCI_INT_CARD_INT;
 		else
-			sdhci_mask_irqs(host, SDHCI_INT_CARD_INT);
+			host->ier &= ~SDHCI_INT_CARD_INT;
+
+		sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+		sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
 		mmiowb();
 	}
 }
@@ -1855,7 +1843,6 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
 	struct sdhci_host *host;
 	u16 ctrl;
-	u32 ier;
 	int tuning_loop_counter = MAX_TUNING_LOOP;
 	unsigned long timeout;
 	int err = 0;
@@ -1909,8 +1896,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 	 * to make sure we don't hit a controller bug, we _only_
 	 * enable Buffer Read Ready interrupt here.
 	 */
-	ier = sdhci_readl(host, SDHCI_INT_ENABLE);
-	sdhci_clear_set_irqs(host, ier, SDHCI_INT_DATA_AVAIL);
+	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
+	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
 
 	/*
 	 * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number
@@ -2042,7 +2029,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 	if (err && (host->flags & SDHCI_USING_RETUNING_TIMER))
 		err = 0;
 
-	sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier);
+	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
 	spin_unlock_irqrestore(&host->lock, flags);
 	sdhci_runtime_pm_put(host);
 
@@ -2455,10 +2443,12 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 			 * More testing are needed here to ensure it works
 			 * for other platforms though.
 			 */
-			sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT :
-							SDHCI_INT_CARD_REMOVE);
-			sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE :
-							  SDHCI_INT_CARD_INSERT);
+			host->ier &= ~(SDHCI_INT_CARD_INSERT |
+				       SDHCI_INT_CARD_REMOVE);
+			host->ier |= present ? SDHCI_INT_CARD_REMOVE :
+					       SDHCI_INT_CARD_INSERT;
+			sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+			sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
 
 			sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
 				     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
@@ -2587,7 +2577,9 @@ int sdhci_suspend_host(struct sdhci_host *host)
 	}
 
 	if (!device_may_wakeup(mmc_dev(host->mmc))) {
-		sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
+		host->ier = 0;
+		sdhci_writel(host, 0, SDHCI_INT_ENABLE);
+		sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
 		free_irq(host->irq, host);
 	} else {
 		sdhci_enable_irq_wakeups(host);
@@ -2686,7 +2678,9 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
 	}
 
 	spin_lock_irqsave(&host->lock, flags);
-	sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK & ~SDHCI_INT_CARD_INT);
+	host->ier &= SDHCI_INT_CARD_INT;
+	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
 	spin_unlock_irqrestore(&host->lock, flags);
 
 	synchronize_hardirq(host->irq);
@@ -3277,7 +3271,8 @@ int sdhci_add_host(struct sdhci_host *host)
 #ifdef SDHCI_USE_LEDS_CLASS
 reset:
 	sdhci_reset(host, SDHCI_RESET_ALL);
-	sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
+	sdhci_writel(host, 0, SDHCI_INT_ENABLE);
+	sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
 	free_irq(host->irq, host);
 #endif
 untasklet:
@@ -3319,7 +3314,8 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
 	if (!dead)
 		sdhci_reset(host, SDHCI_RESET_ALL);
 
-	sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
+	sdhci_writel(host, 0, SDHCI_INT_ENABLE);
+	sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
 	free_irq(host->irq, host);
 
 	del_timer_sync(&host->timer);
include/linux/mmc/sdhci.h +3 -0
index f1c8e14e8751..9361d8ef509d 100644
@@ -178,6 +178,9 @@ struct sdhci_host {
 
 	u32			thread_isr;
 
+	/* cached registers */
+	u32			ier;
+
 	wait_queue_head_t	buf_ready_int;	/* Waitqueue for Buffer Read Ready interrupt */
 	unsigned int		tuning_done;	/* Condition flag set when CMD19 succeeds */
 
Signature · 1 line
1.8.3.1
#11 lore raw

PATCH 8/38 mmc: sdhci: plug hole in disabling card detection interrupts

In reply to Russell King - ARM Linux

When we disable card detection interrupts, we should disable both the insert and remove interrupts irrespective of the current state - this avoids races between the hardware card detect changing state before we've read that updated state and altered the interrupt mask.

---
 drivers/mmc/host/sdhci.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)
drivers/mmc/host/sdhci.c +9 -8
index d568c8e4ee33..6b3ccd2d1f6c 100644
@@ -133,20 +133,21 @@ static void sdhci_dumpregs(struct sdhci_host *host)
 
 static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
 {
-	u32 present, irqs;
+	u32 present;
 
 	if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) ||
 	    (host->mmc->caps & MMC_CAP_NONREMOVABLE))
 		return;
 
-	present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
-			      SDHCI_CARD_PRESENT;
-	irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
+	if (enable) {
+		present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
+				      SDHCI_CARD_PRESENT;
 
-	if (enable)
-		host->ier |= irqs;
-	else
-		host->ier &= ~irqs;
+		host->ier |= present ? SDHCI_INT_CARD_REMOVE :
+				       SDHCI_INT_CARD_INSERT;
+	} else {
+		host->ier &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
+	}
 
 	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
 	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
Signature · 1 line
1.8.3.1
#12 lore raw

PATCH 9/38 mmc: sdhci: convert generic bus width setup to library function

In reply to Russell King - ARM Linux
---
 drivers/mmc/host/sdhci-acpi.c      |  2 ++
 drivers/mmc/host/sdhci-bcm-kona.c  |  1 +
 drivers/mmc/host/sdhci-bcm2835.c   |  1 +
 drivers/mmc/host/sdhci-cns3xxx.c   |  1 +
 drivers/mmc/host/sdhci-dove.c      |  1 +
 drivers/mmc/host/sdhci-esdhc-imx.c |  6 ++---
 drivers/mmc/host/sdhci-of-arasan.c |  1 +
 drivers/mmc/host/sdhci-of-esdhc.c  |  6 ++---
 drivers/mmc/host/sdhci-of-hlwd.c   |  1 +
 drivers/mmc/host/sdhci-pci.c       |  6 ++---
 drivers/mmc/host/sdhci-pltfm.c     |  1 +
 drivers/mmc/host/sdhci-pxav2.c     |  6 ++---
 drivers/mmc/host/sdhci-pxav3.c     |  1 +
 drivers/mmc/host/sdhci-s3c.c       |  8 +++----
 drivers/mmc/host/sdhci-sirf.c      |  1 +
 drivers/mmc/host/sdhci-spear.c     |  2 +-
 drivers/mmc/host/sdhci-tegra.c     |  5 ++---
 drivers/mmc/host/sdhci.c           | 45 +++++++++++++++++++-------------------
 drivers/mmc/host/sdhci.h           |  5 +++--
 19 files changed, 50 insertions(+), 50 deletions(-)
drivers/mmc/host/sdhci-acpi.c +2 -0
index ebb3f392b589..0e4ba0a4cd71 100644
@@ -103,10 +103,12 @@ static void sdhci_acpi_int_hw_reset(struct sdhci_host *host)
 
 static const struct sdhci_ops sdhci_acpi_ops_dflt = {
 	.enable_dma = sdhci_acpi_enable_dma,
+	.set_bus_width = sdhci_set_bus_width,
 };
 
 static const struct sdhci_ops sdhci_acpi_ops_int = {
 	.enable_dma = sdhci_acpi_enable_dma,
+	.set_bus_width = sdhci_set_bus_width,
 	.hw_reset   = sdhci_acpi_int_hw_reset,
 };
 
drivers/mmc/host/sdhci-bcm-kona.c +1 -0
index 6f166e63b817..06cdb8abb25e 100644
@@ -209,6 +209,7 @@ static struct sdhci_ops sdhci_bcm_kona_ops = {
 	.get_max_clock = sdhci_bcm_kona_get_max_clk,
 	.get_timeout_clock = sdhci_bcm_kona_get_timeout_clock,
 	.platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks,
+	.set_bus_width = sdhci_set_bus_width,
 	.card_event = sdhci_bcm_kona_card_event,
 };
 
drivers/mmc/host/sdhci-bcm2835.c +1 -0
index f6d8d67c545f..7ab69af979b4 100644
@@ -133,6 +133,7 @@ static const struct sdhci_ops bcm2835_sdhci_ops = {
 	.read_b = bcm2835_sdhci_readb,
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 	.get_min_clock = bcm2835_sdhci_get_min_clock,
+	.set_bus_width = sdhci_set_bus_width,
 };
 
 static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
drivers/mmc/host/sdhci-cns3xxx.c +1 -0
index f2cc26633cb2..5e0cc9c47887 100644
@@ -82,6 +82,7 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock)
 static const struct sdhci_ops sdhci_cns3xxx_ops = {
 	.get_max_clock	= sdhci_cns3xxx_get_max_clk,
 	.set_clock	= sdhci_cns3xxx_set_clock,
+	.set_bus_width	= sdhci_set_bus_width,
 };
 
 static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
drivers/mmc/host/sdhci-dove.c +1 -0
index 736d7a2eb7ec..8fc547a7048a 100644
@@ -86,6 +86,7 @@ static u32 sdhci_dove_readl(struct sdhci_host *host, int reg)
 static const struct sdhci_ops sdhci_dove_ops = {
 	.read_w	= sdhci_dove_readw,
 	.read_l	= sdhci_dove_readl,
+	.set_bus_width = sdhci_set_bus_width,
 };
 
 static const struct sdhci_pltfm_data sdhci_dove_pdata = {
drivers/mmc/host/sdhci-esdhc-imx.c +2 -4
index b0b4eea8d232..568239d84cbe 100644
@@ -668,7 +668,7 @@ static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
 	return -ENOSYS;
 }
 
-static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
+static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
 {
 	u32 ctrl;
 
@@ -686,8 +686,6 @@ static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
 
 	esdhc_clrset_le(host, ESDHC_CTRL_BUSWIDTH_MASK, ctrl,
 			SDHCI_HOST_CONTROL);
-
-	return 0;
 }
 
 static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
@@ -888,7 +886,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
 	.get_max_clock = esdhc_pltfm_get_max_clock,
 	.get_min_clock = esdhc_pltfm_get_min_clock,
 	.get_ro = esdhc_pltfm_get_ro,
-	.platform_bus_width = esdhc_pltfm_bus_width,
+	.set_bus_width = esdhc_pltfm_set_bus_width,
 	.set_uhs_signaling = esdhc_set_uhs_signaling,
 };
 
drivers/mmc/host/sdhci-of-arasan.c +1 -0
index f7c7cf62437d..9bb1dd263a45 100644
@@ -54,6 +54,7 @@ static unsigned int sdhci_arasan_get_timeout_clock(struct sdhci_host *host)
 static struct sdhci_ops sdhci_arasan_ops = {
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 	.get_timeout_clock = sdhci_arasan_get_timeout_clock,
+	.set_bus_width = sdhci_set_bus_width,
 };
 
 static struct sdhci_pltfm_data sdhci_arasan_pdata = {
drivers/mmc/host/sdhci-of-esdhc.c +2 -4
index 0b249970b119..86b8326e77c3 100644
@@ -269,7 +269,7 @@ static void esdhc_of_platform_init(struct sdhci_host *host)
 		host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
 }
 
-static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
+static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
 {
 	u32 ctrl;
 
@@ -289,8 +289,6 @@ static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
 
 	clrsetbits_be32(host->ioaddr + SDHCI_HOST_CONTROL,
 			ESDHC_CTRL_BUSWIDTH_MASK, ctrl);
-
-	return 0;
 }
 
 static const struct sdhci_ops sdhci_esdhc_ops = {
@@ -310,7 +308,7 @@ static const struct sdhci_ops sdhci_esdhc_ops = {
 	.platform_resume = esdhc_of_resume,
 #endif
 	.adma_workaround = esdhci_of_adma_workaround,
-	.platform_bus_width = esdhc_pltfm_bus_width,
+	.set_bus_width = esdhc_pltfm_set_bus_width,
 };
 
 static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
drivers/mmc/host/sdhci-of-hlwd.c +1 -0
index 57c514a81ca5..4d5d0015e392 100644
@@ -58,6 +58,7 @@ static const struct sdhci_ops sdhci_hlwd_ops = {
 	.write_l = sdhci_hlwd_writel,
 	.write_w = sdhci_hlwd_writew,
 	.write_b = sdhci_hlwd_writeb,
+	.set_bus_width = sdhci_set_bus_width,
 };
 
 static const struct sdhci_pltfm_data sdhci_hlwd_pdata = {
drivers/mmc/host/sdhci-pci.c +2 -4
index fdc612120362..8c4e9c2909b7 100644
@@ -1031,7 +1031,7 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host)
 	return 0;
 }
 
-static int sdhci_pci_bus_width(struct sdhci_host *host, int width)
+static void sdhci_pci_set_bus_width(struct sdhci_host *host, int width)
 {
 	u8 ctrl;
 
@@ -1052,8 +1052,6 @@ static int sdhci_pci_bus_width(struct sdhci_host *host, int width)
 	}
 
 	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-
-	return 0;
 }
 
 static void sdhci_pci_gpio_hw_reset(struct sdhci_host *host)
@@ -1081,7 +1079,7 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host)
 
 static const struct sdhci_ops sdhci_pci_ops = {
 	.enable_dma	= sdhci_pci_enable_dma,
-	.platform_bus_width	= sdhci_pci_bus_width,
+	.set_bus_width	= sdhci_pci_set_bus_width,
 	.hw_reset		= sdhci_pci_hw_reset,
 };
 
drivers/mmc/host/sdhci-pltfm.c +1 -0
index bef250e95418..40b0fe224f9d 100644
@@ -45,6 +45,7 @@ unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host)
 EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock);
 
 static const struct sdhci_ops sdhci_pltfm_ops = {
+	.set_bus_width = sdhci_set_bus_width,
 };
 
 #ifdef CONFIG_OF
drivers/mmc/host/sdhci-pxav2.c +2 -4
index d51e061ec576..d24c282e5eb8 100644
@@ -88,7 +88,7 @@ static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask)
 	}
 }
 
-static int pxav2_mmc_set_width(struct sdhci_host *host, int width)
+static void pxav2_mmc_set_bus_width(struct sdhci_host *host, int width)
 {
 	u8 ctrl;
 	u16 tmp;
@@ -107,14 +107,12 @@ static int pxav2_mmc_set_width(struct sdhci_host *host, int width)
 	}
 	writew(tmp, host->ioaddr + SD_CE_ATA_2);
 	writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
-
-	return 0;
 }
 
 static const struct sdhci_ops pxav2_sdhci_ops = {
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 	.platform_reset_exit = pxav2_set_private_registers,
-	.platform_bus_width = pxav2_mmc_set_width,
+	.set_bus_width = pxav2_mmc_set_bus_width,
 };
 
 #ifdef CONFIG_OF
drivers/mmc/host/sdhci-pxav3.c +1 -0
index 2fd73b38c303..b06db03b6d81 100644
@@ -227,6 +227,7 @@ static const struct sdhci_ops pxav3_sdhci_ops = {
 	.set_uhs_signaling = pxav3_set_uhs_signaling,
 	.platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
+	.set_bus_width = sdhci_set_bus_width,
 };
 
 static struct sdhci_pltfm_data sdhci_pxav3_pdata = {
drivers/mmc/host/sdhci-s3c.c +3 -5
index d61eb5a70833..181d8c962f26 100644
@@ -329,14 +329,14 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
 }
 
 /**
- * sdhci_s3c_platform_bus_width - support 8bit buswidth
+ * sdhci_s3c_set_bus_width - support 8bit buswidth
  * @host: The SDHCI host being queried
  * @width: MMC_BUS_WIDTH_ macro for the bus width being requested
  *
  * We have 8-bit width support but is not a v3 controller.
  * So we add platform_bus_width() and support 8bit width.
  */
-static int sdhci_s3c_platform_bus_width(struct sdhci_host *host, int width)
+static void sdhci_s3c_set_bus_width(struct sdhci_host *host, int width)
 {
 	u8 ctrl;
 
@@ -358,15 +358,13 @@ static int sdhci_s3c_platform_bus_width(struct sdhci_host *host, int width)
 	}
 
 	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-
-	return 0;
 }
 
 static struct sdhci_ops sdhci_s3c_ops = {
 	.get_max_clock		= sdhci_s3c_get_max_clk,
 	.set_clock		= sdhci_s3c_set_clock,
 	.get_min_clock		= sdhci_s3c_get_min_clock,
-	.platform_bus_width	= sdhci_s3c_platform_bus_width,
+	.set_bus_width		= sdhci_s3c_set_bus_width,
 };
 
 static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
drivers/mmc/host/sdhci-sirf.c +1 -0
index 696122c1b468..16fcd48f9556 100644
@@ -29,6 +29,7 @@ static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host)
 
 static struct sdhci_ops sdhci_sirf_ops = {
 	.get_max_clock	= sdhci_sirf_get_max_clk,
+	.set_bus_width = sdhci_set_bus_width,
 };
 
 static struct sdhci_pltfm_data sdhci_sirf_pdata = {
drivers/mmc/host/sdhci-spear.c +1 -1
index 0316dec3f006..dc8967b657ed 100644
@@ -38,7 +38,7 @@ struct spear_sdhci {
 
 /* sdhci ops */
 static const struct sdhci_ops sdhci_pltfm_ops = {
-	/* Nothing to do for now. */
+	.set_bus_width = sdhci_set_bus_width,
 };
 
 #ifdef CONFIG_OF
drivers/mmc/host/sdhci-tegra.c +2 -3
index a835898a68dd..feed799b827a 100644
@@ -127,7 +127,7 @@ static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask)
 	}
 }
 
-static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width)
+static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width)
 {
 	u32 ctrl;
 
@@ -144,7 +144,6 @@ static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width)
 			ctrl &= ~SDHCI_CTRL_4BITBUS;
 	}
 	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-	return 0;
 }
 
 static const struct sdhci_ops tegra_sdhci_ops = {
@@ -152,7 +151,7 @@ static const struct sdhci_ops tegra_sdhci_ops = {
 	.read_l     = tegra_sdhci_readl,
 	.read_w     = tegra_sdhci_readw,
 	.write_l    = tegra_sdhci_writel,
-	.platform_bus_width = tegra_sdhci_buswidth,
+	.set_bus_width = tegra_sdhci_set_bus_width,
 	.platform_reset_exit = tegra_sdhci_reset_exit,
 };
 
drivers/mmc/host/sdhci.c +22 -23

57 lines not on this page · raw message

drivers/mmc/host/sdhci.h +3 -2
index fc6f81d2f377..0301f928eb11 100644
@@ -281,8 +281,7 @@ struct sdhci_ops {
 	unsigned int	(*get_max_clock)(struct sdhci_host *host);
 	unsigned int	(*get_min_clock)(struct sdhci_host *host);
 	unsigned int	(*get_timeout_clock)(struct sdhci_host *host);
-	int		(*platform_bus_width)(struct sdhci_host *host,
-					       int width);
+	void		(*set_bus_width)(struct sdhci_host *host, int width);
 	void (*platform_send_init_74_clocks)(struct sdhci_host *host,
 					     u8 power_mode);
 	unsigned int    (*get_ro)(struct sdhci_host *host);
@@ -402,6 +401,8 @@ static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host)
 	return !!(host->flags & SDHCI_SDIO_IRQ_ENABLED);
 }
 
+void sdhci_set_bus_width(struct sdhci_host *host, int width);
+
 #ifdef CONFIG_PM
 extern int sdhci_suspend_host(struct sdhci_host *host);
 extern int sdhci_resume_host(struct sdhci_host *host);
Signature · 1 line
1.8.3.1
#13 lore raw

PATCH 10/38 mmc: sdhci: convert reset into a library function

In reply to Russell King - ARM Linux

Rather than having platform_reset_enter/platform_reset_exit methods, turn the core of the reset handling into a library function which platforms can call at the appropriate moment in their (new) reset method.

---
 drivers/mmc/host/sdhci-acpi.c      |  2 ++
 drivers/mmc/host/sdhci-bcm-kona.c  |  1 +
 drivers/mmc/host/sdhci-bcm2835.c   |  1 +
 drivers/mmc/host/sdhci-cns3xxx.c   |  1 +
 drivers/mmc/host/sdhci-dove.c      |  1 +
 drivers/mmc/host/sdhci-esdhc-imx.c |  1 +
 drivers/mmc/host/sdhci-of-arasan.c |  1 +
 drivers/mmc/host/sdhci-of-esdhc.c  |  1 +
 drivers/mmc/host/sdhci-of-hlwd.c   |  1 +
 drivers/mmc/host/sdhci-pci.c       |  1 +
 drivers/mmc/host/sdhci-pltfm.c     |  1 +
 drivers/mmc/host/sdhci-pxav2.c     |  6 +++--
 drivers/mmc/host/sdhci-pxav3.c     |  6 +++--
 drivers/mmc/host/sdhci-s3c.c       |  1 +
 drivers/mmc/host/sdhci-sirf.c      |  1 +
 drivers/mmc/host/sdhci-spear.c     |  1 +
 drivers/mmc/host/sdhci-tegra.c     |  6 +++--
 drivers/mmc/host/sdhci.c           | 47 +++++++++++++++++++-------------------
 drivers/mmc/host/sdhci.h           |  4 ++--
 19 files changed, 53 insertions(+), 31 deletions(-)
drivers/mmc/host/sdhci-acpi.c +2 -0
index 0e4ba0a4cd71..aca84a682551 100644
@@ -104,11 +104,13 @@ static void sdhci_acpi_int_hw_reset(struct sdhci_host *host)
 static const struct sdhci_ops sdhci_acpi_ops_dflt = {
 	.enable_dma = sdhci_acpi_enable_dma,
 	.set_bus_width = sdhci_set_bus_width,
+	.reset = sdhci_reset,
 };
 
 static const struct sdhci_ops sdhci_acpi_ops_int = {
 	.enable_dma = sdhci_acpi_enable_dma,
 	.set_bus_width = sdhci_set_bus_width,
+	.reset = sdhci_reset,
 	.hw_reset   = sdhci_acpi_int_hw_reset,
 };
 
drivers/mmc/host/sdhci-bcm-kona.c +1 -0
index 06cdb8abb25e..7b97bfab910d 100644
@@ -210,6 +210,7 @@ static struct sdhci_ops sdhci_bcm_kona_ops = {
 	.get_timeout_clock = sdhci_bcm_kona_get_timeout_clock,
 	.platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks,
 	.set_bus_width = sdhci_set_bus_width,
+	.reset = sdhci_reset,
 	.card_event = sdhci_bcm_kona_card_event,
 };
 
drivers/mmc/host/sdhci-bcm2835.c +1 -0
index 7ab69af979b4..289b1c80d5fc 100644
@@ -134,6 +134,7 @@ static const struct sdhci_ops bcm2835_sdhci_ops = {
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 	.get_min_clock = bcm2835_sdhci_get_min_clock,
 	.set_bus_width = sdhci_set_bus_width,
+	.reset = sdhci_reset,
 };
 
 static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
drivers/mmc/host/sdhci-cns3xxx.c +1 -0
index 5e0cc9c47887..87af66bb1ea8 100644
@@ -83,6 +83,7 @@ static const struct sdhci_ops sdhci_cns3xxx_ops = {
 	.get_max_clock	= sdhci_cns3xxx_get_max_clk,
 	.set_clock	= sdhci_cns3xxx_set_clock,
 	.set_bus_width	= sdhci_set_bus_width,
+	.reset          = sdhci_reset,
 };
 
 static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
drivers/mmc/host/sdhci-dove.c +1 -0
index 8fc547a7048a..1408cc11d881 100644
@@ -87,6 +87,7 @@ static const struct sdhci_ops sdhci_dove_ops = {
 	.read_w	= sdhci_dove_readw,
 	.read_l	= sdhci_dove_readl,
 	.set_bus_width = sdhci_set_bus_width,
+	.reset = sdhci_reset,
 };
 
 static const struct sdhci_pltfm_data sdhci_dove_pdata = {
drivers/mmc/host/sdhci-esdhc-imx.c +1 -0
index 568239d84cbe..b1d74fa33c5f 100644
@@ -888,6 +888,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
 	.get_ro = esdhc_pltfm_get_ro,
 	.set_bus_width = esdhc_pltfm_set_bus_width,
 	.set_uhs_signaling = esdhc_set_uhs_signaling,
+	.reset = sdhci_reset,
 };
 
 static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
drivers/mmc/host/sdhci-of-arasan.c +1 -0
index 9bb1dd263a45..faef21740584 100644
@@ -55,6 +55,7 @@ static struct sdhci_ops sdhci_arasan_ops = {
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 	.get_timeout_clock = sdhci_arasan_get_timeout_clock,
 	.set_bus_width = sdhci_set_bus_width,
+	.reset = sdhci_reset,
 };
 
 static struct sdhci_pltfm_data sdhci_arasan_pdata = {
drivers/mmc/host/sdhci-of-esdhc.c +1 -0
index 86b8326e77c3..4530f9957f20 100644
@@ -309,6 +309,7 @@ static const struct sdhci_ops sdhci_esdhc_ops = {
 #endif
 	.adma_workaround = esdhci_of_adma_workaround,
 	.set_bus_width = esdhc_pltfm_set_bus_width,
+	.reset = sdhci_reset,
 };
 
 static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
drivers/mmc/host/sdhci-of-hlwd.c +1 -0
index 4d5d0015e392..fb01958cb18e 100644
@@ -59,6 +59,7 @@ static const struct sdhci_ops sdhci_hlwd_ops = {
 	.write_w = sdhci_hlwd_writew,
 	.write_b = sdhci_hlwd_writeb,
 	.set_bus_width = sdhci_set_bus_width,
+	.reset = sdhci_reset,
 };
 
 static const struct sdhci_pltfm_data sdhci_hlwd_pdata = {
drivers/mmc/host/sdhci-pci.c +1 -0
index 8c4e9c2909b7..87f9dd91f68c 100644
@@ -1080,6 +1080,7 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host)
 static const struct sdhci_ops sdhci_pci_ops = {
 	.enable_dma	= sdhci_pci_enable_dma,
 	.set_bus_width	= sdhci_pci_set_bus_width,
+	.reset		= sdhci_reset,
 	.hw_reset		= sdhci_pci_hw_reset,
 };
 
drivers/mmc/host/sdhci-pltfm.c +1 -0
index 40b0fe224f9d..bfbf467b61c7 100644
@@ -46,6 +46,7 @@ EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock);
 
 static const struct sdhci_ops sdhci_pltfm_ops = {
 	.set_bus_width = sdhci_set_bus_width,
+	.reset = sdhci_reset,
 };
 
 #ifdef CONFIG_OF
drivers/mmc/host/sdhci-pxav2.c +4 -2
index d24c282e5eb8..2eee0c8b88eb 100644
@@ -51,11 +51,13 @@
 #define MMC_CARD		0x1000
 #define MMC_WIDTH		0x0100
 
-static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask)
+static void pxav2_reset(struct sdhci_host *host, u8 mask)
 {
 	struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
 	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
 
+	sdhci_reset(host, mask);
+
 	if (mask == SDHCI_RESET_ALL) {
 		u16 tmp = 0;
 
@@ -111,8 +113,8 @@ static void pxav2_mmc_set_bus_width(struct sdhci_host *host, int width)
 
 static const struct sdhci_ops pxav2_sdhci_ops = {
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
-	.platform_reset_exit = pxav2_set_private_registers,
 	.set_bus_width = pxav2_mmc_set_bus_width,
+	.reset         = pxav2_reset,
 };
 
 #ifdef CONFIG_OF
drivers/mmc/host/sdhci-pxav3.c +4 -2
index b06db03b6d81..86564233ae93 100644
@@ -112,11 +112,13 @@ static int mv_conf_mbus_windows(struct platform_device *pdev,
 	return 0;
 }
 
-static void pxav3_set_private_registers(struct sdhci_host *host, u8 mask)
+static void pxav3_reset(struct sdhci_host *host, u8 mask)
 {
 	struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
 	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
 
+	sdhci_reset(host, mask);
+
 	if (mask == SDHCI_RESET_ALL) {
 		/*
 		 * tune timing of read data/command when crc error happen
@@ -223,11 +225,11 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 }
 
 static const struct sdhci_ops pxav3_sdhci_ops = {
-	.platform_reset_exit = pxav3_set_private_registers,
 	.set_uhs_signaling = pxav3_set_uhs_signaling,
 	.platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 	.set_bus_width = sdhci_set_bus_width,
+	.reset = pxav3_reset,
 };
 
 static struct sdhci_pltfm_data sdhci_pxav3_pdata = {
drivers/mmc/host/sdhci-s3c.c +1 -0
index 181d8c962f26..8e26172a97de 100644
@@ -365,6 +365,7 @@ static struct sdhci_ops sdhci_s3c_ops = {
 	.set_clock		= sdhci_s3c_set_clock,
 	.get_min_clock		= sdhci_s3c_get_min_clock,
 	.set_bus_width		= sdhci_s3c_set_bus_width,
+	.reset			= sdhci_reset,
 };
 
 static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
drivers/mmc/host/sdhci-sirf.c +1 -0
index 16fcd48f9556..5d79e10e1ba2 100644
@@ -30,6 +30,7 @@ static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host)
 static struct sdhci_ops sdhci_sirf_ops = {
 	.get_max_clock	= sdhci_sirf_get_max_clk,
 	.set_bus_width = sdhci_set_bus_width,
+	.reset = sdhci_reset,
 };
 
 static struct sdhci_pltfm_data sdhci_sirf_pdata = {
drivers/mmc/host/sdhci-spear.c +1 -0
index dc8967b657ed..c2a2bedc8813 100644
@@ -39,6 +39,7 @@ struct spear_sdhci {
 /* sdhci ops */
 static const struct sdhci_ops sdhci_pltfm_ops = {
 	.set_bus_width = sdhci_set_bus_width,
+	.reset = sdhci_reset,
 };
 
 #ifdef CONFIG_OF
drivers/mmc/host/sdhci-tegra.c +4 -2
index feed799b827a..7754c0319fda 100644
@@ -108,12 +108,14 @@ static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host)
 	return mmc_gpio_get_ro(host->mmc);
 }
 
-static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask)
+static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_tegra *tegra_host = pltfm_host->priv;
 	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
 
+	sdhci_reset(host, mask);
+
 	if (!(mask & SDHCI_RESET_ALL))
 		return;
 
@@ -152,7 +154,7 @@ static const struct sdhci_ops tegra_sdhci_ops = {
 	.read_w     = tegra_sdhci_readw,
 	.write_l    = tegra_sdhci_writel,
 	.set_bus_width = tegra_sdhci_set_bus_width,
-	.platform_reset_exit = tegra_sdhci_reset_exit,
+	.reset      = tegra_sdhci_reset,
 };
 
 static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {
drivers/mmc/host/sdhci.c +24 -23

111 lines not on this page · raw message

drivers/mmc/host/sdhci.h +2 -2
index 0301f928eb11..7d84cb3b0e00 100644
@@ -285,8 +285,7 @@ struct sdhci_ops {
 	void (*platform_send_init_74_clocks)(struct sdhci_host *host,
 					     u8 power_mode);
 	unsigned int    (*get_ro)(struct sdhci_host *host);
-	void	(*platform_reset_enter)(struct sdhci_host *host, u8 mask);
-	void	(*platform_reset_exit)(struct sdhci_host *host, u8 mask);
+	void		(*reset)(struct sdhci_host *host, u8 mask);
 	int	(*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
 	int	(*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
 	void	(*hw_reset)(struct sdhci_host *host);
@@ -402,6 +401,7 @@ static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host)
 }
 
 void sdhci_set_bus_width(struct sdhci_host *host, int width);
+void sdhci_reset(struct sdhci_host *host, u8 mask);
 
 #ifdef CONFIG_PM
 extern int sdhci_suspend_host(struct sdhci_host *host);
Signature · 1 line
1.8.3.1
#14 lore raw

PATCH 11/38 mmc: sdhci: move FSL ESDHC reset handling quirk into esdhc code

In reply to Russell King - ARM Linux

The Freescale esdhc driver is the only driver which needs the interrupt registers restored after a reset. Move this quirk to be part of the ESDHC driver implementation.

---
 drivers/mmc/host/sdhci-esdhc-imx.c | 10 +++++++++-
 drivers/mmc/host/sdhci-esdhc.h     |  3 +--
 drivers/mmc/host/sdhci.c           |  5 -----
 include/linux/mmc/sdhci.h          |  2 --
 4 files changed, 10 insertions(+), 10 deletions(-)
drivers/mmc/host/sdhci-esdhc-imx.c +9 -1
index b1d74fa33c5f..812c5772d900 100644
@@ -876,6 +876,14 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 	return esdhc_change_pinstate(host, uhs);
 }
 
+static void esdhc_reset(struct sdhci_host *host, u8 mask)
+{
+	sdhci_reset(host, mask);
+
+	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+}
+
 static struct sdhci_ops sdhci_esdhc_ops = {
 	.read_l = esdhc_readl_le,
 	.read_w = esdhc_readw_le,
@@ -888,7 +896,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
 	.get_ro = esdhc_pltfm_get_ro,
 	.set_bus_width = esdhc_pltfm_set_bus_width,
 	.set_uhs_signaling = esdhc_set_uhs_signaling,
-	.reset = sdhci_reset,
+	.reset = esdhc_reset,
 };
 
 static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
drivers/mmc/host/sdhci-esdhc.h +1 -2
index a7d9f95a7b03..de69bddc3afc 100644
@@ -22,8 +22,7 @@
 				SDHCI_QUIRK_NO_BUSY_IRQ | \
 				SDHCI_QUIRK_NONSTANDARD_CLOCK | \
 				SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \
-				SDHCI_QUIRK_PIO_NEEDS_DELAY | \
-				SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
+				SDHCI_QUIRK_PIO_NEEDS_DELAY)
 
 #define ESDHC_SYSTEM_CONTROL	0x2c
 #define ESDHC_CLOCK_MASK	0x0000fff0
drivers/mmc/host/sdhci.c +0 -5
index b5d1c28048dc..7e2f24ac579b 100644
@@ -203,11 +203,6 @@ static void sdhci_do_reset(struct sdhci_host *host, u8 mask)
 
 	host->ops->reset(host, mask);
 
-	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) {
-		sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
-		sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
-	}
-
 	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
 		if ((host->ops->enable_dma) && (mask & SDHCI_RESET_ALL))
 			host->ops->enable_dma(host);
include/linux/mmc/sdhci.h +0 -2
index 9361d8ef509d..02919ef99419 100644
@@ -61,8 +61,6 @@ struct sdhci_host {
 #define SDHCI_QUIRK_NONSTANDARD_CLOCK			(1<<17)
 /* Controller does not like fast PIO transfers */
 #define SDHCI_QUIRK_PIO_NEEDS_DELAY			(1<<18)
-/* Controller losing signal/interrupt enable states after reset */
-#define SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET		(1<<19)
 /* Controller has to be forced to use block size of 2048 bytes */
 #define SDHCI_QUIRK_FORCE_BLK_SZ_2048			(1<<20)
 /* Controller cannot do multi-block transfers */
Signature · 1 line
1.8.3.1
#15 lore raw

PATCH 12/38 mmc: sdhci: avoid sync'ing the SG if there's no misalignment

In reply to Russell King - ARM Linux

On read, we don't need to sync the whole scatterlist and then check whether any segments need copying - if we check first, we avoid potentially expensive cache handling.

---
 drivers/mmc/host/sdhci.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/mmc/host/sdhci.c +10 -1
index 7e2f24ac579b..078bf43b4aae 100644
@@ -602,6 +602,7 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
 	u8 *align;
 	char *buffer;
 	unsigned long flags;
+	bool has_unaligned;
 
 	if (data->flags & MMC_DATA_READ)
 		direction = DMA_FROM_DEVICE;
@@ -614,7 +615,15 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
 	dma_unmap_single(mmc_dev(host->mmc), host->align_addr,
 		128 * 4, direction);
 
-	if (data->flags & MMC_DATA_READ) {
+	/* Do a quick scan of the SG list for any unaligned mappings */
+	has_unaligned = false;
+	for_each_sg(data->sg, sg, host->sg_count, i)
+		if (sg_dma_address(sg) & 3) {
+			has_unaligned = true;
+			break;
+		}
+
+	if (has_unaligned && data->flags & MMC_DATA_READ) {
 		dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg,
 			data->sg_len, direction);
 
Signature · 1 line
1.8.3.1
#16 lore raw

PATCH 13/38 mmc: sdhci: convert ADMA descriptors to a coherent allocation

In reply to Russell King - ARM Linux

Rather than using the streaming API, use the coherent allocator to provide this memory, thereby eliminating cache flushing of it each time we map and unmap it. This results in a 7.5% increase in transfer speed with a UHS-1 card operating in 3.3v mode at a clock of 49.5MHz.

---
 drivers/mmc/host/sdhci.c | 43 ++++++++++++++++++++++---------------------
 1 file changed, 22 insertions(+), 21 deletions(-)
drivers/mmc/host/sdhci.c +22 -21
index 078bf43b4aae..9efa7d878731 100644
@@ -44,6 +44,8 @@
 
 #define MAX_TUNING_LOOP 40
 
+#define ADMA_SIZE	((128 * 2 + 1) * 4)
+
 static unsigned int debug_quirks = 0;
 static unsigned int debug_quirks2;
 
@@ -481,11 +483,6 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
 	else
 		direction = DMA_TO_DEVICE;
 
-	/*
-	 * The ADMA descriptor table is mapped further down as we
-	 * need to fill it with data first.
-	 */
-
 	host->align_addr = dma_map_single(mmc_dev(host->mmc),
 		host->align_buffer, 128 * 4, direction);
 	if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr))
@@ -546,7 +543,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
 		 * If this triggers then we have a calculation bug
 		 * somewhere. :/
 		 */
-		WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4);
+		WARN_ON((desc - host->adma_desc) > ADMA_SIZE);
 	}
 
 	if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) {
@@ -574,17 +571,8 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
 			host->align_addr, 128 * 4, direction);
 	}
 
-	host->adma_addr = dma_map_single(mmc_dev(host->mmc),
-		host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE);
-	if (dma_mapping_error(mmc_dev(host->mmc), host->adma_addr))
-		goto unmap_entries;
-	BUG_ON(host->adma_addr & 0x3);
-
 	return 0;
 
-unmap_entries:
-	dma_unmap_sg(mmc_dev(host->mmc), data->sg,
-		data->sg_len, direction);
 unmap_align:
 	dma_unmap_single(mmc_dev(host->mmc), host->align_addr,
 		128 * 4, direction);
@@ -609,9 +597,6 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
 	else
 		direction = DMA_TO_DEVICE;
 
-	dma_unmap_single(mmc_dev(host->mmc), host->adma_addr,
-		(128 * 2 + 1) * 4, DMA_TO_DEVICE);
-
 	dma_unmap_single(mmc_dev(host->mmc), host->align_addr,
 		128 * 4, direction);
 
@@ -2851,15 +2836,29 @@ int sdhci_add_host(struct sdhci_host *host)
 		 * (128) and potentially one alignment transfer for
 		 * each of those entries.
 		 */
-		host->adma_desc = kmalloc((128 * 2 + 1) * 4, GFP_KERNEL);
+		host->adma_desc = dma_alloc_coherent(mmc_dev(host->mmc),
+						     ADMA_SIZE, &host->adma_addr,
+						     GFP_KERNEL);
 		host->align_buffer = kmalloc(128 * 4, GFP_KERNEL);
 		if (!host->adma_desc || !host->align_buffer) {
-			kfree(host->adma_desc);
+			dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE,
+					  host->adma_desc, host->adma_addr);
 			kfree(host->align_buffer);
 			pr_warning("%s: Unable to allocate ADMA "
 				"buffers. Falling back to standard DMA.\n",
 				mmc_hostname(mmc));
 			host->flags &= ~SDHCI_USE_ADMA;
+			host->adma_desc = NULL;
+			host->align_buffer = NULL;
+		} else if (host->adma_addr & 3) {
+			pr_warning("%s: unable to allocate aligned ADMA descriptor\n",
+				   mmc_hostname(mmc));
+			host->flags &= ~SDHCI_USE_ADMA;
+			dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE,
+					  host->adma_desc, host->adma_addr);
+			kfree(host->align_buffer);
+			host->adma_desc = NULL;
+			host->align_buffer = NULL;
 		}
 	}
 
@@ -3337,7 +3336,9 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
 		regulator_put(host->vqmmc);
 	}
 
-	kfree(host->adma_desc);
+	if (host->adma_desc)
+		dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE,
+				  host->adma_desc, host->adma_addr);
 	kfree(host->align_buffer);
 
 	host->adma_desc = NULL;
Signature · 1 line
1.8.3.1
#17 lore raw

PATCH 14/38 mmc: sdhci: clean up sdhci_update_clock()/sdhci_set_clock()

In reply to Russell King - ARM Linux

Only one caller to sdhci_set_clock() needs to check whether the requested clock frequency was the same as the currently set frequency, yet we work around this in several other sites via sdhci_update_clock(). Rather than doing this, move those checks out into sdhci_do_set_ios(), which then allows sdhci_update_clock() to be eliminated.

---
 drivers/mmc/host/sdhci-cns3xxx.c |  3 ---
 drivers/mmc/host/sdhci.c         | 21 +++++----------------
 2 files changed, 5 insertions(+), 19 deletions(-)
drivers/mmc/host/sdhci-cns3xxx.c +0 -3
index 87af66bb1ea8..fa11f63b78a0 100644
@@ -30,9 +30,6 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock)
 	u16 clk;
 	unsigned long timeout;
 
-	if (clock == host->clock)
-		return;
-
 	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
 
 	if (clock == 0)
drivers/mmc/host/sdhci.c +5 -16
index 9efa7d878731..518ab1a5e608 100644
@@ -1119,9 +1119,6 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 	u16 clk = 0;
 	unsigned long timeout;
 
-	if (clock && clock == host->clock)
-		return;
-
 	host->mmc->actual_clock = 0;
 
 	if (host->ops->set_clock) {
@@ -1228,15 +1225,6 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 	host->clock = clock;
 }
 
-static inline void sdhci_update_clock(struct sdhci_host *host)
-{
-	unsigned int clock;
-
-	clock = host->clock;
-	host->clock = 0;
-	sdhci_set_clock(host, clock);
-}
-
 static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
 {
 	u8 pwr = 0;
@@ -1453,7 +1441,8 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 		!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN))
 		sdhci_enable_preset_value(host, false);
 
-	sdhci_set_clock(host, ios->clock);
+	if (!ios->clock || ios->clock != host->clock)
+		sdhci_set_clock(host, ios->clock);
 
 	if (ios->power_mode == MMC_POWER_OFF)
 		vdd_bit = sdhci_set_power(host, -1);
@@ -1521,7 +1510,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 			sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 
 			/* Re-enable SD Clock */
-			sdhci_update_clock(host);
+			sdhci_set_clock(host, host->clock);
 		}
 
 
@@ -1565,7 +1554,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 		}
 
 		/* Re-enable SD Clock */
-		sdhci_update_clock(host);
+		sdhci_set_clock(host, host->clock);
 	} else
 		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 
@@ -2136,7 +2125,7 @@ static void sdhci_tasklet_finish(unsigned long param)
 		/* Some controllers need this kick or reset won't work here */
 		if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
 			/* This is to force an update */
-			sdhci_update_clock(host);
+			sdhci_set_clock(host, host->clock);
 
 		/* Spec says we should do both at the same time, but Ricoh
 		   controllers do not like that. */
Signature · 1 line
1.8.3.1
#18 lore raw

PATCH 15/38 mmc: sdhci: move setting host->clock into sdhci_do_set_ios()

In reply to Russell King - ARM Linux

We don't need implementations to do this, since the only time it's necessary is when we change the clock, and the only place that happens is in sdhci_do_set_ios(). So, move it there, and remove it from the iMX platform backend.

---
 drivers/mmc/host/sdhci-cns3xxx.c   | 4 +---
 drivers/mmc/host/sdhci-esdhc-imx.c | 4 +---
 drivers/mmc/host/sdhci-of-esdhc.c  | 4 +---
 drivers/mmc/host/sdhci-s3c.c       | 3 ---
 drivers/mmc/host/sdhci.c           | 9 ++++-----
 5 files changed, 7 insertions(+), 17 deletions(-)
drivers/mmc/host/sdhci-cns3xxx.c +1 -3
index fa11f63b78a0..f11fb908ad78 100644
@@ -33,7 +33,7 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock)
 	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
 
 	if (clock == 0)
-		goto out;
+		return;
 
 	while (host->max_clk / div > clock) {
 		/*
@@ -72,8 +72,6 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock)
 
 	clk |= SDHCI_CLOCK_CARD_EN;
 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-out:
-	host->clock = clock;
 }
 
 static const struct sdhci_ops sdhci_cns3xxx_ops = {
drivers/mmc/host/sdhci-esdhc-imx.c +1 -3
index 812c5772d900..1e68a77c9987 100644
@@ -605,7 +605,7 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
 			writel(val & ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
 					host->ioaddr + ESDHC_VENDOR_SPEC);
 		}
-		goto out;
+		return;
 	}
 
 	if (esdhc_is_usdhc(imx_data) && !imx_data->is_ddr)
@@ -645,8 +645,6 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
 	}
 
 	mdelay(1);
-out:
-	host->clock = clock;
 }
 
 static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
drivers/mmc/host/sdhci-of-esdhc.c +1 -3
index 4530f9957f20..d814b3ecb1f7 100644
@@ -205,7 +205,7 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
 	u32 temp;
 
 	if (clock == 0)
-		goto out;
+		return;
 
 	/* Workaround to reduce the clock frequency for p1010 esdhc */
 	if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) {
@@ -238,8 +238,6 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
 		| (pre_div << ESDHC_PREDIV_SHIFT));
 	sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
 	mdelay(1);
-out:
-	host->clock = clock;
 }
 
 #ifdef CONFIG_PM
drivers/mmc/host/sdhci-s3c.c +0 -3
index 8e26172a97de..6b424a6f79c4 100644
@@ -298,7 +298,6 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
 	/* If the clock is going off, set to 0 at clock control register */
 	if (clock == 0) {
 		sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
-		host->clock = clock;
 		return;
 	}
 
@@ -306,8 +305,6 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
 
 	clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);
 
-	host->clock = clock;
-
 	clk = SDHCI_CLOCK_INT_EN;
 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
 
drivers/mmc/host/sdhci.c +4 -5
index 518ab1a5e608..a8ee5f786660 100644
@@ -1130,7 +1130,7 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
 
 	if (clock == 0)
-		goto out;
+		return;
 
 	if (host->version >= SDHCI_SPEC_300) {
 		if (sdhci_readw(host, SDHCI_HOST_CONTROL2) &
@@ -1220,9 +1220,6 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 
 	clk |= SDHCI_CLOCK_CARD_EN;
 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-
-out:
-	host->clock = clock;
 }
 
 static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
@@ -1441,8 +1438,10 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 		!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN))
 		sdhci_enable_preset_value(host, false);
 
-	if (!ios->clock || ios->clock != host->clock)
+	if (!ios->clock || ios->clock != host->clock) {
 		sdhci_set_clock(host, ios->clock);
+		host->clock = ios->clock;
+	}
 
 	if (ios->power_mode == MMC_POWER_OFF)
 		vdd_bit = sdhci_set_power(host, -1);
Signature · 1 line
1.8.3.1
#19 lore raw

PATCH 16/38 mmc: sdhci: move setting mmc->actual_clock into set_clock handlers

In reply to Russell King - ARM Linux

Move the setting of mmc->actual_clock to zero into the set_clock handlers themselves. This will allow us to clean up the calling logic for the set_clock() method, and turn sdhci_set_clock() into a library function.

---
 drivers/mmc/host/sdhci-cns3xxx.c   | 2 ++
 drivers/mmc/host/sdhci-esdhc-imx.c | 2 ++
 drivers/mmc/host/sdhci-of-esdhc.c  | 3 ++-
 drivers/mmc/host/sdhci-s3c.c       | 4 ++++
 drivers/mmc/host/sdhci.c           | 4 ++--
 5 files changed, 12 insertions(+), 3 deletions(-)
drivers/mmc/host/sdhci-cns3xxx.c +2 -0
index f11fb908ad78..416f4a4c2e35 100644
@@ -30,6 +30,8 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock)
 	u16 clk;
 	unsigned long timeout;
 
+	host->mmc->actual_clock = 0;
+
 	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
 
 	if (clock == 0)
drivers/mmc/host/sdhci-esdhc-imx.c +2 -0
index 1e68a77c9987..ce8939ff97a4 100644
@@ -600,6 +600,8 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
 	u32 temp, val;
 
 	if (clock == 0) {
+		host->mmc->actual_clock = 0;
+
 		if (esdhc_is_usdhc(imx_data)) {
 			val = readl(host->ioaddr + ESDHC_VENDOR_SPEC);
 			writel(val & ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
drivers/mmc/host/sdhci-of-esdhc.c +2 -1
index d814b3ecb1f7..c4f8cd3f83c8 100644
@@ -199,11 +199,12 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
 
 static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
 {
-
 	int pre_div = 2;
 	int div = 1;
 	u32 temp;
 
+	host->mmc->actual_clock = 0;
+
 	if (clock == 0)
 		return;
 
drivers/mmc/host/sdhci-s3c.c +4 -0
index 6b424a6f79c4..464059c91a24 100644
@@ -161,6 +161,8 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
 	int src;
 	u32 ctrl;
 
+	host->mmc->actual_clock = 0;
+
 	/* don't bother if the clock is going off. */
 	if (clock == 0)
 		return;
@@ -295,6 +297,8 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
 	unsigned long timeout;
 	u16 clk = 0;
 
+	host->mmc->actual_clock = 0;
+
 	/* If the clock is going off, set to 0 at clock control register */
 	if (clock == 0) {
 		sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
drivers/mmc/host/sdhci.c +2 -2
index a8ee5f786660..67b7a5752049 100644
@@ -1119,14 +1119,14 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 	u16 clk = 0;
 	unsigned long timeout;
 
-	host->mmc->actual_clock = 0;
-
 	if (host->ops->set_clock) {
 		host->ops->set_clock(host, clock);
 		if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK)
 			return;
 	}
 
+	host->mmc->actual_clock = 0;
+
 	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
 
 	if (clock == 0)
Signature · 1 line
1.8.3.1
#20 lore raw

PATCH 17/38 mmc: sdhci: convert sdhci_set_clock() into a library function

In reply to Russell King - ARM Linux
---
 drivers/mmc/host/sdhci-acpi.c      |  2 ++
 drivers/mmc/host/sdhci-bcm-kona.c  |  1 +
 drivers/mmc/host/sdhci-bcm2835.c   |  1 +
 drivers/mmc/host/sdhci-cns3xxx.c   |  3 +--
 drivers/mmc/host/sdhci-dove.c      |  1 +
 drivers/mmc/host/sdhci-esdhc.h     |  1 -
 drivers/mmc/host/sdhci-of-arasan.c |  1 +
 drivers/mmc/host/sdhci-of-hlwd.c   |  1 +
 drivers/mmc/host/sdhci-pci.c       |  1 +
 drivers/mmc/host/sdhci-pltfm.c     |  1 +
 drivers/mmc/host/sdhci-pxav2.c     |  1 +
 drivers/mmc/host/sdhci-pxav3.c     |  1 +
 drivers/mmc/host/sdhci-s3c.c       | 19 ++++++++++++++-----
 drivers/mmc/host/sdhci-sirf.c      |  1 +
 drivers/mmc/host/sdhci-spear.c     |  1 +
 drivers/mmc/host/sdhci-tegra.c     |  1 +
 drivers/mmc/host/sdhci.c           | 17 ++++++-----------
 drivers/mmc/host/sdhci.h           |  1 +
 include/linux/mmc/sdhci.h          |  2 --
 19 files changed, 36 insertions(+), 21 deletions(-)
drivers/mmc/host/sdhci-acpi.c +2 -0
index aca84a682551..323e2a688563 100644
@@ -102,12 +102,14 @@ static void sdhci_acpi_int_hw_reset(struct sdhci_host *host)
 }
 
 static const struct sdhci_ops sdhci_acpi_ops_dflt = {
+	.set_clock = sdhci_set_clock,
 	.enable_dma = sdhci_acpi_enable_dma,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
 };
 
 static const struct sdhci_ops sdhci_acpi_ops_int = {
+	.set_clock = sdhci_set_clock,
 	.enable_dma = sdhci_acpi_enable_dma,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
drivers/mmc/host/sdhci-bcm-kona.c +1 -0
index 7b97bfab910d..e610811c09b0 100644
@@ -206,6 +206,7 @@ static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host,
 }
 
 static struct sdhci_ops sdhci_bcm_kona_ops = {
+	.set_clock = sdhci_set_clock,
 	.get_max_clock = sdhci_bcm_kona_get_max_clk,
 	.get_timeout_clock = sdhci_bcm_kona_get_timeout_clock,
 	.platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks,
drivers/mmc/host/sdhci-bcm2835.c +1 -0
index 289b1c80d5fc..74906d6008e1 100644
@@ -131,6 +131,7 @@ static const struct sdhci_ops bcm2835_sdhci_ops = {
 	.read_l = bcm2835_sdhci_readl,
 	.read_w = bcm2835_sdhci_readw,
 	.read_b = bcm2835_sdhci_readb,
+	.set_clock = sdhci_set_clock,
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 	.get_min_clock = bcm2835_sdhci_get_min_clock,
 	.set_bus_width = sdhci_set_bus_width,
drivers/mmc/host/sdhci-cns3xxx.c +1 -2
index 416f4a4c2e35..587d73ef33ff 100644
@@ -89,8 +89,7 @@ static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
 		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
 		  SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
 		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
-		  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
-		  SDHCI_QUIRK_NONSTANDARD_CLOCK,
+		  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
 };
 
 static int sdhci_cns3xxx_probe(struct platform_device *pdev)
drivers/mmc/host/sdhci-dove.c +1 -0
index 1408cc11d881..8ef4ab52f8e0 100644
@@ -86,6 +86,7 @@ static u32 sdhci_dove_readl(struct sdhci_host *host, int reg)
 static const struct sdhci_ops sdhci_dove_ops = {
 	.read_w	= sdhci_dove_readw,
 	.read_l	= sdhci_dove_readl,
+	.set_clock = sdhci_set_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
 };
drivers/mmc/host/sdhci-esdhc.h +0 -1
index de69bddc3afc..3497cfaf683c 100644
@@ -20,7 +20,6 @@
 
 #define ESDHC_DEFAULT_QUIRKS	(SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \
 				SDHCI_QUIRK_NO_BUSY_IRQ | \
-				SDHCI_QUIRK_NONSTANDARD_CLOCK | \
 				SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \
 				SDHCI_QUIRK_PIO_NEEDS_DELAY)
 
drivers/mmc/host/sdhci-of-arasan.c +1 -0
index faef21740584..f0ee594f25d1 100644
@@ -52,6 +52,7 @@ static unsigned int sdhci_arasan_get_timeout_clock(struct sdhci_host *host)
 }
 
 static struct sdhci_ops sdhci_arasan_ops = {
+	.set_clock = sdhci_set_clock,
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 	.get_timeout_clock = sdhci_arasan_get_timeout_clock,
 	.set_bus_width = sdhci_set_bus_width,
drivers/mmc/host/sdhci-of-hlwd.c +1 -0
index fb01958cb18e..a4a1f0f2c0a0 100644
@@ -58,6 +58,7 @@ static const struct sdhci_ops sdhci_hlwd_ops = {
 	.write_l = sdhci_hlwd_writel,
 	.write_w = sdhci_hlwd_writew,
 	.write_b = sdhci_hlwd_writeb,
+	.set_clock = sdhci_set_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
 };
drivers/mmc/host/sdhci-pci.c +1 -0
index 87f9dd91f68c..b3a28f6b170e 100644
@@ -1078,6 +1078,7 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host)
 }
 
 static const struct sdhci_ops sdhci_pci_ops = {
+	.set_clock	= sdhci_set_clock,
 	.enable_dma	= sdhci_pci_enable_dma,
 	.set_bus_width	= sdhci_pci_set_bus_width,
 	.reset		= sdhci_reset,
drivers/mmc/host/sdhci-pltfm.c +1 -0
index bfbf467b61c7..1fb89f44bd58 100644
@@ -45,6 +45,7 @@ unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host)
 EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock);
 
 static const struct sdhci_ops sdhci_pltfm_ops = {
+	.set_clock = sdhci_set_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
 };
drivers/mmc/host/sdhci-pxav2.c +1 -0
index 2eee0c8b88eb..db5257bf032e 100644
@@ -112,6 +112,7 @@ static void pxav2_mmc_set_bus_width(struct sdhci_host *host, int width)
 }
 
 static const struct sdhci_ops pxav2_sdhci_ops = {
+	.set_clock     = sdhci_set_clock,
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 	.set_bus_width = pxav2_mmc_set_bus_width,
 	.reset         = pxav2_reset,
drivers/mmc/host/sdhci-pxav3.c +1 -0
index 86564233ae93..8a40e079a57e 100644
@@ -225,6 +225,7 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 }
 
 static const struct sdhci_ops pxav3_sdhci_ops = {
+	.set_clock = sdhci_set_clock,
 	.set_uhs_signaling = pxav3_set_uhs_signaling,
 	.platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
drivers/mmc/host/sdhci-s3c.c +14 -5
index 464059c91a24..0ac075dfd844 100644
@@ -58,6 +58,8 @@ struct sdhci_s3c {
 	struct clk		*clk_io;
 	struct clk		*clk_bus[MAX_BUS_CLK];
 	unsigned long		clk_rates[MAX_BUS_CLK];
+
+	bool			no_divider;
 };
 
 /**
@@ -70,6 +72,7 @@ struct sdhci_s3c {
  */
 struct sdhci_s3c_drv_data {
 	unsigned int	sdhci_quirks;
+	bool		no_divider;
 };
 
 static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
@@ -119,7 +122,7 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
 	 * If controller uses a non-standard clock division, find the best clock
 	 * speed possible with selected clock source and skip the division.
 	 */
-	if (ourhost->host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
+	if (ourhost->no_divider) {
 		rate = clk_round_rate(clksrc, wanted);
 		return wanted - rate;
 	}
@@ -164,8 +167,10 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
 	host->mmc->actual_clock = 0;
 
 	/* don't bother if the clock is going off. */
-	if (clock == 0)
+	if (clock == 0) {
+		sdhci_set_clock(host, clock);
 		return;
+	}
 
 	for (src = 0; src < MAX_BUS_CLK; src++) {
 		delta = sdhci_s3c_consider_clock(ourhost, src, clock);
@@ -217,6 +222,8 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
 	if (clock < 25 * 1000000)
 		ctrl |= (S3C_SDHCI_CTRL3_FCSEL3 | S3C_SDHCI_CTRL3_FCSEL2);
 	writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL3);
+
+	sdhci_set_clock(host, clock);
 }
 
 /**
@@ -606,8 +613,10 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
 	/* Setup quirks for the controller */
 	host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
 	host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
-	if (drv_data)
+	if (drv_data) {
 		host->quirks |= drv_data->sdhci_quirks;
+		sc->no_divider = drv_data->no_divider;
+	}
 
 #ifndef CONFIG_MMC_SDHCI_S3C_DMA
 
@@ -656,7 +665,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
 	 * If controller does not have internal clock divider,
 	 * we can use overriding functions instead of default.
 	 */
-	if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
+	if (sc->no_divider) {
 		sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock;
 		sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock;
 		sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock;
@@ -797,7 +806,7 @@ static const struct dev_pm_ops sdhci_s3c_pmops = {
 
 #if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212)
 static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = {
-	.sdhci_quirks = SDHCI_QUIRK_NONSTANDARD_CLOCK,
+	.no_divider = true,
 };
 #define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)&exynos4_sdhci_drv_data)
 #else
drivers/mmc/host/sdhci-sirf.c +1 -0
index 5d79e10e1ba2..3b775348b470 100644
@@ -28,6 +28,7 @@ static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host)
 }
 
 static struct sdhci_ops sdhci_sirf_ops = {
+	.set_clock = sdhci_set_clock,
 	.get_max_clock	= sdhci_sirf_get_max_clk,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
drivers/mmc/host/sdhci-spear.c +1 -0
index c2a2bedc8813..8bf64ab36720 100644
@@ -38,6 +38,7 @@ struct spear_sdhci {
 
 /* sdhci ops */
 static const struct sdhci_ops sdhci_pltfm_ops = {
+	.set_clock = sdhci_set_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
 };
drivers/mmc/host/sdhci-tegra.c +1 -0
index 7754c0319fda..a0a8b5cc3b0c 100644
@@ -153,6 +153,7 @@ static const struct sdhci_ops tegra_sdhci_ops = {
 	.read_l     = tegra_sdhci_readl,
 	.read_w     = tegra_sdhci_readw,
 	.write_l    = tegra_sdhci_writel,
+	.set_clock  = sdhci_set_clock,
 	.set_bus_width = tegra_sdhci_set_bus_width,
 	.reset      = tegra_sdhci_reset,
 };
drivers/mmc/host/sdhci.c +6 -11
index 67b7a5752049..748333ba6e96 100644
@@ -1112,19 +1112,13 @@ static u16 sdhci_get_preset_value(struct sdhci_host *host)
 	return preset;
 }
 
-static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
+void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 {
 	int div = 0; /* Initialized for compiler warning */
 	int real_div = div, clk_mul = 1;
 	u16 clk = 0;
 	unsigned long timeout;
 
-	if (host->ops->set_clock) {
-		host->ops->set_clock(host, clock);
-		if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK)
-			return;
-	}
-
 	host->mmc->actual_clock = 0;
 
 	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
@@ -1221,6 +1215,7 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 	clk |= SDHCI_CLOCK_CARD_EN;
 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
 }
+EXPORT_SYMBOL_GPL(sdhci_set_clock);
 
 static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
 {
@@ -1439,7 +1434,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 		sdhci_enable_preset_value(host, false);
 
 	if (!ios->clock || ios->clock != host->clock) {
-		sdhci_set_clock(host, ios->clock);
+		host->ops->set_clock(host, ios->clock);
 		host->clock = ios->clock;
 	}
 
@@ -1509,7 +1504,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 			sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 
 			/* Re-enable SD Clock */
-			sdhci_set_clock(host, host->clock);
+			host->ops->set_clock(host, host->clock);
 		}
 
 
@@ -1553,7 +1548,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 		}
 
 		/* Re-enable SD Clock */
-		sdhci_set_clock(host, host->clock);
+		host->ops->set_clock(host, host->clock);
 	} else
 		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 
@@ -2124,7 +2119,7 @@ static void sdhci_tasklet_finish(unsigned long param)
 		/* Some controllers need this kick or reset won't work here */
 		if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
 			/* This is to force an update */
-			sdhci_set_clock(host, host->clock);
+			host->ops->set_clock(host, host->clock);
 
 		/* Spec says we should do both at the same time, but Ricoh
 		   controllers do not like that. */
drivers/mmc/host/sdhci.h +1 -0
index 7d84cb3b0e00..ac20195f667b 100644
@@ -400,6 +400,7 @@ static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host)
 	return !!(host->flags & SDHCI_SDIO_IRQ_ENABLED);
 }
 
+void sdhci_set_clock(struct sdhci_host *host, unsigned int clock);
 void sdhci_set_bus_width(struct sdhci_host *host, int width);
 void sdhci_reset(struct sdhci_host *host, u8 mask);
 
include/linux/mmc/sdhci.h +0 -2
index 02919ef99419..72a90baf111f 100644
@@ -57,8 +57,6 @@ struct sdhci_host {
 #define SDHCI_QUIRK_BROKEN_CARD_DETECTION		(1<<15)
 /* Controller reports inverted write-protect state */
 #define SDHCI_QUIRK_INVERTED_WRITE_PROTECT		(1<<16)
-/* Controller has nonstandard clock management */
-#define SDHCI_QUIRK_NONSTANDARD_CLOCK			(1<<17)
 /* Controller does not like fast PIO transfers */
 #define SDHCI_QUIRK_PIO_NEEDS_DELAY			(1<<18)
 /* Controller has to be forced to use block size of 2048 bytes */
Signature · 1 line
1.8.3.1
#21 lore raw

PATCH 18/38 mmc: sdhci-esdhc-imx: avoid DMA to kernel stack

In reply to Russell King - ARM Linux

sdhci-esdhc-imx tries to DMA to the kernel stack when tuning the interface, which causes dma-debug to complain. Fix this by kmallocing a buffer to hold the received tuning pattern.

---
 drivers/mmc/host/sdhci-esdhc-imx.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)
drivers/mmc/host/sdhci-esdhc-imx.c +16 -9
index ce8939ff97a4..5acfe2fc4fe0 100644
@@ -711,13 +711,12 @@ static void esdhc_request_done(struct mmc_request *mrq)
 	complete(&mrq->completion);
 }
 
-static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode)
+static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode,
+				 struct scatterlist *sg)
 {
 	struct mmc_command cmd = {0};
 	struct mmc_request mrq = {NULL};
 	struct mmc_data data = {0};
-	struct scatterlist sg;
-	char tuning_pattern[ESDHC_TUNING_BLOCK_PATTERN_LEN];
 
 	cmd.opcode = opcode;
 	cmd.arg = 0;
@@ -726,11 +725,9 @@ static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode)
 	data.blksz = ESDHC_TUNING_BLOCK_PATTERN_LEN;
 	data.blocks = 1;
 	data.flags = MMC_DATA_READ;
-	data.sg = &sg;
+	data.sg = sg;
 	data.sg_len = 1;
 
-	sg_init_one(&sg, tuning_pattern, sizeof(tuning_pattern));
-
 	mrq.cmd = &cmd;
 	mrq.cmd->mrq = &mrq;
 	mrq.data = &data;
@@ -770,13 +767,21 @@ static void esdhc_post_tuning(struct sdhci_host *host)
 
 static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
 {
+	struct scatterlist sg;
+	char *tuning_pattern;
 	int min, max, avg, ret;
 
+	tuning_pattern = kmalloc(ESDHC_TUNING_BLOCK_PATTERN_LEN, GFP_KERNEL);
+	if (!tuning_pattern)
+		return -ENOMEM;
+
+	sg_init_one(&sg, tuning_pattern, ESDHC_TUNING_BLOCK_PATTERN_LEN);
+
 	/* find the mininum delay first which can pass tuning */
 	min = ESDHC_TUNE_CTRL_MIN;
 	while (min < ESDHC_TUNE_CTRL_MAX) {
 		esdhc_prepare_tuning(host, min);
-		if (!esdhc_send_tuning_cmd(host, opcode))
+		if (!esdhc_send_tuning_cmd(host, opcode, &sg))
 			break;
 		min += ESDHC_TUNE_CTRL_STEP;
 	}
@@ -785,7 +790,7 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
 	max = min + ESDHC_TUNE_CTRL_STEP;
 	while (max < ESDHC_TUNE_CTRL_MAX) {
 		esdhc_prepare_tuning(host, max);
-		if (esdhc_send_tuning_cmd(host, opcode)) {
+		if (esdhc_send_tuning_cmd(host, opcode, &sg)) {
 			max -= ESDHC_TUNE_CTRL_STEP;
 			break;
 		}
@@ -795,9 +800,11 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
 	/* use average delay to get the best timing */
 	avg = (min + max) / 2;
 	esdhc_prepare_tuning(host, avg);
-	ret = esdhc_send_tuning_cmd(host, opcode);
+	ret = esdhc_send_tuning_cmd(host, opcode, &sg);
 	esdhc_post_tuning(host);
 
+	kfree(tuning_pattern);
+
 	dev_dbg(mmc_dev(host->mmc), "tunning %s at 0x%x ret %d\n",
 		ret ? "failed" : "passed", avg, ret);
 
Signature · 1 line
1.8.3.1
#22 lore raw

PATCH 19/38 mmc: sdhci-esdhc-imx: comment runtime_pm_get_sync() in esdhc_prepare_tuning()

In reply to Russell King - ARM Linux

It is far from obvious what this is doing, and it looks like it's an unbalanced runtime_pm_get() call. However, the put is inside sdhci_tasklet_finish(), so it's not unbalanced at all. This should be documented so people know what's going on here. Do so.

---
 drivers/mmc/host/sdhci-esdhc-imx.c | 1 +
 1 file changed, 1 insertion(+)
drivers/mmc/host/sdhci-esdhc-imx.c +1 -0
index 5acfe2fc4fe0..eb7a13796bcb 100644
@@ -695,6 +695,7 @@ static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
 	/* FIXME: delay a bit for card to be ready for next tuning due to errors */
 	mdelay(1);
 
+	/* This is balanced by the runtime put in sdhci_tasklet_finish */
 	pm_runtime_get_sync(host->mmc->parent);
 	reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
 	reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL |
Signature · 1 line
1.8.3.1
#23 lore raw

PATCH 20/38 mmc: sdhci-esdhc-imx: fix lockdep splat upon tuning

In reply to Russell King - ARM Linux

=================================
[ INFO: inconsistent lock state ]
3.14.0-rc1+ #490 Not tainted
---------------------------------
inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage.
kworker/u8:0/6 [HC0[0]:SC0[0]:HE1:SE1] takes:
(&(&host->lock)->rlock#2){?.-...}, at: [<c04b57a4>] esdhc_send_tuning_cmd+0x104/0x14c
{IN-HARDIRQ-W} state was registered at:

  [<c00652fc>] mark_lock+0x15c/0x6f8
  [<c0066354>] __lock_acquire+0xabc/0x1ca0
  [<c0067ad8>] lock_acquire+0xa0/0x130
  [<c0697a44>] _raw_spin_lock+0x34/0x44
  [<c04b0dbc>] sdhci_irq+0x20/0xa40
  [<c0071b1c>] handle_irq_event_percpu+0x74/0x284
  [<c0071d70>] handle_irq_event+0x44/0x64
  [<c0074db8>] handle_fasteoi_irq+0xac/0x140
  [<c007147c>] generic_handle_irq+0x28/0x38
  [<c000efd4>] handle_IRQ+0x40/0x98
  [<c0008584>] gic_handle_irq+0x30/0x64
  [<c0013144>] __irq_svc+0x44/0x58
  [<c0028fc8>] irq_exit+0xc0/0x120
  [<c000efd8>] handle_IRQ+0x44/0x98
  [<c0008584>] gic_handle_irq+0x30/0x64
  [<c0013144>] __irq_svc+0x44/0x58
  [<c068f398>] printk+0x3c/0x44
  [<c03191d0>] _regulator_get+0x1b4/0x1e0
  [<c031924c>] regulator_get+0x18/0x1c
  [<c049fbc4>] mmc_add_host+0x30/0x1c0
  [<c04b2e10>] sdhci_add_host+0x804/0xbbc
  [<c04b5318>] sdhci_esdhc_imx_probe+0x380/0x674
  [<c036d530>] platform_drv_probe+0x20/0x50
  [<c036b948>] driver_probe_device+0x120/0x234
  [<c036baf8>] __driver_attach+0x9c/0xa0
  [<c036a04c>] bus_for_each_dev+0x5c/0x90
  [<c036b418>] driver_attach+0x24/0x28
  [<c036b018>] bus_add_driver+0xe4/0x1d8
  [<c036c1b0>] driver_register+0x80/0xfc
  [<c036ce28>] __platform_driver_register+0x50/0x64
  [<c093706c>] sdhci_esdhc_imx_driver_init+0x18/0x20
  [<c0008834>] do_one_initcall+0x3c/0x164
  [<c0901c94>] kernel_init_freeable+0x104/0x1d0
  [<c068c45c>] kernel_init+0x10/0x118
  [<c000e768>] ret_from_fork+0x14/0x2c
irq event stamp: 5933
hardirqs last  enabled at (5933): [<c069813c>] _raw_spin_unlock_irqrestore+0x38/0x4c
hardirqs last disabled at (5932): [<c0697b04>] _raw_spin_lock_irqsave+0x24/0x60
softirqs last  enabled at (5914): [<c0028ba0>] __do_softirq+0x260/0x360
softirqs last disabled at (5909): [<c0028fc8>] irq_exit+0xc0/0x120

other info that might help us debug this:

 Possible unsafe locking scenario:
       CPU0
       ----
  lock(&(&host->lock)->rlock#2);
  <Interrupt>
    lock(&(&host->lock)->rlock#2);

*** DEADLOCK ***

2 locks held by kworker/u8:0/6:
#0: (kmmcd){.+.+.+}, at: [<c003d890>] process_one_work+0x134/0x4e8
#1: ((&(&host->detect)->work)){+.+.+.}, at: [<c003d890>] process_one_work+0x134/0x4e8

stack backtrace:
CPU: 2 PID: 6 Comm: kworker/u8:0 Not tainted 3.14.0-rc1+ #490
Workqueue: kmmcd mmc_rescan
Backtrace:
[<c00124a0>] (dump_backtrace) from [<c0012640>] (show_stack+0x18/0x1c)
[<c0012628>] (show_stack) from [<c069164c>] (dump_stack+0x70/0x8c)
[<c06915dc>] (dump_stack) from [<c068f080>] (print_usage_bug+0x274/0x2e4)
[<c068ee0c>] (print_usage_bug) from [<c0065774>] (mark_lock+0x5d4/0x6f8)
[<c00651a0>] (mark_lock) from [<c0065e6c>] (__lock_acquire+0x5d4/0x1ca0)
[<c0065898>] (__lock_acquire) from [<c0067ad8>] (lock_acquire+0xa0/0x130)
[<c0067a38>] (lock_acquire) from [<c0697a44>] (_raw_spin_lock+0x34/0x44)
[<c0697a10>] (_raw_spin_lock) from [<c04b57a4>] (esdhc_send_tuning_cmd+0x104/0x14c)
[<c04b56a0>] (esdhc_send_tuning_cmd) from [<c04b582c>] (esdhc_executing_tuning+0x40/0x100)
[<c04b57ec>] (esdhc_executing_tuning) from [<c04afa54>] (sdhci_execute_tuning+0xcc/0x754)
[<c04af988>] (sdhci_execute_tuning) from [<c04a4684>] (mmc_sd_init_card+0x65c/0x694)
[<c04a4028>] (mmc_sd_init_card) from [<c04a48f0>] (mmc_attach_sd+0xb0/0x184)
[<c04a4840>] (mmc_attach_sd) from [<c049eb28>] (mmc_rescan+0x26c/0x2e8)
[<c049e8bc>] (mmc_rescan) from [<c003d914>] (process_one_work+0x1b8/0x4e8)
[<c003d75c>] (process_one_work) from [<c003e090>] (worker_thread+0x13c/0x3f8)
[<c003df54>] (worker_thread) from [<c00449bc>] (kthread+0xcc/0xe8)
[<c00448f0>] (kthread) from [<c000e768>] (ret_from_fork+0x14/0x2c)
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/mmc/host/sdhci-esdhc-imx.c +2 -4
index eb7a13796bcb..dfed2c37ab3f 100644
@@ -738,14 +738,12 @@ static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode,
 	mrq.done = esdhc_request_done;
 	init_completion(&(mrq.completion));
 
-	disable_irq(host->irq);
-	spin_lock(&host->lock);
+	spin_lock_irq(&host->lock);
 	host->mrq = &mrq;
 
 	sdhci_send_command(host, mrq.cmd);
 
-	spin_unlock(&host->lock);
-	enable_irq(host->irq);
+	spin_unlock_irq(&host->lock);
 
 	wait_for_completion(&mrq.completion);
 
Signature · 1 line
1.8.3.1
#24 lore raw

PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1

In reply to Russell King - ARM Linux

Patch suggested by Dong Aisheng <[email protected]>, this avoids additional clock start/stop cycles during the transition to 1.8V signalling mode.

---
 drivers/mmc/host/sdhci.c | 12 ------------
 1 file changed, 12 deletions(-)
drivers/mmc/host/sdhci.c +0 -12
index 748333ba6e96..0bcef2d42da4 100644
@@ -1507,12 +1507,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 			host->ops->set_clock(host, host->clock);
 		}
 
-
-		/* Reset SD Clock Enable */
-		clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-		clk &= ~SDHCI_CLOCK_CARD_EN;
-		sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-
 		if (host->ops->set_uhs_signaling)
 			host->ops->set_uhs_signaling(host, ios->timing);
 		else {
@@ -1546,9 +1540,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 			ios->drv_type = (preset & SDHCI_PRESET_DRV_MASK)
 				>> SDHCI_PRESET_DRV_SHIFT;
 		}
-
-		/* Re-enable SD Clock */
-		host->ops->set_clock(host, host->clock);
 	} else
 		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 
@@ -1757,9 +1748,6 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
 		ctrl |= SDHCI_CTRL_VDD_180;
 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
-		/* Wait for 5ms */
-		usleep_range(5000, 5500);
-
 		/* 1.8V regulator output should be stable within 5 ms */
 		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 		if (ctrl & SDHCI_CTRL_VDD_180)
Signature · 1 line
1.8.3.1
#25 lore raw

PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1

Hi,

Quoted 5 lines · Russell King

Patch suggested by Dong Aisheng <[email protected]>, this avoids additional clock start/stop cycles during the transition to 1.8V signalling mode.

I tested the series on imx6s with a RIoT board. With this patch applied the RIoT board emmc does not work. Here is the output of the board:

# dmesg | grep mmc2
mmc2: no vqmmc regulator found
mmc2: no vmmc regulator found
mmc2: SDHCI controller on 219c000.usdhc [219c000.usdhc] using ADMA
mmc2: BKOPS_EN bit is not set
mmc2: Timeout waiting for hardware interrupt.
mmc2: Timeout waiting for hardware interrupt.
mmc2: Timeout waiting for hardware interrupt.
mmc2: Timeout waiting for hardware interrupt.
mmc2: error -110 whilst initialising MMC card
mmc2: BKOPS_EN bit is not set
mmc2: Timeout waiting for hardware interrupt.
mmc2: Timeout waiting for hardware interrupt.
mmc2: Timeout waiting for hardware interrupt.
mmc2: Timeout waiting for hardware interrupt.
mmc2: error -110 whilst initialising MMC card
mmc2: BKOPS_EN bit is not set

Any ideas?

Regards,

Markus

Quoted 50 lines
---
 drivers/mmc/host/sdhci.c | 12 ------------
 1 file changed, 12 deletions(-)
drivers/mmc/host/sdhci.c +0 -12
index 748333ba6e96..0bcef2d42da4 100644
@@ -1507,12 +1507,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 			host->ops->set_clock(host, host->clock);
 		}
 
-
-		/* Reset SD Clock Enable */
-		clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-		clk &= ~SDHCI_CLOCK_CARD_EN;
-		sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-
 		if (host->ops->set_uhs_signaling)
 			host->ops->set_uhs_signaling(host, ios->timing);
 		else {
@@ -1546,9 +1540,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 			ios->drv_type = (preset & SDHCI_PRESET_DRV_MASK)
 				>> SDHCI_PRESET_DRV_SHIFT;
 		}
-
-		/* Re-enable SD Clock */
-		host->ops->set_clock(host, host->clock);
 	} else
 		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 
@@ -1757,9 +1748,6 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
 		ctrl |= SDHCI_CTRL_VDD_180;
 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
-		/* Wait for 5ms */
-		usleep_range(5000, 5500);
-
 		/* 1.8V regulator output should be stable within 5 ms */
 		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 		if (ctrl & SDHCI_CTRL_VDD_180)
Signature · 7 lines
1.8.3.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Signature · 11 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140425/7932e0b9/attachment.sig>
#26 lore raw

PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1

Quoted 11 lines · Markus Pargmann

Hi,

Quoted 5 lines · Russell King

Patch suggested by Dong Aisheng <[email protected]>, this avoids additional clock start/stop cycles during the transition to 1.8V signalling mode.

I tested the series on imx6s with a RIoT board. With this patch applied the RIoT board emmc does not work. Here is the output of the board:

Unfortunately, I don't have any emmc sdhci using devices, so this is a combination I can't test myself.

What would be useful is to find out which of the two changes in there is the cause - can you try with just the change to sdhci_do_start_signal_voltage_switch applied, iow just this change:

drivers/mmc/host/sdhci.c +0 -3
index 748333ba6e96..0bcef2d42da4 100644
@@ -1757,9 +1748,6 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
 		ctrl |= SDHCI_CTRL_VDD_180;
 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
-		/* Wait for 5ms */
-		usleep_range(5000, 5500);
-
 		/* 1.8V regulator output should be stable within 5 ms */
 		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 		if (ctrl & SDHCI_CTRL_VDD_180)

Thanks.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#27 lore raw

PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1

Quoted 13 lines · Russell King - ARM Linux
Quoted 11 lines · Markus Pargmann

Hi,

Quoted 5 lines · Russell King

Patch suggested by Dong Aisheng <[email protected]>, this avoids additional clock start/stop cycles during the transition to 1.8V signalling mode.

I tested the series on imx6s with a RIoT board. With this patch applied the RIoT board emmc does not work. Here is the output of the board:

Quoted 6 lines

Unfortunately, I don't have any emmc sdhci using devices, so this is a combination I can't test myself.

What would be useful is to find out which of the two changes in there is the cause - can you try with just the change to sdhci_do_start_signal_voltage_switch applied, iow just this change:

I just tried the different parts of the patch. Without the following change, emmc works:

drivers/mmc/host/sdhci.c +0 -6
@@ -1507,12 +1507,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 			host->ops->set_clock(host, host->clock);
 		}
 
-
-		/* Reset SD Clock Enable */
-		clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-		clk &= ~SDHCI_CLOCK_CARD_EN;
-		sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-
 

Regards,

Markus

Signature · 11 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140425/41d480c8/attachment.sig>
#28 lore raw

PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1

Quoted 6 lines · Markus Pargmann

I just tried the different parts of the patch. Without the following change, emmc works:

drivers/mmc/host/sdhci.c static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) · line 1515

Quoted 9 lines
drivers/mmc/host/sdhci.c +0 -6
@@ -1507,12 +1507,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 			host->ops->set_clock(host, host->clock);
 		}
 
-
-		/* Reset SD Clock Enable */
-		clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-		clk &= ~SDHCI_CLOCK_CARD_EN;
-		sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-

So the bit which stops us violating the SD spec stops eMMC from working... that's... just great.

Okay, I'll look deeper at this and see what can be done, but I suspect it will turn out to require more patches and be more invasive.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#29 lore raw

PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1

Quoted 20 lines · Russell King - ARM Linux
Quoted 6 lines · Markus Pargmann

I just tried the different parts of the patch. Without the following change, emmc works:

drivers/mmc/host/sdhci.c static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) · line 1515

Quoted 9 lines
drivers/mmc/host/sdhci.c +0 -6
@@ -1507,12 +1507,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 			host->ops->set_clock(host, host->clock);
 		}
 
-
-		/* Reset SD Clock Enable */
-		clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-		clk &= ~SDHCI_CLOCK_CARD_EN;
-		sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-

So the bit which stops us violating the SD spec stops eMMC from working... that's... just great.

Quoted 2 lines

Okay, I'll look deeper at this and see what can be done, but I suspect it will turn out to require more patches and be more invasive.

In the mean time, here's the remainder (to patch 33) of the series with this commit omitted.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#30 lore raw

PATCH 21/32 mmc: sdhci: set_uhs_signaling() need not return a value

The set_uhs_signaling() method gives the impression that it can fail, but anything returned from the method is entirely ignored by the sdhci driver. So returning failure has no effect.

So, kill the idea that it's possible for this to return an error by removing the returned value.

---
 drivers/mmc/host/sdhci-esdhc-imx.c | 4 ++--
 drivers/mmc/host/sdhci-pxav3.c     | 4 +---
 drivers/mmc/host/sdhci.h           | 2 +-
 3 files changed, 4 insertions(+), 6 deletions(-)
drivers/mmc/host/sdhci-esdhc-imx.c +2 -2
index dfed2c37ab3f..72e0581e564f 100644
@@ -841,7 +841,7 @@ static int esdhc_change_pinstate(struct sdhci_host *host,
 	return pinctrl_select_state(imx_data->pinctrl, pinctrl);
 }
 
-static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
+static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
@@ -879,7 +879,7 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 		break;
 	}
 
-	return esdhc_change_pinstate(host, uhs);
+	esdhc_change_pinstate(host, uhs);
 }
 
 static void esdhc_reset(struct sdhci_host *host, u8 mask)
drivers/mmc/host/sdhci-pxav3.c +1 -3
index 8a40e079a57e..05574104a254 100644
@@ -186,7 +186,7 @@ static void pxav3_gen_init_74_clocks(struct sdhci_host *host, u8 power_mode)
 	pxa->power_mode = power_mode;
 }
 
-static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
+static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 {
 	u16 ctrl_2;
 
@@ -220,8 +220,6 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 	dev_dbg(mmc_dev(host->mmc),
 		"%s uhs = %d, ctrl_2 = %04X\n",
 		__func__, uhs, ctrl_2);
-
-	return 0;
 }
 
 static const struct sdhci_ops pxav3_sdhci_ops = {
drivers/mmc/host/sdhci.h +1 -1
index ac20195f667b..3179a8053019 100644
@@ -287,7 +287,7 @@ struct sdhci_ops {
 	unsigned int    (*get_ro)(struct sdhci_host *host);
 	void		(*reset)(struct sdhci_host *host, u8 mask);
 	int	(*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
-	int	(*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
+	void	(*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
 	void	(*hw_reset)(struct sdhci_host *host);
 	void	(*platform_suspend)(struct sdhci_host *host);
 	void	(*platform_resume)(struct sdhci_host *host);
Signature · 1 line
1.8.3.1
#31 lore raw

PATCH 22/32 mmc: sdhci: convert sdhci_set_uhs_signaling() into a library function

In reply to Russell King - ARM Linux

Add sdhci_set_uhs_signaling() and always call the set_uhs_signaling method. This avoids quirks being added into sdhci_set_uhs_signaling().

---
 drivers/mmc/host/sdhci-acpi.c      |  2 ++
 drivers/mmc/host/sdhci-bcm-kona.c  |  1 +
 drivers/mmc/host/sdhci-bcm2835.c   |  1 +
 drivers/mmc/host/sdhci-cns3xxx.c   |  1 +
 drivers/mmc/host/sdhci-dove.c      |  1 +
 drivers/mmc/host/sdhci-of-arasan.c |  1 +
 drivers/mmc/host/sdhci-of-esdhc.c  |  1 +
 drivers/mmc/host/sdhci-of-hlwd.c   |  1 +
 drivers/mmc/host/sdhci-pci.c       |  1 +
 drivers/mmc/host/sdhci-pltfm.c     |  1 +
 drivers/mmc/host/sdhci-pxav2.c     |  1 +
 drivers/mmc/host/sdhci-pxav3.c     |  1 +
 drivers/mmc/host/sdhci-s3c.c       |  1 +
 drivers/mmc/host/sdhci-sirf.c      |  1 +
 drivers/mmc/host/sdhci-spear.c     |  1 +
 drivers/mmc/host/sdhci-tegra.c     |  1 +
 drivers/mmc/host/sdhci.c           | 43 ++++++++++++++++++++------------------
 drivers/mmc/host/sdhci.h           |  1 +
 18 files changed, 41 insertions(+), 20 deletions(-)
drivers/mmc/host/sdhci-acpi.c +2 -0
index 323e2a688563..8ce3c28cb76e 100644
@@ -106,6 +106,7 @@ static const struct sdhci_ops sdhci_acpi_ops_dflt = {
 	.enable_dma = sdhci_acpi_enable_dma,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static const struct sdhci_ops sdhci_acpi_ops_int = {
@@ -113,6 +114,7 @@ static const struct sdhci_ops sdhci_acpi_ops_int = {
 	.enable_dma = sdhci_acpi_enable_dma,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 	.hw_reset   = sdhci_acpi_int_hw_reset,
 };
 
drivers/mmc/host/sdhci-bcm-kona.c +1 -0
index e610811c09b0..dd780c315a63 100644
@@ -212,6 +212,7 @@ static struct sdhci_ops sdhci_bcm_kona_ops = {
 	.platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 	.card_event = sdhci_bcm_kona_card_event,
 };
 
drivers/mmc/host/sdhci-bcm2835.c +1 -0
index 74906d6008e1..46af9a439d7b 100644
@@ -136,6 +136,7 @@ static const struct sdhci_ops bcm2835_sdhci_ops = {
 	.get_min_clock = bcm2835_sdhci_get_min_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
drivers/mmc/host/sdhci-cns3xxx.c +1 -0
index 587d73ef33ff..14b74075589a 100644
@@ -81,6 +81,7 @@ static const struct sdhci_ops sdhci_cns3xxx_ops = {
 	.set_clock	= sdhci_cns3xxx_set_clock,
 	.set_bus_width	= sdhci_set_bus_width,
 	.reset          = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
drivers/mmc/host/sdhci-dove.c +1 -0
index 8ef4ab52f8e0..0d315f4496c8 100644
@@ -89,6 +89,7 @@ static const struct sdhci_ops sdhci_dove_ops = {
 	.set_clock = sdhci_set_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static const struct sdhci_pltfm_data sdhci_dove_pdata = {
drivers/mmc/host/sdhci-of-arasan.c +1 -0
index f0ee594f25d1..5bd1092310f2 100644
@@ -57,6 +57,7 @@ static struct sdhci_ops sdhci_arasan_ops = {
 	.get_timeout_clock = sdhci_arasan_get_timeout_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static struct sdhci_pltfm_data sdhci_arasan_pdata = {
drivers/mmc/host/sdhci-of-esdhc.c +1 -0
index c4f8cd3f83c8..fcaeae5f55b8 100644
@@ -309,6 +309,7 @@ static const struct sdhci_ops sdhci_esdhc_ops = {
 	.adma_workaround = esdhci_of_adma_workaround,
 	.set_bus_width = esdhc_pltfm_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
drivers/mmc/host/sdhci-of-hlwd.c +1 -0
index a4a1f0f2c0a0..b341661369a2 100644
@@ -61,6 +61,7 @@ static const struct sdhci_ops sdhci_hlwd_ops = {
 	.set_clock = sdhci_set_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static const struct sdhci_pltfm_data sdhci_hlwd_pdata = {
drivers/mmc/host/sdhci-pci.c +1 -0
index b3a28f6b170e..52c42fcc284c 100644
@@ -1082,6 +1082,7 @@ static const struct sdhci_ops sdhci_pci_ops = {
 	.enable_dma	= sdhci_pci_enable_dma,
 	.set_bus_width	= sdhci_pci_set_bus_width,
 	.reset		= sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 	.hw_reset		= sdhci_pci_hw_reset,
 };
 
drivers/mmc/host/sdhci-pltfm.c +1 -0
index 1fb89f44bd58..7e834fb78f42 100644
@@ -48,6 +48,7 @@ static const struct sdhci_ops sdhci_pltfm_ops = {
 	.set_clock = sdhci_set_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 #ifdef CONFIG_OF
drivers/mmc/host/sdhci-pxav2.c +1 -0
index db5257bf032e..3c0f3c0a1cc8 100644
@@ -116,6 +116,7 @@ static const struct sdhci_ops pxav2_sdhci_ops = {
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 	.set_bus_width = pxav2_mmc_set_bus_width,
 	.reset         = pxav2_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 #ifdef CONFIG_OF
drivers/mmc/host/sdhci-pxav3.c +1 -0
index 05574104a254..f4f128947561 100644
@@ -229,6 +229,7 @@ static const struct sdhci_ops pxav3_sdhci_ops = {
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = pxav3_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static struct sdhci_pltfm_data sdhci_pxav3_pdata = {
drivers/mmc/host/sdhci-s3c.c +1 -0
index 0ac075dfd844..76d7c12d8ef9 100644
@@ -374,6 +374,7 @@ static struct sdhci_ops sdhci_s3c_ops = {
 	.get_min_clock		= sdhci_s3c_get_min_clock,
 	.set_bus_width		= sdhci_s3c_set_bus_width,
 	.reset			= sdhci_reset,
+	.set_uhs_signaling	= sdhci_set_uhs_signaling,
 };
 
 static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
drivers/mmc/host/sdhci-sirf.c +1 -0
index 3b775348b470..17004531d089 100644
@@ -32,6 +32,7 @@ static struct sdhci_ops sdhci_sirf_ops = {
 	.get_max_clock	= sdhci_sirf_get_max_clk,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static struct sdhci_pltfm_data sdhci_sirf_pdata = {
drivers/mmc/host/sdhci-spear.c +1 -0
index 8bf64ab36720..9d535c7336ef 100644
@@ -41,6 +41,7 @@ static const struct sdhci_ops sdhci_pltfm_ops = {
 	.set_clock = sdhci_set_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 #ifdef CONFIG_OF
drivers/mmc/host/sdhci-tegra.c +1 -0
index a0a8b5cc3b0c..d06b6ff60432 100644
@@ -156,6 +156,7 @@ static const struct sdhci_ops tegra_sdhci_ops = {
 	.set_clock  = sdhci_set_clock,
 	.set_bus_width = tegra_sdhci_set_bus_width,
 	.reset      = tegra_sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {
drivers/mmc/host/sdhci.c +23 -20

60 lines not on this page · raw message

drivers/mmc/host/sdhci.h +1 -0
index 3179a8053019..7a35395e5f56 100644
@@ -403,6 +403,7 @@ static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host)
 void sdhci_set_clock(struct sdhci_host *host, unsigned int clock);
 void sdhci_set_bus_width(struct sdhci_host *host, int width);
 void sdhci_reset(struct sdhci_host *host, u8 mask);
+void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing);
 
 #ifdef CONFIG_PM
 extern int sdhci_suspend_host(struct sdhci_host *host);
Signature · 1 line
1.8.3.1
#32 lore raw

PATCH 23/32 mmc: sdhci: cache timing information locally

In reply to Russell King - ARM Linux

Rather than reading back the timing information from the registers, cache it locally. This allows implementations to translate the UHS timing by overriding the set_uhs_signaling() method as required without also having to emulate the SDHCI_HOST_CONTROL2 register.

---
 drivers/mmc/host/sdhci.c  | 23 ++++++++++++-----------
 include/linux/mmc/sdhci.h |  2 ++
 2 files changed, 14 insertions(+), 11 deletions(-)
drivers/mmc/host/sdhci.c +12 -11
index 1d88345f88cd..514a0b827620 100644
@@ -1083,24 +1083,23 @@ static void sdhci_finish_command(struct sdhci_host *host)
 
 static u16 sdhci_get_preset_value(struct sdhci_host *host)
 {
-	u16 ctrl, preset = 0;
+	u16 preset = 0;
 
-	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-
-	switch (ctrl & SDHCI_CTRL_UHS_MASK) {
-	case SDHCI_CTRL_UHS_SDR12:
+	switch (host->timing) {
+	case MMC_TIMING_UHS_SDR12:
 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12);
 		break;
-	case SDHCI_CTRL_UHS_SDR25:
+	case MMC_TIMING_UHS_SDR25:
 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR25);
 		break;
-	case SDHCI_CTRL_UHS_SDR50:
+	case MMC_TIMING_UHS_SDR50:
 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR50);
 		break;
-	case SDHCI_CTRL_UHS_SDR104:
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_MMC_HS200:
 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104);
 		break;
-	case SDHCI_CTRL_UHS_DDR50:
+	case MMC_TIMING_UHS_DDR50:
 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50);
 		break;
 	default:
@@ -1535,6 +1534,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 		sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
 
 		host->ops->set_uhs_signaling(host, ios->timing);
+		host->timing = ios->timing;
 
 		if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) &&
 				((ios->timing == MMC_TIMING_UHS_SDR12) ||
@@ -1839,12 +1839,13 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 	 * If the Host Controller supports the HS200 mode then the
 	 * tuning function has to be executed.
 	 */
-	if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) &&
+	if (host->timing == MMC_TIMING_UHS_SDR50 &&
 	    (host->flags & SDHCI_SDR50_NEEDS_TUNING ||
 	     host->flags & SDHCI_SDR104_NEEDS_TUNING))
 		requires_tuning_nonuhs = true;
 
-	if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) ||
+	if (host->timing == MMC_TIMING_MMC_HS200 ||
+	    host->timing == MMC_TIMING_UHS_SDR104 ||
 	    requires_tuning_nonuhs)
 		ctrl |= SDHCI_CTRL_EXEC_TUNING;
 	else {
include/linux/mmc/sdhci.h +2 -0
index 72a90baf111f..7f3efbab8732 100644
@@ -172,6 +172,8 @@ struct sdhci_host {
 	unsigned int            ocr_avail_mmc;
 	u32 ocr_mask;		/* available voltages */
 
+	unsigned		timing;		/* Current timing */
+
 	u32			thread_isr;
 
 	/* cached registers */
Signature · 1 line
1.8.3.1
#33 lore raw

PATCH 24/32 mmc: sdhci: clean up sdhci_execute_tuning() decision

In reply to Russell King - ARM Linux

Clean up the code in sdhci_execute_tuning() so the decision whether to execute tuning is clearer - and despite this reflecting what the original code was doing, it shows that it may not be what the author actually intended.

---
 drivers/mmc/host/sdhci.c | 31 +++++++++++++++----------------
 1 file changed, 15 insertions(+), 16 deletions(-)
drivers/mmc/host/sdhci.c +15 -16
index 514a0b827620..e5e9f2139f77 100644
@@ -1817,21 +1817,16 @@ static int sdhci_card_busy(struct mmc_host *mmc)
 
 static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
-	struct sdhci_host *host;
+	struct sdhci_host *host = mmc_priv(mmc);
 	u16 ctrl;
 	int tuning_loop_counter = MAX_TUNING_LOOP;
 	unsigned long timeout;
 	int err = 0;
-	bool requires_tuning_nonuhs = false;
 	unsigned long flags;
 
-	host = mmc_priv(mmc);
-
 	sdhci_runtime_pm_get(host);
 	spin_lock_irqsave(&host->lock, flags);
 
-	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-
 	/*
 	 * The Host Controller needs tuning only in case of SDR104 mode
 	 * and for SDR50 mode when Use Tuning for SDR50 is set in the
@@ -1839,16 +1834,18 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 	 * If the Host Controller supports the HS200 mode then the
 	 * tuning function has to be executed.
 	 */
-	if (host->timing == MMC_TIMING_UHS_SDR50 &&
-	    (host->flags & SDHCI_SDR50_NEEDS_TUNING ||
-	     host->flags & SDHCI_SDR104_NEEDS_TUNING))
-		requires_tuning_nonuhs = true;
-
-	if (host->timing == MMC_TIMING_MMC_HS200 ||
-	    host->timing == MMC_TIMING_UHS_SDR104 ||
-	    requires_tuning_nonuhs)
-		ctrl |= SDHCI_CTRL_EXEC_TUNING;
-	else {
+	switch (host->timing) {
+	case MMC_TIMING_MMC_HS200:
+	case MMC_TIMING_UHS_SDR104:
+		break;
+
+	case MMC_TIMING_UHS_SDR50:
+		if (host->flags & SDHCI_SDR50_NEEDS_TUNING ||
+		    host->flags & SDHCI_SDR104_NEEDS_TUNING)
+			break;
+		/* FALLTHROUGH */
+
+	default:
 		spin_unlock_irqrestore(&host->lock, flags);
 		sdhci_runtime_pm_put(host);
 		return 0;
@@ -1861,6 +1858,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 		return err;
 	}
 
+	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+	ctrl |= SDHCI_CTRL_EXEC_TUNING;
 	sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
 	/*
Signature · 1 line
1.8.3.1
#34 lore raw

PATCH 25/32 mmc: sdhci-esdhc-imx: remove emulation of uhs_mode

In reply to Russell King - ARM Linux

We no longer need to emulate the uhs_mode field of the host control2 register - the main sdhci driver never reads this back to evaluate the current mode as it caches the current mode instead.

---
 drivers/mmc/host/sdhci-esdhc-imx.c | 17 +++--------------
 1 file changed, 3 insertions(+), 14 deletions(-)
drivers/mmc/host/sdhci-esdhc-imx.c +3 -14
index 72e0581e564f..4866d802f9e2 100644
@@ -160,7 +160,6 @@ struct pltfm_imx_data {
 		MULTIBLK_IN_PROCESS, /* exact multiblock cmd in process */
 		WAIT_FOR_INT,        /* sent CMD12, waiting for response INT */
 	} multiblock_status;
-	u32 uhs_mode;
 	u32 is_ddr;
 };
 
@@ -382,7 +381,6 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
 		if (val & ESDHC_MIX_CTRL_SMPCLK_SEL)
 			ret |= SDHCI_CTRL_TUNED_CLK;
 
-		ret |= (imx_data->uhs_mode & SDHCI_CTRL_UHS_MASK);
 		ret &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
 
 		return ret;
@@ -429,7 +427,6 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 		else
 			new_val &= ~ESDHC_VENDOR_SPEC_VSELECT;
 		writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC);
-		imx_data->uhs_mode = val & SDHCI_CTRL_UHS_MASK;
 		if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
 			new_val = readl(host->ioaddr + ESDHC_MIX_CTRL);
 			if (val & SDHCI_CTRL_TUNED_CLK)
@@ -841,28 +838,20 @@ static int esdhc_change_pinstate(struct sdhci_host *host,
 	return pinctrl_select_state(imx_data->pinctrl, pinctrl);
 }
 
-static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
+static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
 	struct esdhc_platform_data *boarddata = &imx_data->boarddata;
 
-	switch (uhs) {
+	switch (timing) {
 	case MMC_TIMING_UHS_SDR12:
-		imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR12;
-		break;
 	case MMC_TIMING_UHS_SDR25:
-		imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR25;
-		break;
 	case MMC_TIMING_UHS_SDR50:
-		imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR50;
-		break;
 	case MMC_TIMING_UHS_SDR104:
 	case MMC_TIMING_MMC_HS200:
-		imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR104;
 		break;
 	case MMC_TIMING_UHS_DDR50:
-		imx_data->uhs_mode = SDHCI_CTRL_UHS_DDR50;
 		writel(readl(host->ioaddr + ESDHC_MIX_CTRL) |
 				ESDHC_MIX_CTRL_DDREN,
 				host->ioaddr + ESDHC_MIX_CTRL);
@@ -879,7 +868,7 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 		break;
 	}
 
-	esdhc_change_pinstate(host, uhs);
+	esdhc_change_pinstate(host, timing);
 }
 
 static void esdhc_reset(struct sdhci_host *host, u8 mask)
Signature · 1 line
1.8.3.1
#35 lore raw

PATCH 26/32 mmc: sdhci-of-esdhc: remove platform_suspend/platform_resume callbacks

In reply to Russell King - ARM Linux

We don't need these hooks in order to insert code in these paths, we can just provide our own handlers and call the main sdhci handlers as appropriate.

---
 drivers/mmc/host/sdhci-of-esdhc.c | 55 +++++++++++++++++++++++++--------------
 1 file changed, 36 insertions(+), 19 deletions(-)
drivers/mmc/host/sdhci-of-esdhc.c +36 -19
index fcaeae5f55b8..605815e52f5f 100644
@@ -241,20 +241,6 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
 	mdelay(1);
 }
 
-#ifdef CONFIG_PM
-static u32 esdhc_proctl;
-static void esdhc_of_suspend(struct sdhci_host *host)
-{
-	esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
-}
-
-static void esdhc_of_resume(struct sdhci_host *host)
-{
-	esdhc_of_enable_dma(host);
-	sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
-}
-#endif
-
 static void esdhc_of_platform_init(struct sdhci_host *host)
 {
 	u32 vvn;
@@ -302,16 +288,47 @@ static const struct sdhci_ops sdhci_esdhc_ops = {
 	.get_max_clock = esdhc_of_get_max_clock,
 	.get_min_clock = esdhc_of_get_min_clock,
 	.platform_init = esdhc_of_platform_init,
-#ifdef CONFIG_PM
-	.platform_suspend = esdhc_of_suspend,
-	.platform_resume = esdhc_of_resume,
-#endif
 	.adma_workaround = esdhci_of_adma_workaround,
 	.set_bus_width = esdhc_pltfm_set_bus_width,
 	.reset = sdhci_reset,
 	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
+#ifdef CONFIG_PM
+
+static u32 esdhc_proctl;
+static int esdhc_of_suspend(struct device *dev)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+
+	esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
+
+	return sdhci_suspend_host(host);
+}
+
+static void esdhc_of_resume(device *dev)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	int ret = sdhci_resume_host(host);
+
+	if (ret == 0) {
+		/* Isn't this already done by sdhci_resume_host() ? --rmk */
+		esdhc_of_enable_dma(host);
+		sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
+	}
+
+	return ret;
+}
+
+static const struct dev_pm_ops esdhc_pmops = {
+	.suspend	= esdhci_of_suspend,
+	.resume		= esdhci_of_resume,
+};
+#define ESDHC_PMOPS (&esdhc_pmops)
+#else
+#define ESDHC_PMOPS NULL
+#endif
+
 static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
 	/*
 	 * card detection could be handled via GPIO
@@ -373,7 +390,7 @@ static struct platform_driver sdhci_esdhc_driver = {
 		.name = "sdhci-esdhc",
 		.owner = THIS_MODULE,
 		.of_match_table = sdhci_esdhc_of_match,
-		.pm = SDHCI_PLTFM_PMOPS,
+		.pm = ESDHC_PMOPS,
 	},
 	.probe = sdhci_esdhc_probe,
 	.remove = sdhci_esdhc_remove,
Signature · 1 line
1.8.3.1
#36 lore raw

PATCH 27/32 mmc: sdhci: remove platform_suspend/platform_resume callbacks

In reply to Russell King - ARM Linux

The only user (sdhci-of-esdhc) no longer uses these callbacks, so lets remove them to discourage any further use.

---
 drivers/mmc/host/sdhci.c | 6 ------
 drivers/mmc/host/sdhci.h | 2 --
 2 files changed, 8 deletions(-)
drivers/mmc/host/sdhci.c +0 -6
index e5e9f2139f77..02d43765ddd5 100644
@@ -2541,9 +2541,6 @@ EXPORT_SYMBOL_GPL(sdhci_disable_irq_wakeups);
 
 int sdhci_suspend_host(struct sdhci_host *host)
 {
-	if (host->ops->platform_suspend)
-		host->ops->platform_suspend(host);
-
 	sdhci_disable_card_detection(host);
 
 	/* Disable tuning since we are suspending */
@@ -2600,9 +2597,6 @@ int sdhci_resume_host(struct sdhci_host *host)
 
 	sdhci_enable_card_detection(host);
 
-	if (host->ops->platform_resume)
-		host->ops->platform_resume(host);
-
 	/* Set the re-tuning expiration flag */
 	if (host->flags & SDHCI_USING_RETUNING_TIMER)
 		host->flags |= SDHCI_NEEDS_RETUNING;
drivers/mmc/host/sdhci.h +0 -2
index 7a35395e5f56..4a5cd5e3fa3e 100644
@@ -289,8 +289,6 @@ struct sdhci_ops {
 	int	(*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
 	void	(*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
 	void	(*hw_reset)(struct sdhci_host *host);
-	void	(*platform_suspend)(struct sdhci_host *host);
-	void	(*platform_resume)(struct sdhci_host *host);
 	void    (*adma_workaround)(struct sdhci_host *host, u32 intmask);
 	void	(*platform_init)(struct sdhci_host *host);
 	void    (*card_event)(struct sdhci_host *host);
Signature · 1 line
1.8.3.1
#37 lore raw

PATCH 28/32 mmc: sdhci-tegra: get rid of special PRESENT_STATE register handling

In reply to Russell King - ARM Linux

sdhci-tegra provides a get_ro method, which overrides the checking of the write protect bit in the PRESENT_STATE register in sdhci.c:

        if (host->flags & SDHCI_DEVICE_DEAD)
                is_readonly = 0;
        else if (host->ops->get_ro)
                is_readonly = host->ops->get_ro(host);
        else
                is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE)
                                & SDHCI_WRITE_PROTECT);

This means it's pointless detecting accesses to this register and manually setting the SDHCI_WRITE_PROTECT as it has no effect.

This means that the whole of tegra_sdhci_readl() can be removed and we can use the builtin sdhci readl functionality here.

---
 drivers/mmc/host/sdhci-tegra.c | 14 --------------
 1 file changed, 14 deletions(-)
drivers/mmc/host/sdhci-tegra.c +0 -14
index d06b6ff60432..985247649f46 100644
@@ -48,19 +48,6 @@ struct sdhci_tegra {
 	int power_gpio;
 };
 
-static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg)
-{
-	u32 val;
-
-	if (unlikely(reg == SDHCI_PRESENT_STATE)) {
-		/* Use wp_gpio here instead? */
-		val = readl(host->ioaddr + reg);
-		return val | SDHCI_WRITE_PROTECT;
-	}
-
-	return readl(host->ioaddr + reg);
-}
-
 static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -150,7 +137,6 @@ static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width)
 
 static const struct sdhci_ops tegra_sdhci_ops = {
 	.get_ro     = tegra_sdhci_get_ro,
-	.read_l     = tegra_sdhci_readl,
 	.read_w     = tegra_sdhci_readw,
 	.write_l    = tegra_sdhci_writel,
 	.set_clock  = sdhci_set_clock,
Signature · 1 line
1.8.3.1
#38 lore raw

PATCH 29/32 mmc: sdhci: move regulator handling into sdhci_set_power()

In reply to Russell King - ARM Linux

Move the regulator handling into sdhci_set_power() rather than being in sdhci_do_set_ios(). This wraps all power control up into this function.

---
 drivers/mmc/host/sdhci.c | 72 +++++++++++++++++++++++-------------------------
 1 file changed, 35 insertions(+), 37 deletions(-)
drivers/mmc/host/sdhci.c +35 -37
index 02d43765ddd5..95604e09a00d 100644
@@ -1216,7 +1216,7 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 }
 EXPORT_SYMBOL_GPL(sdhci_set_clock);
 
-static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
+static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
 {
 	u8 pwr = 0;
 
@@ -1239,7 +1239,7 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
 	}
 
 	if (host->pwr == pwr)
-		return -1;
+		return;
 
 	host->pwr = pwr;
 
@@ -1247,38 +1247,43 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
 		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
 		if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
 			sdhci_runtime_pm_bus_off(host);
-		return 0;
-	}
-
-	/*
-	 * Spec says that we should clear the power reg before setting
-	 * a new value. Some controllers don't seem to like this though.
-	 */
-	if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
-		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
+		power = 0;
+	} else {
+		/*
+		 * Spec says that we should clear the power reg before setting
+		 * a new value. Some controllers don't seem to like this though.
+		 */
+		if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
+			sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
 
-	/*
-	 * At least the Marvell CaFe chip gets confused if we set the voltage
-	 * and set turn on power at the same time, so set the voltage first.
-	 */
-	if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
-		sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+		/*
+		 * At least the Marvell CaFe chip gets confused if we set the
+		 * voltage and set turn on power at the same time, so set the
+		 * voltage first.
+		 */
+		if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
+			sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
 
-	pwr |= SDHCI_POWER_ON;
+		pwr |= SDHCI_POWER_ON;
 
-	sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+		sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
 
-	if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
-		sdhci_runtime_pm_bus_on(host);
+		if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
+			sdhci_runtime_pm_bus_on(host);
 
-	/*
-	 * Some controllers need an extra 10ms delay of 10ms before they
-	 * can apply clock after applying power
-	 */
-	if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
-		mdelay(10);
+		/*
+		 * Some controllers need an extra 10ms delay of 10ms before
+		 * they can apply clock after applying power
+		 */
+		if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
+			mdelay(10);
+	}
 
-	return power;
+	if (host->vmmc) {
+		spin_unlock_irq(&host->lock);
+		mmc_regulator_set_ocr(host->mmc, host->vmmc, power);
+		spin_lock_irq(&host->lock);
+	}
 }
 
 /*****************************************************************************\
@@ -1428,7 +1433,6 @@ EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);
 static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 {
 	unsigned long flags;
-	int vdd_bit = -1;
 	u8 ctrl;
 
 	spin_lock_irqsave(&host->lock, flags);
@@ -1460,15 +1464,9 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 	}
 
 	if (ios->power_mode == MMC_POWER_OFF)
-		vdd_bit = sdhci_set_power(host, -1);
+		sdhci_set_power(host, -1);
 	else
-		vdd_bit = sdhci_set_power(host, ios->vdd);
-
-	if (host->vmmc && vdd_bit != -1) {
-		spin_unlock_irqrestore(&host->lock, flags);
-		mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd_bit);
-		spin_lock_irqsave(&host->lock, flags);
-	}
+		sdhci_set_power(host, ios->vdd);
 
 	if (host->ops->platform_send_init_74_clocks)
 		host->ops->platform_send_init_74_clocks(host, ios->power_mode);
Signature · 1 line
1.8.3.1
#39 lore raw

PATCH 30/32 mmc: sdhci: move remaining power handling into sdhci_set_power()

In reply to Russell King - ARM Linux

Move the remaining parts of the power handling in sdhci_do_set_ios() into sdhci_set_power().

---
 drivers/mmc/host/sdhci.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)
drivers/mmc/host/sdhci.c +7 -9
index 95604e09a00d..aad70ffa484e 100644
@@ -1216,12 +1216,13 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 }
 EXPORT_SYMBOL_GPL(sdhci_set_clock);
 
-static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
+static void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
+			    unsigned short vdd)
 {
 	u8 pwr = 0;
 
-	if (power != (unsigned short)-1) {
-		switch (1 << power) {
+	if (mode != MMC_POWER_OFF) {
+		switch (1 << vdd) {
 		case MMC_VDD_165_195:
 			pwr = SDHCI_POWER_180;
 			break;
@@ -1247,7 +1248,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
 		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
 		if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
 			sdhci_runtime_pm_bus_off(host);
-		power = 0;
+		vdd = 0;
 	} else {
 		/*
 		 * Spec says that we should clear the power reg before setting
@@ -1281,7 +1282,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
 
 	if (host->vmmc) {
 		spin_unlock_irq(&host->lock);
-		mmc_regulator_set_ocr(host->mmc, host->vmmc, power);
+		mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd);
 		spin_lock_irq(&host->lock);
 	}
 }
@@ -1463,10 +1464,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 		host->clock = ios->clock;
 	}
 
-	if (ios->power_mode == MMC_POWER_OFF)
-		sdhci_set_power(host, -1);
-	else
-		sdhci_set_power(host, ios->vdd);
+	sdhci_set_power(host, ios->power_mode, ios->vdd);
 
 	if (host->ops->platform_send_init_74_clocks)
 		host->ops->platform_send_init_74_clocks(host, ios->power_mode);
Signature · 1 line
1.8.3.1
#40 lore raw

PATCH 31/32 mmc: sdhci: track whether preset mode is currently enabled in hardware

In reply to Russell King - ARM Linux

Track whether preset mode is currently enabled in hardware, and use that when making decisions elsewhere in the code rather than reading the register and checking the bit.

---
 drivers/mmc/host/sdhci.c  | 44 ++++++++++++++++++++++++++------------------
 include/linux/mmc/sdhci.h |  1 +
 2 files changed, 27 insertions(+), 18 deletions(-)
drivers/mmc/host/sdhci.c +26 -18
index aad70ffa484e..a7dd667aaf95 100644
@@ -205,9 +205,14 @@ static void sdhci_do_reset(struct sdhci_host *host, u8 mask)
 
 	host->ops->reset(host, mask);
 
-	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
-		if ((host->ops->enable_dma) && (mask & SDHCI_RESET_ALL))
-			host->ops->enable_dma(host);
+	if (mask & SDHCI_RESET_ALL) {
+		if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
+			if (host->ops->enable_dma)
+				host->ops->enable_dma(host);
+		}
+
+		/* Resetting the controller clears many */
+		host->preset_enabled = false;
 	}
 }
 
@@ -1126,8 +1131,7 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 		return;
 
 	if (host->version >= SDHCI_SPEC_300) {
-		if (sdhci_readw(host, SDHCI_HOST_CONTROL2) &
-			SDHCI_CTRL_PRESET_VAL_ENABLE) {
+		if (host->preset_enabled) {
 			u16 pre_val;
 
 			clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
@@ -1491,13 +1495,13 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 		    (ios->timing == MMC_TIMING_UHS_SDR25))
 			ctrl |= SDHCI_CTRL_HISPD;
 
-		ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-		if (!(ctrl_2 & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
+		if (!host->preset_enabled) {
 			sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 			/*
 			 * We only need to set Driver Strength if the
 			 * preset value enable is not set.
 			 */
+			ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 			ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK;
 			if (ios->drv_type == MMC_SET_DRIVER_TYPE_A)
 				ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A;
@@ -2012,26 +2016,30 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 
 static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable)
 {
-	u16 ctrl;
-
 	/* Host Controller v3.00 defines preset value registers */
 	if (host->version < SDHCI_SPEC_300)
 		return;
 
-	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-
 	/*
 	 * We only enable or disable Preset Value if they are not already
 	 * enabled or disabled respectively. Otherwise, we bail out.
 	 */
-	if (enable && !(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
-		ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
-		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-		host->flags |= SDHCI_PV_ENABLED;
-	} else if (!enable && (ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
-		ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
+	if (host->preset_enabled != enable) {
+		u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+
+		if (enable)
+			ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
+		else
+			ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
+
 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-		host->flags &= ~SDHCI_PV_ENABLED;
+
+		if (enable)
+			host->flags |= SDHCI_PV_ENABLED;
+		else
+			host->flags &= ~SDHCI_PV_ENABLED;
+
+		host->preset_enabled = enable;
 	}
 }
 
include/linux/mmc/sdhci.h +1 -0
index 7f3efbab8732..08abe9941884 100644
@@ -143,6 +143,7 @@ struct sdhci_host {
 
 	bool runtime_suspended;	/* Host is runtime suspended */
 	bool bus_on;		/* Bus power prevents runtime suspend */
+	bool preset_enabled;	/* Preset is enabled */
 
 	struct mmc_request *mrq;	/* Current request */
 	struct mmc_command *cmd;	/* Current command */
Signature · 1 line
1.8.3.1
#41 lore raw

PATCH 32/32 mmc: sdhci: fix SDHCI dependencies

In reply to Russell King - ARM Linux
---
 drivers/mmc/host/Kconfig | 63 ++++++++++++++++++++++++------------------------
 1 file changed, 32 insertions(+), 31 deletions(-)
drivers/mmc/host/Kconfig +32 -31
index 8aaf8c1f3f63..d8c1f31ab37f 100644
@@ -25,8 +25,7 @@ config MMC_PXA
 	  If unsure, say N.
 
 config MMC_SDHCI
-	tristate "Secure Digital Host Controller Interface support"
-	depends on HAS_DMA
+	tristate
 	help
 	  This selects the generic Secure Digital Host Controller Interface.
 	  It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
@@ -59,7 +58,8 @@ config MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
 
 config MMC_SDHCI_PCI
 	tristate "SDHCI support on PCI bus"
-	depends on MMC_SDHCI && PCI
+	depends on PCI && HAS_DMA
+	select MMC_SDHCI
 	help
 	  This selects the PCI Secure Digital Host Controller Interface.
 	  Most controllers found today are PCI devices.
@@ -83,7 +83,8 @@ config MMC_RICOH_MMC
 
 config MMC_SDHCI_ACPI
 	tristate "SDHCI support for ACPI enumerated SDHCI controllers"
-	depends on MMC_SDHCI && ACPI
+	depends on ACPI && HAS_DMA
+	select MMC_SDHCI
 	help
 	  This selects support for ACPI enumerated SDHCI controllers,
 	  identified by ACPI Compatibility ID PNP0D40 or specific
@@ -94,8 +95,8 @@ config MMC_SDHCI_ACPI
 	  If unsure, say N.
 
 config MMC_SDHCI_PLTFM
-	tristate "SDHCI platform and OF driver helper"
-	depends on MMC_SDHCI
+	tristate
+	select MMC_SDHCI
 	help
 	  This selects the common helper functions support for Secure Digital
 	  Host Controller Interface based platform and OF drivers.
@@ -106,8 +107,8 @@ config MMC_SDHCI_PLTFM
 
 config MMC_SDHCI_OF_ARASAN
 	tristate "SDHCI OF support for the Arasan SDHCI controllers"
-	depends on MMC_SDHCI_PLTFM
-	depends on OF
+	depends on OF && HAS_DMA
+	select MMC_SDHCI_PLTFM
 	help
 	  This selects the Arasan Secure Digital Host Controller Interface
 	  (SDHCI). This hardware is found e.g. in Xilinx' Zynq SoC.
@@ -118,9 +119,9 @@ config MMC_SDHCI_OF_ARASAN
 
 config MMC_SDHCI_OF_ESDHC
 	tristate "SDHCI OF support for the Freescale eSDHC controller"
-	depends on MMC_SDHCI_PLTFM
-	depends on PPC_OF
+	depends on PPC_OF && HAS_DMA
 	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+	select MMC_SDHCI_PLTFM
 	help
 	  This selects the Freescale eSDHC controller support.
 
@@ -130,9 +131,9 @@ config MMC_SDHCI_OF_ESDHC
 
 config MMC_SDHCI_OF_HLWD
 	tristate "SDHCI OF support for the Nintendo Wii SDHCI controllers"
-	depends on MMC_SDHCI_PLTFM
-	depends on PPC_OF
+	depends on PPC_OF && HAS_DMA
 	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+	select MMC_SDHCI_PLTFM
 	help
 	  This selects the Secure Digital Host Controller Interface (SDHCI)
 	  found in the "Hollywood" chipset of the Nintendo Wii video game
@@ -144,8 +145,8 @@ config MMC_SDHCI_OF_HLWD
 
 config MMC_SDHCI_CNS3XXX
 	tristate "SDHCI support on the Cavium Networks CNS3xxx SoC"
-	depends on ARCH_CNS3XXX
-	depends on MMC_SDHCI_PLTFM
+	depends on ARCH_CNS3XXX && HAS_DMA
+	select MMC_SDHCI_PLTFM
 	help
 	  This selects the SDHCI support for CNS3xxx System-on-Chip devices.
 
@@ -155,9 +156,9 @@ config MMC_SDHCI_CNS3XXX
 
 config MMC_SDHCI_ESDHC_IMX
 	tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller"
-	depends on ARCH_MXC
-	depends on MMC_SDHCI_PLTFM
+	depends on ARCH_MXC && HAS_DMA
 	select MMC_SDHCI_IO_ACCESSORS
+	select MMC_SDHCI_PLTFM
 	help
 	  This selects the Freescale eSDHC/uSDHC controller support
 	  found on i.MX25, i.MX35 i.MX5x and i.MX6x.
@@ -168,9 +169,9 @@ config MMC_SDHCI_ESDHC_IMX
 
 config MMC_SDHCI_DOVE
 	tristate "SDHCI support on Marvell's Dove SoC"
-	depends on ARCH_DOVE
-	depends on MMC_SDHCI_PLTFM
+	depends on ARCH_DOVE && HAS_DMA
 	select MMC_SDHCI_IO_ACCESSORS
+	select MMC_SDHCI_PLTFM
 	help
 	  This selects the Secure Digital Host Controller Interface in
 	  Marvell's Dove SoC.
@@ -181,9 +182,9 @@ config MMC_SDHCI_DOVE
 
 config MMC_SDHCI_TEGRA
 	tristate "SDHCI platform support for the Tegra SD/MMC Controller"
-	depends on ARCH_TEGRA
-	depends on MMC_SDHCI_PLTFM
+	depends on ARCH_TEGRA && HAS_DMA
 	select MMC_SDHCI_IO_ACCESSORS
+	select MMC_SDHCI_PLTFM
 	help
 	  This selects the Tegra SD/MMC controller. If you have a Tegra
 	  platform with SD or MMC devices, say Y or M here.
@@ -192,7 +193,8 @@ config MMC_SDHCI_TEGRA
 
 config MMC_SDHCI_S3C
 	tristate "SDHCI support on Samsung S3C SoC"
-	depends on MMC_SDHCI && PLAT_SAMSUNG
+	depends on PLAT_SAMSUNG && HAS_DMA
+	select MMC_SDHCI
 	help
 	  This selects the Secure Digital Host Controller Interface (SDHCI)
 	  often referrered to as the HSMMC block in some of the Samsung S3C
@@ -204,8 +206,8 @@ config MMC_SDHCI_S3C
 
 config MMC_SDHCI_SIRF
 	tristate "SDHCI support on CSR SiRFprimaII and SiRFmarco SoCs"
-	depends on ARCH_SIRF
-	depends on MMC_SDHCI_PLTFM
+	depends on ARCH_SIRF && HAS_DMA
+	select MMC_SDHCI_PLTFM
 	help
 	  This selects the SDHCI support for SiRF System-on-Chip devices.
 
@@ -215,8 +217,7 @@ config MMC_SDHCI_SIRF
 
 config MMC_SDHCI_PXAV3
 	tristate "Marvell MMP2 SD Host Controller support (PXAV3)"
-	depends on CLKDEV_LOOKUP
-	select MMC_SDHCI
+	depends on CLKDEV_LOOKUP && HAS_DMA
 	select MMC_SDHCI_PLTFM
 	default CPU_MMP2
 	help
@@ -228,8 +229,7 @@ config MMC_SDHCI_PXAV3
 
 config MMC_SDHCI_PXAV2
 	tristate "Marvell PXA9XX SD Host Controller support (PXAV2)"
-	depends on CLKDEV_LOOKUP
-	select MMC_SDHCI
+	depends on CLKDEV_LOOKUP && HAS_DMA
 	select MMC_SDHCI_PLTFM
 	default CPU_PXA910
 	help
@@ -241,7 +241,8 @@ config MMC_SDHCI_PXAV2
 
 config MMC_SDHCI_SPEAR
 	tristate "SDHCI support on ST SPEAr platform"
-	depends on MMC_SDHCI && PLAT_SPEAR
+	depends on PLAT_SPEAR && HAS_DMA
+	select MMC_SDHCI
 	help
 	  This selects the Secure Digital Host Controller Interface (SDHCI)
 	  often referrered to as the HSMMC block in some of the ST SPEAR range
@@ -263,7 +264,7 @@ config MMC_SDHCI_S3C_DMA
 
 config MMC_SDHCI_BCM_KONA
 	tristate "SDHCI support on Broadcom KONA platform"
-	depends on ARCH_BCM_MOBILE
+	depends on ARCH_BCM_MOBILE && HAS_DMA
 	select MMC_SDHCI_PLTFM
 	help
 	  This selects the Broadcom Kona Secure Digital Host Controller
@@ -274,9 +275,9 @@ config MMC_SDHCI_BCM_KONA
 
 config MMC_SDHCI_BCM2835
 	tristate "SDHCI platform support for the BCM2835 SD/MMC Controller"
-	depends on ARCH_BCM2835
-	depends on MMC_SDHCI_PLTFM
+	depends on ARCH_BCM2835 && HAS_DMA
 	select MMC_SDHCI_IO_ACCESSORS
+	select MMC_SDHCI_PLTFM
 	help
 	  This selects the BCM2835 SD/MMC controller. If you have a BCM2835
 	  platform with SD or MMC devices, say Y or M here.
Signature · 1 line
1.8.3.1
#42 lore raw

PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1

In reply to Russell King - ARM Linux

Hi,

Quoted 21 lines · Russell King - ARM Linux
Quoted 20 lines · Russell King - ARM Linux
Quoted 6 lines · Markus Pargmann

I just tried the different parts of the patch. Without the following change, emmc works:

drivers/mmc/host/sdhci.c static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) · line 1515

Quoted 9 lines
drivers/mmc/host/sdhci.c +0 -6
@@ -1507,12 +1507,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 			host->ops->set_clock(host, host->clock);
 		}
 
-
-		/* Reset SD Clock Enable */
-		clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-		clk &= ~SDHCI_CLOCK_CARD_EN;
-		sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-

So the bit which stops us violating the SD spec stops eMMC from working... that's... just great.

Quoted 5 lines
Quoted 2 lines

Okay, I'll look deeper at this and see what can be done, but I suspect it will turn out to require more patches and be more invasive.

In the mean time, here's the remainder (to patch 33) of the series with this commit omitted.

I tested the whole series again, from 1 to patch 32 and it is working correctly now on the RIoT board (imx6s) with emmc and sd-card. You can add my tested-by tag for all core and imx related patches if you want to.

Regards,

Markus

Signature · 11 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140428/67e1f8c6/attachment.sig>
#43 lore raw

PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1

In reply to Russell King - ARM Linux
Quoted 20 lines · Russell King - ARM Linux
Quoted 6 lines · Markus Pargmann

I just tried the different parts of the patch. Without the following change, emmc works:

drivers/mmc/host/sdhci.c static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) · line 1515

Quoted 9 lines
drivers/mmc/host/sdhci.c +0 -6
@@ -1507,12 +1507,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 			host->ops->set_clock(host, host->clock);
 		}
 
-
-		/* Reset SD Clock Enable */
-		clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-		clk &= ~SDHCI_CLOCK_CARD_EN;
-		sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-

So the bit which stops us violating the SD spec stops eMMC from working... that's... just great.

Quoted 2 lines

Okay, I'll look deeper at this and see what can be done, but I suspect it will turn out to require more patches and be more invasive.

Well, I've given up trying to work out how to clean that mess up - sdhci will attempt to do all the high speed switching bollocks every time a set_ios call is made, turning the clock on and off multiple times in the process.

I've since replaced it with a patch covering just the last hunk of this patch and killed the other two changes there (and rewritten the description.)

I'm afraid that it looks like we're going to be stuck with turning the clock on and off multiple times during the transition to 1.8V signalling, which is technically against the SD spec. The spec'd procedure is:

- send command
- check card reports busy
- clock off
- switch to 1.8v signalling
- wait 5ms
- clock on
- wait 1ms
- check card reports non-busy

whereas what we end up doing is:

- send command
- check card reports busy
- clock off
- switch to 1.8v signalling, waiting 5 to 5.5ms
- wait 5ms
- clock on
- clock off
- tweak other settings
- clock on again
- wait 1ms
- check card reports non-busy

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#44 lore raw

PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1

In reply to Markus Pargmann
Quoted 11 lines · Markus Pargmann

Hi,

Quoted 5 lines · Russell King

Patch suggested by Dong Aisheng <[email protected]>, this avoids additional clock start/stop cycles during the transition to 1.8V signalling mode.

I tested the series on imx6s with a RIoT board. With this patch applied the RIoT board emmc does not work. Here is the output of the board:

Hi Markus,

Thanks for helping out testing!

Does that mean patch 1->20 works fine for you? May I add your tested-by tag?

Kind regards
Ulf Hansson

Quoted 81 lines
# dmesg | grep mmc2
mmc2: no vqmmc regulator found
mmc2: no vmmc regulator found
mmc2: SDHCI controller on 219c000.usdhc [219c000.usdhc] using ADMA
mmc2: BKOPS_EN bit is not set
mmc2: Timeout waiting for hardware interrupt.
mmc2: Timeout waiting for hardware interrupt.
mmc2: Timeout waiting for hardware interrupt.
mmc2: Timeout waiting for hardware interrupt.
mmc2: error -110 whilst initialising MMC card
mmc2: BKOPS_EN bit is not set
mmc2: Timeout waiting for hardware interrupt.
mmc2: Timeout waiting for hardware interrupt.
mmc2: Timeout waiting for hardware interrupt.
mmc2: Timeout waiting for hardware interrupt.
mmc2: error -110 whilst initialising MMC card
mmc2: BKOPS_EN bit is not set

Any ideas?

Regards,

Markus

Quoted 45 lines
---
 drivers/mmc/host/sdhci.c | 12 ------------
 1 file changed, 12 deletions(-)
drivers/mmc/host/sdhci.c +0 -13
index 748333ba6e96..0bcef2d42da4 100644
@@ -1507,12 +1507,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
                      host->ops->set_clock(host, host->clock);
              }
 
-
-             /* Reset SD Clock Enable */
-             clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-             clk &= ~SDHCI_CLOCK_CARD_EN;
-             sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-
              if (host->ops->set_uhs_signaling)
                      host->ops->set_uhs_signaling(host, ios->timing);
              else {
@@ -1546,9 +1540,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
                      ios->drv_type = (preset & SDHCI_PRESET_DRV_MASK)
                              >> SDHCI_PRESET_DRV_SHIFT;
              }
-
-             /* Re-enable SD Clock */
-             host->ops->set_clock(host, host->clock);
      } else
              sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 
@@ -1757,9 +1748,6 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
              ctrl |= SDHCI_CTRL_VDD_180;
              sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
-             /* Wait for 5ms */
-             usleep_range(5000, 5500);
-
              /* 1.8V regulator output should be stable within 5 ms */
              ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
              if (ctrl & SDHCI_CTRL_VDD_180)
--

1.8.3.1

Quoted 5 lines

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

--

Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
#45 lore raw

PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1

Quoted 10 lines · Ulf Hansson
Quoted 9 lines · Markus Pargmann

Hi,

Quoted 5 lines · Russell King

Patch suggested by Dong Aisheng <[email protected]>, this avoids additional clock start/stop cycles during the transition to 1.8V signalling mode.

Quoted 8 lines
Quoted 2 lines

I tested the series on imx6s with a RIoT board. With this patch applied the RIoT board emmc does not work. Here is the output of the board:

Hi Markus,

Thanks for helping out testing!

Does that mean patch 1->20 works fine for you? May I add your tested-by tag?

Why should _you_ add someone elses tested-by tag to _my_ patches?

I still wonder whether you understood anything that I've already said to you about the handling of this patch set.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#46 lore raw

PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1

Quoted 16 lines · Russell King - ARM Linux
Quoted 15 lines · Ulf Hansson
Quoted 11 lines · Markus Pargmann

Hi,

Quoted 5 lines · Russell King

Patch suggested by Dong Aisheng <[email protected]>, this avoids additional clock start/stop cycles during the transition to 1.8V signalling mode.

I tested the series on imx6s with a RIoT board. With this patch applied the RIoT board emmc does not work. Here is the output of the board:

Hi Markus,

Quoted 8 lines
Quoted 3 lines

Thanks for helping out testing!

Does that mean patch 1->20 works fine for you? May I add your tested-by tag?

Why should _you_ add someone elses tested-by tag to _my_ patches?

I still wonder whether you understood anything that I've already said to you about the handling of this patch set.

That was based upon that _I_ would help out in creating the pull request to Chris, to minimize his effort in resolving conflicts.

All-right, I back off - I was just trying to help here. Please send the pull request to Chris directly instead.

Kind regards
Ulf Hansson

Quoted 4 lines

--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.

#47 lore raw

PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1

Quoted 23 lines · Ulf Hansson
Quoted 22 lines · Russell King - ARM Linux
Quoted 10 lines · Ulf Hansson
Quoted 9 lines · Markus Pargmann

Hi,

Quoted 5 lines · Russell King

Patch suggested by Dong Aisheng <[email protected]>, this avoids additional clock start/stop cycles during the transition to 1.8V signalling mode.

Quoted 8 lines
Quoted 2 lines

I tested the series on imx6s with a RIoT board. With this patch applied the RIoT board emmc does not work. Here is the output of the board:

Hi Markus,

Thanks for helping out testing!

Does that mean patch 1->20 works fine for you? May I add your tested-by tag?

Why should _you_ add someone elses tested-by tag to _my_ patches?

Quoted 8 lines
Quoted 2 lines

I still wonder whether you understood anything that I've already said to you about the handling of this patch set.

That was based upon that _I_ would help out in creating the pull request to Chris, to minimize his effort in resolving conflicts.

All-right, I back off - I was just trying to help here. Please send the pull request to Chris directly instead.

I thought I clearly explained the logistics in a previous mail:

| I /could/ rebase it but then I wouldn't be able to produce the patch
| sets/patches for others [*] (such as the Novena project) to derive
| their kernel tree from my iMX6 patch set.
| 
| What I'd prefer is to keep the patch set intact, and provide Chris
| with a pull request for it up to patch 33, which would need a
| conflict fixed - and this would mean that I can be sure that what
| I'm testing, and what I'm distributing is what Chris will also be
| submitting.

One of the problems with your approaches is that the commit IDs for the patches I'm carrying become different from the commit IDs which will end up being merged, which then means I have to either silently drop _my_ commits and hope that they've been merged intact, or I have to manually diff each patch and compare it with what's merged, or I have to rebase my patch set on top of what's merged and hope that git spots that the patches are already applied (which it won't do if there's other changes on top of them which make it non-obvious to git that they're applied.)

To put it another way, recommitting these changes makes /more/ work for me in the long run because of how git works.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#48 lore raw

PATCH 22/38 mmc: sdhci: set_uhs_signaling() need not return a value

In reply to Russell King - ARM Linux

The set_uhs_signaling() method gives the impression that it can fail, but anything returned from the method is entirely ignored by the sdhci driver. So returning failure has no effect.

So, kill the idea that it's possible for this to return an error by removing the returned value.

---
 drivers/mmc/host/sdhci-esdhc-imx.c | 4 ++--
 drivers/mmc/host/sdhci-pxav3.c     | 4 +---
 drivers/mmc/host/sdhci.h           | 2 +-
 3 files changed, 4 insertions(+), 6 deletions(-)
drivers/mmc/host/sdhci-esdhc-imx.c +2 -2
index dfed2c37ab3f..72e0581e564f 100644
@@ -841,7 +841,7 @@ static int esdhc_change_pinstate(struct sdhci_host *host,
 	return pinctrl_select_state(imx_data->pinctrl, pinctrl);
 }
 
-static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
+static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
@@ -879,7 +879,7 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 		break;
 	}
 
-	return esdhc_change_pinstate(host, uhs);
+	esdhc_change_pinstate(host, uhs);
 }
 
 static void esdhc_reset(struct sdhci_host *host, u8 mask)
drivers/mmc/host/sdhci-pxav3.c +1 -3
index 8a40e079a57e..05574104a254 100644
@@ -186,7 +186,7 @@ static void pxav3_gen_init_74_clocks(struct sdhci_host *host, u8 power_mode)
 	pxa->power_mode = power_mode;
 }
 
-static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
+static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 {
 	u16 ctrl_2;
 
@@ -220,8 +220,6 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 	dev_dbg(mmc_dev(host->mmc),
 		"%s uhs = %d, ctrl_2 = %04X\n",
 		__func__, uhs, ctrl_2);
-
-	return 0;
 }
 
 static const struct sdhci_ops pxav3_sdhci_ops = {
drivers/mmc/host/sdhci.h +1 -1
index ac20195f667b..3179a8053019 100644
@@ -287,7 +287,7 @@ struct sdhci_ops {
 	unsigned int    (*get_ro)(struct sdhci_host *host);
 	void		(*reset)(struct sdhci_host *host, u8 mask);
 	int	(*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
-	int	(*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
+	void	(*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
 	void	(*hw_reset)(struct sdhci_host *host);
 	void	(*platform_suspend)(struct sdhci_host *host);
 	void	(*platform_resume)(struct sdhci_host *host);
Signature · 1 line
1.8.3.1
#49 lore raw

PATCH 23/38 mmc: sdhci: convert sdhci_set_uhs_signaling() into a library function

In reply to Russell King - ARM Linux

Add sdhci_set_uhs_signaling() and always call the set_uhs_signaling method. This avoids quirks being added into sdhci_set_uhs_signaling().

---
 drivers/mmc/host/sdhci-acpi.c      |  2 ++
 drivers/mmc/host/sdhci-bcm-kona.c  |  1 +
 drivers/mmc/host/sdhci-bcm2835.c   |  1 +
 drivers/mmc/host/sdhci-cns3xxx.c   |  1 +
 drivers/mmc/host/sdhci-dove.c      |  1 +
 drivers/mmc/host/sdhci-of-arasan.c |  1 +
 drivers/mmc/host/sdhci-of-esdhc.c  |  1 +
 drivers/mmc/host/sdhci-of-hlwd.c   |  1 +
 drivers/mmc/host/sdhci-pci.c       |  1 +
 drivers/mmc/host/sdhci-pltfm.c     |  1 +
 drivers/mmc/host/sdhci-pxav2.c     |  1 +
 drivers/mmc/host/sdhci-pxav3.c     |  1 +
 drivers/mmc/host/sdhci-s3c.c       |  1 +
 drivers/mmc/host/sdhci-sirf.c      |  1 +
 drivers/mmc/host/sdhci-spear.c     |  1 +
 drivers/mmc/host/sdhci-tegra.c     |  1 +
 drivers/mmc/host/sdhci.c           | 42 +++++++++++++++++++++-----------------
 drivers/mmc/host/sdhci.h           |  1 +
 18 files changed, 41 insertions(+), 19 deletions(-)
drivers/mmc/host/sdhci-acpi.c +2 -0
index 323e2a688563..8ce3c28cb76e 100644
@@ -106,6 +106,7 @@ static const struct sdhci_ops sdhci_acpi_ops_dflt = {
 	.enable_dma = sdhci_acpi_enable_dma,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static const struct sdhci_ops sdhci_acpi_ops_int = {
@@ -113,6 +114,7 @@ static const struct sdhci_ops sdhci_acpi_ops_int = {
 	.enable_dma = sdhci_acpi_enable_dma,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 	.hw_reset   = sdhci_acpi_int_hw_reset,
 };
 
drivers/mmc/host/sdhci-bcm-kona.c +1 -0
index e610811c09b0..dd780c315a63 100644
@@ -212,6 +212,7 @@ static struct sdhci_ops sdhci_bcm_kona_ops = {
 	.platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 	.card_event = sdhci_bcm_kona_card_event,
 };
 
drivers/mmc/host/sdhci-bcm2835.c +1 -0
index 74906d6008e1..46af9a439d7b 100644
@@ -136,6 +136,7 @@ static const struct sdhci_ops bcm2835_sdhci_ops = {
 	.get_min_clock = bcm2835_sdhci_get_min_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
drivers/mmc/host/sdhci-cns3xxx.c +1 -0
index 587d73ef33ff..14b74075589a 100644
@@ -81,6 +81,7 @@ static const struct sdhci_ops sdhci_cns3xxx_ops = {
 	.set_clock	= sdhci_cns3xxx_set_clock,
 	.set_bus_width	= sdhci_set_bus_width,
 	.reset          = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
drivers/mmc/host/sdhci-dove.c +1 -0
index 8ef4ab52f8e0..0d315f4496c8 100644
@@ -89,6 +89,7 @@ static const struct sdhci_ops sdhci_dove_ops = {
 	.set_clock = sdhci_set_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static const struct sdhci_pltfm_data sdhci_dove_pdata = {
drivers/mmc/host/sdhci-of-arasan.c +1 -0
index f0ee594f25d1..5bd1092310f2 100644
@@ -57,6 +57,7 @@ static struct sdhci_ops sdhci_arasan_ops = {
 	.get_timeout_clock = sdhci_arasan_get_timeout_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static struct sdhci_pltfm_data sdhci_arasan_pdata = {
drivers/mmc/host/sdhci-of-esdhc.c +1 -0
index c4f8cd3f83c8..fcaeae5f55b8 100644
@@ -309,6 +309,7 @@ static const struct sdhci_ops sdhci_esdhc_ops = {
 	.adma_workaround = esdhci_of_adma_workaround,
 	.set_bus_width = esdhc_pltfm_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
drivers/mmc/host/sdhci-of-hlwd.c +1 -0
index a4a1f0f2c0a0..b341661369a2 100644
@@ -61,6 +61,7 @@ static const struct sdhci_ops sdhci_hlwd_ops = {
 	.set_clock = sdhci_set_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static const struct sdhci_pltfm_data sdhci_hlwd_pdata = {
drivers/mmc/host/sdhci-pci.c +1 -0
index b3a28f6b170e..52c42fcc284c 100644
@@ -1082,6 +1082,7 @@ static const struct sdhci_ops sdhci_pci_ops = {
 	.enable_dma	= sdhci_pci_enable_dma,
 	.set_bus_width	= sdhci_pci_set_bus_width,
 	.reset		= sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 	.hw_reset		= sdhci_pci_hw_reset,
 };
 
drivers/mmc/host/sdhci-pltfm.c +1 -0
index 1fb89f44bd58..7e834fb78f42 100644
@@ -48,6 +48,7 @@ static const struct sdhci_ops sdhci_pltfm_ops = {
 	.set_clock = sdhci_set_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 #ifdef CONFIG_OF
drivers/mmc/host/sdhci-pxav2.c +1 -0
index db5257bf032e..3c0f3c0a1cc8 100644
@@ -116,6 +116,7 @@ static const struct sdhci_ops pxav2_sdhci_ops = {
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 	.set_bus_width = pxav2_mmc_set_bus_width,
 	.reset         = pxav2_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 #ifdef CONFIG_OF
drivers/mmc/host/sdhci-pxav3.c +1 -0
index 05574104a254..f4f128947561 100644
@@ -229,6 +229,7 @@ static const struct sdhci_ops pxav3_sdhci_ops = {
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = pxav3_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static struct sdhci_pltfm_data sdhci_pxav3_pdata = {
drivers/mmc/host/sdhci-s3c.c +1 -0
index 0ac075dfd844..76d7c12d8ef9 100644
@@ -374,6 +374,7 @@ static struct sdhci_ops sdhci_s3c_ops = {
 	.get_min_clock		= sdhci_s3c_get_min_clock,
 	.set_bus_width		= sdhci_s3c_set_bus_width,
 	.reset			= sdhci_reset,
+	.set_uhs_signaling	= sdhci_set_uhs_signaling,
 };
 
 static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
drivers/mmc/host/sdhci-sirf.c +1 -0
index 3b775348b470..17004531d089 100644
@@ -32,6 +32,7 @@ static struct sdhci_ops sdhci_sirf_ops = {
 	.get_max_clock	= sdhci_sirf_get_max_clk,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static struct sdhci_pltfm_data sdhci_sirf_pdata = {
drivers/mmc/host/sdhci-spear.c +1 -0
index 8bf64ab36720..9d535c7336ef 100644
@@ -41,6 +41,7 @@ static const struct sdhci_ops sdhci_pltfm_ops = {
 	.set_clock = sdhci_set_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 #ifdef CONFIG_OF
drivers/mmc/host/sdhci-tegra.c +1 -0
index a0a8b5cc3b0c..d06b6ff60432 100644
@@ -156,6 +156,7 @@ static const struct sdhci_ops tegra_sdhci_ops = {
 	.set_clock  = sdhci_set_clock,
 	.set_bus_width = tegra_sdhci_set_bus_width,
 	.reset      = tegra_sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {
drivers/mmc/host/sdhci.c +23 -19

54 lines not on this page · raw message

drivers/mmc/host/sdhci.h +1 -0
index 3179a8053019..7a35395e5f56 100644
@@ -403,6 +403,7 @@ static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host)
 void sdhci_set_clock(struct sdhci_host *host, unsigned int clock);
 void sdhci_set_bus_width(struct sdhci_host *host, int width);
 void sdhci_reset(struct sdhci_host *host, u8 mask);
+void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing);
 
 #ifdef CONFIG_PM
 extern int sdhci_suspend_host(struct sdhci_host *host);
Signature · 1 line
1.8.3.1
#50 lore raw

PATCH 23/38 mmc: sdhci: convert sdhci_set_uhs_signaling() into a library function

Quoted 17 lines · Russell King
drivers/mmc/host/sdhci.c +0 -13
@@ -1507,25 +1529,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 			host->ops->set_clock(host, host->clock);
 		}
 
-		if (host->ops->set_uhs_signaling)
-			host->ops->set_uhs_signaling(host, ios->timing);
-		else {
-			ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-			/* Select Bus Speed Mode for host */
-			ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
-			if ((ios->timing == MMC_TIMING_MMC_HS200) ||
-			    (ios->timing == MMC_TIMING_UHS_SDR104))
-				ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
-			else if (ios->timing == MMC_TIMING_UHS_SDR12)
-				ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
-			else if (ios->timing == MMC_TIMING_UHS_SDR25)
-				ctrl_2 |= SDHCI_CTRL_UHS_SDR25;

drivers/mmc/host/sdhci.c static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) · line 1535

Quoted 10 lines
drivers/mmc/host/sdhci.c +1 -6
-			else if (ios->timing == MMC_TIMING_UHS_SDR50)
-				ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
-			else if (ios->timing == MMC_TIMING_UHS_DDR50)
-				ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
-			sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
-		}
+		host->ops->set_uhs_signaling(host, ios->timing);
 
 		if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) &&
 				((ios->timing == MMC_TIMING_UHS_SDR12) ||

Whoever decided to poorly pick these patches up against my will has slightly messed this patch up - whereas my original patch left the code correctly formatted, when whoever applied this patch did so, they left an additional blank line in the above.

The other thing I'd ask is that the MMC people learn C precedence rules, and realise that it's not necessary (and actively harmful) to add additional parenthesis around simple if() conditions. Testing for timing being one of two values does not need anything more than one set of parenthesis - it does not need if ((a == b) || (a == c)) - if (a == b || a == c) does just fine, and is less confusing when encountering more complex statements, such as:

	if ((((a == b) || (a == c)) && ((d > a) || (d < c))) || (z == f))

compared with:

	if (((a == b || a == c) && (d > a || d < c)) || z == f)

With the former "style", I normally end up having to pull the file into the editor, and rewrite the damned statement to work out what the grouping is, because the excessive use of parenthesis is detrimental to readability. Don't do it. Learn the C precedence rules and keep code readable.

Signature · 2 lines
FTTC broadband for 0.8mile line: [email protected] down 460kbps up... slowly
improving, and getting towards what was expected from it.
#51 lore raw

PATCH 23/38 mmc: sdhci: convert sdhci_set_uhs_signaling() into a library function

Quoted 26 lines · Russell King - ARM Linux
Quoted 25 lines · Russell King
drivers/mmc/host/sdhci.c +1 -19
@@ -1507,25 +1529,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
                      host->ops->set_clock(host, host->clock);
              }
 
-             if (host->ops->set_uhs_signaling)
-                     host->ops->set_uhs_signaling(host, ios->timing);
-             else {
-                     ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-                     /* Select Bus Speed Mode for host */
-                     ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
-                     if ((ios->timing == MMC_TIMING_MMC_HS200) ||
-                         (ios->timing == MMC_TIMING_UHS_SDR104))
-                             ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
-                     else if (ios->timing == MMC_TIMING_UHS_SDR12)
-                             ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
-                     else if (ios->timing == MMC_TIMING_UHS_SDR25)
-                             ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
-                     else if (ios->timing == MMC_TIMING_UHS_SDR50)
-                             ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
-                     else if (ios->timing == MMC_TIMING_UHS_DDR50)
-                             ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
-                     sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
-             }
+             host->ops->set_uhs_signaling(host, ios->timing);
 
Quoted 7 lines

drivers/mmc/host/sdhci.c static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) · line 1535

Quoted 2 lines
drivers/mmc/host/sdhci.c +0 -0
              if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) &&
                              ((ios->timing == MMC_TIMING_UHS_SDR12) ||

Whoever decided to poorly pick these patches up against my will has slightly messed this patch up - whereas my original patch left the code correctly formatted, when whoever applied this patch did so, they left an additional blank line in the above.

Hi Russell,

We kindly pinged you several times asking for your state and for the PR, but I suppose you were just too busy. Your PR were kind of blocking patches for sdhci, if you remember.

Anyway, we did get some folks to test the patches and was thus fairly confident that we could merge them. Chris asked me to try to collect them in a PR for him, so I did. Sorry if I managed to screw some things up, there were several conflicts and actual regressions, which I tried to take care of.

The mmc people were also very helping in sending patches to fixup related regressions, immediately after we merged your patchset. Thus together I think we managed to pull it off.

Quoted 13 lines

The other thing I'd ask is that the MMC people learn C precedence rules, and realise that it's not necessary (and actively harmful) to add additional parenthesis around simple if() conditions. Testing for timing being one of two values does not need anything more than one set of parenthesis - it does not need if ((a == b) || (a == c)) - if (a == b || a == c) does just fine, and is less confusing when encountering more complex statements, such as:

        if ((((a == b) || (a == c)) && ((d > a) || (d < c))) || (z == f))

compared with:

Quoted 7 lines
        if (((a == b || a == c) && (d > a || d < c)) || z == f)

With the former "style", I normally end up having to pull the file into the editor, and rewrite the damned statement to work out what the grouping is, because the excessive use of parenthesis is detrimental to readability. Don't do it. Learn the C precedence rules and keep code readable.

Sure, we will adopt.

Please, feel free to send a patch to fixup my misstake. I will happily apply it.

Kind regards
Ulf Hansson

#52 lore raw

PATCH 23/38 mmc: sdhci: convert sdhci_set_uhs_signaling() into a library function

Quoted 35 lines · Ulf Hansson
Quoted 33 lines · Russell King - ARM Linux
Quoted 17 lines · Russell King
drivers/mmc/host/sdhci.c +0 -13
@@ -1507,25 +1529,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
                      host->ops->set_clock(host, host->clock);
              }
 
-             if (host->ops->set_uhs_signaling)
-                     host->ops->set_uhs_signaling(host, ios->timing);
-             else {
-                     ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-                     /* Select Bus Speed Mode for host */
-                     ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
-                     if ((ios->timing == MMC_TIMING_MMC_HS200) ||
-                         (ios->timing == MMC_TIMING_UHS_SDR104))
-                             ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
-                     else if (ios->timing == MMC_TIMING_UHS_SDR12)
-                             ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
-                     else if (ios->timing == MMC_TIMING_UHS_SDR25)
-                             ctrl_2 |= SDHCI_CTRL_UHS_SDR25;

drivers/mmc/host/sdhci.c static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) · line 1535

Quoted 10 lines
drivers/mmc/host/sdhci.c +1 -6
-                     else if (ios->timing == MMC_TIMING_UHS_SDR50)
-                             ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
-                     else if (ios->timing == MMC_TIMING_UHS_DDR50)
-                             ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
-                     sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
-             }
+             host->ops->set_uhs_signaling(host, ios->timing);
 
              if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) &&
                              ((ios->timing == MMC_TIMING_UHS_SDR12) ||

Whoever decided to poorly pick these patches up against my will has slightly messed this patch up - whereas my original patch left the code correctly formatted, when whoever applied this patch did so, they left an additional blank line in the above.

[snip]

Quoted 1 line

Please, feel free to send a patch to fixup my misstake. I will happily apply it.

I had a second look to fix it up myself, but I just can't find that your patch was different than the one I applied (beside the conflict I resolved).

If you do find any other issue regarding the patches in this patchset
- please let me know and I will try to help.

Kind regards
Uffe

#53 lore raw

PATCH 23/38 mmc: sdhci: convert sdhci_set_uhs_signaling() into a library function

In reply to Ulf Hansson
Quoted 35 lines · Ulf Hansson
Quoted 26 lines · Russell King - ARM Linux
Quoted 25 lines · Russell King
drivers/mmc/host/sdhci.c +1 -19
@@ -1507,25 +1529,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
                      host->ops->set_clock(host, host->clock);
              }
 
-             if (host->ops->set_uhs_signaling)
-                     host->ops->set_uhs_signaling(host, ios->timing);
-             else {
-                     ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-                     /* Select Bus Speed Mode for host */
-                     ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
-                     if ((ios->timing == MMC_TIMING_MMC_HS200) ||
-                         (ios->timing == MMC_TIMING_UHS_SDR104))
-                             ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
-                     else if (ios->timing == MMC_TIMING_UHS_SDR12)
-                             ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
-                     else if (ios->timing == MMC_TIMING_UHS_SDR25)
-                             ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
-                     else if (ios->timing == MMC_TIMING_UHS_SDR50)
-                             ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
-                     else if (ios->timing == MMC_TIMING_UHS_DDR50)
-                             ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
-                     sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
-             }
+             host->ops->set_uhs_signaling(host, ios->timing);
 
Quoted 7 lines

drivers/mmc/host/sdhci.c static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) · line 1535

Quoted 2 lines
drivers/mmc/host/sdhci.c +0 -0
              if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) &&
                              ((ios->timing == MMC_TIMING_UHS_SDR12) ||

Whoever decided to poorly pick these patches up against my will has slightly messed this patch up - whereas my original patch left the code correctly formatted, when whoever applied this patch did so, they left an additional blank line in the above.

Quoted 5 lines

Hi Russell,

We kindly pinged you several times asking for your state and for the PR, but I suppose you were just too busy. Your PR were kind of blocking patches for sdhci, if you remember.

I wasn't "too busy". I had walked away from all kernel maintanence in disgust at the way many in the ARM community ignores questions, and ignores patches which need testing - I'm talking there about the L2C patch series which was extremely poorly tested, and still, to this day, has questions outstanding. Yes, the code now produces warnings. It produces warnings /because/ people were not willing to help.

Those warnings serve as a reminder that there's still problems which need solving there, and they're not going to go away until those problems are solved.

While I don't like pushing unfinished code into mainline, in this case, others deemed the patch set too important _not_ to go into mainline even with these problems.

Now, it's been /soo/ long since I worked on that patch set that my knowledge has now diminished... so it's now going to be _much_ harder to resolve those issues than it would have been three months ago.

And I'm also holding a grudge, and I bear grudges for a long time, so expect me to be "difficult" towards Linux stuff for a while yet.

Quoted 3 lines

The mmc people were also very helping in sending patches to fixup related regressions, immediately after we merged your patchset. Thus together I think we managed to pull it off.

The formatting problem I refer to above is line 1532/1533 in sdhci.c - there's an additional blank line which somehow got left behind, caused presumably by insufficient attention paid to cleaning up a conflict between my original patches and the state of the tree they were applied to.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#54 lore raw

PATCH 23/38 mmc: sdhci: convert sdhci_set_uhs_signaling() into a library function

In reply to Ulf Hansson
Quoted 9 lines · Ulf Hansson

Anyway, we did get some folks to test the patches and was thus fairly confident that we could merge them. Chris asked me to try to collect them in a PR for him, so I did. Sorry if I managed to screw some things up, there were several conflicts and actual regressions, which I tried to take care of.

The mmc people were also very helping in sending patches to fixup related regressions, immediately after we merged your patchset. Thus together I think we managed to pull it off.

I tend to look through slightly less rose-tinted glasses.

The fact is... there's loads of ARM platforms which now fail in Olof's build/boot testing, and they all seem to have a very similar pattern:

hummingboard:

[    1.149688] sdhci: Secure Digital Host Controller Interface driver
[    1.155901] sdhci: Copyright(c) Pierre Ossman
...
[    1.253630] Waiting for root device /dev/mmcblk0p2...
[   60.325469] imx-sdma 20ec000.sdma: firmware not found

~$off
# PYBOOT: Exception: timeout

jetson:

[    2.261355] Waiting for root device /dev/mmcblk0p1...

wandboard:

[    1.186870] sdhci: Secure Digital Host Controller Interface driver
[    1.193075] sdhci: Copyright(c) Pierre Ossman
...
[    1.291064] Waiting for root device /dev/mmcblk0p2...

Whether these are caused by the patch set or not is anyone's guess, because we (a) don't know what's causing these failures, and (b) my patch series was never tested on anything but iMX6.

I'm pretty certain that the hummingboard failure is not related to my series as that's one of the platforms I did test my series on.

There's more failures which look like possibly something in core MMC is rather screwed, as OMAP5 (which doesn't use SDHCI) is also failing at a similar point.

What these failures /do/ mean is that when I'm pushing my ARM for-next branch out, Olof's builder picks it up and runs a build across it, and the report returns a whole load of failures. A whole load of failures means that those platforms haven't tested my changes, which means the quality of testing is much lower than it should be.

With 26 passing and 15 failing, that's over 1/3 of platforms failing, which means 1/3 aren't getting tested.

This level of failure has been going on for quite a while now, and (afaik) it remains uninvestigated and undiagnosed. (This is one of the complaints I have about Olof's build/boot test system, much of the information about the build and boot is hidden away and unpublished, which makes it almost impossible for third parties to diagnose any problem there. I've given up looking at most of Olof's build/boot mails because of this - it's just not interesting to see the same abbreviated boot failure logs which give no useful information time and time again.)

We need to get on top of these failures and get them sorted.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#55 lore raw

PATCH 23/38 mmc: sdhci: convert sdhci_set_uhs_signaling() into a library function

Quoted 25 lines · Russell King - ARM Linux
Quoted 9 lines · Ulf Hansson

Anyway, we did get some folks to test the patches and was thus fairly confident that we could merge them. Chris asked me to try to collect them in a PR for him, so I did. Sorry if I managed to screw some things up, there were several conflicts and actual regressions, which I tried to take care of.

The mmc people were also very helping in sending patches to fixup related regressions, immediately after we merged your patchset. Thus together I think we managed to pull it off.

I tend to look through slightly less rose-tinted glasses.

The fact is... there's loads of ARM platforms which now fail in Olof's build/boot testing, and they all seem to have a very similar pattern:

hummingboard:

[    1.149688] sdhci: Secure Digital Host Controller Interface driver
[    1.155901] sdhci: Copyright(c) Pierre Ossman
...
[    1.253630] Waiting for root device /dev/mmcblk0p2...
[   60.325469] imx-sdma 20ec000.sdma: firmware not found

~$off
# PYBOOT: Exception: timeout

Quoted 8 lines

jetson:

[    2.261355] Waiting for root device /dev/mmcblk0p1...

wandboard:

[    1.186870] sdhci: Secure Digital Host Controller Interface driver
[    1.193075] sdhci: Copyright(c) Pierre Ossman
...
[    1.291064] Waiting for root device /dev/mmcblk0p2...

Any SDHCI failures in Linus' tree (but not linux-next) that occur only in multi_v7_defconfig are likely solved by:

http://lists.infradead.org/pipermail/linux-arm-kernel/2014-June/264012.html

[PATCH] ARM: multi_v7_defconfig: re-enable SDHCI drivers

Quoted 3 lines

Whether these are caused by the patch set or not is anyone's guess, because we (a) don't know what's causing these failures, and (b) my patch series was never tested on anything but iMX6.

I thought that I'd tested at least some of it on Tegra.

#56 lore raw

PATCH 23/38 mmc: sdhci: convert sdhci_set_uhs_signaling() into a library function

In reply to Russell King - ARM Linux
Quoted 54 lines · Russell King - ARM Linux
Quoted 9 lines · Ulf Hansson

Anyway, we did get some folks to test the patches and was thus fairly confident that we could merge them. Chris asked me to try to collect them in a PR for him, so I did. Sorry if I managed to screw some things up, there were several conflicts and actual regressions, which I tried to take care of.

The mmc people were also very helping in sending patches to fixup related regressions, immediately after we merged your patchset. Thus together I think we managed to pull it off.

I tend to look through slightly less rose-tinted glasses.

The fact is... there's loads of ARM platforms which now fail in Olof's build/boot testing, and they all seem to have a very similar pattern:

hummingboard:

[    1.149688] sdhci: Secure Digital Host Controller Interface driver
[    1.155901] sdhci: Copyright(c) Pierre Ossman
...
[    1.253630] Waiting for root device /dev/mmcblk0p2...
[   60.325469] imx-sdma 20ec000.sdma: firmware not found

~$off
# PYBOOT: Exception: timeout

jetson:

[    2.261355] Waiting for root device /dev/mmcblk0p1...

wandboard:

[    1.186870] sdhci: Secure Digital Host Controller Interface driver
[    1.193075] sdhci: Copyright(c) Pierre Ossman
...
[    1.291064] Waiting for root device /dev/mmcblk0p2...

Whether these are caused by the patch set or not is anyone's guess, because we (a) don't know what's causing these failures, and (b) my patch series was never tested on anything but iMX6.

I'm pretty certain that the hummingboard failure is not related to my series as that's one of the platforms I did test my series on.

There's more failures which look like possibly something in core MMC is rather screwed, as OMAP5 (which doesn't use SDHCI) is also failing at a similar point.

What these failures /do/ mean is that when I'm pushing my ARM for-next branch out, Olof's builder picks it up and runs a build across it, and the report returns a whole load of failures. A whole load of failures means that those platforms haven't tested my changes, which means the quality of testing is much lower than it should be.

With 26 passing and 15 failing, that's over 1/3 of platforms failing, which means 1/3 aren't getting tested.

Quoted 8 lines

This level of failure has been going on for quite a while now, and (afaik) it remains uninvestigated and undiagnosed. (This is one of the complaints I have about Olof's build/boot test system, much of the information about the build and boot is hidden away and unpublished, which makes it almost impossible for third parties to diagnose any problem there. I've given up looking at most of Olof's build/boot mails because of this - it's just not interesting to see the same abbreviated boot failure logs which give no useful information time and time again.)

Most of this is because I want to avoid sending huuuge emails out with the failures. I'll add a push of the full log to arm-soc.lixom.net and include a link to it in the emails, similar to how I do the build logs. I'll let you know when I've made that change.

-Olof

#57 lore raw

PATCH 24/38 mmc: sdhci: cache timing information locally

In reply to Russell King - ARM Linux

Rather than reading back the timing information from the registers, cache it locally. This allows implementations to translate the UHS timing by overriding the set_uhs_signaling() method as required without also having to emulate the SDHCI_HOST_CONTROL2 register.

---
 drivers/mmc/host/sdhci.c  | 23 ++++++++++++-----------
 include/linux/mmc/sdhci.h |  2 ++
 2 files changed, 14 insertions(+), 11 deletions(-)
drivers/mmc/host/sdhci.c +12 -11
index 1afed0ab338c..5f067a040ec4 100644
@@ -1083,24 +1083,23 @@ static void sdhci_finish_command(struct sdhci_host *host)
 
 static u16 sdhci_get_preset_value(struct sdhci_host *host)
 {
-	u16 ctrl, preset = 0;
+	u16 preset = 0;
 
-	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-
-	switch (ctrl & SDHCI_CTRL_UHS_MASK) {
-	case SDHCI_CTRL_UHS_SDR12:
+	switch (host->timing) {
+	case MMC_TIMING_UHS_SDR12:
 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12);
 		break;
-	case SDHCI_CTRL_UHS_SDR25:
+	case MMC_TIMING_UHS_SDR25:
 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR25);
 		break;
-	case SDHCI_CTRL_UHS_SDR50:
+	case MMC_TIMING_UHS_SDR50:
 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR50);
 		break;
-	case SDHCI_CTRL_UHS_SDR104:
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_MMC_HS200:
 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104);
 		break;
-	case SDHCI_CTRL_UHS_DDR50:
+	case MMC_TIMING_UHS_DDR50:
 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50);
 		break;
 	default:
@@ -1530,6 +1529,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 		}
 
 		host->ops->set_uhs_signaling(host, ios->timing);
+		host->timing = ios->timing;
 
 		if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) &&
 				((ios->timing == MMC_TIMING_UHS_SDR12) ||
@@ -1828,12 +1828,13 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 	 * If the Host Controller supports the HS200 mode then the
 	 * tuning function has to be executed.
 	 */
-	if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) &&
+	if (host->timing == MMC_TIMING_UHS_SDR50 &&
 	    (host->flags & SDHCI_SDR50_NEEDS_TUNING ||
 	     host->flags & SDHCI_SDR104_NEEDS_TUNING))
 		requires_tuning_nonuhs = true;
 
-	if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) ||
+	if (host->timing == MMC_TIMING_MMC_HS200 ||
+	    host->timing == MMC_TIMING_UHS_SDR104 ||
 	    requires_tuning_nonuhs)
 		ctrl |= SDHCI_CTRL_EXEC_TUNING;
 	else {
include/linux/mmc/sdhci.h +2 -0
index 72a90baf111f..7f3efbab8732 100644
@@ -172,6 +172,8 @@ struct sdhci_host {
 	unsigned int            ocr_avail_mmc;
 	u32 ocr_mask;		/* available voltages */
 
+	unsigned		timing;		/* Current timing */
+
 	u32			thread_isr;
 
 	/* cached registers */
Signature · 1 line
1.8.3.1
#58 lore raw

PATCH 25/38 mmc: sdhci: clean up sdhci_execute_tuning() decision

In reply to Russell King - ARM Linux

Clean up the code in sdhci_execute_tuning() so the decision whether to execute tuning is clearer - and despite this reflecting what the original code was doing, it shows that it may not be what the author actually intended.

---
 drivers/mmc/host/sdhci.c | 31 +++++++++++++++----------------
 1 file changed, 15 insertions(+), 16 deletions(-)
drivers/mmc/host/sdhci.c +15 -16
index 5f067a040ec4..c1bd77e17458 100644
@@ -1806,21 +1806,16 @@ static int sdhci_card_busy(struct mmc_host *mmc)
 
 static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
-	struct sdhci_host *host;
+	struct sdhci_host *host = mmc_priv(mmc);
 	u16 ctrl;
 	int tuning_loop_counter = MAX_TUNING_LOOP;
 	unsigned long timeout;
 	int err = 0;
-	bool requires_tuning_nonuhs = false;
 	unsigned long flags;
 
-	host = mmc_priv(mmc);
-
 	sdhci_runtime_pm_get(host);
 	spin_lock_irqsave(&host->lock, flags);
 
-	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-
 	/*
 	 * The Host Controller needs tuning only in case of SDR104 mode
 	 * and for SDR50 mode when Use Tuning for SDR50 is set in the
@@ -1828,16 +1823,18 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 	 * If the Host Controller supports the HS200 mode then the
 	 * tuning function has to be executed.
 	 */
-	if (host->timing == MMC_TIMING_UHS_SDR50 &&
-	    (host->flags & SDHCI_SDR50_NEEDS_TUNING ||
-	     host->flags & SDHCI_SDR104_NEEDS_TUNING))
-		requires_tuning_nonuhs = true;
-
-	if (host->timing == MMC_TIMING_MMC_HS200 ||
-	    host->timing == MMC_TIMING_UHS_SDR104 ||
-	    requires_tuning_nonuhs)
-		ctrl |= SDHCI_CTRL_EXEC_TUNING;
-	else {
+	switch (host->timing) {
+	case MMC_TIMING_MMC_HS200:
+	case MMC_TIMING_UHS_SDR104:
+		break;
+
+	case MMC_TIMING_UHS_SDR50:
+		if (host->flags & SDHCI_SDR50_NEEDS_TUNING ||
+		    host->flags & SDHCI_SDR104_NEEDS_TUNING)
+			break;
+		/* FALLTHROUGH */
+
+	default:
 		spin_unlock_irqrestore(&host->lock, flags);
 		sdhci_runtime_pm_put(host);
 		return 0;
@@ -1850,6 +1847,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 		return err;
 	}
 
+	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+	ctrl |= SDHCI_CTRL_EXEC_TUNING;
 	sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
 	/*
Signature · 1 line
1.8.3.1
#59 lore raw

PATCH 26/38 mmc: sdhci-esdhc-imx: remove emulation of uhs_mode

In reply to Russell King - ARM Linux

We no longer need to emulate the uhs_mode field of the host control2 register - the main sdhci driver never reads this back to evaluate the current mode as it caches the current mode instead.

---
 drivers/mmc/host/sdhci-esdhc-imx.c | 17 +++--------------
 1 file changed, 3 insertions(+), 14 deletions(-)
drivers/mmc/host/sdhci-esdhc-imx.c +3 -14
index 72e0581e564f..4866d802f9e2 100644
@@ -160,7 +160,6 @@ struct pltfm_imx_data {
 		MULTIBLK_IN_PROCESS, /* exact multiblock cmd in process */
 		WAIT_FOR_INT,        /* sent CMD12, waiting for response INT */
 	} multiblock_status;
-	u32 uhs_mode;
 	u32 is_ddr;
 };
 
@@ -382,7 +381,6 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
 		if (val & ESDHC_MIX_CTRL_SMPCLK_SEL)
 			ret |= SDHCI_CTRL_TUNED_CLK;
 
-		ret |= (imx_data->uhs_mode & SDHCI_CTRL_UHS_MASK);
 		ret &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
 
 		return ret;
@@ -429,7 +427,6 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 		else
 			new_val &= ~ESDHC_VENDOR_SPEC_VSELECT;
 		writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC);
-		imx_data->uhs_mode = val & SDHCI_CTRL_UHS_MASK;
 		if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
 			new_val = readl(host->ioaddr + ESDHC_MIX_CTRL);
 			if (val & SDHCI_CTRL_TUNED_CLK)
@@ -841,28 +838,20 @@ static int esdhc_change_pinstate(struct sdhci_host *host,
 	return pinctrl_select_state(imx_data->pinctrl, pinctrl);
 }
 
-static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
+static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
 	struct esdhc_platform_data *boarddata = &imx_data->boarddata;
 
-	switch (uhs) {
+	switch (timing) {
 	case MMC_TIMING_UHS_SDR12:
-		imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR12;
-		break;
 	case MMC_TIMING_UHS_SDR25:
-		imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR25;
-		break;
 	case MMC_TIMING_UHS_SDR50:
-		imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR50;
-		break;
 	case MMC_TIMING_UHS_SDR104:
 	case MMC_TIMING_MMC_HS200:
-		imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR104;
 		break;
 	case MMC_TIMING_UHS_DDR50:
-		imx_data->uhs_mode = SDHCI_CTRL_UHS_DDR50;
 		writel(readl(host->ioaddr + ESDHC_MIX_CTRL) |
 				ESDHC_MIX_CTRL_DDREN,
 				host->ioaddr + ESDHC_MIX_CTRL);
@@ -879,7 +868,7 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 		break;
 	}
 
-	esdhc_change_pinstate(host, uhs);
+	esdhc_change_pinstate(host, timing);
 }
 
 static void esdhc_reset(struct sdhci_host *host, u8 mask)
Signature · 1 line
1.8.3.1
#60 lore raw

PATCH 27/38 mmc: sdhci-of-esdhc: remove platform_suspend/platform_resume callbacks

In reply to Russell King - ARM Linux

We don't need these hooks in order to insert code in these paths, we can just provide our own handlers and call the main sdhci handlers as appropriate.

---
 drivers/mmc/host/sdhci-of-esdhc.c | 55 +++++++++++++++++++++++++--------------
 1 file changed, 36 insertions(+), 19 deletions(-)
drivers/mmc/host/sdhci-of-esdhc.c +36 -19
index fcaeae5f55b8..605815e52f5f 100644
@@ -241,20 +241,6 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
 	mdelay(1);
 }
 
-#ifdef CONFIG_PM
-static u32 esdhc_proctl;
-static void esdhc_of_suspend(struct sdhci_host *host)
-{
-	esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
-}
-
-static void esdhc_of_resume(struct sdhci_host *host)
-{
-	esdhc_of_enable_dma(host);
-	sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
-}
-#endif
-
 static void esdhc_of_platform_init(struct sdhci_host *host)
 {
 	u32 vvn;
@@ -302,16 +288,47 @@ static const struct sdhci_ops sdhci_esdhc_ops = {
 	.get_max_clock = esdhc_of_get_max_clock,
 	.get_min_clock = esdhc_of_get_min_clock,
 	.platform_init = esdhc_of_platform_init,
-#ifdef CONFIG_PM
-	.platform_suspend = esdhc_of_suspend,
-	.platform_resume = esdhc_of_resume,
-#endif
 	.adma_workaround = esdhci_of_adma_workaround,
 	.set_bus_width = esdhc_pltfm_set_bus_width,
 	.reset = sdhci_reset,
 	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
+#ifdef CONFIG_PM
+
+static u32 esdhc_proctl;
+static int esdhc_of_suspend(struct device *dev)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+
+	esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
+
+	return sdhci_suspend_host(host);
+}
+
+static void esdhc_of_resume(device *dev)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	int ret = sdhci_resume_host(host);
+
+	if (ret == 0) {
+		/* Isn't this already done by sdhci_resume_host() ? --rmk */
+		esdhc_of_enable_dma(host);
+		sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
+	}
+
+	return ret;
+}
+
+static const struct dev_pm_ops esdhc_pmops = {
+	.suspend	= esdhci_of_suspend,
+	.resume		= esdhci_of_resume,
+};
+#define ESDHC_PMOPS (&esdhc_pmops)
+#else
+#define ESDHC_PMOPS NULL
+#endif
+
 static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
 	/*
 	 * card detection could be handled via GPIO
@@ -373,7 +390,7 @@ static struct platform_driver sdhci_esdhc_driver = {
 		.name = "sdhci-esdhc",
 		.owner = THIS_MODULE,
 		.of_match_table = sdhci_esdhc_of_match,
-		.pm = SDHCI_PLTFM_PMOPS,
+		.pm = ESDHC_PMOPS,
 	},
 	.probe = sdhci_esdhc_probe,
 	.remove = sdhci_esdhc_remove,
Signature · 1 line
1.8.3.1
#61 lore raw

PATCH 27/38 mmc: sdhci-of-esdhc: remove platform_suspend/platform_resume callbacks

Quoted 39 lines · Russell King

We don't need these hooks in order to insert code in these paths, we can just provide our own handlers and call the main sdhci handlers as appropriate.

---
 drivers/mmc/host/sdhci-of-esdhc.c | 55 +++++++++++++++++++++++++--------------
 1 file changed, 36 insertions(+), 19 deletions(-)
drivers/mmc/host/sdhci-of-esdhc.c +0 -15
index fcaeae5f55b8..605815e52f5f 100644
@@ -241,20 +241,6 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
        mdelay(1);
 }
 
-#ifdef CONFIG_PM
-static u32 esdhc_proctl;
-static void esdhc_of_suspend(struct sdhci_host *host)
-{
-       esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
-}
-
-static void esdhc_of_resume(struct sdhci_host *host)
-{
-       esdhc_of_enable_dma(host);
-       sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
-}
-#endif
-
 static void esdhc_of_platform_init(struct sdhci_host *host)
 {
        u32 vvn;
@@ -302,16 +288,47 @@ static const struct sdhci_ops sdhci_esdhc_ops = {
        .get_max_clock = esdhc_of_get_max_clock,
        .get_min_clock = esdhc_of_get_min_clock,
        .platform_init = esdhc_of_platform_init,
-#ifdef CONFIG_PM

drivers/mmc/host/sdhci-of-esdhc.c static const struct sdhci_ops sdhci_esdhc_ops = { · line 297

Quoted 10 lines
drivers/mmc/host/sdhci-of-esdhc.c +1 -3
-       .platform_suspend = esdhc_of_suspend,
-       .platform_resume = esdhc_of_resume,
-#endif
        .adma_workaround = esdhci_of_adma_workaround,
        .set_bus_width = esdhc_pltfm_set_bus_width,
        .reset = sdhci_reset,
        .set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
+#ifdef CONFIG_PM

This should be CONFIG_PM_SLEEP

Quoted 24 lines
drivers/mmc/host/sdhci-of-esdhc.c +24 -0
+
+static u32 esdhc_proctl;
+static int esdhc_of_suspend(struct device *dev)
+{
+       struct sdhci_host *host = dev_get_drvdata(dev);
+
+       esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
+
+       return sdhci_suspend_host(host);
+}
+
+static void esdhc_of_resume(device *dev)
+{
+       struct sdhci_host *host = dev_get_drvdata(dev);
+       int ret = sdhci_resume_host(host);
+
+       if (ret == 0) {
+               /* Isn't this already done by sdhci_resume_host() ? --rmk */
+               esdhc_of_enable_dma(host);
+               sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
+       }
+
+       return ret;
+}

drivers/mmc/host/sdhci-of-esdhc.c static const struct sdhci_ops sdhci_esdhc_ops = { · line 331

Quoted 10 lines
drivers/mmc/host/sdhci-of-esdhc.c +10 -0
+
+static const struct dev_pm_ops esdhc_pmops = {
+       .suspend        = esdhci_of_suspend,
+       .resume         = esdhci_of_resume,
+};
+#define ESDHC_PMOPS (&esdhc_pmops)
+#else
+#define ESDHC_PMOPS NULL
+#endif
+

I would suggest to use the SIMPLE_DEV_PM_OPS macro to simplify code a bit.

Quoted 15 lines
drivers/mmc/host/sdhci-of-esdhc.c +1 -2
 static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
        /*
         * card detection could be handled via GPIO
@@ -373,7 +390,7 @@ static struct platform_driver sdhci_esdhc_driver = {
                .name = "sdhci-esdhc",
                .owner = THIS_MODULE,
                .of_match_table = sdhci_esdhc_of_match,
-               .pm = SDHCI_PLTFM_PMOPS,
+               .pm = ESDHC_PMOPS,
        },
        .probe = sdhci_esdhc_probe,
        .remove = sdhci_esdhc_remove,
--

1.8.3.1

Quoted 4 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

Kind regards
Ulf Hansson

#62 lore raw

PATCH 27/38 mmc: sdhci-of-esdhc: remove platform_suspend/platform_resume callbacks

Quoted 19 lines · Ulf Hansson
Quoted 18 lines · Russell King

We don't need these hooks in order to insert code in these paths, we can just provide our own handlers and call the main sdhci handlers as appropriate.

---
 drivers/mmc/host/sdhci-of-esdhc.c | 55 +++++++++++++++++++++++++--------------
 1 file changed, 36 insertions(+), 19 deletions(-)
drivers/mmc/host/sdhci-of-esdhc.c +0 -1
index fcaeae5f55b8..605815e52f5f 100644
@@ -241,20 +241,6 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
        mdelay(1);
 }
 
-#ifdef CONFIG_PM

...

Quoted 3 lines
Quoted 1 line

+#ifdef CONFIG_PM

This should be CONFIG_PM_SLEEP

That may be the case, but that would be an additional modification, and so should be a separate patch.

Quoted 29 lines
Quoted 29 lines
drivers/mmc/host/sdhci-of-esdhc.c +28 -0
+
+static u32 esdhc_proctl;
+static int esdhc_of_suspend(struct device *dev)
+{
+       struct sdhci_host *host = dev_get_drvdata(dev);
+
+       esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
+
+       return sdhci_suspend_host(host);
+}
+
+static void esdhc_of_resume(device *dev)
+{
+       struct sdhci_host *host = dev_get_drvdata(dev);
+       int ret = sdhci_resume_host(host);
+
+       if (ret == 0) {
+               /* Isn't this already done by sdhci_resume_host() ? --rmk */
+               esdhc_of_enable_dma(host);
+               sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
+       }
+
+       return ret;
+}
+
+static const struct dev_pm_ops esdhc_pmops = {
+       .suspend        = esdhci_of_suspend,
+       .resume         = esdhci_of_resume,
Quoted 8 lines

drivers/mmc/host/sdhci-of-esdhc.c static const struct sdhci_ops sdhci_esdhc_ops = { · line 331

Quoted 6 lines
drivers/mmc/host/sdhci-of-esdhc.c +6 -0
+};
+#define ESDHC_PMOPS (&esdhc_pmops)
+#else
+#define ESDHC_PMOPS NULL
+#endif
+

I would suggest to use the SIMPLE_DEV_PM_OPS macro to simplify code a bit.

That is dependent on changing the ifdef. As I say, that should be a separate patch - possibly one which comes before this one.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#63 lore raw

PATCH 27/38 mmc: sdhci-of-esdhc: remove platform_suspend/platform_resume callbacks

Quoted 19 lines · Russell King - ARM Linux
Quoted 18 lines · Ulf Hansson
Quoted 17 lines · Russell King

We don't need these hooks in order to insert code in these paths, we can just provide our own handlers and call the main sdhci handlers as appropriate.

---
 drivers/mmc/host/sdhci-of-esdhc.c | 55 +++++++++++++++++++++++++--------------
 1 file changed, 36 insertions(+), 19 deletions(-)
drivers/mmc/host/sdhci-of-esdhc.c +0 -0
index fcaeae5f55b8..605815e52f5f 100644
@@ -241,20 +241,6 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
        mdelay(1);
 }
 
Quoted 8 lines
Quoted 1 line
Quoted 1 line
drivers/mmc/host/sdhci-of-esdhc.c +0 -1
-#ifdef CONFIG_PM

...

Quoted 3 lines
Quoted 1 line

+#ifdef CONFIG_PM

This should be CONFIG_PM_SLEEP

That may be the case, but that would be an additional modification, and so should be a separate patch.

I just thought it make sense to include it here - it's really a simple fix, touching the same code as this patch.

Additionally, it would simplify this patch since you would be able to use the PM macro.

Quoted 38 lines
Quoted 29 lines
Quoted 29 lines
drivers/mmc/host/sdhci-of-esdhc.c +28 -0
+
+static u32 esdhc_proctl;
+static int esdhc_of_suspend(struct device *dev)
+{
+       struct sdhci_host *host = dev_get_drvdata(dev);
+
+       esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
+
+       return sdhci_suspend_host(host);
+}
+
+static void esdhc_of_resume(device *dev)
+{
+       struct sdhci_host *host = dev_get_drvdata(dev);
+       int ret = sdhci_resume_host(host);
+
+       if (ret == 0) {
+               /* Isn't this already done by sdhci_resume_host() ? --rmk */
+               esdhc_of_enable_dma(host);
+               sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
+       }
+
+       return ret;
+}
+
+static const struct dev_pm_ops esdhc_pmops = {
+       .suspend        = esdhci_of_suspend,
+       .resume         = esdhci_of_resume,
Quoted 8 lines

drivers/mmc/host/sdhci-of-esdhc.c static const struct sdhci_ops sdhci_esdhc_ops = { · line 331

Quoted 6 lines
drivers/mmc/host/sdhci-of-esdhc.c +6 -0
+};
+#define ESDHC_PMOPS (&esdhc_pmops)
+#else
+#define ESDHC_PMOPS NULL
+#endif
+

I would suggest to use the SIMPLE_DEV_PM_OPS macro to simplify code a bit.

Quoted 2 lines

That is dependent on changing the ifdef. As I say, that should be a separate patch - possibly one which comes before this one.

So, choose whatever option you prefer, if you would like another patch going before this one, I am fine with that. As long as we convert to use the macro, I am happy. :-)

Quoted 4 lines

--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.

#64 lore raw

PATCH 27/38 mmc: sdhci-of-esdhc: remove platform_suspend/platform_resume callbacks

Quoted 9 lines · Ulf Hansson
Quoted 2 lines · Russell King - ARM Linux

That may be the case, but that would be an additional modification, and so should be a separate patch.

I just thought it make sense to include it here - it's really a simple fix, touching the same code as this patch.

Additionally, it would simplify this patch since you would be able to use the PM macro.

No, I'm not going to make this change after looking deeper at the existing code.

The existing code does this:

sdhci-pltfm.c:
#ifdef CONFIG_PM
int sdhci_pltfm_suspend(struct device *dev)

{
        struct sdhci_host *host = dev_get_drvdata(dev);

        return sdhci_suspend_host(host);
}

EXPORT_SYMBOL_GPL(sdhci_pltfm_suspend);

int sdhci_pltfm_resume(struct device *dev)

{
        struct sdhci_host *host = dev_get_drvdata(dev);

        return sdhci_resume_host(host);
}

EXPORT_SYMBOL_GPL(sdhci_pltfm_resume);

const struct dev_pm_ops sdhci_pltfm_pmops = {
.suspend = sdhci_pltfm_suspend,
.resume = sdhci_pltfm_resume,
};
EXPORT_SYMBOL_GPL(sdhci_pltfm_pmops);
#endif /* CONFIG_PM */

sdhci-pltfm.h:
#ifdef CONFIG_PM
extern int sdhci_pltfm_suspend(struct device *dev); extern int sdhci_pltfm_resume(struct device *dev); extern const struct dev_pm_ops sdhci_pltfm_pmops; #define SDHCI_PLTFM_PMOPS (&sdhci_pltfm_pmops) #else
#define SDHCI_PLTFM_PMOPS NULL
#endif

sdhci-of-esdhc.c:
static struct platform_driver sdhci_esdhc_driver = {
.driver = {
.pm = SDHCI_PLTFM_PMOPS,

Changing this to use SIMPLE_DEV_PM_OPS changes the behaviour of this by placing the callbacks into the other methods.

Is that change correct?
Who's going to test that that change doesn't break anything (I don't have the hardware, and it's not a transformational change like the rest of the patch set, but a functional change)?
Should this change be made for other SDHCI platforms as well?

Frankly, I'm not happy to make such a change in a series which is supposed to be mainly about cleaning up and _not_ introducing functional changes.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#65 lore raw

PATCH 27/38 mmc: sdhci-of-esdhc: remove platform_suspend/platform_resume callbacks

Quoted 59 lines · Russell King - ARM Linux
Quoted 9 lines · Ulf Hansson
Quoted 2 lines · Russell King - ARM Linux

That may be the case, but that would be an additional modification, and so should be a separate patch.

I just thought it make sense to include it here - it's really a simple fix, touching the same code as this patch.

Additionally, it would simplify this patch since you would be able to use the PM macro.

No, I'm not going to make this change after looking deeper at the existing code.

The existing code does this:

sdhci-pltfm.c:
#ifdef CONFIG_PM
int sdhci_pltfm_suspend(struct device *dev)

{
        struct sdhci_host *host = dev_get_drvdata(dev);

        return sdhci_suspend_host(host);
}

EXPORT_SYMBOL_GPL(sdhci_pltfm_suspend);

int sdhci_pltfm_resume(struct device *dev)

{
        struct sdhci_host *host = dev_get_drvdata(dev);

        return sdhci_resume_host(host);
}

EXPORT_SYMBOL_GPL(sdhci_pltfm_resume);

const struct dev_pm_ops sdhci_pltfm_pmops = {
.suspend = sdhci_pltfm_suspend,
.resume = sdhci_pltfm_resume,
};
EXPORT_SYMBOL_GPL(sdhci_pltfm_pmops);
#endif /* CONFIG_PM */

sdhci-pltfm.h:
#ifdef CONFIG_PM
extern int sdhci_pltfm_suspend(struct device *dev); extern int sdhci_pltfm_resume(struct device *dev); extern const struct dev_pm_ops sdhci_pltfm_pmops; #define SDHCI_PLTFM_PMOPS (&sdhci_pltfm_pmops) #else
#define SDHCI_PLTFM_PMOPS NULL
#endif

sdhci-of-esdhc.c:
static struct platform_driver sdhci_esdhc_driver = {
.driver = {
.pm = SDHCI_PLTFM_PMOPS,

Changing this to use SIMPLE_DEV_PM_OPS changes the behaviour of this by placing the callbacks into the other methods.

Quoted 8 lines

Is that change correct?
Who's going to test that that change doesn't break anything (I don't have the hardware, and it's not a transformational change like the rest of the patch set, but a functional change)?
Should this change be made for other SDHCI platforms as well?

Frankly, I'm not happy to make such a change in a series which is supposed to be mainly about cleaning up and _not_ introducing functional changes.

Fair enough, let's keep it as is then and let's handle functional changes separate.

Quoted 4 lines

--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.

#66 lore raw

PATCH 28/38 mmc: sdhci: remove platform_suspend/platform_resume callbacks

In reply to Russell King - ARM Linux

The only user (sdhci-of-esdhc) no longer uses these callbacks, so lets remove them to discourage any further use.

---
 drivers/mmc/host/sdhci.c | 6 ------
 drivers/mmc/host/sdhci.h | 2 --
 2 files changed, 8 deletions(-)
drivers/mmc/host/sdhci.c +0 -6
index c1bd77e17458..f9bca1e7da25 100644
@@ -2530,9 +2530,6 @@ EXPORT_SYMBOL_GPL(sdhci_disable_irq_wakeups);
 
 int sdhci_suspend_host(struct sdhci_host *host)
 {
-	if (host->ops->platform_suspend)
-		host->ops->platform_suspend(host);
-
 	sdhci_disable_card_detection(host);
 
 	/* Disable tuning since we are suspending */
@@ -2589,9 +2586,6 @@ int sdhci_resume_host(struct sdhci_host *host)
 
 	sdhci_enable_card_detection(host);
 
-	if (host->ops->platform_resume)
-		host->ops->platform_resume(host);
-
 	/* Set the re-tuning expiration flag */
 	if (host->flags & SDHCI_USING_RETUNING_TIMER)
 		host->flags |= SDHCI_NEEDS_RETUNING;
drivers/mmc/host/sdhci.h +0 -2
index 7a35395e5f56..4a5cd5e3fa3e 100644
@@ -289,8 +289,6 @@ struct sdhci_ops {
 	int	(*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
 	void	(*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
 	void	(*hw_reset)(struct sdhci_host *host);
-	void	(*platform_suspend)(struct sdhci_host *host);
-	void	(*platform_resume)(struct sdhci_host *host);
 	void    (*adma_workaround)(struct sdhci_host *host, u32 intmask);
 	void	(*platform_init)(struct sdhci_host *host);
 	void    (*card_event)(struct sdhci_host *host);
Signature · 1 line
1.8.3.1
#67 lore raw

PATCH 28/38 mmc: sdhci: remove platform_suspend/platform_resume callbacks

Quoted 4 lines · Russell King

The only user (sdhci-of-esdhc) no longer uses these callbacks, so lets remove them to discourage any further use.

Quoted 49 lines
---
 drivers/mmc/host/sdhci.c | 6 ------
 drivers/mmc/host/sdhci.h | 2 --
 2 files changed, 8 deletions(-)
drivers/mmc/host/sdhci.c +0 -6
index c1bd77e17458..f9bca1e7da25 100644
@@ -2530,9 +2530,6 @@ EXPORT_SYMBOL_GPL(sdhci_disable_irq_wakeups);
 
 int sdhci_suspend_host(struct sdhci_host *host)
 {
-       if (host->ops->platform_suspend)
-               host->ops->platform_suspend(host);
-
        sdhci_disable_card_detection(host);
 
        /* Disable tuning since we are suspending */
@@ -2589,9 +2586,6 @@ int sdhci_resume_host(struct sdhci_host *host)
 
        sdhci_enable_card_detection(host);
 
-       if (host->ops->platform_resume)
-               host->ops->platform_resume(host);
-
        /* Set the re-tuning expiration flag */
        if (host->flags & SDHCI_USING_RETUNING_TIMER)
                host->flags |= SDHCI_NEEDS_RETUNING;
drivers/mmc/host/sdhci.h +0 -3
index 7a35395e5f56..4a5cd5e3fa3e 100644
@@ -289,8 +289,6 @@ struct sdhci_ops {
        int     (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
        void    (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
        void    (*hw_reset)(struct sdhci_host *host);
-       void    (*platform_suspend)(struct sdhci_host *host);
-       void    (*platform_resume)(struct sdhci_host *host);
        void    (*adma_workaround)(struct sdhci_host *host, u32 intmask);
        void    (*platform_init)(struct sdhci_host *host);
        void    (*card_event)(struct sdhci_host *host);
--

1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#68 lore raw

PATCH 29/38 mmc: sdhci-tegra: get rid of special PRESENT_STATE register handling

In reply to Russell King - ARM Linux

sdhci-tegra provides a get_ro method, which overrides the checking of the write protect bit in the PRESENT_STATE register in sdhci.c:

        if (host->flags & SDHCI_DEVICE_DEAD)
                is_readonly = 0;
        else if (host->ops->get_ro)
                is_readonly = host->ops->get_ro(host);
        else
                is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE)
                                & SDHCI_WRITE_PROTECT);

This means it's pointless detecting accesses to this register and manually setting the SDHCI_WRITE_PROTECT as it has no effect.

This means that the whole of tegra_sdhci_readl() can be removed and we can use the builtin sdhci readl functionality here.

---
 drivers/mmc/host/sdhci-tegra.c | 14 --------------
 1 file changed, 14 deletions(-)
drivers/mmc/host/sdhci-tegra.c +0 -14
index d06b6ff60432..985247649f46 100644
@@ -48,19 +48,6 @@ struct sdhci_tegra {
 	int power_gpio;
 };
 
-static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg)
-{
-	u32 val;
-
-	if (unlikely(reg == SDHCI_PRESENT_STATE)) {
-		/* Use wp_gpio here instead? */
-		val = readl(host->ioaddr + reg);
-		return val | SDHCI_WRITE_PROTECT;
-	}
-
-	return readl(host->ioaddr + reg);
-}
-
 static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -150,7 +137,6 @@ static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width)
 
 static const struct sdhci_ops tegra_sdhci_ops = {
 	.get_ro     = tegra_sdhci_get_ro,
-	.read_l     = tegra_sdhci_readl,
 	.read_w     = tegra_sdhci_readw,
 	.write_l    = tegra_sdhci_writel,
 	.set_clock  = sdhci_set_clock,
Signature · 1 line
1.8.3.1
#69 lore raw

PATCH 30/38 mmc: sdhci: move regulator handling into sdhci_set_power()

In reply to Russell King - ARM Linux

Move the regulator handling into sdhci_set_power() rather than being in sdhci_do_set_ios(). This wraps all power control up into this function.

---
 drivers/mmc/host/sdhci.c | 72 +++++++++++++++++++++++-------------------------
 1 file changed, 35 insertions(+), 37 deletions(-)
drivers/mmc/host/sdhci.c +35 -37
index f9bca1e7da25..decc5c64efb8 100644
@@ -1216,7 +1216,7 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 }
 EXPORT_SYMBOL_GPL(sdhci_set_clock);
 
-static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
+static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
 {
 	u8 pwr = 0;
 
@@ -1239,7 +1239,7 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
 	}
 
 	if (host->pwr == pwr)
-		return -1;
+		return;
 
 	host->pwr = pwr;
 
@@ -1247,38 +1247,43 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
 		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
 		if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
 			sdhci_runtime_pm_bus_off(host);
-		return 0;
-	}
-
-	/*
-	 * Spec says that we should clear the power reg before setting
-	 * a new value. Some controllers don't seem to like this though.
-	 */
-	if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
-		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
+		power = 0;
+	} else {
+		/*
+		 * Spec says that we should clear the power reg before setting
+		 * a new value. Some controllers don't seem to like this though.
+		 */
+		if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
+			sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
 
-	/*
-	 * At least the Marvell CaFe chip gets confused if we set the voltage
-	 * and set turn on power at the same time, so set the voltage first.
-	 */
-	if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
-		sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+		/*
+		 * At least the Marvell CaFe chip gets confused if we set the
+		 * voltage and set turn on power at the same time, so set the
+		 * voltage first.
+		 */
+		if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
+			sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
 
-	pwr |= SDHCI_POWER_ON;
+		pwr |= SDHCI_POWER_ON;
 
-	sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+		sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
 
-	if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
-		sdhci_runtime_pm_bus_on(host);
+		if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
+			sdhci_runtime_pm_bus_on(host);
 
-	/*
-	 * Some controllers need an extra 10ms delay of 10ms before they
-	 * can apply clock after applying power
-	 */
-	if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
-		mdelay(10);
+		/*
+		 * Some controllers need an extra 10ms delay of 10ms before
+		 * they can apply clock after applying power
+		 */
+		if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
+			mdelay(10);
+	}
 
-	return power;
+	if (host->vmmc) {
+		spin_unlock_irq(&host->lock);
+		mmc_regulator_set_ocr(host->mmc, host->vmmc, power);
+		spin_lock_irq(&host->lock);
+	}
 }
 
 /*****************************************************************************\
@@ -1428,7 +1433,6 @@ EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);
 static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 {
 	unsigned long flags;
-	int vdd_bit = -1;
 	u8 ctrl;
 
 	spin_lock_irqsave(&host->lock, flags);
@@ -1460,15 +1464,9 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 	}
 
 	if (ios->power_mode == MMC_POWER_OFF)
-		vdd_bit = sdhci_set_power(host, -1);
+		sdhci_set_power(host, -1);
 	else
-		vdd_bit = sdhci_set_power(host, ios->vdd);
-
-	if (host->vmmc && vdd_bit != -1) {
-		spin_unlock_irqrestore(&host->lock, flags);
-		mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd_bit);
-		spin_lock_irqsave(&host->lock, flags);
-	}
+		sdhci_set_power(host, ios->vdd);
 
 	if (host->ops->platform_send_init_74_clocks)
 		host->ops->platform_send_init_74_clocks(host, ios->power_mode);
Signature · 1 line
1.8.3.1
#70 lore raw

PATCH 31/38 mmc: sdhci: move remaining power handling into sdhci_set_power()

In reply to Russell King - ARM Linux

Move the remaining parts of the power handling in sdhci_do_set_ios() into sdhci_set_power().

---
 drivers/mmc/host/sdhci.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)
drivers/mmc/host/sdhci.c +7 -9
index decc5c64efb8..a3334460c0c6 100644
@@ -1216,12 +1216,13 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 }
 EXPORT_SYMBOL_GPL(sdhci_set_clock);
 
-static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
+static void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
+			    unsigned short vdd)
 {
 	u8 pwr = 0;
 
-	if (power != (unsigned short)-1) {
-		switch (1 << power) {
+	if (mode != MMC_POWER_OFF) {
+		switch (1 << vdd) {
 		case MMC_VDD_165_195:
 			pwr = SDHCI_POWER_180;
 			break;
@@ -1247,7 +1248,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
 		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
 		if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
 			sdhci_runtime_pm_bus_off(host);
-		power = 0;
+		vdd = 0;
 	} else {
 		/*
 		 * Spec says that we should clear the power reg before setting
@@ -1281,7 +1282,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
 
 	if (host->vmmc) {
 		spin_unlock_irq(&host->lock);
-		mmc_regulator_set_ocr(host->mmc, host->vmmc, power);
+		mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd);
 		spin_lock_irq(&host->lock);
 	}
 }
@@ -1463,10 +1464,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 		host->clock = ios->clock;
 	}
 
-	if (ios->power_mode == MMC_POWER_OFF)
-		sdhci_set_power(host, -1);
-	else
-		sdhci_set_power(host, ios->vdd);
+	sdhci_set_power(host, ios->power_mode, ios->vdd);
 
 	if (host->ops->platform_send_init_74_clocks)
 		host->ops->platform_send_init_74_clocks(host, ios->power_mode);
Signature · 1 line
1.8.3.1
#71 lore raw

PATCH 32/38 mmc: sdhci: track whether preset mode is currently enabled in hardware

In reply to Russell King - ARM Linux

Track whether preset mode is currently enabled in hardware, and use that when making decisions elsewhere in the code rather than reading the register and checking the bit.

---
 drivers/mmc/host/sdhci.c  | 44 ++++++++++++++++++++++++++------------------
 include/linux/mmc/sdhci.h |  1 +
 2 files changed, 27 insertions(+), 18 deletions(-)
drivers/mmc/host/sdhci.c +26 -18
index a3334460c0c6..4f66722a1ee7 100644
@@ -205,9 +205,14 @@ static void sdhci_do_reset(struct sdhci_host *host, u8 mask)
 
 	host->ops->reset(host, mask);
 
-	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
-		if ((host->ops->enable_dma) && (mask & SDHCI_RESET_ALL))
-			host->ops->enable_dma(host);
+	if (mask & SDHCI_RESET_ALL) {
+		if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
+			if (host->ops->enable_dma)
+				host->ops->enable_dma(host);
+		}
+
+		/* Resetting the controller clears many */
+		host->preset_enabled = false;
 	}
 }
 
@@ -1126,8 +1131,7 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 		return;
 
 	if (host->version >= SDHCI_SPEC_300) {
-		if (sdhci_readw(host, SDHCI_HOST_CONTROL2) &
-			SDHCI_CTRL_PRESET_VAL_ENABLE) {
+		if (host->preset_enabled) {
 			u16 pre_val;
 
 			clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
@@ -1491,13 +1495,13 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 		    (ios->timing == MMC_TIMING_UHS_SDR25))
 			ctrl |= SDHCI_CTRL_HISPD;
 
-		ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-		if (!(ctrl_2 & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
+		if (!host->preset_enabled) {
 			sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 			/*
 			 * We only need to set Driver Strength if the
 			 * preset value enable is not set.
 			 */
+			ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 			ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK;
 			if (ios->drv_type == MMC_SET_DRIVER_TYPE_A)
 				ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A;
@@ -2001,26 +2005,30 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 
 static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable)
 {
-	u16 ctrl;
-
 	/* Host Controller v3.00 defines preset value registers */
 	if (host->version < SDHCI_SPEC_300)
 		return;
 
-	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-
 	/*
 	 * We only enable or disable Preset Value if they are not already
 	 * enabled or disabled respectively. Otherwise, we bail out.
 	 */
-	if (enable && !(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
-		ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
-		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-		host->flags |= SDHCI_PV_ENABLED;
-	} else if (!enable && (ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
-		ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
+	if (host->preset_enabled != enable) {
+		u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+
+		if (enable)
+			ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
+		else
+			ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
+
 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-		host->flags &= ~SDHCI_PV_ENABLED;
+
+		if (enable)
+			host->flags |= SDHCI_PV_ENABLED;
+		else
+			host->flags &= ~SDHCI_PV_ENABLED;
+
+		host->preset_enabled = enable;
 	}
 }
 
include/linux/mmc/sdhci.h +1 -0
index 7f3efbab8732..08abe9941884 100644
@@ -143,6 +143,7 @@ struct sdhci_host {
 
 	bool runtime_suspended;	/* Host is runtime suspended */
 	bool bus_on;		/* Bus power prevents runtime suspend */
+	bool preset_enabled;	/* Preset is enabled */
 
 	struct mmc_request *mrq;	/* Current request */
 	struct mmc_command *cmd;	/* Current command */
Signature · 1 line
1.8.3.1
#72 lore raw

PATCH 33/38 mmc: sdhci: fix SDHCI dependencies

In reply to Russell King - ARM Linux
---
 drivers/mmc/host/Kconfig | 63 ++++++++++++++++++++++++------------------------
 1 file changed, 32 insertions(+), 31 deletions(-)
drivers/mmc/host/Kconfig +32 -31
index 8aaf8c1f3f63..d8c1f31ab37f 100644
@@ -25,8 +25,7 @@ config MMC_PXA
 	  If unsure, say N.
 
 config MMC_SDHCI
-	tristate "Secure Digital Host Controller Interface support"
-	depends on HAS_DMA
+	tristate
 	help
 	  This selects the generic Secure Digital Host Controller Interface.
 	  It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
@@ -59,7 +58,8 @@ config MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
 
 config MMC_SDHCI_PCI
 	tristate "SDHCI support on PCI bus"
-	depends on MMC_SDHCI && PCI
+	depends on PCI && HAS_DMA
+	select MMC_SDHCI
 	help
 	  This selects the PCI Secure Digital Host Controller Interface.
 	  Most controllers found today are PCI devices.
@@ -83,7 +83,8 @@ config MMC_RICOH_MMC
 
 config MMC_SDHCI_ACPI
 	tristate "SDHCI support for ACPI enumerated SDHCI controllers"
-	depends on MMC_SDHCI && ACPI
+	depends on ACPI && HAS_DMA
+	select MMC_SDHCI
 	help
 	  This selects support for ACPI enumerated SDHCI controllers,
 	  identified by ACPI Compatibility ID PNP0D40 or specific
@@ -94,8 +95,8 @@ config MMC_SDHCI_ACPI
 	  If unsure, say N.
 
 config MMC_SDHCI_PLTFM
-	tristate "SDHCI platform and OF driver helper"
-	depends on MMC_SDHCI
+	tristate
+	select MMC_SDHCI
 	help
 	  This selects the common helper functions support for Secure Digital
 	  Host Controller Interface based platform and OF drivers.
@@ -106,8 +107,8 @@ config MMC_SDHCI_PLTFM
 
 config MMC_SDHCI_OF_ARASAN
 	tristate "SDHCI OF support for the Arasan SDHCI controllers"
-	depends on MMC_SDHCI_PLTFM
-	depends on OF
+	depends on OF && HAS_DMA
+	select MMC_SDHCI_PLTFM
 	help
 	  This selects the Arasan Secure Digital Host Controller Interface
 	  (SDHCI). This hardware is found e.g. in Xilinx' Zynq SoC.
@@ -118,9 +119,9 @@ config MMC_SDHCI_OF_ARASAN
 
 config MMC_SDHCI_OF_ESDHC
 	tristate "SDHCI OF support for the Freescale eSDHC controller"
-	depends on MMC_SDHCI_PLTFM
-	depends on PPC_OF
+	depends on PPC_OF && HAS_DMA
 	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+	select MMC_SDHCI_PLTFM
 	help
 	  This selects the Freescale eSDHC controller support.
 
@@ -130,9 +131,9 @@ config MMC_SDHCI_OF_ESDHC
 
 config MMC_SDHCI_OF_HLWD
 	tristate "SDHCI OF support for the Nintendo Wii SDHCI controllers"
-	depends on MMC_SDHCI_PLTFM
-	depends on PPC_OF
+	depends on PPC_OF && HAS_DMA
 	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+	select MMC_SDHCI_PLTFM
 	help
 	  This selects the Secure Digital Host Controller Interface (SDHCI)
 	  found in the "Hollywood" chipset of the Nintendo Wii video game
@@ -144,8 +145,8 @@ config MMC_SDHCI_OF_HLWD
 
 config MMC_SDHCI_CNS3XXX
 	tristate "SDHCI support on the Cavium Networks CNS3xxx SoC"
-	depends on ARCH_CNS3XXX
-	depends on MMC_SDHCI_PLTFM
+	depends on ARCH_CNS3XXX && HAS_DMA
+	select MMC_SDHCI_PLTFM
 	help
 	  This selects the SDHCI support for CNS3xxx System-on-Chip devices.
 
@@ -155,9 +156,9 @@ config MMC_SDHCI_CNS3XXX
 
 config MMC_SDHCI_ESDHC_IMX
 	tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller"
-	depends on ARCH_MXC
-	depends on MMC_SDHCI_PLTFM
+	depends on ARCH_MXC && HAS_DMA
 	select MMC_SDHCI_IO_ACCESSORS
+	select MMC_SDHCI_PLTFM
 	help
 	  This selects the Freescale eSDHC/uSDHC controller support
 	  found on i.MX25, i.MX35 i.MX5x and i.MX6x.
@@ -168,9 +169,9 @@ config MMC_SDHCI_ESDHC_IMX
 
 config MMC_SDHCI_DOVE
 	tristate "SDHCI support on Marvell's Dove SoC"
-	depends on ARCH_DOVE
-	depends on MMC_SDHCI_PLTFM
+	depends on ARCH_DOVE && HAS_DMA
 	select MMC_SDHCI_IO_ACCESSORS
+	select MMC_SDHCI_PLTFM
 	help
 	  This selects the Secure Digital Host Controller Interface in
 	  Marvell's Dove SoC.
@@ -181,9 +182,9 @@ config MMC_SDHCI_DOVE
 
 config MMC_SDHCI_TEGRA
 	tristate "SDHCI platform support for the Tegra SD/MMC Controller"
-	depends on ARCH_TEGRA
-	depends on MMC_SDHCI_PLTFM
+	depends on ARCH_TEGRA && HAS_DMA
 	select MMC_SDHCI_IO_ACCESSORS
+	select MMC_SDHCI_PLTFM
 	help
 	  This selects the Tegra SD/MMC controller. If you have a Tegra
 	  platform with SD or MMC devices, say Y or M here.
@@ -192,7 +193,8 @@ config MMC_SDHCI_TEGRA
 
 config MMC_SDHCI_S3C
 	tristate "SDHCI support on Samsung S3C SoC"
-	depends on MMC_SDHCI && PLAT_SAMSUNG
+	depends on PLAT_SAMSUNG && HAS_DMA
+	select MMC_SDHCI
 	help
 	  This selects the Secure Digital Host Controller Interface (SDHCI)
 	  often referrered to as the HSMMC block in some of the Samsung S3C
@@ -204,8 +206,8 @@ config MMC_SDHCI_S3C
 
 config MMC_SDHCI_SIRF
 	tristate "SDHCI support on CSR SiRFprimaII and SiRFmarco SoCs"
-	depends on ARCH_SIRF
-	depends on MMC_SDHCI_PLTFM
+	depends on ARCH_SIRF && HAS_DMA
+	select MMC_SDHCI_PLTFM
 	help
 	  This selects the SDHCI support for SiRF System-on-Chip devices.
 
@@ -215,8 +217,7 @@ config MMC_SDHCI_SIRF
 
 config MMC_SDHCI_PXAV3
 	tristate "Marvell MMP2 SD Host Controller support (PXAV3)"
-	depends on CLKDEV_LOOKUP
-	select MMC_SDHCI
+	depends on CLKDEV_LOOKUP && HAS_DMA
 	select MMC_SDHCI_PLTFM
 	default CPU_MMP2
 	help
@@ -228,8 +229,7 @@ config MMC_SDHCI_PXAV3
 
 config MMC_SDHCI_PXAV2
 	tristate "Marvell PXA9XX SD Host Controller support (PXAV2)"
-	depends on CLKDEV_LOOKUP
-	select MMC_SDHCI
+	depends on CLKDEV_LOOKUP && HAS_DMA
 	select MMC_SDHCI_PLTFM
 	default CPU_PXA910
 	help
@@ -241,7 +241,8 @@ config MMC_SDHCI_PXAV2
 
 config MMC_SDHCI_SPEAR
 	tristate "SDHCI support on ST SPEAr platform"
-	depends on MMC_SDHCI && PLAT_SPEAR
+	depends on PLAT_SPEAR && HAS_DMA
+	select MMC_SDHCI
 	help
 	  This selects the Secure Digital Host Controller Interface (SDHCI)
 	  often referrered to as the HSMMC block in some of the ST SPEAR range
@@ -263,7 +264,7 @@ config MMC_SDHCI_S3C_DMA
 
 config MMC_SDHCI_BCM_KONA
 	tristate "SDHCI support on Broadcom KONA platform"
-	depends on ARCH_BCM_MOBILE
+	depends on ARCH_BCM_MOBILE && HAS_DMA
 	select MMC_SDHCI_PLTFM
 	help
 	  This selects the Broadcom Kona Secure Digital Host Controller
@@ -274,9 +275,9 @@ config MMC_SDHCI_BCM_KONA
 
 config MMC_SDHCI_BCM2835
 	tristate "SDHCI platform support for the BCM2835 SD/MMC Controller"
-	depends on ARCH_BCM2835
-	depends on MMC_SDHCI_PLTFM
+	depends on ARCH_BCM2835 && HAS_DMA
 	select MMC_SDHCI_IO_ACCESSORS
+	select MMC_SDHCI_PLTFM
 	help
 	  This selects the BCM2835 SD/MMC controller. If you have a BCM2835
 	  platform with SD or MMC devices, say Y or M here.
Signature · 1 line
1.8.3.1
#73 lore raw

PATCH 33/38 mmc: sdhci: fix SDHCI dependencies

Quoted 1 line · Russell King

A patch description would be useful so I can work out why...

drivers/mmc/host/Kconfig config MMC_PXA · line 31

Quoted 9 lines
drivers/mmc/host/Kconfig +1 -2
 
 config MMC_SDHCI
-	tristate "Secure Digital Host Controller Interface support"
-	depends on HAS_DMA
+	tristate
 	help
 	  This selects the generic Secure Digital Host Controller Interface.
 	  It is used by manufacturers such as Texas Instruments(R), Ricoh(R)

... it's useful to remove that depends from here and ...

drivers/mmc/host/Kconfig config MMC_SDHCI_DOVE · line 185

Quoted 5 lines

config MMC_SDHCI_TEGRA

drivers/mmc/host/Kconfig +1 -2
 	tristate "SDHCI platform support for the Tegra SD/MMC Controller"
-	depends on ARCH_TEGRA
-	depends on MMC_SDHCI_PLTFM
+	depends on ARCH_TEGRA && HAS_DMA

... duplicate it in all the HW-specific drivers.

On Tegra (and I believe at least any ARM system), I think HAS_DMA is always true, so is there a need for "&& HAS_DMA" at all, now that this statement is pushed into arch-/HW-specific options?

#74 lore raw

PATCH 34/38 mmc: add support for power-on sequencing through DT

In reply to Russell King - ARM Linux

From: Olof Johansson <[email protected]>

This patch enables support for power-on sequencing of SDIO peripherals through DT.

In general, it's quite common that wifi modules and other similar peripherals have several signals in addition to the SDIO interface that needs wiggling before the module will power on. It's common to have a reference clock, one or several power rails and one or several lines for reset/enable type functions.

The binding as written today introduces a number of reset gpios, a regulator and a clock specifier. The code will handle up to 2 gpio reset lines, but it's trivial to increase to more than that if needed at some point.

Implementation-wise, the MMC core has been changed to handle this during host power up, before the host interface is powered on. I have not yet implemented the power-down side, I wanted people to have a chance for reporting back w.r.t. issues (or comments on the bindings) first.

I have not tested the regulator portion, since the system and module I'm working on doesn't need one (Samsung Chromebook with Marvell 8797-based wifi). Testing of those portions (and reporting back) would be appreciated.

---
 Documentation/devicetree/bindings/mmc/mmc.txt | 11 +++++++
 drivers/mmc/core/core.c                       | 42 +++++++++++++++++++++++++++
 drivers/mmc/core/host.c                       | 30 ++++++++++++++++++-
 include/linux/mmc/host.h                      |  5 ++++
 4 files changed, 87 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/mmc/mmc.txt +11 -0
index 9dce540771fb..b9b534ebc0c5 100644
@@ -5,6 +5,8 @@ these definitions.
 Interpreted by the OF core:
 - reg: Registers location and length.
 - interrupts: Interrupts used by the MMC controller.
+- clocks: Clocks needed for the host controller, if any.
+- clock-names: Goes with clocks above.
 
 Card detection:
 If no property below is supplied, host native card detect is used.
@@ -39,6 +41,15 @@ If no property below is supplied, host native card detect is used.
 - mmc-hs200-1_8v: eMMC HS200 mode(1.8V I/O) is supported
 - mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
 
+Card power and reset control:
+The following properties can be specified for cases where the MMC
+peripheral needs additional reset, regulator and clock lines. It is for
+example common for WiFi/BT adapters to have these separate from the main
+MMC bus:
+  - card-reset-gpios: Specify GPIOs for card reset (reset active low)
+  - card-external-vcc-supply: Regulator to drive (independent) card VCC
+  - clock with name "card_ext_clock": External clock provided to the card
+
 *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
 polarity properties, we have to fix the meaning of the "normal" and "inverted"
 line levels. We choose to follow the SDHCI standard, which specifies both those
drivers/mmc/core/core.c +42 -0

65 lines not on this page · raw message

drivers/mmc/core/host.c +29 -1
index fdea825dbb24..abc60f39aa7e 100644
@@ -12,14 +12,18 @@
  *  MMC host class device management
  */
 
+#include <linux/kernel.h>
+#include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/err.h>
+#include <linux/gpio/consumer.h>
 #include <linux/idr.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/pagemap.h>
 #include <linux/export.h>
 #include <linux/leds.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
 
@@ -312,7 +316,7 @@ int mmc_of_parse(struct mmc_host *host)
 	u32 bus_width;
 	bool explicit_inv_wp, gpio_inv_wp = false;
 	enum of_gpio_flags flags;
-	int len, ret, gpio;
+	int i, len, ret, gpio;
 
 	if (!host->parent || !host->parent->of_node)
 		return 0;
@@ -415,6 +419,30 @@ int mmc_of_parse(struct mmc_host *host)
 	if (explicit_inv_wp ^ gpio_inv_wp)
 		host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
 
+	/* Parse card power/reset/clock control */
+	if (of_find_property(np, "card-reset-gpios", NULL)) {
+		struct gpio_desc *gpd;
+		for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
+			gpd = devm_gpiod_get_index(host->parent, "card-reset", i);
+			if (IS_ERR(gpd))
+				break;
+			gpiod_direction_output(gpd, 0);
+			host->card_reset_gpios[i] = gpd;
+		}
+
+		gpd = devm_gpiod_get_index(host->parent, "card-reset", ARRAY_SIZE(host->card_reset_gpios));
+		if (!IS_ERR(gpd)) {
+			dev_warn(host->parent, "More reset gpios than we can handle");
+			gpiod_put(gpd);
+		}
+	}
+
+	host->card_clk = of_clk_get_by_name(np, "card_ext_clock");
+	if (IS_ERR(host->card_clk))
+		host->card_clk = NULL;
+
+	host->card_regulator = regulator_get(host->parent, "card-external-vcc");
+
 	if (of_find_property(np, "cap-sd-highspeed", &len))
 		host->caps |= MMC_CAP_SD_HIGHSPEED;
 	if (of_find_property(np, "cap-mmc-highspeed", &len))
include/linux/mmc/host.h +5 -0
index 28c5e796292f..c3a8c5f6c9b8 100644
@@ -294,6 +294,11 @@ struct mmc_host {
 	unsigned long           clkgate_delay;
 #endif
 
+	/* card specific properties to deal with power and reset */
+	struct regulator	*card_regulator; /* External VCC needed by the card */
+	struct gpio_desc	*card_reset_gpios[2]; /* External resets, active low */
+	struct clk		*card_clk;	/* External clock needed by the card */
+
 	/* host specific block data */
 	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */
 	unsigned short		max_segs;	/* see blk_queue_max_segments */
Signature · 1 line
1.8.3.1
#75 lore raw

PATCH 34/38 mmc: add support for power-on sequencing through DT

Hi Russell,

Quoted 48 lines · Russell King

From: Olof Johansson <[email protected]>

This patch enables support for power-on sequencing of SDIO peripherals through DT.

In general, it's quite common that wifi modules and other similar peripherals have several signals in addition to the SDIO interface that needs wiggling before the module will power on. It's common to have a reference clock, one or several power rails and one or several lines for reset/enable type functions.

The binding as written today introduces a number of reset gpios, a regulator and a clock specifier. The code will handle up to 2 gpio reset lines, but it's trivial to increase to more than that if needed at some point.

Implementation-wise, the MMC core has been changed to handle this during host power up, before the host interface is powered on. I have not yet implemented the power-down side, I wanted people to have a chance for reporting back w.r.t. issues (or comments on the bindings) first.

I have not tested the regulator portion, since the system and module I'm working on doesn't need one (Samsung Chromebook with Marvell 8797-based wifi). Testing of those portions (and reporting back) would be appreciated.

---
 Documentation/devicetree/bindings/mmc/mmc.txt | 11 +++++++
 drivers/mmc/core/core.c                       | 42 +++++++++++++++++++++++++++
 drivers/mmc/core/host.c                       | 30 ++++++++++++++++++-
 include/linux/mmc/host.h                      |  5 ++++
 4 files changed, 87 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/mmc/mmc.txt +2 -0
index 9dce540771fb..b9b534ebc0c5 100644
@@ -5,6 +5,8 @@ these definitions.
 Interpreted by the OF core:
 - reg: Registers location and length.
 - interrupts: Interrupts used by the MMC controller.
+- clocks: Clocks needed for the host controller, if any.
+- clock-names: Goes with clocks above.
 
 Card detection:
 If no property below is supplied, host native card detect is used.

Documentation/devicetree/bindings/mmc/mmc.txt If no property below is supplied, host native card detect is used. · line 49

Quoted 9 lines
Documentation/devicetree/bindings/mmc/mmc.txt +6 -0
@@ -39,6 +41,15 @@ If no property below is supplied, host native card detect is used.
 - mmc-hs200-1_8v: eMMC HS200 mode(1.8V I/O) is supported
 - mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
 
+Card power and reset control:
+The following properties can be specified for cases where the MMC
+peripheral needs additional reset, regulator and clock lines. It is for
+example common for WiFi/BT adapters to have these separate from the main
+MMC bus:
+  - card-reset-gpios: Specify GPIOs for card reset (reset active low)

That probably can use the reset frameworks bindings and the reset-gpio driver Philipp Zabel has been working on.

Documentation/devicetree/bindings/mmc/mmc.txt If no property below is supplied, host native card detect is used. · line 51

Quoted 2 lines
Documentation/devicetree/bindings/mmc/mmc.txt +2 -0
+  - card-external-vcc-supply: Regulator to drive (independent) card VCC
+  - clock with name "card_ext_clock": External clock provided to the card

I'm not sure this is the right path.

This looks pretty harmless for now, but I'm pretty concerned that it's just going to be an ever-increasing list of properties to deal with the various corner-cases everyone has, like for example how to enforce a given frequency for that card_ext_clock, or the fact that it has several SDIO cards connected to them, each with different clocks/reset/regulator lines.

While all of this would easily be solved by representing all this as a bus, like it should, with subdevices grabbing their own clocks and having whatever property they need.

Maxime

Signature · 10 lines
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140424/d03ee267/attachment.sig>
#76 lore raw

PATCH 35/38 mmc: dw_mmc: call mmc_of_parse to fill in common options

In reply to Russell King - ARM Linux

From: Olof Johansson <[email protected]>

The shared of parse function fills in common options for capabilities, etc, but it needs to be called from each driver that wants to make use of it. dw_mmc was missing the call.

---
 drivers/mmc/host/dw_mmc.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/mmc/host/dw_mmc.c +2 -0
index cced599d5aeb..a2c12ebb376e 100644
@@ -2140,6 +2140,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 	if (!mmc)
 		return -ENOMEM;
 
+	mmc_of_parse(mmc);
+
 	slot = mmc_priv(mmc);
 	slot->id = id;
 	slot->mmc = mmc;
Signature · 1 line
1.8.3.1
maintainer
#77 lore raw

PATCH 35/38 mmc: dw_mmc: call mmc_of_parse to fill in common options

Dear, Russell.

I didn't know which version you have checked.
But I have known that mmc_of_parse() have already included at mmc-next repository.

commit 6ca5c60605dde3420ce7fee6f93ec4a7c7924848

Author: Jaehoon Chung <[email protected]>
Date:   Mon Mar 3 11:36:41 2014 +0900

mmc: dw_mmc: use the mmc_of_parse() instead of local parser

mmc_of_parse() have been already parsed the general capability. Didn't need to use the local parser.

Could you check it, plz?

Best Regards,
Jaehoon Chung

Quoted 26 lines · Russell King

From: Olof Johansson <[email protected]>

The shared of parse function fills in common options for capabilities, etc, but it needs to be called from each driver that wants to make use of it. dw_mmc was missing the call.

---
 drivers/mmc/host/dw_mmc.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/mmc/host/dw_mmc.c +2 -0
index cced599d5aeb..a2c12ebb376e 100644
@@ -2140,6 +2140,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 	if (!mmc)
 		return -ENOMEM;
 
+	mmc_of_parse(mmc);
+
 	slot = mmc_priv(mmc);
 	slot->id = id;
 	slot->mmc = mmc;
#78 lore raw

PATCH 35/38 mmc: dw_mmc: call mmc_of_parse to fill in common options

Quoted 3 lines · Jaehoon Chung

Dear, Russell.

I didn't know which version you have checked.

As I said in the cover, this series is based on v3.15-rc1. It's based there because it's part of a much larger set of patches that need to be based on a common point in order to generate a series of around 230 patches against a mainline kernel version.

Quoted 2 lines

But I have known that mmc_of_parse() have already included at mmc-next repository.

That's partly good news, but only partly because I raised issues with Olof's patches which were silently ignored - you'll notice that patch 36 reworks Olof's patch (my patch 34) in such a way that other hosts (eg, sdhci) can make use of it.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#79 lore raw

PATCH 36/38 mmc: fix power-on sequencing for esdhc-imx driver

In reply to Russell King - ARM Linux

There's no reason that this can't be applied to all MMC interfaces as it's all core code, so tie this into the core rather than it being optional for each host.

---
 drivers/mmc/core/host.c | 90 +++++++++++++++++++++++++++++++++++--------------
 1 file changed, 65 insertions(+), 25 deletions(-)
drivers/mmc/core/host.c +65 -25
index abc60f39aa7e..c523f55b317c 100644
@@ -316,7 +316,7 @@ int mmc_of_parse(struct mmc_host *host)
 	u32 bus_width;
 	bool explicit_inv_wp, gpio_inv_wp = false;
 	enum of_gpio_flags flags;
-	int i, len, ret, gpio;
+	int len, ret, gpio;
 
 	if (!host->parent || !host->parent->of_node)
 		return 0;
@@ -419,30 +419,6 @@ int mmc_of_parse(struct mmc_host *host)
 	if (explicit_inv_wp ^ gpio_inv_wp)
 		host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
 
-	/* Parse card power/reset/clock control */
-	if (of_find_property(np, "card-reset-gpios", NULL)) {
-		struct gpio_desc *gpd;
-		for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
-			gpd = devm_gpiod_get_index(host->parent, "card-reset", i);
-			if (IS_ERR(gpd))
-				break;
-			gpiod_direction_output(gpd, 0);
-			host->card_reset_gpios[i] = gpd;
-		}
-
-		gpd = devm_gpiod_get_index(host->parent, "card-reset", ARRAY_SIZE(host->card_reset_gpios));
-		if (!IS_ERR(gpd)) {
-			dev_warn(host->parent, "More reset gpios than we can handle");
-			gpiod_put(gpd);
-		}
-	}
-
-	host->card_clk = of_clk_get_by_name(np, "card_ext_clock");
-	if (IS_ERR(host->card_clk))
-		host->card_clk = NULL;
-
-	host->card_regulator = regulator_get(host->parent, "card-external-vcc");
-
 	if (of_find_property(np, "cap-sd-highspeed", &len))
 		host->caps |= MMC_CAP_SD_HIGHSPEED;
 	if (of_find_property(np, "cap-mmc-highspeed", &len))
@@ -485,6 +461,66 @@ int mmc_of_parse(struct mmc_host *host)
 
 EXPORT_SYMBOL(mmc_of_parse);
 
+static int mmc_of_parse_child(struct mmc_host *host)
+{
+	struct device_node *np;
+	struct clk *clk;
+	int i;
+
+	if (!host->parent || !host->parent->of_node)
+		return 0;
+
+	np = host->parent->of_node;
+
+	host->card_regulator = regulator_get(host->parent, "card-external-vcc");
+	if (IS_ERR(host->card_regulator)) {
+		if (PTR_ERR(host->card_regulator) == -EPROBE_DEFER)
+			return PTR_ERR(host->card_regulator);
+		host->card_regulator = NULL;
+	}
+
+	/* Parse card power/reset/clock control */
+	if (of_find_property(np, "card-reset-gpios", NULL)) {
+		struct gpio_desc *gpd;
+		int level = 0;
+
+		/*
+		 * If the regulator is enabled, then we can hold the
+		 * card in reset with an active high resets.  Otherwise,
+		 * hold the resets low.
+		 */
+		if (host->card_regulator && regulator_is_enabled(host->card_regulator))
+			level = 1;
+
+		for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
+			gpd = devm_gpiod_get_index(host->parent, "card-reset", i);
+			if (IS_ERR(gpd)) {
+				if (PTR_ERR(gpd) == -EPROBE_DEFER)
+					return PTR_ERR(gpd);
+				break;
+			}
+			gpiod_direction_output(gpd, gpiod_is_active_low(gpd) | level);
+			host->card_reset_gpios[i] = gpd;
+		}
+
+		gpd = devm_gpiod_get_index(host->parent, "card-reset", ARRAY_SIZE(host->card_reset_gpios));
+		if (!IS_ERR(gpd)) {
+			dev_warn(host->parent, "More reset gpios than we can handle");
+			gpiod_put(gpd);
+		}
+	}
+
+	clk = of_clk_get_by_name(np, "card_ext_clock");
+	if (IS_ERR(clk)) {
+		if (PTR_ERR(clk) == -EPROBE_DEFER)
+			return PTR_ERR(clk);
+		clk = NULL;
+	}
+	host->card_clk = clk;
+
+	return 0;
+}
+
 /**
  *	mmc_alloc_host - initialise the per-host structure.
  *	@extra: sizeof private data structure
@@ -564,6 +600,10 @@ int mmc_add_host(struct mmc_host *host)
 {
 	int err;
 
+	err = mmc_of_parse_child(host);
+	if (err)
+		return err;
+
 	WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
 		!host->ops->enable_sdio_irq);
 
Signature · 1 line
1.8.3.1
#80 lore raw

PATCH 37/38 ARM: cubox-i: add support for SD UHS-1 cards

In reply to Russell King - ARM Linux
---
 arch/arm/boot/dts/imx6qdl-cubox-i.dtsi | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)
arch/arm/boot/dts/imx6qdl-cubox-i.dtsi +25 -1
index c2a24888a276..c928c0a5e3cc 100644
@@ -111,6 +111,28 @@
 				MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059
 			>;
 		};
+
+		pinctrl_cubox_i_usdhc2_100mhz: cubox-i-usdhc2-100mhz {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_CMD__SD2_CMD    0x170b9
+				MX6QDL_PAD_SD2_CLK__SD2_CLK    0x100b9
+				MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170b9
+				MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170b9
+				MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170b9
+				MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130b9
+			>;
+		};
+
+		pinctrl_cubox_i_usdhc2_200mhz: cubox-i-usdhc2-200mhz {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_CMD__SD2_CMD    0x170f9
+				MX6QDL_PAD_SD2_CLK__SD2_CLK    0x100f9
+				MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170f9
+				MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170f9
+				MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170f9
+				MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130f9
+			>;
+		};
 	};
 };
 
@@ -131,8 +153,10 @@
 };
 
 &usdhc2 {
-	pinctrl-names = "default";
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
 	pinctrl-0 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2>;
+	pinctrl-1 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2_100mhz>;
+	pinctrl-2 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2_200mhz>;
 	vmmc-supply = <&reg_3p3v>;
 	cd-gpios = <&gpio1 4 0>;
 	status = "okay";
Signature · 1 line
1.8.3.1
#81 lore raw

PATCH 38/38 ARM: cubox-i: add support for Wifi/BT

In reply to Russell King - ARM Linux
---
 arch/arm/boot/dts/imx6qdl-cubox-i.dtsi  |  8 +++
 arch/arm/boot/dts/imx6qdl-microsom.dtsi | 98 +++++++++++++++++++++++++++++++++
 2 files changed, 106 insertions(+)
arch/arm/boot/dts/imx6qdl-cubox-i.dtsi +8 -0
index c928c0a5e3cc..67fe5585f6dd 100644
@@ -152,6 +152,14 @@
 	status = "okay";
 };
 
+&uart4 {
+	status = "okay";
+};
+
+&usdhc1 {
+	status = "okay";
+};
+
 &usdhc2 {
 	pinctrl-names = "default", "state_100mhz", "state_200mhz";
 	pinctrl-0 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2>;
arch/arm/boot/dts/imx6qdl-microsom.dtsi +98 -0

126 lines not on this page · raw message

Signature · 1 line
1.8.3.1
#82 lore raw

cover MMC updates, plus CuBox-i WiFi support

In reply to Russell King - ARM Linux
Quoted 7 lines · Russell King - ARM Linux

All,

This is where I'm at with trying to clean up the SDHCI mess, and sort out issues I've noticed when trying to get UHS support working on CuBoxes. This is my full patch set, but I recommend not applying patch 37 as there appears to be a hardware issue preventing it working reliably.

Quoted 9 lines

In any case, patches 0-33 inclusive are the SDHCI clean up, based against v3.15-rc1. Patches 34 and 35 are Olof's Wifi support, 36 is my fix against those, and 38 adds the Broadcom Wifi and BT support for CuBox.

The questions over how to handle these devices were never properly settled, so I recommend against merging patch 34 onwards. As for the rest, I'm not planning on any further work, so it may be a good idea for people to consider testing them with a view to getting them merged.

I have looked though the patches up until patch 33 and this is clearly a nice piece of clean-up /fixes work for sdhci. Besides my minor comments per patch, I don't have any objections code-review wise to proceed merging them.

I have also tried to applied them on Chris' mmc-next branch, unfortunate it fails at patch 23, so it would be nice to get a re-based patchset for the mmc-next branch.

Kind regards
Ulf Hansson

Quoted 40 lines
 Documentation/devicetree/bindings/mmc/mmc.txt |  11 +
 arch/arm/boot/dts/imx6qdl-cubox-i.dtsi        |  34 +-
 arch/arm/boot/dts/imx6qdl-microsom.dtsi       |  98 ++++
 drivers/mmc/core/core.c                       |  42 ++
 drivers/mmc/core/host.c                       |  68 +++
 drivers/mmc/core/sdio_irq.c                   |  41 +-
 drivers/mmc/host/Kconfig                      |  63 +--
 drivers/mmc/host/dw_mmc.c                     |   2 +
 drivers/mmc/host/sdhci-acpi.c                 |   8 +
 drivers/mmc/host/sdhci-bcm-kona.c             |   4 +
 drivers/mmc/host/sdhci-bcm2835.c              |   4 +
 drivers/mmc/host/sdhci-cns3xxx.c              |  13 +-
 drivers/mmc/host/sdhci-dove.c                 |   4 +
 drivers/mmc/host/sdhci-esdhc-imx.c            |  82 +--
 drivers/mmc/host/sdhci-esdhc.h                |   4 +-
 drivers/mmc/host/sdhci-of-arasan.c            |   4 +
 drivers/mmc/host/sdhci-of-esdhc.c             |  70 ++-
 drivers/mmc/host/sdhci-of-hlwd.c              |   4 +
 drivers/mmc/host/sdhci-pci.c                  |   9 +-
 drivers/mmc/host/sdhci-pltfm.c                |   4 +
 drivers/mmc/host/sdhci-pxav2.c                |  14 +-
 drivers/mmc/host/sdhci-pxav3.c                |  13 +-
 drivers/mmc/host/sdhci-s3c.c                  |  36 +-
 drivers/mmc/host/sdhci-sirf.c                 |   4 +
 drivers/mmc/host/sdhci-spear.c                |   5 +-
 drivers/mmc/host/sdhci-tegra.c                |  27 +-
 drivers/mmc/host/sdhci.c                      | 728 +++++++++++++-------------
 drivers/mmc/host/sdhci.h                      |  20 +-
 include/linux/mmc/host.h                      |   8 +
 include/linux/mmc/sdhci.h                     |  15 +-
 30 files changed, 885 insertions(+), 554 deletions(-)

--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#83 lore raw

cover MMC updates, plus CuBox-i WiFi support

Quoted 8 lines · Ulf Hansson

I have looked though the patches up until patch 33 and this is clearly a nice piece of clean-up /fixes work for sdhci. Besides my minor comments per patch, I don't have any objections code-review wise to proceed merging them.

I have also tried to applied them on Chris' mmc-next branch, unfortunate it fails at patch 23, so it would be nice to get a re-based patchset for the mmc-next branch.

I /could/ rebase it but then I wouldn't be able to produce the patch sets/patches for others [*] (such as the Novena project) to derive their kernel tree from my iMX6 patch set.

What I'd prefer is to keep the patch set intact, and provide Chris with a pull request for it up to patch 33, which would need a conflict fixed - and this would mean that I can be sure that what I'm testing, and what I'm distributing is what Chris will also be submitting.

* - this currently stands at 230 patches in all - mmc + l2c + fec + imx-drm + other iMX6 changes.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#84 lore raw

cover MMC updates, plus CuBox-i WiFi support

Quoted 14 lines · Russell King - ARM Linux
Quoted 8 lines · Ulf Hansson

I have looked though the patches up until patch 33 and this is clearly a nice piece of clean-up /fixes work for sdhci. Besides my minor comments per patch, I don't have any objections code-review wise to proceed merging them.

I have also tried to applied them on Chris' mmc-next branch, unfortunate it fails at patch 23, so it would be nice to get a re-based patchset for the mmc-next branch.

I /could/ rebase it but then I wouldn't be able to produce the patch sets/patches for others [*] (such as the Novena project) to derive their kernel tree from my iMX6 patch set.

Quoted 5 lines

What I'd prefer is to keep the patch set intact, and provide Chris with a pull request for it up to patch 33, which would need a conflict fixed - and this would mean that I can be sure that what I'm testing, and what I'm distributing is what Chris will also be submitting.

Whether there are more than one conflict, I don't know. I just stopped at patch 23.

Moreover, there are other patches for sdhci that have been posted and being discussed. In principle, we then need to put all these on hold to prevent further conflicts. I guess that doable, as long as we don't to that for too long. Maybe Chris have some more thoughts how to handle this!?

Kind regards
Ulf Hansson

Quoted 11 lines

* - this currently stands at 230 patches in all - mmc + l2c + fec + imx-drm + other iMX6 changes.

--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#85 lore raw

cover MMC updates, plus CuBox-i WiFi support

Quoted 21 lines · Ulf Hansson
Quoted 14 lines · Russell King - ARM Linux
Quoted 8 lines · Ulf Hansson

I have looked though the patches up until patch 33 and this is clearly a nice piece of clean-up /fixes work for sdhci. Besides my minor comments per patch, I don't have any objections code-review wise to proceed merging them.

I have also tried to applied them on Chris' mmc-next branch, unfortunate it fails at patch 23, so it would be nice to get a re-based patchset for the mmc-next branch.

I /could/ rebase it but then I wouldn't be able to produce the patch sets/patches for others [*] (such as the Novena project) to derive their kernel tree from my iMX6 patch set.

Quoted 5 lines

What I'd prefer is to keep the patch set intact, and provide Chris with a pull request for it up to patch 33, which would need a conflict fixed - and this would mean that I can be sure that what I'm testing, and what I'm distributing is what Chris will also be submitting.

Quoted 8 lines

Whether there are more than one conflict, I don't know. I just stopped at patch 23.

Moreover, there are other patches for sdhci that have been posted and being discussed. In principle, we then need to put all these on hold to prevent further conflicts. I guess that doable, as long as we don't to that for too long. Maybe Chris have some more thoughts how to handle this!?

This is nothing new or unexpected - it was last posted back in February, and I elected that it should be held off until after the last merge window.

Unfortunately, I didn't have time to post it immediately after the merge window closed, partly because it needed to be rebased on top of tglx's IRQ changes on which it depends. I was carrying those as separate commits to the ones Thomas was carrying in his tree - and in the event, Thomas had modified his patches slightly between sending me copies of them and the versions he sent during the merge window.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#86 lore raw

cover MMC updates, plus CuBox-i WiFi support

Quoted 35 lines · Russell King - ARM Linux
Quoted 21 lines · Ulf Hansson
Quoted 14 lines · Russell King - ARM Linux
Quoted 8 lines · Ulf Hansson

I have looked though the patches up until patch 33 and this is clearly a nice piece of clean-up /fixes work for sdhci. Besides my minor comments per patch, I don't have any objections code-review wise to proceed merging them.

I have also tried to applied them on Chris' mmc-next branch, unfortunate it fails at patch 23, so it would be nice to get a re-based patchset for the mmc-next branch.

I /could/ rebase it but then I wouldn't be able to produce the patch sets/patches for others [*] (such as the Novena project) to derive their kernel tree from my iMX6 patch set.

Quoted 5 lines

What I'd prefer is to keep the patch set intact, and provide Chris with a pull request for it up to patch 33, which would need a conflict fixed - and this would mean that I can be sure that what I'm testing, and what I'm distributing is what Chris will also be submitting.

Quoted 8 lines

Whether there are more than one conflict, I don't know. I just stopped at patch 23.

Moreover, there are other patches for sdhci that have been posted and being discussed. In principle, we then need to put all these on hold to prevent further conflicts. I guess that doable, as long as we don't to that for too long. Maybe Chris have some more thoughts how to handle this!?

This is nothing new or unexpected - it was last posted back in February, and I elected that it should be held off until after the last merge window.

Quoted 6 lines

Unfortunately, I didn't have time to post it immediately after the merge window closed, partly because it needed to be rebased on top of tglx's IRQ changes on which it depends. I was carrying those as separate commits to the ones Thomas was carrying in his tree - and in the event, Thomas had modified his patches slightly between sending me copies of them and the versions he sent during the merge window.

Okay, so let's keep up the frequency here then. I only had some minor comments, please fix them and send a v2.

How about if I resolve the conflicts and send the pull request to Chris? I suppose it makes life a bit easier for Chris.

Kind regards
Ulf Hansson

Quoted 8 lines

--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#87 lore raw

cover MMC updates, plus CuBox-i WiFi support

Quoted 12 lines · Ulf Hansson
Quoted 10 lines · Russell King - ARM Linux

This is nothing new or unexpected - it was last posted back in February, and I elected that it should be held off until after the last merge window.

Unfortunately, I didn't have time to post it immediately after the merge window closed, partly because it needed to be rebased on top of tglx's IRQ changes on which it depends. I was carrying those as separate commits to the ones Thomas was carrying in his tree - and in the event, Thomas had modified his patches slightly between sending me copies of them and the versions he sent during the merge window.

Quoted 2 lines

Okay, so let's keep up the frequency here then. I only had some minor comments, please fix them and send a v2.

Right, so I've updated the patches, and added one ack to one patch. That seems insufficient to me - the only platform these have been tested on is iMX6, which is sdhci-esdhc-imx.c.

They _really_ need testing elsewhere too. Or is the plan to merge them and then see about getting people to test them and fix them up afterwards?

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#88 lore raw

cover MMC updates, plus CuBox-i WiFi support

Quoted 16 lines · Russell King - ARM Linux
Quoted 12 lines · Ulf Hansson
Quoted 10 lines · Russell King - ARM Linux

This is nothing new or unexpected - it was last posted back in February, and I elected that it should be held off until after the last merge window.

Unfortunately, I didn't have time to post it immediately after the merge window closed, partly because it needed to be rebased on top of tglx's IRQ changes on which it depends. I was carrying those as separate commits to the ones Thomas was carrying in his tree - and in the event, Thomas had modified his patches slightly between sending me copies of them and the versions he sent during the merge window.

Quoted 2 lines

Okay, so let's keep up the frequency here then. I only had some minor comments, please fix them and send a v2.

Quoted 7 lines

Right, so I've updated the patches, and added one ack to one patch. That seems insufficient to me - the only platform these have been tested on is iMX6, which is sdhci-esdhc-imx.c.

They _really_ need testing elsewhere too. Or is the plan to merge them and then see about getting people to test them and fix them up afterwards?

I was hoping people could start doing tests, before Chris actually decided to pull them in. Now, if that doesn't happen, we could just merge them, as you say, and thus we have to fix potential problems afterwards. I would expect you to help out if problem occurs.

If we decide to not merge in a while, I am not sure how long we could prevent other sdhci patches from being merged. I guess Chris will have to take the final call.

Quoted 8 lines

--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#89 lore raw

cover MMC updates, plus CuBox-i WiFi support

Quoted 25 lines · Ulf Hansson
Quoted 16 lines · Russell King - ARM Linux
Quoted 12 lines · Ulf Hansson
Quoted 10 lines · Russell King - ARM Linux

This is nothing new or unexpected - it was last posted back in February, and I elected that it should be held off until after the last merge window.

Unfortunately, I didn't have time to post it immediately after the merge window closed, partly because it needed to be rebased on top of tglx's IRQ changes on which it depends. I was carrying those as separate commits to the ones Thomas was carrying in his tree - and in the event, Thomas had modified his patches slightly between sending me copies of them and the versions he sent during the merge window.

Quoted 2 lines

Okay, so let's keep up the frequency here then. I only had some minor comments, please fix them and send a v2.

Quoted 7 lines

Right, so I've updated the patches, and added one ack to one patch. That seems insufficient to me - the only platform these have been tested on is iMX6, which is sdhci-esdhc-imx.c.

They _really_ need testing elsewhere too. Or is the plan to merge them and then see about getting people to test them and fix them up afterwards?

Quoted 8 lines

I was hoping people could start doing tests, before Chris actually decided to pull them in. Now, if that doesn't happen, we could just merge them, as you say, and thus we have to fix potential problems afterwards. I would expect you to help out if problem occurs.

If we decide to not merge in a while, I am not sure how long we could prevent other sdhci patches from being merged. I guess Chris will have to take the final call.

Or we just drop them for yet another cycle and show how mainline kernel development sucks, why getting stuff into mainline is utterly painful, and why using vendor kernels is /soo/ much better than this crap.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#90 lore raw

cover MMC updates, plus CuBox-i WiFi support

Quoted 31 lines · Russell King - ARM Linux
Quoted 30 lines · Ulf Hansson
Quoted 16 lines · Russell King - ARM Linux
Quoted 12 lines · Ulf Hansson
Quoted 10 lines · Russell King - ARM Linux

This is nothing new or unexpected - it was last posted back in February, and I elected that it should be held off until after the last merge window.

Unfortunately, I didn't have time to post it immediately after the merge window closed, partly because it needed to be rebased on top of tglx's IRQ changes on which it depends. I was carrying those as separate commits to the ones Thomas was carrying in his tree - and in the event, Thomas had modified his patches slightly between sending me copies of them and the versions he sent during the merge window.

Quoted 2 lines

Okay, so let's keep up the frequency here then. I only had some minor comments, please fix them and send a v2.

Quoted 7 lines

Right, so I've updated the patches, and added one ack to one patch. That seems insufficient to me - the only platform these have been tested on is iMX6, which is sdhci-esdhc-imx.c.

They _really_ need testing elsewhere too. Or is the plan to merge them and then see about getting people to test them and fix them up afterwards?

I was hoping people could start doing tests, before Chris actually decided to pull them in. Now, if that doesn't happen, we could just merge them, as you say, and thus we have to fix potential problems afterwards. I would expect you to help out if problem occurs.

Quoted 7 lines
Quoted 3 lines

If we decide to not merge in a while, I am not sure how long we could prevent other sdhci patches from being merged. I guess Chris will have to take the final call.

Or we just drop them for yet another cycle and show how mainline kernel development sucks, why getting stuff into mainline is utterly painful, and why using vendor kernels is /soo/ much better than this crap.

Dropping them is too me a bad option and I really don't think that should be needed.

I would like to encourage people to help out with testing and I suppose we have to give this at least some time.

Anyway, post your new version. I will create the pull request based on that.

Quoted 4 lines

--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.

#91 lore raw

cover MMC updates, plus CuBox-i WiFi support

In reply to Russell King - ARM Linux
Quoted 7 lines · Russell King - ARM Linux

All,

This is where I'm at with trying to clean up the SDHCI mess, and sort out issues I've noticed when trying to get UHS support working on CuBoxes. This is my full patch set, but I recommend not applying patch 37 as there appears to be a hardware issue preventing it working reliably.

Quoted 8 lines

In any case, patches 0-33 inclusive are the SDHCI clean up, based against v3.15-rc1. Patches 34 and 35 are Olof's Wifi support, 36 is my fix against those, and 38 adds the Broadcom Wifi and BT support for CuBox.

The questions over how to handle these devices were never properly settled, so I recommend against merging patch 34 onwards. As for the rest, I'm not planning on any further work, so it may be a good idea for people to consider testing them with a view to getting them merged.

The series,

(On an NVIDIA Tegra "Jetson TK1" board, with the patches applied on top of next-20140428, also with Andrew Bresticker's Tegra SDHCI patches "mmc: tegra: disable UHS modes" and "mmc: tegra: fix reporting of base clock frequency" applied)

#92 lore raw

cover MMC updates, plus CuBox-i WiFi support

Hi,

Quoted 7 lines · Stephen Warren

The series,

(On an NVIDIA Tegra "Jetson TK1" board, with the patches applied on top of next-20140428, also with Andrew Bresticker's Tegra SDHCI patches "mmc: tegra: disable UHS modes" and "mmc: tegra: fix reporting of base clock frequency" applied)

Thanks very much Stephen, Russell for the series, and Ulf.

This seems like a good time to merge to mmc-next and call for testing in linux-next -- I'm happy to merge a v2 PR when ready.

- Chris.

Signature · 1 line
Chris Ball   <http://printf.net/>
#93 lore raw

cover MMC updates, plus CuBox-i WiFi support

Quoted 11 lines · Chris Ball

Hi,

Quoted 7 lines · Stephen Warren

The series,

(On an NVIDIA Tegra "Jetson TK1" board, with the patches applied on top of next-20140428, also with Andrew Bresticker's Tegra SDHCI patches "mmc: tegra: disable UHS modes" and "mmc: tegra: fix reporting of base clock frequency" applied)

Quoted 6 lines

Thanks very much Stephen, Russell for the series, and Ulf.

This seems like a good time to merge to mmc-next and call for testing in linux-next -- I'm happy to merge a v2 PR when ready.

- Chris.

Hi Russell,

Do you have a rough idea about when you will post your v2 pull request?

I have a pending sdhci patch that I would like to rebase on top of your latest work once it is available.

Thanks,
Tim Kryger