All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/23] a few sdhci/imx clean up and fix patches
@ 2016-04-15 17:29 ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: aisheng.dong, ulf.hansson, dongas86, chris, haibo.chen,
	adrian.hunter, shawnguo, linux-arm-kernel

Patch 1~10 are mainly sdhci cleanup patches while patch 7,9,10
are fixes which seems needed for stable tree as well.

The main work is:
1) a few minor cleanups
2) re-factor sdhci_start_signal_voltage()
3) fix not checking SDHCI_QUIRK2_NO_1_8_V when do voltage switch
4) fix get wrong data interrupt during no data transfer
5) fix unneeded retuning during card remove

Patch 17 added sdhci auto retune support (TUNING_MODE_3)
Many controller support hw auto retune, with it we do not
need do the frequent retuning after each runtime suspend/resume.

Patch 11~23 are imx esdhc driver clean up and fixes.
1) remove SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
I also tried clean up all SDHCI_QUIRK_BROKEN_TIMEOUT_VAL in the tree,
seems a lot work that many controllers are affected, planned to do it later.
2) support setting tuning start point
This can make us bypass a few meaningless tuning commands at the start
3) add hw state restore function after system resume for low
power mode like LPSR on IMX7D which the controller state got lost.
Without it, the controller may not work after resume.
4) Patch 17~19 added hw auto retune support
5) fix strobe DLL lock wrong clock issue
This makes the eMMC HS400 mode strobe locks the correct clock rate
6) a few other reorgnization to make code more concentrate and maintainable

Dong Aisheng (23):
  mmc: sdhci: removed unneeded function wrappers
  mmc: sdhci: move sdhci_get_cd() forward to avoid declaration
  mmc: core: fix a comment typo
  mmc: sdhci: re-factor sdhci_start_signal_voltage()
  mmc: core: mmc_regulator_set_vqmmc not return error if vqmmc/vmmc not
    exist
  mmc: sdhci: using common mmc_regulator_set_vqmmc()
  mmc: sdhci: check SDHCI_QUIRK2_NO_1_8_V when do voltage switch
  mmc: sdhci: rename quirk SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12
  mmc: sdhci: fix incorrect get data interrupt during no data transfer
  mmc: core: disable auto retune during card detection process
  mmc: sdhci-esdhci-imx: remove SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
  mmc: sdhci-esdhc-imx: add esdhc specific suspend resume callback
  mmc: sdhci-esdhc-imx: restore watermark level setting after resume
  mmc: sdhci-esdhci-imx: disable DLL delay line settings explicitly
  mmc: sdhci-esdhc-imx: support setting tuning start point
  doc: dt: fsl-imx-esdhc: add set tuning start point binding
  mmc: sdhci: add standard hw auto retuning support
  mmc: sdhci-esdhc-imx: enable hw auto retuning for STD_TUNING
  mmc: sdhci-esdhc-imx: enable hw auto retuning for MAN_TUNING
  mmc: sdhci-esdhc-imx: fix strobe DLL lock wrong clock issue
  mmc: sdhci-esdhc-imx: factor out hw related intialization into
    function
  mmc: sdhci-esdhc-imx: move tuning static configuration into hwinit
    function
  mmc: sdhci-esdhc-imx: clear tuning bits during hwinit

 .../devicetree/bindings/mmc/fsl-imx-esdhc.txt      |   2 +
 drivers/mmc/core/core.c                            |   3 +-
 drivers/mmc/core/mmc_ops.c                         |   2 +-
 drivers/mmc/host/sdhci-esdhc-imx.c                 | 150 +++++++++++------
 drivers/mmc/host/sdhci-pci-o2micro.c               |   2 +-
 drivers/mmc/host/sdhci-pltfm.c                     |   2 +-
 drivers/mmc/host/sdhci-s3c.c                       |   2 +-
 drivers/mmc/host/sdhci.c                           | 186 +++++++++------------
 drivers/mmc/host/sdhci.h                           |   5 +-
 include/linux/platform_data/mmc-esdhc-imx.h        |   1 +
 10 files changed, 194 insertions(+), 161 deletions(-)

-- 
1.9.1

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

* [PATCH 00/23] a few sdhci/imx clean up and fix patches
@ 2016-04-15 17:29 ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

Patch 1~10 are mainly sdhci cleanup patches while patch 7,9,10
are fixes which seems needed for stable tree as well.

The main work is:
1) a few minor cleanups
2) re-factor sdhci_start_signal_voltage()
3) fix not checking SDHCI_QUIRK2_NO_1_8_V when do voltage switch
4) fix get wrong data interrupt during no data transfer
5) fix unneeded retuning during card remove

Patch 17 added sdhci auto retune support (TUNING_MODE_3)
Many controller support hw auto retune, with it we do not
need do the frequent retuning after each runtime suspend/resume.

Patch 11~23 are imx esdhc driver clean up and fixes.
1) remove SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
I also tried clean up all SDHCI_QUIRK_BROKEN_TIMEOUT_VAL in the tree,
seems a lot work that many controllers are affected, planned to do it later.
2) support setting tuning start point
This can make us bypass a few meaningless tuning commands at the start
3) add hw state restore function after system resume for low
power mode like LPSR on IMX7D which the controller state got lost.
Without it, the controller may not work after resume.
4) Patch 17~19 added hw auto retune support
5) fix strobe DLL lock wrong clock issue
This makes the eMMC HS400 mode strobe locks the correct clock rate
6) a few other reorgnization to make code more concentrate and maintainable

Dong Aisheng (23):
  mmc: sdhci: removed unneeded function wrappers
  mmc: sdhci: move sdhci_get_cd() forward to avoid declaration
  mmc: core: fix a comment typo
  mmc: sdhci: re-factor sdhci_start_signal_voltage()
  mmc: core: mmc_regulator_set_vqmmc not return error if vqmmc/vmmc not
    exist
  mmc: sdhci: using common mmc_regulator_set_vqmmc()
  mmc: sdhci: check SDHCI_QUIRK2_NO_1_8_V when do voltage switch
  mmc: sdhci: rename quirk SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12
  mmc: sdhci: fix incorrect get data interrupt during no data transfer
  mmc: core: disable auto retune during card detection process
  mmc: sdhci-esdhci-imx: remove SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
  mmc: sdhci-esdhc-imx: add esdhc specific suspend resume callback
  mmc: sdhci-esdhc-imx: restore watermark level setting after resume
  mmc: sdhci-esdhci-imx: disable DLL delay line settings explicitly
  mmc: sdhci-esdhc-imx: support setting tuning start point
  doc: dt: fsl-imx-esdhc: add set tuning start point binding
  mmc: sdhci: add standard hw auto retuning support
  mmc: sdhci-esdhc-imx: enable hw auto retuning for STD_TUNING
  mmc: sdhci-esdhc-imx: enable hw auto retuning for MAN_TUNING
  mmc: sdhci-esdhc-imx: fix strobe DLL lock wrong clock issue
  mmc: sdhci-esdhc-imx: factor out hw related intialization into
    function
  mmc: sdhci-esdhc-imx: move tuning static configuration into hwinit
    function
  mmc: sdhci-esdhc-imx: clear tuning bits during hwinit

 .../devicetree/bindings/mmc/fsl-imx-esdhc.txt      |   2 +
 drivers/mmc/core/core.c                            |   3 +-
 drivers/mmc/core/mmc_ops.c                         |   2 +-
 drivers/mmc/host/sdhci-esdhc-imx.c                 | 150 +++++++++++------
 drivers/mmc/host/sdhci-pci-o2micro.c               |   2 +-
 drivers/mmc/host/sdhci-pltfm.c                     |   2 +-
 drivers/mmc/host/sdhci-s3c.c                       |   2 +-
 drivers/mmc/host/sdhci.c                           | 186 +++++++++------------
 drivers/mmc/host/sdhci.h                           |   5 +-
 include/linux/platform_data/mmc-esdhc-imx.h        |   1 +
 10 files changed, 194 insertions(+), 161 deletions(-)

-- 
1.9.1

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

* [PATCH 01/23] mmc: sdhci: removed unneeded function wrappers
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: aisheng.dong, ulf.hansson, dongas86, chris, haibo.chen,
	adrian.hunter, shawnguo, linux-arm-kernel

After commit d6463f170cf0 ("mmc: sdhci: Remove redundant runtime PM calls"),
some of original sdhci_do_xx() function wrappers becomes meaningless,
so remove them.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci.c | 60 ++++++++++++------------------------------------
 1 file changed, 15 insertions(+), 45 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 8e74e75..be52a3a 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -53,7 +53,7 @@ static void sdhci_finish_data(struct sdhci_host *);
 static void sdhci_finish_command(struct sdhci_host *);
 static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
 static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
-static int sdhci_do_get_cd(struct sdhci_host *host);
+static int sdhci_get_cd(struct mmc_host *mmc);
 
 #ifdef CONFIG_PM
 static void sdhci_runtime_pm_bus_on(struct sdhci_host *host);
@@ -194,7 +194,7 @@ EXPORT_SYMBOL_GPL(sdhci_reset);
 static void sdhci_do_reset(struct sdhci_host *host, u8 mask)
 {
 	if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
-		if (!sdhci_do_get_cd(host))
+		if (!sdhci_get_cd(host->mmc))
 			return;
 	}
 
@@ -1393,11 +1393,11 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
 }
 EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);
 
-static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
+static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
+	struct sdhci_host *host = mmc_priv(mmc);
 	unsigned long flags;
 	u8 ctrl;
-	struct mmc_host *mmc = host->mmc;
 
 	spin_lock_irqsave(&host->lock, flags);
 
@@ -1551,16 +1551,10 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+static int sdhci_get_cd(struct mmc_host *mmc)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
-
-	sdhci_do_set_ios(host, ios);
-}
-
-static int sdhci_do_get_cd(struct sdhci_host *host)
-{
-	int gpio_cd = mmc_gpio_get_cd(host->mmc);
+	int gpio_cd = mmc_gpio_get_cd(mmc);
 
 	if (host->flags & SDHCI_DEVICE_DEAD)
 		return 0;
@@ -1584,13 +1578,6 @@ static int sdhci_do_get_cd(struct sdhci_host *host)
 	return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
 }
 
-static int sdhci_get_cd(struct mmc_host *mmc)
-{
-	struct sdhci_host *host = mmc_priv(mmc);
-
-	return sdhci_do_get_cd(host);
-}
-
 static int sdhci_check_ro(struct sdhci_host *host)
 {
 	unsigned long flags;
@@ -1615,8 +1602,9 @@ static int sdhci_check_ro(struct sdhci_host *host)
 
 #define SAMPLE_COUNT	5
 
-static int sdhci_do_get_ro(struct sdhci_host *host)
+static int sdhci_get_ro(struct mmc_host *mmc)
 {
+	struct sdhci_host *host = mmc_priv(mmc);
 	int i, ro_count;
 
 	if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT))
@@ -1641,13 +1629,6 @@ static void sdhci_hw_reset(struct mmc_host *mmc)
 		host->ops->hw_reset(host);
 }
 
-static int sdhci_get_ro(struct mmc_host *mmc)
-{
-	struct sdhci_host *host = mmc_priv(mmc);
-
-	return sdhci_do_get_ro(host);
-}
-
 static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
 {
 	if (!(host->flags & SDHCI_DEVICE_DEAD)) {
@@ -1677,10 +1658,10 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
-						struct mmc_ios *ios)
+static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
+					     struct mmc_ios *ios)
 {
-	struct mmc_host *mmc = host->mmc;
+	struct sdhci_host *host = mmc_priv(mmc);
 	u16 ctrl;
 	int ret;
 
@@ -1768,17 +1749,6 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
 	}
 }
 
-static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
-	struct mmc_ios *ios)
-{
-	struct sdhci_host *host = mmc_priv(mmc);
-
-	if (host->version < SDHCI_SPEC_300)
-		return 0;
-
-	return sdhci_do_start_signal_voltage_switch(host, ios);
-}
-
 static int sdhci_card_busy(struct mmc_host *mmc)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
@@ -2070,7 +2040,7 @@ static void sdhci_card_event(struct mmc_host *mmc)
 	if (host->ops->card_event)
 		host->ops->card_event(host);
 
-	present = sdhci_do_get_cd(host);
+	present = sdhci_get_cd(host->mmc);
 
 	spin_lock_irqsave(&host->lock, flags);
 
@@ -2643,7 +2613,7 @@ int sdhci_resume_host(struct sdhci_host *host)
 		sdhci_init(host, 0);
 		host->pwr = 0;
 		host->clock = 0;
-		sdhci_do_set_ios(host, &host->mmc->ios);
+		sdhci_set_ios(host->mmc, &host->mmc->ios);
 	} else {
 		sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER));
 		mmiowb();
@@ -2721,8 +2691,8 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
 	/* Force clock and power re-program */
 	host->pwr = 0;
 	host->clock = 0;
-	sdhci_do_start_signal_voltage_switch(host, &host->mmc->ios);
-	sdhci_do_set_ios(host, &host->mmc->ios);
+	sdhci_start_signal_voltage_switch(host->mmc, &host->mmc->ios);
+	sdhci_set_ios(host->mmc, &host->mmc->ios);
 
 	if ((host_flags & SDHCI_PV_ENABLED) &&
 		!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) {
-- 
1.9.1

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

* [PATCH 01/23] mmc: sdhci: removed unneeded function wrappers
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

After commit d6463f170cf0 ("mmc: sdhci: Remove redundant runtime PM calls"),
some of original sdhci_do_xx() function wrappers becomes meaningless,
so remove them.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci.c | 60 ++++++++++++------------------------------------
 1 file changed, 15 insertions(+), 45 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 8e74e75..be52a3a 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -53,7 +53,7 @@ static void sdhci_finish_data(struct sdhci_host *);
 static void sdhci_finish_command(struct sdhci_host *);
 static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
 static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
-static int sdhci_do_get_cd(struct sdhci_host *host);
+static int sdhci_get_cd(struct mmc_host *mmc);
 
 #ifdef CONFIG_PM
 static void sdhci_runtime_pm_bus_on(struct sdhci_host *host);
@@ -194,7 +194,7 @@ EXPORT_SYMBOL_GPL(sdhci_reset);
 static void sdhci_do_reset(struct sdhci_host *host, u8 mask)
 {
 	if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
-		if (!sdhci_do_get_cd(host))
+		if (!sdhci_get_cd(host->mmc))
 			return;
 	}
 
@@ -1393,11 +1393,11 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
 }
 EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);
 
-static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
+static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
+	struct sdhci_host *host = mmc_priv(mmc);
 	unsigned long flags;
 	u8 ctrl;
-	struct mmc_host *mmc = host->mmc;
 
 	spin_lock_irqsave(&host->lock, flags);
 
@@ -1551,16 +1551,10 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+static int sdhci_get_cd(struct mmc_host *mmc)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
-
-	sdhci_do_set_ios(host, ios);
-}
-
-static int sdhci_do_get_cd(struct sdhci_host *host)
-{
-	int gpio_cd = mmc_gpio_get_cd(host->mmc);
+	int gpio_cd = mmc_gpio_get_cd(mmc);
 
 	if (host->flags & SDHCI_DEVICE_DEAD)
 		return 0;
@@ -1584,13 +1578,6 @@ static int sdhci_do_get_cd(struct sdhci_host *host)
 	return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
 }
 
-static int sdhci_get_cd(struct mmc_host *mmc)
-{
-	struct sdhci_host *host = mmc_priv(mmc);
-
-	return sdhci_do_get_cd(host);
-}
-
 static int sdhci_check_ro(struct sdhci_host *host)
 {
 	unsigned long flags;
@@ -1615,8 +1602,9 @@ static int sdhci_check_ro(struct sdhci_host *host)
 
 #define SAMPLE_COUNT	5
 
-static int sdhci_do_get_ro(struct sdhci_host *host)
+static int sdhci_get_ro(struct mmc_host *mmc)
 {
+	struct sdhci_host *host = mmc_priv(mmc);
 	int i, ro_count;
 
 	if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT))
@@ -1641,13 +1629,6 @@ static void sdhci_hw_reset(struct mmc_host *mmc)
 		host->ops->hw_reset(host);
 }
 
-static int sdhci_get_ro(struct mmc_host *mmc)
-{
-	struct sdhci_host *host = mmc_priv(mmc);
-
-	return sdhci_do_get_ro(host);
-}
-
 static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
 {
 	if (!(host->flags & SDHCI_DEVICE_DEAD)) {
@@ -1677,10 +1658,10 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
-						struct mmc_ios *ios)
+static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
+					     struct mmc_ios *ios)
 {
-	struct mmc_host *mmc = host->mmc;
+	struct sdhci_host *host = mmc_priv(mmc);
 	u16 ctrl;
 	int ret;
 
@@ -1768,17 +1749,6 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
 	}
 }
 
-static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
-	struct mmc_ios *ios)
-{
-	struct sdhci_host *host = mmc_priv(mmc);
-
-	if (host->version < SDHCI_SPEC_300)
-		return 0;
-
-	return sdhci_do_start_signal_voltage_switch(host, ios);
-}
-
 static int sdhci_card_busy(struct mmc_host *mmc)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
@@ -2070,7 +2040,7 @@ static void sdhci_card_event(struct mmc_host *mmc)
 	if (host->ops->card_event)
 		host->ops->card_event(host);
 
-	present = sdhci_do_get_cd(host);
+	present = sdhci_get_cd(host->mmc);
 
 	spin_lock_irqsave(&host->lock, flags);
 
@@ -2643,7 +2613,7 @@ int sdhci_resume_host(struct sdhci_host *host)
 		sdhci_init(host, 0);
 		host->pwr = 0;
 		host->clock = 0;
-		sdhci_do_set_ios(host, &host->mmc->ios);
+		sdhci_set_ios(host->mmc, &host->mmc->ios);
 	} else {
 		sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER));
 		mmiowb();
@@ -2721,8 +2691,8 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
 	/* Force clock and power re-program */
 	host->pwr = 0;
 	host->clock = 0;
-	sdhci_do_start_signal_voltage_switch(host, &host->mmc->ios);
-	sdhci_do_set_ios(host, &host->mmc->ios);
+	sdhci_start_signal_voltage_switch(host->mmc, &host->mmc->ios);
+	sdhci_set_ios(host->mmc, &host->mmc->ios);
 
 	if ((host_flags & SDHCI_PV_ENABLED) &&
 		!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) {
-- 
1.9.1

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

* [PATCH 02/23] mmc: sdhci: move sdhci_get_cd() forward to avoid declaration
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: aisheng.dong, ulf.hansson, dongas86, chris, haibo.chen,
	adrian.hunter, shawnguo, linux-arm-kernel

Move sdhci_get_cd() to avoid needing to declare this function
before use.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci.c | 55 ++++++++++++++++++++++++------------------------
 1 file changed, 27 insertions(+), 28 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index be52a3a..839aa4c 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -53,7 +53,6 @@ static void sdhci_finish_data(struct sdhci_host *);
 static void sdhci_finish_command(struct sdhci_host *);
 static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
 static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
-static int sdhci_get_cd(struct mmc_host *mmc);
 
 #ifdef CONFIG_PM
 static void sdhci_runtime_pm_bus_on(struct sdhci_host *host);
@@ -161,6 +160,33 @@ static void sdhci_disable_card_detection(struct sdhci_host *host)
 	sdhci_set_card_detection(host, false);
 }
 
+static int sdhci_get_cd(struct mmc_host *mmc)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	int gpio_cd = mmc_gpio_get_cd(mmc);
+
+	if (host->flags & SDHCI_DEVICE_DEAD)
+		return 0;
+
+	/* If nonremovable, assume that the card is always present. */
+	if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
+		return 1;
+
+	/*
+	 * Try slot gpio detect, if defined it take precedence
+	 * over build in controller functionality
+	 */
+	if (!IS_ERR_VALUE(gpio_cd))
+		return !!gpio_cd;
+
+	/* If polling, assume that the card is always present. */
+	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
+		return 1;
+
+	/* Host native card detect */
+	return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
+}
+
 void sdhci_reset(struct sdhci_host *host, u8 mask)
 {
 	unsigned long timeout;
@@ -1551,33 +1577,6 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static int sdhci_get_cd(struct mmc_host *mmc)
-{
-	struct sdhci_host *host = mmc_priv(mmc);
-	int gpio_cd = mmc_gpio_get_cd(mmc);
-
-	if (host->flags & SDHCI_DEVICE_DEAD)
-		return 0;
-
-	/* If nonremovable, assume that the card is always present. */
-	if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
-		return 1;
-
-	/*
-	 * Try slot gpio detect, if defined it take precedence
-	 * over build in controller functionality
-	 */
-	if (!IS_ERR_VALUE(gpio_cd))
-		return !!gpio_cd;
-
-	/* If polling, assume that the card is always present. */
-	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
-		return 1;
-
-	/* Host native card detect */
-	return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
-}
-
 static int sdhci_check_ro(struct sdhci_host *host)
 {
 	unsigned long flags;
-- 
1.9.1

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

* [PATCH 02/23] mmc: sdhci: move sdhci_get_cd() forward to avoid declaration
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

Move sdhci_get_cd() to avoid needing to declare this function
before use.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci.c | 55 ++++++++++++++++++++++++------------------------
 1 file changed, 27 insertions(+), 28 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index be52a3a..839aa4c 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -53,7 +53,6 @@ static void sdhci_finish_data(struct sdhci_host *);
 static void sdhci_finish_command(struct sdhci_host *);
 static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
 static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
-static int sdhci_get_cd(struct mmc_host *mmc);
 
 #ifdef CONFIG_PM
 static void sdhci_runtime_pm_bus_on(struct sdhci_host *host);
@@ -161,6 +160,33 @@ static void sdhci_disable_card_detection(struct sdhci_host *host)
 	sdhci_set_card_detection(host, false);
 }
 
+static int sdhci_get_cd(struct mmc_host *mmc)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	int gpio_cd = mmc_gpio_get_cd(mmc);
+
+	if (host->flags & SDHCI_DEVICE_DEAD)
+		return 0;
+
+	/* If nonremovable, assume that the card is always present. */
+	if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
+		return 1;
+
+	/*
+	 * Try slot gpio detect, if defined it take precedence
+	 * over build in controller functionality
+	 */
+	if (!IS_ERR_VALUE(gpio_cd))
+		return !!gpio_cd;
+
+	/* If polling, assume that the card is always present. */
+	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
+		return 1;
+
+	/* Host native card detect */
+	return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
+}
+
 void sdhci_reset(struct sdhci_host *host, u8 mask)
 {
 	unsigned long timeout;
@@ -1551,33 +1577,6 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static int sdhci_get_cd(struct mmc_host *mmc)
-{
-	struct sdhci_host *host = mmc_priv(mmc);
-	int gpio_cd = mmc_gpio_get_cd(mmc);
-
-	if (host->flags & SDHCI_DEVICE_DEAD)
-		return 0;
-
-	/* If nonremovable, assume that the card is always present. */
-	if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
-		return 1;
-
-	/*
-	 * Try slot gpio detect, if defined it take precedence
-	 * over build in controller functionality
-	 */
-	if (!IS_ERR_VALUE(gpio_cd))
-		return !!gpio_cd;
-
-	/* If polling, assume that the card is always present. */
-	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
-		return 1;
-
-	/* Host native card detect */
-	return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
-}
-
 static int sdhci_check_ro(struct sdhci_host *host)
 {
 	unsigned long flags;
-- 
1.9.1

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

* [PATCH 03/23] mmc: core: fix a comment typo
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: ulf.hansson, chris, shawnguo, adrian.hunter, linux-arm-kernel,
	aisheng.dong, haibo.chen, dongas86

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/core/mmc_ops.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 62355bd..d220bbd 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -553,7 +553,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 
 		/*
 		 * We are not allowed to issue a status command and the host
-		 * does'nt support MMC_CAP_WAIT_WHILE_BUSY, then we can only
+		 * doesn't support MMC_CAP_WAIT_WHILE_BUSY, then we can only
 		 * rely on waiting for the stated timeout to be sufficient.
 		 */
 		if (!send_status) {
-- 
1.9.1


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

* [PATCH 03/23] mmc: core: fix a comment typo
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/core/mmc_ops.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 62355bd..d220bbd 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -553,7 +553,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 
 		/*
 		 * We are not allowed to issue a status command and the host
-		 * does'nt support MMC_CAP_WAIT_WHILE_BUSY, then we can only
+		 * doesn't support MMC_CAP_WAIT_WHILE_BUSY, then we can only
 		 * rely on waiting for the stated timeout to be sufficient.
 		 */
 		if (!send_status) {
-- 
1.9.1

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

* [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: aisheng.dong, ulf.hansson, dongas86, chris, haibo.chen,
	adrian.hunter, shawnguo, linux-arm-kernel

Handle host and regulator signal voltage switch separately.
Move host signal voltage switch code into a separated function
sdhci_do_signal_voltage_switch() first, the following patches will
remove the regulator voltage switch code and use the common
mmc_regulator_set_vqmmc() instead.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci.c | 97 ++++++++++++++++++++++++++++--------------------
 1 file changed, 57 insertions(+), 40 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 839aa4c..7f63f5d 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1657,19 +1657,10 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
-					     struct mmc_ios *ios)
+static int sdhci_do_signal_voltage_switch(struct sdhci_host *host,
+					  struct mmc_ios *ios)
 {
-	struct sdhci_host *host = mmc_priv(mmc);
 	u16 ctrl;
-	int ret;
-
-	/*
-	 * Signal Voltage Switching is only applicable for Host Controllers
-	 * v3.00 and above.
-	 */
-	if (host->version < SDHCI_SPEC_300)
-		return 0;
 
 	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 
@@ -1679,15 +1670,6 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
 		ctrl &= ~SDHCI_CTRL_VDD_180;
 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
-		if (!IS_ERR(mmc->supply.vqmmc)) {
-			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
-						    3600000);
-			if (ret) {
-				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
-					mmc_hostname(mmc));
-				return -EIO;
-			}
-		}
 		/* Wait for 5ms */
 		usleep_range(5000, 5500);
 
@@ -1697,20 +1679,10 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
 			return 0;
 
 		pr_warn("%s: 3.3V regulator output did not became stable\n",
-			mmc_hostname(mmc));
+			mmc_hostname(host->mmc));
 
 		return -EAGAIN;
 	case MMC_SIGNAL_VOLTAGE_180:
-		if (!IS_ERR(mmc->supply.vqmmc)) {
-			ret = regulator_set_voltage(mmc->supply.vqmmc,
-					1700000, 1950000);
-			if (ret) {
-				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
-					mmc_hostname(mmc));
-				return -EIO;
-			}
-		}
-
 		/*
 		 * Enable 1.8V Signal Enable in the Host Control2
 		 * register
@@ -1728,18 +1700,63 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
 			return 0;
 
 		pr_warn("%s: 1.8V regulator output did not became stable\n",
-			mmc_hostname(mmc));
+			mmc_hostname(host->mmc));
 
 		return -EAGAIN;
+	default:
+		/* No signal voltage switch required */
+		return 0;
+	}
+}
+
+static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
+					     struct mmc_ios *ios)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	int ret;
+
+	/*
+	 * Signal Voltage Switching is only applicable for Host Controllers
+	 * v3.00 and above.
+	 */
+	if (host->version < SDHCI_SPEC_300)
+		return 0;
+
+	ret = sdhci_do_signal_voltage_switch(host, ios);
+	if (ret)
+		return ret;
+
+	if (IS_ERR(mmc->supply.vqmmc))
+		return 0;
+
+	switch (ios->signal_voltage) {
+	case MMC_SIGNAL_VOLTAGE_330:
+		ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
+					    3600000);
+		if (ret) {
+			pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
+				mmc_hostname(mmc));
+			return -EIO;
+		}
+
+		return 0;
+	case MMC_SIGNAL_VOLTAGE_180:
+		ret = regulator_set_voltage(mmc->supply.vqmmc,
+				1700000, 1950000);
+		if (ret) {
+			pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
+				mmc_hostname(mmc));
+			return -EIO;
+		}
+
+		return 0;
 	case MMC_SIGNAL_VOLTAGE_120:
-		if (!IS_ERR(mmc->supply.vqmmc)) {
-			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
-						    1300000);
-			if (ret) {
-				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
-					mmc_hostname(mmc));
-				return -EIO;
-			}
+		ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
+					    1300000);
+		if (ret) {
+			pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
+				mmc_hostname(mmc));
+			return -EIO;
 		}
 		return 0;
 	default:
-- 
1.9.1

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

* [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

Handle host and regulator signal voltage switch separately.
Move host signal voltage switch code into a separated function
sdhci_do_signal_voltage_switch() first, the following patches will
remove the regulator voltage switch code and use the common
mmc_regulator_set_vqmmc() instead.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci.c | 97 ++++++++++++++++++++++++++++--------------------
 1 file changed, 57 insertions(+), 40 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 839aa4c..7f63f5d 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1657,19 +1657,10 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
-					     struct mmc_ios *ios)
+static int sdhci_do_signal_voltage_switch(struct sdhci_host *host,
+					  struct mmc_ios *ios)
 {
-	struct sdhci_host *host = mmc_priv(mmc);
 	u16 ctrl;
-	int ret;
-
-	/*
-	 * Signal Voltage Switching is only applicable for Host Controllers
-	 * v3.00 and above.
-	 */
-	if (host->version < SDHCI_SPEC_300)
-		return 0;
 
 	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 
@@ -1679,15 +1670,6 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
 		ctrl &= ~SDHCI_CTRL_VDD_180;
 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
-		if (!IS_ERR(mmc->supply.vqmmc)) {
-			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
-						    3600000);
-			if (ret) {
-				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
-					mmc_hostname(mmc));
-				return -EIO;
-			}
-		}
 		/* Wait for 5ms */
 		usleep_range(5000, 5500);
 
@@ -1697,20 +1679,10 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
 			return 0;
 
 		pr_warn("%s: 3.3V regulator output did not became stable\n",
-			mmc_hostname(mmc));
+			mmc_hostname(host->mmc));
 
 		return -EAGAIN;
 	case MMC_SIGNAL_VOLTAGE_180:
-		if (!IS_ERR(mmc->supply.vqmmc)) {
-			ret = regulator_set_voltage(mmc->supply.vqmmc,
-					1700000, 1950000);
-			if (ret) {
-				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
-					mmc_hostname(mmc));
-				return -EIO;
-			}
-		}
-
 		/*
 		 * Enable 1.8V Signal Enable in the Host Control2
 		 * register
@@ -1728,18 +1700,63 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
 			return 0;
 
 		pr_warn("%s: 1.8V regulator output did not became stable\n",
-			mmc_hostname(mmc));
+			mmc_hostname(host->mmc));
 
 		return -EAGAIN;
+	default:
+		/* No signal voltage switch required */
+		return 0;
+	}
+}
+
+static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
+					     struct mmc_ios *ios)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	int ret;
+
+	/*
+	 * Signal Voltage Switching is only applicable for Host Controllers
+	 * v3.00 and above.
+	 */
+	if (host->version < SDHCI_SPEC_300)
+		return 0;
+
+	ret = sdhci_do_signal_voltage_switch(host, ios);
+	if (ret)
+		return ret;
+
+	if (IS_ERR(mmc->supply.vqmmc))
+		return 0;
+
+	switch (ios->signal_voltage) {
+	case MMC_SIGNAL_VOLTAGE_330:
+		ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
+					    3600000);
+		if (ret) {
+			pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
+				mmc_hostname(mmc));
+			return -EIO;
+		}
+
+		return 0;
+	case MMC_SIGNAL_VOLTAGE_180:
+		ret = regulator_set_voltage(mmc->supply.vqmmc,
+				1700000, 1950000);
+		if (ret) {
+			pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
+				mmc_hostname(mmc));
+			return -EIO;
+		}
+
+		return 0;
 	case MMC_SIGNAL_VOLTAGE_120:
-		if (!IS_ERR(mmc->supply.vqmmc)) {
-			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
-						    1300000);
-			if (ret) {
-				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
-					mmc_hostname(mmc));
-				return -EIO;
-			}
+		ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
+					    1300000);
+		if (ret) {
+			pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
+				mmc_hostname(mmc));
+			return -EIO;
 		}
 		return 0;
 	default:
-- 
1.9.1

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

* [PATCH 05/23] mmc: core: mmc_regulator_set_vqmmc not return error if vqmmc/vmmc not exist
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: aisheng.dong, ulf.hansson, dongas86, chris, haibo.chen,
	adrian.hunter, shawnguo, linux-arm-kernel

Treat vqmmc/vmmc regulator the same way as mmc_regulator_get_supply()
in mmc_regulator_set_vqmmc(), since they're optional, do not return an
error if not exist.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/core/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 99275e4..52bfaf0 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1440,7 +1440,7 @@ int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios)
 
 	/* If no vqmmc supply then we can't change the voltage */
 	if (IS_ERR(mmc->supply.vqmmc))
-		return -EINVAL;
+		return 0;
 
 	switch (ios->signal_voltage) {
 	case MMC_SIGNAL_VOLTAGE_120:
-- 
1.9.1

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

* [PATCH 05/23] mmc: core: mmc_regulator_set_vqmmc not return error if vqmmc/vmmc not exist
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

Treat vqmmc/vmmc regulator the same way as mmc_regulator_get_supply()
in mmc_regulator_set_vqmmc(), since they're optional, do not return an
error if not exist.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/core/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 99275e4..52bfaf0 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1440,7 +1440,7 @@ int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios)
 
 	/* If no vqmmc supply then we can't change the voltage */
 	if (IS_ERR(mmc->supply.vqmmc))
-		return -EINVAL;
+		return 0;
 
 	switch (ios->signal_voltage) {
 	case MMC_SIGNAL_VOLTAGE_120:
-- 
1.9.1

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

* [PATCH 06/23] mmc: sdhci: using common mmc_regulator_set_vqmmc()
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: ulf.hansson, chris, shawnguo, adrian.hunter, linux-arm-kernel,
	aisheng.dong, haibo.chen, dongas86

Instead of using private VCCQ regulator signal voltage switch code,
we switch to use the more robust common function mmc_regulator_set_vqmmc()
in MMC core which set the target voltage as close as possible to target
voltage.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
Don't have a board to test mmc_regulator_set_vqmmc() switch way,
need others to help verify.
---
 drivers/mmc/host/sdhci.c | 39 ++-------------------------------------
 1 file changed, 2 insertions(+), 37 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 7f63f5d..2338aab 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1726,43 +1726,8 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
 	if (ret)
 		return ret;
 
-	if (IS_ERR(mmc->supply.vqmmc))
-		return 0;
-
-	switch (ios->signal_voltage) {
-	case MMC_SIGNAL_VOLTAGE_330:
-		ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
-					    3600000);
-		if (ret) {
-			pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
-				mmc_hostname(mmc));
-			return -EIO;
-		}
-
-		return 0;
-	case MMC_SIGNAL_VOLTAGE_180:
-		ret = regulator_set_voltage(mmc->supply.vqmmc,
-				1700000, 1950000);
-		if (ret) {
-			pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
-				mmc_hostname(mmc));
-			return -EIO;
-		}
-
-		return 0;
-	case MMC_SIGNAL_VOLTAGE_120:
-		ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
-					    1300000);
-		if (ret) {
-			pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
-				mmc_hostname(mmc));
-			return -EIO;
-		}
-		return 0;
-	default:
-		/* No signal voltage switch required */
-		return 0;
-	}
+	/* do regulator signal voltage switch if exist */
+	return mmc_regulator_set_vqmmc(mmc, ios);
 }
 
 static int sdhci_card_busy(struct mmc_host *mmc)
-- 
1.9.1


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

* [PATCH 06/23] mmc: sdhci: using common mmc_regulator_set_vqmmc()
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

Instead of using private VCCQ regulator signal voltage switch code,
we switch to use the more robust common function mmc_regulator_set_vqmmc()
in MMC core which set the target voltage as close as possible to target
voltage.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
Don't have a board to test mmc_regulator_set_vqmmc() switch way,
need others to help verify.
---
 drivers/mmc/host/sdhci.c | 39 ++-------------------------------------
 1 file changed, 2 insertions(+), 37 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 7f63f5d..2338aab 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1726,43 +1726,8 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
 	if (ret)
 		return ret;
 
-	if (IS_ERR(mmc->supply.vqmmc))
-		return 0;
-
-	switch (ios->signal_voltage) {
-	case MMC_SIGNAL_VOLTAGE_330:
-		ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
-					    3600000);
-		if (ret) {
-			pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
-				mmc_hostname(mmc));
-			return -EIO;
-		}
-
-		return 0;
-	case MMC_SIGNAL_VOLTAGE_180:
-		ret = regulator_set_voltage(mmc->supply.vqmmc,
-				1700000, 1950000);
-		if (ret) {
-			pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
-				mmc_hostname(mmc));
-			return -EIO;
-		}
-
-		return 0;
-	case MMC_SIGNAL_VOLTAGE_120:
-		ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
-					    1300000);
-		if (ret) {
-			pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
-				mmc_hostname(mmc));
-			return -EIO;
-		}
-		return 0;
-	default:
-		/* No signal voltage switch required */
-		return 0;
-	}
+	/* do regulator signal voltage switch if exist */
+	return mmc_regulator_set_vqmmc(mmc, ios);
 }
 
 static int sdhci_card_busy(struct mmc_host *mmc)
-- 
1.9.1

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

* [PATCH 07/23] mmc: sdhci: check SDHCI_QUIRK2_NO_1_8_V when do voltage switch
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: ulf.hansson, chris, shawnguo, adrian.hunter, linux-arm-kernel,
	aisheng.dong, haibo.chen, dongas86

Currently when card type supports EXT_CSD_CARD_TYPE_DDR_1_8V
which means it can work on DDR mode with either 3.3v IO or 1.8v
IO voltage. MMC core will first try 1.8v then 3.3v if host claims
MMC_CAP_1_8V_DDR support.
However the host driver voltage switch code does not check NO_1_8_V
quirk which may set a wrong 1.8v and causes the card fixed to 3.3v
VIO un-work.

Checking 1.8V quirk before setting it to avoid such issue.

CC: stable <stable@vger.kernel.org>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 2338aab..96ccb15 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1683,6 +1683,8 @@ static int sdhci_do_signal_voltage_switch(struct sdhci_host *host,
 
 		return -EAGAIN;
 	case MMC_SIGNAL_VOLTAGE_180:
+		if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)
+			return -EINVAL;
 		/*
 		 * Enable 1.8V Signal Enable in the Host Control2
 		 * register
-- 
1.9.1


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

* [PATCH 07/23] mmc: sdhci: check SDHCI_QUIRK2_NO_1_8_V when do voltage switch
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

Currently when card type supports EXT_CSD_CARD_TYPE_DDR_1_8V
which means it can work on DDR mode with either 3.3v IO or 1.8v
IO voltage. MMC core will first try 1.8v then 3.3v if host claims
MMC_CAP_1_8V_DDR support.
However the host driver voltage switch code does not check NO_1_8_V
quirk which may set a wrong 1.8v and causes the card fixed to 3.3v
VIO un-work.

Checking 1.8V quirk before setting it to avoid such issue.

CC: stable <stable@vger.kernel.org>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 2338aab..96ccb15 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1683,6 +1683,8 @@ static int sdhci_do_signal_voltage_switch(struct sdhci_host *host,
 
 		return -EAGAIN;
 	case MMC_SIGNAL_VOLTAGE_180:
+		if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)
+			return -EINVAL;
 		/*
 		 * Enable 1.8V Signal Enable in the Host Control2
 		 * register
-- 
1.9.1

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

* [PATCH 08/23] mmc: sdhci: rename quirk SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: ulf.hansson, chris, shawnguo, adrian.hunter, linux-arm-kernel,
	aisheng.dong, haibo.chen, dongas86

Rename ACMD12 quirk to SDHCI_QUIRK_MULTIBLOCK_ACMD12 to avoid confusion
since it's needed for both read and write.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-pci-o2micro.c | 2 +-
 drivers/mmc/host/sdhci-pltfm.c       | 2 +-
 drivers/mmc/host/sdhci-s3c.c         | 2 +-
 drivers/mmc/host/sdhci.c             | 2 +-
 drivers/mmc/host/sdhci.h             | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
index d48f031..1ed1f995 100644
--- a/drivers/mmc/host/sdhci-pci-o2micro.c
+++ b/drivers/mmc/host/sdhci-pci-o2micro.c
@@ -162,7 +162,7 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
 	case PCI_DEVICE_ID_O2_FUJIN2:
 		reg = sdhci_readl(host, O2_SD_VENDOR_SETTING);
 		if (reg & 0x1)
-			host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
+			host->quirks |= SDHCI_QUIRK_MULTIBLOCK_ACMD12;
 
 		if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2)
 			break;
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index 072bb27..206057a 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -74,7 +74,7 @@ void sdhci_get_of_property(struct platform_device *pdev)
 	u32 bus_width;
 
 	if (of_get_property(np, "sdhci,auto-cmd12", NULL))
-		host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
+		host->quirks |= SDHCI_QUIRK_MULTIBLOCK_ACMD12;
 
 	if (of_get_property(np, "sdhci,1-bit-only", NULL) ||
 	    (of_property_read_u32(np, "bus-width", &bus_width) == 0 &&
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 70c724b..756b9bb 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -564,7 +564,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
 	host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ;
 
 	/* This host supports the Auto CMD12 */
-	host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
+	host->quirks |= SDHCI_QUIRK_MULTIBLOCK_ACMD12;
 
 	/* Samsung SoCs need BROKEN_ADMA_ZEROLEN_DESC */
 	host->quirks |= SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 96ccb15..40e3551 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2988,7 +2988,7 @@ int sdhci_add_host(struct sdhci_host *host)
 	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
 	mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
 
-	if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
+	if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_ACMD12)
 		host->flags |= SDHCI_AUTO_CMD12;
 
 	/* Auto-CMD23 stuff only works in ADMA or PIO. */
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 0f39f4f..afa4de8 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -379,7 +379,7 @@ struct sdhci_host {
 /* Controller is missing device caps. Use caps provided by host */
 #define SDHCI_QUIRK_MISSING_CAPS			(1<<27)
 /* Controller uses Auto CMD12 command to stop the transfer */
-#define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12		(1<<28)
+#define SDHCI_QUIRK_MULTIBLOCK_ACMD12			(1<<28)
 /* Controller doesn't have HISPD bit field in HI-SPEED SD card */
 #define SDHCI_QUIRK_NO_HISPD_BIT			(1<<29)
 /* Controller treats ADMA descriptors with length 0000h incorrectly */
-- 
1.9.1


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

* [PATCH 08/23] mmc: sdhci: rename quirk SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

Rename ACMD12 quirk to SDHCI_QUIRK_MULTIBLOCK_ACMD12 to avoid confusion
since it's needed for both read and write.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-pci-o2micro.c | 2 +-
 drivers/mmc/host/sdhci-pltfm.c       | 2 +-
 drivers/mmc/host/sdhci-s3c.c         | 2 +-
 drivers/mmc/host/sdhci.c             | 2 +-
 drivers/mmc/host/sdhci.h             | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
index d48f031..1ed1f995 100644
--- a/drivers/mmc/host/sdhci-pci-o2micro.c
+++ b/drivers/mmc/host/sdhci-pci-o2micro.c
@@ -162,7 +162,7 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
 	case PCI_DEVICE_ID_O2_FUJIN2:
 		reg = sdhci_readl(host, O2_SD_VENDOR_SETTING);
 		if (reg & 0x1)
-			host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
+			host->quirks |= SDHCI_QUIRK_MULTIBLOCK_ACMD12;
 
 		if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2)
 			break;
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index 072bb27..206057a 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -74,7 +74,7 @@ void sdhci_get_of_property(struct platform_device *pdev)
 	u32 bus_width;
 
 	if (of_get_property(np, "sdhci,auto-cmd12", NULL))
-		host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
+		host->quirks |= SDHCI_QUIRK_MULTIBLOCK_ACMD12;
 
 	if (of_get_property(np, "sdhci,1-bit-only", NULL) ||
 	    (of_property_read_u32(np, "bus-width", &bus_width) == 0 &&
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 70c724b..756b9bb 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -564,7 +564,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
 	host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ;
 
 	/* This host supports the Auto CMD12 */
-	host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
+	host->quirks |= SDHCI_QUIRK_MULTIBLOCK_ACMD12;
 
 	/* Samsung SoCs need BROKEN_ADMA_ZEROLEN_DESC */
 	host->quirks |= SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 96ccb15..40e3551 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2988,7 +2988,7 @@ int sdhci_add_host(struct sdhci_host *host)
 	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
 	mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
 
-	if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
+	if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_ACMD12)
 		host->flags |= SDHCI_AUTO_CMD12;
 
 	/* Auto-CMD23 stuff only works in ADMA or PIO. */
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 0f39f4f..afa4de8 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -379,7 +379,7 @@ struct sdhci_host {
 /* Controller is missing device caps. Use caps provided by host */
 #define SDHCI_QUIRK_MISSING_CAPS			(1<<27)
 /* Controller uses Auto CMD12 command to stop the transfer */
-#define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12		(1<<28)
+#define SDHCI_QUIRK_MULTIBLOCK_ACMD12			(1<<28)
 /* Controller doesn't have HISPD bit field in HI-SPEED SD card */
 #define SDHCI_QUIRK_NO_HISPD_BIT			(1<<29)
 /* Controller treats ADMA descriptors with length 0000h incorrectly */
-- 
1.9.1

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

* [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during no data transfer
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: ulf.hansson, chris, shawnguo, adrian.hunter, linux-arm-kernel,
	aisheng.dong, haibo.chen, dongas86

Current code will report the wrong data interrupt got when no
data operation in progress assumed by getting !host->data in
sdhci_data_irq().

For a data command handling process, the driver will call
sdhci_finish_data() and clear host->data in case any data error,
then card finish_tasklet will do the rest controller reset work.

Before the tasklet got run, however, controllers may report the
TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
than data CRC error and data end bit error interrupts for single
block transfer or the last block of multiblock transfer.

Controller usually detects and generates data CRC/end bit error
interrupts once one block on the bus is transferred completely.
For single block transfer, since there's only one bock to transfer,
the controller will report transfer complete interrupt as well,
but until the data in controller FIFO has been successfully
transferred to memory. The time gap of TC and CRC interrupt depends on
the system busy state at that point and memory bus access speed.

So it is possible when TC interrupt generated, host->data is already
equal to NULL due to cleared by former CRC/Data End Bit error which
is reasonable.

Thus we DO NOT report the weird data interrupt event for this case.

Else we may easily see warning below during SD3.0 card manually tuning
process (calling mmc_send_tuning() which is a single block transfer)
mmc0: Got data interrupt 0x00000002 even though no data operation was in progress

The detailed command log is as follows:
[ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
[ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
[ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
[ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
[ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
[ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
[ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
[ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
[ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
[ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
[ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
[ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
[ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
[ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
[ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
[ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
[ 1657.929965] sdhci: Host ctl2: 0x000000c8
[ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
[ 1657.929995] sdhci: ===========================================
[ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
[ 1657.930179] mmc0:     0 bytes transferred: -84

It shows we first have a data CRC error interrupt then a data transfer
complete interrupt.
Then we got the !host->data case in sdhci_data_irq().

CC: stable <stable@vger.kernel.org>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 40e3551..2eb0e34 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
 			}
 		}
 
+		/*
+		 * The "data complete" interrupt is possible to happen a bit
+		 * later than CRC error and data end bit error interrupts
+		 * separately for single block transfer or the last block of
+		 * multiblock transfer. For this case, we DO NOT report the
+		 * weird data interrupt event.
+		 */
+		if ((intmask & SDHCI_INT_DATA_END) &&
+		    (host->mrq && host->mrq->data && host->mrq->data->error))
+			return;
+
 		pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
 		       mmc_hostname(host->mmc), (unsigned)intmask);
 		sdhci_dumpregs(host);
-- 
1.9.1


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

* [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during no data transfer
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

Current code will report the wrong data interrupt got when no
data operation in progress assumed by getting !host->data in
sdhci_data_irq().

For a data command handling process, the driver will call
sdhci_finish_data() and clear host->data in case any data error,
then card finish_tasklet will do the rest controller reset work.

Before the tasklet got run, however, controllers may report the
TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
than data CRC error and data end bit error interrupts for single
block transfer or the last block of multiblock transfer.

Controller usually detects and generates data CRC/end bit error
interrupts once one block on the bus is transferred completely.
For single block transfer, since there's only one bock to transfer,
the controller will report transfer complete interrupt as well,
but until the data in controller FIFO has been successfully
transferred to memory. The time gap of TC and CRC interrupt depends on
the system busy state at that point and memory bus access speed.

So it is possible when TC interrupt generated, host->data is already
equal to NULL due to cleared by former CRC/Data End Bit error which
is reasonable.

Thus we DO NOT report the weird data interrupt event for this case.

Else we may easily see warning below during SD3.0 card manually tuning
process (calling mmc_send_tuning() which is a single block transfer)
mmc0: Got data interrupt 0x00000002 even though no data operation was in progress

The detailed command log is as follows:
[ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
[ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
[ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
[ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
[ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
[ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
[ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
[ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
[ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
[ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
[ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
[ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
[ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
[ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
[ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
[ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
[ 1657.929965] sdhci: Host ctl2: 0x000000c8
[ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
[ 1657.929995] sdhci: ===========================================
[ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
[ 1657.930179] mmc0:     0 bytes transferred: -84

It shows we first have a data CRC error interrupt then a data transfer
complete interrupt.
Then we got the !host->data case in sdhci_data_irq().

CC: stable <stable@vger.kernel.org>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 40e3551..2eb0e34 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
 			}
 		}
 
+		/*
+		 * The "data complete" interrupt is possible to happen a bit
+		 * later than CRC error and data end bit error interrupts
+		 * separately for single block transfer or the last block of
+		 * multiblock transfer. For this case, we DO NOT report the
+		 * weird data interrupt event.
+		 */
+		if ((intmask & SDHCI_INT_DATA_END) &&
+		    (host->mrq && host->mrq->data && host->mrq->data->error))
+			return;
+
 		pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
 		       mmc_hostname(host->mmc), (unsigned)intmask);
 		sdhci_dumpregs(host);
-- 
1.9.1

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

* [PATCH 10/23] mmc: core: disable auto retune during card detection process
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: aisheng.dong, ulf.hansson, dongas86, chris, haibo.chen,
	adrian.hunter, shawnguo, linux-arm-kernel

During card detection process, mmc core may sends commands
to detect if card is still exist in mmc_rescan for removable
card which may trigger mmc retuning process after a bit time
of runtime pm suspend.
Obviously this retuning process is meaningless for card remove
case, so we disable mmc_retune in mmc_detect_change() for it.
For card insert case, the mmc_retune will be enabled normally
in its card initialization process later in mmc_execute_tuning().
So disable it at first has no side effection.

CC: stable <stable@vger.kernel.org>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/core/core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 52bfaf0..76d0802 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1888,6 +1888,7 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
 		pm_wakeup_event(mmc_dev(host), 5000);
 
 	host->detect_change = 1;
+	mmc_retune_disable(host);
 	mmc_schedule_delayed_work(&host->detect, delay);
 }
 
-- 
1.9.1

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

* [PATCH 10/23] mmc: core: disable auto retune during card detection process
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

During card detection process, mmc core may sends commands
to detect if card is still exist in mmc_rescan for removable
card which may trigger mmc retuning process after a bit time
of runtime pm suspend.
Obviously this retuning process is meaningless for card remove
case, so we disable mmc_retune in mmc_detect_change() for it.
For card insert case, the mmc_retune will be enabled normally
in its card initialization process later in mmc_execute_tuning().
So disable it at first has no side effection.

CC: stable <stable@vger.kernel.org>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/core/core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 52bfaf0..76d0802 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1888,6 +1888,7 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
 		pm_wakeup_event(mmc_dev(host), 5000);
 
 	host->detect_change = 1;
+	mmc_retune_disable(host);
 	mmc_schedule_delayed_work(&host->detect, delay);
 }
 
-- 
1.9.1

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

* [PATCH 11/23] mmc: sdhci-esdhci-imx: remove SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: aisheng.dong, ulf.hansson, dongas86, chris, haibo.chen,
	adrian.hunter, shawnguo, linux-arm-kernel

The driver has already implemented the private .set_timeout()
callback for common SDHCI code to do correct timeout value setting,
it does not need call sdhci_calc_timeout(), so this quirk actually
is not working. Remove it now.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 2d300d8..03980db 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -1147,8 +1147,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
 	if (IS_ERR(imx_data->pins_default))
 		dev_warn(mmc_dev(host->mmc), "could not get default state\n");
 
-	host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
-
 	if (imx_data->socdata->flags & ESDHC_FLAG_ENGCM07207)
 		/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
 		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK
-- 
1.9.1

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

* [PATCH 11/23] mmc: sdhci-esdhci-imx: remove SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

The driver has already implemented the private .set_timeout()
callback for common SDHCI code to do correct timeout value setting,
it does not need call sdhci_calc_timeout(), so this quirk actually
is not working. Remove it now.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 2d300d8..03980db 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -1147,8 +1147,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
 	if (IS_ERR(imx_data->pins_default))
 		dev_warn(mmc_dev(host->mmc), "could not get default state\n");
 
-	host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
-
 	if (imx_data->socdata->flags & ESDHC_FLAG_ENGCM07207)
 		/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
 		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK
-- 
1.9.1

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

* [PATCH 12/23] mmc: sdhci-esdhc-imx: add esdhc specific suspend resume callback
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: aisheng.dong, ulf.hansson, dongas86, chris, haibo.chen,
	adrian.hunter, shawnguo, linux-arm-kernel

It will be used for platform specific suspend/resume state save/restore
work for some low power mode like Mega/Fast or LPSR mode.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 03980db..6fef6bc 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -1254,6 +1254,16 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
+static int sdhci_esdhc_suspend(struct device *dev)
+{
+	return sdhci_pltfm_suspend(dev);
+}
+
+static int sdhci_esdhc_resume(struct device *dev)
+{
+	return sdhci_pltfm_resume(dev);
+}
+
 static int sdhci_esdhc_runtime_suspend(struct device *dev)
 {
 	struct sdhci_host *host = dev_get_drvdata(dev);
@@ -1289,7 +1299,7 @@ static int sdhci_esdhc_runtime_resume(struct device *dev)
 #endif
 
 static const struct dev_pm_ops sdhci_esdhc_pmops = {
-	SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_suspend, sdhci_pltfm_resume)
+	SET_SYSTEM_SLEEP_PM_OPS(sdhci_esdhc_suspend, sdhci_esdhc_resume)
 	SET_RUNTIME_PM_OPS(sdhci_esdhc_runtime_suspend,
 				sdhci_esdhc_runtime_resume, NULL)
 };
-- 
1.9.1

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

* [PATCH 12/23] mmc: sdhci-esdhc-imx: add esdhc specific suspend resume callback
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

It will be used for platform specific suspend/resume state save/restore
work for some low power mode like Mega/Fast or LPSR mode.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 03980db..6fef6bc 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -1254,6 +1254,16 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
+static int sdhci_esdhc_suspend(struct device *dev)
+{
+	return sdhci_pltfm_suspend(dev);
+}
+
+static int sdhci_esdhc_resume(struct device *dev)
+{
+	return sdhci_pltfm_resume(dev);
+}
+
 static int sdhci_esdhc_runtime_suspend(struct device *dev)
 {
 	struct sdhci_host *host = dev_get_drvdata(dev);
@@ -1289,7 +1299,7 @@ static int sdhci_esdhc_runtime_resume(struct device *dev)
 #endif
 
 static const struct dev_pm_ops sdhci_esdhc_pmops = {
-	SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_suspend, sdhci_pltfm_resume)
+	SET_SYSTEM_SLEEP_PM_OPS(sdhci_esdhc_suspend, sdhci_esdhc_resume)
 	SET_RUNTIME_PM_OPS(sdhci_esdhc_runtime_suspend,
 				sdhci_esdhc_runtime_resume, NULL)
 };
-- 
1.9.1

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

* [PATCH 13/23] mmc: sdhci-esdhc-imx: restore watermark level setting after resume
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: aisheng.dong, ulf.hansson, dongas86, chris, haibo.chen,
	adrian.hunter, shawnguo, linux-arm-kernel

Currently, we config the watermark_level register only in probe.
This will cause the mmc write operation timeout issue after system
resume back in LPSR mode. Because in LPSR mode, after system resume
back, the watermark_level register(0x44) changes to 0x08000880, which
set the write watermark level as 0, and set the read watermark level
as 128. This value is incorrect.

This patch restores the setting of watermark level register after
system resume back.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 6fef6bc..4c28fbb 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -1261,6 +1261,11 @@ static int sdhci_esdhc_suspend(struct device *dev)
 
 static int sdhci_esdhc_resume(struct device *dev)
 {
+	struct sdhci_host *host = dev_get_drvdata(dev);
+
+	/* restore watermark setting in case it's lost in low power mode */
+	writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
+
 	return sdhci_pltfm_resume(dev);
 }
 
-- 
1.9.1

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

* [PATCH 13/23] mmc: sdhci-esdhc-imx: restore watermark level setting after resume
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

Currently, we config the watermark_level register only in probe.
This will cause the mmc write operation timeout issue after system
resume back in LPSR mode. Because in LPSR mode, after system resume
back, the watermark_level register(0x44) changes to 0x08000880, which
set the write watermark level as 0, and set the read watermark level
as 128. This value is incorrect.

This patch restores the setting of watermark level register after
system resume back.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 6fef6bc..4c28fbb 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -1261,6 +1261,11 @@ static int sdhci_esdhc_suspend(struct device *dev)
 
 static int sdhci_esdhc_resume(struct device *dev)
 {
+	struct sdhci_host *host = dev_get_drvdata(dev);
+
+	/* restore watermark setting in case it's lost in low power mode */
+	writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
+
 	return sdhci_pltfm_resume(dev);
 }
 
-- 
1.9.1

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

* [PATCH 14/23] mmc: sdhci-esdhci-imx: disable DLL delay line settings explicitly
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: aisheng.dong, ulf.hansson, dongas86, chris, haibo.chen,
	adrian.hunter, shawnguo, linux-arm-kernel

From: Dong Aisheng <aisheng.dong@freescale.com>

Disable DLL delay line settings explicitly during driver initialization
in case ROM/uBoot had set an invalid delay.
e.g. MX6DL ROM has set the default delay line(DLLCTRL) to 0x1000021,
the uSDHC clock timing will become marginal when works on DDR mode
due to default delay and will possibly see CRC errors in case the board
is not perfectly designed on the eMMC chip layout.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 4c28fbb..d02db66 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -1186,6 +1186,9 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
 		*/
 		writel(readl(host->ioaddr + 0x6c) | BIT(7),
 			host->ioaddr + 0x6c);
+
+		/* disable DLL_CTRL delay line settings */
+		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
 	}
 
 	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
-- 
1.9.1

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

* [PATCH 14/23] mmc: sdhci-esdhci-imx: disable DLL delay line settings explicitly
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

From: Dong Aisheng <aisheng.dong@freescale.com>

Disable DLL delay line settings explicitly during driver initialization
in case ROM/uBoot had set an invalid delay.
e.g. MX6DL ROM has set the default delay line(DLLCTRL) to 0x1000021,
the uSDHC clock timing will become marginal when works on DDR mode
due to default delay and will possibly see CRC errors in case the board
is not perfectly designed on the eMMC chip layout.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 4c28fbb..d02db66 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -1186,6 +1186,9 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
 		*/
 		writel(readl(host->ioaddr + 0x6c) | BIT(7),
 			host->ioaddr + 0x6c);
+
+		/* disable DLL_CTRL delay line settings */
+		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
 	}
 
 	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
-- 
1.9.1

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

* [PATCH 15/23] mmc: sdhci-esdhc-imx: support setting tuning start point
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: ulf.hansson, chris, shawnguo, adrian.hunter, linux-arm-kernel,
	aisheng.dong, haibo.chen, dongas86

The delay cells of some SoCs may have less delay per one cell,
for such SoCs, user could set the start delay cell point to bypass
the first a few meaningless tuning commands.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c          | 14 +++++++++++---
 include/linux/platform_data/mmc-esdhc-imx.h |  1 +
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index d02db66..9f9be3f 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -75,7 +75,8 @@
 #define ESDHC_TUNING_CTRL		0xcc
 #define ESDHC_STD_TUNING_EN		(1 << 24)
 /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */
-#define ESDHC_TUNING_START_TAP		0x1
+#define ESDHC_TUNING_START_TAP_DEFAULT	0x1
+#define ESDHC_TUNING_START_TAP_MASK	0xff
 #define ESDHC_TUNING_STEP_MASK		0x00070000
 #define ESDHC_TUNING_STEP_SHIFT		16
 
@@ -489,7 +490,12 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 				v |= ESDHC_MIX_CTRL_EXE_TUNE;
 				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
 				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
-				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP;
+				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT;
+				if (imx_data->boarddata.tuning_start_tap) {
+					tuning_ctrl &= ~ESDHC_TUNING_START_TAP_MASK;
+					tuning_ctrl |= imx_data->boarddata.tuning_start_tap;
+				}
+
 				if (imx_data->boarddata.tuning_step) {
 					tuning_ctrl &= ~ESDHC_TUNING_STEP_MASK;
 					tuning_ctrl |= imx_data->boarddata.tuning_step << ESDHC_TUNING_STEP_SHIFT;
@@ -975,6 +981,8 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
 		boarddata->wp_type = ESDHC_WP_GPIO;
 
 	of_property_read_u32(np, "fsl,tuning-step", &boarddata->tuning_step);
+	of_property_read_u32(np, "fsl,tuning-start-tap",
+			     &boarddata->tuning_start_tap);
 
 	if (of_find_property(np, "no-1-8-v", NULL))
 		boarddata->support_vsel = false;
@@ -1197,7 +1205,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
 
 	if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING)
 		writel(readl(host->ioaddr + ESDHC_TUNING_CTRL) |
-			ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP,
+			ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT,
 			host->ioaddr + ESDHC_TUNING_CTRL);
 
 	if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h
index 95ccab3..7daa78a 100644
--- a/include/linux/platform_data/mmc-esdhc-imx.h
+++ b/include/linux/platform_data/mmc-esdhc-imx.h
@@ -46,5 +46,6 @@ struct esdhc_platform_data {
 	bool support_vsel;
 	unsigned int delay_line;
 	unsigned int tuning_step;       /* The delay cell steps in tuning procedure */
+	unsigned int tuning_start_tap;	/* The start delay cell point in tuning procedure */
 };
 #endif /* __ASM_ARCH_IMX_ESDHC_H */
-- 
1.9.1


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

* [PATCH 15/23] mmc: sdhci-esdhc-imx: support setting tuning start point
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

The delay cells of some SoCs may have less delay per one cell,
for such SoCs, user could set the start delay cell point to bypass
the first a few meaningless tuning commands.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c          | 14 +++++++++++---
 include/linux/platform_data/mmc-esdhc-imx.h |  1 +
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index d02db66..9f9be3f 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -75,7 +75,8 @@
 #define ESDHC_TUNING_CTRL		0xcc
 #define ESDHC_STD_TUNING_EN		(1 << 24)
 /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */
-#define ESDHC_TUNING_START_TAP		0x1
+#define ESDHC_TUNING_START_TAP_DEFAULT	0x1
+#define ESDHC_TUNING_START_TAP_MASK	0xff
 #define ESDHC_TUNING_STEP_MASK		0x00070000
 #define ESDHC_TUNING_STEP_SHIFT		16
 
@@ -489,7 +490,12 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 				v |= ESDHC_MIX_CTRL_EXE_TUNE;
 				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
 				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
-				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP;
+				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT;
+				if (imx_data->boarddata.tuning_start_tap) {
+					tuning_ctrl &= ~ESDHC_TUNING_START_TAP_MASK;
+					tuning_ctrl |= imx_data->boarddata.tuning_start_tap;
+				}
+
 				if (imx_data->boarddata.tuning_step) {
 					tuning_ctrl &= ~ESDHC_TUNING_STEP_MASK;
 					tuning_ctrl |= imx_data->boarddata.tuning_step << ESDHC_TUNING_STEP_SHIFT;
@@ -975,6 +981,8 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
 		boarddata->wp_type = ESDHC_WP_GPIO;
 
 	of_property_read_u32(np, "fsl,tuning-step", &boarddata->tuning_step);
+	of_property_read_u32(np, "fsl,tuning-start-tap",
+			     &boarddata->tuning_start_tap);
 
 	if (of_find_property(np, "no-1-8-v", NULL))
 		boarddata->support_vsel = false;
@@ -1197,7 +1205,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
 
 	if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING)
 		writel(readl(host->ioaddr + ESDHC_TUNING_CTRL) |
-			ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP,
+			ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT,
 			host->ioaddr + ESDHC_TUNING_CTRL);
 
 	if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h
index 95ccab3..7daa78a 100644
--- a/include/linux/platform_data/mmc-esdhc-imx.h
+++ b/include/linux/platform_data/mmc-esdhc-imx.h
@@ -46,5 +46,6 @@ struct esdhc_platform_data {
 	bool support_vsel;
 	unsigned int delay_line;
 	unsigned int tuning_step;       /* The delay cell steps in tuning procedure */
+	unsigned int tuning_start_tap;	/* The start delay cell point in tuning procedure */
 };
 #endif /* __ASM_ARCH_IMX_ESDHC_H */
-- 
1.9.1

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

* [PATCH 16/23] doc: dt: fsl-imx-esdhc: add set tuning start point binding
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: aisheng.dong, ulf.hansson, dongas86, chris, haibo.chen,
	adrian.hunter, shawnguo, linux-arm-kernel

add tuning start point binding

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
index dca56d6..3e29050 100644
--- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
+++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
@@ -28,6 +28,8 @@ Optional properties:
   transparent level shifters on the outputs of the controller. Two cells are
   required, first cell specifies minimum slot voltage (mV), second cell
   specifies maximum slot voltage (mV). Several ranges could be specified.
+- fsl,tuning-start-tap: Specify the start dealy cell point when send first CMD19
+  in tuning procedure.
 - fsl,tuning-step: Specify the increasing delay cell steps in tuning procedure.
   The uSDHC use one delay cell as default increasing step to do tuning process.
   This property allows user to change the tuning step to more than one delay
-- 
1.9.1

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

* [PATCH 16/23] doc: dt: fsl-imx-esdhc: add set tuning start point binding
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

add tuning start point binding

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
index dca56d6..3e29050 100644
--- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
+++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
@@ -28,6 +28,8 @@ Optional properties:
   transparent level shifters on the outputs of the controller. Two cells are
   required, first cell specifies minimum slot voltage (mV), second cell
   specifies maximum slot voltage (mV). Several ranges could be specified.
+- fsl,tuning-start-tap: Specify the start dealy cell point when send first CMD19
+  in tuning procedure.
 - fsl,tuning-step: Specify the increasing delay cell steps in tuning procedure.
   The uSDHC use one delay cell as default increasing step to do tuning process.
   This property allows user to change the tuning step to more than one delay
-- 
1.9.1

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

* [PATCH 17/23] mmc: sdhci: add standard hw auto retuning support
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: aisheng.dong, ulf.hansson, dongas86, chris, haibo.chen,
	adrian.hunter, shawnguo, linux-arm-kernel

If HW supports SDHCI_TUNING_MODE_3 which is auto retuning, we won't
retune during runtime suspend and resume, instead we use Re-tuning
Request signaled via SDHCI_INT_RETUNE interrupt to do retuning and
hw auto retuning during data transfer to guarantee the signal sample
window correction.

This can avoid a mass of repeatly retuning during small file system
data access and improve the performance.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci.c | 18 ++++++++++++++----
 drivers/mmc/host/sdhci.h |  3 +++
 2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 2eb0e34..0027b87 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -252,6 +252,9 @@ static void sdhci_init(struct sdhci_host *host, int soft)
 		    SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END |
 		    SDHCI_INT_RESPONSE;
 
+	if (host->tuning_mode == SDHCI_TUNING_MODE_3)
+		host->ier |= SDHCI_INT_RETUNE;
+
 	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
 	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
 
@@ -2477,6 +2480,9 @@ 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_RETUNE)
+			mmc_retune_needed(host->mmc);
+
 		if (intmask & SDHCI_INT_CARD_INT) {
 			sdhci_enable_sdio_irq_nolock(host, false);
 			host->thread_isr |= SDHCI_INT_CARD_INT;
@@ -2575,8 +2581,10 @@ int sdhci_suspend_host(struct sdhci_host *host)
 {
 	sdhci_disable_card_detection(host);
 
-	mmc_retune_timer_stop(host->mmc);
-	mmc_retune_needed(host->mmc);
+	if (host->tuning_mode == SDHCI_TUNING_MODE_1) {
+		mmc_retune_timer_stop(host->mmc);
+		mmc_retune_needed(host->mmc);
+	}
 
 	if (!device_may_wakeup(mmc_dev(host->mmc))) {
 		host->ier = 0;
@@ -2651,8 +2659,10 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
 {
 	unsigned long flags;
 
-	mmc_retune_timer_stop(host->mmc);
-	mmc_retune_needed(host->mmc);
+	if (host->tuning_mode == SDHCI_TUNING_MODE_1) {
+		mmc_retune_timer_stop(host->mmc);
+		mmc_retune_needed(host->mmc);
+	}
 
 	spin_lock_irqsave(&host->lock, flags);
 	host->ier &= SDHCI_INT_CARD_INT;
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index afa4de8..2c2404f 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -128,6 +128,7 @@
 #define  SDHCI_INT_CARD_INSERT	0x00000040
 #define  SDHCI_INT_CARD_REMOVE	0x00000080
 #define  SDHCI_INT_CARD_INT	0x00000100
+#define  SDHCI_INT_RETUNE	0x00001000
 #define  SDHCI_INT_ERROR	0x00008000
 #define  SDHCI_INT_TIMEOUT	0x00010000
 #define  SDHCI_INT_CRC		0x00020000
@@ -514,6 +515,8 @@ struct sdhci_host {
 	unsigned int		tuning_count;	/* Timer count for re-tuning */
 	unsigned int		tuning_mode;	/* Re-tuning mode supported by host */
 #define SDHCI_TUNING_MODE_1	0
+#define SDHCI_TUNING_MODE_2	1
+#define SDHCI_TUNING_MODE_3	2
 
 	unsigned long private[0] ____cacheline_aligned;
 };
-- 
1.9.1

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

* [PATCH 17/23] mmc: sdhci: add standard hw auto retuning support
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

If HW supports SDHCI_TUNING_MODE_3 which is auto retuning, we won't
retune during runtime suspend and resume, instead we use Re-tuning
Request signaled via SDHCI_INT_RETUNE interrupt to do retuning and
hw auto retuning during data transfer to guarantee the signal sample
window correction.

This can avoid a mass of repeatly retuning during small file system
data access and improve the performance.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci.c | 18 ++++++++++++++----
 drivers/mmc/host/sdhci.h |  3 +++
 2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 2eb0e34..0027b87 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -252,6 +252,9 @@ static void sdhci_init(struct sdhci_host *host, int soft)
 		    SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END |
 		    SDHCI_INT_RESPONSE;
 
+	if (host->tuning_mode == SDHCI_TUNING_MODE_3)
+		host->ier |= SDHCI_INT_RETUNE;
+
 	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
 	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
 
@@ -2477,6 +2480,9 @@ 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_RETUNE)
+			mmc_retune_needed(host->mmc);
+
 		if (intmask & SDHCI_INT_CARD_INT) {
 			sdhci_enable_sdio_irq_nolock(host, false);
 			host->thread_isr |= SDHCI_INT_CARD_INT;
@@ -2575,8 +2581,10 @@ int sdhci_suspend_host(struct sdhci_host *host)
 {
 	sdhci_disable_card_detection(host);
 
-	mmc_retune_timer_stop(host->mmc);
-	mmc_retune_needed(host->mmc);
+	if (host->tuning_mode == SDHCI_TUNING_MODE_1) {
+		mmc_retune_timer_stop(host->mmc);
+		mmc_retune_needed(host->mmc);
+	}
 
 	if (!device_may_wakeup(mmc_dev(host->mmc))) {
 		host->ier = 0;
@@ -2651,8 +2659,10 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
 {
 	unsigned long flags;
 
-	mmc_retune_timer_stop(host->mmc);
-	mmc_retune_needed(host->mmc);
+	if (host->tuning_mode == SDHCI_TUNING_MODE_1) {
+		mmc_retune_timer_stop(host->mmc);
+		mmc_retune_needed(host->mmc);
+	}
 
 	spin_lock_irqsave(&host->lock, flags);
 	host->ier &= SDHCI_INT_CARD_INT;
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index afa4de8..2c2404f 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -128,6 +128,7 @@
 #define  SDHCI_INT_CARD_INSERT	0x00000040
 #define  SDHCI_INT_CARD_REMOVE	0x00000080
 #define  SDHCI_INT_CARD_INT	0x00000100
+#define  SDHCI_INT_RETUNE	0x00001000
 #define  SDHCI_INT_ERROR	0x00008000
 #define  SDHCI_INT_TIMEOUT	0x00010000
 #define  SDHCI_INT_CRC		0x00020000
@@ -514,6 +515,8 @@ struct sdhci_host {
 	unsigned int		tuning_count;	/* Timer count for re-tuning */
 	unsigned int		tuning_mode;	/* Re-tuning mode supported by host */
 #define SDHCI_TUNING_MODE_1	0
+#define SDHCI_TUNING_MODE_2	1
+#define SDHCI_TUNING_MODE_3	2
 
 	unsigned long private[0] ____cacheline_aligned;
 };
-- 
1.9.1

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

* [PATCH 18/23] mmc: sdhci-esdhc-imx: enable hw auto retuning for STD_TUNING
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: aisheng.dong, ulf.hansson, dongas86, chris, haibo.chen,
	adrian.hunter, shawnguo, linux-arm-kernel

Enable HW auto retuning when set SDHCI_CTRL_EXEC_TUNING and clear it
when clear SDHCI_CTRL_TUNED_CLK.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 9f9be3f..a582a83 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -44,6 +44,7 @@
 #define  ESDHC_MIX_CTRL_AC23EN		(1 << 7)
 #define  ESDHC_MIX_CTRL_EXE_TUNE	(1 << 22)
 #define  ESDHC_MIX_CTRL_SMPCLK_SEL	(1 << 23)
+#define  ESDHC_MIX_CTRL_AUTO_TUNE_EN	(1 << 24)
 #define  ESDHC_MIX_CTRL_FBCLK_SEL	(1 << 25)
 #define  ESDHC_MIX_CTRL_HS400_EN	(1 << 26)
 /* Bits 3 and 6 are not SDHCI standard definitions */
@@ -484,11 +485,13 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 			} else {
 				v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
 				m &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
+				m &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
 			}
 
 			if (val & SDHCI_CTRL_EXEC_TUNING) {
 				v |= ESDHC_MIX_CTRL_EXE_TUNE;
 				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
+				m |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
 				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
 				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT;
 				if (imx_data->boarddata.tuning_start_tap) {
-- 
1.9.1

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

* [PATCH 18/23] mmc: sdhci-esdhc-imx: enable hw auto retuning for STD_TUNING
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

Enable HW auto retuning when set SDHCI_CTRL_EXEC_TUNING and clear it
when clear SDHCI_CTRL_TUNED_CLK.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 9f9be3f..a582a83 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -44,6 +44,7 @@
 #define  ESDHC_MIX_CTRL_AC23EN		(1 << 7)
 #define  ESDHC_MIX_CTRL_EXE_TUNE	(1 << 22)
 #define  ESDHC_MIX_CTRL_SMPCLK_SEL	(1 << 23)
+#define  ESDHC_MIX_CTRL_AUTO_TUNE_EN	(1 << 24)
 #define  ESDHC_MIX_CTRL_FBCLK_SEL	(1 << 25)
 #define  ESDHC_MIX_CTRL_HS400_EN	(1 << 26)
 /* Bits 3 and 6 are not SDHCI standard definitions */
@@ -484,11 +485,13 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 			} else {
 				v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
 				m &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
+				m &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
 			}
 
 			if (val & SDHCI_CTRL_EXEC_TUNING) {
 				v |= ESDHC_MIX_CTRL_EXE_TUNE;
 				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
+				m |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
 				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
 				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT;
 				if (imx_data->boarddata.tuning_start_tap) {
-- 
1.9.1

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

* [PATCH 19/23] mmc: sdhci-esdhc-imx: enable hw auto retuning for MAN_TUNING
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: aisheng.dong, ulf.hansson, dongas86, chris, haibo.chen,
	adrian.hunter, shawnguo, linux-arm-kernel

Indicating hw auto retuning support for mx6qdl in the fake caps_1
register and enable auto retuning in post_tuning process after
tuning completes.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index a582a83..07b1144 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -301,7 +301,8 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
 				/* imx6q/dl does not have cap_1 register, fake one */
 				val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104
 					| SDHCI_SUPPORT_SDR50
-					| SDHCI_USE_SDR50_TUNING;
+					| SDHCI_USE_SDR50_TUNING
+					| (SDHCI_TUNING_MODE_3 << SDHCI_RETUNING_MODE_SHIFT);
 
 			if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
 				val |= SDHCI_SUPPORT_HS400;
@@ -471,10 +472,13 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 		writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC);
 		if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
 			new_val = readl(host->ioaddr + ESDHC_MIX_CTRL);
-			if (val & SDHCI_CTRL_TUNED_CLK)
+			if (val & SDHCI_CTRL_TUNED_CLK) {
 				new_val |= ESDHC_MIX_CTRL_SMPCLK_SEL;
-			else
+				new_val |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
+			} else {
 				new_val &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
+				new_val &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
+			}
 			writel(new_val , host->ioaddr + ESDHC_MIX_CTRL);
 		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
 			u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR);
@@ -760,6 +764,7 @@ static void esdhc_post_tuning(struct sdhci_host *host)
 
 	reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
 	reg &= ~ESDHC_MIX_CTRL_EXE_TUNE;
+	reg |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
 	writel(reg, host->ioaddr + ESDHC_MIX_CTRL);
 }
 
-- 
1.9.1

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

* [PATCH 19/23] mmc: sdhci-esdhc-imx: enable hw auto retuning for MAN_TUNING
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

Indicating hw auto retuning support for mx6qdl in the fake caps_1
register and enable auto retuning in post_tuning process after
tuning completes.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index a582a83..07b1144 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -301,7 +301,8 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
 				/* imx6q/dl does not have cap_1 register, fake one */
 				val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104
 					| SDHCI_SUPPORT_SDR50
-					| SDHCI_USE_SDR50_TUNING;
+					| SDHCI_USE_SDR50_TUNING
+					| (SDHCI_TUNING_MODE_3 << SDHCI_RETUNING_MODE_SHIFT);
 
 			if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
 				val |= SDHCI_SUPPORT_HS400;
@@ -471,10 +472,13 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 		writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC);
 		if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
 			new_val = readl(host->ioaddr + ESDHC_MIX_CTRL);
-			if (val & SDHCI_CTRL_TUNED_CLK)
+			if (val & SDHCI_CTRL_TUNED_CLK) {
 				new_val |= ESDHC_MIX_CTRL_SMPCLK_SEL;
-			else
+				new_val |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
+			} else {
 				new_val &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
+				new_val &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
+			}
 			writel(new_val , host->ioaddr + ESDHC_MIX_CTRL);
 		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
 			u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR);
@@ -760,6 +764,7 @@ static void esdhc_post_tuning(struct sdhci_host *host)
 
 	reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
 	reg &= ~ESDHC_MIX_CTRL_EXE_TUNE;
+	reg |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
 	writel(reg, host->ioaddr + ESDHC_MIX_CTRL);
 }
 
-- 
1.9.1

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

* [PATCH 20/23] mmc: sdhci-esdhc-imx: fix strobe DLL lock wrong clock issue
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: aisheng.dong, ulf.hansson, dongas86, chris, haibo.chen,
	adrian.hunter, shawnguo, linux-arm-kernel

When enable DDR, the clock factor definition is changed.
e.g. original 200Mhz will become 100Mhz one MIX_CTRL_DDREN bit is set
So we need to update the clock setting then the strobe dll can lock
the correct clock rate.

Additionally we also need disable the clock before locking strobe dll.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 07b1144..3ff213f 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -852,6 +852,11 @@ static void esdhc_set_strobe_dll(struct sdhci_host *host)
 	u32 v;
 
 	if (host->mmc->actual_clock > ESDHC_STROBE_DLL_CLK_FREQ) {
+		/* disable clock before enabling strobe dll */
+		writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) &
+		       (~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON),
+		       host->ioaddr + ESDHC_VENDOR_SPEC);
+
 		/* force a reset on strobe dll */
 		writel(ESDHC_STROBE_DLL_CTRL_RESET,
 			host->ioaddr + ESDHC_STROBE_DLL_CTRL);
@@ -913,6 +918,8 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
 		m |= ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN;
 		writel(m, host->ioaddr + ESDHC_MIX_CTRL);
 		imx_data->is_ddr = 1;
+		/* update clock after enable DDR for strobe DLL lock */
+		host->ops->set_clock(host, host->clock);
 		esdhc_set_strobe_dll(host);
 		break;
 	}
-- 
1.9.1

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

* [PATCH 20/23] mmc: sdhci-esdhc-imx: fix strobe DLL lock wrong clock issue
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

When enable DDR, the clock factor definition is changed.
e.g. original 200Mhz will become 100Mhz one MIX_CTRL_DDREN bit is set
So we need to update the clock setting then the strobe dll can lock
the correct clock rate.

Additionally we also need disable the clock before locking strobe dll.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 07b1144..3ff213f 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -852,6 +852,11 @@ static void esdhc_set_strobe_dll(struct sdhci_host *host)
 	u32 v;
 
 	if (host->mmc->actual_clock > ESDHC_STROBE_DLL_CLK_FREQ) {
+		/* disable clock before enabling strobe dll */
+		writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) &
+		       (~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON),
+		       host->ioaddr + ESDHC_VENDOR_SPEC);
+
 		/* force a reset on strobe dll */
 		writel(ESDHC_STROBE_DLL_CTRL_RESET,
 			host->ioaddr + ESDHC_STROBE_DLL_CTRL);
@@ -913,6 +918,8 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
 		m |= ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN;
 		writel(m, host->ioaddr + ESDHC_MIX_CTRL);
 		imx_data->is_ddr = 1;
+		/* update clock after enable DDR for strobe DLL lock */
+		host->ops->set_clock(host, host->clock);
 		esdhc_set_strobe_dll(host);
 		break;
 	}
-- 
1.9.1

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

* [PATCH 21/23] mmc: sdhci-esdhc-imx: factor out hw related intialization into function
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: aisheng.dong, ulf.hansson, dongas86, chris, haibo.chen,
	adrian.hunter, shawnguo, linux-arm-kernel

Factor out hw related intialization into a separate function which
has two benifits:
1) concentrate hw related intialization at one place
2) ease the hw state restore after resume by simply
calling this function

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 76 +++++++++++++++++++++-----------------
 1 file changed, 42 insertions(+), 34 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 3ff213f..95f3632 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -978,6 +978,44 @@ static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
 	.ops = &sdhci_esdhc_ops,
 };
 
+static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
+
+	if (esdhc_is_usdhc(imx_data)) {
+		/*
+		 * The imx6q ROM code will change the default watermark
+		 * level setting to something insane.  Change it back here.
+		 */
+		writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
+
+		/*
+		 * ROM code will change the bit burst_length_enable setting
+		 * to zero if this usdhc is choosed to boot system. Change
+		 * it back here, otherwise it will impact the performance a
+		 * lot. This bit is used to enable/disable the burst length
+		 * for the external AHB2AXI bridge, it's usefully especially
+		 * for INCR transfer because without burst length indicator,
+		 * the AHB2AXI bridge does not know the burst length in
+		 * advance. And without burst length indicator, AHB INCR
+		 * transfer can only be converted to singles on the AXI side.
+		 */
+		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
+			| ESDHC_BURST_LEN_EN_INCR,
+			host->ioaddr + SDHCI_HOST_CONTROL);
+		/*
+		* errata ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
+		* TO1.1, it's harmless for MX6SL
+		*/
+		writel(readl(host->ioaddr + 0x6c) | BIT(7),
+			host->ioaddr + 0x6c);
+
+		/* disable DLL_CTRL delay line settings */
+		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
+	}
+}
+
 #ifdef CONFIG_OF
 static int
 sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
@@ -1175,43 +1213,13 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
 		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK
 			| SDHCI_QUIRK_BROKEN_ADMA;
 
-	/*
-	 * The imx6q ROM code will change the default watermark level setting
-	 * to something insane.  Change it back here.
-	 */
-	if (esdhc_is_usdhc(imx_data)) {
-		writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
+	sdhci_esdhc_imx_hwinit(host);
 
+	if (esdhc_is_usdhc(imx_data)) {
 		host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
 		host->mmc->caps |= MMC_CAP_1_8V_DDR;
-
-		/*
-		 * ROM code will change the bit burst_length_enable setting
-		 * to zero if this usdhc is choosed to boot system. Change
-		 * it back here, otherwise it will impact the performance a
-		 * lot. This bit is used to enable/disable the burst length
-		 * for the external AHB2AXI bridge, it's usefully especially
-		 * for INCR transfer because without burst length indicator,
-		 * the AHB2AXI bridge does not know the burst length in
-		 * advance. And without burst length indicator, AHB INCR
-		 * transfer can only be converted to singles on the AXI side.
-		 */
-		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
-			| ESDHC_BURST_LEN_EN_INCR,
-			host->ioaddr + SDHCI_HOST_CONTROL);
-
 		if (!(imx_data->socdata->flags & ESDHC_FLAG_HS200))
 			host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
-
-		/*
-		* errata ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
-		* TO1.1, it's harmless for MX6SL
-		*/
-		writel(readl(host->ioaddr + 0x6c) | BIT(7),
-			host->ioaddr + 0x6c);
-
-		/* disable DLL_CTRL delay line settings */
-		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
 	}
 
 	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
@@ -1289,8 +1297,8 @@ static int sdhci_esdhc_resume(struct device *dev)
 {
 	struct sdhci_host *host = dev_get_drvdata(dev);
 
-	/* restore watermark setting in case it's lost in low power mode */
-	writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
+	/* reinitialize hw state in case it's lost in low power mode */
+	sdhci_esdhc_imx_hwinit(host);
 
 	return sdhci_pltfm_resume(dev);
 }
-- 
1.9.1

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

* [PATCH 21/23] mmc: sdhci-esdhc-imx: factor out hw related intialization into function
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

Factor out hw related intialization into a separate function which
has two benifits:
1) concentrate hw related intialization at one place
2) ease the hw state restore after resume by simply
calling this function

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 76 +++++++++++++++++++++-----------------
 1 file changed, 42 insertions(+), 34 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 3ff213f..95f3632 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -978,6 +978,44 @@ static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
 	.ops = &sdhci_esdhc_ops,
 };
 
+static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
+
+	if (esdhc_is_usdhc(imx_data)) {
+		/*
+		 * The imx6q ROM code will change the default watermark
+		 * level setting to something insane.  Change it back here.
+		 */
+		writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
+
+		/*
+		 * ROM code will change the bit burst_length_enable setting
+		 * to zero if this usdhc is choosed to boot system. Change
+		 * it back here, otherwise it will impact the performance a
+		 * lot. This bit is used to enable/disable the burst length
+		 * for the external AHB2AXI bridge, it's usefully especially
+		 * for INCR transfer because without burst length indicator,
+		 * the AHB2AXI bridge does not know the burst length in
+		 * advance. And without burst length indicator, AHB INCR
+		 * transfer can only be converted to singles on the AXI side.
+		 */
+		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
+			| ESDHC_BURST_LEN_EN_INCR,
+			host->ioaddr + SDHCI_HOST_CONTROL);
+		/*
+		* errata ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
+		* TO1.1, it's harmless for MX6SL
+		*/
+		writel(readl(host->ioaddr + 0x6c) | BIT(7),
+			host->ioaddr + 0x6c);
+
+		/* disable DLL_CTRL delay line settings */
+		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
+	}
+}
+
 #ifdef CONFIG_OF
 static int
 sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
@@ -1175,43 +1213,13 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
 		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK
 			| SDHCI_QUIRK_BROKEN_ADMA;
 
-	/*
-	 * The imx6q ROM code will change the default watermark level setting
-	 * to something insane.  Change it back here.
-	 */
-	if (esdhc_is_usdhc(imx_data)) {
-		writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
+	sdhci_esdhc_imx_hwinit(host);
 
+	if (esdhc_is_usdhc(imx_data)) {
 		host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
 		host->mmc->caps |= MMC_CAP_1_8V_DDR;
-
-		/*
-		 * ROM code will change the bit burst_length_enable setting
-		 * to zero if this usdhc is choosed to boot system. Change
-		 * it back here, otherwise it will impact the performance a
-		 * lot. This bit is used to enable/disable the burst length
-		 * for the external AHB2AXI bridge, it's usefully especially
-		 * for INCR transfer because without burst length indicator,
-		 * the AHB2AXI bridge does not know the burst length in
-		 * advance. And without burst length indicator, AHB INCR
-		 * transfer can only be converted to singles on the AXI side.
-		 */
-		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
-			| ESDHC_BURST_LEN_EN_INCR,
-			host->ioaddr + SDHCI_HOST_CONTROL);
-
 		if (!(imx_data->socdata->flags & ESDHC_FLAG_HS200))
 			host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
-
-		/*
-		* errata ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
-		* TO1.1, it's harmless for MX6SL
-		*/
-		writel(readl(host->ioaddr + 0x6c) | BIT(7),
-			host->ioaddr + 0x6c);
-
-		/* disable DLL_CTRL delay line settings */
-		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
 	}
 
 	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
@@ -1289,8 +1297,8 @@ static int sdhci_esdhc_resume(struct device *dev)
 {
 	struct sdhci_host *host = dev_get_drvdata(dev);
 
-	/* restore watermark setting in case it's lost in low power mode */
-	writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
+	/* reinitialize hw state in case it's lost in low power mode */
+	sdhci_esdhc_imx_hwinit(host);
 
 	return sdhci_pltfm_resume(dev);
 }
-- 
1.9.1

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

* [PATCH 22/23] mmc: sdhci-esdhc-imx: move tuning static configuration into hwinit function
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: aisheng.dong, ulf.hansson, dongas86, chris, haibo.chen,
	adrian.hunter, shawnguo, linux-arm-kernel

Move tuning static configuration into hwinit function.
Tuning configuration may also be lost in low power mode,
so need restore in hwinit().

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 95f3632..98aa6b5 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -483,7 +483,6 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
 			u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR);
 			u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL);
-			u32 tuning_ctrl;
 			if (val & SDHCI_CTRL_TUNED_CLK) {
 				v |= ESDHC_MIX_CTRL_SMPCLK_SEL;
 			} else {
@@ -496,18 +495,6 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 				v |= ESDHC_MIX_CTRL_EXE_TUNE;
 				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
 				m |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
-				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
-				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT;
-				if (imx_data->boarddata.tuning_start_tap) {
-					tuning_ctrl &= ~ESDHC_TUNING_START_TAP_MASK;
-					tuning_ctrl |= imx_data->boarddata.tuning_start_tap;
-				}
-
-				if (imx_data->boarddata.tuning_step) {
-					tuning_ctrl &= ~ESDHC_TUNING_STEP_MASK;
-					tuning_ctrl |= imx_data->boarddata.tuning_step << ESDHC_TUNING_STEP_SHIFT;
-				}
-				writel(tuning_ctrl, host->ioaddr + ESDHC_TUNING_CTRL);
 			} else {
 				v &= ~ESDHC_MIX_CTRL_EXE_TUNE;
 			}
@@ -982,6 +969,7 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
+	int tmp;
 
 	if (esdhc_is_usdhc(imx_data)) {
 		/*
@@ -1013,6 +1001,23 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
 
 		/* disable DLL_CTRL delay line settings */
 		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
+
+		if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
+			tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL);
+			tmp |= ESDHC_STD_TUNING_EN |
+				ESDHC_TUNING_START_TAP_DEFAULT;
+			if (imx_data->boarddata.tuning_start_tap) {
+				tmp &= ~ESDHC_TUNING_START_TAP_MASK;
+				tmp |= imx_data->boarddata.tuning_start_tap;
+			}
+
+			if (imx_data->boarddata.tuning_step) {
+				tmp &= ~ESDHC_TUNING_STEP_MASK;
+				tmp |= imx_data->boarddata.tuning_step
+					<< ESDHC_TUNING_STEP_SHIFT;
+			}
+			writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL);
+		}
 	}
 }
 
@@ -1226,11 +1231,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
 		sdhci_esdhc_ops.platform_execute_tuning =
 					esdhc_executing_tuning;
 
-	if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING)
-		writel(readl(host->ioaddr + ESDHC_TUNING_CTRL) |
-			ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT,
-			host->ioaddr + ESDHC_TUNING_CTRL);
-
 	if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
 		host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
 
-- 
1.9.1

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

* [PATCH 22/23] mmc: sdhci-esdhc-imx: move tuning static configuration into hwinit function
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

Move tuning static configuration into hwinit function.
Tuning configuration may also be lost in low power mode,
so need restore in hwinit().

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 95f3632..98aa6b5 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -483,7 +483,6 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
 			u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR);
 			u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL);
-			u32 tuning_ctrl;
 			if (val & SDHCI_CTRL_TUNED_CLK) {
 				v |= ESDHC_MIX_CTRL_SMPCLK_SEL;
 			} else {
@@ -496,18 +495,6 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 				v |= ESDHC_MIX_CTRL_EXE_TUNE;
 				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
 				m |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
-				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
-				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT;
-				if (imx_data->boarddata.tuning_start_tap) {
-					tuning_ctrl &= ~ESDHC_TUNING_START_TAP_MASK;
-					tuning_ctrl |= imx_data->boarddata.tuning_start_tap;
-				}
-
-				if (imx_data->boarddata.tuning_step) {
-					tuning_ctrl &= ~ESDHC_TUNING_STEP_MASK;
-					tuning_ctrl |= imx_data->boarddata.tuning_step << ESDHC_TUNING_STEP_SHIFT;
-				}
-				writel(tuning_ctrl, host->ioaddr + ESDHC_TUNING_CTRL);
 			} else {
 				v &= ~ESDHC_MIX_CTRL_EXE_TUNE;
 			}
@@ -982,6 +969,7 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
+	int tmp;
 
 	if (esdhc_is_usdhc(imx_data)) {
 		/*
@@ -1013,6 +1001,23 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
 
 		/* disable DLL_CTRL delay line settings */
 		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
+
+		if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
+			tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL);
+			tmp |= ESDHC_STD_TUNING_EN |
+				ESDHC_TUNING_START_TAP_DEFAULT;
+			if (imx_data->boarddata.tuning_start_tap) {
+				tmp &= ~ESDHC_TUNING_START_TAP_MASK;
+				tmp |= imx_data->boarddata.tuning_start_tap;
+			}
+
+			if (imx_data->boarddata.tuning_step) {
+				tmp &= ~ESDHC_TUNING_STEP_MASK;
+				tmp |= imx_data->boarddata.tuning_step
+					<< ESDHC_TUNING_STEP_SHIFT;
+			}
+			writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL);
+		}
 	}
 }
 
@@ -1226,11 +1231,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
 		sdhci_esdhc_ops.platform_execute_tuning =
 					esdhc_executing_tuning;
 
-	if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING)
-		writel(readl(host->ioaddr + ESDHC_TUNING_CTRL) |
-			ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT,
-			host->ioaddr + ESDHC_TUNING_CTRL);
-
 	if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
 		host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
 
-- 
1.9.1

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

* [PATCH 23/23] mmc: sdhci-esdhc-imx: clear tuning bits during hwinit
  2016-04-15 17:29 ` Dong Aisheng
@ 2016-04-15 17:29   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-mmc
  Cc: ulf.hansson, chris, shawnguo, adrian.hunter, linux-arm-kernel,
	aisheng.dong, haibo.chen, dongas86

The tuning bits like FBCLK_SEL, SMP_CLK_SEL and DLY_CELL which affects
timing may have already been set by ROM if booting from SD3.0 mode like
SDR104. Let's clear it first during hw initialization before do the
new card enumeration.

For system resume case, it's safe to clear them too since the following
card re-initialization in mmc_xx_init_card() will do retuning and set
correct value again.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 98aa6b5..6a699d1 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -1018,6 +1018,11 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
 			}
 			writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL);
 		}
+
+		/* clear tuning bits in case ROM has set it already */
+		writel(0x0, host->ioaddr + ESDHC_MIX_CTRL);
+		writel(0x0, host->ioaddr + SDHCI_ACMD12_ERR);
+		writel(0x0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
 	}
 }
 
-- 
1.9.1


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

* [PATCH 23/23] mmc: sdhci-esdhc-imx: clear tuning bits during hwinit
@ 2016-04-15 17:29   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-15 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

The tuning bits like FBCLK_SEL, SMP_CLK_SEL and DLY_CELL which affects
timing may have already been set by ROM if booting from SD3.0 mode like
SDR104. Let's clear it first during hw initialization before do the
new card enumeration.

For system resume case, it's safe to clear them too since the following
card re-initialization in mmc_xx_init_card() will do retuning and set
correct value again.

Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 98aa6b5..6a699d1 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -1018,6 +1018,11 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
 			}
 			writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL);
 		}
+
+		/* clear tuning bits in case ROM has set it already */
+		writel(0x0, host->ioaddr + ESDHC_MIX_CTRL);
+		writel(0x0, host->ioaddr + SDHCI_ACMD12_ERR);
+		writel(0x0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
 	}
 }
 
-- 
1.9.1

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

* Re: [PATCH 01/23] mmc: sdhci: removed unneeded function wrappers
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-04-22 10:27     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-22 10:27 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> After commit d6463f170cf0 ("mmc: sdhci: Remove redundant runtime PM calls"),
> some of original sdhci_do_xx() function wrappers becomes meaningless,
> so remove them.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

Didn't apply cleanly, otherwise:

Acked-by: Adrian Hunter <adrian.hunter@intel.com>


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

* [PATCH 01/23] mmc: sdhci: removed unneeded function wrappers
@ 2016-04-22 10:27     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-22 10:27 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> After commit d6463f170cf0 ("mmc: sdhci: Remove redundant runtime PM calls"),
> some of original sdhci_do_xx() function wrappers becomes meaningless,
> so remove them.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

Didn't apply cleanly, otherwise:

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

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

* Re: [PATCH 02/23] mmc: sdhci: move sdhci_get_cd() forward to avoid declaration
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-04-22 10:27     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-22 10:27 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> Move sdhci_get_cd() to avoid needing to declare this function
> before use.

In fact, we shouldn't be calling host functions directly. i.e. the call
should be host->mmc->ops->get_cd().

However the caller sdhci_do_reset() is called under spinlock so it should
not be calling ->get_cd at all.

What that means is that we really need to get rid of
SDHCI_QUIRK_NO_CARD_NO_RESET, after which this patch wouldn't be needed, so
let's leave it for now.

> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
>  drivers/mmc/host/sdhci.c | 55 ++++++++++++++++++++++++------------------------
>  1 file changed, 27 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index be52a3a..839aa4c 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -53,7 +53,6 @@ static void sdhci_finish_data(struct sdhci_host *);
>  static void sdhci_finish_command(struct sdhci_host *);
>  static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
>  static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
> -static int sdhci_get_cd(struct mmc_host *mmc);
>  
>  #ifdef CONFIG_PM
>  static void sdhci_runtime_pm_bus_on(struct sdhci_host *host);
> @@ -161,6 +160,33 @@ static void sdhci_disable_card_detection(struct sdhci_host *host)
>  	sdhci_set_card_detection(host, false);
>  }
>  
> +static int sdhci_get_cd(struct mmc_host *mmc)
> +{
> +	struct sdhci_host *host = mmc_priv(mmc);
> +	int gpio_cd = mmc_gpio_get_cd(mmc);
> +
> +	if (host->flags & SDHCI_DEVICE_DEAD)
> +		return 0;
> +
> +	/* If nonremovable, assume that the card is always present. */
> +	if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
> +		return 1;
> +
> +	/*
> +	 * Try slot gpio detect, if defined it take precedence
> +	 * over build in controller functionality
> +	 */
> +	if (!IS_ERR_VALUE(gpio_cd))
> +		return !!gpio_cd;
> +
> +	/* If polling, assume that the card is always present. */
> +	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
> +		return 1;
> +
> +	/* Host native card detect */
> +	return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
> +}
> +
>  void sdhci_reset(struct sdhci_host *host, u8 mask)
>  {
>  	unsigned long timeout;
> @@ -1551,33 +1577,6 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  	spin_unlock_irqrestore(&host->lock, flags);
>  }
>  
> -static int sdhci_get_cd(struct mmc_host *mmc)
> -{
> -	struct sdhci_host *host = mmc_priv(mmc);
> -	int gpio_cd = mmc_gpio_get_cd(mmc);
> -
> -	if (host->flags & SDHCI_DEVICE_DEAD)
> -		return 0;
> -
> -	/* If nonremovable, assume that the card is always present. */
> -	if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
> -		return 1;
> -
> -	/*
> -	 * Try slot gpio detect, if defined it take precedence
> -	 * over build in controller functionality
> -	 */
> -	if (!IS_ERR_VALUE(gpio_cd))
> -		return !!gpio_cd;
> -
> -	/* If polling, assume that the card is always present. */
> -	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
> -		return 1;
> -
> -	/* Host native card detect */
> -	return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
> -}
> -
>  static int sdhci_check_ro(struct sdhci_host *host)
>  {
>  	unsigned long flags;
> 


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

* [PATCH 02/23] mmc: sdhci: move sdhci_get_cd() forward to avoid declaration
@ 2016-04-22 10:27     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-22 10:27 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> Move sdhci_get_cd() to avoid needing to declare this function
> before use.

In fact, we shouldn't be calling host functions directly. i.e. the call
should be host->mmc->ops->get_cd().

However the caller sdhci_do_reset() is called under spinlock so it should
not be calling ->get_cd at all.

What that means is that we really need to get rid of
SDHCI_QUIRK_NO_CARD_NO_RESET, after which this patch wouldn't be needed, so
let's leave it for now.

> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
>  drivers/mmc/host/sdhci.c | 55 ++++++++++++++++++++++++------------------------
>  1 file changed, 27 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index be52a3a..839aa4c 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -53,7 +53,6 @@ static void sdhci_finish_data(struct sdhci_host *);
>  static void sdhci_finish_command(struct sdhci_host *);
>  static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
>  static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
> -static int sdhci_get_cd(struct mmc_host *mmc);
>  
>  #ifdef CONFIG_PM
>  static void sdhci_runtime_pm_bus_on(struct sdhci_host *host);
> @@ -161,6 +160,33 @@ static void sdhci_disable_card_detection(struct sdhci_host *host)
>  	sdhci_set_card_detection(host, false);
>  }
>  
> +static int sdhci_get_cd(struct mmc_host *mmc)
> +{
> +	struct sdhci_host *host = mmc_priv(mmc);
> +	int gpio_cd = mmc_gpio_get_cd(mmc);
> +
> +	if (host->flags & SDHCI_DEVICE_DEAD)
> +		return 0;
> +
> +	/* If nonremovable, assume that the card is always present. */
> +	if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
> +		return 1;
> +
> +	/*
> +	 * Try slot gpio detect, if defined it take precedence
> +	 * over build in controller functionality
> +	 */
> +	if (!IS_ERR_VALUE(gpio_cd))
> +		return !!gpio_cd;
> +
> +	/* If polling, assume that the card is always present. */
> +	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
> +		return 1;
> +
> +	/* Host native card detect */
> +	return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
> +}
> +
>  void sdhci_reset(struct sdhci_host *host, u8 mask)
>  {
>  	unsigned long timeout;
> @@ -1551,33 +1577,6 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  	spin_unlock_irqrestore(&host->lock, flags);
>  }
>  
> -static int sdhci_get_cd(struct mmc_host *mmc)
> -{
> -	struct sdhci_host *host = mmc_priv(mmc);
> -	int gpio_cd = mmc_gpio_get_cd(mmc);
> -
> -	if (host->flags & SDHCI_DEVICE_DEAD)
> -		return 0;
> -
> -	/* If nonremovable, assume that the card is always present. */
> -	if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
> -		return 1;
> -
> -	/*
> -	 * Try slot gpio detect, if defined it take precedence
> -	 * over build in controller functionality
> -	 */
> -	if (!IS_ERR_VALUE(gpio_cd))
> -		return !!gpio_cd;
> -
> -	/* If polling, assume that the card is always present. */
> -	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
> -		return 1;
> -
> -	/* Host native card detect */
> -	return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
> -}
> -
>  static int sdhci_check_ro(struct sdhci_host *host)
>  {
>  	unsigned long flags;
> 

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

* Re: [PATCH 03/23] mmc: core: fix a comment typo
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-04-22 10:28     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-22 10:28 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc, ulf.hansson
  Cc: chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

I'll leave this one up to Ulf.

> ---
>  drivers/mmc/core/mmc_ops.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
> index 62355bd..d220bbd 100644
> --- a/drivers/mmc/core/mmc_ops.c
> +++ b/drivers/mmc/core/mmc_ops.c
> @@ -553,7 +553,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
>  
>  		/*
>  		 * We are not allowed to issue a status command and the host
> -		 * does'nt support MMC_CAP_WAIT_WHILE_BUSY, then we can only
> +		 * doesn't support MMC_CAP_WAIT_WHILE_BUSY, then we can only
>  		 * rely on waiting for the stated timeout to be sufficient.
>  		 */
>  		if (!send_status) {
> 


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

* [PATCH 03/23] mmc: core: fix a comment typo
@ 2016-04-22 10:28     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-22 10:28 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

I'll leave this one up to Ulf.

> ---
>  drivers/mmc/core/mmc_ops.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
> index 62355bd..d220bbd 100644
> --- a/drivers/mmc/core/mmc_ops.c
> +++ b/drivers/mmc/core/mmc_ops.c
> @@ -553,7 +553,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
>  
>  		/*
>  		 * We are not allowed to issue a status command and the host
> -		 * does'nt support MMC_CAP_WAIT_WHILE_BUSY, then we can only
> +		 * doesn't support MMC_CAP_WAIT_WHILE_BUSY, then we can only
>  		 * rely on waiting for the stated timeout to be sufficient.
>  		 */
>  		if (!send_status) {
> 

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

* Re: [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-04-22 11:43     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-22 11:43 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> Handle host and regulator signal voltage switch separately.
> Move host signal voltage switch code into a separated function
> sdhci_do_signal_voltage_switch() first, the following patches will
> remove the regulator voltage switch code and use the common
> mmc_regulator_set_vqmmc() instead.

You have changed the order that things are done.  There is no way to know
what that will break, so let's not do that.  What about just changing
regulator_set_voltage() to mmc_regulator_set_vqmmc()?

> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
>  drivers/mmc/host/sdhci.c | 97 ++++++++++++++++++++++++++++--------------------
>  1 file changed, 57 insertions(+), 40 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 839aa4c..7f63f5d 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1657,19 +1657,10 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
>  	spin_unlock_irqrestore(&host->lock, flags);
>  }
>  
> -static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
> -					     struct mmc_ios *ios)
> +static int sdhci_do_signal_voltage_switch(struct sdhci_host *host,
> +					  struct mmc_ios *ios)
>  {
> -	struct sdhci_host *host = mmc_priv(mmc);
>  	u16 ctrl;
> -	int ret;
> -
> -	/*
> -	 * Signal Voltage Switching is only applicable for Host Controllers
> -	 * v3.00 and above.
> -	 */
> -	if (host->version < SDHCI_SPEC_300)
> -		return 0;
>  
>  	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
>  
> @@ -1679,15 +1670,6 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>  		ctrl &= ~SDHCI_CTRL_VDD_180;
>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>  
> -		if (!IS_ERR(mmc->supply.vqmmc)) {
> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
> -						    3600000);
> -			if (ret) {
> -				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
> -					mmc_hostname(mmc));
> -				return -EIO;
> -			}
> -		}
>  		/* Wait for 5ms */
>  		usleep_range(5000, 5500);
>  
> @@ -1697,20 +1679,10 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>  			return 0;
>  
>  		pr_warn("%s: 3.3V regulator output did not became stable\n",
> -			mmc_hostname(mmc));
> +			mmc_hostname(host->mmc));
>  
>  		return -EAGAIN;
>  	case MMC_SIGNAL_VOLTAGE_180:
> -		if (!IS_ERR(mmc->supply.vqmmc)) {
> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
> -					1700000, 1950000);
> -			if (ret) {
> -				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
> -					mmc_hostname(mmc));
> -				return -EIO;
> -			}
> -		}
> -
>  		/*
>  		 * Enable 1.8V Signal Enable in the Host Control2
>  		 * register
> @@ -1728,18 +1700,63 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>  			return 0;
>  
>  		pr_warn("%s: 1.8V regulator output did not became stable\n",
> -			mmc_hostname(mmc));
> +			mmc_hostname(host->mmc));
>  
>  		return -EAGAIN;
> +	default:
> +		/* No signal voltage switch required */
> +		return 0;
> +	}
> +}
> +
> +static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
> +					     struct mmc_ios *ios)
> +{
> +	struct sdhci_host *host = mmc_priv(mmc);
> +	int ret;
> +
> +	/*
> +	 * Signal Voltage Switching is only applicable for Host Controllers
> +	 * v3.00 and above.
> +	 */
> +	if (host->version < SDHCI_SPEC_300)
> +		return 0;
> +
> +	ret = sdhci_do_signal_voltage_switch(host, ios);
> +	if (ret)
> +		return ret;
> +
> +	if (IS_ERR(mmc->supply.vqmmc))
> +		return 0;
> +
> +	switch (ios->signal_voltage) {
> +	case MMC_SIGNAL_VOLTAGE_330:
> +		ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
> +					    3600000);
> +		if (ret) {
> +			pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
> +				mmc_hostname(mmc));
> +			return -EIO;
> +		}
> +
> +		return 0;
> +	case MMC_SIGNAL_VOLTAGE_180:
> +		ret = regulator_set_voltage(mmc->supply.vqmmc,
> +				1700000, 1950000);
> +		if (ret) {
> +			pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
> +				mmc_hostname(mmc));
> +			return -EIO;
> +		}
> +
> +		return 0;
>  	case MMC_SIGNAL_VOLTAGE_120:
> -		if (!IS_ERR(mmc->supply.vqmmc)) {
> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
> -						    1300000);
> -			if (ret) {
> -				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
> -					mmc_hostname(mmc));
> -				return -EIO;
> -			}
> +		ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
> +					    1300000);
> +		if (ret) {
> +			pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
> +				mmc_hostname(mmc));
> +			return -EIO;
>  		}
>  		return 0;
>  	default:
> 


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

* [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
@ 2016-04-22 11:43     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-22 11:43 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> Handle host and regulator signal voltage switch separately.
> Move host signal voltage switch code into a separated function
> sdhci_do_signal_voltage_switch() first, the following patches will
> remove the regulator voltage switch code and use the common
> mmc_regulator_set_vqmmc() instead.

You have changed the order that things are done.  There is no way to know
what that will break, so let's not do that.  What about just changing
regulator_set_voltage() to mmc_regulator_set_vqmmc()?

> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
>  drivers/mmc/host/sdhci.c | 97 ++++++++++++++++++++++++++++--------------------
>  1 file changed, 57 insertions(+), 40 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 839aa4c..7f63f5d 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1657,19 +1657,10 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
>  	spin_unlock_irqrestore(&host->lock, flags);
>  }
>  
> -static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
> -					     struct mmc_ios *ios)
> +static int sdhci_do_signal_voltage_switch(struct sdhci_host *host,
> +					  struct mmc_ios *ios)
>  {
> -	struct sdhci_host *host = mmc_priv(mmc);
>  	u16 ctrl;
> -	int ret;
> -
> -	/*
> -	 * Signal Voltage Switching is only applicable for Host Controllers
> -	 * v3.00 and above.
> -	 */
> -	if (host->version < SDHCI_SPEC_300)
> -		return 0;
>  
>  	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
>  
> @@ -1679,15 +1670,6 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>  		ctrl &= ~SDHCI_CTRL_VDD_180;
>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>  
> -		if (!IS_ERR(mmc->supply.vqmmc)) {
> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
> -						    3600000);
> -			if (ret) {
> -				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
> -					mmc_hostname(mmc));
> -				return -EIO;
> -			}
> -		}
>  		/* Wait for 5ms */
>  		usleep_range(5000, 5500);
>  
> @@ -1697,20 +1679,10 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>  			return 0;
>  
>  		pr_warn("%s: 3.3V regulator output did not became stable\n",
> -			mmc_hostname(mmc));
> +			mmc_hostname(host->mmc));
>  
>  		return -EAGAIN;
>  	case MMC_SIGNAL_VOLTAGE_180:
> -		if (!IS_ERR(mmc->supply.vqmmc)) {
> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
> -					1700000, 1950000);
> -			if (ret) {
> -				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
> -					mmc_hostname(mmc));
> -				return -EIO;
> -			}
> -		}
> -
>  		/*
>  		 * Enable 1.8V Signal Enable in the Host Control2
>  		 * register
> @@ -1728,18 +1700,63 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>  			return 0;
>  
>  		pr_warn("%s: 1.8V regulator output did not became stable\n",
> -			mmc_hostname(mmc));
> +			mmc_hostname(host->mmc));
>  
>  		return -EAGAIN;
> +	default:
> +		/* No signal voltage switch required */
> +		return 0;
> +	}
> +}
> +
> +static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
> +					     struct mmc_ios *ios)
> +{
> +	struct sdhci_host *host = mmc_priv(mmc);
> +	int ret;
> +
> +	/*
> +	 * Signal Voltage Switching is only applicable for Host Controllers
> +	 * v3.00 and above.
> +	 */
> +	if (host->version < SDHCI_SPEC_300)
> +		return 0;
> +
> +	ret = sdhci_do_signal_voltage_switch(host, ios);
> +	if (ret)
> +		return ret;
> +
> +	if (IS_ERR(mmc->supply.vqmmc))
> +		return 0;
> +
> +	switch (ios->signal_voltage) {
> +	case MMC_SIGNAL_VOLTAGE_330:
> +		ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
> +					    3600000);
> +		if (ret) {
> +			pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
> +				mmc_hostname(mmc));
> +			return -EIO;
> +		}
> +
> +		return 0;
> +	case MMC_SIGNAL_VOLTAGE_180:
> +		ret = regulator_set_voltage(mmc->supply.vqmmc,
> +				1700000, 1950000);
> +		if (ret) {
> +			pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
> +				mmc_hostname(mmc));
> +			return -EIO;
> +		}
> +
> +		return 0;
>  	case MMC_SIGNAL_VOLTAGE_120:
> -		if (!IS_ERR(mmc->supply.vqmmc)) {
> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
> -						    1300000);
> -			if (ret) {
> -				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
> -					mmc_hostname(mmc));
> -				return -EIO;
> -			}
> +		ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
> +					    1300000);
> +		if (ret) {
> +			pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
> +				mmc_hostname(mmc));
> +			return -EIO;
>  		}
>  		return 0;
>  	default:
> 

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

* Re: [PATCH 06/23] mmc: sdhci: using common mmc_regulator_set_vqmmc()
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-04-22 11:48     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-22 11:48 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> Instead of using private VCCQ regulator signal voltage switch code,
> we switch to use the more robust common function mmc_regulator_set_vqmmc()
> in MMC core which set the target voltage as close as possible to target
> voltage.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
> Don't have a board to test mmc_regulator_set_vqmmc() switch way,
> need others to help verify.

So was there a reason you wanted to change it?

I agree mmc_regulator_set_vqmmc() looks superior, but we really need
feedback from people using this code..

> ---
>  drivers/mmc/host/sdhci.c | 39 ++-------------------------------------
>  1 file changed, 2 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 7f63f5d..2338aab 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1726,43 +1726,8 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>  	if (ret)
>  		return ret;
>  
> -	if (IS_ERR(mmc->supply.vqmmc))
> -		return 0;
> -
> -	switch (ios->signal_voltage) {
> -	case MMC_SIGNAL_VOLTAGE_330:
> -		ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
> -					    3600000);
> -		if (ret) {
> -			pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
> -				mmc_hostname(mmc));
> -			return -EIO;
> -		}
> -
> -		return 0;
> -	case MMC_SIGNAL_VOLTAGE_180:
> -		ret = regulator_set_voltage(mmc->supply.vqmmc,
> -				1700000, 1950000);
> -		if (ret) {
> -			pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
> -				mmc_hostname(mmc));
> -			return -EIO;
> -		}
> -
> -		return 0;
> -	case MMC_SIGNAL_VOLTAGE_120:
> -		ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
> -					    1300000);
> -		if (ret) {
> -			pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
> -				mmc_hostname(mmc));
> -			return -EIO;
> -		}
> -		return 0;
> -	default:
> -		/* No signal voltage switch required */
> -		return 0;
> -	}
> +	/* do regulator signal voltage switch if exist */
> +	return mmc_regulator_set_vqmmc(mmc, ios);
>  }
>  
>  static int sdhci_card_busy(struct mmc_host *mmc)
> 


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

* [PATCH 06/23] mmc: sdhci: using common mmc_regulator_set_vqmmc()
@ 2016-04-22 11:48     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-22 11:48 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> Instead of using private VCCQ regulator signal voltage switch code,
> we switch to use the more robust common function mmc_regulator_set_vqmmc()
> in MMC core which set the target voltage as close as possible to target
> voltage.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
> Don't have a board to test mmc_regulator_set_vqmmc() switch way,
> need others to help verify.

So was there a reason you wanted to change it?

I agree mmc_regulator_set_vqmmc() looks superior, but we really need
feedback from people using this code..

> ---
>  drivers/mmc/host/sdhci.c | 39 ++-------------------------------------
>  1 file changed, 2 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 7f63f5d..2338aab 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1726,43 +1726,8 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>  	if (ret)
>  		return ret;
>  
> -	if (IS_ERR(mmc->supply.vqmmc))
> -		return 0;
> -
> -	switch (ios->signal_voltage) {
> -	case MMC_SIGNAL_VOLTAGE_330:
> -		ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
> -					    3600000);
> -		if (ret) {
> -			pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
> -				mmc_hostname(mmc));
> -			return -EIO;
> -		}
> -
> -		return 0;
> -	case MMC_SIGNAL_VOLTAGE_180:
> -		ret = regulator_set_voltage(mmc->supply.vqmmc,
> -				1700000, 1950000);
> -		if (ret) {
> -			pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
> -				mmc_hostname(mmc));
> -			return -EIO;
> -		}
> -
> -		return 0;
> -	case MMC_SIGNAL_VOLTAGE_120:
> -		ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
> -					    1300000);
> -		if (ret) {
> -			pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
> -				mmc_hostname(mmc));
> -			return -EIO;
> -		}
> -		return 0;
> -	default:
> -		/* No signal voltage switch required */
> -		return 0;
> -	}
> +	/* do regulator signal voltage switch if exist */
> +	return mmc_regulator_set_vqmmc(mmc, ios);
>  }
>  
>  static int sdhci_card_busy(struct mmc_host *mmc)
> 

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

* Re: [PATCH 07/23] mmc: sdhci: check SDHCI_QUIRK2_NO_1_8_V when do voltage switch
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-04-22 12:30     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-22 12:30 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> Currently when card type supports EXT_CSD_CARD_TYPE_DDR_1_8V
> which means it can work on DDR mode with either 3.3v IO or 1.8v
> IO voltage. MMC core will first try 1.8v then 3.3v if host claims
> MMC_CAP_1_8V_DDR support.
> However the host driver voltage switch code does not check NO_1_8_V
> quirk which may set a wrong 1.8v and causes the card fixed to 3.3v
> VIO un-work.
> 
> Checking 1.8V quirk before setting it to avoid such issue.

We need to look forward to when SDHCI_QUIRK2_NO_1_8_V doesn't exist.

There are two possibilities:

1. Add MMC_CAP_3_3V_DDR and support to core and use that instead of
MMC_CAP_1_8V_DDR.  You'll need Ulf's feedback on that.

2. Replace ->start_signal_voltage_switch() i.e.

host->mmc_host_ops.start_signal_voltage_switch =
esdhci_start_signal_voltage_switch;

You will also need to change all calls to
sdhci_start_signal_voltage_switch() with
host->mmc->ops->start_signal_voltage_switch(), but that needs to be done anyway.

> 
> CC: stable <stable@vger.kernel.org>
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
>  drivers/mmc/host/sdhci.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 2338aab..96ccb15 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1683,6 +1683,8 @@ static int sdhci_do_signal_voltage_switch(struct sdhci_host *host,
>  
>  		return -EAGAIN;
>  	case MMC_SIGNAL_VOLTAGE_180:
> +		if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)
> +			return -EINVAL;
>  		/*
>  		 * Enable 1.8V Signal Enable in the Host Control2
>  		 * register
> 


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

* [PATCH 07/23] mmc: sdhci: check SDHCI_QUIRK2_NO_1_8_V when do voltage switch
@ 2016-04-22 12:30     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-22 12:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> Currently when card type supports EXT_CSD_CARD_TYPE_DDR_1_8V
> which means it can work on DDR mode with either 3.3v IO or 1.8v
> IO voltage. MMC core will first try 1.8v then 3.3v if host claims
> MMC_CAP_1_8V_DDR support.
> However the host driver voltage switch code does not check NO_1_8_V
> quirk which may set a wrong 1.8v and causes the card fixed to 3.3v
> VIO un-work.
> 
> Checking 1.8V quirk before setting it to avoid such issue.

We need to look forward to when SDHCI_QUIRK2_NO_1_8_V doesn't exist.

There are two possibilities:

1. Add MMC_CAP_3_3V_DDR and support to core and use that instead of
MMC_CAP_1_8V_DDR.  You'll need Ulf's feedback on that.

2. Replace ->start_signal_voltage_switch() i.e.

host->mmc_host_ops.start_signal_voltage_switch =
esdhci_start_signal_voltage_switch;

You will also need to change all calls to
sdhci_start_signal_voltage_switch() with
host->mmc->ops->start_signal_voltage_switch(), but that needs to be done anyway.

> 
> CC: stable <stable@vger.kernel.org>
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
>  drivers/mmc/host/sdhci.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 2338aab..96ccb15 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1683,6 +1683,8 @@ static int sdhci_do_signal_voltage_switch(struct sdhci_host *host,
>  
>  		return -EAGAIN;
>  	case MMC_SIGNAL_VOLTAGE_180:
> +		if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)
> +			return -EINVAL;
>  		/*
>  		 * Enable 1.8V Signal Enable in the Host Control2
>  		 * register
> 

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

* Re: [PATCH 08/23] mmc: sdhci: rename quirk SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-04-22 12:33     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-22 12:33 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> Rename ACMD12 quirk to SDHCI_QUIRK_MULTIBLOCK_ACMD12 to avoid confusion
> since it's needed for both read and write.

I am not in favour of renaming unless the original name is really really
bad.  In this case it is a quirk which we anyway expect to remove at some
point, so let's leave it alone for now.

> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
>  drivers/mmc/host/sdhci-pci-o2micro.c | 2 +-
>  drivers/mmc/host/sdhci-pltfm.c       | 2 +-
>  drivers/mmc/host/sdhci-s3c.c         | 2 +-
>  drivers/mmc/host/sdhci.c             | 2 +-
>  drivers/mmc/host/sdhci.h             | 2 +-
>  5 files changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
> index d48f031..1ed1f995 100644
> --- a/drivers/mmc/host/sdhci-pci-o2micro.c
> +++ b/drivers/mmc/host/sdhci-pci-o2micro.c
> @@ -162,7 +162,7 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
>  	case PCI_DEVICE_ID_O2_FUJIN2:
>  		reg = sdhci_readl(host, O2_SD_VENDOR_SETTING);
>  		if (reg & 0x1)
> -			host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
> +			host->quirks |= SDHCI_QUIRK_MULTIBLOCK_ACMD12;
>  
>  		if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2)
>  			break;
> diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
> index 072bb27..206057a 100644
> --- a/drivers/mmc/host/sdhci-pltfm.c
> +++ b/drivers/mmc/host/sdhci-pltfm.c
> @@ -74,7 +74,7 @@ void sdhci_get_of_property(struct platform_device *pdev)
>  	u32 bus_width;
>  
>  	if (of_get_property(np, "sdhci,auto-cmd12", NULL))
> -		host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
> +		host->quirks |= SDHCI_QUIRK_MULTIBLOCK_ACMD12;
>  
>  	if (of_get_property(np, "sdhci,1-bit-only", NULL) ||
>  	    (of_property_read_u32(np, "bus-width", &bus_width) == 0 &&
> diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
> index 70c724b..756b9bb 100644
> --- a/drivers/mmc/host/sdhci-s3c.c
> +++ b/drivers/mmc/host/sdhci-s3c.c
> @@ -564,7 +564,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
>  	host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ;
>  
>  	/* This host supports the Auto CMD12 */
> -	host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
> +	host->quirks |= SDHCI_QUIRK_MULTIBLOCK_ACMD12;
>  
>  	/* Samsung SoCs need BROKEN_ADMA_ZEROLEN_DESC */
>  	host->quirks |= SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC;
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 96ccb15..40e3551 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -2988,7 +2988,7 @@ int sdhci_add_host(struct sdhci_host *host)
>  	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
>  	mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
>  
> -	if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
> +	if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_ACMD12)
>  		host->flags |= SDHCI_AUTO_CMD12;
>  
>  	/* Auto-CMD23 stuff only works in ADMA or PIO. */
> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index 0f39f4f..afa4de8 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -379,7 +379,7 @@ struct sdhci_host {
>  /* Controller is missing device caps. Use caps provided by host */
>  #define SDHCI_QUIRK_MISSING_CAPS			(1<<27)
>  /* Controller uses Auto CMD12 command to stop the transfer */
> -#define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12		(1<<28)
> +#define SDHCI_QUIRK_MULTIBLOCK_ACMD12			(1<<28)
>  /* Controller doesn't have HISPD bit field in HI-SPEED SD card */
>  #define SDHCI_QUIRK_NO_HISPD_BIT			(1<<29)
>  /* Controller treats ADMA descriptors with length 0000h incorrectly */
> 


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

* [PATCH 08/23] mmc: sdhci: rename quirk SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12
@ 2016-04-22 12:33     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-22 12:33 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> Rename ACMD12 quirk to SDHCI_QUIRK_MULTIBLOCK_ACMD12 to avoid confusion
> since it's needed for both read and write.

I am not in favour of renaming unless the original name is really really
bad.  In this case it is a quirk which we anyway expect to remove at some
point, so let's leave it alone for now.

> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
>  drivers/mmc/host/sdhci-pci-o2micro.c | 2 +-
>  drivers/mmc/host/sdhci-pltfm.c       | 2 +-
>  drivers/mmc/host/sdhci-s3c.c         | 2 +-
>  drivers/mmc/host/sdhci.c             | 2 +-
>  drivers/mmc/host/sdhci.h             | 2 +-
>  5 files changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
> index d48f031..1ed1f995 100644
> --- a/drivers/mmc/host/sdhci-pci-o2micro.c
> +++ b/drivers/mmc/host/sdhci-pci-o2micro.c
> @@ -162,7 +162,7 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
>  	case PCI_DEVICE_ID_O2_FUJIN2:
>  		reg = sdhci_readl(host, O2_SD_VENDOR_SETTING);
>  		if (reg & 0x1)
> -			host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
> +			host->quirks |= SDHCI_QUIRK_MULTIBLOCK_ACMD12;
>  
>  		if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2)
>  			break;
> diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
> index 072bb27..206057a 100644
> --- a/drivers/mmc/host/sdhci-pltfm.c
> +++ b/drivers/mmc/host/sdhci-pltfm.c
> @@ -74,7 +74,7 @@ void sdhci_get_of_property(struct platform_device *pdev)
>  	u32 bus_width;
>  
>  	if (of_get_property(np, "sdhci,auto-cmd12", NULL))
> -		host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
> +		host->quirks |= SDHCI_QUIRK_MULTIBLOCK_ACMD12;
>  
>  	if (of_get_property(np, "sdhci,1-bit-only", NULL) ||
>  	    (of_property_read_u32(np, "bus-width", &bus_width) == 0 &&
> diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
> index 70c724b..756b9bb 100644
> --- a/drivers/mmc/host/sdhci-s3c.c
> +++ b/drivers/mmc/host/sdhci-s3c.c
> @@ -564,7 +564,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
>  	host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ;
>  
>  	/* This host supports the Auto CMD12 */
> -	host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
> +	host->quirks |= SDHCI_QUIRK_MULTIBLOCK_ACMD12;
>  
>  	/* Samsung SoCs need BROKEN_ADMA_ZEROLEN_DESC */
>  	host->quirks |= SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC;
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 96ccb15..40e3551 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -2988,7 +2988,7 @@ int sdhci_add_host(struct sdhci_host *host)
>  	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
>  	mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
>  
> -	if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
> +	if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_ACMD12)
>  		host->flags |= SDHCI_AUTO_CMD12;
>  
>  	/* Auto-CMD23 stuff only works in ADMA or PIO. */
> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index 0f39f4f..afa4de8 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -379,7 +379,7 @@ struct sdhci_host {
>  /* Controller is missing device caps. Use caps provided by host */
>  #define SDHCI_QUIRK_MISSING_CAPS			(1<<27)
>  /* Controller uses Auto CMD12 command to stop the transfer */
> -#define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12		(1<<28)
> +#define SDHCI_QUIRK_MULTIBLOCK_ACMD12			(1<<28)
>  /* Controller doesn't have HISPD bit field in HI-SPEED SD card */
>  #define SDHCI_QUIRK_NO_HISPD_BIT			(1<<29)
>  /* Controller treats ADMA descriptors with length 0000h incorrectly */
> 

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

* Re: [PATCH 10/23] mmc: core: disable auto retune during card detection process
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-04-22 12:48     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-22 12:48 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> During card detection process, mmc core may sends commands
> to detect if card is still exist in mmc_rescan for removable
> card which may trigger mmc retuning process after a bit time
> of runtime pm suspend.
> Obviously this retuning process is meaningless for card remove
> case, so we disable mmc_retune in mmc_detect_change() for it.
> For card insert case, the mmc_retune will be enabled normally
> in its card initialization process later in mmc_execute_tuning().
> So disable it at first has no side effection.

We don't assume that the card has been removed, which is why we send
commands to find out if it is still there.  If it is still there, this
change will have incorrectly disabled re-tuning.

Do you have an actual problem with the way it works now?

> 
> CC: stable <stable@vger.kernel.org>
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
>  drivers/mmc/core/core.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index 52bfaf0..76d0802 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -1888,6 +1888,7 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
>  		pm_wakeup_event(mmc_dev(host), 5000);
>  
>  	host->detect_change = 1;
> +	mmc_retune_disable(host);
>  	mmc_schedule_delayed_work(&host->detect, delay);
>  }
>  
> 


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

* [PATCH 10/23] mmc: core: disable auto retune during card detection process
@ 2016-04-22 12:48     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-22 12:48 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> During card detection process, mmc core may sends commands
> to detect if card is still exist in mmc_rescan for removable
> card which may trigger mmc retuning process after a bit time
> of runtime pm suspend.
> Obviously this retuning process is meaningless for card remove
> case, so we disable mmc_retune in mmc_detect_change() for it.
> For card insert case, the mmc_retune will be enabled normally
> in its card initialization process later in mmc_execute_tuning().
> So disable it at first has no side effection.

We don't assume that the card has been removed, which is why we send
commands to find out if it is still there.  If it is still there, this
change will have incorrectly disabled re-tuning.

Do you have an actual problem with the way it works now?

> 
> CC: stable <stable@vger.kernel.org>
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
>  drivers/mmc/core/core.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index 52bfaf0..76d0802 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -1888,6 +1888,7 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
>  		pm_wakeup_event(mmc_dev(host), 5000);
>  
>  	host->detect_change = 1;
> +	mmc_retune_disable(host);
>  	mmc_schedule_delayed_work(&host->detect, delay);
>  }
>  
> 

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

* Re: [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
  2016-04-22 11:43     ` Adrian Hunter
@ 2016-04-24  9:14       ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-24  9:14 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

Hi Adrian,

Thanks for the review first.

On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
>> Handle host and regulator signal voltage switch separately.
>> Move host signal voltage switch code into a separated function
>> sdhci_do_signal_voltage_switch() first, the following patches will
>> remove the regulator voltage switch code and use the common
>> mmc_regulator_set_vqmmc() instead.
>
> You have changed the order that things are done.

Yes, the oder changes a bit that we always do controller voltage switch first.
I suppose the order is irrelevant here since i don't recall any
requirement from card.

Actually the original order is also a bit mass.
e.g.
For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
It looks to us the original one also order irrelevant.

> There is no way to know
> what that will break, so let's not do that.  What about just changing
> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
>

Currently what i can think out VIO switch using are three cases: (Pls
help add if any)
1) Both host IO and card IO use external vqmmc to do switch
(e.g eMMC 1.8V DDR/HS200/HS400 mode)

eMMC has no IO voltage switch protocol and requirement, so usually
board designed
using fixed 1.8V for eMMC and host IO.
Event it's switchable, it should be done in the first mmc_power_up().
Dynamical switch later may cause eMMC unable to work properly.
(We have been confirmed about this issue by many eMMC vendors
like Micron and Sandisk. I'm not sure if any exceptions in the community
still doing VIO dynamical switch for eMMC, if yes, please help share
the experience!).

Event some people still do dynamical IO switch for eMMC, since eMMC
spec has no requirement, so the order should also not care.

2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)

SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
regulator to do card IO voltage switch. It does not use external vqmmc
regulator.
So order irrelevant too.

3) Host using controller IO switch while card using external vqmmc
(special SDIO3.0 or eMMC)
I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
the spec and using external regulator for card IO voltage.
Usually it's required to fix to 1.8v and also not order irrelevant.

For eMMC, refer to case 1), it should be fixed to 1.8v at power up.

So it looks all cases seems are not order required.

Furthermore, i think sdhci_start_signal_voltage_switch() interface should not
be order dependant, if yes, then the issue should be fixed at a higher level.

The main purpose of this patch and next patch is to make
sdhci_signal_voltage_swithc()
more clear since we already have a more robust mmc_regulator_set_vqmmc()
and for host without vqmmc, we event do not need run that part of code.

BTW changing regulator_set_voltage() to mmc_regulator_set_vqmmc()
is the same situation here.

Anyway, more test from others will be a great help and appreciated.

Regards
Dong Aisheng

>>
>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>> ---
>>  drivers/mmc/host/sdhci.c | 97 ++++++++++++++++++++++++++++--------------------
>>  1 file changed, 57 insertions(+), 40 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 839aa4c..7f63f5d 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -1657,19 +1657,10 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
>>       spin_unlock_irqrestore(&host->lock, flags);
>>  }
>>
>> -static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>> -                                          struct mmc_ios *ios)
>> +static int sdhci_do_signal_voltage_switch(struct sdhci_host *host,
>> +                                       struct mmc_ios *ios)
>>  {
>> -     struct sdhci_host *host = mmc_priv(mmc);
>>       u16 ctrl;
>> -     int ret;
>> -
>> -     /*
>> -      * Signal Voltage Switching is only applicable for Host Controllers
>> -      * v3.00 and above.
>> -      */
>> -     if (host->version < SDHCI_SPEC_300)
>> -             return 0;
>>
>>       ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
>>
>> @@ -1679,15 +1670,6 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>>               ctrl &= ~SDHCI_CTRL_VDD_180;
>>               sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>
>> -             if (!IS_ERR(mmc->supply.vqmmc)) {
>> -                     ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
>> -                                                 3600000);
>> -                     if (ret) {
>> -                             pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>> -                                     mmc_hostname(mmc));
>> -                             return -EIO;
>> -                     }
>> -             }
>>               /* Wait for 5ms */
>>               usleep_range(5000, 5500);
>>
>> @@ -1697,20 +1679,10 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>>                       return 0;
>>
>>               pr_warn("%s: 3.3V regulator output did not became stable\n",
>> -                     mmc_hostname(mmc));
>> +                     mmc_hostname(host->mmc));
>>
>>               return -EAGAIN;
>>       case MMC_SIGNAL_VOLTAGE_180:
>> -             if (!IS_ERR(mmc->supply.vqmmc)) {
>> -                     ret = regulator_set_voltage(mmc->supply.vqmmc,
>> -                                     1700000, 1950000);
>> -                     if (ret) {
>> -                             pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>> -                                     mmc_hostname(mmc));
>> -                             return -EIO;
>> -                     }
>> -             }
>> -
>>               /*
>>                * Enable 1.8V Signal Enable in the Host Control2
>>                * register
>> @@ -1728,18 +1700,63 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>>                       return 0;
>>
>>               pr_warn("%s: 1.8V regulator output did not became stable\n",
>> -                     mmc_hostname(mmc));
>> +                     mmc_hostname(host->mmc));
>>
>>               return -EAGAIN;
>> +     default:
>> +             /* No signal voltage switch required */
>> +             return 0;
>> +     }
>> +}
>> +
>> +static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>> +                                          struct mmc_ios *ios)
>> +{
>> +     struct sdhci_host *host = mmc_priv(mmc);
>> +     int ret;
>> +
>> +     /*
>> +      * Signal Voltage Switching is only applicable for Host Controllers
>> +      * v3.00 and above.
>> +      */
>> +     if (host->version < SDHCI_SPEC_300)
>> +             return 0;
>> +
>> +     ret = sdhci_do_signal_voltage_switch(host, ios);
>> +     if (ret)
>> +             return ret;
>> +
>> +     if (IS_ERR(mmc->supply.vqmmc))
>> +             return 0;
>> +
>> +     switch (ios->signal_voltage) {
>> +     case MMC_SIGNAL_VOLTAGE_330:
>> +             ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
>> +                                         3600000);
>> +             if (ret) {
>> +                     pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>> +                             mmc_hostname(mmc));
>> +                     return -EIO;
>> +             }
>> +
>> +             return 0;
>> +     case MMC_SIGNAL_VOLTAGE_180:
>> +             ret = regulator_set_voltage(mmc->supply.vqmmc,
>> +                             1700000, 1950000);
>> +             if (ret) {
>> +                     pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>> +                             mmc_hostname(mmc));
>> +                     return -EIO;
>> +             }
>> +
>> +             return 0;
>>       case MMC_SIGNAL_VOLTAGE_120:
>> -             if (!IS_ERR(mmc->supply.vqmmc)) {
>> -                     ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
>> -                                                 1300000);
>> -                     if (ret) {
>> -                             pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>> -                                     mmc_hostname(mmc));
>> -                             return -EIO;
>> -                     }
>> +             ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
>> +                                         1300000);
>> +             if (ret) {
>> +                     pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>> +                             mmc_hostname(mmc));
>> +                     return -EIO;
>>               }
>>               return 0;
>>       default:
>>
>

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

* [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
@ 2016-04-24  9:14       ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-24  9:14 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Adrian,

Thanks for the review first.

On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
>> Handle host and regulator signal voltage switch separately.
>> Move host signal voltage switch code into a separated function
>> sdhci_do_signal_voltage_switch() first, the following patches will
>> remove the regulator voltage switch code and use the common
>> mmc_regulator_set_vqmmc() instead.
>
> You have changed the order that things are done.

Yes, the oder changes a bit that we always do controller voltage switch first.
I suppose the order is irrelevant here since i don't recall any
requirement from card.

Actually the original order is also a bit mass.
e.g.
For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
It looks to us the original one also order irrelevant.

> There is no way to know
> what that will break, so let's not do that.  What about just changing
> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
>

Currently what i can think out VIO switch using are three cases: (Pls
help add if any)
1) Both host IO and card IO use external vqmmc to do switch
(e.g eMMC 1.8V DDR/HS200/HS400 mode)

eMMC has no IO voltage switch protocol and requirement, so usually
board designed
using fixed 1.8V for eMMC and host IO.
Event it's switchable, it should be done in the first mmc_power_up().
Dynamical switch later may cause eMMC unable to work properly.
(We have been confirmed about this issue by many eMMC vendors
like Micron and Sandisk. I'm not sure if any exceptions in the community
still doing VIO dynamical switch for eMMC, if yes, please help share
the experience!).

Event some people still do dynamical IO switch for eMMC, since eMMC
spec has no requirement, so the order should also not care.

2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)

SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
regulator to do card IO voltage switch. It does not use external vqmmc
regulator.
So order irrelevant too.

3) Host using controller IO switch while card using external vqmmc
(special SDIO3.0 or eMMC)
I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
the spec and using external regulator for card IO voltage.
Usually it's required to fix to 1.8v and also not order irrelevant.

For eMMC, refer to case 1), it should be fixed to 1.8v at power up.

So it looks all cases seems are not order required.

Furthermore, i think sdhci_start_signal_voltage_switch() interface should not
be order dependant, if yes, then the issue should be fixed at a higher level.

The main purpose of this patch and next patch is to make
sdhci_signal_voltage_swithc()
more clear since we already have a more robust mmc_regulator_set_vqmmc()
and for host without vqmmc, we event do not need run that part of code.

BTW changing regulator_set_voltage() to mmc_regulator_set_vqmmc()
is the same situation here.

Anyway, more test from others will be a great help and appreciated.

Regards
Dong Aisheng

>>
>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>> ---
>>  drivers/mmc/host/sdhci.c | 97 ++++++++++++++++++++++++++++--------------------
>>  1 file changed, 57 insertions(+), 40 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 839aa4c..7f63f5d 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -1657,19 +1657,10 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
>>       spin_unlock_irqrestore(&host->lock, flags);
>>  }
>>
>> -static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>> -                                          struct mmc_ios *ios)
>> +static int sdhci_do_signal_voltage_switch(struct sdhci_host *host,
>> +                                       struct mmc_ios *ios)
>>  {
>> -     struct sdhci_host *host = mmc_priv(mmc);
>>       u16 ctrl;
>> -     int ret;
>> -
>> -     /*
>> -      * Signal Voltage Switching is only applicable for Host Controllers
>> -      * v3.00 and above.
>> -      */
>> -     if (host->version < SDHCI_SPEC_300)
>> -             return 0;
>>
>>       ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
>>
>> @@ -1679,15 +1670,6 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>>               ctrl &= ~SDHCI_CTRL_VDD_180;
>>               sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>
>> -             if (!IS_ERR(mmc->supply.vqmmc)) {
>> -                     ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
>> -                                                 3600000);
>> -                     if (ret) {
>> -                             pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>> -                                     mmc_hostname(mmc));
>> -                             return -EIO;
>> -                     }
>> -             }
>>               /* Wait for 5ms */
>>               usleep_range(5000, 5500);
>>
>> @@ -1697,20 +1679,10 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>>                       return 0;
>>
>>               pr_warn("%s: 3.3V regulator output did not became stable\n",
>> -                     mmc_hostname(mmc));
>> +                     mmc_hostname(host->mmc));
>>
>>               return -EAGAIN;
>>       case MMC_SIGNAL_VOLTAGE_180:
>> -             if (!IS_ERR(mmc->supply.vqmmc)) {
>> -                     ret = regulator_set_voltage(mmc->supply.vqmmc,
>> -                                     1700000, 1950000);
>> -                     if (ret) {
>> -                             pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>> -                                     mmc_hostname(mmc));
>> -                             return -EIO;
>> -                     }
>> -             }
>> -
>>               /*
>>                * Enable 1.8V Signal Enable in the Host Control2
>>                * register
>> @@ -1728,18 +1700,63 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>>                       return 0;
>>
>>               pr_warn("%s: 1.8V regulator output did not became stable\n",
>> -                     mmc_hostname(mmc));
>> +                     mmc_hostname(host->mmc));
>>
>>               return -EAGAIN;
>> +     default:
>> +             /* No signal voltage switch required */
>> +             return 0;
>> +     }
>> +}
>> +
>> +static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>> +                                          struct mmc_ios *ios)
>> +{
>> +     struct sdhci_host *host = mmc_priv(mmc);
>> +     int ret;
>> +
>> +     /*
>> +      * Signal Voltage Switching is only applicable for Host Controllers
>> +      * v3.00 and above.
>> +      */
>> +     if (host->version < SDHCI_SPEC_300)
>> +             return 0;
>> +
>> +     ret = sdhci_do_signal_voltage_switch(host, ios);
>> +     if (ret)
>> +             return ret;
>> +
>> +     if (IS_ERR(mmc->supply.vqmmc))
>> +             return 0;
>> +
>> +     switch (ios->signal_voltage) {
>> +     case MMC_SIGNAL_VOLTAGE_330:
>> +             ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
>> +                                         3600000);
>> +             if (ret) {
>> +                     pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>> +                             mmc_hostname(mmc));
>> +                     return -EIO;
>> +             }
>> +
>> +             return 0;
>> +     case MMC_SIGNAL_VOLTAGE_180:
>> +             ret = regulator_set_voltage(mmc->supply.vqmmc,
>> +                             1700000, 1950000);
>> +             if (ret) {
>> +                     pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>> +                             mmc_hostname(mmc));
>> +                     return -EIO;
>> +             }
>> +
>> +             return 0;
>>       case MMC_SIGNAL_VOLTAGE_120:
>> -             if (!IS_ERR(mmc->supply.vqmmc)) {
>> -                     ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
>> -                                                 1300000);
>> -                     if (ret) {
>> -                             pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>> -                                     mmc_hostname(mmc));
>> -                             return -EIO;
>> -                     }
>> +             ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
>> +                                         1300000);
>> +             if (ret) {
>> +                     pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>> +                             mmc_hostname(mmc));
>> +                     return -EIO;
>>               }
>>               return 0;
>>       default:
>>
>

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

* Re: [PATCH 02/23] mmc: sdhci: move sdhci_get_cd() forward to avoid declaration
  2016-04-22 10:27     ` Adrian Hunter
@ 2016-04-24  9:17       ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-24  9:17 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On Fri, Apr 22, 2016 at 6:27 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
>> Move sdhci_get_cd() to avoid needing to declare this function
>> before use.
>
> In fact, we shouldn't be calling host functions directly. i.e. the call
> should be host->mmc->ops->get_cd().
>
> However the caller sdhci_do_reset() is called under spinlock so it should
> not be calling ->get_cd at all.
>
> What that means is that we really need to get rid of
> SDHCI_QUIRK_NO_CARD_NO_RESET, after which this patch wouldn't be needed, so
> let's leave it for now.
>

Yes, i agree we need get rid of SDHCI_QUIRK_NO_CARD_NO_RESET.
However, after that, we still need to remove the sdhci_get_cd
pre-declaration, right?

Regards
Dong Aisheng

>>
>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>> ---
>>  drivers/mmc/host/sdhci.c | 55 ++++++++++++++++++++++++------------------------
>>  1 file changed, 27 insertions(+), 28 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index be52a3a..839aa4c 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -53,7 +53,6 @@ static void sdhci_finish_data(struct sdhci_host *);
>>  static void sdhci_finish_command(struct sdhci_host *);
>>  static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
>>  static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
>> -static int sdhci_get_cd(struct mmc_host *mmc);
>>
>>  #ifdef CONFIG_PM
>>  static void sdhci_runtime_pm_bus_on(struct sdhci_host *host);
>> @@ -161,6 +160,33 @@ static void sdhci_disable_card_detection(struct sdhci_host *host)
>>       sdhci_set_card_detection(host, false);
>>  }
>>
>> +static int sdhci_get_cd(struct mmc_host *mmc)
>> +{
>> +     struct sdhci_host *host = mmc_priv(mmc);
>> +     int gpio_cd = mmc_gpio_get_cd(mmc);
>> +
>> +     if (host->flags & SDHCI_DEVICE_DEAD)
>> +             return 0;
>> +
>> +     /* If nonremovable, assume that the card is always present. */
>> +     if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
>> +             return 1;
>> +
>> +     /*
>> +      * Try slot gpio detect, if defined it take precedence
>> +      * over build in controller functionality
>> +      */
>> +     if (!IS_ERR_VALUE(gpio_cd))
>> +             return !!gpio_cd;
>> +
>> +     /* If polling, assume that the card is always present. */
>> +     if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
>> +             return 1;
>> +
>> +     /* Host native card detect */
>> +     return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
>> +}
>> +
>>  void sdhci_reset(struct sdhci_host *host, u8 mask)
>>  {
>>       unsigned long timeout;
>> @@ -1551,33 +1577,6 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>>       spin_unlock_irqrestore(&host->lock, flags);
>>  }
>>
>> -static int sdhci_get_cd(struct mmc_host *mmc)
>> -{
>> -     struct sdhci_host *host = mmc_priv(mmc);
>> -     int gpio_cd = mmc_gpio_get_cd(mmc);
>> -
>> -     if (host->flags & SDHCI_DEVICE_DEAD)
>> -             return 0;
>> -
>> -     /* If nonremovable, assume that the card is always present. */
>> -     if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
>> -             return 1;
>> -
>> -     /*
>> -      * Try slot gpio detect, if defined it take precedence
>> -      * over build in controller functionality
>> -      */
>> -     if (!IS_ERR_VALUE(gpio_cd))
>> -             return !!gpio_cd;
>> -
>> -     /* If polling, assume that the card is always present. */
>> -     if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
>> -             return 1;
>> -
>> -     /* Host native card detect */
>> -     return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
>> -}
>> -
>>  static int sdhci_check_ro(struct sdhci_host *host)
>>  {
>>       unsigned long flags;
>>
>

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

* [PATCH 02/23] mmc: sdhci: move sdhci_get_cd() forward to avoid declaration
@ 2016-04-24  9:17       ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-24  9:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 22, 2016 at 6:27 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
>> Move sdhci_get_cd() to avoid needing to declare this function
>> before use.
>
> In fact, we shouldn't be calling host functions directly. i.e. the call
> should be host->mmc->ops->get_cd().
>
> However the caller sdhci_do_reset() is called under spinlock so it should
> not be calling ->get_cd at all.
>
> What that means is that we really need to get rid of
> SDHCI_QUIRK_NO_CARD_NO_RESET, after which this patch wouldn't be needed, so
> let's leave it for now.
>

Yes, i agree we need get rid of SDHCI_QUIRK_NO_CARD_NO_RESET.
However, after that, we still need to remove the sdhci_get_cd
pre-declaration, right?

Regards
Dong Aisheng

>>
>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>> ---
>>  drivers/mmc/host/sdhci.c | 55 ++++++++++++++++++++++++------------------------
>>  1 file changed, 27 insertions(+), 28 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index be52a3a..839aa4c 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -53,7 +53,6 @@ static void sdhci_finish_data(struct sdhci_host *);
>>  static void sdhci_finish_command(struct sdhci_host *);
>>  static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
>>  static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
>> -static int sdhci_get_cd(struct mmc_host *mmc);
>>
>>  #ifdef CONFIG_PM
>>  static void sdhci_runtime_pm_bus_on(struct sdhci_host *host);
>> @@ -161,6 +160,33 @@ static void sdhci_disable_card_detection(struct sdhci_host *host)
>>       sdhci_set_card_detection(host, false);
>>  }
>>
>> +static int sdhci_get_cd(struct mmc_host *mmc)
>> +{
>> +     struct sdhci_host *host = mmc_priv(mmc);
>> +     int gpio_cd = mmc_gpio_get_cd(mmc);
>> +
>> +     if (host->flags & SDHCI_DEVICE_DEAD)
>> +             return 0;
>> +
>> +     /* If nonremovable, assume that the card is always present. */
>> +     if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
>> +             return 1;
>> +
>> +     /*
>> +      * Try slot gpio detect, if defined it take precedence
>> +      * over build in controller functionality
>> +      */
>> +     if (!IS_ERR_VALUE(gpio_cd))
>> +             return !!gpio_cd;
>> +
>> +     /* If polling, assume that the card is always present. */
>> +     if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
>> +             return 1;
>> +
>> +     /* Host native card detect */
>> +     return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
>> +}
>> +
>>  void sdhci_reset(struct sdhci_host *host, u8 mask)
>>  {
>>       unsigned long timeout;
>> @@ -1551,33 +1577,6 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>>       spin_unlock_irqrestore(&host->lock, flags);
>>  }
>>
>> -static int sdhci_get_cd(struct mmc_host *mmc)
>> -{
>> -     struct sdhci_host *host = mmc_priv(mmc);
>> -     int gpio_cd = mmc_gpio_get_cd(mmc);
>> -
>> -     if (host->flags & SDHCI_DEVICE_DEAD)
>> -             return 0;
>> -
>> -     /* If nonremovable, assume that the card is always present. */
>> -     if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
>> -             return 1;
>> -
>> -     /*
>> -      * Try slot gpio detect, if defined it take precedence
>> -      * over build in controller functionality
>> -      */
>> -     if (!IS_ERR_VALUE(gpio_cd))
>> -             return !!gpio_cd;
>> -
>> -     /* If polling, assume that the card is always present. */
>> -     if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
>> -             return 1;
>> -
>> -     /* Host native card detect */
>> -     return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
>> -}
>> -
>>  static int sdhci_check_ro(struct sdhci_host *host)
>>  {
>>       unsigned long flags;
>>
>

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

* Re: [PATCH 06/23] mmc: sdhci: using common mmc_regulator_set_vqmmc()
  2016-04-22 11:48     ` Adrian Hunter
@ 2016-04-24  9:25       ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-24  9:25 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On Fri, Apr 22, 2016 at 7:48 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
>> Instead of using private VCCQ regulator signal voltage switch code,
>> we switch to use the more robust common function mmc_regulator_set_vqmmc()
>> in MMC core which set the target voltage as close as possible to target
>> voltage.
>>
>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>> ---
>> Don't have a board to test mmc_regulator_set_vqmmc() switch way,
>> need others to help verify.
>
> So was there a reason you wanted to change it?
>

Yes, main reason is we already have common mmc_regulator_set_vqmmc(),
we don't want to maintain two copies of it. And the common one is more robust.

The original one is more error prone since it may set a margine IO voltage
which may more easy to lead an potential IO error.
e.g. if vqmmc is capable of 1.7V, then our host will set to 1.7v
rather than 1.8v
which is a mininum allowed IO voltage range(1.7v ~ 1.95v) defined by spec.

> I agree mmc_regulator_set_vqmmc() looks superior, but we really need
> feedback from people using this code..
>

Yes, although from code inspection, there's no functionality change,
but tests from others using it will be appreciated.

Regards
Dong Aisheng

>> ---
>>  drivers/mmc/host/sdhci.c | 39 ++-------------------------------------
>>  1 file changed, 2 insertions(+), 37 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 7f63f5d..2338aab 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -1726,43 +1726,8 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>>       if (ret)
>>               return ret;
>>
>> -     if (IS_ERR(mmc->supply.vqmmc))
>> -             return 0;
>> -
>> -     switch (ios->signal_voltage) {
>> -     case MMC_SIGNAL_VOLTAGE_330:
>> -             ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
>> -                                         3600000);
>> -             if (ret) {
>> -                     pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>> -                             mmc_hostname(mmc));
>> -                     return -EIO;
>> -             }
>> -
>> -             return 0;
>> -     case MMC_SIGNAL_VOLTAGE_180:
>> -             ret = regulator_set_voltage(mmc->supply.vqmmc,
>> -                             1700000, 1950000);
>> -             if (ret) {
>> -                     pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>> -                             mmc_hostname(mmc));
>> -                     return -EIO;
>> -             }
>> -
>> -             return 0;
>> -     case MMC_SIGNAL_VOLTAGE_120:
>> -             ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
>> -                                         1300000);
>> -             if (ret) {
>> -                     pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>> -                             mmc_hostname(mmc));
>> -                     return -EIO;
>> -             }
>> -             return 0;
>> -     default:
>> -             /* No signal voltage switch required */
>> -             return 0;
>> -     }
>> +     /* do regulator signal voltage switch if exist */
>> +     return mmc_regulator_set_vqmmc(mmc, ios);
>>  }
>>
>>  static int sdhci_card_busy(struct mmc_host *mmc)
>>
>

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

* [PATCH 06/23] mmc: sdhci: using common mmc_regulator_set_vqmmc()
@ 2016-04-24  9:25       ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-24  9:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 22, 2016 at 7:48 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
>> Instead of using private VCCQ regulator signal voltage switch code,
>> we switch to use the more robust common function mmc_regulator_set_vqmmc()
>> in MMC core which set the target voltage as close as possible to target
>> voltage.
>>
>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>> ---
>> Don't have a board to test mmc_regulator_set_vqmmc() switch way,
>> need others to help verify.
>
> So was there a reason you wanted to change it?
>

Yes, main reason is we already have common mmc_regulator_set_vqmmc(),
we don't want to maintain two copies of it. And the common one is more robust.

The original one is more error prone since it may set a margine IO voltage
which may more easy to lead an potential IO error.
e.g. if vqmmc is capable of 1.7V, then our host will set to 1.7v
rather than 1.8v
which is a mininum allowed IO voltage range(1.7v ~ 1.95v) defined by spec.

> I agree mmc_regulator_set_vqmmc() looks superior, but we really need
> feedback from people using this code..
>

Yes, although from code inspection, there's no functionality change,
but tests from others using it will be appreciated.

Regards
Dong Aisheng

>> ---
>>  drivers/mmc/host/sdhci.c | 39 ++-------------------------------------
>>  1 file changed, 2 insertions(+), 37 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 7f63f5d..2338aab 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -1726,43 +1726,8 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>>       if (ret)
>>               return ret;
>>
>> -     if (IS_ERR(mmc->supply.vqmmc))
>> -             return 0;
>> -
>> -     switch (ios->signal_voltage) {
>> -     case MMC_SIGNAL_VOLTAGE_330:
>> -             ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
>> -                                         3600000);
>> -             if (ret) {
>> -                     pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>> -                             mmc_hostname(mmc));
>> -                     return -EIO;
>> -             }
>> -
>> -             return 0;
>> -     case MMC_SIGNAL_VOLTAGE_180:
>> -             ret = regulator_set_voltage(mmc->supply.vqmmc,
>> -                             1700000, 1950000);
>> -             if (ret) {
>> -                     pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>> -                             mmc_hostname(mmc));
>> -                     return -EIO;
>> -             }
>> -
>> -             return 0;
>> -     case MMC_SIGNAL_VOLTAGE_120:
>> -             ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
>> -                                         1300000);
>> -             if (ret) {
>> -                     pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>> -                             mmc_hostname(mmc));
>> -                     return -EIO;
>> -             }
>> -             return 0;
>> -     default:
>> -             /* No signal voltage switch required */
>> -             return 0;
>> -     }
>> +     /* do regulator signal voltage switch if exist */
>> +     return mmc_regulator_set_vqmmc(mmc, ios);
>>  }
>>
>>  static int sdhci_card_busy(struct mmc_host *mmc)
>>
>

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

* Re: [PATCH 07/23] mmc: sdhci: check SDHCI_QUIRK2_NO_1_8_V when do voltage switch
  2016-04-22 12:30     ` Adrian Hunter
@ 2016-04-24  9:56       ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-24  9:56 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On Fri, Apr 22, 2016 at 8:30 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
>> Currently when card type supports EXT_CSD_CARD_TYPE_DDR_1_8V
>> which means it can work on DDR mode with either 3.3v IO or 1.8v
>> IO voltage. MMC core will first try 1.8v then 3.3v if host claims
>> MMC_CAP_1_8V_DDR support.
>> However the host driver voltage switch code does not check NO_1_8_V
>> quirk which may set a wrong 1.8v and causes the card fixed to 3.3v
>> VIO un-work.
>>
>> Checking 1.8V quirk before setting it to avoid such issue.
>
> We need to look forward to when SDHCI_QUIRK2_NO_1_8_V doesn't exist.
>

Yes, i did try to clean up SDHCI_QUIRK2_NO_1_8_V.
However, it seems not that simply.
Currently we may still need it before we got a better way.

My point is whether we should stop fixing the exist issue in SDHCI driver
just caused by we want to clean up it later?

> There are two possibilities:
>
> 1. Add MMC_CAP_3_3V_DDR and support to core and use that instead of
> MMC_CAP_1_8V_DDR.  You'll need Ulf's feedback on that.
>

Yes, we can do it.
But the point is for DDR50/SD3.0/SDIO3.0/HS200/HS400 cards we have
the same situation and still need QUIRK2_NO_1_8_V.

And i somehow a bit wonder whether we should retrieve the speed mode
support from device tree since it's actually controller capability.
IO range capability is another thing.

Probably we may start another topic to discuss it specificly.

> 2. Replace ->start_signal_voltage_switch() i.e.
>
> host->mmc_host_ops.start_signal_voltage_switch =
> esdhci_start_signal_voltage_switch;
>
> You will also need to change all calls to
> sdhci_start_signal_voltage_switch() with
> host->mmc->ops->start_signal_voltage_switch(), but that needs to be done anyway.
>

esdhc can fully use the common sdhci_start_signal_voltag_switch.
Since it's already support QUIRK_NO_1_8_V, we don't want to
invent imx voltage swith currently, but fix and use it first.

Regards
Dong Aisheng

>>
>> CC: stable <stable@vger.kernel.org>
>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>> ---
>>  drivers/mmc/host/sdhci.c | 2 ++
>>  1 file changed, 2 insertions(+)
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 2338aab..96ccb15 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -1683,6 +1683,8 @@ static int sdhci_do_signal_voltage_switch(struct sdhci_host *host,
>>
>>               return -EAGAIN;
>>       case MMC_SIGNAL_VOLTAGE_180:
>> +             if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)
>> +                     return -EINVAL;
>>               /*
>>                * Enable 1.8V Signal Enable in the Host Control2
>>                * register
>>
>

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

* [PATCH 07/23] mmc: sdhci: check SDHCI_QUIRK2_NO_1_8_V when do voltage switch
@ 2016-04-24  9:56       ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-24  9:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 22, 2016 at 8:30 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
>> Currently when card type supports EXT_CSD_CARD_TYPE_DDR_1_8V
>> which means it can work on DDR mode with either 3.3v IO or 1.8v
>> IO voltage. MMC core will first try 1.8v then 3.3v if host claims
>> MMC_CAP_1_8V_DDR support.
>> However the host driver voltage switch code does not check NO_1_8_V
>> quirk which may set a wrong 1.8v and causes the card fixed to 3.3v
>> VIO un-work.
>>
>> Checking 1.8V quirk before setting it to avoid such issue.
>
> We need to look forward to when SDHCI_QUIRK2_NO_1_8_V doesn't exist.
>

Yes, i did try to clean up SDHCI_QUIRK2_NO_1_8_V.
However, it seems not that simply.
Currently we may still need it before we got a better way.

My point is whether we should stop fixing the exist issue in SDHCI driver
just caused by we want to clean up it later?

> There are two possibilities:
>
> 1. Add MMC_CAP_3_3V_DDR and support to core and use that instead of
> MMC_CAP_1_8V_DDR.  You'll need Ulf's feedback on that.
>

Yes, we can do it.
But the point is for DDR50/SD3.0/SDIO3.0/HS200/HS400 cards we have
the same situation and still need QUIRK2_NO_1_8_V.

And i somehow a bit wonder whether we should retrieve the speed mode
support from device tree since it's actually controller capability.
IO range capability is another thing.

Probably we may start another topic to discuss it specificly.

> 2. Replace ->start_signal_voltage_switch() i.e.
>
> host->mmc_host_ops.start_signal_voltage_switch =
> esdhci_start_signal_voltage_switch;
>
> You will also need to change all calls to
> sdhci_start_signal_voltage_switch() with
> host->mmc->ops->start_signal_voltage_switch(), but that needs to be done anyway.
>

esdhc can fully use the common sdhci_start_signal_voltag_switch.
Since it's already support QUIRK_NO_1_8_V, we don't want to
invent imx voltage swith currently, but fix and use it first.

Regards
Dong Aisheng

>>
>> CC: stable <stable@vger.kernel.org>
>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>> ---
>>  drivers/mmc/host/sdhci.c | 2 ++
>>  1 file changed, 2 insertions(+)
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 2338aab..96ccb15 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -1683,6 +1683,8 @@ static int sdhci_do_signal_voltage_switch(struct sdhci_host *host,
>>
>>               return -EAGAIN;
>>       case MMC_SIGNAL_VOLTAGE_180:
>> +             if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)
>> +                     return -EINVAL;
>>               /*
>>                * Enable 1.8V Signal Enable in the Host Control2
>>                * register
>>
>

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

* Re: [PATCH 08/23] mmc: sdhci: rename quirk SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12
  2016-04-22 12:33     ` Adrian Hunter
@ 2016-04-24 10:00       ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-24 10:00 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On Fri, Apr 22, 2016 at 8:33 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
>> Rename ACMD12 quirk to SDHCI_QUIRK_MULTIBLOCK_ACMD12 to avoid confusion
>> since it's needed for both read and write.
>
> I am not in favour of renaming unless the original name is really really
> bad.  In this case it is a quirk which we anyway expect to remove at some
> point, so let's leave it alone for now.
>

It is really confusing when i first see it. So i made this patch.
We could clear it later.
And i think it's more like a capability rather than a quirk.

Anyway, it's up to you whether we should pick it.

Regards
Dong Aisheng

>>
>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>> ---
>>  drivers/mmc/host/sdhci-pci-o2micro.c | 2 +-
>>  drivers/mmc/host/sdhci-pltfm.c       | 2 +-
>>  drivers/mmc/host/sdhci-s3c.c         | 2 +-
>>  drivers/mmc/host/sdhci.c             | 2 +-
>>  drivers/mmc/host/sdhci.h             | 2 +-
>>  5 files changed, 5 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
>> index d48f031..1ed1f995 100644
>> --- a/drivers/mmc/host/sdhci-pci-o2micro.c
>> +++ b/drivers/mmc/host/sdhci-pci-o2micro.c
>> @@ -162,7 +162,7 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
>>       case PCI_DEVICE_ID_O2_FUJIN2:
>>               reg = sdhci_readl(host, O2_SD_VENDOR_SETTING);
>>               if (reg & 0x1)
>> -                     host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
>> +                     host->quirks |= SDHCI_QUIRK_MULTIBLOCK_ACMD12;
>>
>>               if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2)
>>                       break;
>> diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
>> index 072bb27..206057a 100644
>> --- a/drivers/mmc/host/sdhci-pltfm.c
>> +++ b/drivers/mmc/host/sdhci-pltfm.c
>> @@ -74,7 +74,7 @@ void sdhci_get_of_property(struct platform_device *pdev)
>>       u32 bus_width;
>>
>>       if (of_get_property(np, "sdhci,auto-cmd12", NULL))
>> -             host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
>> +             host->quirks |= SDHCI_QUIRK_MULTIBLOCK_ACMD12;
>>
>>       if (of_get_property(np, "sdhci,1-bit-only", NULL) ||
>>           (of_property_read_u32(np, "bus-width", &bus_width) == 0 &&
>> diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
>> index 70c724b..756b9bb 100644
>> --- a/drivers/mmc/host/sdhci-s3c.c
>> +++ b/drivers/mmc/host/sdhci-s3c.c
>> @@ -564,7 +564,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
>>       host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ;
>>
>>       /* This host supports the Auto CMD12 */
>> -     host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
>> +     host->quirks |= SDHCI_QUIRK_MULTIBLOCK_ACMD12;
>>
>>       /* Samsung SoCs need BROKEN_ADMA_ZEROLEN_DESC */
>>       host->quirks |= SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC;
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 96ccb15..40e3551 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -2988,7 +2988,7 @@ int sdhci_add_host(struct sdhci_host *host)
>>       mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
>>       mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
>>
>> -     if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
>> +     if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_ACMD12)
>>               host->flags |= SDHCI_AUTO_CMD12;
>>
>>       /* Auto-CMD23 stuff only works in ADMA or PIO. */
>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>> index 0f39f4f..afa4de8 100644
>> --- a/drivers/mmc/host/sdhci.h
>> +++ b/drivers/mmc/host/sdhci.h
>> @@ -379,7 +379,7 @@ struct sdhci_host {
>>  /* Controller is missing device caps. Use caps provided by host */
>>  #define SDHCI_QUIRK_MISSING_CAPS                     (1<<27)
>>  /* Controller uses Auto CMD12 command to stop the transfer */
>> -#define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12           (1<<28)
>> +#define SDHCI_QUIRK_MULTIBLOCK_ACMD12                        (1<<28)
>>  /* Controller doesn't have HISPD bit field in HI-SPEED SD card */
>>  #define SDHCI_QUIRK_NO_HISPD_BIT                     (1<<29)
>>  /* Controller treats ADMA descriptors with length 0000h incorrectly */
>>
>

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

* [PATCH 08/23] mmc: sdhci: rename quirk SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12
@ 2016-04-24 10:00       ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-24 10:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 22, 2016 at 8:33 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
>> Rename ACMD12 quirk to SDHCI_QUIRK_MULTIBLOCK_ACMD12 to avoid confusion
>> since it's needed for both read and write.
>
> I am not in favour of renaming unless the original name is really really
> bad.  In this case it is a quirk which we anyway expect to remove at some
> point, so let's leave it alone for now.
>

It is really confusing when i first see it. So i made this patch.
We could clear it later.
And i think it's more like a capability rather than a quirk.

Anyway, it's up to you whether we should pick it.

Regards
Dong Aisheng

>>
>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>> ---
>>  drivers/mmc/host/sdhci-pci-o2micro.c | 2 +-
>>  drivers/mmc/host/sdhci-pltfm.c       | 2 +-
>>  drivers/mmc/host/sdhci-s3c.c         | 2 +-
>>  drivers/mmc/host/sdhci.c             | 2 +-
>>  drivers/mmc/host/sdhci.h             | 2 +-
>>  5 files changed, 5 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
>> index d48f031..1ed1f995 100644
>> --- a/drivers/mmc/host/sdhci-pci-o2micro.c
>> +++ b/drivers/mmc/host/sdhci-pci-o2micro.c
>> @@ -162,7 +162,7 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
>>       case PCI_DEVICE_ID_O2_FUJIN2:
>>               reg = sdhci_readl(host, O2_SD_VENDOR_SETTING);
>>               if (reg & 0x1)
>> -                     host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
>> +                     host->quirks |= SDHCI_QUIRK_MULTIBLOCK_ACMD12;
>>
>>               if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2)
>>                       break;
>> diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
>> index 072bb27..206057a 100644
>> --- a/drivers/mmc/host/sdhci-pltfm.c
>> +++ b/drivers/mmc/host/sdhci-pltfm.c
>> @@ -74,7 +74,7 @@ void sdhci_get_of_property(struct platform_device *pdev)
>>       u32 bus_width;
>>
>>       if (of_get_property(np, "sdhci,auto-cmd12", NULL))
>> -             host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
>> +             host->quirks |= SDHCI_QUIRK_MULTIBLOCK_ACMD12;
>>
>>       if (of_get_property(np, "sdhci,1-bit-only", NULL) ||
>>           (of_property_read_u32(np, "bus-width", &bus_width) == 0 &&
>> diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
>> index 70c724b..756b9bb 100644
>> --- a/drivers/mmc/host/sdhci-s3c.c
>> +++ b/drivers/mmc/host/sdhci-s3c.c
>> @@ -564,7 +564,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
>>       host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ;
>>
>>       /* This host supports the Auto CMD12 */
>> -     host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
>> +     host->quirks |= SDHCI_QUIRK_MULTIBLOCK_ACMD12;
>>
>>       /* Samsung SoCs need BROKEN_ADMA_ZEROLEN_DESC */
>>       host->quirks |= SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC;
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 96ccb15..40e3551 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -2988,7 +2988,7 @@ int sdhci_add_host(struct sdhci_host *host)
>>       mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
>>       mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
>>
>> -     if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
>> +     if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_ACMD12)
>>               host->flags |= SDHCI_AUTO_CMD12;
>>
>>       /* Auto-CMD23 stuff only works in ADMA or PIO. */
>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>> index 0f39f4f..afa4de8 100644
>> --- a/drivers/mmc/host/sdhci.h
>> +++ b/drivers/mmc/host/sdhci.h
>> @@ -379,7 +379,7 @@ struct sdhci_host {
>>  /* Controller is missing device caps. Use caps provided by host */
>>  #define SDHCI_QUIRK_MISSING_CAPS                     (1<<27)
>>  /* Controller uses Auto CMD12 command to stop the transfer */
>> -#define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12           (1<<28)
>> +#define SDHCI_QUIRK_MULTIBLOCK_ACMD12                        (1<<28)
>>  /* Controller doesn't have HISPD bit field in HI-SPEED SD card */
>>  #define SDHCI_QUIRK_NO_HISPD_BIT                     (1<<29)
>>  /* Controller treats ADMA descriptors with length 0000h incorrectly */
>>
>

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

* Re: [PATCH 10/23] mmc: core: disable auto retune during card detection process
  2016-04-22 12:48     ` Adrian Hunter
@ 2016-04-24 10:47       ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-24 10:47 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On Fri, Apr 22, 2016 at 8:48 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
>> During card detection process, mmc core may sends commands
>> to detect if card is still exist in mmc_rescan for removable
>> card which may trigger mmc retuning process after a bit time
>> of runtime pm suspend.
>> Obviously this retuning process is meaningless for card remove
>> case, so we disable mmc_retune in mmc_detect_change() for it.
>> For card insert case, the mmc_retune will be enabled normally
>> in its card initialization process later in mmc_execute_tuning().
>> So disable it at first has no side effection.
>
> We don't assume that the card has been removed, which is why we send
> commands to find out if it is still there.  If it is still there, this
> change will have incorrectly disabled re-tuning.
>

Do you mean the 'fake' card remove interrupt like caused by glitch?
Yes, if that the card is still exist and re-tuning is wrongly disabled.

So we could re-enable re-tuning for this special case?
Something like:
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 41b1e76..e1990a8 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2607,6 +2607,8 @@ void mmc_rescan(struct work_struct *work)

        /* if there still is a card present, stop here */
        if (host->bus_ops != NULL) {
+               if (tuning_is_enabled_before())
+                       mmc_retune_enable(host);
                mmc_bus_put(host);
                goto out;
        }


> Do you have an actual problem with the way it works now?
>

No actual problems now.
I just observe a lot tuning commands keep sending although the card is already
removed which seems a bit meaningless.
And most tuning execution process is executed with sin_lock_irqsave, i'm not
sure if the mass tuning commands may affect the system when CPU is busy.
What do you think?

Regards
Dong Aisheng

>>
>> CC: stable <stable@vger.kernel.org>
>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>> ---
>>  drivers/mmc/core/core.c | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
>> index 52bfaf0..76d0802 100644
>> --- a/drivers/mmc/core/core.c
>> +++ b/drivers/mmc/core/core.c
>> @@ -1888,6 +1888,7 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
>>               pm_wakeup_event(mmc_dev(host), 5000);
>>
>>       host->detect_change = 1;
>> +     mmc_retune_disable(host);
>>       mmc_schedule_delayed_work(&host->detect, delay);
>>  }
>>
>>
>

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

* [PATCH 10/23] mmc: core: disable auto retune during card detection process
@ 2016-04-24 10:47       ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-24 10:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 22, 2016 at 8:48 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
>> During card detection process, mmc core may sends commands
>> to detect if card is still exist in mmc_rescan for removable
>> card which may trigger mmc retuning process after a bit time
>> of runtime pm suspend.
>> Obviously this retuning process is meaningless for card remove
>> case, so we disable mmc_retune in mmc_detect_change() for it.
>> For card insert case, the mmc_retune will be enabled normally
>> in its card initialization process later in mmc_execute_tuning().
>> So disable it at first has no side effection.
>
> We don't assume that the card has been removed, which is why we send
> commands to find out if it is still there.  If it is still there, this
> change will have incorrectly disabled re-tuning.
>

Do you mean the 'fake' card remove interrupt like caused by glitch?
Yes, if that the card is still exist and re-tuning is wrongly disabled.

So we could re-enable re-tuning for this special case?
Something like:
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 41b1e76..e1990a8 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2607,6 +2607,8 @@ void mmc_rescan(struct work_struct *work)

        /* if there still is a card present, stop here */
        if (host->bus_ops != NULL) {
+               if (tuning_is_enabled_before())
+                       mmc_retune_enable(host);
                mmc_bus_put(host);
                goto out;
        }


> Do you have an actual problem with the way it works now?
>

No actual problems now.
I just observe a lot tuning commands keep sending although the card is already
removed which seems a bit meaningless.
And most tuning execution process is executed with sin_lock_irqsave, i'm not
sure if the mass tuning commands may affect the system when CPU is busy.
What do you think?

Regards
Dong Aisheng

>>
>> CC: stable <stable@vger.kernel.org>
>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>> ---
>>  drivers/mmc/core/core.c | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
>> index 52bfaf0..76d0802 100644
>> --- a/drivers/mmc/core/core.c
>> +++ b/drivers/mmc/core/core.c
>> @@ -1888,6 +1888,7 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
>>               pm_wakeup_event(mmc_dev(host), 5000);
>>
>>       host->detect_change = 1;
>> +     mmc_retune_disable(host);
>>       mmc_schedule_delayed_work(&host->detect, delay);
>>  }
>>
>>
>

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

* Re: [PATCH 02/23] mmc: sdhci: move sdhci_get_cd() forward to avoid declaration
  2016-04-24  9:17       ` Dong Aisheng
@ 2016-04-27 20:26         ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-27 20:26 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On 24/04/2016 12:17 p.m., Dong Aisheng wrote:
> On Fri, Apr 22, 2016 at 6:27 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>> On 15/04/16 20:29, Dong Aisheng wrote:
>>> Move sdhci_get_cd() to avoid needing to declare this function
>>> before use.
>>
>> In fact, we shouldn't be calling host functions directly. i.e. the call
>> should be host->mmc->ops->get_cd().
>>
>> However the caller sdhci_do_reset() is called under spinlock so it should
>> not be calling ->get_cd at all.
>>
>> What that means is that we really need to get rid of
>> SDHCI_QUIRK_NO_CARD_NO_RESET, after which this patch wouldn't be needed, so
>> let's leave it for now.
>>
>
> Yes, i agree we need get rid of SDHCI_QUIRK_NO_CARD_NO_RESET.
> However, after that, we still need to remove the sdhci_get_cd
> pre-declaration, right?

Sure

>
> Regards
> Dong Aisheng
>
>>>
>>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>>> ---
>>>   drivers/mmc/host/sdhci.c | 55 ++++++++++++++++++++++++------------------------
>>>   1 file changed, 27 insertions(+), 28 deletions(-)
>>>
>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>> index be52a3a..839aa4c 100644
>>> --- a/drivers/mmc/host/sdhci.c
>>> +++ b/drivers/mmc/host/sdhci.c
>>> @@ -53,7 +53,6 @@ static void sdhci_finish_data(struct sdhci_host *);
>>>   static void sdhci_finish_command(struct sdhci_host *);
>>>   static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
>>>   static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
>>> -static int sdhci_get_cd(struct mmc_host *mmc);
>>>
>>>   #ifdef CONFIG_PM
>>>   static void sdhci_runtime_pm_bus_on(struct sdhci_host *host);
>>> @@ -161,6 +160,33 @@ static void sdhci_disable_card_detection(struct sdhci_host *host)
>>>        sdhci_set_card_detection(host, false);
>>>   }
>>>
>>> +static int sdhci_get_cd(struct mmc_host *mmc)
>>> +{
>>> +     struct sdhci_host *host = mmc_priv(mmc);
>>> +     int gpio_cd = mmc_gpio_get_cd(mmc);
>>> +
>>> +     if (host->flags & SDHCI_DEVICE_DEAD)
>>> +             return 0;
>>> +
>>> +     /* If nonremovable, assume that the card is always present. */
>>> +     if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
>>> +             return 1;
>>> +
>>> +     /*
>>> +      * Try slot gpio detect, if defined it take precedence
>>> +      * over build in controller functionality
>>> +      */
>>> +     if (!IS_ERR_VALUE(gpio_cd))
>>> +             return !!gpio_cd;
>>> +
>>> +     /* If polling, assume that the card is always present. */
>>> +     if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
>>> +             return 1;
>>> +
>>> +     /* Host native card detect */
>>> +     return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
>>> +}
>>> +
>>>   void sdhci_reset(struct sdhci_host *host, u8 mask)
>>>   {
>>>        unsigned long timeout;
>>> @@ -1551,33 +1577,6 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>>>        spin_unlock_irqrestore(&host->lock, flags);
>>>   }
>>>
>>> -static int sdhci_get_cd(struct mmc_host *mmc)
>>> -{
>>> -     struct sdhci_host *host = mmc_priv(mmc);
>>> -     int gpio_cd = mmc_gpio_get_cd(mmc);
>>> -
>>> -     if (host->flags & SDHCI_DEVICE_DEAD)
>>> -             return 0;
>>> -
>>> -     /* If nonremovable, assume that the card is always present. */
>>> -     if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
>>> -             return 1;
>>> -
>>> -     /*
>>> -      * Try slot gpio detect, if defined it take precedence
>>> -      * over build in controller functionality
>>> -      */
>>> -     if (!IS_ERR_VALUE(gpio_cd))
>>> -             return !!gpio_cd;
>>> -
>>> -     /* If polling, assume that the card is always present. */
>>> -     if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
>>> -             return 1;
>>> -
>>> -     /* Host native card detect */
>>> -     return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
>>> -}
>>> -
>>>   static int sdhci_check_ro(struct sdhci_host *host)
>>>   {
>>>        unsigned long flags;
>>>
>>

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

* [PATCH 02/23] mmc: sdhci: move sdhci_get_cd() forward to avoid declaration
@ 2016-04-27 20:26         ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-27 20:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 24/04/2016 12:17 p.m., Dong Aisheng wrote:
> On Fri, Apr 22, 2016 at 6:27 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>> On 15/04/16 20:29, Dong Aisheng wrote:
>>> Move sdhci_get_cd() to avoid needing to declare this function
>>> before use.
>>
>> In fact, we shouldn't be calling host functions directly. i.e. the call
>> should be host->mmc->ops->get_cd().
>>
>> However the caller sdhci_do_reset() is called under spinlock so it should
>> not be calling ->get_cd at all.
>>
>> What that means is that we really need to get rid of
>> SDHCI_QUIRK_NO_CARD_NO_RESET, after which this patch wouldn't be needed, so
>> let's leave it for now.
>>
>
> Yes, i agree we need get rid of SDHCI_QUIRK_NO_CARD_NO_RESET.
> However, after that, we still need to remove the sdhci_get_cd
> pre-declaration, right?

Sure

>
> Regards
> Dong Aisheng
>
>>>
>>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>>> ---
>>>   drivers/mmc/host/sdhci.c | 55 ++++++++++++++++++++++++------------------------
>>>   1 file changed, 27 insertions(+), 28 deletions(-)
>>>
>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>> index be52a3a..839aa4c 100644
>>> --- a/drivers/mmc/host/sdhci.c
>>> +++ b/drivers/mmc/host/sdhci.c
>>> @@ -53,7 +53,6 @@ static void sdhci_finish_data(struct sdhci_host *);
>>>   static void sdhci_finish_command(struct sdhci_host *);
>>>   static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
>>>   static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
>>> -static int sdhci_get_cd(struct mmc_host *mmc);
>>>
>>>   #ifdef CONFIG_PM
>>>   static void sdhci_runtime_pm_bus_on(struct sdhci_host *host);
>>> @@ -161,6 +160,33 @@ static void sdhci_disable_card_detection(struct sdhci_host *host)
>>>        sdhci_set_card_detection(host, false);
>>>   }
>>>
>>> +static int sdhci_get_cd(struct mmc_host *mmc)
>>> +{
>>> +     struct sdhci_host *host = mmc_priv(mmc);
>>> +     int gpio_cd = mmc_gpio_get_cd(mmc);
>>> +
>>> +     if (host->flags & SDHCI_DEVICE_DEAD)
>>> +             return 0;
>>> +
>>> +     /* If nonremovable, assume that the card is always present. */
>>> +     if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
>>> +             return 1;
>>> +
>>> +     /*
>>> +      * Try slot gpio detect, if defined it take precedence
>>> +      * over build in controller functionality
>>> +      */
>>> +     if (!IS_ERR_VALUE(gpio_cd))
>>> +             return !!gpio_cd;
>>> +
>>> +     /* If polling, assume that the card is always present. */
>>> +     if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
>>> +             return 1;
>>> +
>>> +     /* Host native card detect */
>>> +     return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
>>> +}
>>> +
>>>   void sdhci_reset(struct sdhci_host *host, u8 mask)
>>>   {
>>>        unsigned long timeout;
>>> @@ -1551,33 +1577,6 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>>>        spin_unlock_irqrestore(&host->lock, flags);
>>>   }
>>>
>>> -static int sdhci_get_cd(struct mmc_host *mmc)
>>> -{
>>> -     struct sdhci_host *host = mmc_priv(mmc);
>>> -     int gpio_cd = mmc_gpio_get_cd(mmc);
>>> -
>>> -     if (host->flags & SDHCI_DEVICE_DEAD)
>>> -             return 0;
>>> -
>>> -     /* If nonremovable, assume that the card is always present. */
>>> -     if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
>>> -             return 1;
>>> -
>>> -     /*
>>> -      * Try slot gpio detect, if defined it take precedence
>>> -      * over build in controller functionality
>>> -      */
>>> -     if (!IS_ERR_VALUE(gpio_cd))
>>> -             return !!gpio_cd;
>>> -
>>> -     /* If polling, assume that the card is always present. */
>>> -     if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
>>> -             return 1;
>>> -
>>> -     /* Host native card detect */
>>> -     return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
>>> -}
>>> -
>>>   static int sdhci_check_ro(struct sdhci_host *host)
>>>   {
>>>        unsigned long flags;
>>>
>>

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

* Re: [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
  2016-04-24  9:14       ` Dong Aisheng
@ 2016-04-27 20:26         ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-27 20:26 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
> Hi Adrian,
>
> Thanks for the review first.
>
> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>> On 15/04/16 20:29, Dong Aisheng wrote:
>>> Handle host and regulator signal voltage switch separately.
>>> Move host signal voltage switch code into a separated function
>>> sdhci_do_signal_voltage_switch() first, the following patches will
>>> remove the regulator voltage switch code and use the common
>>> mmc_regulator_set_vqmmc() instead.
>>
>> You have changed the order that things are done.
>
> Yes, the oder changes a bit that we always do controller voltage switch first.
> I suppose the order is irrelevant here since i don't recall any
> requirement from card.
>
> Actually the original order is also a bit mass.
> e.g.
> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
> It looks to us the original one also order irrelevant.
>
>> There is no way to know
>> what that will break, so let's not do that.  What about just changing
>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
>>
>
> Currently what i can think out VIO switch using are three cases: (Pls
> help add if any)
> 1) Both host IO and card IO use external vqmmc to do switch
> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
>
> eMMC has no IO voltage switch protocol and requirement, so usually
> board designed
> using fixed 1.8V for eMMC and host IO.
> Event it's switchable, it should be done in the first mmc_power_up().
> Dynamical switch later may cause eMMC unable to work properly.
> (We have been confirmed about this issue by many eMMC vendors
> like Micron and Sandisk. I'm not sure if any exceptions in the community
> still doing VIO dynamical switch for eMMC, if yes, please help share
> the experience!).
>
> Event some people still do dynamical IO switch for eMMC, since eMMC
> spec has no requirement, so the order should also not care.
>
> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
>
> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
> regulator to do card IO voltage switch. It does not use external vqmmc
> regulator.
> So order irrelevant too.
>
> 3) Host using controller IO switch while card using external vqmmc
> (special SDIO3.0 or eMMC)
> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
> the spec and using external regulator for card IO voltage.
> Usually it's required to fix to 1.8v and also not order irrelevant.
>
> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
>
> So it looks all cases seems are not order required.

I don't agree that there is any way to know that other host controllers
are not affected.  I don't want a repeat of sdhci_set_power().

Please instead send a patch for just using mmc_regulator_set_vqmmc()
in place of regulator_set_voltage().

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

* [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
@ 2016-04-27 20:26         ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-27 20:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
> Hi Adrian,
>
> Thanks for the review first.
>
> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>> On 15/04/16 20:29, Dong Aisheng wrote:
>>> Handle host and regulator signal voltage switch separately.
>>> Move host signal voltage switch code into a separated function
>>> sdhci_do_signal_voltage_switch() first, the following patches will
>>> remove the regulator voltage switch code and use the common
>>> mmc_regulator_set_vqmmc() instead.
>>
>> You have changed the order that things are done.
>
> Yes, the oder changes a bit that we always do controller voltage switch first.
> I suppose the order is irrelevant here since i don't recall any
> requirement from card.
>
> Actually the original order is also a bit mass.
> e.g.
> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
> It looks to us the original one also order irrelevant.
>
>> There is no way to know
>> what that will break, so let's not do that.  What about just changing
>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
>>
>
> Currently what i can think out VIO switch using are three cases: (Pls
> help add if any)
> 1) Both host IO and card IO use external vqmmc to do switch
> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
>
> eMMC has no IO voltage switch protocol and requirement, so usually
> board designed
> using fixed 1.8V for eMMC and host IO.
> Event it's switchable, it should be done in the first mmc_power_up().
> Dynamical switch later may cause eMMC unable to work properly.
> (We have been confirmed about this issue by many eMMC vendors
> like Micron and Sandisk. I'm not sure if any exceptions in the community
> still doing VIO dynamical switch for eMMC, if yes, please help share
> the experience!).
>
> Event some people still do dynamical IO switch for eMMC, since eMMC
> spec has no requirement, so the order should also not care.
>
> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
>
> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
> regulator to do card IO voltage switch. It does not use external vqmmc
> regulator.
> So order irrelevant too.
>
> 3) Host using controller IO switch while card using external vqmmc
> (special SDIO3.0 or eMMC)
> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
> the spec and using external regulator for card IO voltage.
> Usually it's required to fix to 1.8v and also not order irrelevant.
>
> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
>
> So it looks all cases seems are not order required.

I don't agree that there is any way to know that other host controllers
are not affected.  I don't want a repeat of sdhci_set_power().

Please instead send a patch for just using mmc_regulator_set_vqmmc()
in place of regulator_set_voltage().

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

* Re: [PATCH 07/23] mmc: sdhci: check SDHCI_QUIRK2_NO_1_8_V when do voltage switch
  2016-04-24  9:56       ` Dong Aisheng
@ 2016-04-27 20:27         ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-27 20:27 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On 24/04/2016 12:56 p.m., Dong Aisheng wrote:
> On Fri, Apr 22, 2016 at 8:30 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>> On 15/04/16 20:29, Dong Aisheng wrote:
>>> Currently when card type supports EXT_CSD_CARD_TYPE_DDR_1_8V
>>> which means it can work on DDR mode with either 3.3v IO or 1.8v
>>> IO voltage. MMC core will first try 1.8v then 3.3v if host claims
>>> MMC_CAP_1_8V_DDR support.
>>> However the host driver voltage switch code does not check NO_1_8_V
>>> quirk which may set a wrong 1.8v and causes the card fixed to 3.3v
>>> VIO un-work.
>>>
>>> Checking 1.8V quirk before setting it to avoid such issue.
>>
>> We need to look forward to when SDHCI_QUIRK2_NO_1_8_V doesn't exist.
>>
>
> Yes, i did try to clean up SDHCI_QUIRK2_NO_1_8_V.
> However, it seems not that simply.
> Currently we may still need it before we got a better way.
>
> My point is whether we should stop fixing the exist issue in SDHCI driver
> just caused by we want to clean up it later?

If you want a fix for stable kernels, then I guess it is OK.  In that case
it is better to have a fix that applies cleanly to older kernels
i.e. not on top of re-factoring

>
>> There are two possibilities:
>>
>> 1. Add MMC_CAP_3_3V_DDR and support to core and use that instead of
>> MMC_CAP_1_8V_DDR.  You'll need Ulf's feedback on that.
>>
>
> Yes, we can do it.
> But the point is for DDR50/SD3.0/SDIO3.0/HS200/HS400 cards we have
> the same situation and still need QUIRK2_NO_1_8_V.
>
> And i somehow a bit wonder whether we should retrieve the speed mode
> support from device tree since it's actually controller capability.
> IO range capability is another thing.
>
> Probably we may start another topic to discuss it specificly.
>
>> 2. Replace ->start_signal_voltage_switch() i.e.
>>
>> host->mmc_host_ops.start_signal_voltage_switch =
>> esdhci_start_signal_voltage_switch;
>>
>> You will also need to change all calls to
>> sdhci_start_signal_voltage_switch() with
>> host->mmc->ops->start_signal_voltage_switch(), but that needs to be done anyway.
>>
>
> esdhc can fully use the common sdhci_start_signal_voltag_switch.
> Since it's already support QUIRK_NO_1_8_V, we don't want to
> invent imx voltage swith currently, but fix and use it first.
>
> Regards
> Dong Aisheng
>
>>>
>>> CC: stable <stable@vger.kernel.org>
>>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>>> ---
>>>   drivers/mmc/host/sdhci.c | 2 ++
>>>   1 file changed, 2 insertions(+)
>>>
>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>> index 2338aab..96ccb15 100644
>>> --- a/drivers/mmc/host/sdhci.c
>>> +++ b/drivers/mmc/host/sdhci.c
>>> @@ -1683,6 +1683,8 @@ static int sdhci_do_signal_voltage_switch(struct sdhci_host *host,
>>>
>>>                return -EAGAIN;
>>>        case MMC_SIGNAL_VOLTAGE_180:
>>> +             if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)
>>> +                     return -EINVAL;
>>>                /*
>>>                 * Enable 1.8V Signal Enable in the Host Control2
>>>                 * register
>>>
>>

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

* [PATCH 07/23] mmc: sdhci: check SDHCI_QUIRK2_NO_1_8_V when do voltage switch
@ 2016-04-27 20:27         ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-27 20:27 UTC (permalink / raw)
  To: linux-arm-kernel

On 24/04/2016 12:56 p.m., Dong Aisheng wrote:
> On Fri, Apr 22, 2016 at 8:30 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>> On 15/04/16 20:29, Dong Aisheng wrote:
>>> Currently when card type supports EXT_CSD_CARD_TYPE_DDR_1_8V
>>> which means it can work on DDR mode with either 3.3v IO or 1.8v
>>> IO voltage. MMC core will first try 1.8v then 3.3v if host claims
>>> MMC_CAP_1_8V_DDR support.
>>> However the host driver voltage switch code does not check NO_1_8_V
>>> quirk which may set a wrong 1.8v and causes the card fixed to 3.3v
>>> VIO un-work.
>>>
>>> Checking 1.8V quirk before setting it to avoid such issue.
>>
>> We need to look forward to when SDHCI_QUIRK2_NO_1_8_V doesn't exist.
>>
>
> Yes, i did try to clean up SDHCI_QUIRK2_NO_1_8_V.
> However, it seems not that simply.
> Currently we may still need it before we got a better way.
>
> My point is whether we should stop fixing the exist issue in SDHCI driver
> just caused by we want to clean up it later?

If you want a fix for stable kernels, then I guess it is OK.  In that case
it is better to have a fix that applies cleanly to older kernels
i.e. not on top of re-factoring

>
>> There are two possibilities:
>>
>> 1. Add MMC_CAP_3_3V_DDR and support to core and use that instead of
>> MMC_CAP_1_8V_DDR.  You'll need Ulf's feedback on that.
>>
>
> Yes, we can do it.
> But the point is for DDR50/SD3.0/SDIO3.0/HS200/HS400 cards we have
> the same situation and still need QUIRK2_NO_1_8_V.
>
> And i somehow a bit wonder whether we should retrieve the speed mode
> support from device tree since it's actually controller capability.
> IO range capability is another thing.
>
> Probably we may start another topic to discuss it specificly.
>
>> 2. Replace ->start_signal_voltage_switch() i.e.
>>
>> host->mmc_host_ops.start_signal_voltage_switch =
>> esdhci_start_signal_voltage_switch;
>>
>> You will also need to change all calls to
>> sdhci_start_signal_voltage_switch() with
>> host->mmc->ops->start_signal_voltage_switch(), but that needs to be done anyway.
>>
>
> esdhc can fully use the common sdhci_start_signal_voltag_switch.
> Since it's already support QUIRK_NO_1_8_V, we don't want to
> invent imx voltage swith currently, but fix and use it first.
>
> Regards
> Dong Aisheng
>
>>>
>>> CC: stable <stable@vger.kernel.org>
>>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>>> ---
>>>   drivers/mmc/host/sdhci.c | 2 ++
>>>   1 file changed, 2 insertions(+)
>>>
>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>> index 2338aab..96ccb15 100644
>>> --- a/drivers/mmc/host/sdhci.c
>>> +++ b/drivers/mmc/host/sdhci.c
>>> @@ -1683,6 +1683,8 @@ static int sdhci_do_signal_voltage_switch(struct sdhci_host *host,
>>>
>>>                return -EAGAIN;
>>>        case MMC_SIGNAL_VOLTAGE_180:
>>> +             if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)
>>> +                     return -EINVAL;
>>>                /*
>>>                 * Enable 1.8V Signal Enable in the Host Control2
>>>                 * register
>>>
>>

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

* Re: [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
  2016-04-27 20:26         ` Adrian Hunter
@ 2016-04-28  3:09           ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-28  3:09 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
> >Hi Adrian,
> >
> >Thanks for the review first.
> >
> >On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> >>On 15/04/16 20:29, Dong Aisheng wrote:
> >>>Handle host and regulator signal voltage switch separately.
> >>>Move host signal voltage switch code into a separated function
> >>>sdhci_do_signal_voltage_switch() first, the following patches will
> >>>remove the regulator voltage switch code and use the common
> >>>mmc_regulator_set_vqmmc() instead.
> >>
> >>You have changed the order that things are done.
> >
> >Yes, the oder changes a bit that we always do controller voltage switch first.
> >I suppose the order is irrelevant here since i don't recall any
> >requirement from card.
> >
> >Actually the original order is also a bit mass.
> >e.g.
> >For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
> >But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
> >It looks to us the original one also order irrelevant.
> >
> >>There is no way to know
> >>what that will break, so let's not do that.  What about just changing
> >>regulator_set_voltage() to mmc_regulator_set_vqmmc()?
> >>
> >
> >Currently what i can think out VIO switch using are three cases: (Pls
> >help add if any)
> >1) Both host IO and card IO use external vqmmc to do switch
> >(e.g eMMC 1.8V DDR/HS200/HS400 mode)
> >
> >eMMC has no IO voltage switch protocol and requirement, so usually
> >board designed
> >using fixed 1.8V for eMMC and host IO.
> >Event it's switchable, it should be done in the first mmc_power_up().
> >Dynamical switch later may cause eMMC unable to work properly.
> >(We have been confirmed about this issue by many eMMC vendors
> >like Micron and Sandisk. I'm not sure if any exceptions in the community
> >still doing VIO dynamical switch for eMMC, if yes, please help share
> >the experience!).
> >
> >Event some people still do dynamical IO switch for eMMC, since eMMC
> >spec has no requirement, so the order should also not care.
> >
> >2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
> >
> >SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
> >regulator to do card IO voltage switch. It does not use external vqmmc
> >regulator.
> >So order irrelevant too.
> >
> >3) Host using controller IO switch while card using external vqmmc
> >(special SDIO3.0 or eMMC)
> >I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
> >the spec and using external regulator for card IO voltage.
> >Usually it's required to fix to 1.8v and also not order irrelevant.
> >
> >For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
> >
> >So it looks all cases seems are not order required.
> 
> I don't agree that there is any way to know that other host controllers
> are not affected.  I don't want a repeat of sdhci_set_power().
> 

Can you share some more info about sdhci_set_power() issue?
I'd like to see if we are same the issue.

BTW, IMHO i don't think we should stop keep moving only afraid of potential
break if it's correct way. Because .start_signal_voltage_switch() interface
seems shouldn't be order dependant.
If it is, then it should be fixed and handled in high layer like MMC core
rather than in host driver. Right?

> Please instead send a patch for just using mmc_regulator_set_vqmmc()
> in place of regulator_set_voltage().

Just using mmc_regulator_set_vqmmc() also changes the order which
is the same situation.

Regards
Dong Aisheng

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

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

* [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
@ 2016-04-28  3:09           ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-28  3:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
> >Hi Adrian,
> >
> >Thanks for the review first.
> >
> >On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> >>On 15/04/16 20:29, Dong Aisheng wrote:
> >>>Handle host and regulator signal voltage switch separately.
> >>>Move host signal voltage switch code into a separated function
> >>>sdhci_do_signal_voltage_switch() first, the following patches will
> >>>remove the regulator voltage switch code and use the common
> >>>mmc_regulator_set_vqmmc() instead.
> >>
> >>You have changed the order that things are done.
> >
> >Yes, the oder changes a bit that we always do controller voltage switch first.
> >I suppose the order is irrelevant here since i don't recall any
> >requirement from card.
> >
> >Actually the original order is also a bit mass.
> >e.g.
> >For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
> >But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
> >It looks to us the original one also order irrelevant.
> >
> >>There is no way to know
> >>what that will break, so let's not do that.  What about just changing
> >>regulator_set_voltage() to mmc_regulator_set_vqmmc()?
> >>
> >
> >Currently what i can think out VIO switch using are three cases: (Pls
> >help add if any)
> >1) Both host IO and card IO use external vqmmc to do switch
> >(e.g eMMC 1.8V DDR/HS200/HS400 mode)
> >
> >eMMC has no IO voltage switch protocol and requirement, so usually
> >board designed
> >using fixed 1.8V for eMMC and host IO.
> >Event it's switchable, it should be done in the first mmc_power_up().
> >Dynamical switch later may cause eMMC unable to work properly.
> >(We have been confirmed about this issue by many eMMC vendors
> >like Micron and Sandisk. I'm not sure if any exceptions in the community
> >still doing VIO dynamical switch for eMMC, if yes, please help share
> >the experience!).
> >
> >Event some people still do dynamical IO switch for eMMC, since eMMC
> >spec has no requirement, so the order should also not care.
> >
> >2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
> >
> >SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
> >regulator to do card IO voltage switch. It does not use external vqmmc
> >regulator.
> >So order irrelevant too.
> >
> >3) Host using controller IO switch while card using external vqmmc
> >(special SDIO3.0 or eMMC)
> >I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
> >the spec and using external regulator for card IO voltage.
> >Usually it's required to fix to 1.8v and also not order irrelevant.
> >
> >For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
> >
> >So it looks all cases seems are not order required.
> 
> I don't agree that there is any way to know that other host controllers
> are not affected.  I don't want a repeat of sdhci_set_power().
> 

Can you share some more info about sdhci_set_power() issue?
I'd like to see if we are same the issue.

BTW, IMHO i don't think we should stop keep moving only afraid of potential
break if it's correct way. Because .start_signal_voltage_switch() interface
seems shouldn't be order dependant.
If it is, then it should be fixed and handled in high layer like MMC core
rather than in host driver. Right?

> Please instead send a patch for just using mmc_regulator_set_vqmmc()
> in place of regulator_set_voltage().

Just using mmc_regulator_set_vqmmc() also changes the order which
is the same situation.

Regards
Dong Aisheng

> --
> 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

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

* Re: [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
  2016-04-28  3:09           ` Dong Aisheng
@ 2016-04-28  6:39             ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-28  6:39 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On 28/04/16 06:09, Dong Aisheng wrote:
> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
>>> Hi Adrian,
>>>
>>> Thanks for the review first.
>>>
>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>>> Handle host and regulator signal voltage switch separately.
>>>>> Move host signal voltage switch code into a separated function
>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
>>>>> remove the regulator voltage switch code and use the common
>>>>> mmc_regulator_set_vqmmc() instead.
>>>>
>>>> You have changed the order that things are done.
>>>
>>> Yes, the oder changes a bit that we always do controller voltage switch first.
>>> I suppose the order is irrelevant here since i don't recall any
>>> requirement from card.
>>>
>>> Actually the original order is also a bit mass.
>>> e.g.
>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
>>> It looks to us the original one also order irrelevant.
>>>
>>>> There is no way to know
>>>> what that will break, so let's not do that.  What about just changing
>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
>>>>
>>>
>>> Currently what i can think out VIO switch using are three cases: (Pls
>>> help add if any)
>>> 1) Both host IO and card IO use external vqmmc to do switch
>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
>>>
>>> eMMC has no IO voltage switch protocol and requirement, so usually
>>> board designed
>>> using fixed 1.8V for eMMC and host IO.
>>> Event it's switchable, it should be done in the first mmc_power_up().
>>> Dynamical switch later may cause eMMC unable to work properly.
>>> (We have been confirmed about this issue by many eMMC vendors
>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
>>> still doing VIO dynamical switch for eMMC, if yes, please help share
>>> the experience!).
>>>
>>> Event some people still do dynamical IO switch for eMMC, since eMMC
>>> spec has no requirement, so the order should also not care.
>>>
>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
>>>
>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
>>> regulator to do card IO voltage switch. It does not use external vqmmc
>>> regulator.
>>> So order irrelevant too.
>>>
>>> 3) Host using controller IO switch while card using external vqmmc
>>> (special SDIO3.0 or eMMC)
>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
>>> the spec and using external regulator for card IO voltage.
>>> Usually it's required to fix to 1.8v and also not order irrelevant.
>>>
>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
>>>
>>> So it looks all cases seems are not order required.
>>
>> I don't agree that there is any way to know that other host controllers
>> are not affected.  I don't want a repeat of sdhci_set_power().
>>
> 
> Can you share some more info about sdhci_set_power() issue?
> I'd like to see if we are same the issue.

Not the same issue, but the same concept.  People changing the code under
the impression that their way was correct, and then breaking other people's
drivers.  Check the git history and mailing list.

	http://marc.info/?l=linux-mmc&m=145880454106474&w=2

> 
> BTW, IMHO i don't think we should stop keep moving only afraid of potential
> break if it's correct way. Because .start_signal_voltage_switch() interface
> seems shouldn't be order dependant.
> If it is, then it should be fixed and handled in high layer like MMC core
> rather than in host driver. Right?

The SDHCI spec. does not define how to use external regulators, so there is
no "correct way".

We have to move forward *and* avoid potential breakage.

In this case it seems me that the risk of breakage outweighs the value of
prettier code.

By the way, there are ways to get rid of the ugliness - such as pushing it down
into individual drivers.

> 
>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
>> in place of regulator_set_voltage().
> 
> Just using mmc_regulator_set_vqmmc() also changes the order which
> is the same situation.

How so?  It looks like a drop-in replacement to me:

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 94cffa77490a..69b4d48aff87 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
 		if (!IS_ERR(mmc->supply.vqmmc)) {
-			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
-						    3600000);
+			ret = mmc_regulator_set_vqmmc(mmc, ios);
 			if (ret) {
 				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
 					mmc_hostname(mmc));
@@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
 		return -EAGAIN;
 	case MMC_SIGNAL_VOLTAGE_180:
 		if (!IS_ERR(mmc->supply.vqmmc)) {
-			ret = regulator_set_voltage(mmc->supply.vqmmc,
-					1700000, 1950000);
+			ret = mmc_regulator_set_vqmmc(mmc, ios);
 			if (ret) {
 				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
 					mmc_hostname(mmc));
@@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
 		return -EAGAIN;
 	case MMC_SIGNAL_VOLTAGE_120:
 		if (!IS_ERR(mmc->supply.vqmmc)) {
-			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
-						    1300000);
+			ret = mmc_regulator_set_vqmmc(mmc, ios);
 			if (ret) {
 				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
 					mmc_hostname(mmc));




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

* [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
@ 2016-04-28  6:39             ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-28  6:39 UTC (permalink / raw)
  To: linux-arm-kernel

On 28/04/16 06:09, Dong Aisheng wrote:
> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
>>> Hi Adrian,
>>>
>>> Thanks for the review first.
>>>
>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>>> Handle host and regulator signal voltage switch separately.
>>>>> Move host signal voltage switch code into a separated function
>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
>>>>> remove the regulator voltage switch code and use the common
>>>>> mmc_regulator_set_vqmmc() instead.
>>>>
>>>> You have changed the order that things are done.
>>>
>>> Yes, the oder changes a bit that we always do controller voltage switch first.
>>> I suppose the order is irrelevant here since i don't recall any
>>> requirement from card.
>>>
>>> Actually the original order is also a bit mass.
>>> e.g.
>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
>>> It looks to us the original one also order irrelevant.
>>>
>>>> There is no way to know
>>>> what that will break, so let's not do that.  What about just changing
>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
>>>>
>>>
>>> Currently what i can think out VIO switch using are three cases: (Pls
>>> help add if any)
>>> 1) Both host IO and card IO use external vqmmc to do switch
>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
>>>
>>> eMMC has no IO voltage switch protocol and requirement, so usually
>>> board designed
>>> using fixed 1.8V for eMMC and host IO.
>>> Event it's switchable, it should be done in the first mmc_power_up().
>>> Dynamical switch later may cause eMMC unable to work properly.
>>> (We have been confirmed about this issue by many eMMC vendors
>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
>>> still doing VIO dynamical switch for eMMC, if yes, please help share
>>> the experience!).
>>>
>>> Event some people still do dynamical IO switch for eMMC, since eMMC
>>> spec has no requirement, so the order should also not care.
>>>
>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
>>>
>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
>>> regulator to do card IO voltage switch. It does not use external vqmmc
>>> regulator.
>>> So order irrelevant too.
>>>
>>> 3) Host using controller IO switch while card using external vqmmc
>>> (special SDIO3.0 or eMMC)
>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
>>> the spec and using external regulator for card IO voltage.
>>> Usually it's required to fix to 1.8v and also not order irrelevant.
>>>
>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
>>>
>>> So it looks all cases seems are not order required.
>>
>> I don't agree that there is any way to know that other host controllers
>> are not affected.  I don't want a repeat of sdhci_set_power().
>>
> 
> Can you share some more info about sdhci_set_power() issue?
> I'd like to see if we are same the issue.

Not the same issue, but the same concept.  People changing the code under
the impression that their way was correct, and then breaking other people's
drivers.  Check the git history and mailing list.

	http://marc.info/?l=linux-mmc&m=145880454106474&w=2

> 
> BTW, IMHO i don't think we should stop keep moving only afraid of potential
> break if it's correct way. Because .start_signal_voltage_switch() interface
> seems shouldn't be order dependant.
> If it is, then it should be fixed and handled in high layer like MMC core
> rather than in host driver. Right?

The SDHCI spec. does not define how to use external regulators, so there is
no "correct way".

We have to move forward *and* avoid potential breakage.

In this case it seems me that the risk of breakage outweighs the value of
prettier code.

By the way, there are ways to get rid of the ugliness - such as pushing it down
into individual drivers.

> 
>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
>> in place of regulator_set_voltage().
> 
> Just using mmc_regulator_set_vqmmc() also changes the order which
> is the same situation.

How so?  It looks like a drop-in replacement to me:

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 94cffa77490a..69b4d48aff87 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
 		if (!IS_ERR(mmc->supply.vqmmc)) {
-			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
-						    3600000);
+			ret = mmc_regulator_set_vqmmc(mmc, ios);
 			if (ret) {
 				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
 					mmc_hostname(mmc));
@@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
 		return -EAGAIN;
 	case MMC_SIGNAL_VOLTAGE_180:
 		if (!IS_ERR(mmc->supply.vqmmc)) {
-			ret = regulator_set_voltage(mmc->supply.vqmmc,
-					1700000, 1950000);
+			ret = mmc_regulator_set_vqmmc(mmc, ios);
 			if (ret) {
 				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
 					mmc_hostname(mmc));
@@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
 		return -EAGAIN;
 	case MMC_SIGNAL_VOLTAGE_120:
 		if (!IS_ERR(mmc->supply.vqmmc)) {
-			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
-						    1300000);
+			ret = mmc_regulator_set_vqmmc(mmc, ios);
 			if (ret) {
 				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
 					mmc_hostname(mmc));

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

* Re: [PATCH 10/23] mmc: core: disable auto retune during card detection process
  2016-04-24 10:47       ` Dong Aisheng
@ 2016-04-28  7:04         ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-28  7:04 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On 24/04/16 13:47, Dong Aisheng wrote:
> On Fri, Apr 22, 2016 at 8:48 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>> On 15/04/16 20:29, Dong Aisheng wrote:
>>> During card detection process, mmc core may sends commands
>>> to detect if card is still exist in mmc_rescan for removable
>>> card which may trigger mmc retuning process after a bit time
>>> of runtime pm suspend.
>>> Obviously this retuning process is meaningless for card remove
>>> case, so we disable mmc_retune in mmc_detect_change() for it.
>>> For card insert case, the mmc_retune will be enabled normally
>>> in its card initialization process later in mmc_execute_tuning().
>>> So disable it at first has no side effection.
>>
>> We don't assume that the card has been removed, which is why we send
>> commands to find out if it is still there.  If it is still there, this
>> change will have incorrectly disabled re-tuning.
>>
> 
> Do you mean the 'fake' card remove interrupt like caused by glitch?

Sure

> Yes, if that the card is still exist and re-tuning is wrongly disabled.
> 
> So we could re-enable re-tuning for this special case?
> Something like:
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index 41b1e76..e1990a8 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -2607,6 +2607,8 @@ void mmc_rescan(struct work_struct *work)
> 
>         /* if there still is a card present, stop here */
>         if (host->bus_ops != NULL) {
> +               if (tuning_is_enabled_before())
> +                       mmc_retune_enable(host);
>                 mmc_bus_put(host);
>                 goto out;
>         }
> 
> 
>> Do you have an actual problem with the way it works now?
>>
> 
> No actual problems now.

So let's not spend time on it.

> I just observe a lot tuning commands keep sending although the card is already
> removed which seems a bit meaningless.
> And most tuning execution process is executed with sin_lock_irqsave, i'm not
> sure if the mass tuning commands may affect the system when CPU is busy.
> What do you think?

sdhci spin lock is unlocked while waiting for tuning commands.

> 
> Regards
> Dong Aisheng
> 
>>>
>>> CC: stable <stable@vger.kernel.org>
>>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>>> ---
>>>  drivers/mmc/core/core.c | 1 +
>>>  1 file changed, 1 insertion(+)
>>>
>>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
>>> index 52bfaf0..76d0802 100644
>>> --- a/drivers/mmc/core/core.c
>>> +++ b/drivers/mmc/core/core.c
>>> @@ -1888,6 +1888,7 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
>>>               pm_wakeup_event(mmc_dev(host), 5000);
>>>
>>>       host->detect_change = 1;
>>> +     mmc_retune_disable(host);
>>>       mmc_schedule_delayed_work(&host->detect, delay);
>>>  }
>>>
>>>
>>
> 


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

* [PATCH 10/23] mmc: core: disable auto retune during card detection process
@ 2016-04-28  7:04         ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-28  7:04 UTC (permalink / raw)
  To: linux-arm-kernel

On 24/04/16 13:47, Dong Aisheng wrote:
> On Fri, Apr 22, 2016 at 8:48 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>> On 15/04/16 20:29, Dong Aisheng wrote:
>>> During card detection process, mmc core may sends commands
>>> to detect if card is still exist in mmc_rescan for removable
>>> card which may trigger mmc retuning process after a bit time
>>> of runtime pm suspend.
>>> Obviously this retuning process is meaningless for card remove
>>> case, so we disable mmc_retune in mmc_detect_change() for it.
>>> For card insert case, the mmc_retune will be enabled normally
>>> in its card initialization process later in mmc_execute_tuning().
>>> So disable it at first has no side effection.
>>
>> We don't assume that the card has been removed, which is why we send
>> commands to find out if it is still there.  If it is still there, this
>> change will have incorrectly disabled re-tuning.
>>
> 
> Do you mean the 'fake' card remove interrupt like caused by glitch?

Sure

> Yes, if that the card is still exist and re-tuning is wrongly disabled.
> 
> So we could re-enable re-tuning for this special case?
> Something like:
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index 41b1e76..e1990a8 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -2607,6 +2607,8 @@ void mmc_rescan(struct work_struct *work)
> 
>         /* if there still is a card present, stop here */
>         if (host->bus_ops != NULL) {
> +               if (tuning_is_enabled_before())
> +                       mmc_retune_enable(host);
>                 mmc_bus_put(host);
>                 goto out;
>         }
> 
> 
>> Do you have an actual problem with the way it works now?
>>
> 
> No actual problems now.

So let's not spend time on it.

> I just observe a lot tuning commands keep sending although the card is already
> removed which seems a bit meaningless.
> And most tuning execution process is executed with sin_lock_irqsave, i'm not
> sure if the mass tuning commands may affect the system when CPU is busy.
> What do you think?

sdhci spin lock is unlocked while waiting for tuning commands.

> 
> Regards
> Dong Aisheng
> 
>>>
>>> CC: stable <stable@vger.kernel.org>
>>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>>> ---
>>>  drivers/mmc/core/core.c | 1 +
>>>  1 file changed, 1 insertion(+)
>>>
>>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
>>> index 52bfaf0..76d0802 100644
>>> --- a/drivers/mmc/core/core.c
>>> +++ b/drivers/mmc/core/core.c
>>> @@ -1888,6 +1888,7 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
>>>               pm_wakeup_event(mmc_dev(host), 5000);
>>>
>>>       host->detect_change = 1;
>>> +     mmc_retune_disable(host);
>>>       mmc_schedule_delayed_work(&host->detect, delay);
>>>  }
>>>
>>>
>>
> 

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

* Re: [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
  2016-04-28  6:39             ` Adrian Hunter
@ 2016-04-28  7:15               ` Jaehoon Chung
  -1 siblings, 0 replies; 170+ messages in thread
From: Jaehoon Chung @ 2016-04-28  7:15 UTC (permalink / raw)
  To: Adrian Hunter, Dong Aisheng
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen, CPGS

Hi Adrian,

On 04/28/2016 03:39 PM, Adrian Hunter wrote:
> On 28/04/16 06:09, Dong Aisheng wrote:
>> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
>>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
>>>> Hi Adrian,
>>>>
>>>> Thanks for the review first.
>>>>
>>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>>>> Handle host and regulator signal voltage switch separately.
>>>>>> Move host signal voltage switch code into a separated function
>>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
>>>>>> remove the regulator voltage switch code and use the common
>>>>>> mmc_regulator_set_vqmmc() instead.
>>>>>
>>>>> You have changed the order that things are done.
>>>>
>>>> Yes, the oder changes a bit that we always do controller voltage switch first.
>>>> I suppose the order is irrelevant here since i don't recall any
>>>> requirement from card.
>>>>
>>>> Actually the original order is also a bit mass.
>>>> e.g.
>>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
>>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
>>>> It looks to us the original one also order irrelevant.
>>>>
>>>>> There is no way to know
>>>>> what that will break, so let's not do that.  What about just changing
>>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
>>>>>
>>>>
>>>> Currently what i can think out VIO switch using are three cases: (Pls
>>>> help add if any)
>>>> 1) Both host IO and card IO use external vqmmc to do switch
>>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
>>>>
>>>> eMMC has no IO voltage switch protocol and requirement, so usually
>>>> board designed
>>>> using fixed 1.8V for eMMC and host IO.
>>>> Event it's switchable, it should be done in the first mmc_power_up().
>>>> Dynamical switch later may cause eMMC unable to work properly.
>>>> (We have been confirmed about this issue by many eMMC vendors
>>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
>>>> still doing VIO dynamical switch for eMMC, if yes, please help share
>>>> the experience!).
>>>>
>>>> Event some people still do dynamical IO switch for eMMC, since eMMC
>>>> spec has no requirement, so the order should also not care.
>>>>
>>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
>>>>
>>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
>>>> regulator to do card IO voltage switch. It does not use external vqmmc
>>>> regulator.
>>>> So order irrelevant too.
>>>>
>>>> 3) Host using controller IO switch while card using external vqmmc
>>>> (special SDIO3.0 or eMMC)
>>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
>>>> the spec and using external regulator for card IO voltage.
>>>> Usually it's required to fix to 1.8v and also not order irrelevant.
>>>>
>>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
>>>>
>>>> So it looks all cases seems are not order required.
>>>
>>> I don't agree that there is any way to know that other host controllers
>>> are not affected.  I don't want a repeat of sdhci_set_power().
>>>
>>
>> Can you share some more info about sdhci_set_power() issue?
>> I'd like to see if we are same the issue.
> 
> Not the same issue, but the same concept.  People changing the code under
> the impression that their way was correct, and then breaking other people's
> drivers.  Check the git history and mailing list.
> 
> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
> 
>>
>> BTW, IMHO i don't think we should stop keep moving only afraid of potential
>> break if it's correct way. Because .start_signal_voltage_switch() interface
>> seems shouldn't be order dependant.
>> If it is, then it should be fixed and handled in high layer like MMC core
>> rather than in host driver. Right?
> 
> The SDHCI spec. does not define how to use external regulators, so there is
> no "correct way".
> 
> We have to move forward *and* avoid potential breakage.
> 
> In this case it seems me that the risk of breakage outweighs the value of
> prettier code.
> 
> By the way, there are ways to get rid of the ugliness - such as pushing it down
> into individual drivers.
> 
>>
>>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
>>> in place of regulator_set_voltage().
>>
>> Just using mmc_regulator_set_vqmmc() also changes the order which
>> is the same situation.
> 
> How so?  It looks like a drop-in replacement to me:

maybe.. this question should not be related with this discussion..
But i have one question..sdhci_do_start_signal_voltage_switch() returned 0 or EAGAIN, when IS_ERR(mmc->supply.vqmmc) is ture.
It there any problem?

I'm also checking on core side. but just wondering this.
(Because i'm fixing dwmmc controller for this.)

Best Regards,
Jaehoon Chung

> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 94cffa77490a..69b4d48aff87 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>  
>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
> -						    3600000);
> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>  			if (ret) {
>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>  					mmc_hostname(mmc));
> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>  		return -EAGAIN;
>  	case MMC_SIGNAL_VOLTAGE_180:
>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
> -					1700000, 1950000);
> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>  			if (ret) {
>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>  					mmc_hostname(mmc));
> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>  		return -EAGAIN;
>  	case MMC_SIGNAL_VOLTAGE_120:
>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
> -						    1300000);
> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>  			if (ret) {
>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>  					mmc_hostname(mmc));
> 
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 


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

* [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
@ 2016-04-28  7:15               ` Jaehoon Chung
  0 siblings, 0 replies; 170+ messages in thread
From: Jaehoon Chung @ 2016-04-28  7:15 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Adrian,

On 04/28/2016 03:39 PM, Adrian Hunter wrote:
> On 28/04/16 06:09, Dong Aisheng wrote:
>> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
>>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
>>>> Hi Adrian,
>>>>
>>>> Thanks for the review first.
>>>>
>>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>>>> Handle host and regulator signal voltage switch separately.
>>>>>> Move host signal voltage switch code into a separated function
>>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
>>>>>> remove the regulator voltage switch code and use the common
>>>>>> mmc_regulator_set_vqmmc() instead.
>>>>>
>>>>> You have changed the order that things are done.
>>>>
>>>> Yes, the oder changes a bit that we always do controller voltage switch first.
>>>> I suppose the order is irrelevant here since i don't recall any
>>>> requirement from card.
>>>>
>>>> Actually the original order is also a bit mass.
>>>> e.g.
>>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
>>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
>>>> It looks to us the original one also order irrelevant.
>>>>
>>>>> There is no way to know
>>>>> what that will break, so let's not do that.  What about just changing
>>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
>>>>>
>>>>
>>>> Currently what i can think out VIO switch using are three cases: (Pls
>>>> help add if any)
>>>> 1) Both host IO and card IO use external vqmmc to do switch
>>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
>>>>
>>>> eMMC has no IO voltage switch protocol and requirement, so usually
>>>> board designed
>>>> using fixed 1.8V for eMMC and host IO.
>>>> Event it's switchable, it should be done in the first mmc_power_up().
>>>> Dynamical switch later may cause eMMC unable to work properly.
>>>> (We have been confirmed about this issue by many eMMC vendors
>>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
>>>> still doing VIO dynamical switch for eMMC, if yes, please help share
>>>> the experience!).
>>>>
>>>> Event some people still do dynamical IO switch for eMMC, since eMMC
>>>> spec has no requirement, so the order should also not care.
>>>>
>>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
>>>>
>>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
>>>> regulator to do card IO voltage switch. It does not use external vqmmc
>>>> regulator.
>>>> So order irrelevant too.
>>>>
>>>> 3) Host using controller IO switch while card using external vqmmc
>>>> (special SDIO3.0 or eMMC)
>>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
>>>> the spec and using external regulator for card IO voltage.
>>>> Usually it's required to fix to 1.8v and also not order irrelevant.
>>>>
>>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
>>>>
>>>> So it looks all cases seems are not order required.
>>>
>>> I don't agree that there is any way to know that other host controllers
>>> are not affected.  I don't want a repeat of sdhci_set_power().
>>>
>>
>> Can you share some more info about sdhci_set_power() issue?
>> I'd like to see if we are same the issue.
> 
> Not the same issue, but the same concept.  People changing the code under
> the impression that their way was correct, and then breaking other people's
> drivers.  Check the git history and mailing list.
> 
> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
> 
>>
>> BTW, IMHO i don't think we should stop keep moving only afraid of potential
>> break if it's correct way. Because .start_signal_voltage_switch() interface
>> seems shouldn't be order dependant.
>> If it is, then it should be fixed and handled in high layer like MMC core
>> rather than in host driver. Right?
> 
> The SDHCI spec. does not define how to use external regulators, so there is
> no "correct way".
> 
> We have to move forward *and* avoid potential breakage.
> 
> In this case it seems me that the risk of breakage outweighs the value of
> prettier code.
> 
> By the way, there are ways to get rid of the ugliness - such as pushing it down
> into individual drivers.
> 
>>
>>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
>>> in place of regulator_set_voltage().
>>
>> Just using mmc_regulator_set_vqmmc() also changes the order which
>> is the same situation.
> 
> How so?  It looks like a drop-in replacement to me:

maybe.. this question should not be related with this discussion..
But i have one question..sdhci_do_start_signal_voltage_switch() returned 0 or EAGAIN, when IS_ERR(mmc->supply.vqmmc) is ture.
It there any problem?

I'm also checking on core side. but just wondering this.
(Because i'm fixing dwmmc controller for this.)

Best Regards,
Jaehoon Chung

> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 94cffa77490a..69b4d48aff87 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>  
>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
> -						    3600000);
> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>  			if (ret) {
>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>  					mmc_hostname(mmc));
> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>  		return -EAGAIN;
>  	case MMC_SIGNAL_VOLTAGE_180:
>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
> -					1700000, 1950000);
> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>  			if (ret) {
>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>  					mmc_hostname(mmc));
> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>  		return -EAGAIN;
>  	case MMC_SIGNAL_VOLTAGE_120:
>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
> -						    1300000);
> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>  			if (ret) {
>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>  					mmc_hostname(mmc));
> 
> 
> 
> --
> 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
> 
> 

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

* Re: [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
  2016-04-28  7:15               ` Jaehoon Chung
@ 2016-04-28  7:44                 ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-28  7:44 UTC (permalink / raw)
  To: Jaehoon Chung, Dong Aisheng
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen, CPGS

On 28/04/16 10:15, Jaehoon Chung wrote:
> Hi Adrian,
> 
> On 04/28/2016 03:39 PM, Adrian Hunter wrote:
>> On 28/04/16 06:09, Dong Aisheng wrote:
>>> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
>>>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
>>>>> Hi Adrian,
>>>>>
>>>>> Thanks for the review first.
>>>>>
>>>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>>>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>>>>> Handle host and regulator signal voltage switch separately.
>>>>>>> Move host signal voltage switch code into a separated function
>>>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
>>>>>>> remove the regulator voltage switch code and use the common
>>>>>>> mmc_regulator_set_vqmmc() instead.
>>>>>>
>>>>>> You have changed the order that things are done.
>>>>>
>>>>> Yes, the oder changes a bit that we always do controller voltage switch first.
>>>>> I suppose the order is irrelevant here since i don't recall any
>>>>> requirement from card.
>>>>>
>>>>> Actually the original order is also a bit mass.
>>>>> e.g.
>>>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
>>>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
>>>>> It looks to us the original one also order irrelevant.
>>>>>
>>>>>> There is no way to know
>>>>>> what that will break, so let's not do that.  What about just changing
>>>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
>>>>>>
>>>>>
>>>>> Currently what i can think out VIO switch using are three cases: (Pls
>>>>> help add if any)
>>>>> 1) Both host IO and card IO use external vqmmc to do switch
>>>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
>>>>>
>>>>> eMMC has no IO voltage switch protocol and requirement, so usually
>>>>> board designed
>>>>> using fixed 1.8V for eMMC and host IO.
>>>>> Event it's switchable, it should be done in the first mmc_power_up().
>>>>> Dynamical switch later may cause eMMC unable to work properly.
>>>>> (We have been confirmed about this issue by many eMMC vendors
>>>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
>>>>> still doing VIO dynamical switch for eMMC, if yes, please help share
>>>>> the experience!).
>>>>>
>>>>> Event some people still do dynamical IO switch for eMMC, since eMMC
>>>>> spec has no requirement, so the order should also not care.
>>>>>
>>>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
>>>>>
>>>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
>>>>> regulator to do card IO voltage switch. It does not use external vqmmc
>>>>> regulator.
>>>>> So order irrelevant too.
>>>>>
>>>>> 3) Host using controller IO switch while card using external vqmmc
>>>>> (special SDIO3.0 or eMMC)
>>>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
>>>>> the spec and using external regulator for card IO voltage.
>>>>> Usually it's required to fix to 1.8v and also not order irrelevant.
>>>>>
>>>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
>>>>>
>>>>> So it looks all cases seems are not order required.
>>>>
>>>> I don't agree that there is any way to know that other host controllers
>>>> are not affected.  I don't want a repeat of sdhci_set_power().
>>>>
>>>
>>> Can you share some more info about sdhci_set_power() issue?
>>> I'd like to see if we are same the issue.
>>
>> Not the same issue, but the same concept.  People changing the code under
>> the impression that their way was correct, and then breaking other people's
>> drivers.  Check the git history and mailing list.
>>
>> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
>>
>>>
>>> BTW, IMHO i don't think we should stop keep moving only afraid of potential
>>> break if it's correct way. Because .start_signal_voltage_switch() interface
>>> seems shouldn't be order dependant.
>>> If it is, then it should be fixed and handled in high layer like MMC core
>>> rather than in host driver. Right?
>>
>> The SDHCI spec. does not define how to use external regulators, so there is
>> no "correct way".
>>
>> We have to move forward *and* avoid potential breakage.
>>
>> In this case it seems me that the risk of breakage outweighs the value of
>> prettier code.
>>
>> By the way, there are ways to get rid of the ugliness - such as pushing it down
>> into individual drivers.
>>
>>>
>>>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
>>>> in place of regulator_set_voltage().
>>>
>>> Just using mmc_regulator_set_vqmmc() also changes the order which
>>> is the same situation.
>>
>> How so?  It looks like a drop-in replacement to me:
> 
> maybe.. this question should not be related with this discussion..
> But i have one question..sdhci_do_start_signal_voltage_switch() returned 0 or EAGAIN, when IS_ERR(mmc->supply.vqmmc) is ture.
> It there any problem?

Not that I am aware of.

> 
> I'm also checking on core side. but just wondering this.
> (Because i'm fixing dwmmc controller for this.)

What is the problem?

> 
> Best Regards,
> Jaehoon Chung
> 
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 94cffa77490a..69b4d48aff87 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>  
>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
>> -						    3600000);
>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>  			if (ret) {
>>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>>  					mmc_hostname(mmc));
>> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>  		return -EAGAIN;
>>  	case MMC_SIGNAL_VOLTAGE_180:
>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
>> -					1700000, 1950000);
>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>  			if (ret) {
>>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>>  					mmc_hostname(mmc));
>> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>  		return -EAGAIN;
>>  	case MMC_SIGNAL_VOLTAGE_120:
>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
>> -						    1300000);
>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>  			if (ret) {
>>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>>  					mmc_hostname(mmc));
>>
>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>>
> 
> 


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

* [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
@ 2016-04-28  7:44                 ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-28  7:44 UTC (permalink / raw)
  To: linux-arm-kernel

On 28/04/16 10:15, Jaehoon Chung wrote:
> Hi Adrian,
> 
> On 04/28/2016 03:39 PM, Adrian Hunter wrote:
>> On 28/04/16 06:09, Dong Aisheng wrote:
>>> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
>>>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
>>>>> Hi Adrian,
>>>>>
>>>>> Thanks for the review first.
>>>>>
>>>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>>>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>>>>> Handle host and regulator signal voltage switch separately.
>>>>>>> Move host signal voltage switch code into a separated function
>>>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
>>>>>>> remove the regulator voltage switch code and use the common
>>>>>>> mmc_regulator_set_vqmmc() instead.
>>>>>>
>>>>>> You have changed the order that things are done.
>>>>>
>>>>> Yes, the oder changes a bit that we always do controller voltage switch first.
>>>>> I suppose the order is irrelevant here since i don't recall any
>>>>> requirement from card.
>>>>>
>>>>> Actually the original order is also a bit mass.
>>>>> e.g.
>>>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
>>>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
>>>>> It looks to us the original one also order irrelevant.
>>>>>
>>>>>> There is no way to know
>>>>>> what that will break, so let's not do that.  What about just changing
>>>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
>>>>>>
>>>>>
>>>>> Currently what i can think out VIO switch using are three cases: (Pls
>>>>> help add if any)
>>>>> 1) Both host IO and card IO use external vqmmc to do switch
>>>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
>>>>>
>>>>> eMMC has no IO voltage switch protocol and requirement, so usually
>>>>> board designed
>>>>> using fixed 1.8V for eMMC and host IO.
>>>>> Event it's switchable, it should be done in the first mmc_power_up().
>>>>> Dynamical switch later may cause eMMC unable to work properly.
>>>>> (We have been confirmed about this issue by many eMMC vendors
>>>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
>>>>> still doing VIO dynamical switch for eMMC, if yes, please help share
>>>>> the experience!).
>>>>>
>>>>> Event some people still do dynamical IO switch for eMMC, since eMMC
>>>>> spec has no requirement, so the order should also not care.
>>>>>
>>>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
>>>>>
>>>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
>>>>> regulator to do card IO voltage switch. It does not use external vqmmc
>>>>> regulator.
>>>>> So order irrelevant too.
>>>>>
>>>>> 3) Host using controller IO switch while card using external vqmmc
>>>>> (special SDIO3.0 or eMMC)
>>>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
>>>>> the spec and using external regulator for card IO voltage.
>>>>> Usually it's required to fix to 1.8v and also not order irrelevant.
>>>>>
>>>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
>>>>>
>>>>> So it looks all cases seems are not order required.
>>>>
>>>> I don't agree that there is any way to know that other host controllers
>>>> are not affected.  I don't want a repeat of sdhci_set_power().
>>>>
>>>
>>> Can you share some more info about sdhci_set_power() issue?
>>> I'd like to see if we are same the issue.
>>
>> Not the same issue, but the same concept.  People changing the code under
>> the impression that their way was correct, and then breaking other people's
>> drivers.  Check the git history and mailing list.
>>
>> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
>>
>>>
>>> BTW, IMHO i don't think we should stop keep moving only afraid of potential
>>> break if it's correct way. Because .start_signal_voltage_switch() interface
>>> seems shouldn't be order dependant.
>>> If it is, then it should be fixed and handled in high layer like MMC core
>>> rather than in host driver. Right?
>>
>> The SDHCI spec. does not define how to use external regulators, so there is
>> no "correct way".
>>
>> We have to move forward *and* avoid potential breakage.
>>
>> In this case it seems me that the risk of breakage outweighs the value of
>> prettier code.
>>
>> By the way, there are ways to get rid of the ugliness - such as pushing it down
>> into individual drivers.
>>
>>>
>>>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
>>>> in place of regulator_set_voltage().
>>>
>>> Just using mmc_regulator_set_vqmmc() also changes the order which
>>> is the same situation.
>>
>> How so?  It looks like a drop-in replacement to me:
> 
> maybe.. this question should not be related with this discussion..
> But i have one question..sdhci_do_start_signal_voltage_switch() returned 0 or EAGAIN, when IS_ERR(mmc->supply.vqmmc) is ture.
> It there any problem?

Not that I am aware of.

> 
> I'm also checking on core side. but just wondering this.
> (Because i'm fixing dwmmc controller for this.)

What is the problem?

> 
> Best Regards,
> Jaehoon Chung
> 
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 94cffa77490a..69b4d48aff87 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>  
>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
>> -						    3600000);
>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>  			if (ret) {
>>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>>  					mmc_hostname(mmc));
>> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>  		return -EAGAIN;
>>  	case MMC_SIGNAL_VOLTAGE_180:
>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
>> -					1700000, 1950000);
>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>  			if (ret) {
>>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>>  					mmc_hostname(mmc));
>> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>  		return -EAGAIN;
>>  	case MMC_SIGNAL_VOLTAGE_120:
>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
>> -						    1300000);
>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>  			if (ret) {
>>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>>  					mmc_hostname(mmc));
>>
>>
>>
>> --
>> 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
>>
>>
> 
> 

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

* Re: [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
  2016-04-28  7:44                 ` Adrian Hunter
@ 2016-04-28  8:30                   ` Jaehoon Chung
  -1 siblings, 0 replies; 170+ messages in thread
From: Jaehoon Chung @ 2016-04-28  8:30 UTC (permalink / raw)
  To: Adrian Hunter, Dong Aisheng
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen, CPGS

On 04/28/2016 04:44 PM, Adrian Hunter wrote:
> On 28/04/16 10:15, Jaehoon Chung wrote:
>> Hi Adrian,
>>
>> On 04/28/2016 03:39 PM, Adrian Hunter wrote:
>>> On 28/04/16 06:09, Dong Aisheng wrote:
>>>> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
>>>>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
>>>>>> Hi Adrian,
>>>>>>
>>>>>> Thanks for the review first.
>>>>>>
>>>>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>>>>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>>>>>> Handle host and regulator signal voltage switch separately.
>>>>>>>> Move host signal voltage switch code into a separated function
>>>>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
>>>>>>>> remove the regulator voltage switch code and use the common
>>>>>>>> mmc_regulator_set_vqmmc() instead.
>>>>>>>
>>>>>>> You have changed the order that things are done.
>>>>>>
>>>>>> Yes, the oder changes a bit that we always do controller voltage switch first.
>>>>>> I suppose the order is irrelevant here since i don't recall any
>>>>>> requirement from card.
>>>>>>
>>>>>> Actually the original order is also a bit mass.
>>>>>> e.g.
>>>>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
>>>>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
>>>>>> It looks to us the original one also order irrelevant.
>>>>>>
>>>>>>> There is no way to know
>>>>>>> what that will break, so let's not do that.  What about just changing
>>>>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
>>>>>>>
>>>>>>
>>>>>> Currently what i can think out VIO switch using are three cases: (Pls
>>>>>> help add if any)
>>>>>> 1) Both host IO and card IO use external vqmmc to do switch
>>>>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
>>>>>>
>>>>>> eMMC has no IO voltage switch protocol and requirement, so usually
>>>>>> board designed
>>>>>> using fixed 1.8V for eMMC and host IO.
>>>>>> Event it's switchable, it should be done in the first mmc_power_up().
>>>>>> Dynamical switch later may cause eMMC unable to work properly.
>>>>>> (We have been confirmed about this issue by many eMMC vendors
>>>>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
>>>>>> still doing VIO dynamical switch for eMMC, if yes, please help share
>>>>>> the experience!).
>>>>>>
>>>>>> Event some people still do dynamical IO switch for eMMC, since eMMC
>>>>>> spec has no requirement, so the order should also not care.
>>>>>>
>>>>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
>>>>>>
>>>>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
>>>>>> regulator to do card IO voltage switch. It does not use external vqmmc
>>>>>> regulator.
>>>>>> So order irrelevant too.
>>>>>>
>>>>>> 3) Host using controller IO switch while card using external vqmmc
>>>>>> (special SDIO3.0 or eMMC)
>>>>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
>>>>>> the spec and using external regulator for card IO voltage.
>>>>>> Usually it's required to fix to 1.8v and also not order irrelevant.
>>>>>>
>>>>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
>>>>>>
>>>>>> So it looks all cases seems are not order required.
>>>>>
>>>>> I don't agree that there is any way to know that other host controllers
>>>>> are not affected.  I don't want a repeat of sdhci_set_power().
>>>>>
>>>>
>>>> Can you share some more info about sdhci_set_power() issue?
>>>> I'd like to see if we are same the issue.
>>>
>>> Not the same issue, but the same concept.  People changing the code under
>>> the impression that their way was correct, and then breaking other people's
>>> drivers.  Check the git history and mailing list.
>>>
>>> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
>>>
>>>>
>>>> BTW, IMHO i don't think we should stop keep moving only afraid of potential
>>>> break if it's correct way. Because .start_signal_voltage_switch() interface
>>>> seems shouldn't be order dependant.
>>>> If it is, then it should be fixed and handled in high layer like MMC core
>>>> rather than in host driver. Right?
>>>
>>> The SDHCI spec. does not define how to use external regulators, so there is
>>> no "correct way".
>>>
>>> We have to move forward *and* avoid potential breakage.
>>>
>>> In this case it seems me that the risk of breakage outweighs the value of
>>> prettier code.
>>>
>>> By the way, there are ways to get rid of the ugliness - such as pushing it down
>>> into individual drivers.
>>>
>>>>
>>>>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
>>>>> in place of regulator_set_voltage().
>>>>
>>>> Just using mmc_regulator_set_vqmmc() also changes the order which
>>>> is the same situation.
>>>
>>> How so?  It looks like a drop-in replacement to me:
>>
>> maybe.. this question should not be related with this discussion..
>> But i have one question..sdhci_do_start_signal_voltage_switch() returned 0 or EAGAIN, when IS_ERR(mmc->supply.vqmmc) is ture.
>> It there any problem?
> 
> Not that I am aware of.
> 
>>
>> I'm also checking on core side. but just wondering this.
>> (Because i'm fixing dwmmc controller for this.)
> 
> What is the problem?

It should be difference with dwmmc controller.
if mmc->supply.vqmmc is not assigned, it didn't change the voltage..
(I'm not sure that HOST_CONTROL2 register can internally change the voltage..because i didn't have SDHC 3.0 spec.)

__mmc_set_signal_voltage()
-> host->ops->start_signal_voltage_switch()
-> host controller just set the bits for v1.8 or v3.3..(if vqmmc didn't use.)
	if return -EAGAIN or 0 , the bits that was set for v1.8 or v3.3 should be maintained.

And do mmc_power_cycle() -> mmc_power_off and mmc_set_initial_state()

But host controller didn't initialize.

That is dwmmc controller's side..

As my understanding, if voltage switch(UHS-I mode) is failed, it should be set to HS mode.
but dwmmc controller didn't work this case..so i will fix.
(Some parts are code bugs in dwmmc controller.)

I don't know sdhci is working fine or not..just wondering. :)

I'm going to analyze the sequence and other thing..so i may miss something.

Best Regards,
Jaehoon Chung

> 
>>
>> Best Regards,
>> Jaehoon Chung
>>
>>>
>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>> index 94cffa77490a..69b4d48aff87 100644
>>> --- a/drivers/mmc/host/sdhci.c
>>> +++ b/drivers/mmc/host/sdhci.c
>>> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>>  
>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
>>> -						    3600000);
>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>  			if (ret) {
>>>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>>>  					mmc_hostname(mmc));
>>> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>>  		return -EAGAIN;
>>>  	case MMC_SIGNAL_VOLTAGE_180:
>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
>>> -					1700000, 1950000);
>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>  			if (ret) {
>>>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>>>  					mmc_hostname(mmc));
>>> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>>  		return -EAGAIN;
>>>  	case MMC_SIGNAL_VOLTAGE_120:
>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
>>> -						    1300000);
>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>  			if (ret) {
>>>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>>>  					mmc_hostname(mmc));
>>>
>>>
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>
>>>
>>
>>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 


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

* [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
@ 2016-04-28  8:30                   ` Jaehoon Chung
  0 siblings, 0 replies; 170+ messages in thread
From: Jaehoon Chung @ 2016-04-28  8:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/28/2016 04:44 PM, Adrian Hunter wrote:
> On 28/04/16 10:15, Jaehoon Chung wrote:
>> Hi Adrian,
>>
>> On 04/28/2016 03:39 PM, Adrian Hunter wrote:
>>> On 28/04/16 06:09, Dong Aisheng wrote:
>>>> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
>>>>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
>>>>>> Hi Adrian,
>>>>>>
>>>>>> Thanks for the review first.
>>>>>>
>>>>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>>>>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>>>>>> Handle host and regulator signal voltage switch separately.
>>>>>>>> Move host signal voltage switch code into a separated function
>>>>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
>>>>>>>> remove the regulator voltage switch code and use the common
>>>>>>>> mmc_regulator_set_vqmmc() instead.
>>>>>>>
>>>>>>> You have changed the order that things are done.
>>>>>>
>>>>>> Yes, the oder changes a bit that we always do controller voltage switch first.
>>>>>> I suppose the order is irrelevant here since i don't recall any
>>>>>> requirement from card.
>>>>>>
>>>>>> Actually the original order is also a bit mass.
>>>>>> e.g.
>>>>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
>>>>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
>>>>>> It looks to us the original one also order irrelevant.
>>>>>>
>>>>>>> There is no way to know
>>>>>>> what that will break, so let's not do that.  What about just changing
>>>>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
>>>>>>>
>>>>>>
>>>>>> Currently what i can think out VIO switch using are three cases: (Pls
>>>>>> help add if any)
>>>>>> 1) Both host IO and card IO use external vqmmc to do switch
>>>>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
>>>>>>
>>>>>> eMMC has no IO voltage switch protocol and requirement, so usually
>>>>>> board designed
>>>>>> using fixed 1.8V for eMMC and host IO.
>>>>>> Event it's switchable, it should be done in the first mmc_power_up().
>>>>>> Dynamical switch later may cause eMMC unable to work properly.
>>>>>> (We have been confirmed about this issue by many eMMC vendors
>>>>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
>>>>>> still doing VIO dynamical switch for eMMC, if yes, please help share
>>>>>> the experience!).
>>>>>>
>>>>>> Event some people still do dynamical IO switch for eMMC, since eMMC
>>>>>> spec has no requirement, so the order should also not care.
>>>>>>
>>>>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
>>>>>>
>>>>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
>>>>>> regulator to do card IO voltage switch. It does not use external vqmmc
>>>>>> regulator.
>>>>>> So order irrelevant too.
>>>>>>
>>>>>> 3) Host using controller IO switch while card using external vqmmc
>>>>>> (special SDIO3.0 or eMMC)
>>>>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
>>>>>> the spec and using external regulator for card IO voltage.
>>>>>> Usually it's required to fix to 1.8v and also not order irrelevant.
>>>>>>
>>>>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
>>>>>>
>>>>>> So it looks all cases seems are not order required.
>>>>>
>>>>> I don't agree that there is any way to know that other host controllers
>>>>> are not affected.  I don't want a repeat of sdhci_set_power().
>>>>>
>>>>
>>>> Can you share some more info about sdhci_set_power() issue?
>>>> I'd like to see if we are same the issue.
>>>
>>> Not the same issue, but the same concept.  People changing the code under
>>> the impression that their way was correct, and then breaking other people's
>>> drivers.  Check the git history and mailing list.
>>>
>>> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
>>>
>>>>
>>>> BTW, IMHO i don't think we should stop keep moving only afraid of potential
>>>> break if it's correct way. Because .start_signal_voltage_switch() interface
>>>> seems shouldn't be order dependant.
>>>> If it is, then it should be fixed and handled in high layer like MMC core
>>>> rather than in host driver. Right?
>>>
>>> The SDHCI spec. does not define how to use external regulators, so there is
>>> no "correct way".
>>>
>>> We have to move forward *and* avoid potential breakage.
>>>
>>> In this case it seems me that the risk of breakage outweighs the value of
>>> prettier code.
>>>
>>> By the way, there are ways to get rid of the ugliness - such as pushing it down
>>> into individual drivers.
>>>
>>>>
>>>>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
>>>>> in place of regulator_set_voltage().
>>>>
>>>> Just using mmc_regulator_set_vqmmc() also changes the order which
>>>> is the same situation.
>>>
>>> How so?  It looks like a drop-in replacement to me:
>>
>> maybe.. this question should not be related with this discussion..
>> But i have one question..sdhci_do_start_signal_voltage_switch() returned 0 or EAGAIN, when IS_ERR(mmc->supply.vqmmc) is ture.
>> It there any problem?
> 
> Not that I am aware of.
> 
>>
>> I'm also checking on core side. but just wondering this.
>> (Because i'm fixing dwmmc controller for this.)
> 
> What is the problem?

It should be difference with dwmmc controller.
if mmc->supply.vqmmc is not assigned, it didn't change the voltage..
(I'm not sure that HOST_CONTROL2 register can internally change the voltage..because i didn't have SDHC 3.0 spec.)

__mmc_set_signal_voltage()
-> host->ops->start_signal_voltage_switch()
-> host controller just set the bits for v1.8 or v3.3..(if vqmmc didn't use.)
	if return -EAGAIN or 0 , the bits that was set for v1.8 or v3.3 should be maintained.

And do mmc_power_cycle() -> mmc_power_off and mmc_set_initial_state()

But host controller didn't initialize.

That is dwmmc controller's side..

As my understanding, if voltage switch(UHS-I mode) is failed, it should be set to HS mode.
but dwmmc controller didn't work this case..so i will fix.
(Some parts are code bugs in dwmmc controller.)

I don't know sdhci is working fine or not..just wondering. :)

I'm going to analyze the sequence and other thing..so i may miss something.

Best Regards,
Jaehoon Chung

> 
>>
>> Best Regards,
>> Jaehoon Chung
>>
>>>
>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>> index 94cffa77490a..69b4d48aff87 100644
>>> --- a/drivers/mmc/host/sdhci.c
>>> +++ b/drivers/mmc/host/sdhci.c
>>> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>>  
>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
>>> -						    3600000);
>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>  			if (ret) {
>>>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>>>  					mmc_hostname(mmc));
>>> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>>  		return -EAGAIN;
>>>  	case MMC_SIGNAL_VOLTAGE_180:
>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
>>> -					1700000, 1950000);
>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>  			if (ret) {
>>>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>>>  					mmc_hostname(mmc));
>>> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>>  		return -EAGAIN;
>>>  	case MMC_SIGNAL_VOLTAGE_120:
>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
>>> -						    1300000);
>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>  			if (ret) {
>>>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>>>  					mmc_hostname(mmc));
>>>
>>>
>>>
>>> --
>>> 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
>>>
>>>
>>
>>
> 
> --
> 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
> 
> 

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

* Re: [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
  2016-04-28  6:39             ` Adrian Hunter
@ 2016-04-28 13:14               ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-28 13:14 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On Thu, Apr 28, 2016 at 09:39:54AM +0300, Adrian Hunter wrote:
> On 28/04/16 06:09, Dong Aisheng wrote:
> > On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
> >> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
> >>> Hi Adrian,
> >>>
> >>> Thanks for the review first.
> >>>
> >>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> >>>> On 15/04/16 20:29, Dong Aisheng wrote:
> >>>>> Handle host and regulator signal voltage switch separately.
> >>>>> Move host signal voltage switch code into a separated function
> >>>>> sdhci_do_signal_voltage_switch() first, the following patches will
> >>>>> remove the regulator voltage switch code and use the common
> >>>>> mmc_regulator_set_vqmmc() instead.
> >>>>
> >>>> You have changed the order that things are done.
> >>>
> >>> Yes, the oder changes a bit that we always do controller voltage switch first.
> >>> I suppose the order is irrelevant here since i don't recall any
> >>> requirement from card.
> >>>
> >>> Actually the original order is also a bit mass.
> >>> e.g.
> >>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
> >>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
> >>> It looks to us the original one also order irrelevant.
> >>>
> >>>> There is no way to know
> >>>> what that will break, so let's not do that.  What about just changing
> >>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
> >>>>
> >>>
> >>> Currently what i can think out VIO switch using are three cases: (Pls
> >>> help add if any)
> >>> 1) Both host IO and card IO use external vqmmc to do switch
> >>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
> >>>
> >>> eMMC has no IO voltage switch protocol and requirement, so usually
> >>> board designed
> >>> using fixed 1.8V for eMMC and host IO.
> >>> Event it's switchable, it should be done in the first mmc_power_up().
> >>> Dynamical switch later may cause eMMC unable to work properly.
> >>> (We have been confirmed about this issue by many eMMC vendors
> >>> like Micron and Sandisk. I'm not sure if any exceptions in the community
> >>> still doing VIO dynamical switch for eMMC, if yes, please help share
> >>> the experience!).
> >>>
> >>> Event some people still do dynamical IO switch for eMMC, since eMMC
> >>> spec has no requirement, so the order should also not care.
> >>>
> >>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
> >>>
> >>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
> >>> regulator to do card IO voltage switch. It does not use external vqmmc
> >>> regulator.
> >>> So order irrelevant too.
> >>>
> >>> 3) Host using controller IO switch while card using external vqmmc
> >>> (special SDIO3.0 or eMMC)
> >>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
> >>> the spec and using external regulator for card IO voltage.
> >>> Usually it's required to fix to 1.8v and also not order irrelevant.
> >>>
> >>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
> >>>
> >>> So it looks all cases seems are not order required.
> >>
> >> I don't agree that there is any way to know that other host controllers
> >> are not affected.  I don't want a repeat of sdhci_set_power().
> >>
> > 
> > Can you share some more info about sdhci_set_power() issue?
> > I'd like to see if we are same the issue.
> 
> Not the same issue, but the same concept.  People changing the code under
> the impression that their way was correct, and then breaking other people's
> drivers.  Check the git history and mailing list.
> 
> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
> 

Yes, now i understand your concern.

> > 
> > BTW, IMHO i don't think we should stop keep moving only afraid of potential
> > break if it's correct way. Because .start_signal_voltage_switch() interface
> > seems shouldn't be order dependant.
> > If it is, then it should be fixed and handled in high layer like MMC core
> > rather than in host driver. Right?
> 
> The SDHCI spec. does not define how to use external regulators, so there is
> no "correct way".
> 

The "correct way" i mean here is .start_signal_voltage_switch() shouldn't be
order dependant, would you agree?

> We have to move forward *and* avoid potential breakage.
> 

If really break happens, fix platform driver, not common SDHCI.
That's the same thing you done for sdhci_set_power().

> In this case it seems me that the risk of breakage outweighs the value of
> prettier code.
> 

Actually my main purpose is patch 6: using mmc_regulator_set_vqmmc()
which is worth and it does improve the stability and eliminate the
potential signal issue.
However it's not the same way as you proposed.
See below.

> By the way, there are ways to get rid of the ugliness - such as pushing it down
> into individual drivers.
> 
> > 
> >> Please instead send a patch for just using mmc_regulator_set_vqmmc()
> >> in place of regulator_set_voltage().
> > 
> > Just using mmc_regulator_set_vqmmc() also changes the order which
> > is the same situation.
> 
> How so?  It looks like a drop-in replacement to me:
> 

Sorry, i did not get that you want to change like below.
However, it looks that it does not make too much sense to call
mmc_regulator_set_vqmmc() for each VOLTAGE type like 3.3v/1.8v/1.2v
which introduces ugliness because mmc_regulator_set_vqmmc()
already handles it internally, right?
Only because we want to keep an "ASSUMED" order as before?

Regards
Dong Aisheng

> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 94cffa77490a..69b4d48aff87 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>  
>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
> -						    3600000);
> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>  			if (ret) {
>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>  					mmc_hostname(mmc));
> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>  		return -EAGAIN;
>  	case MMC_SIGNAL_VOLTAGE_180:
>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
> -					1700000, 1950000);
> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>  			if (ret) {
>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>  					mmc_hostname(mmc));
> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>  		return -EAGAIN;
>  	case MMC_SIGNAL_VOLTAGE_120:
>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
> -						    1300000);
> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>  			if (ret) {
>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>  					mmc_hostname(mmc));
> 
> 
> 

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

* [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
@ 2016-04-28 13:14               ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-28 13:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 28, 2016 at 09:39:54AM +0300, Adrian Hunter wrote:
> On 28/04/16 06:09, Dong Aisheng wrote:
> > On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
> >> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
> >>> Hi Adrian,
> >>>
> >>> Thanks for the review first.
> >>>
> >>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> >>>> On 15/04/16 20:29, Dong Aisheng wrote:
> >>>>> Handle host and regulator signal voltage switch separately.
> >>>>> Move host signal voltage switch code into a separated function
> >>>>> sdhci_do_signal_voltage_switch() first, the following patches will
> >>>>> remove the regulator voltage switch code and use the common
> >>>>> mmc_regulator_set_vqmmc() instead.
> >>>>
> >>>> You have changed the order that things are done.
> >>>
> >>> Yes, the oder changes a bit that we always do controller voltage switch first.
> >>> I suppose the order is irrelevant here since i don't recall any
> >>> requirement from card.
> >>>
> >>> Actually the original order is also a bit mass.
> >>> e.g.
> >>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
> >>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
> >>> It looks to us the original one also order irrelevant.
> >>>
> >>>> There is no way to know
> >>>> what that will break, so let's not do that.  What about just changing
> >>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
> >>>>
> >>>
> >>> Currently what i can think out VIO switch using are three cases: (Pls
> >>> help add if any)
> >>> 1) Both host IO and card IO use external vqmmc to do switch
> >>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
> >>>
> >>> eMMC has no IO voltage switch protocol and requirement, so usually
> >>> board designed
> >>> using fixed 1.8V for eMMC and host IO.
> >>> Event it's switchable, it should be done in the first mmc_power_up().
> >>> Dynamical switch later may cause eMMC unable to work properly.
> >>> (We have been confirmed about this issue by many eMMC vendors
> >>> like Micron and Sandisk. I'm not sure if any exceptions in the community
> >>> still doing VIO dynamical switch for eMMC, if yes, please help share
> >>> the experience!).
> >>>
> >>> Event some people still do dynamical IO switch for eMMC, since eMMC
> >>> spec has no requirement, so the order should also not care.
> >>>
> >>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
> >>>
> >>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
> >>> regulator to do card IO voltage switch. It does not use external vqmmc
> >>> regulator.
> >>> So order irrelevant too.
> >>>
> >>> 3) Host using controller IO switch while card using external vqmmc
> >>> (special SDIO3.0 or eMMC)
> >>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
> >>> the spec and using external regulator for card IO voltage.
> >>> Usually it's required to fix to 1.8v and also not order irrelevant.
> >>>
> >>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
> >>>
> >>> So it looks all cases seems are not order required.
> >>
> >> I don't agree that there is any way to know that other host controllers
> >> are not affected.  I don't want a repeat of sdhci_set_power().
> >>
> > 
> > Can you share some more info about sdhci_set_power() issue?
> > I'd like to see if we are same the issue.
> 
> Not the same issue, but the same concept.  People changing the code under
> the impression that their way was correct, and then breaking other people's
> drivers.  Check the git history and mailing list.
> 
> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
> 

Yes, now i understand your concern.

> > 
> > BTW, IMHO i don't think we should stop keep moving only afraid of potential
> > break if it's correct way. Because .start_signal_voltage_switch() interface
> > seems shouldn't be order dependant.
> > If it is, then it should be fixed and handled in high layer like MMC core
> > rather than in host driver. Right?
> 
> The SDHCI spec. does not define how to use external regulators, so there is
> no "correct way".
> 

The "correct way" i mean here is .start_signal_voltage_switch() shouldn't be
order dependant, would you agree?

> We have to move forward *and* avoid potential breakage.
> 

If really break happens, fix platform driver, not common SDHCI.
That's the same thing you done for sdhci_set_power().

> In this case it seems me that the risk of breakage outweighs the value of
> prettier code.
> 

Actually my main purpose is patch 6: using mmc_regulator_set_vqmmc()
which is worth and it does improve the stability and eliminate the
potential signal issue.
However it's not the same way as you proposed.
See below.

> By the way, there are ways to get rid of the ugliness - such as pushing it down
> into individual drivers.
> 
> > 
> >> Please instead send a patch for just using mmc_regulator_set_vqmmc()
> >> in place of regulator_set_voltage().
> > 
> > Just using mmc_regulator_set_vqmmc() also changes the order which
> > is the same situation.
> 
> How so?  It looks like a drop-in replacement to me:
> 

Sorry, i did not get that you want to change like below.
However, it looks that it does not make too much sense to call
mmc_regulator_set_vqmmc() for each VOLTAGE type like 3.3v/1.8v/1.2v
which introduces ugliness because mmc_regulator_set_vqmmc()
already handles it internally, right?
Only because we want to keep an "ASSUMED" order as before?

Regards
Dong Aisheng

> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 94cffa77490a..69b4d48aff87 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>  
>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
> -						    3600000);
> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>  			if (ret) {
>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>  					mmc_hostname(mmc));
> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>  		return -EAGAIN;
>  	case MMC_SIGNAL_VOLTAGE_180:
>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
> -					1700000, 1950000);
> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>  			if (ret) {
>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>  					mmc_hostname(mmc));
> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>  		return -EAGAIN;
>  	case MMC_SIGNAL_VOLTAGE_120:
>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
> -						    1300000);
> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>  			if (ret) {
>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>  					mmc_hostname(mmc));
> 
> 
> 

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

* Re: [PATCH 10/23] mmc: core: disable auto retune during card detection process
  2016-04-28  7:04         ` Adrian Hunter
@ 2016-04-28 13:22           ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-28 13:22 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On Thu, Apr 28, 2016 at 10:04:34AM +0300, Adrian Hunter wrote:
> On 24/04/16 13:47, Dong Aisheng wrote:
> > On Fri, Apr 22, 2016 at 8:48 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> >> On 15/04/16 20:29, Dong Aisheng wrote:
> >>> During card detection process, mmc core may sends commands
> >>> to detect if card is still exist in mmc_rescan for removable
> >>> card which may trigger mmc retuning process after a bit time
> >>> of runtime pm suspend.
> >>> Obviously this retuning process is meaningless for card remove
> >>> case, so we disable mmc_retune in mmc_detect_change() for it.
> >>> For card insert case, the mmc_retune will be enabled normally
> >>> in its card initialization process later in mmc_execute_tuning().
> >>> So disable it at first has no side effection.
> >>
> >> We don't assume that the card has been removed, which is why we send
> >> commands to find out if it is still there.  If it is still there, this
> >> change will have incorrectly disabled re-tuning.
> >>
> > 
> > Do you mean the 'fake' card remove interrupt like caused by glitch?
> 
> Sure
> 
> > Yes, if that the card is still exist and re-tuning is wrongly disabled.
> > 
> > So we could re-enable re-tuning for this special case?
> > Something like:
> > diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> > index 41b1e76..e1990a8 100644
> > --- a/drivers/mmc/core/core.c
> > +++ b/drivers/mmc/core/core.c
> > @@ -2607,6 +2607,8 @@ void mmc_rescan(struct work_struct *work)
> > 
> >         /* if there still is a card present, stop here */
> >         if (host->bus_ops != NULL) {
> > +               if (tuning_is_enabled_before())
> > +                       mmc_retune_enable(host);
> >                 mmc_bus_put(host);
> >                 goto out;
> >         }
> > 
> > 
> >> Do you have an actual problem with the way it works now?
> >>
> > 
> > No actual problems now.
> 
> So let's not spend time on it.
> 
> > I just observe a lot tuning commands keep sending although the card is already
> > removed which seems a bit meaningless.
> > And most tuning execution process is executed with sin_lock_irqsave, i'm not
> > sure if the mass tuning commands may affect the system when CPU is busy.
> > What do you think?
> 
> sdhci spin lock is unlocked while waiting for tuning commands.
> 

It's 40 commands continuously and only cmd transfer time is unlocked.

Hmm.. I can't sure it's no affection.
e.g we did have customers reporting cd plug in/out causing jitters
when system is busy playing audio or video.
Maybe we need to do those tests.

Anyway, what's your point to keep sending tuning commands after card
is already removed?

Regards
Dong Aisheng

> > 
> > Regards
> > Dong Aisheng
> > 
> >>>
> >>> CC: stable <stable@vger.kernel.org>
> >>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> >>> ---
> >>>  drivers/mmc/core/core.c | 1 +
> >>>  1 file changed, 1 insertion(+)
> >>>
> >>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> >>> index 52bfaf0..76d0802 100644
> >>> --- a/drivers/mmc/core/core.c
> >>> +++ b/drivers/mmc/core/core.c
> >>> @@ -1888,6 +1888,7 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
> >>>               pm_wakeup_event(mmc_dev(host), 5000);
> >>>
> >>>       host->detect_change = 1;
> >>> +     mmc_retune_disable(host);
> >>>       mmc_schedule_delayed_work(&host->detect, delay);
> >>>  }
> >>>
> >>>
> >>
> > 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 10/23] mmc: core: disable auto retune during card detection process
@ 2016-04-28 13:22           ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-28 13:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 28, 2016 at 10:04:34AM +0300, Adrian Hunter wrote:
> On 24/04/16 13:47, Dong Aisheng wrote:
> > On Fri, Apr 22, 2016 at 8:48 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> >> On 15/04/16 20:29, Dong Aisheng wrote:
> >>> During card detection process, mmc core may sends commands
> >>> to detect if card is still exist in mmc_rescan for removable
> >>> card which may trigger mmc retuning process after a bit time
> >>> of runtime pm suspend.
> >>> Obviously this retuning process is meaningless for card remove
> >>> case, so we disable mmc_retune in mmc_detect_change() for it.
> >>> For card insert case, the mmc_retune will be enabled normally
> >>> in its card initialization process later in mmc_execute_tuning().
> >>> So disable it at first has no side effection.
> >>
> >> We don't assume that the card has been removed, which is why we send
> >> commands to find out if it is still there.  If it is still there, this
> >> change will have incorrectly disabled re-tuning.
> >>
> > 
> > Do you mean the 'fake' card remove interrupt like caused by glitch?
> 
> Sure
> 
> > Yes, if that the card is still exist and re-tuning is wrongly disabled.
> > 
> > So we could re-enable re-tuning for this special case?
> > Something like:
> > diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> > index 41b1e76..e1990a8 100644
> > --- a/drivers/mmc/core/core.c
> > +++ b/drivers/mmc/core/core.c
> > @@ -2607,6 +2607,8 @@ void mmc_rescan(struct work_struct *work)
> > 
> >         /* if there still is a card present, stop here */
> >         if (host->bus_ops != NULL) {
> > +               if (tuning_is_enabled_before())
> > +                       mmc_retune_enable(host);
> >                 mmc_bus_put(host);
> >                 goto out;
> >         }
> > 
> > 
> >> Do you have an actual problem with the way it works now?
> >>
> > 
> > No actual problems now.
> 
> So let's not spend time on it.
> 
> > I just observe a lot tuning commands keep sending although the card is already
> > removed which seems a bit meaningless.
> > And most tuning execution process is executed with sin_lock_irqsave, i'm not
> > sure if the mass tuning commands may affect the system when CPU is busy.
> > What do you think?
> 
> sdhci spin lock is unlocked while waiting for tuning commands.
> 

It's 40 commands continuously and only cmd transfer time is unlocked.

Hmm.. I can't sure it's no affection.
e.g we did have customers reporting cd plug in/out causing jitters
when system is busy playing audio or video.
Maybe we need to do those tests.

Anyway, what's your point to keep sending tuning commands after card
is already removed?

Regards
Dong Aisheng

> > 
> > Regards
> > Dong Aisheng
> > 
> >>>
> >>> CC: stable <stable@vger.kernel.org>
> >>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> >>> ---
> >>>  drivers/mmc/core/core.c | 1 +
> >>>  1 file changed, 1 insertion(+)
> >>>
> >>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> >>> index 52bfaf0..76d0802 100644
> >>> --- a/drivers/mmc/core/core.c
> >>> +++ b/drivers/mmc/core/core.c
> >>> @@ -1888,6 +1888,7 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
> >>>               pm_wakeup_event(mmc_dev(host), 5000);
> >>>
> >>>       host->detect_change = 1;
> >>> +     mmc_retune_disable(host);
> >>>       mmc_schedule_delayed_work(&host->detect, delay);
> >>>  }
> >>>
> >>>
> >>
> > 
> 
> --
> 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

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

* Re: [PATCH 07/23] mmc: sdhci: check SDHCI_QUIRK2_NO_1_8_V when do voltage switch
  2016-04-27 20:27         ` Adrian Hunter
@ 2016-04-28 13:24           ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-28 13:24 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On Wed, Apr 27, 2016 at 11:27:07PM +0300, Adrian Hunter wrote:
> On 24/04/2016 12:56 p.m., Dong Aisheng wrote:
> >On Fri, Apr 22, 2016 at 8:30 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> >>On 15/04/16 20:29, Dong Aisheng wrote:
> >>>Currently when card type supports EXT_CSD_CARD_TYPE_DDR_1_8V
> >>>which means it can work on DDR mode with either 3.3v IO or 1.8v
> >>>IO voltage. MMC core will first try 1.8v then 3.3v if host claims
> >>>MMC_CAP_1_8V_DDR support.
> >>>However the host driver voltage switch code does not check NO_1_8_V
> >>>quirk which may set a wrong 1.8v and causes the card fixed to 3.3v
> >>>VIO un-work.
> >>>
> >>>Checking 1.8V quirk before setting it to avoid such issue.
> >>
> >>We need to look forward to when SDHCI_QUIRK2_NO_1_8_V doesn't exist.
> >>
> >
> >Yes, i did try to clean up SDHCI_QUIRK2_NO_1_8_V.
> >However, it seems not that simply.
> >Currently we may still need it before we got a better way.
> >
> >My point is whether we should stop fixing the exist issue in SDHCI driver
> >just caused by we want to clean up it later?
> 
> If you want a fix for stable kernels, then I guess it is OK.  In that case
> it is better to have a fix that applies cleanly to older kernels
> i.e. not on top of re-factoring
> 

Okay, i would think more about how to remove SDHCI_QUIRK2_NO_1_8_V first.

Regards
Dong Aisheng

> >
> >>There are two possibilities:
> >>
> >>1. Add MMC_CAP_3_3V_DDR and support to core and use that instead of
> >>MMC_CAP_1_8V_DDR.  You'll need Ulf's feedback on that.
> >>
> >
> >Yes, we can do it.
> >But the point is for DDR50/SD3.0/SDIO3.0/HS200/HS400 cards we have
> >the same situation and still need QUIRK2_NO_1_8_V.
> >
> >And i somehow a bit wonder whether we should retrieve the speed mode
> >support from device tree since it's actually controller capability.
> >IO range capability is another thing.
> >
> >Probably we may start another topic to discuss it specificly.
> >
> >>2. Replace ->start_signal_voltage_switch() i.e.
> >>
> >>host->mmc_host_ops.start_signal_voltage_switch =
> >>esdhci_start_signal_voltage_switch;
> >>
> >>You will also need to change all calls to
> >>sdhci_start_signal_voltage_switch() with
> >>host->mmc->ops->start_signal_voltage_switch(), but that needs to be done anyway.
> >>
> >
> >esdhc can fully use the common sdhci_start_signal_voltag_switch.
> >Since it's already support QUIRK_NO_1_8_V, we don't want to
> >invent imx voltage swith currently, but fix and use it first.
> >
> >Regards
> >Dong Aisheng
> >
> >>>
> >>>CC: stable <stable@vger.kernel.org>
> >>>Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> >>>---
> >>>  drivers/mmc/host/sdhci.c | 2 ++
> >>>  1 file changed, 2 insertions(+)
> >>>
> >>>diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> >>>index 2338aab..96ccb15 100644
> >>>--- a/drivers/mmc/host/sdhci.c
> >>>+++ b/drivers/mmc/host/sdhci.c
> >>>@@ -1683,6 +1683,8 @@ static int sdhci_do_signal_voltage_switch(struct sdhci_host *host,
> >>>
> >>>               return -EAGAIN;
> >>>       case MMC_SIGNAL_VOLTAGE_180:
> >>>+             if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)
> >>>+                     return -EINVAL;
> >>>               /*
> >>>                * Enable 1.8V Signal Enable in the Host Control2
> >>>                * register
> >>>
> >>

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

* [PATCH 07/23] mmc: sdhci: check SDHCI_QUIRK2_NO_1_8_V when do voltage switch
@ 2016-04-28 13:24           ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-28 13:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Apr 27, 2016 at 11:27:07PM +0300, Adrian Hunter wrote:
> On 24/04/2016 12:56 p.m., Dong Aisheng wrote:
> >On Fri, Apr 22, 2016 at 8:30 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> >>On 15/04/16 20:29, Dong Aisheng wrote:
> >>>Currently when card type supports EXT_CSD_CARD_TYPE_DDR_1_8V
> >>>which means it can work on DDR mode with either 3.3v IO or 1.8v
> >>>IO voltage. MMC core will first try 1.8v then 3.3v if host claims
> >>>MMC_CAP_1_8V_DDR support.
> >>>However the host driver voltage switch code does not check NO_1_8_V
> >>>quirk which may set a wrong 1.8v and causes the card fixed to 3.3v
> >>>VIO un-work.
> >>>
> >>>Checking 1.8V quirk before setting it to avoid such issue.
> >>
> >>We need to look forward to when SDHCI_QUIRK2_NO_1_8_V doesn't exist.
> >>
> >
> >Yes, i did try to clean up SDHCI_QUIRK2_NO_1_8_V.
> >However, it seems not that simply.
> >Currently we may still need it before we got a better way.
> >
> >My point is whether we should stop fixing the exist issue in SDHCI driver
> >just caused by we want to clean up it later?
> 
> If you want a fix for stable kernels, then I guess it is OK.  In that case
> it is better to have a fix that applies cleanly to older kernels
> i.e. not on top of re-factoring
> 

Okay, i would think more about how to remove SDHCI_QUIRK2_NO_1_8_V first.

Regards
Dong Aisheng

> >
> >>There are two possibilities:
> >>
> >>1. Add MMC_CAP_3_3V_DDR and support to core and use that instead of
> >>MMC_CAP_1_8V_DDR.  You'll need Ulf's feedback on that.
> >>
> >
> >Yes, we can do it.
> >But the point is for DDR50/SD3.0/SDIO3.0/HS200/HS400 cards we have
> >the same situation and still need QUIRK2_NO_1_8_V.
> >
> >And i somehow a bit wonder whether we should retrieve the speed mode
> >support from device tree since it's actually controller capability.
> >IO range capability is another thing.
> >
> >Probably we may start another topic to discuss it specificly.
> >
> >>2. Replace ->start_signal_voltage_switch() i.e.
> >>
> >>host->mmc_host_ops.start_signal_voltage_switch =
> >>esdhci_start_signal_voltage_switch;
> >>
> >>You will also need to change all calls to
> >>sdhci_start_signal_voltage_switch() with
> >>host->mmc->ops->start_signal_voltage_switch(), but that needs to be done anyway.
> >>
> >
> >esdhc can fully use the common sdhci_start_signal_voltag_switch.
> >Since it's already support QUIRK_NO_1_8_V, we don't want to
> >invent imx voltage swith currently, but fix and use it first.
> >
> >Regards
> >Dong Aisheng
> >
> >>>
> >>>CC: stable <stable@vger.kernel.org>
> >>>Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> >>>---
> >>>  drivers/mmc/host/sdhci.c | 2 ++
> >>>  1 file changed, 2 insertions(+)
> >>>
> >>>diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> >>>index 2338aab..96ccb15 100644
> >>>--- a/drivers/mmc/host/sdhci.c
> >>>+++ b/drivers/mmc/host/sdhci.c
> >>>@@ -1683,6 +1683,8 @@ static int sdhci_do_signal_voltage_switch(struct sdhci_host *host,
> >>>
> >>>               return -EAGAIN;
> >>>       case MMC_SIGNAL_VOLTAGE_180:
> >>>+             if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)
> >>>+                     return -EINVAL;
> >>>               /*
> >>>                * Enable 1.8V Signal Enable in the Host Control2
> >>>                * register
> >>>
> >>

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

* Re: [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
  2016-04-28 13:14               ` Dong Aisheng
@ 2016-04-28 13:36                 ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-28 13:36 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On 28/04/16 16:14, Dong Aisheng wrote:
> On Thu, Apr 28, 2016 at 09:39:54AM +0300, Adrian Hunter wrote:
>> On 28/04/16 06:09, Dong Aisheng wrote:
>>> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
>>>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
>>>>> Hi Adrian,
>>>>>
>>>>> Thanks for the review first.
>>>>>
>>>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>>>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>>>>> Handle host and regulator signal voltage switch separately.
>>>>>>> Move host signal voltage switch code into a separated function
>>>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
>>>>>>> remove the regulator voltage switch code and use the common
>>>>>>> mmc_regulator_set_vqmmc() instead.
>>>>>>
>>>>>> You have changed the order that things are done.
>>>>>
>>>>> Yes, the oder changes a bit that we always do controller voltage switch first.
>>>>> I suppose the order is irrelevant here since i don't recall any
>>>>> requirement from card.
>>>>>
>>>>> Actually the original order is also a bit mass.
>>>>> e.g.
>>>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
>>>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
>>>>> It looks to us the original one also order irrelevant.
>>>>>
>>>>>> There is no way to know
>>>>>> what that will break, so let's not do that.  What about just changing
>>>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
>>>>>>
>>>>>
>>>>> Currently what i can think out VIO switch using are three cases: (Pls
>>>>> help add if any)
>>>>> 1) Both host IO and card IO use external vqmmc to do switch
>>>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
>>>>>
>>>>> eMMC has no IO voltage switch protocol and requirement, so usually
>>>>> board designed
>>>>> using fixed 1.8V for eMMC and host IO.
>>>>> Event it's switchable, it should be done in the first mmc_power_up().
>>>>> Dynamical switch later may cause eMMC unable to work properly.
>>>>> (We have been confirmed about this issue by many eMMC vendors
>>>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
>>>>> still doing VIO dynamical switch for eMMC, if yes, please help share
>>>>> the experience!).
>>>>>
>>>>> Event some people still do dynamical IO switch for eMMC, since eMMC
>>>>> spec has no requirement, so the order should also not care.
>>>>>
>>>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
>>>>>
>>>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
>>>>> regulator to do card IO voltage switch. It does not use external vqmmc
>>>>> regulator.
>>>>> So order irrelevant too.
>>>>>
>>>>> 3) Host using controller IO switch while card using external vqmmc
>>>>> (special SDIO3.0 or eMMC)
>>>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
>>>>> the spec and using external regulator for card IO voltage.
>>>>> Usually it's required to fix to 1.8v and also not order irrelevant.
>>>>>
>>>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
>>>>>
>>>>> So it looks all cases seems are not order required.
>>>>
>>>> I don't agree that there is any way to know that other host controllers
>>>> are not affected.  I don't want a repeat of sdhci_set_power().
>>>>
>>>
>>> Can you share some more info about sdhci_set_power() issue?
>>> I'd like to see if we are same the issue.
>>
>> Not the same issue, but the same concept.  People changing the code under
>> the impression that their way was correct, and then breaking other people's
>> drivers.  Check the git history and mailing list.
>>
>> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
>>
> 
> Yes, now i understand your concern.
> 
>>>
>>> BTW, IMHO i don't think we should stop keep moving only afraid of potential
>>> break if it's correct way. Because .start_signal_voltage_switch() interface
>>> seems shouldn't be order dependant.
>>> If it is, then it should be fixed and handled in high layer like MMC core
>>> rather than in host driver. Right?
>>
>> The SDHCI spec. does not define how to use external regulators, so there is
>> no "correct way".
>>
> 
> The "correct way" i mean here is .start_signal_voltage_switch() shouldn't be
> order dependant, would you agree?

No.  There is no way to know if the regulator must be switched before or
after the host controller register is changed.

> 
>> We have to move forward *and* avoid potential breakage.
>>
> 
> If really break happens, fix platform driver, not common SDHCI.
> That's the same thing you done for sdhci_set_power().

In that case the original behaviour was kept in the common SDHCI code and
the driver had to provide its own way.

> 
>> In this case it seems me that the risk of breakage outweighs the value of
>> prettier code.
>>
> 
> Actually my main purpose is patch 6: using mmc_regulator_set_vqmmc()
> which is worth and it does improve the stability and eliminate the
> potential signal issue.
> However it's not the same way as you proposed.
> See below.
> 
>> By the way, there are ways to get rid of the ugliness - such as pushing it down
>> into individual drivers.
>>
>>>
>>>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
>>>> in place of regulator_set_voltage().
>>>
>>> Just using mmc_regulator_set_vqmmc() also changes the order which
>>> is the same situation.
>>
>> How so?  It looks like a drop-in replacement to me:
>>
> 
> Sorry, i did not get that you want to change like below.
> However, it looks that it does not make too much sense to call
> mmc_regulator_set_vqmmc() for each VOLTAGE type like 3.3v/1.8v/1.2v
> which introduces ugliness because mmc_regulator_set_vqmmc()
> already handles it internally, right?
> Only because we want to keep an "ASSUMED" order as before?

Yes

> 
> Regards
> Dong Aisheng
> 
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 94cffa77490a..69b4d48aff87 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>  
>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
>> -						    3600000);
>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>  			if (ret) {
>>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>>  					mmc_hostname(mmc));
>> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>  		return -EAGAIN;
>>  	case MMC_SIGNAL_VOLTAGE_180:
>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
>> -					1700000, 1950000);
>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>  			if (ret) {
>>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>>  					mmc_hostname(mmc));
>> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>  		return -EAGAIN;
>>  	case MMC_SIGNAL_VOLTAGE_120:
>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
>> -						    1300000);
>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>  			if (ret) {
>>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>>  					mmc_hostname(mmc));
>>
>>
>>
> 


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

* [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
@ 2016-04-28 13:36                 ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-28 13:36 UTC (permalink / raw)
  To: linux-arm-kernel

On 28/04/16 16:14, Dong Aisheng wrote:
> On Thu, Apr 28, 2016 at 09:39:54AM +0300, Adrian Hunter wrote:
>> On 28/04/16 06:09, Dong Aisheng wrote:
>>> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
>>>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
>>>>> Hi Adrian,
>>>>>
>>>>> Thanks for the review first.
>>>>>
>>>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>>>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>>>>> Handle host and regulator signal voltage switch separately.
>>>>>>> Move host signal voltage switch code into a separated function
>>>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
>>>>>>> remove the regulator voltage switch code and use the common
>>>>>>> mmc_regulator_set_vqmmc() instead.
>>>>>>
>>>>>> You have changed the order that things are done.
>>>>>
>>>>> Yes, the oder changes a bit that we always do controller voltage switch first.
>>>>> I suppose the order is irrelevant here since i don't recall any
>>>>> requirement from card.
>>>>>
>>>>> Actually the original order is also a bit mass.
>>>>> e.g.
>>>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
>>>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
>>>>> It looks to us the original one also order irrelevant.
>>>>>
>>>>>> There is no way to know
>>>>>> what that will break, so let's not do that.  What about just changing
>>>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
>>>>>>
>>>>>
>>>>> Currently what i can think out VIO switch using are three cases: (Pls
>>>>> help add if any)
>>>>> 1) Both host IO and card IO use external vqmmc to do switch
>>>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
>>>>>
>>>>> eMMC has no IO voltage switch protocol and requirement, so usually
>>>>> board designed
>>>>> using fixed 1.8V for eMMC and host IO.
>>>>> Event it's switchable, it should be done in the first mmc_power_up().
>>>>> Dynamical switch later may cause eMMC unable to work properly.
>>>>> (We have been confirmed about this issue by many eMMC vendors
>>>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
>>>>> still doing VIO dynamical switch for eMMC, if yes, please help share
>>>>> the experience!).
>>>>>
>>>>> Event some people still do dynamical IO switch for eMMC, since eMMC
>>>>> spec has no requirement, so the order should also not care.
>>>>>
>>>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
>>>>>
>>>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
>>>>> regulator to do card IO voltage switch. It does not use external vqmmc
>>>>> regulator.
>>>>> So order irrelevant too.
>>>>>
>>>>> 3) Host using controller IO switch while card using external vqmmc
>>>>> (special SDIO3.0 or eMMC)
>>>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
>>>>> the spec and using external regulator for card IO voltage.
>>>>> Usually it's required to fix to 1.8v and also not order irrelevant.
>>>>>
>>>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
>>>>>
>>>>> So it looks all cases seems are not order required.
>>>>
>>>> I don't agree that there is any way to know that other host controllers
>>>> are not affected.  I don't want a repeat of sdhci_set_power().
>>>>
>>>
>>> Can you share some more info about sdhci_set_power() issue?
>>> I'd like to see if we are same the issue.
>>
>> Not the same issue, but the same concept.  People changing the code under
>> the impression that their way was correct, and then breaking other people's
>> drivers.  Check the git history and mailing list.
>>
>> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
>>
> 
> Yes, now i understand your concern.
> 
>>>
>>> BTW, IMHO i don't think we should stop keep moving only afraid of potential
>>> break if it's correct way. Because .start_signal_voltage_switch() interface
>>> seems shouldn't be order dependant.
>>> If it is, then it should be fixed and handled in high layer like MMC core
>>> rather than in host driver. Right?
>>
>> The SDHCI spec. does not define how to use external regulators, so there is
>> no "correct way".
>>
> 
> The "correct way" i mean here is .start_signal_voltage_switch() shouldn't be
> order dependant, would you agree?

No.  There is no way to know if the regulator must be switched before or
after the host controller register is changed.

> 
>> We have to move forward *and* avoid potential breakage.
>>
> 
> If really break happens, fix platform driver, not common SDHCI.
> That's the same thing you done for sdhci_set_power().

In that case the original behaviour was kept in the common SDHCI code and
the driver had to provide its own way.

> 
>> In this case it seems me that the risk of breakage outweighs the value of
>> prettier code.
>>
> 
> Actually my main purpose is patch 6: using mmc_regulator_set_vqmmc()
> which is worth and it does improve the stability and eliminate the
> potential signal issue.
> However it's not the same way as you proposed.
> See below.
> 
>> By the way, there are ways to get rid of the ugliness - such as pushing it down
>> into individual drivers.
>>
>>>
>>>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
>>>> in place of regulator_set_voltage().
>>>
>>> Just using mmc_regulator_set_vqmmc() also changes the order which
>>> is the same situation.
>>
>> How so?  It looks like a drop-in replacement to me:
>>
> 
> Sorry, i did not get that you want to change like below.
> However, it looks that it does not make too much sense to call
> mmc_regulator_set_vqmmc() for each VOLTAGE type like 3.3v/1.8v/1.2v
> which introduces ugliness because mmc_regulator_set_vqmmc()
> already handles it internally, right?
> Only because we want to keep an "ASSUMED" order as before?

Yes

> 
> Regards
> Dong Aisheng
> 
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 94cffa77490a..69b4d48aff87 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>  
>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
>> -						    3600000);
>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>  			if (ret) {
>>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>>  					mmc_hostname(mmc));
>> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>  		return -EAGAIN;
>>  	case MMC_SIGNAL_VOLTAGE_180:
>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
>> -					1700000, 1950000);
>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>  			if (ret) {
>>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>>  					mmc_hostname(mmc));
>> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>  		return -EAGAIN;
>>  	case MMC_SIGNAL_VOLTAGE_120:
>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
>> -						    1300000);
>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>  			if (ret) {
>>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>>  					mmc_hostname(mmc));
>>
>>
>>
> 

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

* Re: [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
  2016-04-28  8:30                   ` Jaehoon Chung
@ 2016-04-28 14:09                     ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-28 14:09 UTC (permalink / raw)
  To: Jaehoon Chung
  Cc: Adrian Hunter, Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball,
	Shawn Guo, linux-arm-kernel, haibo.chen, CPGS

On Thu, Apr 28, 2016 at 05:30:11PM +0900, Jaehoon Chung wrote:
> On 04/28/2016 04:44 PM, Adrian Hunter wrote:
> > On 28/04/16 10:15, Jaehoon Chung wrote:
> >> Hi Adrian,
> >>
> >> On 04/28/2016 03:39 PM, Adrian Hunter wrote:
> >>> On 28/04/16 06:09, Dong Aisheng wrote:
> >>>> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
> >>>>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
> >>>>>> Hi Adrian,
> >>>>>>
> >>>>>> Thanks for the review first.
> >>>>>>
> >>>>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> >>>>>>> On 15/04/16 20:29, Dong Aisheng wrote:
> >>>>>>>> Handle host and regulator signal voltage switch separately.
> >>>>>>>> Move host signal voltage switch code into a separated function
> >>>>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
> >>>>>>>> remove the regulator voltage switch code and use the common
> >>>>>>>> mmc_regulator_set_vqmmc() instead.
> >>>>>>>
> >>>>>>> You have changed the order that things are done.
> >>>>>>
> >>>>>> Yes, the oder changes a bit that we always do controller voltage switch first.
> >>>>>> I suppose the order is irrelevant here since i don't recall any
> >>>>>> requirement from card.
> >>>>>>
> >>>>>> Actually the original order is also a bit mass.
> >>>>>> e.g.
> >>>>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
> >>>>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
> >>>>>> It looks to us the original one also order irrelevant.
> >>>>>>
> >>>>>>> There is no way to know
> >>>>>>> what that will break, so let's not do that.  What about just changing
> >>>>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
> >>>>>>>
> >>>>>>
> >>>>>> Currently what i can think out VIO switch using are three cases: (Pls
> >>>>>> help add if any)
> >>>>>> 1) Both host IO and card IO use external vqmmc to do switch
> >>>>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
> >>>>>>
> >>>>>> eMMC has no IO voltage switch protocol and requirement, so usually
> >>>>>> board designed
> >>>>>> using fixed 1.8V for eMMC and host IO.
> >>>>>> Event it's switchable, it should be done in the first mmc_power_up().
> >>>>>> Dynamical switch later may cause eMMC unable to work properly.
> >>>>>> (We have been confirmed about this issue by many eMMC vendors
> >>>>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
> >>>>>> still doing VIO dynamical switch for eMMC, if yes, please help share
> >>>>>> the experience!).
> >>>>>>
> >>>>>> Event some people still do dynamical IO switch for eMMC, since eMMC
> >>>>>> spec has no requirement, so the order should also not care.
> >>>>>>
> >>>>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
> >>>>>>
> >>>>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
> >>>>>> regulator to do card IO voltage switch. It does not use external vqmmc
> >>>>>> regulator.
> >>>>>> So order irrelevant too.
> >>>>>>
> >>>>>> 3) Host using controller IO switch while card using external vqmmc
> >>>>>> (special SDIO3.0 or eMMC)
> >>>>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
> >>>>>> the spec and using external regulator for card IO voltage.
> >>>>>> Usually it's required to fix to 1.8v and also not order irrelevant.
> >>>>>>
> >>>>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
> >>>>>>
> >>>>>> So it looks all cases seems are not order required.
> >>>>>
> >>>>> I don't agree that there is any way to know that other host controllers
> >>>>> are not affected.  I don't want a repeat of sdhci_set_power().
> >>>>>
> >>>>
> >>>> Can you share some more info about sdhci_set_power() issue?
> >>>> I'd like to see if we are same the issue.
> >>>
> >>> Not the same issue, but the same concept.  People changing the code under
> >>> the impression that their way was correct, and then breaking other people's
> >>> drivers.  Check the git history and mailing list.
> >>>
> >>> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
> >>>
> >>>>
> >>>> BTW, IMHO i don't think we should stop keep moving only afraid of potential
> >>>> break if it's correct way. Because .start_signal_voltage_switch() interface
> >>>> seems shouldn't be order dependant.
> >>>> If it is, then it should be fixed and handled in high layer like MMC core
> >>>> rather than in host driver. Right?
> >>>
> >>> The SDHCI spec. does not define how to use external regulators, so there is
> >>> no "correct way".
> >>>
> >>> We have to move forward *and* avoid potential breakage.
> >>>
> >>> In this case it seems me that the risk of breakage outweighs the value of
> >>> prettier code.
> >>>
> >>> By the way, there are ways to get rid of the ugliness - such as pushing it down
> >>> into individual drivers.
> >>>
> >>>>
> >>>>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
> >>>>> in place of regulator_set_voltage().
> >>>>
> >>>> Just using mmc_regulator_set_vqmmc() also changes the order which
> >>>> is the same situation.
> >>>
> >>> How so?  It looks like a drop-in replacement to me:
> >>
> >> maybe.. this question should not be related with this discussion..
> >> But i have one question..sdhci_do_start_signal_voltage_switch() returned 0 or EAGAIN, when IS_ERR(mmc->supply.vqmmc) is ture.
> >> It there any problem?
> > 
> > Not that I am aware of.
> > 
> >>
> >> I'm also checking on core side. but just wondering this.
> >> (Because i'm fixing dwmmc controller for this.)
> > 
> > What is the problem?
> 
> It should be difference with dwmmc controller.
> if mmc->supply.vqmmc is not assigned, it didn't change the voltage..
> (I'm not sure that HOST_CONTROL2 register can internally change the voltage..because i didn't have SDHC 3.0 spec.)
> 
> __mmc_set_signal_voltage()
> -> host->ops->start_signal_voltage_switch()
> -> host controller just set the bits for v1.8 or v3.3..(if vqmmc didn't use.)
> 	if return -EAGAIN or 0 , the bits that was set for v1.8 or v3.3 should be maintained.
> 
> And do mmc_power_cycle() -> mmc_power_off and mmc_set_initial_state()
> 
> But host controller didn't initialize.
> 
> That is dwmmc controller's side..
> 
> As my understanding, if voltage switch(UHS-I mode) is failed, it should be set to HS mode.
> but dwmmc controller didn't work this case..so i will fix.
> (Some parts are code bugs in dwmmc controller.)
> 

MMC core will retry HS mode initialization if voltage switch reach 10
times failure.
See: mmc_sd_get_cid()

> I don't know sdhci is working fine or not..just wondering. :)
> 

I tested sdhci is working fine.

> I'm going to analyze the sequence and other thing..so i may miss something.
> 

Probably you may need check if the IO voltage is correctly back up
after failure.

Regards
Dong Aisheng

> Best Regards,
> Jaehoon Chung
> 
> > 
> >>
> >> Best Regards,
> >> Jaehoon Chung
> >>
> >>>
> >>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> >>> index 94cffa77490a..69b4d48aff87 100644
> >>> --- a/drivers/mmc/host/sdhci.c
> >>> +++ b/drivers/mmc/host/sdhci.c
> >>> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> >>>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
> >>>  
> >>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> >>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
> >>> -						    3600000);
> >>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
> >>>  			if (ret) {
> >>>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
> >>>  					mmc_hostname(mmc));
> >>> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> >>>  		return -EAGAIN;
> >>>  	case MMC_SIGNAL_VOLTAGE_180:
> >>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> >>> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
> >>> -					1700000, 1950000);
> >>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
> >>>  			if (ret) {
> >>>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
> >>>  					mmc_hostname(mmc));
> >>> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> >>>  		return -EAGAIN;
> >>>  	case MMC_SIGNAL_VOLTAGE_120:
> >>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> >>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
> >>> -						    1300000);
> >>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
> >>>  			if (ret) {
> >>>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
> >>>  					mmc_hostname(mmc));
> >>>
> >>>
> >>>
> >>> --
> >>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> >>> the body of a message to majordomo@vger.kernel.org
> >>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >>>
> >>>
> >>
> >>
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > 
> > 
> 

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

* [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
@ 2016-04-28 14:09                     ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-28 14:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 28, 2016 at 05:30:11PM +0900, Jaehoon Chung wrote:
> On 04/28/2016 04:44 PM, Adrian Hunter wrote:
> > On 28/04/16 10:15, Jaehoon Chung wrote:
> >> Hi Adrian,
> >>
> >> On 04/28/2016 03:39 PM, Adrian Hunter wrote:
> >>> On 28/04/16 06:09, Dong Aisheng wrote:
> >>>> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
> >>>>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
> >>>>>> Hi Adrian,
> >>>>>>
> >>>>>> Thanks for the review first.
> >>>>>>
> >>>>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> >>>>>>> On 15/04/16 20:29, Dong Aisheng wrote:
> >>>>>>>> Handle host and regulator signal voltage switch separately.
> >>>>>>>> Move host signal voltage switch code into a separated function
> >>>>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
> >>>>>>>> remove the regulator voltage switch code and use the common
> >>>>>>>> mmc_regulator_set_vqmmc() instead.
> >>>>>>>
> >>>>>>> You have changed the order that things are done.
> >>>>>>
> >>>>>> Yes, the oder changes a bit that we always do controller voltage switch first.
> >>>>>> I suppose the order is irrelevant here since i don't recall any
> >>>>>> requirement from card.
> >>>>>>
> >>>>>> Actually the original order is also a bit mass.
> >>>>>> e.g.
> >>>>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
> >>>>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
> >>>>>> It looks to us the original one also order irrelevant.
> >>>>>>
> >>>>>>> There is no way to know
> >>>>>>> what that will break, so let's not do that.  What about just changing
> >>>>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
> >>>>>>>
> >>>>>>
> >>>>>> Currently what i can think out VIO switch using are three cases: (Pls
> >>>>>> help add if any)
> >>>>>> 1) Both host IO and card IO use external vqmmc to do switch
> >>>>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
> >>>>>>
> >>>>>> eMMC has no IO voltage switch protocol and requirement, so usually
> >>>>>> board designed
> >>>>>> using fixed 1.8V for eMMC and host IO.
> >>>>>> Event it's switchable, it should be done in the first mmc_power_up().
> >>>>>> Dynamical switch later may cause eMMC unable to work properly.
> >>>>>> (We have been confirmed about this issue by many eMMC vendors
> >>>>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
> >>>>>> still doing VIO dynamical switch for eMMC, if yes, please help share
> >>>>>> the experience!).
> >>>>>>
> >>>>>> Event some people still do dynamical IO switch for eMMC, since eMMC
> >>>>>> spec has no requirement, so the order should also not care.
> >>>>>>
> >>>>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
> >>>>>>
> >>>>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
> >>>>>> regulator to do card IO voltage switch. It does not use external vqmmc
> >>>>>> regulator.
> >>>>>> So order irrelevant too.
> >>>>>>
> >>>>>> 3) Host using controller IO switch while card using external vqmmc
> >>>>>> (special SDIO3.0 or eMMC)
> >>>>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
> >>>>>> the spec and using external regulator for card IO voltage.
> >>>>>> Usually it's required to fix to 1.8v and also not order irrelevant.
> >>>>>>
> >>>>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
> >>>>>>
> >>>>>> So it looks all cases seems are not order required.
> >>>>>
> >>>>> I don't agree that there is any way to know that other host controllers
> >>>>> are not affected.  I don't want a repeat of sdhci_set_power().
> >>>>>
> >>>>
> >>>> Can you share some more info about sdhci_set_power() issue?
> >>>> I'd like to see if we are same the issue.
> >>>
> >>> Not the same issue, but the same concept.  People changing the code under
> >>> the impression that their way was correct, and then breaking other people's
> >>> drivers.  Check the git history and mailing list.
> >>>
> >>> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
> >>>
> >>>>
> >>>> BTW, IMHO i don't think we should stop keep moving only afraid of potential
> >>>> break if it's correct way. Because .start_signal_voltage_switch() interface
> >>>> seems shouldn't be order dependant.
> >>>> If it is, then it should be fixed and handled in high layer like MMC core
> >>>> rather than in host driver. Right?
> >>>
> >>> The SDHCI spec. does not define how to use external regulators, so there is
> >>> no "correct way".
> >>>
> >>> We have to move forward *and* avoid potential breakage.
> >>>
> >>> In this case it seems me that the risk of breakage outweighs the value of
> >>> prettier code.
> >>>
> >>> By the way, there are ways to get rid of the ugliness - such as pushing it down
> >>> into individual drivers.
> >>>
> >>>>
> >>>>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
> >>>>> in place of regulator_set_voltage().
> >>>>
> >>>> Just using mmc_regulator_set_vqmmc() also changes the order which
> >>>> is the same situation.
> >>>
> >>> How so?  It looks like a drop-in replacement to me:
> >>
> >> maybe.. this question should not be related with this discussion..
> >> But i have one question..sdhci_do_start_signal_voltage_switch() returned 0 or EAGAIN, when IS_ERR(mmc->supply.vqmmc) is ture.
> >> It there any problem?
> > 
> > Not that I am aware of.
> > 
> >>
> >> I'm also checking on core side. but just wondering this.
> >> (Because i'm fixing dwmmc controller for this.)
> > 
> > What is the problem?
> 
> It should be difference with dwmmc controller.
> if mmc->supply.vqmmc is not assigned, it didn't change the voltage..
> (I'm not sure that HOST_CONTROL2 register can internally change the voltage..because i didn't have SDHC 3.0 spec.)
> 
> __mmc_set_signal_voltage()
> -> host->ops->start_signal_voltage_switch()
> -> host controller just set the bits for v1.8 or v3.3..(if vqmmc didn't use.)
> 	if return -EAGAIN or 0 , the bits that was set for v1.8 or v3.3 should be maintained.
> 
> And do mmc_power_cycle() -> mmc_power_off and mmc_set_initial_state()
> 
> But host controller didn't initialize.
> 
> That is dwmmc controller's side..
> 
> As my understanding, if voltage switch(UHS-I mode) is failed, it should be set to HS mode.
> but dwmmc controller didn't work this case..so i will fix.
> (Some parts are code bugs in dwmmc controller.)
> 

MMC core will retry HS mode initialization if voltage switch reach 10
times failure.
See: mmc_sd_get_cid()

> I don't know sdhci is working fine or not..just wondering. :)
> 

I tested sdhci is working fine.

> I'm going to analyze the sequence and other thing..so i may miss something.
> 

Probably you may need check if the IO voltage is correctly back up
after failure.

Regards
Dong Aisheng

> Best Regards,
> Jaehoon Chung
> 
> > 
> >>
> >> Best Regards,
> >> Jaehoon Chung
> >>
> >>>
> >>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> >>> index 94cffa77490a..69b4d48aff87 100644
> >>> --- a/drivers/mmc/host/sdhci.c
> >>> +++ b/drivers/mmc/host/sdhci.c
> >>> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> >>>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
> >>>  
> >>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> >>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
> >>> -						    3600000);
> >>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
> >>>  			if (ret) {
> >>>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
> >>>  					mmc_hostname(mmc));
> >>> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> >>>  		return -EAGAIN;
> >>>  	case MMC_SIGNAL_VOLTAGE_180:
> >>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> >>> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
> >>> -					1700000, 1950000);
> >>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
> >>>  			if (ret) {
> >>>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
> >>>  					mmc_hostname(mmc));
> >>> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> >>>  		return -EAGAIN;
> >>>  	case MMC_SIGNAL_VOLTAGE_120:
> >>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> >>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
> >>> -						    1300000);
> >>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
> >>>  			if (ret) {
> >>>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
> >>>  					mmc_hostname(mmc));
> >>>
> >>>
> >>>
> >>> --
> >>> 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
> >>>
> >>>
> >>
> >>
> > 
> > --
> > 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
> > 
> > 
> 

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

* Re: [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
  2016-04-28 13:36                 ` Adrian Hunter
@ 2016-04-28 14:28                   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-28 14:28 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On Thu, Apr 28, 2016 at 04:36:25PM +0300, Adrian Hunter wrote:
> On 28/04/16 16:14, Dong Aisheng wrote:
> > On Thu, Apr 28, 2016 at 09:39:54AM +0300, Adrian Hunter wrote:
> >> On 28/04/16 06:09, Dong Aisheng wrote:
> >>> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
> >>>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
> >>>>> Hi Adrian,
> >>>>>
> >>>>> Thanks for the review first.
> >>>>>
> >>>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> >>>>>> On 15/04/16 20:29, Dong Aisheng wrote:
> >>>>>>> Handle host and regulator signal voltage switch separately.
> >>>>>>> Move host signal voltage switch code into a separated function
> >>>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
> >>>>>>> remove the regulator voltage switch code and use the common
> >>>>>>> mmc_regulator_set_vqmmc() instead.
> >>>>>>
> >>>>>> You have changed the order that things are done.
> >>>>>
> >>>>> Yes, the oder changes a bit that we always do controller voltage switch first.
> >>>>> I suppose the order is irrelevant here since i don't recall any
> >>>>> requirement from card.
> >>>>>
> >>>>> Actually the original order is also a bit mass.
> >>>>> e.g.
> >>>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
> >>>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
> >>>>> It looks to us the original one also order irrelevant.
> >>>>>
> >>>>>> There is no way to know
> >>>>>> what that will break, so let's not do that.  What about just changing
> >>>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
> >>>>>>
> >>>>>
> >>>>> Currently what i can think out VIO switch using are three cases: (Pls
> >>>>> help add if any)
> >>>>> 1) Both host IO and card IO use external vqmmc to do switch
> >>>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
> >>>>>
> >>>>> eMMC has no IO voltage switch protocol and requirement, so usually
> >>>>> board designed
> >>>>> using fixed 1.8V for eMMC and host IO.
> >>>>> Event it's switchable, it should be done in the first mmc_power_up().
> >>>>> Dynamical switch later may cause eMMC unable to work properly.
> >>>>> (We have been confirmed about this issue by many eMMC vendors
> >>>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
> >>>>> still doing VIO dynamical switch for eMMC, if yes, please help share
> >>>>> the experience!).
> >>>>>
> >>>>> Event some people still do dynamical IO switch for eMMC, since eMMC
> >>>>> spec has no requirement, so the order should also not care.
> >>>>>
> >>>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
> >>>>>
> >>>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
> >>>>> regulator to do card IO voltage switch. It does not use external vqmmc
> >>>>> regulator.
> >>>>> So order irrelevant too.
> >>>>>
> >>>>> 3) Host using controller IO switch while card using external vqmmc
> >>>>> (special SDIO3.0 or eMMC)
> >>>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
> >>>>> the spec and using external regulator for card IO voltage.
> >>>>> Usually it's required to fix to 1.8v and also not order irrelevant.
> >>>>>
> >>>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
> >>>>>
> >>>>> So it looks all cases seems are not order required.
> >>>>
> >>>> I don't agree that there is any way to know that other host controllers
> >>>> are not affected.  I don't want a repeat of sdhci_set_power().
> >>>>
> >>>
> >>> Can you share some more info about sdhci_set_power() issue?
> >>> I'd like to see if we are same the issue.
> >>
> >> Not the same issue, but the same concept.  People changing the code under
> >> the impression that their way was correct, and then breaking other people's
> >> drivers.  Check the git history and mailing list.
> >>
> >> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
> >>
> > 
> > Yes, now i understand your concern.
> > 
> >>>
> >>> BTW, IMHO i don't think we should stop keep moving only afraid of potential
> >>> break if it's correct way. Because .start_signal_voltage_switch() interface
> >>> seems shouldn't be order dependant.
> >>> If it is, then it should be fixed and handled in high layer like MMC core
> >>> rather than in host driver. Right?
> >>
> >> The SDHCI spec. does not define how to use external regulators, so there is
> >> no "correct way".
> >>
> > 
> > The "correct way" i mean here is .start_signal_voltage_switch() shouldn't be
> > order dependant, would you agree?
> 
> No.  There is no way to know if the regulator must be switched before or
> after the host controller register is changed.
> 

Hmm... If there is no way to know the correct order, how can we
assume the exist order is correct?
And i already pointed out, the exist order is also confused that
it switch controller first then vqmmc for 3.3v and switch vqmmc
first, then controller for 1.8v

If we can't sure the exist order is correct, why do we block
the changing to correctly use mmc_regulator_set_vqmmc() to
improve the driver stability?

And actually the change is not made arbitrarily, i already list
all possibilities based on my knowledge. People can raise more
if any.
The target is correct that we make start_signal_voltage_switch()
order independant.
It's worth a try even there's a potential very low possibility
break IMHO.

Or else if we can find a better way to switch to
mmc_regulator_set_vqmmc i would also love to try.
 
Maybe we need more people's thought on it!

Ulf,
Would you give some inputs?

Regards
Dong Aisheng

> > 
> >> We have to move forward *and* avoid potential breakage.
> >>
> > 
> > If really break happens, fix platform driver, not common SDHCI.
> > That's the same thing you done for sdhci_set_power().
> 
> In that case the original behaviour was kept in the common SDHCI code and
> the driver had to provide its own way.
> 
> > 
> >> In this case it seems me that the risk of breakage outweighs the value of
> >> prettier code.
> >>
> > 
> > Actually my main purpose is patch 6: using mmc_regulator_set_vqmmc()
> > which is worth and it does improve the stability and eliminate the
> > potential signal issue.
> > However it's not the same way as you proposed.
> > See below.
> > 
> >> By the way, there are ways to get rid of the ugliness - such as pushing it down
> >> into individual drivers.
> >>
> >>>
> >>>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
> >>>> in place of regulator_set_voltage().
> >>>
> >>> Just using mmc_regulator_set_vqmmc() also changes the order which
> >>> is the same situation.
> >>
> >> How so?  It looks like a drop-in replacement to me:
> >>
> > 
> > Sorry, i did not get that you want to change like below.
> > However, it looks that it does not make too much sense to call
> > mmc_regulator_set_vqmmc() for each VOLTAGE type like 3.3v/1.8v/1.2v
> > which introduces ugliness because mmc_regulator_set_vqmmc()
> > already handles it internally, right?
> > Only because we want to keep an "ASSUMED" order as before?
> 
> Yes
> 
> > 
> > Regards
> > Dong Aisheng
> > 
> >> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> >> index 94cffa77490a..69b4d48aff87 100644
> >> --- a/drivers/mmc/host/sdhci.c
> >> +++ b/drivers/mmc/host/sdhci.c
> >> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> >>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
> >>  
> >>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> >> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
> >> -						    3600000);
> >> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
> >>  			if (ret) {
> >>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
> >>  					mmc_hostname(mmc));
> >> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> >>  		return -EAGAIN;
> >>  	case MMC_SIGNAL_VOLTAGE_180:
> >>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> >> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
> >> -					1700000, 1950000);
> >> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
> >>  			if (ret) {
> >>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
> >>  					mmc_hostname(mmc));
> >> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> >>  		return -EAGAIN;
> >>  	case MMC_SIGNAL_VOLTAGE_120:
> >>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> >> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
> >> -						    1300000);
> >> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
> >>  			if (ret) {
> >>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
> >>  					mmc_hostname(mmc));
> >>
> >>
> >>
> > 
> 

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

* [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
@ 2016-04-28 14:28                   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-28 14:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 28, 2016 at 04:36:25PM +0300, Adrian Hunter wrote:
> On 28/04/16 16:14, Dong Aisheng wrote:
> > On Thu, Apr 28, 2016 at 09:39:54AM +0300, Adrian Hunter wrote:
> >> On 28/04/16 06:09, Dong Aisheng wrote:
> >>> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
> >>>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
> >>>>> Hi Adrian,
> >>>>>
> >>>>> Thanks for the review first.
> >>>>>
> >>>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> >>>>>> On 15/04/16 20:29, Dong Aisheng wrote:
> >>>>>>> Handle host and regulator signal voltage switch separately.
> >>>>>>> Move host signal voltage switch code into a separated function
> >>>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
> >>>>>>> remove the regulator voltage switch code and use the common
> >>>>>>> mmc_regulator_set_vqmmc() instead.
> >>>>>>
> >>>>>> You have changed the order that things are done.
> >>>>>
> >>>>> Yes, the oder changes a bit that we always do controller voltage switch first.
> >>>>> I suppose the order is irrelevant here since i don't recall any
> >>>>> requirement from card.
> >>>>>
> >>>>> Actually the original order is also a bit mass.
> >>>>> e.g.
> >>>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
> >>>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
> >>>>> It looks to us the original one also order irrelevant.
> >>>>>
> >>>>>> There is no way to know
> >>>>>> what that will break, so let's not do that.  What about just changing
> >>>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
> >>>>>>
> >>>>>
> >>>>> Currently what i can think out VIO switch using are three cases: (Pls
> >>>>> help add if any)
> >>>>> 1) Both host IO and card IO use external vqmmc to do switch
> >>>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
> >>>>>
> >>>>> eMMC has no IO voltage switch protocol and requirement, so usually
> >>>>> board designed
> >>>>> using fixed 1.8V for eMMC and host IO.
> >>>>> Event it's switchable, it should be done in the first mmc_power_up().
> >>>>> Dynamical switch later may cause eMMC unable to work properly.
> >>>>> (We have been confirmed about this issue by many eMMC vendors
> >>>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
> >>>>> still doing VIO dynamical switch for eMMC, if yes, please help share
> >>>>> the experience!).
> >>>>>
> >>>>> Event some people still do dynamical IO switch for eMMC, since eMMC
> >>>>> spec has no requirement, so the order should also not care.
> >>>>>
> >>>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
> >>>>>
> >>>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
> >>>>> regulator to do card IO voltage switch. It does not use external vqmmc
> >>>>> regulator.
> >>>>> So order irrelevant too.
> >>>>>
> >>>>> 3) Host using controller IO switch while card using external vqmmc
> >>>>> (special SDIO3.0 or eMMC)
> >>>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
> >>>>> the spec and using external regulator for card IO voltage.
> >>>>> Usually it's required to fix to 1.8v and also not order irrelevant.
> >>>>>
> >>>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
> >>>>>
> >>>>> So it looks all cases seems are not order required.
> >>>>
> >>>> I don't agree that there is any way to know that other host controllers
> >>>> are not affected.  I don't want a repeat of sdhci_set_power().
> >>>>
> >>>
> >>> Can you share some more info about sdhci_set_power() issue?
> >>> I'd like to see if we are same the issue.
> >>
> >> Not the same issue, but the same concept.  People changing the code under
> >> the impression that their way was correct, and then breaking other people's
> >> drivers.  Check the git history and mailing list.
> >>
> >> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
> >>
> > 
> > Yes, now i understand your concern.
> > 
> >>>
> >>> BTW, IMHO i don't think we should stop keep moving only afraid of potential
> >>> break if it's correct way. Because .start_signal_voltage_switch() interface
> >>> seems shouldn't be order dependant.
> >>> If it is, then it should be fixed and handled in high layer like MMC core
> >>> rather than in host driver. Right?
> >>
> >> The SDHCI spec. does not define how to use external regulators, so there is
> >> no "correct way".
> >>
> > 
> > The "correct way" i mean here is .start_signal_voltage_switch() shouldn't be
> > order dependant, would you agree?
> 
> No.  There is no way to know if the regulator must be switched before or
> after the host controller register is changed.
> 

Hmm... If there is no way to know the correct order, how can we
assume the exist order is correct?
And i already pointed out, the exist order is also confused that
it switch controller first then vqmmc for 3.3v and switch vqmmc
first, then controller for 1.8v

If we can't sure the exist order is correct, why do we block
the changing to correctly use mmc_regulator_set_vqmmc() to
improve the driver stability?

And actually the change is not made arbitrarily, i already list
all possibilities based on my knowledge. People can raise more
if any.
The target is correct that we make start_signal_voltage_switch()
order independant.
It's worth a try even there's a potential very low possibility
break IMHO.

Or else if we can find a better way to switch to
mmc_regulator_set_vqmmc i would also love to try.
 
Maybe we need more people's thought on it!

Ulf,
Would you give some inputs?

Regards
Dong Aisheng

> > 
> >> We have to move forward *and* avoid potential breakage.
> >>
> > 
> > If really break happens, fix platform driver, not common SDHCI.
> > That's the same thing you done for sdhci_set_power().
> 
> In that case the original behaviour was kept in the common SDHCI code and
> the driver had to provide its own way.
> 
> > 
> >> In this case it seems me that the risk of breakage outweighs the value of
> >> prettier code.
> >>
> > 
> > Actually my main purpose is patch 6: using mmc_regulator_set_vqmmc()
> > which is worth and it does improve the stability and eliminate the
> > potential signal issue.
> > However it's not the same way as you proposed.
> > See below.
> > 
> >> By the way, there are ways to get rid of the ugliness - such as pushing it down
> >> into individual drivers.
> >>
> >>>
> >>>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
> >>>> in place of regulator_set_voltage().
> >>>
> >>> Just using mmc_regulator_set_vqmmc() also changes the order which
> >>> is the same situation.
> >>
> >> How so?  It looks like a drop-in replacement to me:
> >>
> > 
> > Sorry, i did not get that you want to change like below.
> > However, it looks that it does not make too much sense to call
> > mmc_regulator_set_vqmmc() for each VOLTAGE type like 3.3v/1.8v/1.2v
> > which introduces ugliness because mmc_regulator_set_vqmmc()
> > already handles it internally, right?
> > Only because we want to keep an "ASSUMED" order as before?
> 
> Yes
> 
> > 
> > Regards
> > Dong Aisheng
> > 
> >> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> >> index 94cffa77490a..69b4d48aff87 100644
> >> --- a/drivers/mmc/host/sdhci.c
> >> +++ b/drivers/mmc/host/sdhci.c
> >> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> >>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
> >>  
> >>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> >> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
> >> -						    3600000);
> >> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
> >>  			if (ret) {
> >>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
> >>  					mmc_hostname(mmc));
> >> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> >>  		return -EAGAIN;
> >>  	case MMC_SIGNAL_VOLTAGE_180:
> >>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> >> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
> >> -					1700000, 1950000);
> >> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
> >>  			if (ret) {
> >>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
> >>  					mmc_hostname(mmc));
> >> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> >>  		return -EAGAIN;
> >>  	case MMC_SIGNAL_VOLTAGE_120:
> >>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> >> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
> >> -						    1300000);
> >> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
> >>  			if (ret) {
> >>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
> >>  					mmc_hostname(mmc));
> >>
> >>
> >>
> > 
> 

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

* Re: [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
  2016-04-28 14:09                     ` Dong Aisheng
@ 2016-04-28 23:06                       ` Jaehoon Chung
  -1 siblings, 0 replies; 170+ messages in thread
From: Jaehoon Chung @ 2016-04-28 23:06 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Adrian Hunter, Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball,
	Shawn Guo, linux-arm-kernel, haibo.chen, CPGS

On 04/28/2016 11:09 PM, Dong Aisheng wrote:
> On Thu, Apr 28, 2016 at 05:30:11PM +0900, Jaehoon Chung wrote:
>> On 04/28/2016 04:44 PM, Adrian Hunter wrote:
>>> On 28/04/16 10:15, Jaehoon Chung wrote:
>>>> Hi Adrian,
>>>>
>>>> On 04/28/2016 03:39 PM, Adrian Hunter wrote:
>>>>> On 28/04/16 06:09, Dong Aisheng wrote:
>>>>>> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
>>>>>>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
>>>>>>>> Hi Adrian,
>>>>>>>>
>>>>>>>> Thanks for the review first.
>>>>>>>>
>>>>>>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>>>>>>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>>>>>>>> Handle host and regulator signal voltage switch separately.
>>>>>>>>>> Move host signal voltage switch code into a separated function
>>>>>>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
>>>>>>>>>> remove the regulator voltage switch code and use the common
>>>>>>>>>> mmc_regulator_set_vqmmc() instead.
>>>>>>>>>
>>>>>>>>> You have changed the order that things are done.
>>>>>>>>
>>>>>>>> Yes, the oder changes a bit that we always do controller voltage switch first.
>>>>>>>> I suppose the order is irrelevant here since i don't recall any
>>>>>>>> requirement from card.
>>>>>>>>
>>>>>>>> Actually the original order is also a bit mass.
>>>>>>>> e.g.
>>>>>>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
>>>>>>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
>>>>>>>> It looks to us the original one also order irrelevant.
>>>>>>>>
>>>>>>>>> There is no way to know
>>>>>>>>> what that will break, so let's not do that.  What about just changing
>>>>>>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
>>>>>>>>>
>>>>>>>>
>>>>>>>> Currently what i can think out VIO switch using are three cases: (Pls
>>>>>>>> help add if any)
>>>>>>>> 1) Both host IO and card IO use external vqmmc to do switch
>>>>>>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
>>>>>>>>
>>>>>>>> eMMC has no IO voltage switch protocol and requirement, so usually
>>>>>>>> board designed
>>>>>>>> using fixed 1.8V for eMMC and host IO.
>>>>>>>> Event it's switchable, it should be done in the first mmc_power_up().
>>>>>>>> Dynamical switch later may cause eMMC unable to work properly.
>>>>>>>> (We have been confirmed about this issue by many eMMC vendors
>>>>>>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
>>>>>>>> still doing VIO dynamical switch for eMMC, if yes, please help share
>>>>>>>> the experience!).
>>>>>>>>
>>>>>>>> Event some people still do dynamical IO switch for eMMC, since eMMC
>>>>>>>> spec has no requirement, so the order should also not care.
>>>>>>>>
>>>>>>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
>>>>>>>>
>>>>>>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
>>>>>>>> regulator to do card IO voltage switch. It does not use external vqmmc
>>>>>>>> regulator.
>>>>>>>> So order irrelevant too.
>>>>>>>>
>>>>>>>> 3) Host using controller IO switch while card using external vqmmc
>>>>>>>> (special SDIO3.0 or eMMC)
>>>>>>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
>>>>>>>> the spec and using external regulator for card IO voltage.
>>>>>>>> Usually it's required to fix to 1.8v and also not order irrelevant.
>>>>>>>>
>>>>>>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
>>>>>>>>
>>>>>>>> So it looks all cases seems are not order required.
>>>>>>>
>>>>>>> I don't agree that there is any way to know that other host controllers
>>>>>>> are not affected.  I don't want a repeat of sdhci_set_power().
>>>>>>>
>>>>>>
>>>>>> Can you share some more info about sdhci_set_power() issue?
>>>>>> I'd like to see if we are same the issue.
>>>>>
>>>>> Not the same issue, but the same concept.  People changing the code under
>>>>> the impression that their way was correct, and then breaking other people's
>>>>> drivers.  Check the git history and mailing list.
>>>>>
>>>>> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
>>>>>
>>>>>>
>>>>>> BTW, IMHO i don't think we should stop keep moving only afraid of potential
>>>>>> break if it's correct way. Because .start_signal_voltage_switch() interface
>>>>>> seems shouldn't be order dependant.
>>>>>> If it is, then it should be fixed and handled in high layer like MMC core
>>>>>> rather than in host driver. Right?
>>>>>
>>>>> The SDHCI spec. does not define how to use external regulators, so there is
>>>>> no "correct way".
>>>>>
>>>>> We have to move forward *and* avoid potential breakage.
>>>>>
>>>>> In this case it seems me that the risk of breakage outweighs the value of
>>>>> prettier code.
>>>>>
>>>>> By the way, there are ways to get rid of the ugliness - such as pushing it down
>>>>> into individual drivers.
>>>>>
>>>>>>
>>>>>>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
>>>>>>> in place of regulator_set_voltage().
>>>>>>
>>>>>> Just using mmc_regulator_set_vqmmc() also changes the order which
>>>>>> is the same situation.
>>>>>
>>>>> How so?  It looks like a drop-in replacement to me:
>>>>
>>>> maybe.. this question should not be related with this discussion..
>>>> But i have one question..sdhci_do_start_signal_voltage_switch() returned 0 or EAGAIN, when IS_ERR(mmc->supply.vqmmc) is ture.
>>>> It there any problem?
>>>
>>> Not that I am aware of.
>>>
>>>>
>>>> I'm also checking on core side. but just wondering this.
>>>> (Because i'm fixing dwmmc controller for this.)
>>>
>>> What is the problem?
>>
>> It should be difference with dwmmc controller.
>> if mmc->supply.vqmmc is not assigned, it didn't change the voltage..
>> (I'm not sure that HOST_CONTROL2 register can internally change the voltage..because i didn't have SDHC 3.0 spec.)
>>
>> __mmc_set_signal_voltage()
>> -> host->ops->start_signal_voltage_switch()
>> -> host controller just set the bits for v1.8 or v3.3..(if vqmmc didn't use.)
>> 	if return -EAGAIN or 0 , the bits that was set for v1.8 or v3.3 should be maintained.
>>
>> And do mmc_power_cycle() -> mmc_power_off and mmc_set_initial_state()
>>
>> But host controller didn't initialize.
>>
>> That is dwmmc controller's side..
>>
>> As my understanding, if voltage switch(UHS-I mode) is failed, it should be set to HS mode.
>> but dwmmc controller didn't work this case..so i will fix.
>> (Some parts are code bugs in dwmmc controller.)
>>
> 
> MMC core will retry HS mode initialization if voltage switch reach 10
> times failure.
> See: mmc_sd_get_cid()

Yes, i knew.

> 
>> I don't know sdhci is working fine or not..just wondering. :)
>>
> 
> I tested sdhci is working fine.
> 
>> I'm going to analyze the sequence and other thing..so i may miss something.
>>
> 
> Probably you may need check if the IO voltage is correctly back up
> after failure.

As i mentioned, this is dwmmc controller's problem..there is some bugs. :)
So i'm fixing. Thanks!

Best Regards,
Jaehoon Chung

> 
> Regards
> Dong Aisheng
> 
>> Best Regards,
>> Jaehoon Chung
>>
>>>
>>>>
>>>> Best Regards,
>>>> Jaehoon Chung
>>>>
>>>>>
>>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>>>> index 94cffa77490a..69b4d48aff87 100644
>>>>> --- a/drivers/mmc/host/sdhci.c
>>>>> +++ b/drivers/mmc/host/sdhci.c
>>>>> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>>>>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>>>>  
>>>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>>>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
>>>>> -						    3600000);
>>>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>>  			if (ret) {
>>>>>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>>>>>  					mmc_hostname(mmc));
>>>>> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>>>>  		return -EAGAIN;
>>>>>  	case MMC_SIGNAL_VOLTAGE_180:
>>>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>>>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
>>>>> -					1700000, 1950000);
>>>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>>  			if (ret) {
>>>>>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>>>>>  					mmc_hostname(mmc));
>>>>> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>>>>  		return -EAGAIN;
>>>>>  	case MMC_SIGNAL_VOLTAGE_120:
>>>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>>>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
>>>>> -						    1300000);
>>>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>>  			if (ret) {
>>>>>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>>>>>  					mmc_hostname(mmc));
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>>>>> the body of a message to majordomo@vger.kernel.org
>>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>>>
>>>>>
>>>>
>>>>
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>
>>>
>>
> 
> 


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

* [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
@ 2016-04-28 23:06                       ` Jaehoon Chung
  0 siblings, 0 replies; 170+ messages in thread
From: Jaehoon Chung @ 2016-04-28 23:06 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/28/2016 11:09 PM, Dong Aisheng wrote:
> On Thu, Apr 28, 2016 at 05:30:11PM +0900, Jaehoon Chung wrote:
>> On 04/28/2016 04:44 PM, Adrian Hunter wrote:
>>> On 28/04/16 10:15, Jaehoon Chung wrote:
>>>> Hi Adrian,
>>>>
>>>> On 04/28/2016 03:39 PM, Adrian Hunter wrote:
>>>>> On 28/04/16 06:09, Dong Aisheng wrote:
>>>>>> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
>>>>>>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
>>>>>>>> Hi Adrian,
>>>>>>>>
>>>>>>>> Thanks for the review first.
>>>>>>>>
>>>>>>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>>>>>>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>>>>>>>> Handle host and regulator signal voltage switch separately.
>>>>>>>>>> Move host signal voltage switch code into a separated function
>>>>>>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
>>>>>>>>>> remove the regulator voltage switch code and use the common
>>>>>>>>>> mmc_regulator_set_vqmmc() instead.
>>>>>>>>>
>>>>>>>>> You have changed the order that things are done.
>>>>>>>>
>>>>>>>> Yes, the oder changes a bit that we always do controller voltage switch first.
>>>>>>>> I suppose the order is irrelevant here since i don't recall any
>>>>>>>> requirement from card.
>>>>>>>>
>>>>>>>> Actually the original order is also a bit mass.
>>>>>>>> e.g.
>>>>>>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
>>>>>>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
>>>>>>>> It looks to us the original one also order irrelevant.
>>>>>>>>
>>>>>>>>> There is no way to know
>>>>>>>>> what that will break, so let's not do that.  What about just changing
>>>>>>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
>>>>>>>>>
>>>>>>>>
>>>>>>>> Currently what i can think out VIO switch using are three cases: (Pls
>>>>>>>> help add if any)
>>>>>>>> 1) Both host IO and card IO use external vqmmc to do switch
>>>>>>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
>>>>>>>>
>>>>>>>> eMMC has no IO voltage switch protocol and requirement, so usually
>>>>>>>> board designed
>>>>>>>> using fixed 1.8V for eMMC and host IO.
>>>>>>>> Event it's switchable, it should be done in the first mmc_power_up().
>>>>>>>> Dynamical switch later may cause eMMC unable to work properly.
>>>>>>>> (We have been confirmed about this issue by many eMMC vendors
>>>>>>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
>>>>>>>> still doing VIO dynamical switch for eMMC, if yes, please help share
>>>>>>>> the experience!).
>>>>>>>>
>>>>>>>> Event some people still do dynamical IO switch for eMMC, since eMMC
>>>>>>>> spec has no requirement, so the order should also not care.
>>>>>>>>
>>>>>>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
>>>>>>>>
>>>>>>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
>>>>>>>> regulator to do card IO voltage switch. It does not use external vqmmc
>>>>>>>> regulator.
>>>>>>>> So order irrelevant too.
>>>>>>>>
>>>>>>>> 3) Host using controller IO switch while card using external vqmmc
>>>>>>>> (special SDIO3.0 or eMMC)
>>>>>>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
>>>>>>>> the spec and using external regulator for card IO voltage.
>>>>>>>> Usually it's required to fix to 1.8v and also not order irrelevant.
>>>>>>>>
>>>>>>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
>>>>>>>>
>>>>>>>> So it looks all cases seems are not order required.
>>>>>>>
>>>>>>> I don't agree that there is any way to know that other host controllers
>>>>>>> are not affected.  I don't want a repeat of sdhci_set_power().
>>>>>>>
>>>>>>
>>>>>> Can you share some more info about sdhci_set_power() issue?
>>>>>> I'd like to see if we are same the issue.
>>>>>
>>>>> Not the same issue, but the same concept.  People changing the code under
>>>>> the impression that their way was correct, and then breaking other people's
>>>>> drivers.  Check the git history and mailing list.
>>>>>
>>>>> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
>>>>>
>>>>>>
>>>>>> BTW, IMHO i don't think we should stop keep moving only afraid of potential
>>>>>> break if it's correct way. Because .start_signal_voltage_switch() interface
>>>>>> seems shouldn't be order dependant.
>>>>>> If it is, then it should be fixed and handled in high layer like MMC core
>>>>>> rather than in host driver. Right?
>>>>>
>>>>> The SDHCI spec. does not define how to use external regulators, so there is
>>>>> no "correct way".
>>>>>
>>>>> We have to move forward *and* avoid potential breakage.
>>>>>
>>>>> In this case it seems me that the risk of breakage outweighs the value of
>>>>> prettier code.
>>>>>
>>>>> By the way, there are ways to get rid of the ugliness - such as pushing it down
>>>>> into individual drivers.
>>>>>
>>>>>>
>>>>>>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
>>>>>>> in place of regulator_set_voltage().
>>>>>>
>>>>>> Just using mmc_regulator_set_vqmmc() also changes the order which
>>>>>> is the same situation.
>>>>>
>>>>> How so?  It looks like a drop-in replacement to me:
>>>>
>>>> maybe.. this question should not be related with this discussion..
>>>> But i have one question..sdhci_do_start_signal_voltage_switch() returned 0 or EAGAIN, when IS_ERR(mmc->supply.vqmmc) is ture.
>>>> It there any problem?
>>>
>>> Not that I am aware of.
>>>
>>>>
>>>> I'm also checking on core side. but just wondering this.
>>>> (Because i'm fixing dwmmc controller for this.)
>>>
>>> What is the problem?
>>
>> It should be difference with dwmmc controller.
>> if mmc->supply.vqmmc is not assigned, it didn't change the voltage..
>> (I'm not sure that HOST_CONTROL2 register can internally change the voltage..because i didn't have SDHC 3.0 spec.)
>>
>> __mmc_set_signal_voltage()
>> -> host->ops->start_signal_voltage_switch()
>> -> host controller just set the bits for v1.8 or v3.3..(if vqmmc didn't use.)
>> 	if return -EAGAIN or 0 , the bits that was set for v1.8 or v3.3 should be maintained.
>>
>> And do mmc_power_cycle() -> mmc_power_off and mmc_set_initial_state()
>>
>> But host controller didn't initialize.
>>
>> That is dwmmc controller's side..
>>
>> As my understanding, if voltage switch(UHS-I mode) is failed, it should be set to HS mode.
>> but dwmmc controller didn't work this case..so i will fix.
>> (Some parts are code bugs in dwmmc controller.)
>>
> 
> MMC core will retry HS mode initialization if voltage switch reach 10
> times failure.
> See: mmc_sd_get_cid()

Yes, i knew.

> 
>> I don't know sdhci is working fine or not..just wondering. :)
>>
> 
> I tested sdhci is working fine.
> 
>> I'm going to analyze the sequence and other thing..so i may miss something.
>>
> 
> Probably you may need check if the IO voltage is correctly back up
> after failure.

As i mentioned, this is dwmmc controller's problem..there is some bugs. :)
So i'm fixing. Thanks!

Best Regards,
Jaehoon Chung

> 
> Regards
> Dong Aisheng
> 
>> Best Regards,
>> Jaehoon Chung
>>
>>>
>>>>
>>>> Best Regards,
>>>> Jaehoon Chung
>>>>
>>>>>
>>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>>>> index 94cffa77490a..69b4d48aff87 100644
>>>>> --- a/drivers/mmc/host/sdhci.c
>>>>> +++ b/drivers/mmc/host/sdhci.c
>>>>> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>>>>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>>>>  
>>>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>>>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
>>>>> -						    3600000);
>>>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>>  			if (ret) {
>>>>>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>>>>>  					mmc_hostname(mmc));
>>>>> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>>>>  		return -EAGAIN;
>>>>>  	case MMC_SIGNAL_VOLTAGE_180:
>>>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>>>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
>>>>> -					1700000, 1950000);
>>>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>>  			if (ret) {
>>>>>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>>>>>  					mmc_hostname(mmc));
>>>>> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>>>>  		return -EAGAIN;
>>>>>  	case MMC_SIGNAL_VOLTAGE_120:
>>>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>>>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
>>>>> -						    1300000);
>>>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>>  			if (ret) {
>>>>>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>>>>>  					mmc_hostname(mmc));
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> 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
>>>>>
>>>>>
>>>>
>>>>
>>>
>>> --
>>> 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
>>>
>>>
>>
> 
> 

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

* Re: [PATCH 10/23] mmc: core: disable auto retune during card detection process
  2016-04-28 13:22           ` Dong Aisheng
@ 2016-04-29  6:54             ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-29  6:54 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On 28/04/16 16:22, Dong Aisheng wrote:
> On Thu, Apr 28, 2016 at 10:04:34AM +0300, Adrian Hunter wrote:
>> On 24/04/16 13:47, Dong Aisheng wrote:
>>> On Fri, Apr 22, 2016 at 8:48 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>>> During card detection process, mmc core may sends commands
>>>>> to detect if card is still exist in mmc_rescan for removable
>>>>> card which may trigger mmc retuning process after a bit time
>>>>> of runtime pm suspend.
>>>>> Obviously this retuning process is meaningless for card remove
>>>>> case, so we disable mmc_retune in mmc_detect_change() for it.
>>>>> For card insert case, the mmc_retune will be enabled normally
>>>>> in its card initialization process later in mmc_execute_tuning().
>>>>> So disable it at first has no side effection.
>>>>
>>>> We don't assume that the card has been removed, which is why we send
>>>> commands to find out if it is still there.  If it is still there, this
>>>> change will have incorrectly disabled re-tuning.
>>>>
>>>
>>> Do you mean the 'fake' card remove interrupt like caused by glitch?
>>
>> Sure
>>
>>> Yes, if that the card is still exist and re-tuning is wrongly disabled.
>>>
>>> So we could re-enable re-tuning for this special case?
>>> Something like:
>>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
>>> index 41b1e76..e1990a8 100644
>>> --- a/drivers/mmc/core/core.c
>>> +++ b/drivers/mmc/core/core.c
>>> @@ -2607,6 +2607,8 @@ void mmc_rescan(struct work_struct *work)
>>>
>>>         /* if there still is a card present, stop here */
>>>         if (host->bus_ops != NULL) {
>>> +               if (tuning_is_enabled_before())
>>> +                       mmc_retune_enable(host);
>>>                 mmc_bus_put(host);
>>>                 goto out;
>>>         }
>>>
>>>
>>>> Do you have an actual problem with the way it works now?
>>>>
>>>
>>> No actual problems now.
>>
>> So let's not spend time on it.
>>
>>> I just observe a lot tuning commands keep sending although the card is already
>>> removed which seems a bit meaningless.
>>> And most tuning execution process is executed with sin_lock_irqsave, i'm not
>>> sure if the mass tuning commands may affect the system when CPU is busy.
>>> What do you think?
>>
>> sdhci spin lock is unlocked while waiting for tuning commands.
>>
> 
> It's 40 commands continuously and only cmd transfer time is unlocked.

Not for sdhci_execute_tuning() it's not.  Only one command is sent.
Currently we don't even send the CMD13 because we check card detect first.
I added prints for sdhci_execute_tuning and got this:

[  255.536326] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000080
[  255.743653] mmc1: starting CMD13 arg 59b40000 flags 00000195
[  255.750093] mmc1: sdhci_execute_tuning
[  255.754358] mmc1: sdhci_execute_tuning: send command
[  255.809638] sdhci: Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock
[  255.824810] mmc1: req failed (CMD13): -123, retrying...
[  255.832766] mmc1: req failed (CMD13): -123, retrying...
[  255.840722] mmc1: req failed (CMD13): -123, retrying...
[  255.848672] mmc1: req done (CMD13): -123: 00000000 00000000 00000000 00000000
[  255.856773] mmc1: card remove detected
[  255.861056] mmc1: card 59b4 removed
[  255.872872] mmc1: clock 0Hz busmode 2 powermode 0 cs 0 Vdd 0 width 0 timing 0

> 
> Hmm.. I can't sure it's no affection.
> e.g we did have customers reporting cd plug in/out causing jitters
> when system is busy playing audio or video.
> Maybe we need to do those tests.
> 
> Anyway, what's your point to keep sending tuning commands after card
> is already removed?

Seems like a problem for your driver not the core.  Why not check card detect
after the first error in esdhc_executing_tuning().

> 
> Regards
> Dong Aisheng
> 
>>>
>>> Regards
>>> Dong Aisheng
>>>
>>>>>
>>>>> CC: stable <stable@vger.kernel.org>
>>>>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>>>>> ---
>>>>>  drivers/mmc/core/core.c | 1 +
>>>>>  1 file changed, 1 insertion(+)
>>>>>
>>>>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
>>>>> index 52bfaf0..76d0802 100644
>>>>> --- a/drivers/mmc/core/core.c
>>>>> +++ b/drivers/mmc/core/core.c
>>>>> @@ -1888,6 +1888,7 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
>>>>>               pm_wakeup_event(mmc_dev(host), 5000);
>>>>>
>>>>>       host->detect_change = 1;
>>>>> +     mmc_retune_disable(host);
>>>>>       mmc_schedule_delayed_work(&host->detect, delay);
>>>>>  }
>>>>>
>>>>>
>>>>
>>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


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

* [PATCH 10/23] mmc: core: disable auto retune during card detection process
@ 2016-04-29  6:54             ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-29  6:54 UTC (permalink / raw)
  To: linux-arm-kernel

On 28/04/16 16:22, Dong Aisheng wrote:
> On Thu, Apr 28, 2016 at 10:04:34AM +0300, Adrian Hunter wrote:
>> On 24/04/16 13:47, Dong Aisheng wrote:
>>> On Fri, Apr 22, 2016 at 8:48 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>>> During card detection process, mmc core may sends commands
>>>>> to detect if card is still exist in mmc_rescan for removable
>>>>> card which may trigger mmc retuning process after a bit time
>>>>> of runtime pm suspend.
>>>>> Obviously this retuning process is meaningless for card remove
>>>>> case, so we disable mmc_retune in mmc_detect_change() for it.
>>>>> For card insert case, the mmc_retune will be enabled normally
>>>>> in its card initialization process later in mmc_execute_tuning().
>>>>> So disable it at first has no side effection.
>>>>
>>>> We don't assume that the card has been removed, which is why we send
>>>> commands to find out if it is still there.  If it is still there, this
>>>> change will have incorrectly disabled re-tuning.
>>>>
>>>
>>> Do you mean the 'fake' card remove interrupt like caused by glitch?
>>
>> Sure
>>
>>> Yes, if that the card is still exist and re-tuning is wrongly disabled.
>>>
>>> So we could re-enable re-tuning for this special case?
>>> Something like:
>>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
>>> index 41b1e76..e1990a8 100644
>>> --- a/drivers/mmc/core/core.c
>>> +++ b/drivers/mmc/core/core.c
>>> @@ -2607,6 +2607,8 @@ void mmc_rescan(struct work_struct *work)
>>>
>>>         /* if there still is a card present, stop here */
>>>         if (host->bus_ops != NULL) {
>>> +               if (tuning_is_enabled_before())
>>> +                       mmc_retune_enable(host);
>>>                 mmc_bus_put(host);
>>>                 goto out;
>>>         }
>>>
>>>
>>>> Do you have an actual problem with the way it works now?
>>>>
>>>
>>> No actual problems now.
>>
>> So let's not spend time on it.
>>
>>> I just observe a lot tuning commands keep sending although the card is already
>>> removed which seems a bit meaningless.
>>> And most tuning execution process is executed with sin_lock_irqsave, i'm not
>>> sure if the mass tuning commands may affect the system when CPU is busy.
>>> What do you think?
>>
>> sdhci spin lock is unlocked while waiting for tuning commands.
>>
> 
> It's 40 commands continuously and only cmd transfer time is unlocked.

Not for sdhci_execute_tuning() it's not.  Only one command is sent.
Currently we don't even send the CMD13 because we check card detect first.
I added prints for sdhci_execute_tuning and got this:

[  255.536326] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000080
[  255.743653] mmc1: starting CMD13 arg 59b40000 flags 00000195
[  255.750093] mmc1: sdhci_execute_tuning
[  255.754358] mmc1: sdhci_execute_tuning: send command
[  255.809638] sdhci: Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock
[  255.824810] mmc1: req failed (CMD13): -123, retrying...
[  255.832766] mmc1: req failed (CMD13): -123, retrying...
[  255.840722] mmc1: req failed (CMD13): -123, retrying...
[  255.848672] mmc1: req done (CMD13): -123: 00000000 00000000 00000000 00000000
[  255.856773] mmc1: card remove detected
[  255.861056] mmc1: card 59b4 removed
[  255.872872] mmc1: clock 0Hz busmode 2 powermode 0 cs 0 Vdd 0 width 0 timing 0

> 
> Hmm.. I can't sure it's no affection.
> e.g we did have customers reporting cd plug in/out causing jitters
> when system is busy playing audio or video.
> Maybe we need to do those tests.
> 
> Anyway, what's your point to keep sending tuning commands after card
> is already removed?

Seems like a problem for your driver not the core.  Why not check card detect
after the first error in esdhc_executing_tuning().

> 
> Regards
> Dong Aisheng
> 
>>>
>>> Regards
>>> Dong Aisheng
>>>
>>>>>
>>>>> CC: stable <stable@vger.kernel.org>
>>>>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>>>>> ---
>>>>>  drivers/mmc/core/core.c | 1 +
>>>>>  1 file changed, 1 insertion(+)
>>>>>
>>>>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
>>>>> index 52bfaf0..76d0802 100644
>>>>> --- a/drivers/mmc/core/core.c
>>>>> +++ b/drivers/mmc/core/core.c
>>>>> @@ -1888,6 +1888,7 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
>>>>>               pm_wakeup_event(mmc_dev(host), 5000);
>>>>>
>>>>>       host->detect_change = 1;
>>>>> +     mmc_retune_disable(host);
>>>>>       mmc_schedule_delayed_work(&host->detect, delay);
>>>>>  }
>>>>>
>>>>>
>>>>
>>>
>>
>> --
>> 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
> 

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

* Re: [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
  2016-04-28 14:28                   ` Dong Aisheng
@ 2016-04-29  7:32                     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-29  7:32 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On 28/04/16 17:28, Dong Aisheng wrote:
> On Thu, Apr 28, 2016 at 04:36:25PM +0300, Adrian Hunter wrote:
>> On 28/04/16 16:14, Dong Aisheng wrote:
>>> On Thu, Apr 28, 2016 at 09:39:54AM +0300, Adrian Hunter wrote:
>>>> On 28/04/16 06:09, Dong Aisheng wrote:
>>>>> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
>>>>>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
>>>>>>> Hi Adrian,
>>>>>>>
>>>>>>> Thanks for the review first.
>>>>>>>
>>>>>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>>>>>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>>>>>>> Handle host and regulator signal voltage switch separately.
>>>>>>>>> Move host signal voltage switch code into a separated function
>>>>>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
>>>>>>>>> remove the regulator voltage switch code and use the common
>>>>>>>>> mmc_regulator_set_vqmmc() instead.
>>>>>>>>
>>>>>>>> You have changed the order that things are done.
>>>>>>>
>>>>>>> Yes, the oder changes a bit that we always do controller voltage switch first.
>>>>>>> I suppose the order is irrelevant here since i don't recall any
>>>>>>> requirement from card.
>>>>>>>
>>>>>>> Actually the original order is also a bit mass.
>>>>>>> e.g.
>>>>>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
>>>>>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
>>>>>>> It looks to us the original one also order irrelevant.
>>>>>>>
>>>>>>>> There is no way to know
>>>>>>>> what that will break, so let's not do that.  What about just changing
>>>>>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
>>>>>>>>
>>>>>>>
>>>>>>> Currently what i can think out VIO switch using are three cases: (Pls
>>>>>>> help add if any)
>>>>>>> 1) Both host IO and card IO use external vqmmc to do switch
>>>>>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
>>>>>>>
>>>>>>> eMMC has no IO voltage switch protocol and requirement, so usually
>>>>>>> board designed
>>>>>>> using fixed 1.8V for eMMC and host IO.
>>>>>>> Event it's switchable, it should be done in the first mmc_power_up().
>>>>>>> Dynamical switch later may cause eMMC unable to work properly.
>>>>>>> (We have been confirmed about this issue by many eMMC vendors
>>>>>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
>>>>>>> still doing VIO dynamical switch for eMMC, if yes, please help share
>>>>>>> the experience!).
>>>>>>>
>>>>>>> Event some people still do dynamical IO switch for eMMC, since eMMC
>>>>>>> spec has no requirement, so the order should also not care.
>>>>>>>
>>>>>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
>>>>>>>
>>>>>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
>>>>>>> regulator to do card IO voltage switch. It does not use external vqmmc
>>>>>>> regulator.
>>>>>>> So order irrelevant too.
>>>>>>>
>>>>>>> 3) Host using controller IO switch while card using external vqmmc
>>>>>>> (special SDIO3.0 or eMMC)
>>>>>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
>>>>>>> the spec and using external regulator for card IO voltage.
>>>>>>> Usually it's required to fix to 1.8v and also not order irrelevant.
>>>>>>>
>>>>>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
>>>>>>>
>>>>>>> So it looks all cases seems are not order required.
>>>>>>
>>>>>> I don't agree that there is any way to know that other host controllers
>>>>>> are not affected.  I don't want a repeat of sdhci_set_power().
>>>>>>
>>>>>
>>>>> Can you share some more info about sdhci_set_power() issue?
>>>>> I'd like to see if we are same the issue.
>>>>
>>>> Not the same issue, but the same concept.  People changing the code under
>>>> the impression that their way was correct, and then breaking other people's
>>>> drivers.  Check the git history and mailing list.
>>>>
>>>> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
>>>>
>>>
>>> Yes, now i understand your concern.
>>>
>>>>>
>>>>> BTW, IMHO i don't think we should stop keep moving only afraid of potential
>>>>> break if it's correct way. Because .start_signal_voltage_switch() interface
>>>>> seems shouldn't be order dependant.
>>>>> If it is, then it should be fixed and handled in high layer like MMC core
>>>>> rather than in host driver. Right?
>>>>
>>>> The SDHCI spec. does not define how to use external regulators, so there is
>>>> no "correct way".
>>>>
>>>
>>> The "correct way" i mean here is .start_signal_voltage_switch() shouldn't be
>>> order dependant, would you agree?
>>
>> No.  There is no way to know if the regulator must be switched before or
>> after the host controller register is changed.
>>
> 
> Hmm... If there is no way to know the correct order, how can we
> assume the exist order is correct?

There is no correct order.  This is outside the SDHCI spec. and so belongs
to individual drivers.

If it mattered we could push the ugly code down onto the drivers, and then
driver maintainers could opt to use the new pretty code.  However at the
moment there is a lot more important work, so I would want to avoid that
code churn.

> And i already pointed out, the exist order is also confused that
> it switch controller first then vqmmc for 3.3v and switch vqmmc
> first, then controller for 1.8v
> 
> If we can't sure the exist order is correct, why do we block
> the changing to correctly use mmc_regulator_set_vqmmc() to
> improve the driver stability?

Not sure what you mean here.  I have already showed how we can use
mmc_regulator_set_vqmmc().

> 
> And actually the change is not made arbitrarily, i already list
> all possibilities based on my knowledge. People can raise more
> if any.

You are assuming every driver has a maintainer and every maintainer is
following this thread, and understands how it might affect all the
different versions of their hardware.  That is extremely unlikely.

> The target is correct that we make start_signal_voltage_switch()
> order independant.
> It's worth a try even there's a potential very low possibility
> break IMHO.

And so we disagree.

Aren't your needs met by changing to use mmc_regulator_set_vqmmc() the way I
suggested?

> 
> Or else if we can find a better way to switch to
> mmc_regulator_set_vqmmc i would also love to try.
>  
> Maybe we need more people's thought on it!
> 
> Ulf,
> Would you give some inputs?
> 
> Regards
> Dong Aisheng
> 
>>>
>>>> We have to move forward *and* avoid potential breakage.
>>>>
>>>
>>> If really break happens, fix platform driver, not common SDHCI.
>>> That's the same thing you done for sdhci_set_power().
>>
>> In that case the original behaviour was kept in the common SDHCI code and
>> the driver had to provide its own way.
>>
>>>
>>>> In this case it seems me that the risk of breakage outweighs the value of
>>>> prettier code.
>>>>
>>>
>>> Actually my main purpose is patch 6: using mmc_regulator_set_vqmmc()
>>> which is worth and it does improve the stability and eliminate the
>>> potential signal issue.
>>> However it's not the same way as you proposed.
>>> See below.
>>>
>>>> By the way, there are ways to get rid of the ugliness - such as pushing it down
>>>> into individual drivers.
>>>>
>>>>>
>>>>>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
>>>>>> in place of regulator_set_voltage().
>>>>>
>>>>> Just using mmc_regulator_set_vqmmc() also changes the order which
>>>>> is the same situation.
>>>>
>>>> How so?  It looks like a drop-in replacement to me:
>>>>
>>>
>>> Sorry, i did not get that you want to change like below.
>>> However, it looks that it does not make too much sense to call
>>> mmc_regulator_set_vqmmc() for each VOLTAGE type like 3.3v/1.8v/1.2v
>>> which introduces ugliness because mmc_regulator_set_vqmmc()
>>> already handles it internally, right?
>>> Only because we want to keep an "ASSUMED" order as before?
>>
>> Yes
>>
>>>
>>> Regards
>>> Dong Aisheng
>>>
>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>>> index 94cffa77490a..69b4d48aff87 100644
>>>> --- a/drivers/mmc/host/sdhci.c
>>>> +++ b/drivers/mmc/host/sdhci.c
>>>> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>>>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>>>  
>>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
>>>> -						    3600000);
>>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>  			if (ret) {
>>>>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>>>>  					mmc_hostname(mmc));
>>>> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>>>  		return -EAGAIN;
>>>>  	case MMC_SIGNAL_VOLTAGE_180:
>>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
>>>> -					1700000, 1950000);
>>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>  			if (ret) {
>>>>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>>>>  					mmc_hostname(mmc));
>>>> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>>>  		return -EAGAIN;
>>>>  	case MMC_SIGNAL_VOLTAGE_120:
>>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
>>>> -						    1300000);
>>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>  			if (ret) {
>>>>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>>>>  					mmc_hostname(mmc));
>>>>
>>>>
>>>>
>>>
>>
> 


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

* [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
@ 2016-04-29  7:32                     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-04-29  7:32 UTC (permalink / raw)
  To: linux-arm-kernel

On 28/04/16 17:28, Dong Aisheng wrote:
> On Thu, Apr 28, 2016 at 04:36:25PM +0300, Adrian Hunter wrote:
>> On 28/04/16 16:14, Dong Aisheng wrote:
>>> On Thu, Apr 28, 2016 at 09:39:54AM +0300, Adrian Hunter wrote:
>>>> On 28/04/16 06:09, Dong Aisheng wrote:
>>>>> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
>>>>>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
>>>>>>> Hi Adrian,
>>>>>>>
>>>>>>> Thanks for the review first.
>>>>>>>
>>>>>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>>>>>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>>>>>>> Handle host and regulator signal voltage switch separately.
>>>>>>>>> Move host signal voltage switch code into a separated function
>>>>>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
>>>>>>>>> remove the regulator voltage switch code and use the common
>>>>>>>>> mmc_regulator_set_vqmmc() instead.
>>>>>>>>
>>>>>>>> You have changed the order that things are done.
>>>>>>>
>>>>>>> Yes, the oder changes a bit that we always do controller voltage switch first.
>>>>>>> I suppose the order is irrelevant here since i don't recall any
>>>>>>> requirement from card.
>>>>>>>
>>>>>>> Actually the original order is also a bit mass.
>>>>>>> e.g.
>>>>>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
>>>>>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
>>>>>>> It looks to us the original one also order irrelevant.
>>>>>>>
>>>>>>>> There is no way to know
>>>>>>>> what that will break, so let's not do that.  What about just changing
>>>>>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
>>>>>>>>
>>>>>>>
>>>>>>> Currently what i can think out VIO switch using are three cases: (Pls
>>>>>>> help add if any)
>>>>>>> 1) Both host IO and card IO use external vqmmc to do switch
>>>>>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
>>>>>>>
>>>>>>> eMMC has no IO voltage switch protocol and requirement, so usually
>>>>>>> board designed
>>>>>>> using fixed 1.8V for eMMC and host IO.
>>>>>>> Event it's switchable, it should be done in the first mmc_power_up().
>>>>>>> Dynamical switch later may cause eMMC unable to work properly.
>>>>>>> (We have been confirmed about this issue by many eMMC vendors
>>>>>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
>>>>>>> still doing VIO dynamical switch for eMMC, if yes, please help share
>>>>>>> the experience!).
>>>>>>>
>>>>>>> Event some people still do dynamical IO switch for eMMC, since eMMC
>>>>>>> spec has no requirement, so the order should also not care.
>>>>>>>
>>>>>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
>>>>>>>
>>>>>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
>>>>>>> regulator to do card IO voltage switch. It does not use external vqmmc
>>>>>>> regulator.
>>>>>>> So order irrelevant too.
>>>>>>>
>>>>>>> 3) Host using controller IO switch while card using external vqmmc
>>>>>>> (special SDIO3.0 or eMMC)
>>>>>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
>>>>>>> the spec and using external regulator for card IO voltage.
>>>>>>> Usually it's required to fix to 1.8v and also not order irrelevant.
>>>>>>>
>>>>>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
>>>>>>>
>>>>>>> So it looks all cases seems are not order required.
>>>>>>
>>>>>> I don't agree that there is any way to know that other host controllers
>>>>>> are not affected.  I don't want a repeat of sdhci_set_power().
>>>>>>
>>>>>
>>>>> Can you share some more info about sdhci_set_power() issue?
>>>>> I'd like to see if we are same the issue.
>>>>
>>>> Not the same issue, but the same concept.  People changing the code under
>>>> the impression that their way was correct, and then breaking other people's
>>>> drivers.  Check the git history and mailing list.
>>>>
>>>> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
>>>>
>>>
>>> Yes, now i understand your concern.
>>>
>>>>>
>>>>> BTW, IMHO i don't think we should stop keep moving only afraid of potential
>>>>> break if it's correct way. Because .start_signal_voltage_switch() interface
>>>>> seems shouldn't be order dependant.
>>>>> If it is, then it should be fixed and handled in high layer like MMC core
>>>>> rather than in host driver. Right?
>>>>
>>>> The SDHCI spec. does not define how to use external regulators, so there is
>>>> no "correct way".
>>>>
>>>
>>> The "correct way" i mean here is .start_signal_voltage_switch() shouldn't be
>>> order dependant, would you agree?
>>
>> No.  There is no way to know if the regulator must be switched before or
>> after the host controller register is changed.
>>
> 
> Hmm... If there is no way to know the correct order, how can we
> assume the exist order is correct?

There is no correct order.  This is outside the SDHCI spec. and so belongs
to individual drivers.

If it mattered we could push the ugly code down onto the drivers, and then
driver maintainers could opt to use the new pretty code.  However at the
moment there is a lot more important work, so I would want to avoid that
code churn.

> And i already pointed out, the exist order is also confused that
> it switch controller first then vqmmc for 3.3v and switch vqmmc
> first, then controller for 1.8v
> 
> If we can't sure the exist order is correct, why do we block
> the changing to correctly use mmc_regulator_set_vqmmc() to
> improve the driver stability?

Not sure what you mean here.  I have already showed how we can use
mmc_regulator_set_vqmmc().

> 
> And actually the change is not made arbitrarily, i already list
> all possibilities based on my knowledge. People can raise more
> if any.

You are assuming every driver has a maintainer and every maintainer is
following this thread, and understands how it might affect all the
different versions of their hardware.  That is extremely unlikely.

> The target is correct that we make start_signal_voltage_switch()
> order independant.
> It's worth a try even there's a potential very low possibility
> break IMHO.

And so we disagree.

Aren't your needs met by changing to use mmc_regulator_set_vqmmc() the way I
suggested?

> 
> Or else if we can find a better way to switch to
> mmc_regulator_set_vqmmc i would also love to try.
>  
> Maybe we need more people's thought on it!
> 
> Ulf,
> Would you give some inputs?
> 
> Regards
> Dong Aisheng
> 
>>>
>>>> We have to move forward *and* avoid potential breakage.
>>>>
>>>
>>> If really break happens, fix platform driver, not common SDHCI.
>>> That's the same thing you done for sdhci_set_power().
>>
>> In that case the original behaviour was kept in the common SDHCI code and
>> the driver had to provide its own way.
>>
>>>
>>>> In this case it seems me that the risk of breakage outweighs the value of
>>>> prettier code.
>>>>
>>>
>>> Actually my main purpose is patch 6: using mmc_regulator_set_vqmmc()
>>> which is worth and it does improve the stability and eliminate the
>>> potential signal issue.
>>> However it's not the same way as you proposed.
>>> See below.
>>>
>>>> By the way, there are ways to get rid of the ugliness - such as pushing it down
>>>> into individual drivers.
>>>>
>>>>>
>>>>>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
>>>>>> in place of regulator_set_voltage().
>>>>>
>>>>> Just using mmc_regulator_set_vqmmc() also changes the order which
>>>>> is the same situation.
>>>>
>>>> How so?  It looks like a drop-in replacement to me:
>>>>
>>>
>>> Sorry, i did not get that you want to change like below.
>>> However, it looks that it does not make too much sense to call
>>> mmc_regulator_set_vqmmc() for each VOLTAGE type like 3.3v/1.8v/1.2v
>>> which introduces ugliness because mmc_regulator_set_vqmmc()
>>> already handles it internally, right?
>>> Only because we want to keep an "ASSUMED" order as before?
>>
>> Yes
>>
>>>
>>> Regards
>>> Dong Aisheng
>>>
>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>>> index 94cffa77490a..69b4d48aff87 100644
>>>> --- a/drivers/mmc/host/sdhci.c
>>>> +++ b/drivers/mmc/host/sdhci.c
>>>> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>>>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>>>  
>>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
>>>> -						    3600000);
>>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>  			if (ret) {
>>>>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>>>>  					mmc_hostname(mmc));
>>>> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>>>  		return -EAGAIN;
>>>>  	case MMC_SIGNAL_VOLTAGE_180:
>>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
>>>> -					1700000, 1950000);
>>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>  			if (ret) {
>>>>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>>>>  					mmc_hostname(mmc));
>>>> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>>>>  		return -EAGAIN;
>>>>  	case MMC_SIGNAL_VOLTAGE_120:
>>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
>>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
>>>> -						    1300000);
>>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>  			if (ret) {
>>>>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
>>>>  					mmc_hostname(mmc));
>>>>
>>>>
>>>>
>>>
>>
> 

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

* Re: [PATCH 10/23] mmc: core: disable auto retune during card detection process
  2016-04-29  6:54             ` Adrian Hunter
@ 2016-04-29  7:42               ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-29  7:42 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On Fri, Apr 29, 2016 at 09:54:13AM +0300, Adrian Hunter wrote:
> On 28/04/16 16:22, Dong Aisheng wrote:
> > On Thu, Apr 28, 2016 at 10:04:34AM +0300, Adrian Hunter wrote:
> >> On 24/04/16 13:47, Dong Aisheng wrote:
> >>> On Fri, Apr 22, 2016 at 8:48 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> >>>> On 15/04/16 20:29, Dong Aisheng wrote:
> >>>>> During card detection process, mmc core may sends commands
> >>>>> to detect if card is still exist in mmc_rescan for removable
> >>>>> card which may trigger mmc retuning process after a bit time
> >>>>> of runtime pm suspend.
> >>>>> Obviously this retuning process is meaningless for card remove
> >>>>> case, so we disable mmc_retune in mmc_detect_change() for it.
> >>>>> For card insert case, the mmc_retune will be enabled normally
> >>>>> in its card initialization process later in mmc_execute_tuning().
> >>>>> So disable it at first has no side effection.
> >>>>
> >>>> We don't assume that the card has been removed, which is why we send
> >>>> commands to find out if it is still there.  If it is still there, this
> >>>> change will have incorrectly disabled re-tuning.
> >>>>
> >>>
> >>> Do you mean the 'fake' card remove interrupt like caused by glitch?
> >>
> >> Sure
> >>
> >>> Yes, if that the card is still exist and re-tuning is wrongly disabled.
> >>>
> >>> So we could re-enable re-tuning for this special case?
> >>> Something like:
> >>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> >>> index 41b1e76..e1990a8 100644
> >>> --- a/drivers/mmc/core/core.c
> >>> +++ b/drivers/mmc/core/core.c
> >>> @@ -2607,6 +2607,8 @@ void mmc_rescan(struct work_struct *work)
> >>>
> >>>         /* if there still is a card present, stop here */
> >>>         if (host->bus_ops != NULL) {
> >>> +               if (tuning_is_enabled_before())
> >>> +                       mmc_retune_enable(host);
> >>>                 mmc_bus_put(host);
> >>>                 goto out;
> >>>         }
> >>>
> >>>
> >>>> Do you have an actual problem with the way it works now?
> >>>>
> >>>
> >>> No actual problems now.
> >>
> >> So let's not spend time on it.
> >>
> >>> I just observe a lot tuning commands keep sending although the card is already
> >>> removed which seems a bit meaningless.
> >>> And most tuning execution process is executed with sin_lock_irqsave, i'm not
> >>> sure if the mass tuning commands may affect the system when CPU is busy.
> >>> What do you think?
> >>
> >> sdhci spin lock is unlocked while waiting for tuning commands.
> >>
> > 
> > It's 40 commands continuously and only cmd transfer time is unlocked.
> 
> Not for sdhci_execute_tuning() it's not.  Only one command is sent.

IMX case is different.
Please see below log on MX6SX SDB.

For IMX6SX SDB:
root@imx6qdlsolo:~# [   39.649322] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[   39.661452] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 6
[   39.668295] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[   39.679146] mmc1: starting CMD13 arg e6240000 flags 00000195
[   39.684908] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.693359] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.701654] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.709717] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.717718] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.725057] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.734818] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.744197] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.752316] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.760363] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.778296] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.788348] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.795731] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.803932] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.811865] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.819801] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.827710] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.835046] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.843384] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.851293] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.859209] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.867111] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.874450] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.882725] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.890610] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.898615] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.905953] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.913821] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.922283] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.930177] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.938082] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.945676] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.953696] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.961914] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.969792] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.977682] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.985018] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.992898] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   40.001107] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   40.009125] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   40.018058] mmc1: req failed (CMD13): -123, retrying...
[   40.023435] mmc1: req failed (CMD13): -123, retrying...
[   40.029614] mmc1: req failed (CMD13): -123, retrying...
[   40.034981] mmc1: req done (CMD13): -123: 00000000 00000000 00000000 00000000
[   40.042891] mmc1: card remove detected
[   40.047446] mmc1: card e624 removed
[   40.208083] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[   40.222000] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 6
[   40.228813] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[   40.238175] mmc1: clock 0Hz busmode 2 powermode 0 cs 0 Vdd 0 width 1 timing 0
[   40.247693] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 0


And IMX6DL ARD is even worser due to it's using common
mmc_send_tuning() function.
root@imx6qdlsolo:~# 
root@imx6qdlsolo:~# [  129.462564] sysrq: SysRq : Changing Loglevel
[  129.466902] sysrq: Loglevel set to 8
[  131.616078] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[  131.625311] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 6
[  131.632133] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[  131.642121] mmc0: starting CMD13 arg 59b40000 flags 00000195
[  131.648925] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x0 ESDHC_TUNE_CTRL_STATUS 0x0
[  131.657818] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.663518] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.670835] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.678069] mmc0:     0 bytes transferred: 0
[  131.683433] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x1 ESDHC_TUNE_CTRL_STATUS 0x1000100
[  131.692940] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.698709] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.705625] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.712854] mmc0:     0 bytes transferred: 0
[  131.718251] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x2 ESDHC_TUNE_CTRL_STATUS 0x2000200
[  131.727375] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.733074] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.740043] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.747256] mmc0:     0 bytes transferred: 0
[  131.752611] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x3 ESDHC_TUNE_CTRL_STATUS 0x3000300
[  131.761751] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.767506] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.774419] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.781642] mmc0:     0 bytes transferred: 0
[  131.787035] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x4 ESDHC_TUNE_CTRL_STATUS 0x4000400
[  131.796156] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.801851] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.808832] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.816037] mmc0:     0 bytes transferred: 0
[  131.821389] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x5 ESDHC_TUNE_CTRL_STATUS 0x5000500
[  131.830503] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.836254] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.843162] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.850385] mmc0:     0 bytes transferred: 0
[  131.855737] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x6 ESDHC_TUNE_CTRL_STATUS 0x6000600
[  131.864863] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.870613] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.877565] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.884728] mmc0:     0 bytes transferred: 0
[  131.890133] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x7 ESDHC_TUNE_CTRL_STATUS 0x7000700
[  131.899247] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.904939] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.911903] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.919122] mmc0:     0 bytes transferred: 0
[  131.924474] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x8 ESDHC_TUNE_CTRL_STATUS 0x8000800
[  131.933591] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.939340] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.946300] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.953464] mmc0:     0 bytes transferred: 0
[  131.958869] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x9 ESDHC_TUNE_CTRL_STATUS 0x9000900
[  131.967965] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.973657] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.980621] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.987831] mmc0:     0 bytes transferred: 0
[  131.993183] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0xa ESDHC_TUNE_CTRL_STATUS 0xa000a00
[  132.002295] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.008039] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.014945] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.022167] mmc0:     0 bytes transferred: 0
[  132.027555] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0xb ESDHC_TUNE_CTRL_STATUS 0xb000b00
[  132.036682] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.042376] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.049341] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.056555] mmc0:     0 bytes transferred: 0
[  132.061905] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0xc ESDHC_TUNE_CTRL_STATUS 0xc000c00
[  132.071020] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.076760] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.083663] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.090886] mmc0:     0 bytes transferred: 0
[  132.096237] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0xd ESDHC_TUNE_CTRL_STATUS 0xd000d00
[  132.105233] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.110981] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.117911] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.125072] mmc0:     0 bytes transferred: 0
[  132.130494] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0xe ESDHC_TUNE_CTRL_STATUS 0xe000e00
[  132.139538] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.145227] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.152185] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.159403] mmc0:     0 bytes transferred: 0
[  132.164755] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0xf ESDHC_TUNE_CTRL_STATUS 0xf000f00
[  132.173884] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.179622] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.186579] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.193743] mmc0:     0 bytes transferred: 0
[  132.199157] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x10 ESDHC_TUNE_CTRL_STATUS 0x10001000
[  132.208432] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.214124] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.221088] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.228308] mmc0:     0 bytes transferred: 0
[  132.233658] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x11 ESDHC_TUNE_CTRL_STATUS 0x11001100
[  132.242930] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.248677] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.255584] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.262803] mmc0:     0 bytes transferred: 0
[  132.268190] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x12 ESDHC_TUNE_CTRL_STATUS 0x12001200
[  132.277483] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.283184] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.290171] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.297385] mmc0:     0 bytes transferred: 0
[  132.302737] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x13 ESDHC_TUNE_CTRL_STATUS 0x13001300
[  132.312043] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.317786] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.324697] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.331920] mmc0:     0 bytes transferred: 0
[  132.337308] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x14 ESDHC_TUNE_CTRL_STATUS 0x14001400
[  132.346604] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.352297] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.359271] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.366482] mmc0:     0 bytes transferred: 0
[  132.371833] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x15 ESDHC_TUNE_CTRL_STATUS 0x15001500
[  132.381125] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.386867] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.393773] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.400990] mmc0:     0 bytes transferred: 0
[  132.406344] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x16 ESDHC_TUNE_CTRL_STATUS 0x16001600
[  132.415517] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.421265] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.428214] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.435375] mmc0:     0 bytes transferred: 0
[  132.440827] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x17 ESDHC_TUNE_CTRL_STATUS 0x17001700
[  132.450046] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.455736] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.462696] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.469914] mmc0:     0 bytes transferred: 0
[  132.475264] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x18 ESDHC_TUNE_CTRL_STATUS 0x18001800
[  132.484554] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.490299] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.497255] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.504419] mmc0:     0 bytes transferred: 0
[  132.509826] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x19 ESDHC_TUNE_CTRL_STATUS 0x19001900
[  132.519096] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.524786] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.531751] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.538971] mmc0:     0 bytes transferred: 0
[  132.544322] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x1a ESDHC_TUNE_CTRL_STATUS 0x1a001a00
[  132.553609] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.559357] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.566325] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.573488] mmc0:     0 bytes transferred: 0
[  132.578898] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x1b ESDHC_TUNE_CTRL_STATUS 0x1b001b00
[  132.588168] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.593861] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.600820] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.608037] mmc0:     0 bytes transferred: 0
[  132.613390] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x1c ESDHC_TUNE_CTRL_STATUS 0x1c001c00
[  132.622680] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.628428] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.635334] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.642556] mmc0:     0 bytes transferred: 0
[  132.647945] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x1d ESDHC_TUNE_CTRL_STATUS 0x1d001d00
[  132.657231] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.662930] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.669892] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.677099] mmc0:     0 bytes transferred: 0
[  132.682450] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x1e ESDHC_TUNE_CTRL_STATUS 0x1e001e00
[  132.691737] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.697490] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.704403] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.711624] mmc0:     0 bytes transferred: 0
[  132.717010] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x1f ESDHC_TUNE_CTRL_STATUS 0x1f001f00
[  132.726301] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.731998] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.738960] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.746169] mmc0:     0 bytes transferred: 0
[  132.751525] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x20 ESDHC_TUNE_CTRL_STATUS 0x20002000
[  132.760817] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.766577] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.773491] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.780714] mmc0:     0 bytes transferred: 0
[  132.786069] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x21 ESDHC_TUNE_CTRL_STATUS 0x21002100
[  132.795243] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.800992] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.807923] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.815084] mmc0:     0 bytes transferred: 0
[  132.820546] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x22 ESDHC_TUNE_CTRL_STATUS 0x22002200
[  132.829787] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.835477] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.842441] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.849663] mmc0:     0 bytes transferred: 0
[  132.855016] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x23 ESDHC_TUNE_CTRL_STATUS 0x23002300
[  132.864305] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.870056] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.877015] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.884179] mmc0:     0 bytes transferred: 0
[  132.889584] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x24 ESDHC_TUNE_CTRL_STATUS 0x24002400
[  132.898860] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.904551] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.911512] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.918731] mmc0:     0 bytes transferred: 0
[  132.924080] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x25 ESDHC_TUNE_CTRL_STATUS 0x25002500
[  132.933368] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.939114] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.946071] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.953235] mmc0:     0 bytes transferred: 0
[  132.958640] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x26 ESDHC_TUNE_CTRL_STATUS 0x26002600
[  132.967924] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.973614] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.980584] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.987796] mmc0:     0 bytes transferred: 0
[  132.993147] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x27 ESDHC_TUNE_CTRL_STATUS 0x27002700
[  133.002433] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.008181] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.015089] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.022310] mmc0:     0 bytes transferred: 0
[  133.027699] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x28 ESDHC_TUNE_CTRL_STATUS 0x28002800
[  133.037014] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.042712] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.049679] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.056890] mmc0:     0 bytes transferred: 0
[  133.062237] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x29 ESDHC_TUNE_CTRL_STATUS 0x29002900
[  133.071525] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.077267] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.084172] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.091392] mmc0:     0 bytes transferred: 0
[  133.096746] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x2a ESDHC_TUNE_CTRL_STATUS 0x2a002a00
[  133.106021] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.111714] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.118679] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.125889] mmc0:     0 bytes transferred: 0
[  133.131241] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x2b ESDHC_TUNE_CTRL_STATUS 0x2b002b00
[  133.140530] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.146272] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.153184] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.160409] mmc0:     0 bytes transferred: 0
[  133.165762] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x2c ESDHC_TUNE_CTRL_STATUS 0x2c002c00
[  133.175059] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.180798] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.187759] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.194922] mmc0:     0 bytes transferred: 0
[  133.200329] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x2d ESDHC_TUNE_CTRL_STATUS 0x2d002d00
[  133.209600] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.215291] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.222254] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.229474] mmc0:     0 bytes transferred: 0
[  133.234823] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x2e ESDHC_TUNE_CTRL_STATUS 0x2e002e00
[  133.244124] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.249865] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.256828] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.263991] mmc0:     0 bytes transferred: 0
[  133.269395] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x2f ESDHC_TUNE_CTRL_STATUS 0x2f002f00
[  133.278668] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.284361] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.291340] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.298566] mmc0:     0 bytes transferred: 0
[  133.303922] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x30 ESDHC_TUNE_CTRL_STATUS 0x30003000
[  133.313213] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.318975] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.325939] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.333103] mmc0:     0 bytes transferred: 0
[  133.338506] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x31 ESDHC_TUNE_CTRL_STATUS 0x31003100
[  133.347792] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.353484] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.360450] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.367661] mmc0:     0 bytes transferred: 0
[  133.373010] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x32 ESDHC_TUNE_CTRL_STATUS 0x32003200
[  133.382312] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.388059] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.394965] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.402178] mmc0:     0 bytes transferred: 0
[  133.407573] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x33 ESDHC_TUNE_CTRL_STATUS 0x33003300
[  133.416864] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.422560] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.429523] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.436727] mmc0:     0 bytes transferred: 0
[  133.442079] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x34 ESDHC_TUNE_CTRL_STATUS 0x34003400
[  133.451364] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.457116] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.464027] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.471251] mmc0:     0 bytes transferred: 0
[  133.476608] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x35 ESDHC_TUNE_CTRL_STATUS 0x35003500
[  133.485780] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.491574] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.498529] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.505693] mmc0:     0 bytes transferred: 0
[  133.511177] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x36 ESDHC_TUNE_CTRL_STATUS 0x36003600
[  133.520407] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.526149] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.533061] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.540285] mmc0:     0 bytes transferred: 0
[  133.545638] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x37 ESDHC_TUNE_CTRL_STATUS 0x37003700
[  133.554931] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.560681] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.567639] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.574802] mmc0:     0 bytes transferred: 0
[  133.580206] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x38 ESDHC_TUNE_CTRL_STATUS 0x38003800
[  133.589493] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.595185] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.602144] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.609359] mmc0:     0 bytes transferred: 0
[  133.614712] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x39 ESDHC_TUNE_CTRL_STATUS 0x39003900
[  133.624000] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.629754] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.636727] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.643891] mmc0:     0 bytes transferred: 0
[  133.649293] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x3a ESDHC_TUNE_CTRL_STATUS 0x3a003a00
[  133.658567] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.664259] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.671225] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.678445] mmc0:     0 bytes transferred: 0
[  133.683798] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x3b ESDHC_TUNE_CTRL_STATUS 0x3b003b00
[  133.693086] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.698824] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.705728] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.712950] mmc0:     0 bytes transferred: 0
[  133.718336] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x3c ESDHC_TUNE_CTRL_STATUS 0x3c003c00
[  133.727625] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.733322] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.740287] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.747498] mmc0:     0 bytes transferred: 0
[  133.752851] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x3d ESDHC_TUNE_CTRL_STATUS 0x3d003d00
[  133.762139] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.767913] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.774827] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.782051] mmc0:     0 bytes transferred: 0
[  133.787438] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x3e ESDHC_TUNE_CTRL_STATUS 0x3e003e00
[  133.796727] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.802421] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.809397] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.816617] mmc0:     0 bytes transferred: 0
[  133.821967] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x3f ESDHC_TUNE_CTRL_STATUS 0x3f003f00
[  133.831258] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.837001] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.843909] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.851122] mmc0:     0 bytes transferred: 0
[  133.856476] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x40 ESDHC_TUNE_CTRL_STATUS 0x40004000
[  133.865647] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.871395] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.878332] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.885495] mmc0:     0 bytes transferred: 0
[  133.890922] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x41 ESDHC_TUNE_CTRL_STATUS 0x41004100
[  133.900145] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.905886] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.912795] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.920018] mmc0:     0 bytes transferred: 0
[  133.925371] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x42 ESDHC_TUNE_CTRL_STATUS 0x42004200
[  133.934662] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.940411] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.947371] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.954536] mmc0:     0 bytes transferred: 0
[  133.959943] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x43 ESDHC_TUNE_CTRL_STATUS 0x43004300
[  133.969217] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.974908] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.981871] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.989092] mmc0:     0 bytes transferred: 0
[  133.994441] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x44 ESDHC_TUNE_CTRL_STATUS 0x44004400
[  134.003714] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.009465] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.016434] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.023598] mmc0:     0 bytes transferred: 0
[  134.029006] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x45 ESDHC_TUNE_CTRL_STATUS 0x45004500
[  134.038294] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.043984] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.050936] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.058150] mmc0:     0 bytes transferred: 0
[  134.063501] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x46 ESDHC_TUNE_CTRL_STATUS 0x46004600
[  134.072790] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.078541] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.085447] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.092664] mmc0:     0 bytes transferred: 0
[  134.098068] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x47 ESDHC_TUNE_CTRL_STATUS 0x47004700
[  134.107355] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.113053] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.120021] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.127231] mmc0:     0 bytes transferred: 0
[  134.132580] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x48 ESDHC_TUNE_CTRL_STATUS 0x48004800
[  134.141866] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.147617] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.154527] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.161749] mmc0:     0 bytes transferred: 0
[  134.167137] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x49 ESDHC_TUNE_CTRL_STATUS 0x49004900
[  134.176430] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.182129] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.189101] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.196310] mmc0:     0 bytes transferred: 0
[  134.201660] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x4a ESDHC_TUNE_CTRL_STATUS 0x4a004a00
[  134.210944] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.216683] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.223586] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.230807] mmc0:     0 bytes transferred: 0
[  134.236162] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x4b ESDHC_TUNE_CTRL_STATUS 0x4b004b00
[  134.245335] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.251076] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.258013] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.265177] mmc0:     0 bytes transferred: 0
[  134.270609] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x4c ESDHC_TUNE_CTRL_STATUS 0x4c004c00
[  134.279849] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.285539] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.292509] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.299730] mmc0:     0 bytes transferred: 0
[  134.305087] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x4d ESDHC_TUNE_CTRL_STATUS 0x4d004d00
[  134.314397] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.320147] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.327115] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.334281] mmc0:     0 bytes transferred: 0
[  134.339692] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x4e ESDHC_TUNE_CTRL_STATUS 0x4e004e00
[  134.348979] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.354671] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.361642] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.368858] mmc0:     0 bytes transferred: 0
[  134.374209] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x4f ESDHC_TUNE_CTRL_STATUS 0x4f004f00
[  134.383503] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.389253] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.396215] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.403378] mmc0:     0 bytes transferred: 0
[  134.408785] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x50 ESDHC_TUNE_CTRL_STATUS 0x50005000
[  134.418057] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.423747] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.430706] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.437930] mmc0:     0 bytes transferred: 0
[  134.443285] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x51 ESDHC_TUNE_CTRL_STATUS 0x51005100
[  134.452586] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.458348] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.465259] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.472479] mmc0:     0 bytes transferred: 0
[  134.477873] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x52 ESDHC_TUNE_CTRL_STATUS 0x52005200
[  134.487159] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.492855] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.499830] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.507051] mmc0:     0 bytes transferred: 0
[  134.512400] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x53 ESDHC_TUNE_CTRL_STATUS 0x53005300
[  134.521693] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.527433] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.534342] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.541563] mmc0:     0 bytes transferred: 0
[  134.546952] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x54 ESDHC_TUNE_CTRL_STATUS 0x54005400
[  134.556236] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.561935] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.568899] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.576107] mmc0:     0 bytes transferred: 0
[  134.581455] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x55 ESDHC_TUNE_CTRL_STATUS 0x55005500
[  134.590757] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.596497] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.603405] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.610625] mmc0:     0 bytes transferred: 0
[  134.615978] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x56 ESDHC_TUNE_CTRL_STATUS 0x56005600
[  134.625152] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.630900] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.637831] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.644992] mmc0:     0 bytes transferred: 0
[  134.650416] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x57 ESDHC_TUNE_CTRL_STATUS 0x57005700
[  134.659636] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.665325] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.672284] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.679498] mmc0:     0 bytes transferred: 0
[  134.684849] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x58 ESDHC_TUNE_CTRL_STATUS 0x58005800
[  134.694145] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.699896] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.706858] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.714022] mmc0:     0 bytes transferred: 0
[  134.719434] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x59 ESDHC_TUNE_CTRL_STATUS 0x59005900
[  134.728722] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.734413] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.741380] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.748608] mmc0:     0 bytes transferred: 0
[  134.753963] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x5a ESDHC_TUNE_CTRL_STATUS 0x5a005a00
[  134.763253] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.769011] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.775986] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.783153] mmc0:     0 bytes transferred: 0
[  134.788564] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x5b ESDHC_TUNE_CTRL_STATUS 0x5b005b00
[  134.797852] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.803543] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.810512] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.817723] mmc0:     0 bytes transferred: 0
[  134.823075] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x5c ESDHC_TUNE_CTRL_STATUS 0x5c005c00
[  134.832368] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.838117] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.845029] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.852241] mmc0:     0 bytes transferred: 0
[  134.857633] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x5d ESDHC_TUNE_CTRL_STATUS 0x5d005d00
[  134.866932] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.872626] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.879595] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.886806] mmc0:     0 bytes transferred: 0
[  134.892156] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x5e ESDHC_TUNE_CTRL_STATUS 0x5e005e00
[  134.901443] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.907182] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.914092] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.921315] mmc0:     0 bytes transferred: 0
[  134.926673] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x5f ESDHC_TUNE_CTRL_STATUS 0x5f005f00
[  134.935947] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.941639] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.948607] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.955772] mmc0:     0 bytes transferred: 0
[  134.961210] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x60 ESDHC_TUNE_CTRL_STATUS 0x60006000
[  134.970504] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.976244] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.983152] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.990374] mmc0:     0 bytes transferred: 0
[  134.995734] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x61 ESDHC_TUNE_CTRL_STATUS 0x61006100
[  135.005021] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.010768] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.017753] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.024919] mmc0:     0 bytes transferred: 0
[  135.030320] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x62 ESDHC_TUNE_CTRL_STATUS 0x62006200
[  135.039604] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.045295] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.052271] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.059486] mmc0:     0 bytes transferred: 0
[  135.064837] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x63 ESDHC_TUNE_CTRL_STATUS 0x63006300
[  135.074125] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.079884] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.086848] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.094012] mmc0:     0 bytes transferred: 0
[  135.099418] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x64 ESDHC_TUNE_CTRL_STATUS 0x64006400
[  135.108707] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.114399] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.121366] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.128591] mmc0:     0 bytes transferred: 0
[  135.133943] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x65 ESDHC_TUNE_CTRL_STATUS 0x65006500
[  135.143236] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.148988] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.155949] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.163114] mmc0:     0 bytes transferred: 0
[  135.168523] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x66 ESDHC_TUNE_CTRL_STATUS 0x66006600
[  135.177798] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.183489] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.190452] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.197662] mmc0:     0 bytes transferred: 0
[  135.203010] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x67 ESDHC_TUNE_CTRL_STATUS 0x67006700
[  135.212295] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.218043] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.224949] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.232173] mmc0:     0 bytes transferred: 0
[  135.237560] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x68 ESDHC_TUNE_CTRL_STATUS 0x68006800
[  135.246843] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.252540] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.259505] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.266712] mmc0:     0 bytes transferred: 0
[  135.272060] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x69 ESDHC_TUNE_CTRL_STATUS 0x69006900
[  135.281350] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.287101] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.294008] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.301231] mmc0:     0 bytes transferred: 0
[  135.306589] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x6a ESDHC_TUNE_CTRL_STATUS 0x6a006a00
[  135.315763] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.321523] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.328479] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.335640] mmc0:     0 bytes transferred: 0
[  135.341099] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x6b ESDHC_TUNE_CTRL_STATUS 0x6b006b00
[  135.350324] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.356063] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.362976] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.370198] mmc0:     0 bytes transferred: 0
[  135.375553] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x6c ESDHC_TUNE_CTRL_STATUS 0x6c006c00
[  135.384848] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.390597] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.397554] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.404717] mmc0:     0 bytes transferred: 0
[  135.410125] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x6d ESDHC_TUNE_CTRL_STATUS 0x6d006d00
[  135.419424] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.425117] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.432086] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.439313] mmc0:     0 bytes transferred: 0
[  135.444664] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x6e ESDHC_TUNE_CTRL_STATUS 0x6e006e00
[  135.453948] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.459709] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.466672] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.473836] mmc0:     0 bytes transferred: 0
[  135.479239] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x6f ESDHC_TUNE_CTRL_STATUS 0x6f006f00
[  135.488521] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.494213] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.501177] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.508392] mmc0:     0 bytes transferred: 0
[  135.513742] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x70 ESDHC_TUNE_CTRL_STATUS 0x70007000
[  135.523027] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.528777] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.535683] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.542902] mmc0:     0 bytes transferred: 0
[  135.548295] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x71 ESDHC_TUNE_CTRL_STATUS 0x71007100
[  135.557587] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.563280] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.570241] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.577451] mmc0:     0 bytes transferred: 0
[  135.582802] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x72 ESDHC_TUNE_CTRL_STATUS 0x72007200
[  135.592096] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.597839] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.604746] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.611968] mmc0:     0 bytes transferred: 0
[  135.617357] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x73 ESDHC_TUNE_CTRL_STATUS 0x73007300
[  135.626650] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.632347] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.639314] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.646523] mmc0:     0 bytes transferred: 0
[  135.651872] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x74 ESDHC_TUNE_CTRL_STATUS 0x74007400
[  135.661160] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.666903] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.673811] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.681033] mmc0:     0 bytes transferred: 0
[  135.686388] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x75 ESDHC_TUNE_CTRL_STATUS 0x75007500
[  135.695558] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.701309] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.708245] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.715406] mmc0:     0 bytes transferred: 0
[  135.720832] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x76 ESDHC_TUNE_CTRL_STATUS 0x76007600
[  135.730053] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.735742] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.742700] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.749929] mmc0:     0 bytes transferred: 0
[  135.755283] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x77 ESDHC_TUNE_CTRL_STATUS 0x77007700
[  135.764573] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.770334] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.777303] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.784468] mmc0:     0 bytes transferred: 0
[  135.789882] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x78 ESDHC_TUNE_CTRL_STATUS 0x78007800
[  135.799170] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.804863] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.811831] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.819052] mmc0:     0 bytes transferred: 0
[  135.824404] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x79 ESDHC_TUNE_CTRL_STATUS 0x79007900
[  135.833708] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.839457] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.846418] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.853582] mmc0:     0 bytes transferred: 0
[  135.858990] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x7a ESDHC_TUNE_CTRL_STATUS 0x7a007a00
[  135.868280] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.873973] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.880955] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.888190] mmc0:     0 bytes transferred: 0
[  135.893542] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x7b ESDHC_TUNE_CTRL_STATUS 0x7b007b00
[  135.902832] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.908590] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.915500] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.922722] mmc0:     0 bytes transferred: 0
[  135.928115] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x7c ESDHC_TUNE_CTRL_STATUS 0x7c007c00
[  135.937409] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.943108] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.950080] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.957288] mmc0:     0 bytes transferred: 0
[  135.962637] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x7d ESDHC_TUNE_CTRL_STATUS 0x7d007d00
[  135.971935] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.977695] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.984873] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.992111] mmc0:     0 bytes transferred: 0
[  135.997536] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x7e ESDHC_TUNE_CTRL_STATUS 0x7e007e00
[  136.006774] mmc0: starting CMD19 arg 00000000 flags 00000035
[  136.012466] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  136.019444] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  136.026656] mmc0:     0 bytes transferred: 0
[  136.032008] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x7f ESDHC_TUNE_CTRL_STATUS 0x7f00
[  136.040939] mmc0: starting CMD19 arg 00000000 flags 00000035
[  136.046687] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  136.053600] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  136.060826] mmc0:     0 bytes transferred: 0
[  136.065180] sdhci-esdhc-imx 2198000.usdhc: tunning failed at 0x7f ret -123
[  136.072151] mmc0: tuning execution failed: -123
[  136.076816] mmc0: req failed (CMD13): -123, retrying...
[  136.082738] mmc0: req failed (CMD13): -123, retrying...
[  136.088413] mmc0: req failed (CMD13): -123, retrying...
[  136.093743] mmc0: req done (CMD13): -123: 00000000 00000000 00000000 00000000
[  136.100994] mmc0: card remove detected
[  136.104984] mmc0: card 59b4 removed
[  136.113392] mmc0: clock 0Hz busmode 2 powermode 0 cs 0 Vdd 0 width 1 timing 0
[  136.120648] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 0
[  136.373709] FAT-fs (mmcblk0p1): FAT read failed (blocknr 942)

So it's a bit hard for me to believe it has no affection.

> Currently we don't even send the CMD13 because we check card detect first.
> I added prints for sdhci_execute_tuning and got this:
> 
> [  255.536326] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000080
> [  255.743653] mmc1: starting CMD13 arg 59b40000 flags 00000195
> [  255.750093] mmc1: sdhci_execute_tuning
> [  255.754358] mmc1: sdhci_execute_tuning: send command
> [  255.809638] sdhci: Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock

I double checked the code, it seems why your platform only sends one tuning
command is because your controller did not generate buffer ready interrupt
if card is already removed.

> [  255.824810] mmc1: req failed (CMD13): -123, retrying...
> [  255.832766] mmc1: req failed (CMD13): -123, retrying...
> [  255.840722] mmc1: req failed (CMD13): -123, retrying...
> [  255.848672] mmc1: req done (CMD13): -123: 00000000 00000000 00000000 00000000
> [  255.856773] mmc1: card remove detected
> [  255.861056] mmc1: card 59b4 removed
> [  255.872872] mmc1: clock 0Hz busmode 2 powermode 0 cs 0 Vdd 0 width 0 timing 0
> 
> > 
> > Hmm.. I can't sure it's no affection.
> > e.g we did have customers reporting cd plug in/out causing jitters
> > when system is busy playing audio or video.
> > Maybe we need to do those tests.
> > 
> > Anyway, what's your point to keep sending tuning commands after card
> > is already removed?
> 
> Seems like a problem for your driver not the core.  Why not check card detect
> after the first error in esdhc_executing_tuning().
> 

It is not IMX driver problem.
IMX is based on SDHCI driver and it does check card detect for CMD13,
but sdhci_execute_tuning not.

We may either check CD in sdhci_execute_tuning() or disable tuning
for card remove case.

Personally i'd like to disable it in core since i really can't see
the meaning to keep it for card remove.

What's your idea?

Regards
Dong Aisheng

> > 
> > Regards
> > Dong Aisheng
> > 
> >>>
> >>> Regards
> >>> Dong Aisheng
> >>>
> >>>>>
> >>>>> CC: stable <stable@vger.kernel.org>
> >>>>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> >>>>> ---
> >>>>>  drivers/mmc/core/core.c | 1 +
> >>>>>  1 file changed, 1 insertion(+)
> >>>>>
> >>>>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> >>>>> index 52bfaf0..76d0802 100644
> >>>>> --- a/drivers/mmc/core/core.c
> >>>>> +++ b/drivers/mmc/core/core.c
> >>>>> @@ -1888,6 +1888,7 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
> >>>>>               pm_wakeup_event(mmc_dev(host), 5000);
> >>>>>
> >>>>>       host->detect_change = 1;
> >>>>> +     mmc_retune_disable(host);
> >>>>>       mmc_schedule_delayed_work(&host->detect, delay);
> >>>>>  }
> >>>>>
> >>>>>
> >>>>
> >>>
> >>
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> >> the body of a message to majordomo@vger.kernel.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > 
> 

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

* [PATCH 10/23] mmc: core: disable auto retune during card detection process
@ 2016-04-29  7:42               ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-29  7:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 29, 2016 at 09:54:13AM +0300, Adrian Hunter wrote:
> On 28/04/16 16:22, Dong Aisheng wrote:
> > On Thu, Apr 28, 2016 at 10:04:34AM +0300, Adrian Hunter wrote:
> >> On 24/04/16 13:47, Dong Aisheng wrote:
> >>> On Fri, Apr 22, 2016 at 8:48 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> >>>> On 15/04/16 20:29, Dong Aisheng wrote:
> >>>>> During card detection process, mmc core may sends commands
> >>>>> to detect if card is still exist in mmc_rescan for removable
> >>>>> card which may trigger mmc retuning process after a bit time
> >>>>> of runtime pm suspend.
> >>>>> Obviously this retuning process is meaningless for card remove
> >>>>> case, so we disable mmc_retune in mmc_detect_change() for it.
> >>>>> For card insert case, the mmc_retune will be enabled normally
> >>>>> in its card initialization process later in mmc_execute_tuning().
> >>>>> So disable it at first has no side effection.
> >>>>
> >>>> We don't assume that the card has been removed, which is why we send
> >>>> commands to find out if it is still there.  If it is still there, this
> >>>> change will have incorrectly disabled re-tuning.
> >>>>
> >>>
> >>> Do you mean the 'fake' card remove interrupt like caused by glitch?
> >>
> >> Sure
> >>
> >>> Yes, if that the card is still exist and re-tuning is wrongly disabled.
> >>>
> >>> So we could re-enable re-tuning for this special case?
> >>> Something like:
> >>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> >>> index 41b1e76..e1990a8 100644
> >>> --- a/drivers/mmc/core/core.c
> >>> +++ b/drivers/mmc/core/core.c
> >>> @@ -2607,6 +2607,8 @@ void mmc_rescan(struct work_struct *work)
> >>>
> >>>         /* if there still is a card present, stop here */
> >>>         if (host->bus_ops != NULL) {
> >>> +               if (tuning_is_enabled_before())
> >>> +                       mmc_retune_enable(host);
> >>>                 mmc_bus_put(host);
> >>>                 goto out;
> >>>         }
> >>>
> >>>
> >>>> Do you have an actual problem with the way it works now?
> >>>>
> >>>
> >>> No actual problems now.
> >>
> >> So let's not spend time on it.
> >>
> >>> I just observe a lot tuning commands keep sending although the card is already
> >>> removed which seems a bit meaningless.
> >>> And most tuning execution process is executed with sin_lock_irqsave, i'm not
> >>> sure if the mass tuning commands may affect the system when CPU is busy.
> >>> What do you think?
> >>
> >> sdhci spin lock is unlocked while waiting for tuning commands.
> >>
> > 
> > It's 40 commands continuously and only cmd transfer time is unlocked.
> 
> Not for sdhci_execute_tuning() it's not.  Only one command is sent.

IMX case is different.
Please see below log on MX6SX SDB.

For IMX6SX SDB:
root at imx6qdlsolo:~# [   39.649322] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[   39.661452] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 6
[   39.668295] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[   39.679146] mmc1: starting CMD13 arg e6240000 flags 00000195
[   39.684908] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.693359] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.701654] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.709717] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.717718] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.725057] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.734818] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.744197] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.752316] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.760363] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.778296] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.788348] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.795731] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.803932] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.811865] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.819801] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.827710] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.835046] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.843384] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.851293] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.859209] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.867111] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.874450] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.882725] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.890610] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.898615] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.905953] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.913821] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.922283] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.930177] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.938082] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.945676] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.953696] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.961914] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.969792] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.977682] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.985018] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   39.992898] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   40.001107] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   40.009125] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000020
[   40.018058] mmc1: req failed (CMD13): -123, retrying...
[   40.023435] mmc1: req failed (CMD13): -123, retrying...
[   40.029614] mmc1: req failed (CMD13): -123, retrying...
[   40.034981] mmc1: req done (CMD13): -123: 00000000 00000000 00000000 00000000
[   40.042891] mmc1: card remove detected
[   40.047446] mmc1: card e624 removed
[   40.208083] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[   40.222000] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 6
[   40.228813] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[   40.238175] mmc1: clock 0Hz busmode 2 powermode 0 cs 0 Vdd 0 width 1 timing 0
[   40.247693] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 0


And IMX6DL ARD is even worser due to it's using common
mmc_send_tuning() function.
root at imx6qdlsolo:~# 
root at imx6qdlsolo:~# [  129.462564] sysrq: SysRq : Changing Loglevel
[  129.466902] sysrq: Loglevel set to 8
[  131.616078] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[  131.625311] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 6
[  131.632133] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[  131.642121] mmc0: starting CMD13 arg 59b40000 flags 00000195
[  131.648925] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x0 ESDHC_TUNE_CTRL_STATUS 0x0
[  131.657818] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.663518] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.670835] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.678069] mmc0:     0 bytes transferred: 0
[  131.683433] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x1 ESDHC_TUNE_CTRL_STATUS 0x1000100
[  131.692940] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.698709] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.705625] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.712854] mmc0:     0 bytes transferred: 0
[  131.718251] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x2 ESDHC_TUNE_CTRL_STATUS 0x2000200
[  131.727375] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.733074] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.740043] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.747256] mmc0:     0 bytes transferred: 0
[  131.752611] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x3 ESDHC_TUNE_CTRL_STATUS 0x3000300
[  131.761751] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.767506] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.774419] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.781642] mmc0:     0 bytes transferred: 0
[  131.787035] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x4 ESDHC_TUNE_CTRL_STATUS 0x4000400
[  131.796156] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.801851] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.808832] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.816037] mmc0:     0 bytes transferred: 0
[  131.821389] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x5 ESDHC_TUNE_CTRL_STATUS 0x5000500
[  131.830503] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.836254] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.843162] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.850385] mmc0:     0 bytes transferred: 0
[  131.855737] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x6 ESDHC_TUNE_CTRL_STATUS 0x6000600
[  131.864863] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.870613] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.877565] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.884728] mmc0:     0 bytes transferred: 0
[  131.890133] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x7 ESDHC_TUNE_CTRL_STATUS 0x7000700
[  131.899247] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.904939] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.911903] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.919122] mmc0:     0 bytes transferred: 0
[  131.924474] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x8 ESDHC_TUNE_CTRL_STATUS 0x8000800
[  131.933591] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.939340] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.946300] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.953464] mmc0:     0 bytes transferred: 0
[  131.958869] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x9 ESDHC_TUNE_CTRL_STATUS 0x9000900
[  131.967965] mmc0: starting CMD19 arg 00000000 flags 00000035
[  131.973657] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  131.980621] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  131.987831] mmc0:     0 bytes transferred: 0
[  131.993183] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0xa ESDHC_TUNE_CTRL_STATUS 0xa000a00
[  132.002295] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.008039] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.014945] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.022167] mmc0:     0 bytes transferred: 0
[  132.027555] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0xb ESDHC_TUNE_CTRL_STATUS 0xb000b00
[  132.036682] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.042376] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.049341] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.056555] mmc0:     0 bytes transferred: 0
[  132.061905] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0xc ESDHC_TUNE_CTRL_STATUS 0xc000c00
[  132.071020] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.076760] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.083663] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.090886] mmc0:     0 bytes transferred: 0
[  132.096237] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0xd ESDHC_TUNE_CTRL_STATUS 0xd000d00
[  132.105233] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.110981] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.117911] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.125072] mmc0:     0 bytes transferred: 0
[  132.130494] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0xe ESDHC_TUNE_CTRL_STATUS 0xe000e00
[  132.139538] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.145227] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.152185] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.159403] mmc0:     0 bytes transferred: 0
[  132.164755] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0xf ESDHC_TUNE_CTRL_STATUS 0xf000f00
[  132.173884] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.179622] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.186579] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.193743] mmc0:     0 bytes transferred: 0
[  132.199157] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x10 ESDHC_TUNE_CTRL_STATUS 0x10001000
[  132.208432] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.214124] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.221088] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.228308] mmc0:     0 bytes transferred: 0
[  132.233658] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x11 ESDHC_TUNE_CTRL_STATUS 0x11001100
[  132.242930] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.248677] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.255584] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.262803] mmc0:     0 bytes transferred: 0
[  132.268190] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x12 ESDHC_TUNE_CTRL_STATUS 0x12001200
[  132.277483] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.283184] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.290171] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.297385] mmc0:     0 bytes transferred: 0
[  132.302737] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x13 ESDHC_TUNE_CTRL_STATUS 0x13001300
[  132.312043] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.317786] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.324697] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.331920] mmc0:     0 bytes transferred: 0
[  132.337308] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x14 ESDHC_TUNE_CTRL_STATUS 0x14001400
[  132.346604] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.352297] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.359271] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.366482] mmc0:     0 bytes transferred: 0
[  132.371833] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x15 ESDHC_TUNE_CTRL_STATUS 0x15001500
[  132.381125] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.386867] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.393773] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.400990] mmc0:     0 bytes transferred: 0
[  132.406344] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x16 ESDHC_TUNE_CTRL_STATUS 0x16001600
[  132.415517] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.421265] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.428214] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.435375] mmc0:     0 bytes transferred: 0
[  132.440827] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x17 ESDHC_TUNE_CTRL_STATUS 0x17001700
[  132.450046] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.455736] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.462696] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.469914] mmc0:     0 bytes transferred: 0
[  132.475264] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x18 ESDHC_TUNE_CTRL_STATUS 0x18001800
[  132.484554] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.490299] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.497255] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.504419] mmc0:     0 bytes transferred: 0
[  132.509826] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x19 ESDHC_TUNE_CTRL_STATUS 0x19001900
[  132.519096] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.524786] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.531751] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.538971] mmc0:     0 bytes transferred: 0
[  132.544322] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x1a ESDHC_TUNE_CTRL_STATUS 0x1a001a00
[  132.553609] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.559357] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.566325] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.573488] mmc0:     0 bytes transferred: 0
[  132.578898] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x1b ESDHC_TUNE_CTRL_STATUS 0x1b001b00
[  132.588168] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.593861] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.600820] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.608037] mmc0:     0 bytes transferred: 0
[  132.613390] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x1c ESDHC_TUNE_CTRL_STATUS 0x1c001c00
[  132.622680] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.628428] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.635334] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.642556] mmc0:     0 bytes transferred: 0
[  132.647945] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x1d ESDHC_TUNE_CTRL_STATUS 0x1d001d00
[  132.657231] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.662930] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.669892] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.677099] mmc0:     0 bytes transferred: 0
[  132.682450] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x1e ESDHC_TUNE_CTRL_STATUS 0x1e001e00
[  132.691737] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.697490] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.704403] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.711624] mmc0:     0 bytes transferred: 0
[  132.717010] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x1f ESDHC_TUNE_CTRL_STATUS 0x1f001f00
[  132.726301] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.731998] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.738960] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.746169] mmc0:     0 bytes transferred: 0
[  132.751525] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x20 ESDHC_TUNE_CTRL_STATUS 0x20002000
[  132.760817] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.766577] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.773491] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.780714] mmc0:     0 bytes transferred: 0
[  132.786069] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x21 ESDHC_TUNE_CTRL_STATUS 0x21002100
[  132.795243] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.800992] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.807923] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.815084] mmc0:     0 bytes transferred: 0
[  132.820546] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x22 ESDHC_TUNE_CTRL_STATUS 0x22002200
[  132.829787] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.835477] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.842441] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.849663] mmc0:     0 bytes transferred: 0
[  132.855016] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x23 ESDHC_TUNE_CTRL_STATUS 0x23002300
[  132.864305] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.870056] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.877015] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.884179] mmc0:     0 bytes transferred: 0
[  132.889584] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x24 ESDHC_TUNE_CTRL_STATUS 0x24002400
[  132.898860] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.904551] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.911512] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.918731] mmc0:     0 bytes transferred: 0
[  132.924080] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x25 ESDHC_TUNE_CTRL_STATUS 0x25002500
[  132.933368] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.939114] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.946071] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.953235] mmc0:     0 bytes transferred: 0
[  132.958640] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x26 ESDHC_TUNE_CTRL_STATUS 0x26002600
[  132.967924] mmc0: starting CMD19 arg 00000000 flags 00000035
[  132.973614] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  132.980584] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  132.987796] mmc0:     0 bytes transferred: 0
[  132.993147] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x27 ESDHC_TUNE_CTRL_STATUS 0x27002700
[  133.002433] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.008181] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.015089] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.022310] mmc0:     0 bytes transferred: 0
[  133.027699] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x28 ESDHC_TUNE_CTRL_STATUS 0x28002800
[  133.037014] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.042712] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.049679] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.056890] mmc0:     0 bytes transferred: 0
[  133.062237] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x29 ESDHC_TUNE_CTRL_STATUS 0x29002900
[  133.071525] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.077267] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.084172] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.091392] mmc0:     0 bytes transferred: 0
[  133.096746] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x2a ESDHC_TUNE_CTRL_STATUS 0x2a002a00
[  133.106021] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.111714] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.118679] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.125889] mmc0:     0 bytes transferred: 0
[  133.131241] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x2b ESDHC_TUNE_CTRL_STATUS 0x2b002b00
[  133.140530] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.146272] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.153184] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.160409] mmc0:     0 bytes transferred: 0
[  133.165762] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x2c ESDHC_TUNE_CTRL_STATUS 0x2c002c00
[  133.175059] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.180798] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.187759] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.194922] mmc0:     0 bytes transferred: 0
[  133.200329] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x2d ESDHC_TUNE_CTRL_STATUS 0x2d002d00
[  133.209600] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.215291] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.222254] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.229474] mmc0:     0 bytes transferred: 0
[  133.234823] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x2e ESDHC_TUNE_CTRL_STATUS 0x2e002e00
[  133.244124] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.249865] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.256828] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.263991] mmc0:     0 bytes transferred: 0
[  133.269395] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x2f ESDHC_TUNE_CTRL_STATUS 0x2f002f00
[  133.278668] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.284361] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.291340] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.298566] mmc0:     0 bytes transferred: 0
[  133.303922] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x30 ESDHC_TUNE_CTRL_STATUS 0x30003000
[  133.313213] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.318975] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.325939] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.333103] mmc0:     0 bytes transferred: 0
[  133.338506] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x31 ESDHC_TUNE_CTRL_STATUS 0x31003100
[  133.347792] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.353484] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.360450] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.367661] mmc0:     0 bytes transferred: 0
[  133.373010] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x32 ESDHC_TUNE_CTRL_STATUS 0x32003200
[  133.382312] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.388059] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.394965] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.402178] mmc0:     0 bytes transferred: 0
[  133.407573] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x33 ESDHC_TUNE_CTRL_STATUS 0x33003300
[  133.416864] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.422560] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.429523] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.436727] mmc0:     0 bytes transferred: 0
[  133.442079] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x34 ESDHC_TUNE_CTRL_STATUS 0x34003400
[  133.451364] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.457116] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.464027] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.471251] mmc0:     0 bytes transferred: 0
[  133.476608] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x35 ESDHC_TUNE_CTRL_STATUS 0x35003500
[  133.485780] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.491574] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.498529] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.505693] mmc0:     0 bytes transferred: 0
[  133.511177] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x36 ESDHC_TUNE_CTRL_STATUS 0x36003600
[  133.520407] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.526149] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.533061] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.540285] mmc0:     0 bytes transferred: 0
[  133.545638] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x37 ESDHC_TUNE_CTRL_STATUS 0x37003700
[  133.554931] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.560681] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.567639] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.574802] mmc0:     0 bytes transferred: 0
[  133.580206] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x38 ESDHC_TUNE_CTRL_STATUS 0x38003800
[  133.589493] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.595185] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.602144] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.609359] mmc0:     0 bytes transferred: 0
[  133.614712] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x39 ESDHC_TUNE_CTRL_STATUS 0x39003900
[  133.624000] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.629754] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.636727] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.643891] mmc0:     0 bytes transferred: 0
[  133.649293] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x3a ESDHC_TUNE_CTRL_STATUS 0x3a003a00
[  133.658567] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.664259] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.671225] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.678445] mmc0:     0 bytes transferred: 0
[  133.683798] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x3b ESDHC_TUNE_CTRL_STATUS 0x3b003b00
[  133.693086] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.698824] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.705728] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.712950] mmc0:     0 bytes transferred: 0
[  133.718336] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x3c ESDHC_TUNE_CTRL_STATUS 0x3c003c00
[  133.727625] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.733322] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.740287] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.747498] mmc0:     0 bytes transferred: 0
[  133.752851] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x3d ESDHC_TUNE_CTRL_STATUS 0x3d003d00
[  133.762139] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.767913] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.774827] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.782051] mmc0:     0 bytes transferred: 0
[  133.787438] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x3e ESDHC_TUNE_CTRL_STATUS 0x3e003e00
[  133.796727] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.802421] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.809397] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.816617] mmc0:     0 bytes transferred: 0
[  133.821967] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x3f ESDHC_TUNE_CTRL_STATUS 0x3f003f00
[  133.831258] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.837001] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.843909] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.851122] mmc0:     0 bytes transferred: 0
[  133.856476] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x40 ESDHC_TUNE_CTRL_STATUS 0x40004000
[  133.865647] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.871395] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.878332] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.885495] mmc0:     0 bytes transferred: 0
[  133.890922] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x41 ESDHC_TUNE_CTRL_STATUS 0x41004100
[  133.900145] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.905886] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.912795] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.920018] mmc0:     0 bytes transferred: 0
[  133.925371] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x42 ESDHC_TUNE_CTRL_STATUS 0x42004200
[  133.934662] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.940411] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.947371] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.954536] mmc0:     0 bytes transferred: 0
[  133.959943] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x43 ESDHC_TUNE_CTRL_STATUS 0x43004300
[  133.969217] mmc0: starting CMD19 arg 00000000 flags 00000035
[  133.974908] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  133.981871] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  133.989092] mmc0:     0 bytes transferred: 0
[  133.994441] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x44 ESDHC_TUNE_CTRL_STATUS 0x44004400
[  134.003714] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.009465] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.016434] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.023598] mmc0:     0 bytes transferred: 0
[  134.029006] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x45 ESDHC_TUNE_CTRL_STATUS 0x45004500
[  134.038294] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.043984] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.050936] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.058150] mmc0:     0 bytes transferred: 0
[  134.063501] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x46 ESDHC_TUNE_CTRL_STATUS 0x46004600
[  134.072790] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.078541] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.085447] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.092664] mmc0:     0 bytes transferred: 0
[  134.098068] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x47 ESDHC_TUNE_CTRL_STATUS 0x47004700
[  134.107355] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.113053] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.120021] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.127231] mmc0:     0 bytes transferred: 0
[  134.132580] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x48 ESDHC_TUNE_CTRL_STATUS 0x48004800
[  134.141866] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.147617] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.154527] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.161749] mmc0:     0 bytes transferred: 0
[  134.167137] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x49 ESDHC_TUNE_CTRL_STATUS 0x49004900
[  134.176430] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.182129] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.189101] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.196310] mmc0:     0 bytes transferred: 0
[  134.201660] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x4a ESDHC_TUNE_CTRL_STATUS 0x4a004a00
[  134.210944] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.216683] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.223586] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.230807] mmc0:     0 bytes transferred: 0
[  134.236162] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x4b ESDHC_TUNE_CTRL_STATUS 0x4b004b00
[  134.245335] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.251076] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.258013] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.265177] mmc0:     0 bytes transferred: 0
[  134.270609] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x4c ESDHC_TUNE_CTRL_STATUS 0x4c004c00
[  134.279849] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.285539] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.292509] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.299730] mmc0:     0 bytes transferred: 0
[  134.305087] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x4d ESDHC_TUNE_CTRL_STATUS 0x4d004d00
[  134.314397] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.320147] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.327115] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.334281] mmc0:     0 bytes transferred: 0
[  134.339692] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x4e ESDHC_TUNE_CTRL_STATUS 0x4e004e00
[  134.348979] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.354671] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.361642] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.368858] mmc0:     0 bytes transferred: 0
[  134.374209] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x4f ESDHC_TUNE_CTRL_STATUS 0x4f004f00
[  134.383503] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.389253] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.396215] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.403378] mmc0:     0 bytes transferred: 0
[  134.408785] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x50 ESDHC_TUNE_CTRL_STATUS 0x50005000
[  134.418057] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.423747] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.430706] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.437930] mmc0:     0 bytes transferred: 0
[  134.443285] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x51 ESDHC_TUNE_CTRL_STATUS 0x51005100
[  134.452586] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.458348] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.465259] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.472479] mmc0:     0 bytes transferred: 0
[  134.477873] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x52 ESDHC_TUNE_CTRL_STATUS 0x52005200
[  134.487159] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.492855] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.499830] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.507051] mmc0:     0 bytes transferred: 0
[  134.512400] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x53 ESDHC_TUNE_CTRL_STATUS 0x53005300
[  134.521693] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.527433] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.534342] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.541563] mmc0:     0 bytes transferred: 0
[  134.546952] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x54 ESDHC_TUNE_CTRL_STATUS 0x54005400
[  134.556236] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.561935] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.568899] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.576107] mmc0:     0 bytes transferred: 0
[  134.581455] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x55 ESDHC_TUNE_CTRL_STATUS 0x55005500
[  134.590757] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.596497] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.603405] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.610625] mmc0:     0 bytes transferred: 0
[  134.615978] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x56 ESDHC_TUNE_CTRL_STATUS 0x56005600
[  134.625152] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.630900] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.637831] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.644992] mmc0:     0 bytes transferred: 0
[  134.650416] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x57 ESDHC_TUNE_CTRL_STATUS 0x57005700
[  134.659636] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.665325] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.672284] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.679498] mmc0:     0 bytes transferred: 0
[  134.684849] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x58 ESDHC_TUNE_CTRL_STATUS 0x58005800
[  134.694145] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.699896] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.706858] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.714022] mmc0:     0 bytes transferred: 0
[  134.719434] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x59 ESDHC_TUNE_CTRL_STATUS 0x59005900
[  134.728722] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.734413] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.741380] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.748608] mmc0:     0 bytes transferred: 0
[  134.753963] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x5a ESDHC_TUNE_CTRL_STATUS 0x5a005a00
[  134.763253] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.769011] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.775986] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.783153] mmc0:     0 bytes transferred: 0
[  134.788564] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x5b ESDHC_TUNE_CTRL_STATUS 0x5b005b00
[  134.797852] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.803543] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.810512] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.817723] mmc0:     0 bytes transferred: 0
[  134.823075] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x5c ESDHC_TUNE_CTRL_STATUS 0x5c005c00
[  134.832368] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.838117] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.845029] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.852241] mmc0:     0 bytes transferred: 0
[  134.857633] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x5d ESDHC_TUNE_CTRL_STATUS 0x5d005d00
[  134.866932] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.872626] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.879595] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.886806] mmc0:     0 bytes transferred: 0
[  134.892156] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x5e ESDHC_TUNE_CTRL_STATUS 0x5e005e00
[  134.901443] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.907182] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.914092] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.921315] mmc0:     0 bytes transferred: 0
[  134.926673] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x5f ESDHC_TUNE_CTRL_STATUS 0x5f005f00
[  134.935947] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.941639] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.948607] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.955772] mmc0:     0 bytes transferred: 0
[  134.961210] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x60 ESDHC_TUNE_CTRL_STATUS 0x60006000
[  134.970504] mmc0: starting CMD19 arg 00000000 flags 00000035
[  134.976244] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  134.983152] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  134.990374] mmc0:     0 bytes transferred: 0
[  134.995734] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x61 ESDHC_TUNE_CTRL_STATUS 0x61006100
[  135.005021] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.010768] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.017753] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.024919] mmc0:     0 bytes transferred: 0
[  135.030320] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x62 ESDHC_TUNE_CTRL_STATUS 0x62006200
[  135.039604] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.045295] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.052271] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.059486] mmc0:     0 bytes transferred: 0
[  135.064837] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x63 ESDHC_TUNE_CTRL_STATUS 0x63006300
[  135.074125] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.079884] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.086848] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.094012] mmc0:     0 bytes transferred: 0
[  135.099418] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x64 ESDHC_TUNE_CTRL_STATUS 0x64006400
[  135.108707] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.114399] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.121366] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.128591] mmc0:     0 bytes transferred: 0
[  135.133943] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x65 ESDHC_TUNE_CTRL_STATUS 0x65006500
[  135.143236] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.148988] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.155949] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.163114] mmc0:     0 bytes transferred: 0
[  135.168523] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x66 ESDHC_TUNE_CTRL_STATUS 0x66006600
[  135.177798] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.183489] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.190452] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.197662] mmc0:     0 bytes transferred: 0
[  135.203010] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x67 ESDHC_TUNE_CTRL_STATUS 0x67006700
[  135.212295] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.218043] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.224949] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.232173] mmc0:     0 bytes transferred: 0
[  135.237560] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x68 ESDHC_TUNE_CTRL_STATUS 0x68006800
[  135.246843] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.252540] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.259505] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.266712] mmc0:     0 bytes transferred: 0
[  135.272060] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x69 ESDHC_TUNE_CTRL_STATUS 0x69006900
[  135.281350] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.287101] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.294008] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.301231] mmc0:     0 bytes transferred: 0
[  135.306589] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x6a ESDHC_TUNE_CTRL_STATUS 0x6a006a00
[  135.315763] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.321523] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.328479] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.335640] mmc0:     0 bytes transferred: 0
[  135.341099] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x6b ESDHC_TUNE_CTRL_STATUS 0x6b006b00
[  135.350324] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.356063] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.362976] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.370198] mmc0:     0 bytes transferred: 0
[  135.375553] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x6c ESDHC_TUNE_CTRL_STATUS 0x6c006c00
[  135.384848] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.390597] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.397554] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.404717] mmc0:     0 bytes transferred: 0
[  135.410125] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x6d ESDHC_TUNE_CTRL_STATUS 0x6d006d00
[  135.419424] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.425117] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.432086] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.439313] mmc0:     0 bytes transferred: 0
[  135.444664] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x6e ESDHC_TUNE_CTRL_STATUS 0x6e006e00
[  135.453948] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.459709] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.466672] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.473836] mmc0:     0 bytes transferred: 0
[  135.479239] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x6f ESDHC_TUNE_CTRL_STATUS 0x6f006f00
[  135.488521] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.494213] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.501177] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.508392] mmc0:     0 bytes transferred: 0
[  135.513742] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x70 ESDHC_TUNE_CTRL_STATUS 0x70007000
[  135.523027] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.528777] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.535683] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.542902] mmc0:     0 bytes transferred: 0
[  135.548295] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x71 ESDHC_TUNE_CTRL_STATUS 0x71007100
[  135.557587] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.563280] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.570241] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.577451] mmc0:     0 bytes transferred: 0
[  135.582802] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x72 ESDHC_TUNE_CTRL_STATUS 0x72007200
[  135.592096] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.597839] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.604746] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.611968] mmc0:     0 bytes transferred: 0
[  135.617357] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x73 ESDHC_TUNE_CTRL_STATUS 0x73007300
[  135.626650] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.632347] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.639314] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.646523] mmc0:     0 bytes transferred: 0
[  135.651872] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x74 ESDHC_TUNE_CTRL_STATUS 0x74007400
[  135.661160] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.666903] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.673811] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.681033] mmc0:     0 bytes transferred: 0
[  135.686388] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x75 ESDHC_TUNE_CTRL_STATUS 0x75007500
[  135.695558] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.701309] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.708245] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.715406] mmc0:     0 bytes transferred: 0
[  135.720832] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x76 ESDHC_TUNE_CTRL_STATUS 0x76007600
[  135.730053] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.735742] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.742700] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.749929] mmc0:     0 bytes transferred: 0
[  135.755283] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x77 ESDHC_TUNE_CTRL_STATUS 0x77007700
[  135.764573] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.770334] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.777303] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.784468] mmc0:     0 bytes transferred: 0
[  135.789882] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x78 ESDHC_TUNE_CTRL_STATUS 0x78007800
[  135.799170] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.804863] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.811831] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.819052] mmc0:     0 bytes transferred: 0
[  135.824404] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x79 ESDHC_TUNE_CTRL_STATUS 0x79007900
[  135.833708] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.839457] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.846418] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.853582] mmc0:     0 bytes transferred: 0
[  135.858990] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x7a ESDHC_TUNE_CTRL_STATUS 0x7a007a00
[  135.868280] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.873973] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.880955] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.888190] mmc0:     0 bytes transferred: 0
[  135.893542] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x7b ESDHC_TUNE_CTRL_STATUS 0x7b007b00
[  135.902832] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.908590] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.915500] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.922722] mmc0:     0 bytes transferred: 0
[  135.928115] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x7c ESDHC_TUNE_CTRL_STATUS 0x7c007c00
[  135.937409] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.943108] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.950080] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.957288] mmc0:     0 bytes transferred: 0
[  135.962637] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x7d ESDHC_TUNE_CTRL_STATUS 0x7d007d00
[  135.971935] mmc0: starting CMD19 arg 00000000 flags 00000035
[  135.977695] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  135.984873] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  135.992111] mmc0:     0 bytes transferred: 0
[  135.997536] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x7e ESDHC_TUNE_CTRL_STATUS 0x7e007e00
[  136.006774] mmc0: starting CMD19 arg 00000000 flags 00000035
[  136.012466] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  136.019444] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  136.026656] mmc0:     0 bytes transferred: 0
[  136.032008] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x7f ESDHC_TUNE_CTRL_STATUS 0x7f00
[  136.040939] mmc0: starting CMD19 arg 00000000 flags 00000035
[  136.046687] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[  136.053600] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[  136.060826] mmc0:     0 bytes transferred: 0
[  136.065180] sdhci-esdhc-imx 2198000.usdhc: tunning failed at 0x7f ret -123
[  136.072151] mmc0: tuning execution failed: -123
[  136.076816] mmc0: req failed (CMD13): -123, retrying...
[  136.082738] mmc0: req failed (CMD13): -123, retrying...
[  136.088413] mmc0: req failed (CMD13): -123, retrying...
[  136.093743] mmc0: req done (CMD13): -123: 00000000 00000000 00000000 00000000
[  136.100994] mmc0: card remove detected
[  136.104984] mmc0: card 59b4 removed
[  136.113392] mmc0: clock 0Hz busmode 2 powermode 0 cs 0 Vdd 0 width 1 timing 0
[  136.120648] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 0
[  136.373709] FAT-fs (mmcblk0p1): FAT read failed (blocknr 942)

So it's a bit hard for me to believe it has no affection.

> Currently we don't even send the CMD13 because we check card detect first.
> I added prints for sdhci_execute_tuning and got this:
> 
> [  255.536326] sdhci [sdhci_irq()]: *** mmc1 got interrupt: 0x00000080
> [  255.743653] mmc1: starting CMD13 arg 59b40000 flags 00000195
> [  255.750093] mmc1: sdhci_execute_tuning
> [  255.754358] mmc1: sdhci_execute_tuning: send command
> [  255.809638] sdhci: Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock

I double checked the code, it seems why your platform only sends one tuning
command is because your controller did not generate buffer ready interrupt
if card is already removed.

> [  255.824810] mmc1: req failed (CMD13): -123, retrying...
> [  255.832766] mmc1: req failed (CMD13): -123, retrying...
> [  255.840722] mmc1: req failed (CMD13): -123, retrying...
> [  255.848672] mmc1: req done (CMD13): -123: 00000000 00000000 00000000 00000000
> [  255.856773] mmc1: card remove detected
> [  255.861056] mmc1: card 59b4 removed
> [  255.872872] mmc1: clock 0Hz busmode 2 powermode 0 cs 0 Vdd 0 width 0 timing 0
> 
> > 
> > Hmm.. I can't sure it's no affection.
> > e.g we did have customers reporting cd plug in/out causing jitters
> > when system is busy playing audio or video.
> > Maybe we need to do those tests.
> > 
> > Anyway, what's your point to keep sending tuning commands after card
> > is already removed?
> 
> Seems like a problem for your driver not the core.  Why not check card detect
> after the first error in esdhc_executing_tuning().
> 

It is not IMX driver problem.
IMX is based on SDHCI driver and it does check card detect for CMD13,
but sdhci_execute_tuning not.

We may either check CD in sdhci_execute_tuning() or disable tuning
for card remove case.

Personally i'd like to disable it in core since i really can't see
the meaning to keep it for card remove.

What's your idea?

Regards
Dong Aisheng

> > 
> > Regards
> > Dong Aisheng
> > 
> >>>
> >>> Regards
> >>> Dong Aisheng
> >>>
> >>>>>
> >>>>> CC: stable <stable@vger.kernel.org>
> >>>>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> >>>>> ---
> >>>>>  drivers/mmc/core/core.c | 1 +
> >>>>>  1 file changed, 1 insertion(+)
> >>>>>
> >>>>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> >>>>> index 52bfaf0..76d0802 100644
> >>>>> --- a/drivers/mmc/core/core.c
> >>>>> +++ b/drivers/mmc/core/core.c
> >>>>> @@ -1888,6 +1888,7 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
> >>>>>               pm_wakeup_event(mmc_dev(host), 5000);
> >>>>>
> >>>>>       host->detect_change = 1;
> >>>>> +     mmc_retune_disable(host);
> >>>>>       mmc_schedule_delayed_work(&host->detect, delay);
> >>>>>  }
> >>>>>
> >>>>>
> >>>>
> >>>
> >>
> >> --
> >> 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
> > 
> 

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

* Re: [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
  2016-04-29  7:32                     ` Adrian Hunter
@ 2016-04-29  7:57                       ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-29  7:57 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On Fri, Apr 29, 2016 at 10:32:36AM +0300, Adrian Hunter wrote:
> On 28/04/16 17:28, Dong Aisheng wrote:
> > On Thu, Apr 28, 2016 at 04:36:25PM +0300, Adrian Hunter wrote:
> >> On 28/04/16 16:14, Dong Aisheng wrote:
> >>> On Thu, Apr 28, 2016 at 09:39:54AM +0300, Adrian Hunter wrote:
> >>>> On 28/04/16 06:09, Dong Aisheng wrote:
> >>>>> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
> >>>>>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
> >>>>>>> Hi Adrian,
> >>>>>>>
> >>>>>>> Thanks for the review first.
> >>>>>>>
> >>>>>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> >>>>>>>> On 15/04/16 20:29, Dong Aisheng wrote:
> >>>>>>>>> Handle host and regulator signal voltage switch separately.
> >>>>>>>>> Move host signal voltage switch code into a separated function
> >>>>>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
> >>>>>>>>> remove the regulator voltage switch code and use the common
> >>>>>>>>> mmc_regulator_set_vqmmc() instead.
> >>>>>>>>
> >>>>>>>> You have changed the order that things are done.
> >>>>>>>
> >>>>>>> Yes, the oder changes a bit that we always do controller voltage switch first.
> >>>>>>> I suppose the order is irrelevant here since i don't recall any
> >>>>>>> requirement from card.
> >>>>>>>
> >>>>>>> Actually the original order is also a bit mass.
> >>>>>>> e.g.
> >>>>>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
> >>>>>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
> >>>>>>> It looks to us the original one also order irrelevant.
> >>>>>>>
> >>>>>>>> There is no way to know
> >>>>>>>> what that will break, so let's not do that.  What about just changing
> >>>>>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
> >>>>>>>>
> >>>>>>>
> >>>>>>> Currently what i can think out VIO switch using are three cases: (Pls
> >>>>>>> help add if any)
> >>>>>>> 1) Both host IO and card IO use external vqmmc to do switch
> >>>>>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
> >>>>>>>
> >>>>>>> eMMC has no IO voltage switch protocol and requirement, so usually
> >>>>>>> board designed
> >>>>>>> using fixed 1.8V for eMMC and host IO.
> >>>>>>> Event it's switchable, it should be done in the first mmc_power_up().
> >>>>>>> Dynamical switch later may cause eMMC unable to work properly.
> >>>>>>> (We have been confirmed about this issue by many eMMC vendors
> >>>>>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
> >>>>>>> still doing VIO dynamical switch for eMMC, if yes, please help share
> >>>>>>> the experience!).
> >>>>>>>
> >>>>>>> Event some people still do dynamical IO switch for eMMC, since eMMC
> >>>>>>> spec has no requirement, so the order should also not care.
> >>>>>>>
> >>>>>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
> >>>>>>>
> >>>>>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
> >>>>>>> regulator to do card IO voltage switch. It does not use external vqmmc
> >>>>>>> regulator.
> >>>>>>> So order irrelevant too.
> >>>>>>>
> >>>>>>> 3) Host using controller IO switch while card using external vqmmc
> >>>>>>> (special SDIO3.0 or eMMC)
> >>>>>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
> >>>>>>> the spec and using external regulator for card IO voltage.
> >>>>>>> Usually it's required to fix to 1.8v and also not order irrelevant.
> >>>>>>>
> >>>>>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
> >>>>>>>
> >>>>>>> So it looks all cases seems are not order required.
> >>>>>>
> >>>>>> I don't agree that there is any way to know that other host controllers
> >>>>>> are not affected.  I don't want a repeat of sdhci_set_power().
> >>>>>>
> >>>>>
> >>>>> Can you share some more info about sdhci_set_power() issue?
> >>>>> I'd like to see if we are same the issue.
> >>>>
> >>>> Not the same issue, but the same concept.  People changing the code under
> >>>> the impression that their way was correct, and then breaking other people's
> >>>> drivers.  Check the git history and mailing list.
> >>>>
> >>>> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
> >>>>
> >>>
> >>> Yes, now i understand your concern.
> >>>
> >>>>>
> >>>>> BTW, IMHO i don't think we should stop keep moving only afraid of potential
> >>>>> break if it's correct way. Because .start_signal_voltage_switch() interface
> >>>>> seems shouldn't be order dependant.
> >>>>> If it is, then it should be fixed and handled in high layer like MMC core
> >>>>> rather than in host driver. Right?
> >>>>
> >>>> The SDHCI spec. does not define how to use external regulators, so there is
> >>>> no "correct way".
> >>>>
> >>>
> >>> The "correct way" i mean here is .start_signal_voltage_switch() shouldn't be
> >>> order dependant, would you agree?
> >>
> >> No.  There is no way to know if the regulator must be switched before or
> >> after the host controller register is changed.
> >>
> > 
> > Hmm... If there is no way to know the correct order, how can we
> > assume the exist order is correct?
> 
> There is no correct order.  This is outside the SDHCI spec. and so belongs
> to individual drivers.
> 
> If it mattered we could push the ugly code down onto the drivers, and then
> driver maintainers could opt to use the new pretty code.  However at the
> moment there is a lot more important work, so I would want to avoid that
> code churn.
> 
> > And i already pointed out, the exist order is also confused that
> > it switch controller first then vqmmc for 3.3v and switch vqmmc
> > first, then controller for 1.8v
> > 
> > If we can't sure the exist order is correct, why do we block
> > the changing to correctly use mmc_regulator_set_vqmmc() to
> > improve the driver stability?
> 
> Not sure what you mean here.  I have already showed how we can use
> mmc_regulator_set_vqmmc().
> 
> > 
> > And actually the change is not made arbitrarily, i already list
> > all possibilities based on my knowledge. People can raise more
> > if any.
> 
> You are assuming every driver has a maintainer and every maintainer is
> following this thread, and understands how it might affect all the
> different versions of their hardware.  That is extremely unlikely.
> 

Yes, we can't sure it.
All we can do on breaking old rules is do it early and test people.
Potential break shouldn't block us to going forward IMHO.
But i understand at this time you may not want it.

> > The target is correct that we make start_signal_voltage_switch()
> > order independant.
> > It's worth a try even there's a potential very low possibility
> > break IMHO.
> 
> And so we disagree.
> 
> Aren't your needs met by changing to use mmc_regulator_set_vqmmc() the way I
> suggested?
> 

Well, although i'm not in favor of that way.
But as you insist, i will re-cook the patch to fix the issue first.

Regards
Dong Aisheng

> > 
> > Or else if we can find a better way to switch to
> > mmc_regulator_set_vqmmc i would also love to try.
> >  
> > Maybe we need more people's thought on it!
> > 
> > Ulf,
> > Would you give some inputs?
> > 
> > Regards
> > Dong Aisheng
> > 
> >>>
> >>>> We have to move forward *and* avoid potential breakage.
> >>>>
> >>>
> >>> If really break happens, fix platform driver, not common SDHCI.
> >>> That's the same thing you done for sdhci_set_power().
> >>
> >> In that case the original behaviour was kept in the common SDHCI code and
> >> the driver had to provide its own way.
> >>
> >>>
> >>>> In this case it seems me that the risk of breakage outweighs the value of
> >>>> prettier code.
> >>>>
> >>>
> >>> Actually my main purpose is patch 6: using mmc_regulator_set_vqmmc()
> >>> which is worth and it does improve the stability and eliminate the
> >>> potential signal issue.
> >>> However it's not the same way as you proposed.
> >>> See below.
> >>>
> >>>> By the way, there are ways to get rid of the ugliness - such as pushing it down
> >>>> into individual drivers.
> >>>>
> >>>>>
> >>>>>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
> >>>>>> in place of regulator_set_voltage().
> >>>>>
> >>>>> Just using mmc_regulator_set_vqmmc() also changes the order which
> >>>>> is the same situation.
> >>>>
> >>>> How so?  It looks like a drop-in replacement to me:
> >>>>
> >>>
> >>> Sorry, i did not get that you want to change like below.
> >>> However, it looks that it does not make too much sense to call
> >>> mmc_regulator_set_vqmmc() for each VOLTAGE type like 3.3v/1.8v/1.2v
> >>> which introduces ugliness because mmc_regulator_set_vqmmc()
> >>> already handles it internally, right?
> >>> Only because we want to keep an "ASSUMED" order as before?
> >>
> >> Yes
> >>
> >>>
> >>> Regards
> >>> Dong Aisheng
> >>>
> >>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> >>>> index 94cffa77490a..69b4d48aff87 100644
> >>>> --- a/drivers/mmc/host/sdhci.c
> >>>> +++ b/drivers/mmc/host/sdhci.c
> >>>> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> >>>>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
> >>>>  
> >>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> >>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
> >>>> -						    3600000);
> >>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
> >>>>  			if (ret) {
> >>>>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
> >>>>  					mmc_hostname(mmc));
> >>>> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> >>>>  		return -EAGAIN;
> >>>>  	case MMC_SIGNAL_VOLTAGE_180:
> >>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> >>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
> >>>> -					1700000, 1950000);
> >>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
> >>>>  			if (ret) {
> >>>>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
> >>>>  					mmc_hostname(mmc));
> >>>> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> >>>>  		return -EAGAIN;
> >>>>  	case MMC_SIGNAL_VOLTAGE_120:
> >>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> >>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
> >>>> -						    1300000);
> >>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
> >>>>  			if (ret) {
> >>>>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
> >>>>  					mmc_hostname(mmc));
> >>>>
> >>>>
> >>>>
> >>>
> >>
> > 
> 

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

* [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage()
@ 2016-04-29  7:57                       ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-04-29  7:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 29, 2016 at 10:32:36AM +0300, Adrian Hunter wrote:
> On 28/04/16 17:28, Dong Aisheng wrote:
> > On Thu, Apr 28, 2016 at 04:36:25PM +0300, Adrian Hunter wrote:
> >> On 28/04/16 16:14, Dong Aisheng wrote:
> >>> On Thu, Apr 28, 2016 at 09:39:54AM +0300, Adrian Hunter wrote:
> >>>> On 28/04/16 06:09, Dong Aisheng wrote:
> >>>>> On Wed, Apr 27, 2016 at 11:26:52PM +0300, Adrian Hunter wrote:
> >>>>>> On 24/04/2016 12:14 p.m., Dong Aisheng wrote:
> >>>>>>> Hi Adrian,
> >>>>>>>
> >>>>>>> Thanks for the review first.
> >>>>>>>
> >>>>>>> On Fri, Apr 22, 2016 at 7:43 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> >>>>>>>> On 15/04/16 20:29, Dong Aisheng wrote:
> >>>>>>>>> Handle host and regulator signal voltage switch separately.
> >>>>>>>>> Move host signal voltage switch code into a separated function
> >>>>>>>>> sdhci_do_signal_voltage_switch() first, the following patches will
> >>>>>>>>> remove the regulator voltage switch code and use the common
> >>>>>>>>> mmc_regulator_set_vqmmc() instead.
> >>>>>>>>
> >>>>>>>> You have changed the order that things are done.
> >>>>>>>
> >>>>>>> Yes, the oder changes a bit that we always do controller voltage switch first.
> >>>>>>> I suppose the order is irrelevant here since i don't recall any
> >>>>>>> requirement from card.
> >>>>>>>
> >>>>>>> Actually the original order is also a bit mass.
> >>>>>>> e.g.
> >>>>>>> For MMC_SIGNAL_VOLTAGE_330, switch controller first, then vqmmc.
> >>>>>>> But for MMC_SIGNAL_VOLTAGE_180, switch vqmmc first, then controller.
> >>>>>>> It looks to us the original one also order irrelevant.
> >>>>>>>
> >>>>>>>> There is no way to know
> >>>>>>>> what that will break, so let's not do that.  What about just changing
> >>>>>>>> regulator_set_voltage() to mmc_regulator_set_vqmmc()?
> >>>>>>>>
> >>>>>>>
> >>>>>>> Currently what i can think out VIO switch using are three cases: (Pls
> >>>>>>> help add if any)
> >>>>>>> 1) Both host IO and card IO use external vqmmc to do switch
> >>>>>>> (e.g eMMC 1.8V DDR/HS200/HS400 mode)
> >>>>>>>
> >>>>>>> eMMC has no IO voltage switch protocol and requirement, so usually
> >>>>>>> board designed
> >>>>>>> using fixed 1.8V for eMMC and host IO.
> >>>>>>> Event it's switchable, it should be done in the first mmc_power_up().
> >>>>>>> Dynamical switch later may cause eMMC unable to work properly.
> >>>>>>> (We have been confirmed about this issue by many eMMC vendors
> >>>>>>> like Micron and Sandisk. I'm not sure if any exceptions in the community
> >>>>>>> still doing VIO dynamical switch for eMMC, if yes, please help share
> >>>>>>> the experience!).
> >>>>>>>
> >>>>>>> Event some people still do dynamical IO switch for eMMC, since eMMC
> >>>>>>> spec has no requirement, so the order should also not care.
> >>>>>>>
> >>>>>>> 2) Host using controller IO switch while card using standard CMD (SD/SDIO3.0)
> >>>>>>>
> >>>>>>> SD/SDIO 3.0 spec defines the standard IO switch process and using it's internal
> >>>>>>> regulator to do card IO voltage switch. It does not use external vqmmc
> >>>>>>> regulator.
> >>>>>>> So order irrelevant too.
> >>>>>>>
> >>>>>>> 3) Host using controller IO switch while card using external vqmmc
> >>>>>>> (special SDIO3.0 or eMMC)
> >>>>>>> I have met some special SDIO3.0 card like Broadcom WiFi which does not follow
> >>>>>>> the spec and using external regulator for card IO voltage.
> >>>>>>> Usually it's required to fix to 1.8v and also not order irrelevant.
> >>>>>>>
> >>>>>>> For eMMC, refer to case 1), it should be fixed to 1.8v at power up.
> >>>>>>>
> >>>>>>> So it looks all cases seems are not order required.
> >>>>>>
> >>>>>> I don't agree that there is any way to know that other host controllers
> >>>>>> are not affected.  I don't want a repeat of sdhci_set_power().
> >>>>>>
> >>>>>
> >>>>> Can you share some more info about sdhci_set_power() issue?
> >>>>> I'd like to see if we are same the issue.
> >>>>
> >>>> Not the same issue, but the same concept.  People changing the code under
> >>>> the impression that their way was correct, and then breaking other people's
> >>>> drivers.  Check the git history and mailing list.
> >>>>
> >>>> 	http://marc.info/?l=linux-mmc&m=145880454106474&w=2
> >>>>
> >>>
> >>> Yes, now i understand your concern.
> >>>
> >>>>>
> >>>>> BTW, IMHO i don't think we should stop keep moving only afraid of potential
> >>>>> break if it's correct way. Because .start_signal_voltage_switch() interface
> >>>>> seems shouldn't be order dependant.
> >>>>> If it is, then it should be fixed and handled in high layer like MMC core
> >>>>> rather than in host driver. Right?
> >>>>
> >>>> The SDHCI spec. does not define how to use external regulators, so there is
> >>>> no "correct way".
> >>>>
> >>>
> >>> The "correct way" i mean here is .start_signal_voltage_switch() shouldn't be
> >>> order dependant, would you agree?
> >>
> >> No.  There is no way to know if the regulator must be switched before or
> >> after the host controller register is changed.
> >>
> > 
> > Hmm... If there is no way to know the correct order, how can we
> > assume the exist order is correct?
> 
> There is no correct order.  This is outside the SDHCI spec. and so belongs
> to individual drivers.
> 
> If it mattered we could push the ugly code down onto the drivers, and then
> driver maintainers could opt to use the new pretty code.  However at the
> moment there is a lot more important work, so I would want to avoid that
> code churn.
> 
> > And i already pointed out, the exist order is also confused that
> > it switch controller first then vqmmc for 3.3v and switch vqmmc
> > first, then controller for 1.8v
> > 
> > If we can't sure the exist order is correct, why do we block
> > the changing to correctly use mmc_regulator_set_vqmmc() to
> > improve the driver stability?
> 
> Not sure what you mean here.  I have already showed how we can use
> mmc_regulator_set_vqmmc().
> 
> > 
> > And actually the change is not made arbitrarily, i already list
> > all possibilities based on my knowledge. People can raise more
> > if any.
> 
> You are assuming every driver has a maintainer and every maintainer is
> following this thread, and understands how it might affect all the
> different versions of their hardware.  That is extremely unlikely.
> 

Yes, we can't sure it.
All we can do on breaking old rules is do it early and test people.
Potential break shouldn't block us to going forward IMHO.
But i understand at this time you may not want it.

> > The target is correct that we make start_signal_voltage_switch()
> > order independant.
> > It's worth a try even there's a potential very low possibility
> > break IMHO.
> 
> And so we disagree.
> 
> Aren't your needs met by changing to use mmc_regulator_set_vqmmc() the way I
> suggested?
> 

Well, although i'm not in favor of that way.
But as you insist, i will re-cook the patch to fix the issue first.

Regards
Dong Aisheng

> > 
> > Or else if we can find a better way to switch to
> > mmc_regulator_set_vqmmc i would also love to try.
> >  
> > Maybe we need more people's thought on it!
> > 
> > Ulf,
> > Would you give some inputs?
> > 
> > Regards
> > Dong Aisheng
> > 
> >>>
> >>>> We have to move forward *and* avoid potential breakage.
> >>>>
> >>>
> >>> If really break happens, fix platform driver, not common SDHCI.
> >>> That's the same thing you done for sdhci_set_power().
> >>
> >> In that case the original behaviour was kept in the common SDHCI code and
> >> the driver had to provide its own way.
> >>
> >>>
> >>>> In this case it seems me that the risk of breakage outweighs the value of
> >>>> prettier code.
> >>>>
> >>>
> >>> Actually my main purpose is patch 6: using mmc_regulator_set_vqmmc()
> >>> which is worth and it does improve the stability and eliminate the
> >>> potential signal issue.
> >>> However it's not the same way as you proposed.
> >>> See below.
> >>>
> >>>> By the way, there are ways to get rid of the ugliness - such as pushing it down
> >>>> into individual drivers.
> >>>>
> >>>>>
> >>>>>> Please instead send a patch for just using mmc_regulator_set_vqmmc()
> >>>>>> in place of regulator_set_voltage().
> >>>>>
> >>>>> Just using mmc_regulator_set_vqmmc() also changes the order which
> >>>>> is the same situation.
> >>>>
> >>>> How so?  It looks like a drop-in replacement to me:
> >>>>
> >>>
> >>> Sorry, i did not get that you want to change like below.
> >>> However, it looks that it does not make too much sense to call
> >>> mmc_regulator_set_vqmmc() for each VOLTAGE type like 3.3v/1.8v/1.2v
> >>> which introduces ugliness because mmc_regulator_set_vqmmc()
> >>> already handles it internally, right?
> >>> Only because we want to keep an "ASSUMED" order as before?
> >>
> >> Yes
> >>
> >>>
> >>> Regards
> >>> Dong Aisheng
> >>>
> >>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> >>>> index 94cffa77490a..69b4d48aff87 100644
> >>>> --- a/drivers/mmc/host/sdhci.c
> >>>> +++ b/drivers/mmc/host/sdhci.c
> >>>> @@ -1757,8 +1757,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> >>>>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
> >>>>  
> >>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> >>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
> >>>> -						    3600000);
> >>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
> >>>>  			if (ret) {
> >>>>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
> >>>>  					mmc_hostname(mmc));
> >>>> @@ -1779,8 +1778,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> >>>>  		return -EAGAIN;
> >>>>  	case MMC_SIGNAL_VOLTAGE_180:
> >>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> >>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc,
> >>>> -					1700000, 1950000);
> >>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
> >>>>  			if (ret) {
> >>>>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
> >>>>  					mmc_hostname(mmc));
> >>>> @@ -1810,8 +1808,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> >>>>  		return -EAGAIN;
> >>>>  	case MMC_SIGNAL_VOLTAGE_120:
> >>>>  		if (!IS_ERR(mmc->supply.vqmmc)) {
> >>>> -			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
> >>>> -						    1300000);
> >>>> +			ret = mmc_regulator_set_vqmmc(mmc, ios);
> >>>>  			if (ret) {
> >>>>  				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
> >>>>  					mmc_hostname(mmc));
> >>>>
> >>>>
> >>>>
> >>>
> >>
> > 
> 

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

* Re: [PATCH 01/23] mmc: sdhci: removed unneeded function wrappers
  2016-04-22 10:27     ` Adrian Hunter
@ 2016-05-10  6:32       ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10  6:32 UTC (permalink / raw)
  To: ulf.hansson
  Cc: Dong Aisheng, linux-mmc, chris, shawnguo, linux-arm-kernel,
	haibo.chen, dongas86

On 22/04/16 13:27, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
>> After commit d6463f170cf0 ("mmc: sdhci: Remove redundant runtime PM calls"),
>> some of original sdhci_do_xx() function wrappers becomes meaningless,
>> so remove them.
>>
>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> 
> Didn't apply cleanly, otherwise:
> 
> Acked-by: Adrian Hunter <adrian.hunter@intel.com>

Ulf, will you apply this one?


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

* [PATCH 01/23] mmc: sdhci: removed unneeded function wrappers
@ 2016-05-10  6:32       ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10  6:32 UTC (permalink / raw)
  To: linux-arm-kernel

On 22/04/16 13:27, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
>> After commit d6463f170cf0 ("mmc: sdhci: Remove redundant runtime PM calls"),
>> some of original sdhci_do_xx() function wrappers becomes meaningless,
>> so remove them.
>>
>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> 
> Didn't apply cleanly, otherwise:
> 
> Acked-by: Adrian Hunter <adrian.hunter@intel.com>

Ulf, will you apply this one?

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

* Re: [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during no data transfer
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-05-10  6:51     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10  6:51 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> Current code will report the wrong data interrupt got when no
> data operation in progress assumed by getting !host->data in
> sdhci_data_irq().
> 
> For a data command handling process, the driver will call
> sdhci_finish_data() and clear host->data in case any data error,
> then card finish_tasklet will do the rest controller reset work.
> 
> Before the tasklet got run, however, controllers may report the
> TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
> than data CRC error and data end bit error interrupts for single
> block transfer or the last block of multiblock transfer.
> 
> Controller usually detects and generates data CRC/end bit error
> interrupts once one block on the bus is transferred completely.
> For single block transfer, since there's only one bock to transfer,
> the controller will report transfer complete interrupt as well,
> but until the data in controller FIFO has been successfully
> transferred to memory. The time gap of TC and CRC interrupt depends on
> the system busy state at that point and memory bus access speed.
> 
> So it is possible when TC interrupt generated, host->data is already
> equal to NULL due to cleared by former CRC/Data End Bit error which
> is reasonable.
> 
> Thus we DO NOT report the weird data interrupt event for this case.
> 
> Else we may easily see warning below during SD3.0 card manually tuning
> process (calling mmc_send_tuning() which is a single block transfer)
> mmc0: Got data interrupt 0x00000002 even though no data operation was in progress
> 
> The detailed command log is as follows:
> [ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
> [ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
> [ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
> [ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
> [ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
> [ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
> [ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
> [ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
> [ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
> [ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
> [ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
> [ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
> [ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
> [ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
> [ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
> [ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
> [ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
> [ 1657.929965] sdhci: Host ctl2: 0x000000c8
> [ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
> [ 1657.929995] sdhci: ===========================================
> [ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
> [ 1657.930179] mmc0:     0 bytes transferred: -84
> 
> It shows we first have a data CRC error interrupt then a data transfer
> complete interrupt.
> Then we got the !host->data case in sdhci_data_irq().
> 
> CC: stable <stable@vger.kernel.org>
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
>  drivers/mmc/host/sdhci.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 40e3551..2eb0e34 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
>  			}
>  		}
>  
> +		/*
> +		 * The "data complete" interrupt is possible to happen a bit
> +		 * later than CRC error and data end bit error interrupts
> +		 * separately for single block transfer or the last block of
> +		 * multiblock transfer. For this case, we DO NOT report the
> +		 * weird data interrupt event.
> +		 */
> +		if ((intmask & SDHCI_INT_DATA_END) &&
> +		    (host->mrq && host->mrq->data && host->mrq->data->error))
> +			return;

This could be generalized a bit more i.e. what about:

		/*
		 * After an error and before the the data circuit is reset in
		 * sdhci_tasklet_finish, we could get more interrupts, but we
		 * already have an error, so ignore them.
		 */
		if (host->mrq && host->mrq->data && host->mrq->data->error)
			return;

> +
>  		pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
>  		       mmc_hostname(host->mmc), (unsigned)intmask);
>  		sdhci_dumpregs(host);
> 


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

* [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during no data transfer
@ 2016-05-10  6:51     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10  6:51 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> Current code will report the wrong data interrupt got when no
> data operation in progress assumed by getting !host->data in
> sdhci_data_irq().
> 
> For a data command handling process, the driver will call
> sdhci_finish_data() and clear host->data in case any data error,
> then card finish_tasklet will do the rest controller reset work.
> 
> Before the tasklet got run, however, controllers may report the
> TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
> than data CRC error and data end bit error interrupts for single
> block transfer or the last block of multiblock transfer.
> 
> Controller usually detects and generates data CRC/end bit error
> interrupts once one block on the bus is transferred completely.
> For single block transfer, since there's only one bock to transfer,
> the controller will report transfer complete interrupt as well,
> but until the data in controller FIFO has been successfully
> transferred to memory. The time gap of TC and CRC interrupt depends on
> the system busy state at that point and memory bus access speed.
> 
> So it is possible when TC interrupt generated, host->data is already
> equal to NULL due to cleared by former CRC/Data End Bit error which
> is reasonable.
> 
> Thus we DO NOT report the weird data interrupt event for this case.
> 
> Else we may easily see warning below during SD3.0 card manually tuning
> process (calling mmc_send_tuning() which is a single block transfer)
> mmc0: Got data interrupt 0x00000002 even though no data operation was in progress
> 
> The detailed command log is as follows:
> [ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
> [ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
> [ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
> [ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
> [ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
> [ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
> [ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
> [ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
> [ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
> [ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
> [ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
> [ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
> [ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
> [ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
> [ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
> [ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
> [ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
> [ 1657.929965] sdhci: Host ctl2: 0x000000c8
> [ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
> [ 1657.929995] sdhci: ===========================================
> [ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
> [ 1657.930179] mmc0:     0 bytes transferred: -84
> 
> It shows we first have a data CRC error interrupt then a data transfer
> complete interrupt.
> Then we got the !host->data case in sdhci_data_irq().
> 
> CC: stable <stable@vger.kernel.org>
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
>  drivers/mmc/host/sdhci.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 40e3551..2eb0e34 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
>  			}
>  		}
>  
> +		/*
> +		 * The "data complete" interrupt is possible to happen a bit
> +		 * later than CRC error and data end bit error interrupts
> +		 * separately for single block transfer or the last block of
> +		 * multiblock transfer. For this case, we DO NOT report the
> +		 * weird data interrupt event.
> +		 */
> +		if ((intmask & SDHCI_INT_DATA_END) &&
> +		    (host->mrq && host->mrq->data && host->mrq->data->error))
> +			return;

This could be generalized a bit more i.e. what about:

		/*
		 * After an error and before the the data circuit is reset in
		 * sdhci_tasklet_finish, we could get more interrupts, but we
		 * already have an error, so ignore them.
		 */
		if (host->mrq && host->mrq->data && host->mrq->data->error)
			return;

> +
>  		pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
>  		       mmc_hostname(host->mmc), (unsigned)intmask);
>  		sdhci_dumpregs(host);
> 

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

* Re: [PATCH 10/23] mmc: core: disable auto retune during card detection process
  2016-04-29  7:42               ` Dong Aisheng
@ 2016-05-10  6:55                 ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10  6:55 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On 29/04/16 10:42, Dong Aisheng wrote:
> And IMX6DL ARD is even worser due to it's using common
> mmc_send_tuning() function.
> root@imx6qdlsolo:~# 
> root@imx6qdlsolo:~# [  129.462564] sysrq: SysRq : Changing Loglevel
> [  129.466902] sysrq: Loglevel set to 8
> [  131.616078] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
> [  131.625311] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 6
> [  131.632133] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
> [  131.642121] mmc0: starting CMD13 arg 59b40000 flags 00000195
> [  131.648925] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x0 ESDHC_TUNE_CTRL_STATUS 0x0
> [  131.657818] mmc0: starting CMD19 arg 00000000 flags 00000035
> [  131.663518] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
> [  131.670835] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000

You should stop here because -123 is -ENOMEDIUM


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

* [PATCH 10/23] mmc: core: disable auto retune during card detection process
@ 2016-05-10  6:55                 ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10  6:55 UTC (permalink / raw)
  To: linux-arm-kernel

On 29/04/16 10:42, Dong Aisheng wrote:
> And IMX6DL ARD is even worser due to it's using common
> mmc_send_tuning() function.
> root at imx6qdlsolo:~# 
> root at imx6qdlsolo:~# [  129.462564] sysrq: SysRq : Changing Loglevel
> [  129.466902] sysrq: Loglevel set to 8
> [  131.616078] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
> [  131.625311] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 6
> [  131.632133] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
> [  131.642121] mmc0: starting CMD13 arg 59b40000 flags 00000195
> [  131.648925] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x0 ESDHC_TUNE_CTRL_STATUS 0x0
> [  131.657818] mmc0: starting CMD19 arg 00000000 flags 00000035
> [  131.663518] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
> [  131.670835] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000

You should stop here because -123 is -ENOMEDIUM

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

* Re: [PATCH 17/23] mmc: sdhci: add standard hw auto retuning support
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-05-10  8:35     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10  8:35 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> If HW supports SDHCI_TUNING_MODE_3 which is auto retuning, we won't

Since this is about tuning mode 3, could you put that in the subject e.g.
"Add support for auto re-tuning (tuning mode 3)"

> retune during runtime suspend and resume, instead we use Re-tuning
> Request signaled via SDHCI_INT_RETUNE interrupt to do retuning and
> hw auto retuning during data transfer to guarantee the signal sample
> window correction.
> 
> This can avoid a mass of repeatly retuning during small file system

repeatly -> repeatedly

> data access and improve the performance.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
>  drivers/mmc/host/sdhci.c | 18 ++++++++++++++----
>  drivers/mmc/host/sdhci.h |  3 +++
>  2 files changed, 17 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 2eb0e34..0027b87 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -252,6 +252,9 @@ static void sdhci_init(struct sdhci_host *host, int soft)
>  		    SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END |
>  		    SDHCI_INT_RESPONSE;
>  
> +	if (host->tuning_mode == SDHCI_TUNING_MODE_3)

Tuning mode 2 uses this as well.  Might as well add it here.

> +		host->ier |= SDHCI_INT_RETUNE;
> +
>  	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
>  	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
>  
> @@ -2477,6 +2480,9 @@ 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_RETUNE)
> +			mmc_retune_needed(host->mmc);
> +

Also need to add SDHCI_INT_RETUNE to the bits cleared further on, otherwise
it will show up in the "Unexpected interrupt" message

>  		if (intmask & SDHCI_INT_CARD_INT) {
>  			sdhci_enable_sdio_irq_nolock(host, false);
>  			host->thread_isr |= SDHCI_INT_CARD_INT;
> @@ -2575,8 +2581,10 @@ int sdhci_suspend_host(struct sdhci_host *host)
>  {
>  	sdhci_disable_card_detection(host);
>  
> -	mmc_retune_timer_stop(host->mmc);
> -	mmc_retune_needed(host->mmc);
> +	if (host->tuning_mode == SDHCI_TUNING_MODE_1) {
> +		mmc_retune_timer_stop(host->mmc);
> +		mmc_retune_needed(host->mmc);
> +	}

Probably wouldn't hurt to stop the timer always whether it's going or not.
And tuning mode 2 is not auto re-tuning, so I would still expect to need
re-tuning after power loss i.e.

	mmc_retune_timer_stop(host->mmc);
	if (host->tuning_mode != SDHCI_TUNING_MODE_3)
		mmc_retune_needed(host->mmc);

>  
>  	if (!device_may_wakeup(mmc_dev(host->mmc))) {
>  		host->ier = 0;
> @@ -2651,8 +2659,10 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
>  {
>  	unsigned long flags;
>  
> -	mmc_retune_timer_stop(host->mmc);
> -	mmc_retune_needed(host->mmc);
> +	if (host->tuning_mode == SDHCI_TUNING_MODE_1) {
> +		mmc_retune_timer_stop(host->mmc);
> +		mmc_retune_needed(host->mmc);
> +	}

Ditto

>  
>  	spin_lock_irqsave(&host->lock, flags);
>  	host->ier &= SDHCI_INT_CARD_INT;
> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index afa4de8..2c2404f 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -128,6 +128,7 @@
>  #define  SDHCI_INT_CARD_INSERT	0x00000040
>  #define  SDHCI_INT_CARD_REMOVE	0x00000080
>  #define  SDHCI_INT_CARD_INT	0x00000100
> +#define  SDHCI_INT_RETUNE	0x00001000
>  #define  SDHCI_INT_ERROR	0x00008000
>  #define  SDHCI_INT_TIMEOUT	0x00010000
>  #define  SDHCI_INT_CRC		0x00020000
> @@ -514,6 +515,8 @@ struct sdhci_host {
>  	unsigned int		tuning_count;	/* Timer count for re-tuning */
>  	unsigned int		tuning_mode;	/* Re-tuning mode supported by host */
>  #define SDHCI_TUNING_MODE_1	0
> +#define SDHCI_TUNING_MODE_2	1
> +#define SDHCI_TUNING_MODE_3	2
>  
>  	unsigned long private[0] ____cacheline_aligned;
>  };
> 


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

* [PATCH 17/23] mmc: sdhci: add standard hw auto retuning support
@ 2016-05-10  8:35     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10  8:35 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> If HW supports SDHCI_TUNING_MODE_3 which is auto retuning, we won't

Since this is about tuning mode 3, could you put that in the subject e.g.
"Add support for auto re-tuning (tuning mode 3)"

> retune during runtime suspend and resume, instead we use Re-tuning
> Request signaled via SDHCI_INT_RETUNE interrupt to do retuning and
> hw auto retuning during data transfer to guarantee the signal sample
> window correction.
> 
> This can avoid a mass of repeatly retuning during small file system

repeatly -> repeatedly

> data access and improve the performance.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
>  drivers/mmc/host/sdhci.c | 18 ++++++++++++++----
>  drivers/mmc/host/sdhci.h |  3 +++
>  2 files changed, 17 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 2eb0e34..0027b87 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -252,6 +252,9 @@ static void sdhci_init(struct sdhci_host *host, int soft)
>  		    SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END |
>  		    SDHCI_INT_RESPONSE;
>  
> +	if (host->tuning_mode == SDHCI_TUNING_MODE_3)

Tuning mode 2 uses this as well.  Might as well add it here.

> +		host->ier |= SDHCI_INT_RETUNE;
> +
>  	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
>  	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
>  
> @@ -2477,6 +2480,9 @@ 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_RETUNE)
> +			mmc_retune_needed(host->mmc);
> +

Also need to add SDHCI_INT_RETUNE to the bits cleared further on, otherwise
it will show up in the "Unexpected interrupt" message

>  		if (intmask & SDHCI_INT_CARD_INT) {
>  			sdhci_enable_sdio_irq_nolock(host, false);
>  			host->thread_isr |= SDHCI_INT_CARD_INT;
> @@ -2575,8 +2581,10 @@ int sdhci_suspend_host(struct sdhci_host *host)
>  {
>  	sdhci_disable_card_detection(host);
>  
> -	mmc_retune_timer_stop(host->mmc);
> -	mmc_retune_needed(host->mmc);
> +	if (host->tuning_mode == SDHCI_TUNING_MODE_1) {
> +		mmc_retune_timer_stop(host->mmc);
> +		mmc_retune_needed(host->mmc);
> +	}

Probably wouldn't hurt to stop the timer always whether it's going or not.
And tuning mode 2 is not auto re-tuning, so I would still expect to need
re-tuning after power loss i.e.

	mmc_retune_timer_stop(host->mmc);
	if (host->tuning_mode != SDHCI_TUNING_MODE_3)
		mmc_retune_needed(host->mmc);

>  
>  	if (!device_may_wakeup(mmc_dev(host->mmc))) {
>  		host->ier = 0;
> @@ -2651,8 +2659,10 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
>  {
>  	unsigned long flags;
>  
> -	mmc_retune_timer_stop(host->mmc);
> -	mmc_retune_needed(host->mmc);
> +	if (host->tuning_mode == SDHCI_TUNING_MODE_1) {
> +		mmc_retune_timer_stop(host->mmc);
> +		mmc_retune_needed(host->mmc);
> +	}

Ditto

>  
>  	spin_lock_irqsave(&host->lock, flags);
>  	host->ier &= SDHCI_INT_CARD_INT;
> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index afa4de8..2c2404f 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -128,6 +128,7 @@
>  #define  SDHCI_INT_CARD_INSERT	0x00000040
>  #define  SDHCI_INT_CARD_REMOVE	0x00000080
>  #define  SDHCI_INT_CARD_INT	0x00000100
> +#define  SDHCI_INT_RETUNE	0x00001000
>  #define  SDHCI_INT_ERROR	0x00008000
>  #define  SDHCI_INT_TIMEOUT	0x00010000
>  #define  SDHCI_INT_CRC		0x00020000
> @@ -514,6 +515,8 @@ struct sdhci_host {
>  	unsigned int		tuning_count;	/* Timer count for re-tuning */
>  	unsigned int		tuning_mode;	/* Re-tuning mode supported by host */
>  #define SDHCI_TUNING_MODE_1	0
> +#define SDHCI_TUNING_MODE_2	1
> +#define SDHCI_TUNING_MODE_3	2
>  
>  	unsigned long private[0] ____cacheline_aligned;
>  };
> 

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

* Re: [PATCH 11/23] mmc: sdhci-esdhci-imx: remove SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-05-10  9:30     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10  9:30 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> The driver has already implemented the private .set_timeout()
> callback for common SDHCI code to do correct timeout value setting,
> it does not need call sdhci_calc_timeout(), so this quirk actually
> is not working. Remove it now.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

Pedantically, the subject needs:

	sdhci-esdhci-imx -> sdhci-esdhc-imx

Otherwise:

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 2d300d8..03980db 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -1147,8 +1147,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
>  	if (IS_ERR(imx_data->pins_default))
>  		dev_warn(mmc_dev(host->mmc), "could not get default state\n");
>  
> -	host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
> -
>  	if (imx_data->socdata->flags & ESDHC_FLAG_ENGCM07207)
>  		/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
>  		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK
> 


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

* [PATCH 11/23] mmc: sdhci-esdhci-imx: remove SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
@ 2016-05-10  9:30     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10  9:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> The driver has already implemented the private .set_timeout()
> callback for common SDHCI code to do correct timeout value setting,
> it does not need call sdhci_calc_timeout(), so this quirk actually
> is not working. Remove it now.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

Pedantically, the subject needs:

	sdhci-esdhci-imx -> sdhci-esdhc-imx

Otherwise:

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 2d300d8..03980db 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -1147,8 +1147,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
>  	if (IS_ERR(imx_data->pins_default))
>  		dev_warn(mmc_dev(host->mmc), "could not get default state\n");
>  
> -	host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
> -
>  	if (imx_data->socdata->flags & ESDHC_FLAG_ENGCM07207)
>  		/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
>  		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK
> 

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

* Re: [PATCH 13/23] mmc: sdhci-esdhc-imx: restore watermark level setting after resume
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-05-10  9:30     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10  9:30 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> Currently, we config the watermark_level register only in probe.
> This will cause the mmc write operation timeout issue after system
> resume back in LPSR mode. Because in LPSR mode, after system resume
> back, the watermark_level register(0x44) changes to 0x08000880, which
> set the write watermark level as 0, and set the read watermark level
> as 128. This value is incorrect.
> 
> This patch restores the setting of watermark level register after
> system resume back.

In sdhci_esdhc_imx_probe() the watermark setting is conditional on
esdhc_is_usdhc(imx_data), but in the resume it is not.  Is that intended?
If so, maybe explain that in the commit message.

Might be worth pulling out the constant 0x10401040 and #defining it since it
is used in more than one place too.

> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 6fef6bc..4c28fbb 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -1261,6 +1261,11 @@ static int sdhci_esdhc_suspend(struct device *dev)
>  
>  static int sdhci_esdhc_resume(struct device *dev)
>  {
> +	struct sdhci_host *host = dev_get_drvdata(dev);
> +
> +	/* restore watermark setting in case it's lost in low power mode */
> +	writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> +
>  	return sdhci_pltfm_resume(dev);
>  }
>  
> 


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

* [PATCH 13/23] mmc: sdhci-esdhc-imx: restore watermark level setting after resume
@ 2016-05-10  9:30     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10  9:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> Currently, we config the watermark_level register only in probe.
> This will cause the mmc write operation timeout issue after system
> resume back in LPSR mode. Because in LPSR mode, after system resume
> back, the watermark_level register(0x44) changes to 0x08000880, which
> set the write watermark level as 0, and set the read watermark level
> as 128. This value is incorrect.
> 
> This patch restores the setting of watermark level register after
> system resume back.

In sdhci_esdhc_imx_probe() the watermark setting is conditional on
esdhc_is_usdhc(imx_data), but in the resume it is not.  Is that intended?
If so, maybe explain that in the commit message.

Might be worth pulling out the constant 0x10401040 and #defining it since it
is used in more than one place too.

> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 6fef6bc..4c28fbb 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -1261,6 +1261,11 @@ static int sdhci_esdhc_suspend(struct device *dev)
>  
>  static int sdhci_esdhc_resume(struct device *dev)
>  {
> +	struct sdhci_host *host = dev_get_drvdata(dev);
> +
> +	/* restore watermark setting in case it's lost in low power mode */
> +	writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> +
>  	return sdhci_pltfm_resume(dev);
>  }
>  
> 

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

* Re: [PATCH 12/23] mmc: sdhci-esdhc-imx: add esdhc specific suspend resume callback
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-05-10  9:35     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10  9:35 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> It will be used for platform specific suspend/resume state save/restore
> work for some low power mode like Mega/Fast or LPSR mode.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 12 +++++++++++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 03980db..6fef6bc 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -1254,6 +1254,16 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev)
>  }
>  
>  #ifdef CONFIG_PM
> +static int sdhci_esdhc_suspend(struct device *dev)
> +{
> +	return sdhci_pltfm_suspend(dev);
> +}
> +
> +static int sdhci_esdhc_resume(struct device *dev)
> +{
> +	return sdhci_pltfm_resume(dev);
> +}
> +
>  static int sdhci_esdhc_runtime_suspend(struct device *dev)
>  {
>  	struct sdhci_host *host = dev_get_drvdata(dev);
> @@ -1289,7 +1299,7 @@ static int sdhci_esdhc_runtime_resume(struct device *dev)
>  #endif
>  
>  static const struct dev_pm_ops sdhci_esdhc_pmops = {
> -	SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_suspend, sdhci_pltfm_resume)
> +	SET_SYSTEM_SLEEP_PM_OPS(sdhci_esdhc_suspend, sdhci_esdhc_resume)
>  	SET_RUNTIME_PM_OPS(sdhci_esdhc_runtime_suspend,
>  				sdhci_esdhc_runtime_resume, NULL)
>  };
> 


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

* [PATCH 12/23] mmc: sdhci-esdhc-imx: add esdhc specific suspend resume callback
@ 2016-05-10  9:35     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10  9:35 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> It will be used for platform specific suspend/resume state save/restore
> work for some low power mode like Mega/Fast or LPSR mode.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 12 +++++++++++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 03980db..6fef6bc 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -1254,6 +1254,16 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev)
>  }
>  
>  #ifdef CONFIG_PM
> +static int sdhci_esdhc_suspend(struct device *dev)
> +{
> +	return sdhci_pltfm_suspend(dev);
> +}
> +
> +static int sdhci_esdhc_resume(struct device *dev)
> +{
> +	return sdhci_pltfm_resume(dev);
> +}
> +
>  static int sdhci_esdhc_runtime_suspend(struct device *dev)
>  {
>  	struct sdhci_host *host = dev_get_drvdata(dev);
> @@ -1289,7 +1299,7 @@ static int sdhci_esdhc_runtime_resume(struct device *dev)
>  #endif
>  
>  static const struct dev_pm_ops sdhci_esdhc_pmops = {
> -	SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_suspend, sdhci_pltfm_resume)
> +	SET_SYSTEM_SLEEP_PM_OPS(sdhci_esdhc_suspend, sdhci_esdhc_resume)
>  	SET_RUNTIME_PM_OPS(sdhci_esdhc_runtime_suspend,
>  				sdhci_esdhc_runtime_resume, NULL)
>  };
> 

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

* Re: [PATCH 01/23] mmc: sdhci: removed unneeded function wrappers
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-05-10  9:46     ` Ulf Hansson
  -1 siblings, 0 replies; 170+ messages in thread
From: Ulf Hansson @ 2016-05-10  9:46 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: linux-mmc, Chris Ball, Shawn Guo, Adrian Hunter,
	linux-arm-kernel, Haibo Chen, Dong Aisheng

On 15 April 2016 at 19:29, Dong Aisheng <aisheng.dong@nxp.com> wrote:
> After commit d6463f170cf0 ("mmc: sdhci: Remove redundant runtime PM calls"),
> some of original sdhci_do_xx() function wrappers becomes meaningless,
> so remove them.
>
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

Thanks, applied for next!

Kind regards
Uffe

> ---
>  drivers/mmc/host/sdhci.c | 60 ++++++++++++------------------------------------
>  1 file changed, 15 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 8e74e75..be52a3a 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -53,7 +53,7 @@ static void sdhci_finish_data(struct sdhci_host *);
>  static void sdhci_finish_command(struct sdhci_host *);
>  static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
>  static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
> -static int sdhci_do_get_cd(struct sdhci_host *host);
> +static int sdhci_get_cd(struct mmc_host *mmc);
>
>  #ifdef CONFIG_PM
>  static void sdhci_runtime_pm_bus_on(struct sdhci_host *host);
> @@ -194,7 +194,7 @@ EXPORT_SYMBOL_GPL(sdhci_reset);
>  static void sdhci_do_reset(struct sdhci_host *host, u8 mask)
>  {
>         if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
> -               if (!sdhci_do_get_cd(host))
> +               if (!sdhci_get_cd(host->mmc))
>                         return;
>         }
>
> @@ -1393,11 +1393,11 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
>  }
>  EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);
>
> -static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
> +static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  {
> +       struct sdhci_host *host = mmc_priv(mmc);
>         unsigned long flags;
>         u8 ctrl;
> -       struct mmc_host *mmc = host->mmc;
>
>         spin_lock_irqsave(&host->lock, flags);
>
> @@ -1551,16 +1551,10 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
>         spin_unlock_irqrestore(&host->lock, flags);
>  }
>
> -static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> +static int sdhci_get_cd(struct mmc_host *mmc)
>  {
>         struct sdhci_host *host = mmc_priv(mmc);
> -
> -       sdhci_do_set_ios(host, ios);
> -}
> -
> -static int sdhci_do_get_cd(struct sdhci_host *host)
> -{
> -       int gpio_cd = mmc_gpio_get_cd(host->mmc);
> +       int gpio_cd = mmc_gpio_get_cd(mmc);
>
>         if (host->flags & SDHCI_DEVICE_DEAD)
>                 return 0;
> @@ -1584,13 +1578,6 @@ static int sdhci_do_get_cd(struct sdhci_host *host)
>         return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
>  }
>
> -static int sdhci_get_cd(struct mmc_host *mmc)
> -{
> -       struct sdhci_host *host = mmc_priv(mmc);
> -
> -       return sdhci_do_get_cd(host);
> -}
> -
>  static int sdhci_check_ro(struct sdhci_host *host)
>  {
>         unsigned long flags;
> @@ -1615,8 +1602,9 @@ static int sdhci_check_ro(struct sdhci_host *host)
>
>  #define SAMPLE_COUNT   5
>
> -static int sdhci_do_get_ro(struct sdhci_host *host)
> +static int sdhci_get_ro(struct mmc_host *mmc)
>  {
> +       struct sdhci_host *host = mmc_priv(mmc);
>         int i, ro_count;
>
>         if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT))
> @@ -1641,13 +1629,6 @@ static void sdhci_hw_reset(struct mmc_host *mmc)
>                 host->ops->hw_reset(host);
>  }
>
> -static int sdhci_get_ro(struct mmc_host *mmc)
> -{
> -       struct sdhci_host *host = mmc_priv(mmc);
> -
> -       return sdhci_do_get_ro(host);
> -}
> -
>  static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
>  {
>         if (!(host->flags & SDHCI_DEVICE_DEAD)) {
> @@ -1677,10 +1658,10 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
>         spin_unlock_irqrestore(&host->lock, flags);
>  }
>
> -static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> -                                               struct mmc_ios *ios)
> +static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
> +                                            struct mmc_ios *ios)
>  {
> -       struct mmc_host *mmc = host->mmc;
> +       struct sdhci_host *host = mmc_priv(mmc);
>         u16 ctrl;
>         int ret;
>
> @@ -1768,17 +1749,6 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>         }
>  }
>
> -static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
> -       struct mmc_ios *ios)
> -{
> -       struct sdhci_host *host = mmc_priv(mmc);
> -
> -       if (host->version < SDHCI_SPEC_300)
> -               return 0;
> -
> -       return sdhci_do_start_signal_voltage_switch(host, ios);
> -}
> -
>  static int sdhci_card_busy(struct mmc_host *mmc)
>  {
>         struct sdhci_host *host = mmc_priv(mmc);
> @@ -2070,7 +2040,7 @@ static void sdhci_card_event(struct mmc_host *mmc)
>         if (host->ops->card_event)
>                 host->ops->card_event(host);
>
> -       present = sdhci_do_get_cd(host);
> +       present = sdhci_get_cd(host->mmc);
>
>         spin_lock_irqsave(&host->lock, flags);
>
> @@ -2643,7 +2613,7 @@ int sdhci_resume_host(struct sdhci_host *host)
>                 sdhci_init(host, 0);
>                 host->pwr = 0;
>                 host->clock = 0;
> -               sdhci_do_set_ios(host, &host->mmc->ios);
> +               sdhci_set_ios(host->mmc, &host->mmc->ios);
>         } else {
>                 sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER));
>                 mmiowb();
> @@ -2721,8 +2691,8 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
>         /* Force clock and power re-program */
>         host->pwr = 0;
>         host->clock = 0;
> -       sdhci_do_start_signal_voltage_switch(host, &host->mmc->ios);
> -       sdhci_do_set_ios(host, &host->mmc->ios);
> +       sdhci_start_signal_voltage_switch(host->mmc, &host->mmc->ios);
> +       sdhci_set_ios(host->mmc, &host->mmc->ios);
>
>         if ((host_flags & SDHCI_PV_ENABLED) &&
>                 !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) {
> --
> 1.9.1
>

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

* [PATCH 01/23] mmc: sdhci: removed unneeded function wrappers
@ 2016-05-10  9:46     ` Ulf Hansson
  0 siblings, 0 replies; 170+ messages in thread
From: Ulf Hansson @ 2016-05-10  9:46 UTC (permalink / raw)
  To: linux-arm-kernel

On 15 April 2016 at 19:29, Dong Aisheng <aisheng.dong@nxp.com> wrote:
> After commit d6463f170cf0 ("mmc: sdhci: Remove redundant runtime PM calls"),
> some of original sdhci_do_xx() function wrappers becomes meaningless,
> so remove them.
>
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

Thanks, applied for next!

Kind regards
Uffe

> ---
>  drivers/mmc/host/sdhci.c | 60 ++++++++++++------------------------------------
>  1 file changed, 15 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 8e74e75..be52a3a 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -53,7 +53,7 @@ static void sdhci_finish_data(struct sdhci_host *);
>  static void sdhci_finish_command(struct sdhci_host *);
>  static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
>  static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
> -static int sdhci_do_get_cd(struct sdhci_host *host);
> +static int sdhci_get_cd(struct mmc_host *mmc);
>
>  #ifdef CONFIG_PM
>  static void sdhci_runtime_pm_bus_on(struct sdhci_host *host);
> @@ -194,7 +194,7 @@ EXPORT_SYMBOL_GPL(sdhci_reset);
>  static void sdhci_do_reset(struct sdhci_host *host, u8 mask)
>  {
>         if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
> -               if (!sdhci_do_get_cd(host))
> +               if (!sdhci_get_cd(host->mmc))
>                         return;
>         }
>
> @@ -1393,11 +1393,11 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
>  }
>  EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);
>
> -static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
> +static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  {
> +       struct sdhci_host *host = mmc_priv(mmc);
>         unsigned long flags;
>         u8 ctrl;
> -       struct mmc_host *mmc = host->mmc;
>
>         spin_lock_irqsave(&host->lock, flags);
>
> @@ -1551,16 +1551,10 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
>         spin_unlock_irqrestore(&host->lock, flags);
>  }
>
> -static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> +static int sdhci_get_cd(struct mmc_host *mmc)
>  {
>         struct sdhci_host *host = mmc_priv(mmc);
> -
> -       sdhci_do_set_ios(host, ios);
> -}
> -
> -static int sdhci_do_get_cd(struct sdhci_host *host)
> -{
> -       int gpio_cd = mmc_gpio_get_cd(host->mmc);
> +       int gpio_cd = mmc_gpio_get_cd(mmc);
>
>         if (host->flags & SDHCI_DEVICE_DEAD)
>                 return 0;
> @@ -1584,13 +1578,6 @@ static int sdhci_do_get_cd(struct sdhci_host *host)
>         return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
>  }
>
> -static int sdhci_get_cd(struct mmc_host *mmc)
> -{
> -       struct sdhci_host *host = mmc_priv(mmc);
> -
> -       return sdhci_do_get_cd(host);
> -}
> -
>  static int sdhci_check_ro(struct sdhci_host *host)
>  {
>         unsigned long flags;
> @@ -1615,8 +1602,9 @@ static int sdhci_check_ro(struct sdhci_host *host)
>
>  #define SAMPLE_COUNT   5
>
> -static int sdhci_do_get_ro(struct sdhci_host *host)
> +static int sdhci_get_ro(struct mmc_host *mmc)
>  {
> +       struct sdhci_host *host = mmc_priv(mmc);
>         int i, ro_count;
>
>         if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT))
> @@ -1641,13 +1629,6 @@ static void sdhci_hw_reset(struct mmc_host *mmc)
>                 host->ops->hw_reset(host);
>  }
>
> -static int sdhci_get_ro(struct mmc_host *mmc)
> -{
> -       struct sdhci_host *host = mmc_priv(mmc);
> -
> -       return sdhci_do_get_ro(host);
> -}
> -
>  static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
>  {
>         if (!(host->flags & SDHCI_DEVICE_DEAD)) {
> @@ -1677,10 +1658,10 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
>         spin_unlock_irqrestore(&host->lock, flags);
>  }
>
> -static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> -                                               struct mmc_ios *ios)
> +static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
> +                                            struct mmc_ios *ios)
>  {
> -       struct mmc_host *mmc = host->mmc;
> +       struct sdhci_host *host = mmc_priv(mmc);
>         u16 ctrl;
>         int ret;
>
> @@ -1768,17 +1749,6 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>         }
>  }
>
> -static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
> -       struct mmc_ios *ios)
> -{
> -       struct sdhci_host *host = mmc_priv(mmc);
> -
> -       if (host->version < SDHCI_SPEC_300)
> -               return 0;
> -
> -       return sdhci_do_start_signal_voltage_switch(host, ios);
> -}
> -
>  static int sdhci_card_busy(struct mmc_host *mmc)
>  {
>         struct sdhci_host *host = mmc_priv(mmc);
> @@ -2070,7 +2040,7 @@ static void sdhci_card_event(struct mmc_host *mmc)
>         if (host->ops->card_event)
>                 host->ops->card_event(host);
>
> -       present = sdhci_do_get_cd(host);
> +       present = sdhci_get_cd(host->mmc);
>
>         spin_lock_irqsave(&host->lock, flags);
>
> @@ -2643,7 +2613,7 @@ int sdhci_resume_host(struct sdhci_host *host)
>                 sdhci_init(host, 0);
>                 host->pwr = 0;
>                 host->clock = 0;
> -               sdhci_do_set_ios(host, &host->mmc->ios);
> +               sdhci_set_ios(host->mmc, &host->mmc->ios);
>         } else {
>                 sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER));
>                 mmiowb();
> @@ -2721,8 +2691,8 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
>         /* Force clock and power re-program */
>         host->pwr = 0;
>         host->clock = 0;
> -       sdhci_do_start_signal_voltage_switch(host, &host->mmc->ios);
> -       sdhci_do_set_ios(host, &host->mmc->ios);
> +       sdhci_start_signal_voltage_switch(host->mmc, &host->mmc->ios);
> +       sdhci_set_ios(host->mmc, &host->mmc->ios);
>
>         if ((host_flags & SDHCI_PV_ENABLED) &&
>                 !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) {
> --
> 1.9.1
>

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

* Re: [PATCH 14/23] mmc: sdhci-esdhci-imx: disable DLL delay line settings explicitly
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-05-10 11:02     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10 11:02 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> From: Dong Aisheng <aisheng.dong@freescale.com>
> 
> Disable DLL delay line settings explicitly during driver initialization
> in case ROM/uBoot had set an invalid delay.
> e.g. MX6DL ROM has set the default delay line(DLLCTRL) to 0x1000021,
> the uSDHC clock timing will become marginal when works on DDR mode
> due to default delay and will possibly see CRC errors in case the board
> is not perfectly designed on the eMMC chip layout.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 4c28fbb..d02db66 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -1186,6 +1186,9 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
>  		*/
>  		writel(readl(host->ioaddr + 0x6c) | BIT(7),
>  			host->ioaddr + 0x6c);
> +
> +		/* disable DLL_CTRL delay line settings */
> +		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
>  	}
>  
>  	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
> 


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

* [PATCH 14/23] mmc: sdhci-esdhci-imx: disable DLL delay line settings explicitly
@ 2016-05-10 11:02     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10 11:02 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> From: Dong Aisheng <aisheng.dong@freescale.com>
> 
> Disable DLL delay line settings explicitly during driver initialization
> in case ROM/uBoot had set an invalid delay.
> e.g. MX6DL ROM has set the default delay line(DLLCTRL) to 0x1000021,
> the uSDHC clock timing will become marginal when works on DDR mode
> due to default delay and will possibly see CRC errors in case the board
> is not perfectly designed on the eMMC chip layout.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 4c28fbb..d02db66 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -1186,6 +1186,9 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
>  		*/
>  		writel(readl(host->ioaddr + 0x6c) | BIT(7),
>  			host->ioaddr + 0x6c);
> +
> +		/* disable DLL_CTRL delay line settings */
> +		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
>  	}
>  
>  	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
> 

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

* Re: [PATCH 15/23] mmc: sdhci-esdhc-imx: support setting tuning start point
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-05-10 11:17     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10 11:17 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, dongas86, chris, haibo.chen, shawnguo, linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> The delay cells of some SoCs may have less delay per one cell,
> for such SoCs, user could set the start delay cell point to bypass
> the first a few meaningless tuning commands.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c          | 14 +++++++++++---
>  include/linux/platform_data/mmc-esdhc-imx.h |  1 +
>  2 files changed, 12 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index d02db66..9f9be3f 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -75,7 +75,8 @@
>  #define ESDHC_TUNING_CTRL		0xcc
>  #define ESDHC_STD_TUNING_EN		(1 << 24)
>  /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */
> -#define ESDHC_TUNING_START_TAP		0x1
> +#define ESDHC_TUNING_START_TAP_DEFAULT	0x1
> +#define ESDHC_TUNING_START_TAP_MASK	0xff
>  #define ESDHC_TUNING_STEP_MASK		0x00070000
>  #define ESDHC_TUNING_STEP_SHIFT		16
>  
> @@ -489,7 +490,12 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>  				v |= ESDHC_MIX_CTRL_EXE_TUNE;
>  				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
>  				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
> -				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP;
> +				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT;
> +				if (imx_data->boarddata.tuning_start_tap) {
> +					tuning_ctrl &= ~ESDHC_TUNING_START_TAP_MASK;
> +					tuning_ctrl |= imx_data->boarddata.tuning_start_tap;
> +				}
> +
>  				if (imx_data->boarddata.tuning_step) {
>  					tuning_ctrl &= ~ESDHC_TUNING_STEP_MASK;
>  					tuning_ctrl |= imx_data->boarddata.tuning_step << ESDHC_TUNING_STEP_SHIFT;
> @@ -975,6 +981,8 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
>  		boarddata->wp_type = ESDHC_WP_GPIO;
>  
>  	of_property_read_u32(np, "fsl,tuning-step", &boarddata->tuning_step);
> +	of_property_read_u32(np, "fsl,tuning-start-tap",
> +			     &boarddata->tuning_start_tap);
>  
>  	if (of_find_property(np, "no-1-8-v", NULL))
>  		boarddata->support_vsel = false;
> @@ -1197,7 +1205,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
>  
>  	if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING)
>  		writel(readl(host->ioaddr + ESDHC_TUNING_CTRL) |
> -			ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP,
> +			ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT,
>  			host->ioaddr + ESDHC_TUNING_CTRL);
>  
>  	if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
> diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h
> index 95ccab3..7daa78a 100644
> --- a/include/linux/platform_data/mmc-esdhc-imx.h
> +++ b/include/linux/platform_data/mmc-esdhc-imx.h
> @@ -46,5 +46,6 @@ struct esdhc_platform_data {
>  	bool support_vsel;
>  	unsigned int delay_line;
>  	unsigned int tuning_step;       /* The delay cell steps in tuning procedure */
> +	unsigned int tuning_start_tap;	/* The start delay cell point in tuning procedure */
>  };
>  #endif /* __ASM_ARCH_IMX_ESDHC_H */
> 

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

* [PATCH 15/23] mmc: sdhci-esdhc-imx: support setting tuning start point
@ 2016-05-10 11:17     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10 11:17 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> The delay cells of some SoCs may have less delay per one cell,
> for such SoCs, user could set the start delay cell point to bypass
> the first a few meaningless tuning commands.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c          | 14 +++++++++++---
>  include/linux/platform_data/mmc-esdhc-imx.h |  1 +
>  2 files changed, 12 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index d02db66..9f9be3f 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -75,7 +75,8 @@
>  #define ESDHC_TUNING_CTRL		0xcc
>  #define ESDHC_STD_TUNING_EN		(1 << 24)
>  /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */
> -#define ESDHC_TUNING_START_TAP		0x1
> +#define ESDHC_TUNING_START_TAP_DEFAULT	0x1
> +#define ESDHC_TUNING_START_TAP_MASK	0xff
>  #define ESDHC_TUNING_STEP_MASK		0x00070000
>  #define ESDHC_TUNING_STEP_SHIFT		16
>  
> @@ -489,7 +490,12 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>  				v |= ESDHC_MIX_CTRL_EXE_TUNE;
>  				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
>  				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
> -				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP;
> +				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT;
> +				if (imx_data->boarddata.tuning_start_tap) {
> +					tuning_ctrl &= ~ESDHC_TUNING_START_TAP_MASK;
> +					tuning_ctrl |= imx_data->boarddata.tuning_start_tap;
> +				}
> +
>  				if (imx_data->boarddata.tuning_step) {
>  					tuning_ctrl &= ~ESDHC_TUNING_STEP_MASK;
>  					tuning_ctrl |= imx_data->boarddata.tuning_step << ESDHC_TUNING_STEP_SHIFT;
> @@ -975,6 +981,8 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
>  		boarddata->wp_type = ESDHC_WP_GPIO;
>  
>  	of_property_read_u32(np, "fsl,tuning-step", &boarddata->tuning_step);
> +	of_property_read_u32(np, "fsl,tuning-start-tap",
> +			     &boarddata->tuning_start_tap);
>  
>  	if (of_find_property(np, "no-1-8-v", NULL))
>  		boarddata->support_vsel = false;
> @@ -1197,7 +1205,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
>  
>  	if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING)
>  		writel(readl(host->ioaddr + ESDHC_TUNING_CTRL) |
> -			ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP,
> +			ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT,
>  			host->ioaddr + ESDHC_TUNING_CTRL);
>  
>  	if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
> diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h
> index 95ccab3..7daa78a 100644
> --- a/include/linux/platform_data/mmc-esdhc-imx.h
> +++ b/include/linux/platform_data/mmc-esdhc-imx.h
> @@ -46,5 +46,6 @@ struct esdhc_platform_data {
>  	bool support_vsel;
>  	unsigned int delay_line;
>  	unsigned int tuning_step;       /* The delay cell steps in tuning procedure */
> +	unsigned int tuning_start_tap;	/* The start delay cell point in tuning procedure */
>  };
>  #endif /* __ASM_ARCH_IMX_ESDHC_H */
> 

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

* Re: [PATCH 18/23] mmc: sdhci-esdhc-imx: enable hw auto retuning for STD_TUNING
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-05-10 11:19     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10 11:19 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> Enable HW auto retuning when set SDHCI_CTRL_EXEC_TUNING and clear it
> when clear SDHCI_CTRL_TUNED_CLK.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

I presume this patch should wait for patch 17, but nevertheless:

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 9f9be3f..a582a83 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -44,6 +44,7 @@
>  #define  ESDHC_MIX_CTRL_AC23EN		(1 << 7)
>  #define  ESDHC_MIX_CTRL_EXE_TUNE	(1 << 22)
>  #define  ESDHC_MIX_CTRL_SMPCLK_SEL	(1 << 23)
> +#define  ESDHC_MIX_CTRL_AUTO_TUNE_EN	(1 << 24)
>  #define  ESDHC_MIX_CTRL_FBCLK_SEL	(1 << 25)
>  #define  ESDHC_MIX_CTRL_HS400_EN	(1 << 26)
>  /* Bits 3 and 6 are not SDHCI standard definitions */
> @@ -484,11 +485,13 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>  			} else {
>  				v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
>  				m &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
> +				m &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
>  			}
>  
>  			if (val & SDHCI_CTRL_EXEC_TUNING) {
>  				v |= ESDHC_MIX_CTRL_EXE_TUNE;
>  				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
> +				m |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
>  				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
>  				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT;
>  				if (imx_data->boarddata.tuning_start_tap) {
> 


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

* [PATCH 18/23] mmc: sdhci-esdhc-imx: enable hw auto retuning for STD_TUNING
@ 2016-05-10 11:19     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10 11:19 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> Enable HW auto retuning when set SDHCI_CTRL_EXEC_TUNING and clear it
> when clear SDHCI_CTRL_TUNED_CLK.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

I presume this patch should wait for patch 17, but nevertheless:

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 9f9be3f..a582a83 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -44,6 +44,7 @@
>  #define  ESDHC_MIX_CTRL_AC23EN		(1 << 7)
>  #define  ESDHC_MIX_CTRL_EXE_TUNE	(1 << 22)
>  #define  ESDHC_MIX_CTRL_SMPCLK_SEL	(1 << 23)
> +#define  ESDHC_MIX_CTRL_AUTO_TUNE_EN	(1 << 24)
>  #define  ESDHC_MIX_CTRL_FBCLK_SEL	(1 << 25)
>  #define  ESDHC_MIX_CTRL_HS400_EN	(1 << 26)
>  /* Bits 3 and 6 are not SDHCI standard definitions */
> @@ -484,11 +485,13 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>  			} else {
>  				v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
>  				m &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
> +				m &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
>  			}
>  
>  			if (val & SDHCI_CTRL_EXEC_TUNING) {
>  				v |= ESDHC_MIX_CTRL_EXE_TUNE;
>  				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
> +				m |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
>  				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
>  				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT;
>  				if (imx_data->boarddata.tuning_start_tap) {
> 

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

* Re: [PATCH 19/23] mmc: sdhci-esdhc-imx: enable hw auto retuning for MAN_TUNING
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-05-10 11:24     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10 11:24 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> Indicating hw auto retuning support for mx6qdl in the fake caps_1
> register and enable auto retuning in post_tuning process after
> tuning completes.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

I presume this patch should wait for patch 17, but nevertheless:

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index a582a83..07b1144 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -301,7 +301,8 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
>  				/* imx6q/dl does not have cap_1 register, fake one */
>  				val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104
>  					| SDHCI_SUPPORT_SDR50
> -					| SDHCI_USE_SDR50_TUNING;
> +					| SDHCI_USE_SDR50_TUNING
> +					| (SDHCI_TUNING_MODE_3 << SDHCI_RETUNING_MODE_SHIFT);
>  
>  			if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
>  				val |= SDHCI_SUPPORT_HS400;
> @@ -471,10 +472,13 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>  		writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC);
>  		if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
>  			new_val = readl(host->ioaddr + ESDHC_MIX_CTRL);
> -			if (val & SDHCI_CTRL_TUNED_CLK)
> +			if (val & SDHCI_CTRL_TUNED_CLK) {
>  				new_val |= ESDHC_MIX_CTRL_SMPCLK_SEL;
> -			else
> +				new_val |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
> +			} else {
>  				new_val &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
> +				new_val &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
> +			}
>  			writel(new_val , host->ioaddr + ESDHC_MIX_CTRL);
>  		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
>  			u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR);
> @@ -760,6 +764,7 @@ static void esdhc_post_tuning(struct sdhci_host *host)
>  
>  	reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
>  	reg &= ~ESDHC_MIX_CTRL_EXE_TUNE;
> +	reg |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
>  	writel(reg, host->ioaddr + ESDHC_MIX_CTRL);
>  }
>  
> 


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

* [PATCH 19/23] mmc: sdhci-esdhc-imx: enable hw auto retuning for MAN_TUNING
@ 2016-05-10 11:24     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10 11:24 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> Indicating hw auto retuning support for mx6qdl in the fake caps_1
> register and enable auto retuning in post_tuning process after
> tuning completes.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

I presume this patch should wait for patch 17, but nevertheless:

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index a582a83..07b1144 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -301,7 +301,8 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
>  				/* imx6q/dl does not have cap_1 register, fake one */
>  				val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104
>  					| SDHCI_SUPPORT_SDR50
> -					| SDHCI_USE_SDR50_TUNING;
> +					| SDHCI_USE_SDR50_TUNING
> +					| (SDHCI_TUNING_MODE_3 << SDHCI_RETUNING_MODE_SHIFT);
>  
>  			if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
>  				val |= SDHCI_SUPPORT_HS400;
> @@ -471,10 +472,13 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>  		writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC);
>  		if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
>  			new_val = readl(host->ioaddr + ESDHC_MIX_CTRL);
> -			if (val & SDHCI_CTRL_TUNED_CLK)
> +			if (val & SDHCI_CTRL_TUNED_CLK) {
>  				new_val |= ESDHC_MIX_CTRL_SMPCLK_SEL;
> -			else
> +				new_val |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
> +			} else {
>  				new_val &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
> +				new_val &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
> +			}
>  			writel(new_val , host->ioaddr + ESDHC_MIX_CTRL);
>  		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
>  			u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR);
> @@ -760,6 +764,7 @@ static void esdhc_post_tuning(struct sdhci_host *host)
>  
>  	reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
>  	reg &= ~ESDHC_MIX_CTRL_EXE_TUNE;
> +	reg |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
>  	writel(reg, host->ioaddr + ESDHC_MIX_CTRL);
>  }
>  
> 

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

* Re: [PATCH 20/23] mmc: sdhci-esdhc-imx: fix strobe DLL lock wrong clock issue
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-05-10 12:03     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10 12:03 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> When enable DDR, the clock factor definition is changed.
> e.g. original 200Mhz will become 100Mhz one MIX_CTRL_DDREN bit is set
> So we need to update the clock setting then the strobe dll can lock
> the correct clock rate.
> 
> Additionally we also need disable the clock before locking strobe dll.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

Apart from redundant parentheses (refer below):

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 07b1144..3ff213f 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -852,6 +852,11 @@ static void esdhc_set_strobe_dll(struct sdhci_host *host)
>  	u32 v;
>  
>  	if (host->mmc->actual_clock > ESDHC_STROBE_DLL_CLK_FREQ) {
> +		/* disable clock before enabling strobe dll */
> +		writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) &
> +		       (~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON),

Parentheses look redundant

> +		       host->ioaddr + ESDHC_VENDOR_SPEC);
> +
>  		/* force a reset on strobe dll */
>  		writel(ESDHC_STROBE_DLL_CTRL_RESET,
>  			host->ioaddr + ESDHC_STROBE_DLL_CTRL);
> @@ -913,6 +918,8 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
>  		m |= ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN;
>  		writel(m, host->ioaddr + ESDHC_MIX_CTRL);
>  		imx_data->is_ddr = 1;
> +		/* update clock after enable DDR for strobe DLL lock */
> +		host->ops->set_clock(host, host->clock);
>  		esdhc_set_strobe_dll(host);
>  		break;
>  	}
> 


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

* [PATCH 20/23] mmc: sdhci-esdhc-imx: fix strobe DLL lock wrong clock issue
@ 2016-05-10 12:03     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10 12:03 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> When enable DDR, the clock factor definition is changed.
> e.g. original 200Mhz will become 100Mhz one MIX_CTRL_DDREN bit is set
> So we need to update the clock setting then the strobe dll can lock
> the correct clock rate.
> 
> Additionally we also need disable the clock before locking strobe dll.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

Apart from redundant parentheses (refer below):

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 07b1144..3ff213f 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -852,6 +852,11 @@ static void esdhc_set_strobe_dll(struct sdhci_host *host)
>  	u32 v;
>  
>  	if (host->mmc->actual_clock > ESDHC_STROBE_DLL_CLK_FREQ) {
> +		/* disable clock before enabling strobe dll */
> +		writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) &
> +		       (~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON),

Parentheses look redundant

> +		       host->ioaddr + ESDHC_VENDOR_SPEC);
> +
>  		/* force a reset on strobe dll */
>  		writel(ESDHC_STROBE_DLL_CTRL_RESET,
>  			host->ioaddr + ESDHC_STROBE_DLL_CTRL);
> @@ -913,6 +918,8 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
>  		m |= ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN;
>  		writel(m, host->ioaddr + ESDHC_MIX_CTRL);
>  		imx_data->is_ddr = 1;
> +		/* update clock after enable DDR for strobe DLL lock */
> +		host->ops->set_clock(host, host->clock);
>  		esdhc_set_strobe_dll(host);
>  		break;
>  	}
> 

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

* Re: [PATCH 21/23] mmc: sdhci-esdhc-imx: factor out hw related intialization into function
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-05-10 12:15     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10 12:15 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> Factor out hw related intialization into a separate function which
> has two benifits:
> 1) concentrate hw related intialization at one place
> 2) ease the hw state restore after resume by simply
> calling this function

There are really 2 changes here, please make it 2 patches.

> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 76 +++++++++++++++++++++-----------------
>  1 file changed, 42 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 3ff213f..95f3632 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -978,6 +978,44 @@ static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
>  	.ops = &sdhci_esdhc_ops,
>  };
>  
> +static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
> +{
> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
> +
> +	if (esdhc_is_usdhc(imx_data)) {
> +		/*
> +		 * The imx6q ROM code will change the default watermark
> +		 * level setting to something insane.  Change it back here.
> +		 */
> +		writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> +
> +		/*
> +		 * ROM code will change the bit burst_length_enable setting
> +		 * to zero if this usdhc is choosed to boot system. Change
> +		 * it back here, otherwise it will impact the performance a
> +		 * lot. This bit is used to enable/disable the burst length
> +		 * for the external AHB2AXI bridge, it's usefully especially
> +		 * for INCR transfer because without burst length indicator,
> +		 * the AHB2AXI bridge does not know the burst length in
> +		 * advance. And without burst length indicator, AHB INCR
> +		 * transfer can only be converted to singles on the AXI side.
> +		 */
> +		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
> +			| ESDHC_BURST_LEN_EN_INCR,
> +			host->ioaddr + SDHCI_HOST_CONTROL);
> +		/*
> +		* errata ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
> +		* TO1.1, it's harmless for MX6SL
> +		*/
> +		writel(readl(host->ioaddr + 0x6c) | BIT(7),
> +			host->ioaddr + 0x6c);
> +
> +		/* disable DLL_CTRL delay line settings */
> +		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
> +	}
> +}
> +
>  #ifdef CONFIG_OF
>  static int
>  sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
> @@ -1175,43 +1213,13 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
>  		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK
>  			| SDHCI_QUIRK_BROKEN_ADMA;
>  
> -	/*
> -	 * The imx6q ROM code will change the default watermark level setting
> -	 * to something insane.  Change it back here.
> -	 */
> -	if (esdhc_is_usdhc(imx_data)) {
> -		writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> +	sdhci_esdhc_imx_hwinit(host);
>  
> +	if (esdhc_is_usdhc(imx_data)) {
>  		host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
>  		host->mmc->caps |= MMC_CAP_1_8V_DDR;
> -
> -		/*
> -		 * ROM code will change the bit burst_length_enable setting
> -		 * to zero if this usdhc is choosed to boot system. Change
> -		 * it back here, otherwise it will impact the performance a
> -		 * lot. This bit is used to enable/disable the burst length
> -		 * for the external AHB2AXI bridge, it's usefully especially
> -		 * for INCR transfer because without burst length indicator,
> -		 * the AHB2AXI bridge does not know the burst length in
> -		 * advance. And without burst length indicator, AHB INCR
> -		 * transfer can only be converted to singles on the AXI side.
> -		 */
> -		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
> -			| ESDHC_BURST_LEN_EN_INCR,
> -			host->ioaddr + SDHCI_HOST_CONTROL);
> -
>  		if (!(imx_data->socdata->flags & ESDHC_FLAG_HS200))
>  			host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
> -
> -		/*
> -		* errata ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
> -		* TO1.1, it's harmless for MX6SL
> -		*/
> -		writel(readl(host->ioaddr + 0x6c) | BIT(7),
> -			host->ioaddr + 0x6c);
> -
> -		/* disable DLL_CTRL delay line settings */
> -		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
>  	}
>  
>  	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
> @@ -1289,8 +1297,8 @@ static int sdhci_esdhc_resume(struct device *dev)
>  {
>  	struct sdhci_host *host = dev_get_drvdata(dev);
>  
> -	/* restore watermark setting in case it's lost in low power mode */
> -	writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> +	/* reinitialize hw state in case it's lost in low power mode */
> +	sdhci_esdhc_imx_hwinit(host);
>  
>  	return sdhci_pltfm_resume(dev);
>  }
> 


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

* [PATCH 21/23] mmc: sdhci-esdhc-imx: factor out hw related intialization into function
@ 2016-05-10 12:15     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10 12:15 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> Factor out hw related intialization into a separate function which
> has two benifits:
> 1) concentrate hw related intialization at one place
> 2) ease the hw state restore after resume by simply
> calling this function

There are really 2 changes here, please make it 2 patches.

> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 76 +++++++++++++++++++++-----------------
>  1 file changed, 42 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 3ff213f..95f3632 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -978,6 +978,44 @@ static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
>  	.ops = &sdhci_esdhc_ops,
>  };
>  
> +static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
> +{
> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
> +
> +	if (esdhc_is_usdhc(imx_data)) {
> +		/*
> +		 * The imx6q ROM code will change the default watermark
> +		 * level setting to something insane.  Change it back here.
> +		 */
> +		writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> +
> +		/*
> +		 * ROM code will change the bit burst_length_enable setting
> +		 * to zero if this usdhc is choosed to boot system. Change
> +		 * it back here, otherwise it will impact the performance a
> +		 * lot. This bit is used to enable/disable the burst length
> +		 * for the external AHB2AXI bridge, it's usefully especially
> +		 * for INCR transfer because without burst length indicator,
> +		 * the AHB2AXI bridge does not know the burst length in
> +		 * advance. And without burst length indicator, AHB INCR
> +		 * transfer can only be converted to singles on the AXI side.
> +		 */
> +		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
> +			| ESDHC_BURST_LEN_EN_INCR,
> +			host->ioaddr + SDHCI_HOST_CONTROL);
> +		/*
> +		* errata ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
> +		* TO1.1, it's harmless for MX6SL
> +		*/
> +		writel(readl(host->ioaddr + 0x6c) | BIT(7),
> +			host->ioaddr + 0x6c);
> +
> +		/* disable DLL_CTRL delay line settings */
> +		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
> +	}
> +}
> +
>  #ifdef CONFIG_OF
>  static int
>  sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
> @@ -1175,43 +1213,13 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
>  		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK
>  			| SDHCI_QUIRK_BROKEN_ADMA;
>  
> -	/*
> -	 * The imx6q ROM code will change the default watermark level setting
> -	 * to something insane.  Change it back here.
> -	 */
> -	if (esdhc_is_usdhc(imx_data)) {
> -		writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> +	sdhci_esdhc_imx_hwinit(host);
>  
> +	if (esdhc_is_usdhc(imx_data)) {
>  		host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
>  		host->mmc->caps |= MMC_CAP_1_8V_DDR;
> -
> -		/*
> -		 * ROM code will change the bit burst_length_enable setting
> -		 * to zero if this usdhc is choosed to boot system. Change
> -		 * it back here, otherwise it will impact the performance a
> -		 * lot. This bit is used to enable/disable the burst length
> -		 * for the external AHB2AXI bridge, it's usefully especially
> -		 * for INCR transfer because without burst length indicator,
> -		 * the AHB2AXI bridge does not know the burst length in
> -		 * advance. And without burst length indicator, AHB INCR
> -		 * transfer can only be converted to singles on the AXI side.
> -		 */
> -		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
> -			| ESDHC_BURST_LEN_EN_INCR,
> -			host->ioaddr + SDHCI_HOST_CONTROL);
> -
>  		if (!(imx_data->socdata->flags & ESDHC_FLAG_HS200))
>  			host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
> -
> -		/*
> -		* errata ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
> -		* TO1.1, it's harmless for MX6SL
> -		*/
> -		writel(readl(host->ioaddr + 0x6c) | BIT(7),
> -			host->ioaddr + 0x6c);
> -
> -		/* disable DLL_CTRL delay line settings */
> -		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
>  	}
>  
>  	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
> @@ -1289,8 +1297,8 @@ static int sdhci_esdhc_resume(struct device *dev)
>  {
>  	struct sdhci_host *host = dev_get_drvdata(dev);
>  
> -	/* restore watermark setting in case it's lost in low power mode */
> -	writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> +	/* reinitialize hw state in case it's lost in low power mode */
> +	sdhci_esdhc_imx_hwinit(host);
>  
>  	return sdhci_pltfm_resume(dev);
>  }
> 

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

* Re: [PATCH 22/23] mmc: sdhci-esdhc-imx: move tuning static configuration into hwinit function
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-05-10 13:07     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10 13:07 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> Move tuning static configuration into hwinit function.
> Tuning configuration may also be lost in low power mode,
> so need restore in hwinit().
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 36 ++++++++++++++++++------------------
>  1 file changed, 18 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 95f3632..98aa6b5 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -483,7 +483,6 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>  		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
>  			u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR);
>  			u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL);
> -			u32 tuning_ctrl;
>  			if (val & SDHCI_CTRL_TUNED_CLK) {
>  				v |= ESDHC_MIX_CTRL_SMPCLK_SEL;
>  			} else {
> @@ -496,18 +495,6 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>  				v |= ESDHC_MIX_CTRL_EXE_TUNE;
>  				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
>  				m |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
> -				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
> -				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT;
> -				if (imx_data->boarddata.tuning_start_tap) {
> -					tuning_ctrl &= ~ESDHC_TUNING_START_TAP_MASK;
> -					tuning_ctrl |= imx_data->boarddata.tuning_start_tap;
> -				}
> -
> -				if (imx_data->boarddata.tuning_step) {
> -					tuning_ctrl &= ~ESDHC_TUNING_STEP_MASK;
> -					tuning_ctrl |= imx_data->boarddata.tuning_step << ESDHC_TUNING_STEP_SHIFT;
> -				}
> -				writel(tuning_ctrl, host->ioaddr + ESDHC_TUNING_CTRL);
>  			} else {
>  				v &= ~ESDHC_MIX_CTRL_EXE_TUNE;
>  			}
> @@ -982,6 +969,7 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
>  {
>  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>  	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
> +	int tmp;
>  
>  	if (esdhc_is_usdhc(imx_data)) {
>  		/*
> @@ -1013,6 +1001,23 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
>  
>  		/* disable DLL_CTRL delay line settings */
>  		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
> +
> +		if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
> +			tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL);
> +			tmp |= ESDHC_STD_TUNING_EN |
> +				ESDHC_TUNING_START_TAP_DEFAULT;
> +			if (imx_data->boarddata.tuning_start_tap) {
> +				tmp &= ~ESDHC_TUNING_START_TAP_MASK;
> +				tmp |= imx_data->boarddata.tuning_start_tap;
> +			}
> +
> +			if (imx_data->boarddata.tuning_step) {
> +				tmp &= ~ESDHC_TUNING_STEP_MASK;
> +				tmp |= imx_data->boarddata.tuning_step
> +					<< ESDHC_TUNING_STEP_SHIFT;
> +			}
> +			writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL);
> +		}
>  	}
>  }
>  
> @@ -1226,11 +1231,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
>  		sdhci_esdhc_ops.platform_execute_tuning =
>  					esdhc_executing_tuning;
>  
> -	if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING)
> -		writel(readl(host->ioaddr + ESDHC_TUNING_CTRL) |
> -			ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT,
> -			host->ioaddr + ESDHC_TUNING_CTRL);
> -
>  	if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
>  		host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
>  
> 


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

* [PATCH 22/23] mmc: sdhci-esdhc-imx: move tuning static configuration into hwinit function
@ 2016-05-10 13:07     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10 13:07 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> Move tuning static configuration into hwinit function.
> Tuning configuration may also be lost in low power mode,
> so need restore in hwinit().
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 36 ++++++++++++++++++------------------
>  1 file changed, 18 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 95f3632..98aa6b5 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -483,7 +483,6 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>  		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
>  			u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR);
>  			u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL);
> -			u32 tuning_ctrl;
>  			if (val & SDHCI_CTRL_TUNED_CLK) {
>  				v |= ESDHC_MIX_CTRL_SMPCLK_SEL;
>  			} else {
> @@ -496,18 +495,6 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>  				v |= ESDHC_MIX_CTRL_EXE_TUNE;
>  				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
>  				m |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
> -				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
> -				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT;
> -				if (imx_data->boarddata.tuning_start_tap) {
> -					tuning_ctrl &= ~ESDHC_TUNING_START_TAP_MASK;
> -					tuning_ctrl |= imx_data->boarddata.tuning_start_tap;
> -				}
> -
> -				if (imx_data->boarddata.tuning_step) {
> -					tuning_ctrl &= ~ESDHC_TUNING_STEP_MASK;
> -					tuning_ctrl |= imx_data->boarddata.tuning_step << ESDHC_TUNING_STEP_SHIFT;
> -				}
> -				writel(tuning_ctrl, host->ioaddr + ESDHC_TUNING_CTRL);
>  			} else {
>  				v &= ~ESDHC_MIX_CTRL_EXE_TUNE;
>  			}
> @@ -982,6 +969,7 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
>  {
>  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>  	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
> +	int tmp;
>  
>  	if (esdhc_is_usdhc(imx_data)) {
>  		/*
> @@ -1013,6 +1001,23 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
>  
>  		/* disable DLL_CTRL delay line settings */
>  		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
> +
> +		if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
> +			tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL);
> +			tmp |= ESDHC_STD_TUNING_EN |
> +				ESDHC_TUNING_START_TAP_DEFAULT;
> +			if (imx_data->boarddata.tuning_start_tap) {
> +				tmp &= ~ESDHC_TUNING_START_TAP_MASK;
> +				tmp |= imx_data->boarddata.tuning_start_tap;
> +			}
> +
> +			if (imx_data->boarddata.tuning_step) {
> +				tmp &= ~ESDHC_TUNING_STEP_MASK;
> +				tmp |= imx_data->boarddata.tuning_step
> +					<< ESDHC_TUNING_STEP_SHIFT;
> +			}
> +			writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL);
> +		}
>  	}
>  }
>  
> @@ -1226,11 +1231,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
>  		sdhci_esdhc_ops.platform_execute_tuning =
>  					esdhc_executing_tuning;
>  
> -	if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING)
> -		writel(readl(host->ioaddr + ESDHC_TUNING_CTRL) |
> -			ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT,
> -			host->ioaddr + ESDHC_TUNING_CTRL);
> -
>  	if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
>  		host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
>  
> 

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

* Re: [PATCH 23/23] mmc: sdhci-esdhc-imx: clear tuning bits during hwinit
  2016-04-15 17:29   ` Dong Aisheng
@ 2016-05-10 13:10     ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10 13:10 UTC (permalink / raw)
  To: Dong Aisheng, linux-mmc
  Cc: ulf.hansson, chris, shawnguo, linux-arm-kernel, haibo.chen, dongas86

On 15/04/16 20:29, Dong Aisheng wrote:
> The tuning bits like FBCLK_SEL, SMP_CLK_SEL and DLY_CELL which affects
> timing may have already been set by ROM if booting from SD3.0 mode like
> SDR104. Let's clear it first during hw initialization before do the
> new card enumeration.
> 
> For system resume case, it's safe to clear them too since the following
> card re-initialization in mmc_xx_init_card() will do retuning and set
> correct value again.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 98aa6b5..6a699d1 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -1018,6 +1018,11 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
>  			}
>  			writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL);
>  		}
> +
> +		/* clear tuning bits in case ROM has set it already */
> +		writel(0x0, host->ioaddr + ESDHC_MIX_CTRL);
> +		writel(0x0, host->ioaddr + SDHCI_ACMD12_ERR);
> +		writel(0x0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
>  	}
>  }
>  
> 


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

* [PATCH 23/23] mmc: sdhci-esdhc-imx: clear tuning bits during hwinit
@ 2016-05-10 13:10     ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-10 13:10 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/16 20:29, Dong Aisheng wrote:
> The tuning bits like FBCLK_SEL, SMP_CLK_SEL and DLY_CELL which affects
> timing may have already been set by ROM if booting from SD3.0 mode like
> SDR104. Let's clear it first during hw initialization before do the
> new card enumeration.
> 
> For system resume case, it's safe to clear them too since the following
> card re-initialization in mmc_xx_init_card() will do retuning and set
> correct value again.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 98aa6b5..6a699d1 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -1018,6 +1018,11 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
>  			}
>  			writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL);
>  		}
> +
> +		/* clear tuning bits in case ROM has set it already */
> +		writel(0x0, host->ioaddr + ESDHC_MIX_CTRL);
> +		writel(0x0, host->ioaddr + SDHCI_ACMD12_ERR);
> +		writel(0x0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
>  	}
>  }
>  
> 

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

* Re: [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during no data transfer
  2016-05-10  6:51     ` Adrian Hunter
@ 2016-05-17  4:31       ` Ritesh Harjani
  -1 siblings, 0 replies; 170+ messages in thread
From: Ritesh Harjani @ 2016-05-17  4:31 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, chris, shawnguo,
	linux-arm-kernel, haibo.chen, dongas86

On Tue, May 10, 2016 at 12:21 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
>> Current code will report the wrong data interrupt got when no
>> data operation in progress assumed by getting !host->data in
>> sdhci_data_irq().
>>
>> For a data command handling process, the driver will call
>> sdhci_finish_data() and clear host->data in case any data error,
>> then card finish_tasklet will do the rest controller reset work.
>>
>> Before the tasklet got run, however, controllers may report the
>> TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
>> than data CRC error and data end bit error interrupts for single
>> block transfer or the last block of multiblock transfer.

What if the controller generates Transfer complete interrupt bit more slower
and the tasklet do get a chance to run. In that case even host->mrq
will become NULL.
Actually if that happens it's even more worse since the driver may
start issuing other commands to controller.

Are we covering that case here? Do you think that this case is possible?


>>
>> Controller usually detects and generates data CRC/end bit error
>> interrupts once one block on the bus is transferred completely.
>> For single block transfer, since there's only one bock to transfer,
>> the controller will report transfer complete interrupt as well,
>> but until the data in controller FIFO has been successfully
>> transferred to memory. The time gap of TC and CRC interrupt depends on
>> the system busy state at that point and memory bus access speed.
>>
>> So it is possible when TC interrupt generated, host->data is already
>> equal to NULL due to cleared by former CRC/Data End Bit error which
>> is reasonable.
>>
>> Thus we DO NOT report the weird data interrupt event for this case.
>>
>> Else we may easily see warning below during SD3.0 card manually tuning
>> process (calling mmc_send_tuning() which is a single block transfer)
>> mmc0: Got data interrupt 0x00000002 even though no data operation was in progress
>>
>> The detailed command log is as follows:
>> [ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
>> [ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
>> [ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
>> [ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
>> [ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
>> [ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
>> [ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
>> [ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
>> [ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
>> [ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
>> [ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
>> [ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
>> [ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
>> [ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
>> [ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
>> [ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
>> [ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
>> [ 1657.929965] sdhci: Host ctl2: 0x000000c8
>> [ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
>> [ 1657.929995] sdhci: ===========================================
>> [ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
>> [ 1657.930179] mmc0:     0 bytes transferred: -84
>>
>> It shows we first have a data CRC error interrupt then a data transfer
>> complete interrupt.
>> Then we got the !host->data case in sdhci_data_irq().
>>
>> CC: stable <stable@vger.kernel.org>
>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>> ---
>>  drivers/mmc/host/sdhci.c | 11 +++++++++++
>>  1 file changed, 11 insertions(+)
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 40e3551..2eb0e34 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
>>                       }
>>               }
>>
>> +             /*
>> +              * The "data complete" interrupt is possible to happen a bit
>> +              * later than CRC error and data end bit error interrupts
>> +              * separately for single block transfer or the last block of
>> +              * multiblock transfer. For this case, we DO NOT report the
>> +              * weird data interrupt event.
>> +              */
>> +             if ((intmask & SDHCI_INT_DATA_END) &&
>> +                 (host->mrq && host->mrq->data && host->mrq->data->error))
>> +                     return;
>
> This could be generalized a bit more i.e. what about:
>
>                 /*
>                  * After an error and before the the data circuit is reset in
>                  * sdhci_tasklet_finish, we could get more interrupts, but we
>                  * already have an error, so ignore them.
>                  */
>                 if (host->mrq && host->mrq->data && host->mrq->data->error)
>                         return;
>
>> +
>>               pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
>>                      mmc_hostname(host->mmc), (unsigned)intmask);
>>               sdhci_dumpregs(host);
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during no data transfer
@ 2016-05-17  4:31       ` Ritesh Harjani
  0 siblings, 0 replies; 170+ messages in thread
From: Ritesh Harjani @ 2016-05-17  4:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, May 10, 2016 at 12:21 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
>> Current code will report the wrong data interrupt got when no
>> data operation in progress assumed by getting !host->data in
>> sdhci_data_irq().
>>
>> For a data command handling process, the driver will call
>> sdhci_finish_data() and clear host->data in case any data error,
>> then card finish_tasklet will do the rest controller reset work.
>>
>> Before the tasklet got run, however, controllers may report the
>> TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
>> than data CRC error and data end bit error interrupts for single
>> block transfer or the last block of multiblock transfer.

What if the controller generates Transfer complete interrupt bit more slower
and the tasklet do get a chance to run. In that case even host->mrq
will become NULL.
Actually if that happens it's even more worse since the driver may
start issuing other commands to controller.

Are we covering that case here? Do you think that this case is possible?


>>
>> Controller usually detects and generates data CRC/end bit error
>> interrupts once one block on the bus is transferred completely.
>> For single block transfer, since there's only one bock to transfer,
>> the controller will report transfer complete interrupt as well,
>> but until the data in controller FIFO has been successfully
>> transferred to memory. The time gap of TC and CRC interrupt depends on
>> the system busy state at that point and memory bus access speed.
>>
>> So it is possible when TC interrupt generated, host->data is already
>> equal to NULL due to cleared by former CRC/Data End Bit error which
>> is reasonable.
>>
>> Thus we DO NOT report the weird data interrupt event for this case.
>>
>> Else we may easily see warning below during SD3.0 card manually tuning
>> process (calling mmc_send_tuning() which is a single block transfer)
>> mmc0: Got data interrupt 0x00000002 even though no data operation was in progress
>>
>> The detailed command log is as follows:
>> [ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
>> [ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
>> [ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
>> [ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
>> [ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
>> [ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
>> [ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
>> [ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
>> [ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
>> [ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
>> [ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
>> [ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
>> [ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
>> [ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
>> [ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
>> [ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
>> [ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
>> [ 1657.929965] sdhci: Host ctl2: 0x000000c8
>> [ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
>> [ 1657.929995] sdhci: ===========================================
>> [ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
>> [ 1657.930179] mmc0:     0 bytes transferred: -84
>>
>> It shows we first have a data CRC error interrupt then a data transfer
>> complete interrupt.
>> Then we got the !host->data case in sdhci_data_irq().
>>
>> CC: stable <stable@vger.kernel.org>
>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>> ---
>>  drivers/mmc/host/sdhci.c | 11 +++++++++++
>>  1 file changed, 11 insertions(+)
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 40e3551..2eb0e34 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
>>                       }
>>               }
>>
>> +             /*
>> +              * The "data complete" interrupt is possible to happen a bit
>> +              * later than CRC error and data end bit error interrupts
>> +              * separately for single block transfer or the last block of
>> +              * multiblock transfer. For this case, we DO NOT report the
>> +              * weird data interrupt event.
>> +              */
>> +             if ((intmask & SDHCI_INT_DATA_END) &&
>> +                 (host->mrq && host->mrq->data && host->mrq->data->error))
>> +                     return;
>
> This could be generalized a bit more i.e. what about:
>
>                 /*
>                  * After an error and before the the data circuit is reset in
>                  * sdhci_tasklet_finish, we could get more interrupts, but we
>                  * already have an error, so ignore them.
>                  */
>                 if (host->mrq && host->mrq->data && host->mrq->data->error)
>                         return;
>
>> +
>>               pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
>>                      mmc_hostname(host->mmc), (unsigned)intmask);
>>               sdhci_dumpregs(host);
>>
>
> --
> 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

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

* Re: [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during no data transfer
  2016-05-17  4:31       ` Ritesh Harjani
@ 2016-05-17  5:58         ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-17  5:58 UTC (permalink / raw)
  To: Ritesh Harjani
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, chris, shawnguo,
	linux-arm-kernel, haibo.chen, dongas86

On 17/05/16 07:31, Ritesh Harjani wrote:
> On Tue, May 10, 2016 at 12:21 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>> On 15/04/16 20:29, Dong Aisheng wrote:
>>> Current code will report the wrong data interrupt got when no
>>> data operation in progress assumed by getting !host->data in
>>> sdhci_data_irq().
>>>
>>> For a data command handling process, the driver will call
>>> sdhci_finish_data() and clear host->data in case any data error,
>>> then card finish_tasklet will do the rest controller reset work.
>>>
>>> Before the tasklet got run, however, controllers may report the
>>> TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
>>> than data CRC error and data end bit error interrupts for single
>>> block transfer or the last block of multiblock transfer.
> 
> What if the controller generates Transfer complete interrupt bit more slower
> and the tasklet do get a chance to run. In that case even host->mrq
> will become NULL.
> Actually if that happens it's even more worse since the driver may
> start issuing other commands to controller.
> 
> Are we covering that case here? Do you think that this case is possible?

After data error, the host driver resets the controller so there will be no
more interrupts relating to that mrq.

This patch is avoiding unnecessary warnings until that happens.

> 
> 
>>>
>>> Controller usually detects and generates data CRC/end bit error
>>> interrupts once one block on the bus is transferred completely.
>>> For single block transfer, since there's only one bock to transfer,
>>> the controller will report transfer complete interrupt as well,
>>> but until the data in controller FIFO has been successfully
>>> transferred to memory. The time gap of TC and CRC interrupt depends on
>>> the system busy state at that point and memory bus access speed.
>>>
>>> So it is possible when TC interrupt generated, host->data is already
>>> equal to NULL due to cleared by former CRC/Data End Bit error which
>>> is reasonable.
>>>
>>> Thus we DO NOT report the weird data interrupt event for this case.
>>>
>>> Else we may easily see warning below during SD3.0 card manually tuning
>>> process (calling mmc_send_tuning() which is a single block transfer)
>>> mmc0: Got data interrupt 0x00000002 even though no data operation was in progress
>>>
>>> The detailed command log is as follows:
>>> [ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
>>> [ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
>>> [ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
>>> [ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
>>> [ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
>>> [ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
>>> [ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
>>> [ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
>>> [ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
>>> [ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
>>> [ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
>>> [ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
>>> [ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
>>> [ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
>>> [ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
>>> [ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
>>> [ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
>>> [ 1657.929965] sdhci: Host ctl2: 0x000000c8
>>> [ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
>>> [ 1657.929995] sdhci: ===========================================
>>> [ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
>>> [ 1657.930179] mmc0:     0 bytes transferred: -84
>>>
>>> It shows we first have a data CRC error interrupt then a data transfer
>>> complete interrupt.
>>> Then we got the !host->data case in sdhci_data_irq().
>>>
>>> CC: stable <stable@vger.kernel.org>
>>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>>> ---
>>>  drivers/mmc/host/sdhci.c | 11 +++++++++++
>>>  1 file changed, 11 insertions(+)
>>>
>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>> index 40e3551..2eb0e34 100644
>>> --- a/drivers/mmc/host/sdhci.c
>>> +++ b/drivers/mmc/host/sdhci.c
>>> @@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
>>>                       }
>>>               }
>>>
>>> +             /*
>>> +              * The "data complete" interrupt is possible to happen a bit
>>> +              * later than CRC error and data end bit error interrupts
>>> +              * separately for single block transfer or the last block of
>>> +              * multiblock transfer. For this case, we DO NOT report the
>>> +              * weird data interrupt event.
>>> +              */
>>> +             if ((intmask & SDHCI_INT_DATA_END) &&
>>> +                 (host->mrq && host->mrq->data && host->mrq->data->error))
>>> +                     return;
>>
>> This could be generalized a bit more i.e. what about:
>>
>>                 /*
>>                  * After an error and before the the data circuit is reset in
>>                  * sdhci_tasklet_finish, we could get more interrupts, but we
>>                  * already have an error, so ignore them.
>>                  */
>>                 if (host->mrq && host->mrq->data && host->mrq->data->error)
>>                         return;
>>
>>> +
>>>               pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
>>>                      mmc_hostname(host->mmc), (unsigned)intmask);
>>>               sdhci_dumpregs(host);
>>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


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

* [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during no data transfer
@ 2016-05-17  5:58         ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-17  5:58 UTC (permalink / raw)
  To: linux-arm-kernel

On 17/05/16 07:31, Ritesh Harjani wrote:
> On Tue, May 10, 2016 at 12:21 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>> On 15/04/16 20:29, Dong Aisheng wrote:
>>> Current code will report the wrong data interrupt got when no
>>> data operation in progress assumed by getting !host->data in
>>> sdhci_data_irq().
>>>
>>> For a data command handling process, the driver will call
>>> sdhci_finish_data() and clear host->data in case any data error,
>>> then card finish_tasklet will do the rest controller reset work.
>>>
>>> Before the tasklet got run, however, controllers may report the
>>> TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
>>> than data CRC error and data end bit error interrupts for single
>>> block transfer or the last block of multiblock transfer.
> 
> What if the controller generates Transfer complete interrupt bit more slower
> and the tasklet do get a chance to run. In that case even host->mrq
> will become NULL.
> Actually if that happens it's even more worse since the driver may
> start issuing other commands to controller.
> 
> Are we covering that case here? Do you think that this case is possible?

After data error, the host driver resets the controller so there will be no
more interrupts relating to that mrq.

This patch is avoiding unnecessary warnings until that happens.

> 
> 
>>>
>>> Controller usually detects and generates data CRC/end bit error
>>> interrupts once one block on the bus is transferred completely.
>>> For single block transfer, since there's only one bock to transfer,
>>> the controller will report transfer complete interrupt as well,
>>> but until the data in controller FIFO has been successfully
>>> transferred to memory. The time gap of TC and CRC interrupt depends on
>>> the system busy state at that point and memory bus access speed.
>>>
>>> So it is possible when TC interrupt generated, host->data is already
>>> equal to NULL due to cleared by former CRC/Data End Bit error which
>>> is reasonable.
>>>
>>> Thus we DO NOT report the weird data interrupt event for this case.
>>>
>>> Else we may easily see warning below during SD3.0 card manually tuning
>>> process (calling mmc_send_tuning() which is a single block transfer)
>>> mmc0: Got data interrupt 0x00000002 even though no data operation was in progress
>>>
>>> The detailed command log is as follows:
>>> [ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
>>> [ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
>>> [ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
>>> [ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
>>> [ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
>>> [ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
>>> [ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
>>> [ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
>>> [ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
>>> [ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
>>> [ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
>>> [ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
>>> [ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
>>> [ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
>>> [ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
>>> [ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
>>> [ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
>>> [ 1657.929965] sdhci: Host ctl2: 0x000000c8
>>> [ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
>>> [ 1657.929995] sdhci: ===========================================
>>> [ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
>>> [ 1657.930179] mmc0:     0 bytes transferred: -84
>>>
>>> It shows we first have a data CRC error interrupt then a data transfer
>>> complete interrupt.
>>> Then we got the !host->data case in sdhci_data_irq().
>>>
>>> CC: stable <stable@vger.kernel.org>
>>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>>> ---
>>>  drivers/mmc/host/sdhci.c | 11 +++++++++++
>>>  1 file changed, 11 insertions(+)
>>>
>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>> index 40e3551..2eb0e34 100644
>>> --- a/drivers/mmc/host/sdhci.c
>>> +++ b/drivers/mmc/host/sdhci.c
>>> @@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
>>>                       }
>>>               }
>>>
>>> +             /*
>>> +              * The "data complete" interrupt is possible to happen a bit
>>> +              * later than CRC error and data end bit error interrupts
>>> +              * separately for single block transfer or the last block of
>>> +              * multiblock transfer. For this case, we DO NOT report the
>>> +              * weird data interrupt event.
>>> +              */
>>> +             if ((intmask & SDHCI_INT_DATA_END) &&
>>> +                 (host->mrq && host->mrq->data && host->mrq->data->error))
>>> +                     return;
>>
>> This could be generalized a bit more i.e. what about:
>>
>>                 /*
>>                  * After an error and before the the data circuit is reset in
>>                  * sdhci_tasklet_finish, we could get more interrupts, but we
>>                  * already have an error, so ignore them.
>>                  */
>>                 if (host->mrq && host->mrq->data && host->mrq->data->error)
>>                         return;
>>
>>> +
>>>               pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
>>>                      mmc_hostname(host->mmc), (unsigned)intmask);
>>>               sdhci_dumpregs(host);
>>>
>>
>> --
>> 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
> 

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

* Re: [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during no data transfer
  2016-05-10  6:51     ` Adrian Hunter
@ 2016-05-26 11:41       ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-05-26 11:41 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, ulf.hansson, chris, shawnguo,
	linux-arm-kernel, haibo.chen

On Tue, May 10, 2016 at 09:51:31AM +0300, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
> > Current code will report the wrong data interrupt got when no
> > data operation in progress assumed by getting !host->data in
> > sdhci_data_irq().
> > 
> > For a data command handling process, the driver will call
> > sdhci_finish_data() and clear host->data in case any data error,
> > then card finish_tasklet will do the rest controller reset work.
> > 
> > Before the tasklet got run, however, controllers may report the
> > TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
> > than data CRC error and data end bit error interrupts for single
> > block transfer or the last block of multiblock transfer.
> > 
> > Controller usually detects and generates data CRC/end bit error
> > interrupts once one block on the bus is transferred completely.
> > For single block transfer, since there's only one bock to transfer,
> > the controller will report transfer complete interrupt as well,
> > but until the data in controller FIFO has been successfully
> > transferred to memory. The time gap of TC and CRC interrupt depends on
> > the system busy state at that point and memory bus access speed.
> > 
> > So it is possible when TC interrupt generated, host->data is already
> > equal to NULL due to cleared by former CRC/Data End Bit error which
> > is reasonable.
> > 
> > Thus we DO NOT report the weird data interrupt event for this case.
> > 
> > Else we may easily see warning below during SD3.0 card manually tuning
> > process (calling mmc_send_tuning() which is a single block transfer)
> > mmc0: Got data interrupt 0x00000002 even though no data operation was in progress
> > 
> > The detailed command log is as follows:
> > [ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
> > [ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
> > [ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
> > [ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
> > [ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
> > [ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
> > [ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
> > [ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
> > [ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
> > [ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
> > [ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
> > [ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
> > [ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
> > [ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
> > [ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
> > [ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
> > [ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
> > [ 1657.929965] sdhci: Host ctl2: 0x000000c8
> > [ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
> > [ 1657.929995] sdhci: ===========================================
> > [ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
> > [ 1657.930179] mmc0:     0 bytes transferred: -84
> > 
> > It shows we first have a data CRC error interrupt then a data transfer
> > complete interrupt.
> > Then we got the !host->data case in sdhci_data_irq().
> > 
> > CC: stable <stable@vger.kernel.org>
> > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> > ---
> >  drivers/mmc/host/sdhci.c | 11 +++++++++++
> >  1 file changed, 11 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> > index 40e3551..2eb0e34 100644
> > --- a/drivers/mmc/host/sdhci.c
> > +++ b/drivers/mmc/host/sdhci.c
> > @@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
> >  			}
> >  		}
> >  
> > +		/*
> > +		 * The "data complete" interrupt is possible to happen a bit
> > +		 * later than CRC error and data end bit error interrupts
> > +		 * separately for single block transfer or the last block of
> > +		 * multiblock transfer. For this case, we DO NOT report the
> > +		 * weird data interrupt event.
> > +		 */
> > +		if ((intmask & SDHCI_INT_DATA_END) &&
> > +		    (host->mrq && host->mrq->data && host->mrq->data->error))
> > +			return;
> 
> This could be generalized a bit more i.e. what about:
> 
> 		/*
> 		 * After an error and before the the data circuit is reset in
> 		 * sdhci_tasklet_finish, we could get more interrupts, but we
> 		 * already have an error, so ignore them.
> 		 */
> 		if (host->mrq && host->mrq->data && host->mrq->data->error)
> 			return;
> 

Sounds good to me.
If you wouldn't mind, i'd like to add a bit more:
		/*
		 * After an error and before the data circuit is reset in
		 * sdhci_tasklet_finish, we could get more interrupts
		 * e.g. "data complete" interrupt, but we already have
		 * an error, so ignore them.
		 */

Regards
Dong Aisheng

> > +
> >  		pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
> >  		       mmc_hostname(host->mmc), (unsigned)intmask);
> >  		sdhci_dumpregs(host);
> > 
> 

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

* [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during no data transfer
@ 2016-05-26 11:41       ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-05-26 11:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, May 10, 2016 at 09:51:31AM +0300, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
> > Current code will report the wrong data interrupt got when no
> > data operation in progress assumed by getting !host->data in
> > sdhci_data_irq().
> > 
> > For a data command handling process, the driver will call
> > sdhci_finish_data() and clear host->data in case any data error,
> > then card finish_tasklet will do the rest controller reset work.
> > 
> > Before the tasklet got run, however, controllers may report the
> > TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
> > than data CRC error and data end bit error interrupts for single
> > block transfer or the last block of multiblock transfer.
> > 
> > Controller usually detects and generates data CRC/end bit error
> > interrupts once one block on the bus is transferred completely.
> > For single block transfer, since there's only one bock to transfer,
> > the controller will report transfer complete interrupt as well,
> > but until the data in controller FIFO has been successfully
> > transferred to memory. The time gap of TC and CRC interrupt depends on
> > the system busy state at that point and memory bus access speed.
> > 
> > So it is possible when TC interrupt generated, host->data is already
> > equal to NULL due to cleared by former CRC/Data End Bit error which
> > is reasonable.
> > 
> > Thus we DO NOT report the weird data interrupt event for this case.
> > 
> > Else we may easily see warning below during SD3.0 card manually tuning
> > process (calling mmc_send_tuning() which is a single block transfer)
> > mmc0: Got data interrupt 0x00000002 even though no data operation was in progress
> > 
> > The detailed command log is as follows:
> > [ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
> > [ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
> > [ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
> > [ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
> > [ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
> > [ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
> > [ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
> > [ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
> > [ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
> > [ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
> > [ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
> > [ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
> > [ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
> > [ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
> > [ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
> > [ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
> > [ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
> > [ 1657.929965] sdhci: Host ctl2: 0x000000c8
> > [ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
> > [ 1657.929995] sdhci: ===========================================
> > [ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
> > [ 1657.930179] mmc0:     0 bytes transferred: -84
> > 
> > It shows we first have a data CRC error interrupt then a data transfer
> > complete interrupt.
> > Then we got the !host->data case in sdhci_data_irq().
> > 
> > CC: stable <stable@vger.kernel.org>
> > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> > ---
> >  drivers/mmc/host/sdhci.c | 11 +++++++++++
> >  1 file changed, 11 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> > index 40e3551..2eb0e34 100644
> > --- a/drivers/mmc/host/sdhci.c
> > +++ b/drivers/mmc/host/sdhci.c
> > @@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
> >  			}
> >  		}
> >  
> > +		/*
> > +		 * The "data complete" interrupt is possible to happen a bit
> > +		 * later than CRC error and data end bit error interrupts
> > +		 * separately for single block transfer or the last block of
> > +		 * multiblock transfer. For this case, we DO NOT report the
> > +		 * weird data interrupt event.
> > +		 */
> > +		if ((intmask & SDHCI_INT_DATA_END) &&
> > +		    (host->mrq && host->mrq->data && host->mrq->data->error))
> > +			return;
> 
> This could be generalized a bit more i.e. what about:
> 
> 		/*
> 		 * After an error and before the the data circuit is reset in
> 		 * sdhci_tasklet_finish, we could get more interrupts, but we
> 		 * already have an error, so ignore them.
> 		 */
> 		if (host->mrq && host->mrq->data && host->mrq->data->error)
> 			return;
> 

Sounds good to me.
If you wouldn't mind, i'd like to add a bit more:
		/*
		 * After an error and before the data circuit is reset in
		 * sdhci_tasklet_finish, we could get more interrupts
		 * e.g. "data complete" interrupt, but we already have
		 * an error, so ignore them.
		 */

Regards
Dong Aisheng

> > +
> >  		pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
> >  		       mmc_hostname(host->mmc), (unsigned)intmask);
> >  		sdhci_dumpregs(host);
> > 
> 

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

* Re: [PATCH 21/23] mmc: sdhci-esdhc-imx: factor out hw related intialization into function
  2016-05-10 12:15     ` Adrian Hunter
@ 2016-05-26 11:45       ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-05-26 11:45 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, ulf.hansson, chris, shawnguo,
	linux-arm-kernel, haibo.chen

On Tue, May 10, 2016 at 03:15:59PM +0300, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
> > Factor out hw related intialization into a separate function which
> > has two benifits:
> > 1) concentrate hw related intialization at one place
> > 2) ease the hw state restore after resume by simply
> > calling this function
> 
> There are really 2 changes here, please make it 2 patches.
> 

Okay i will do it in V2.
Thanks for the suggestion.

Regards
Dong Aisheng

> > 
> > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> > ---
> >  drivers/mmc/host/sdhci-esdhc-imx.c | 76 +++++++++++++++++++++-----------------
> >  1 file changed, 42 insertions(+), 34 deletions(-)
> > 
> > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> > index 3ff213f..95f3632 100644
> > --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> > @@ -978,6 +978,44 @@ static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
> >  	.ops = &sdhci_esdhc_ops,
> >  };
> >  
> > +static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
> > +{
> > +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> > +	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
> > +
> > +	if (esdhc_is_usdhc(imx_data)) {
> > +		/*
> > +		 * The imx6q ROM code will change the default watermark
> > +		 * level setting to something insane.  Change it back here.
> > +		 */
> > +		writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> > +
> > +		/*
> > +		 * ROM code will change the bit burst_length_enable setting
> > +		 * to zero if this usdhc is choosed to boot system. Change
> > +		 * it back here, otherwise it will impact the performance a
> > +		 * lot. This bit is used to enable/disable the burst length
> > +		 * for the external AHB2AXI bridge, it's usefully especially
> > +		 * for INCR transfer because without burst length indicator,
> > +		 * the AHB2AXI bridge does not know the burst length in
> > +		 * advance. And without burst length indicator, AHB INCR
> > +		 * transfer can only be converted to singles on the AXI side.
> > +		 */
> > +		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
> > +			| ESDHC_BURST_LEN_EN_INCR,
> > +			host->ioaddr + SDHCI_HOST_CONTROL);
> > +		/*
> > +		* errata ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
> > +		* TO1.1, it's harmless for MX6SL
> > +		*/
> > +		writel(readl(host->ioaddr + 0x6c) | BIT(7),
> > +			host->ioaddr + 0x6c);
> > +
> > +		/* disable DLL_CTRL delay line settings */
> > +		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
> > +	}
> > +}
> > +
> >  #ifdef CONFIG_OF
> >  static int
> >  sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
> > @@ -1175,43 +1213,13 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
> >  		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK
> >  			| SDHCI_QUIRK_BROKEN_ADMA;
> >  
> > -	/*
> > -	 * The imx6q ROM code will change the default watermark level setting
> > -	 * to something insane.  Change it back here.
> > -	 */
> > -	if (esdhc_is_usdhc(imx_data)) {
> > -		writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> > +	sdhci_esdhc_imx_hwinit(host);
> >  
> > +	if (esdhc_is_usdhc(imx_data)) {
> >  		host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
> >  		host->mmc->caps |= MMC_CAP_1_8V_DDR;
> > -
> > -		/*
> > -		 * ROM code will change the bit burst_length_enable setting
> > -		 * to zero if this usdhc is choosed to boot system. Change
> > -		 * it back here, otherwise it will impact the performance a
> > -		 * lot. This bit is used to enable/disable the burst length
> > -		 * for the external AHB2AXI bridge, it's usefully especially
> > -		 * for INCR transfer because without burst length indicator,
> > -		 * the AHB2AXI bridge does not know the burst length in
> > -		 * advance. And without burst length indicator, AHB INCR
> > -		 * transfer can only be converted to singles on the AXI side.
> > -		 */
> > -		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
> > -			| ESDHC_BURST_LEN_EN_INCR,
> > -			host->ioaddr + SDHCI_HOST_CONTROL);
> > -
> >  		if (!(imx_data->socdata->flags & ESDHC_FLAG_HS200))
> >  			host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
> > -
> > -		/*
> > -		* errata ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
> > -		* TO1.1, it's harmless for MX6SL
> > -		*/
> > -		writel(readl(host->ioaddr + 0x6c) | BIT(7),
> > -			host->ioaddr + 0x6c);
> > -
> > -		/* disable DLL_CTRL delay line settings */
> > -		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
> >  	}
> >  
> >  	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
> > @@ -1289,8 +1297,8 @@ static int sdhci_esdhc_resume(struct device *dev)
> >  {
> >  	struct sdhci_host *host = dev_get_drvdata(dev);
> >  
> > -	/* restore watermark setting in case it's lost in low power mode */
> > -	writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> > +	/* reinitialize hw state in case it's lost in low power mode */
> > +	sdhci_esdhc_imx_hwinit(host);
> >  
> >  	return sdhci_pltfm_resume(dev);
> >  }
> > 
> 

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

* [PATCH 21/23] mmc: sdhci-esdhc-imx: factor out hw related intialization into function
@ 2016-05-26 11:45       ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-05-26 11:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, May 10, 2016 at 03:15:59PM +0300, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
> > Factor out hw related intialization into a separate function which
> > has two benifits:
> > 1) concentrate hw related intialization at one place
> > 2) ease the hw state restore after resume by simply
> > calling this function
> 
> There are really 2 changes here, please make it 2 patches.
> 

Okay i will do it in V2.
Thanks for the suggestion.

Regards
Dong Aisheng

> > 
> > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> > ---
> >  drivers/mmc/host/sdhci-esdhc-imx.c | 76 +++++++++++++++++++++-----------------
> >  1 file changed, 42 insertions(+), 34 deletions(-)
> > 
> > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> > index 3ff213f..95f3632 100644
> > --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> > @@ -978,6 +978,44 @@ static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
> >  	.ops = &sdhci_esdhc_ops,
> >  };
> >  
> > +static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
> > +{
> > +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> > +	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
> > +
> > +	if (esdhc_is_usdhc(imx_data)) {
> > +		/*
> > +		 * The imx6q ROM code will change the default watermark
> > +		 * level setting to something insane.  Change it back here.
> > +		 */
> > +		writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> > +
> > +		/*
> > +		 * ROM code will change the bit burst_length_enable setting
> > +		 * to zero if this usdhc is choosed to boot system. Change
> > +		 * it back here, otherwise it will impact the performance a
> > +		 * lot. This bit is used to enable/disable the burst length
> > +		 * for the external AHB2AXI bridge, it's usefully especially
> > +		 * for INCR transfer because without burst length indicator,
> > +		 * the AHB2AXI bridge does not know the burst length in
> > +		 * advance. And without burst length indicator, AHB INCR
> > +		 * transfer can only be converted to singles on the AXI side.
> > +		 */
> > +		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
> > +			| ESDHC_BURST_LEN_EN_INCR,
> > +			host->ioaddr + SDHCI_HOST_CONTROL);
> > +		/*
> > +		* errata ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
> > +		* TO1.1, it's harmless for MX6SL
> > +		*/
> > +		writel(readl(host->ioaddr + 0x6c) | BIT(7),
> > +			host->ioaddr + 0x6c);
> > +
> > +		/* disable DLL_CTRL delay line settings */
> > +		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
> > +	}
> > +}
> > +
> >  #ifdef CONFIG_OF
> >  static int
> >  sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
> > @@ -1175,43 +1213,13 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
> >  		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK
> >  			| SDHCI_QUIRK_BROKEN_ADMA;
> >  
> > -	/*
> > -	 * The imx6q ROM code will change the default watermark level setting
> > -	 * to something insane.  Change it back here.
> > -	 */
> > -	if (esdhc_is_usdhc(imx_data)) {
> > -		writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> > +	sdhci_esdhc_imx_hwinit(host);
> >  
> > +	if (esdhc_is_usdhc(imx_data)) {
> >  		host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
> >  		host->mmc->caps |= MMC_CAP_1_8V_DDR;
> > -
> > -		/*
> > -		 * ROM code will change the bit burst_length_enable setting
> > -		 * to zero if this usdhc is choosed to boot system. Change
> > -		 * it back here, otherwise it will impact the performance a
> > -		 * lot. This bit is used to enable/disable the burst length
> > -		 * for the external AHB2AXI bridge, it's usefully especially
> > -		 * for INCR transfer because without burst length indicator,
> > -		 * the AHB2AXI bridge does not know the burst length in
> > -		 * advance. And without burst length indicator, AHB INCR
> > -		 * transfer can only be converted to singles on the AXI side.
> > -		 */
> > -		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
> > -			| ESDHC_BURST_LEN_EN_INCR,
> > -			host->ioaddr + SDHCI_HOST_CONTROL);
> > -
> >  		if (!(imx_data->socdata->flags & ESDHC_FLAG_HS200))
> >  			host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
> > -
> > -		/*
> > -		* errata ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
> > -		* TO1.1, it's harmless for MX6SL
> > -		*/
> > -		writel(readl(host->ioaddr + 0x6c) | BIT(7),
> > -			host->ioaddr + 0x6c);
> > -
> > -		/* disable DLL_CTRL delay line settings */
> > -		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
> >  	}
> >  
> >  	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
> > @@ -1289,8 +1297,8 @@ static int sdhci_esdhc_resume(struct device *dev)
> >  {
> >  	struct sdhci_host *host = dev_get_drvdata(dev);
> >  
> > -	/* restore watermark setting in case it's lost in low power mode */
> > -	writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> > +	/* reinitialize hw state in case it's lost in low power mode */
> > +	sdhci_esdhc_imx_hwinit(host);
> >  
> >  	return sdhci_pltfm_resume(dev);
> >  }
> > 
> 

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

* Re: [PATCH 20/23] mmc: sdhci-esdhc-imx: fix strobe DLL lock wrong clock issue
  2016-05-10 12:03     ` Adrian Hunter
@ 2016-05-26 11:47       ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-05-26 11:47 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, ulf.hansson, chris, shawnguo,
	linux-arm-kernel, haibo.chen

On Tue, May 10, 2016 at 03:03:48PM +0300, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
> > When enable DDR, the clock factor definition is changed.
> > e.g. original 200Mhz will become 100Mhz one MIX_CTRL_DDREN bit is set
> > So we need to update the clock setting then the strobe dll can lock
> > the correct clock rate.
> > 
> > Additionally we also need disable the clock before locking strobe dll.
> > 
> > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> 
> Apart from redundant parentheses (refer below):
> 
> Acked-by: Adrian Hunter <adrian.hunter@intel.com>
> 

Could remove in V2.
Thanks for the suggestion.

Regards
Dong Aisheng

> > ---
> >  drivers/mmc/host/sdhci-esdhc-imx.c | 7 +++++++
> >  1 file changed, 7 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> > index 07b1144..3ff213f 100644
> > --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> > @@ -852,6 +852,11 @@ static void esdhc_set_strobe_dll(struct sdhci_host *host)
> >  	u32 v;
> >  
> >  	if (host->mmc->actual_clock > ESDHC_STROBE_DLL_CLK_FREQ) {
> > +		/* disable clock before enabling strobe dll */
> > +		writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) &
> > +		       (~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON),
> 
> Parentheses look redundant
> 
> > +		       host->ioaddr + ESDHC_VENDOR_SPEC);
> > +
> >  		/* force a reset on strobe dll */
> >  		writel(ESDHC_STROBE_DLL_CTRL_RESET,
> >  			host->ioaddr + ESDHC_STROBE_DLL_CTRL);
> > @@ -913,6 +918,8 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
> >  		m |= ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN;
> >  		writel(m, host->ioaddr + ESDHC_MIX_CTRL);
> >  		imx_data->is_ddr = 1;
> > +		/* update clock after enable DDR for strobe DLL lock */
> > +		host->ops->set_clock(host, host->clock);
> >  		esdhc_set_strobe_dll(host);
> >  		break;
> >  	}
> > 
> 

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

* [PATCH 20/23] mmc: sdhci-esdhc-imx: fix strobe DLL lock wrong clock issue
@ 2016-05-26 11:47       ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-05-26 11:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, May 10, 2016 at 03:03:48PM +0300, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
> > When enable DDR, the clock factor definition is changed.
> > e.g. original 200Mhz will become 100Mhz one MIX_CTRL_DDREN bit is set
> > So we need to update the clock setting then the strobe dll can lock
> > the correct clock rate.
> > 
> > Additionally we also need disable the clock before locking strobe dll.
> > 
> > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> 
> Apart from redundant parentheses (refer below):
> 
> Acked-by: Adrian Hunter <adrian.hunter@intel.com>
> 

Could remove in V2.
Thanks for the suggestion.

Regards
Dong Aisheng

> > ---
> >  drivers/mmc/host/sdhci-esdhc-imx.c | 7 +++++++
> >  1 file changed, 7 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> > index 07b1144..3ff213f 100644
> > --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> > @@ -852,6 +852,11 @@ static void esdhc_set_strobe_dll(struct sdhci_host *host)
> >  	u32 v;
> >  
> >  	if (host->mmc->actual_clock > ESDHC_STROBE_DLL_CLK_FREQ) {
> > +		/* disable clock before enabling strobe dll */
> > +		writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) &
> > +		       (~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON),
> 
> Parentheses look redundant
> 
> > +		       host->ioaddr + ESDHC_VENDOR_SPEC);
> > +
> >  		/* force a reset on strobe dll */
> >  		writel(ESDHC_STROBE_DLL_CTRL_RESET,
> >  			host->ioaddr + ESDHC_STROBE_DLL_CTRL);
> > @@ -913,6 +918,8 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
> >  		m |= ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN;
> >  		writel(m, host->ioaddr + ESDHC_MIX_CTRL);
> >  		imx_data->is_ddr = 1;
> > +		/* update clock after enable DDR for strobe DLL lock */
> > +		host->ops->set_clock(host, host->clock);
> >  		esdhc_set_strobe_dll(host);
> >  		break;
> >  	}
> > 
> 

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

* Re: [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during no data transfer
  2016-05-26 11:41       ` Dong Aisheng
@ 2016-05-26 11:59         ` Adrian Hunter
  -1 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-26 11:59 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Dong Aisheng, linux-mmc, ulf.hansson, chris, shawnguo,
	linux-arm-kernel, haibo.chen

On 26/05/16 14:41, Dong Aisheng wrote:
> On Tue, May 10, 2016 at 09:51:31AM +0300, Adrian Hunter wrote:
>> On 15/04/16 20:29, Dong Aisheng wrote:
>>> Current code will report the wrong data interrupt got when no
>>> data operation in progress assumed by getting !host->data in
>>> sdhci_data_irq().
>>>
>>> For a data command handling process, the driver will call
>>> sdhci_finish_data() and clear host->data in case any data error,
>>> then card finish_tasklet will do the rest controller reset work.
>>>
>>> Before the tasklet got run, however, controllers may report the
>>> TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
>>> than data CRC error and data end bit error interrupts for single
>>> block transfer or the last block of multiblock transfer.
>>>
>>> Controller usually detects and generates data CRC/end bit error
>>> interrupts once one block on the bus is transferred completely.
>>> For single block transfer, since there's only one bock to transfer,
>>> the controller will report transfer complete interrupt as well,
>>> but until the data in controller FIFO has been successfully
>>> transferred to memory. The time gap of TC and CRC interrupt depends on
>>> the system busy state at that point and memory bus access speed.
>>>
>>> So it is possible when TC interrupt generated, host->data is already
>>> equal to NULL due to cleared by former CRC/Data End Bit error which
>>> is reasonable.
>>>
>>> Thus we DO NOT report the weird data interrupt event for this case.
>>>
>>> Else we may easily see warning below during SD3.0 card manually tuning
>>> process (calling mmc_send_tuning() which is a single block transfer)
>>> mmc0: Got data interrupt 0x00000002 even though no data operation was in progress
>>>
>>> The detailed command log is as follows:
>>> [ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
>>> [ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
>>> [ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
>>> [ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
>>> [ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
>>> [ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
>>> [ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
>>> [ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
>>> [ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
>>> [ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
>>> [ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
>>> [ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
>>> [ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
>>> [ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
>>> [ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
>>> [ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
>>> [ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
>>> [ 1657.929965] sdhci: Host ctl2: 0x000000c8
>>> [ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
>>> [ 1657.929995] sdhci: ===========================================
>>> [ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
>>> [ 1657.930179] mmc0:     0 bytes transferred: -84
>>>
>>> It shows we first have a data CRC error interrupt then a data transfer
>>> complete interrupt.
>>> Then we got the !host->data case in sdhci_data_irq().
>>>
>>> CC: stable <stable@vger.kernel.org>
>>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>>> ---
>>>  drivers/mmc/host/sdhci.c | 11 +++++++++++
>>>  1 file changed, 11 insertions(+)
>>>
>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>> index 40e3551..2eb0e34 100644
>>> --- a/drivers/mmc/host/sdhci.c
>>> +++ b/drivers/mmc/host/sdhci.c
>>> @@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
>>>  			}
>>>  		}
>>>  
>>> +		/*
>>> +		 * The "data complete" interrupt is possible to happen a bit
>>> +		 * later than CRC error and data end bit error interrupts
>>> +		 * separately for single block transfer or the last block of
>>> +		 * multiblock transfer. For this case, we DO NOT report the
>>> +		 * weird data interrupt event.
>>> +		 */
>>> +		if ((intmask & SDHCI_INT_DATA_END) &&
>>> +		    (host->mrq && host->mrq->data && host->mrq->data->error))
>>> +			return;
>>
>> This could be generalized a bit more i.e. what about:
>>
>> 		/*
>> 		 * After an error and before the the data circuit is reset in
>> 		 * sdhci_tasklet_finish, we could get more interrupts, but we
>> 		 * already have an error, so ignore them.
>> 		 */
>> 		if (host->mrq && host->mrq->data && host->mrq->data->error)
>> 			return;
>>
> 
> Sounds good to me.
> If you wouldn't mind, i'd like to add a bit more:
> 		/*
> 		 * After an error and before the data circuit is reset in
> 		 * sdhci_tasklet_finish, we could get more interrupts
> 		 * e.g. "data complete" interrupt, but we already have
> 		 * an error, so ignore them.
> 		 */
> 

Fine by me



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

* [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during no data transfer
@ 2016-05-26 11:59         ` Adrian Hunter
  0 siblings, 0 replies; 170+ messages in thread
From: Adrian Hunter @ 2016-05-26 11:59 UTC (permalink / raw)
  To: linux-arm-kernel

On 26/05/16 14:41, Dong Aisheng wrote:
> On Tue, May 10, 2016 at 09:51:31AM +0300, Adrian Hunter wrote:
>> On 15/04/16 20:29, Dong Aisheng wrote:
>>> Current code will report the wrong data interrupt got when no
>>> data operation in progress assumed by getting !host->data in
>>> sdhci_data_irq().
>>>
>>> For a data command handling process, the driver will call
>>> sdhci_finish_data() and clear host->data in case any data error,
>>> then card finish_tasklet will do the rest controller reset work.
>>>
>>> Before the tasklet got run, however, controllers may report the
>>> TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
>>> than data CRC error and data end bit error interrupts for single
>>> block transfer or the last block of multiblock transfer.
>>>
>>> Controller usually detects and generates data CRC/end bit error
>>> interrupts once one block on the bus is transferred completely.
>>> For single block transfer, since there's only one bock to transfer,
>>> the controller will report transfer complete interrupt as well,
>>> but until the data in controller FIFO has been successfully
>>> transferred to memory. The time gap of TC and CRC interrupt depends on
>>> the system busy state at that point and memory bus access speed.
>>>
>>> So it is possible when TC interrupt generated, host->data is already
>>> equal to NULL due to cleared by former CRC/Data End Bit error which
>>> is reasonable.
>>>
>>> Thus we DO NOT report the weird data interrupt event for this case.
>>>
>>> Else we may easily see warning below during SD3.0 card manually tuning
>>> process (calling mmc_send_tuning() which is a single block transfer)
>>> mmc0: Got data interrupt 0x00000002 even though no data operation was in progress
>>>
>>> The detailed command log is as follows:
>>> [ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
>>> [ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
>>> [ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
>>> [ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
>>> [ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
>>> [ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
>>> [ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
>>> [ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
>>> [ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
>>> [ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
>>> [ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
>>> [ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
>>> [ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
>>> [ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
>>> [ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
>>> [ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
>>> [ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
>>> [ 1657.929965] sdhci: Host ctl2: 0x000000c8
>>> [ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
>>> [ 1657.929995] sdhci: ===========================================
>>> [ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
>>> [ 1657.930179] mmc0:     0 bytes transferred: -84
>>>
>>> It shows we first have a data CRC error interrupt then a data transfer
>>> complete interrupt.
>>> Then we got the !host->data case in sdhci_data_irq().
>>>
>>> CC: stable <stable@vger.kernel.org>
>>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>>> ---
>>>  drivers/mmc/host/sdhci.c | 11 +++++++++++
>>>  1 file changed, 11 insertions(+)
>>>
>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>> index 40e3551..2eb0e34 100644
>>> --- a/drivers/mmc/host/sdhci.c
>>> +++ b/drivers/mmc/host/sdhci.c
>>> @@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
>>>  			}
>>>  		}
>>>  
>>> +		/*
>>> +		 * The "data complete" interrupt is possible to happen a bit
>>> +		 * later than CRC error and data end bit error interrupts
>>> +		 * separately for single block transfer or the last block of
>>> +		 * multiblock transfer. For this case, we DO NOT report the
>>> +		 * weird data interrupt event.
>>> +		 */
>>> +		if ((intmask & SDHCI_INT_DATA_END) &&
>>> +		    (host->mrq && host->mrq->data && host->mrq->data->error))
>>> +			return;
>>
>> This could be generalized a bit more i.e. what about:
>>
>> 		/*
>> 		 * After an error and before the the data circuit is reset in
>> 		 * sdhci_tasklet_finish, we could get more interrupts, but we
>> 		 * already have an error, so ignore them.
>> 		 */
>> 		if (host->mrq && host->mrq->data && host->mrq->data->error)
>> 			return;
>>
> 
> Sounds good to me.
> If you wouldn't mind, i'd like to add a bit more:
> 		/*
> 		 * After an error and before the data circuit is reset in
> 		 * sdhci_tasklet_finish, we could get more interrupts
> 		 * e.g. "data complete" interrupt, but we already have
> 		 * an error, so ignore them.
> 		 */
> 

Fine by me

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

* Re: [PATCH 17/23] mmc: sdhci: add standard hw auto retuning support
  2016-05-10  8:35     ` Adrian Hunter
@ 2016-05-26 12:11       ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-05-26 12:11 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, ulf.hansson, chris, shawnguo,
	linux-arm-kernel, haibo.chen

On Tue, May 10, 2016 at 11:35:29AM +0300, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
> > If HW supports SDHCI_TUNING_MODE_3 which is auto retuning, we won't
> 
> Since this is about tuning mode 3, could you put that in the subject e.g.
> "Add support for auto re-tuning (tuning mode 3)"
> 
> > retune during runtime suspend and resume, instead we use Re-tuning
> > Request signaled via SDHCI_INT_RETUNE interrupt to do retuning and
> > hw auto retuning during data transfer to guarantee the signal sample
> > window correction.
> > 
> > This can avoid a mass of repeatly retuning during small file system
> 
> repeatly -> repeatedly
> 

Got it.

> > data access and improve the performance.
> > 
> > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> > ---
> >  drivers/mmc/host/sdhci.c | 18 ++++++++++++++----
> >  drivers/mmc/host/sdhci.h |  3 +++
> >  2 files changed, 17 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> > index 2eb0e34..0027b87 100644
> > --- a/drivers/mmc/host/sdhci.c
> > +++ b/drivers/mmc/host/sdhci.c
> > @@ -252,6 +252,9 @@ static void sdhci_init(struct sdhci_host *host, int soft)
> >  		    SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END |
> >  		    SDHCI_INT_RESPONSE;
> >  
> > +	if (host->tuning_mode == SDHCI_TUNING_MODE_3)
> 
> Tuning mode 2 uses this as well.  Might as well add it here.
> 

The origin plan is adding only mode 3 support here to make life
a bit easier. Seems mode 2 does not need much more things added.
So i can add it here too.

> > +		host->ier |= SDHCI_INT_RETUNE;
> > +
> >  	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
> >  	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
> >  
> > @@ -2477,6 +2480,9 @@ 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_RETUNE)
> > +			mmc_retune_needed(host->mmc);
> > +
> 
> Also need to add SDHCI_INT_RETUNE to the bits cleared further on, otherwise
> it will show up in the "Unexpected interrupt" message
> 

That's true.

> >  		if (intmask & SDHCI_INT_CARD_INT) {
> >  			sdhci_enable_sdio_irq_nolock(host, false);
> >  			host->thread_isr |= SDHCI_INT_CARD_INT;
> > @@ -2575,8 +2581,10 @@ int sdhci_suspend_host(struct sdhci_host *host)
> >  {
> >  	sdhci_disable_card_detection(host);
> >  
> > -	mmc_retune_timer_stop(host->mmc);
> > -	mmc_retune_needed(host->mmc);
> > +	if (host->tuning_mode == SDHCI_TUNING_MODE_1) {
> > +		mmc_retune_timer_stop(host->mmc);
> > +		mmc_retune_needed(host->mmc);
> > +	}
> 
> Probably wouldn't hurt to stop the timer always whether it's going or not.

Sounds correct.

> And tuning mode 2 is not auto re-tuning, so I would still expect to need
> re-tuning after power loss i.e.
> 
> 	mmc_retune_timer_stop(host->mmc);
> 	if (host->tuning_mode != SDHCI_TUNING_MODE_3)
> 		mmc_retune_needed(host->mmc);
> 

I agree with you.
Will get it in v2.

Regards
Dong Aisheng

> >  
> >  	if (!device_may_wakeup(mmc_dev(host->mmc))) {
> >  		host->ier = 0;
> > @@ -2651,8 +2659,10 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
> >  {
> >  	unsigned long flags;
> >  
> > -	mmc_retune_timer_stop(host->mmc);
> > -	mmc_retune_needed(host->mmc);
> > +	if (host->tuning_mode == SDHCI_TUNING_MODE_1) {
> > +		mmc_retune_timer_stop(host->mmc);
> > +		mmc_retune_needed(host->mmc);
> > +	}
> 
> Ditto
> 
> >  
> >  	spin_lock_irqsave(&host->lock, flags);
> >  	host->ier &= SDHCI_INT_CARD_INT;
> > diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> > index afa4de8..2c2404f 100644
> > --- a/drivers/mmc/host/sdhci.h
> > +++ b/drivers/mmc/host/sdhci.h
> > @@ -128,6 +128,7 @@
> >  #define  SDHCI_INT_CARD_INSERT	0x00000040
> >  #define  SDHCI_INT_CARD_REMOVE	0x00000080
> >  #define  SDHCI_INT_CARD_INT	0x00000100
> > +#define  SDHCI_INT_RETUNE	0x00001000
> >  #define  SDHCI_INT_ERROR	0x00008000
> >  #define  SDHCI_INT_TIMEOUT	0x00010000
> >  #define  SDHCI_INT_CRC		0x00020000
> > @@ -514,6 +515,8 @@ struct sdhci_host {
> >  	unsigned int		tuning_count;	/* Timer count for re-tuning */
> >  	unsigned int		tuning_mode;	/* Re-tuning mode supported by host */
> >  #define SDHCI_TUNING_MODE_1	0
> > +#define SDHCI_TUNING_MODE_2	1
> > +#define SDHCI_TUNING_MODE_3	2
> >  
> >  	unsigned long private[0] ____cacheline_aligned;
> >  };
> > 
> 

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

* [PATCH 17/23] mmc: sdhci: add standard hw auto retuning support
@ 2016-05-26 12:11       ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-05-26 12:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, May 10, 2016 at 11:35:29AM +0300, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
> > If HW supports SDHCI_TUNING_MODE_3 which is auto retuning, we won't
> 
> Since this is about tuning mode 3, could you put that in the subject e.g.
> "Add support for auto re-tuning (tuning mode 3)"
> 
> > retune during runtime suspend and resume, instead we use Re-tuning
> > Request signaled via SDHCI_INT_RETUNE interrupt to do retuning and
> > hw auto retuning during data transfer to guarantee the signal sample
> > window correction.
> > 
> > This can avoid a mass of repeatly retuning during small file system
> 
> repeatly -> repeatedly
> 

Got it.

> > data access and improve the performance.
> > 
> > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> > ---
> >  drivers/mmc/host/sdhci.c | 18 ++++++++++++++----
> >  drivers/mmc/host/sdhci.h |  3 +++
> >  2 files changed, 17 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> > index 2eb0e34..0027b87 100644
> > --- a/drivers/mmc/host/sdhci.c
> > +++ b/drivers/mmc/host/sdhci.c
> > @@ -252,6 +252,9 @@ static void sdhci_init(struct sdhci_host *host, int soft)
> >  		    SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END |
> >  		    SDHCI_INT_RESPONSE;
> >  
> > +	if (host->tuning_mode == SDHCI_TUNING_MODE_3)
> 
> Tuning mode 2 uses this as well.  Might as well add it here.
> 

The origin plan is adding only mode 3 support here to make life
a bit easier. Seems mode 2 does not need much more things added.
So i can add it here too.

> > +		host->ier |= SDHCI_INT_RETUNE;
> > +
> >  	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
> >  	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
> >  
> > @@ -2477,6 +2480,9 @@ 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_RETUNE)
> > +			mmc_retune_needed(host->mmc);
> > +
> 
> Also need to add SDHCI_INT_RETUNE to the bits cleared further on, otherwise
> it will show up in the "Unexpected interrupt" message
> 

That's true.

> >  		if (intmask & SDHCI_INT_CARD_INT) {
> >  			sdhci_enable_sdio_irq_nolock(host, false);
> >  			host->thread_isr |= SDHCI_INT_CARD_INT;
> > @@ -2575,8 +2581,10 @@ int sdhci_suspend_host(struct sdhci_host *host)
> >  {
> >  	sdhci_disable_card_detection(host);
> >  
> > -	mmc_retune_timer_stop(host->mmc);
> > -	mmc_retune_needed(host->mmc);
> > +	if (host->tuning_mode == SDHCI_TUNING_MODE_1) {
> > +		mmc_retune_timer_stop(host->mmc);
> > +		mmc_retune_needed(host->mmc);
> > +	}
> 
> Probably wouldn't hurt to stop the timer always whether it's going or not.

Sounds correct.

> And tuning mode 2 is not auto re-tuning, so I would still expect to need
> re-tuning after power loss i.e.
> 
> 	mmc_retune_timer_stop(host->mmc);
> 	if (host->tuning_mode != SDHCI_TUNING_MODE_3)
> 		mmc_retune_needed(host->mmc);
> 

I agree with you.
Will get it in v2.

Regards
Dong Aisheng

> >  
> >  	if (!device_may_wakeup(mmc_dev(host->mmc))) {
> >  		host->ier = 0;
> > @@ -2651,8 +2659,10 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
> >  {
> >  	unsigned long flags;
> >  
> > -	mmc_retune_timer_stop(host->mmc);
> > -	mmc_retune_needed(host->mmc);
> > +	if (host->tuning_mode == SDHCI_TUNING_MODE_1) {
> > +		mmc_retune_timer_stop(host->mmc);
> > +		mmc_retune_needed(host->mmc);
> > +	}
> 
> Ditto
> 
> >  
> >  	spin_lock_irqsave(&host->lock, flags);
> >  	host->ier &= SDHCI_INT_CARD_INT;
> > diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> > index afa4de8..2c2404f 100644
> > --- a/drivers/mmc/host/sdhci.h
> > +++ b/drivers/mmc/host/sdhci.h
> > @@ -128,6 +128,7 @@
> >  #define  SDHCI_INT_CARD_INSERT	0x00000040
> >  #define  SDHCI_INT_CARD_REMOVE	0x00000080
> >  #define  SDHCI_INT_CARD_INT	0x00000100
> > +#define  SDHCI_INT_RETUNE	0x00001000
> >  #define  SDHCI_INT_ERROR	0x00008000
> >  #define  SDHCI_INT_TIMEOUT	0x00010000
> >  #define  SDHCI_INT_CRC		0x00020000
> > @@ -514,6 +515,8 @@ struct sdhci_host {
> >  	unsigned int		tuning_count;	/* Timer count for re-tuning */
> >  	unsigned int		tuning_mode;	/* Re-tuning mode supported by host */
> >  #define SDHCI_TUNING_MODE_1	0
> > +#define SDHCI_TUNING_MODE_2	1
> > +#define SDHCI_TUNING_MODE_3	2
> >  
> >  	unsigned long private[0] ____cacheline_aligned;
> >  };
> > 
> 

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

* Re: [PATCH 18/23] mmc: sdhci-esdhc-imx: enable hw auto retuning for STD_TUNING
  2016-05-10 11:19     ` Adrian Hunter
@ 2016-05-26 12:21       ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-05-26 12:21 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, ulf.hansson, chris, shawnguo,
	linux-arm-kernel, haibo.chen

On Tue, May 10, 2016 at 02:19:40PM +0300, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
> > Enable HW auto retuning when set SDHCI_CTRL_EXEC_TUNING and clear it
> > when clear SDHCI_CTRL_TUNED_CLK.
> > 
> > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> 
> I presume this patch should wait for patch 17, but nevertheless:
> 
> Acked-by: Adrian Hunter <adrian.hunter@intel.com>
> 

Actually the interesting thing here is patch 18 and 19 do not need
patch 17 since our IC guy told me IMX uSDHC auto-tuning will
not Retuning request for mode 3.

Thanks for the pre-ACK.

Regards
Dong Aisheng

> > ---
> >  drivers/mmc/host/sdhci-esdhc-imx.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> > index 9f9be3f..a582a83 100644
> > --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> > @@ -44,6 +44,7 @@
> >  #define  ESDHC_MIX_CTRL_AC23EN		(1 << 7)
> >  #define  ESDHC_MIX_CTRL_EXE_TUNE	(1 << 22)
> >  #define  ESDHC_MIX_CTRL_SMPCLK_SEL	(1 << 23)
> > +#define  ESDHC_MIX_CTRL_AUTO_TUNE_EN	(1 << 24)
> >  #define  ESDHC_MIX_CTRL_FBCLK_SEL	(1 << 25)
> >  #define  ESDHC_MIX_CTRL_HS400_EN	(1 << 26)
> >  /* Bits 3 and 6 are not SDHCI standard definitions */
> > @@ -484,11 +485,13 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
> >  			} else {
> >  				v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
> >  				m &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
> > +				m &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
> >  			}
> >  
> >  			if (val & SDHCI_CTRL_EXEC_TUNING) {
> >  				v |= ESDHC_MIX_CTRL_EXE_TUNE;
> >  				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
> > +				m |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
> >  				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
> >  				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT;
> >  				if (imx_data->boarddata.tuning_start_tap) {
> > 
> 

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

* [PATCH 18/23] mmc: sdhci-esdhc-imx: enable hw auto retuning for STD_TUNING
@ 2016-05-26 12:21       ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-05-26 12:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, May 10, 2016 at 02:19:40PM +0300, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
> > Enable HW auto retuning when set SDHCI_CTRL_EXEC_TUNING and clear it
> > when clear SDHCI_CTRL_TUNED_CLK.
> > 
> > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> 
> I presume this patch should wait for patch 17, but nevertheless:
> 
> Acked-by: Adrian Hunter <adrian.hunter@intel.com>
> 

Actually the interesting thing here is patch 18 and 19 do not need
patch 17 since our IC guy told me IMX uSDHC auto-tuning will
not Retuning request for mode 3.

Thanks for the pre-ACK.

Regards
Dong Aisheng

> > ---
> >  drivers/mmc/host/sdhci-esdhc-imx.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> > index 9f9be3f..a582a83 100644
> > --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> > @@ -44,6 +44,7 @@
> >  #define  ESDHC_MIX_CTRL_AC23EN		(1 << 7)
> >  #define  ESDHC_MIX_CTRL_EXE_TUNE	(1 << 22)
> >  #define  ESDHC_MIX_CTRL_SMPCLK_SEL	(1 << 23)
> > +#define  ESDHC_MIX_CTRL_AUTO_TUNE_EN	(1 << 24)
> >  #define  ESDHC_MIX_CTRL_FBCLK_SEL	(1 << 25)
> >  #define  ESDHC_MIX_CTRL_HS400_EN	(1 << 26)
> >  /* Bits 3 and 6 are not SDHCI standard definitions */
> > @@ -484,11 +485,13 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
> >  			} else {
> >  				v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
> >  				m &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
> > +				m &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
> >  			}
> >  
> >  			if (val & SDHCI_CTRL_EXEC_TUNING) {
> >  				v |= ESDHC_MIX_CTRL_EXE_TUNE;
> >  				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
> > +				m |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
> >  				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
> >  				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT;
> >  				if (imx_data->boarddata.tuning_start_tap) {
> > 
> 

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

* Re: [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during no data transfer
  2016-05-17  5:58         ` Adrian Hunter
@ 2016-05-26 14:59           ` Ritesh Harjani
  -1 siblings, 0 replies; 170+ messages in thread
From: Ritesh Harjani @ 2016-05-26 14:59 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, chris, shawnguo,
	linux-arm-kernel, haibo.chen, Dong Aisheng

Hi Adrian,


On Tue, May 17, 2016 at 11:28 AM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 17/05/16 07:31, Ritesh Harjani wrote:
>> On Tue, May 10, 2016 at 12:21 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>> Current code will report the wrong data interrupt got when no
>>>> data operation in progress assumed by getting !host->data in
>>>> sdhci_data_irq().
>>>>
>>>> For a data command handling process, the driver will call
>>>> sdhci_finish_data() and clear host->data in case any data error,
>>>> then card finish_tasklet will do the rest controller reset work.
>>>>
>>>> Before the tasklet got run, however, controllers may report the
>>>> TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
>>>> than data CRC error and data end bit error interrupts for single
>>>> block transfer or the last block of multiblock transfer.
>>
>> What if the controller generates Transfer complete interrupt bit more slower
>> and the tasklet do get a chance to run. In that case even host->mrq
>> will become NULL.
>> Actually if that happens it's even more worse since the driver may
>> start issuing other commands to controller.
>>
>> Are we covering that case here? Do you think that this case is possible?
>
> After data error, the host driver resets the controller so there will be no
> more interrupts relating to that mrq.
Resetting will happen in sdhci_tasklet_finish.
My case was -
1. Controller raised a Data CRC error.
2. sdhci_irq made host->data = NULL in sdhci_finish_data and scheduled
the finish_tasklet.
3. while the tasklet is running and before resetting CMD and Data
machine, TC interrupt is raised by controller.
4. sdhci_irq will call for sdhci_data_irq.

But I get it that the second interrupt will end up printing the same
error since host->data will be found as NULL in sdhci_data_irq and
will return.
So below patch should do the job :)

>
> This patch is avoiding unnecessary warnings until that happens.
Yes.



>
>>
>>
>>>>
>>>> Controller usually detects and generates data CRC/end bit error
>>>> interrupts once one block on the bus is transferred completely.
>>>> For single block transfer, since there's only one bock to transfer,
>>>> the controller will report transfer complete interrupt as well,
>>>> but until the data in controller FIFO has been successfully
>>>> transferred to memory. The time gap of TC and CRC interrupt depends on
>>>> the system busy state at that point and memory bus access speed.
>>>>
>>>> So it is possible when TC interrupt generated, host->data is already
>>>> equal to NULL due to cleared by former CRC/Data End Bit error which
>>>> is reasonable.
>>>>
>>>> Thus we DO NOT report the weird data interrupt event for this case.
>>>>
>>>> Else we may easily see warning below during SD3.0 card manually tuning
>>>> process (calling mmc_send_tuning() which is a single block transfer)
>>>> mmc0: Got data interrupt 0x00000002 even though no data operation was in progress
>>>>
>>>> The detailed command log is as follows:
>>>> [ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
>>>> [ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
>>>> [ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
>>>> [ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
>>>> [ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
>>>> [ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
>>>> [ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
>>>> [ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
>>>> [ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
>>>> [ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
>>>> [ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
>>>> [ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
>>>> [ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
>>>> [ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
>>>> [ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
>>>> [ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
>>>> [ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
>>>> [ 1657.929965] sdhci: Host ctl2: 0x000000c8
>>>> [ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
>>>> [ 1657.929995] sdhci: ===========================================
>>>> [ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
>>>> [ 1657.930179] mmc0:     0 bytes transferred: -84
>>>>
>>>> It shows we first have a data CRC error interrupt then a data transfer
>>>> complete interrupt.
>>>> Then we got the !host->data case in sdhci_data_irq().
>>>>
>>>> CC: stable <stable@vger.kernel.org>
>>>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>>>> ---
>>>>  drivers/mmc/host/sdhci.c | 11 +++++++++++
>>>>  1 file changed, 11 insertions(+)
>>>>
>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>>> index 40e3551..2eb0e34 100644
>>>> --- a/drivers/mmc/host/sdhci.c
>>>> +++ b/drivers/mmc/host/sdhci.c
>>>> @@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
>>>>                       }
>>>>               }
>>>>
>>>> +             /*
>>>> +              * The "data complete" interrupt is possible to happen a bit
>>>> +              * later than CRC error and data end bit error interrupts
>>>> +              * separately for single block transfer or the last block of
>>>> +              * multiblock transfer. For this case, we DO NOT report the
>>>> +              * weird data interrupt event.
>>>> +              */
>>>> +             if ((intmask & SDHCI_INT_DATA_END) &&
>>>> +                 (host->mrq && host->mrq->data && host->mrq->data->error))
>>>> +                     return;
>>>
>>> This could be generalized a bit more i.e. what about:
>>>
>>>                 /*
>>>                  * After an error and before the the data circuit is reset in
>>>                  * sdhci_tasklet_finish, we could get more interrupts, but we
>>>                  * already have an error, so ignore them.
>>>                  */
>>>                 if (host->mrq && host->mrq->data && host->mrq->data->error)
>>>                         return;
>>>
>>>> +
>>>>               pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
>>>>                      mmc_hostname(host->mmc), (unsigned)intmask);
>>>>               sdhci_dumpregs(host);
>>>>
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>

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

* [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during no data transfer
@ 2016-05-26 14:59           ` Ritesh Harjani
  0 siblings, 0 replies; 170+ messages in thread
From: Ritesh Harjani @ 2016-05-26 14:59 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Adrian,


On Tue, May 17, 2016 at 11:28 AM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 17/05/16 07:31, Ritesh Harjani wrote:
>> On Tue, May 10, 2016 at 12:21 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>> Current code will report the wrong data interrupt got when no
>>>> data operation in progress assumed by getting !host->data in
>>>> sdhci_data_irq().
>>>>
>>>> For a data command handling process, the driver will call
>>>> sdhci_finish_data() and clear host->data in case any data error,
>>>> then card finish_tasklet will do the rest controller reset work.
>>>>
>>>> Before the tasklet got run, however, controllers may report the
>>>> TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
>>>> than data CRC error and data end bit error interrupts for single
>>>> block transfer or the last block of multiblock transfer.
>>
>> What if the controller generates Transfer complete interrupt bit more slower
>> and the tasklet do get a chance to run. In that case even host->mrq
>> will become NULL.
>> Actually if that happens it's even more worse since the driver may
>> start issuing other commands to controller.
>>
>> Are we covering that case here? Do you think that this case is possible?
>
> After data error, the host driver resets the controller so there will be no
> more interrupts relating to that mrq.
Resetting will happen in sdhci_tasklet_finish.
My case was -
1. Controller raised a Data CRC error.
2. sdhci_irq made host->data = NULL in sdhci_finish_data and scheduled
the finish_tasklet.
3. while the tasklet is running and before resetting CMD and Data
machine, TC interrupt is raised by controller.
4. sdhci_irq will call for sdhci_data_irq.

But I get it that the second interrupt will end up printing the same
error since host->data will be found as NULL in sdhci_data_irq and
will return.
So below patch should do the job :)

>
> This patch is avoiding unnecessary warnings until that happens.
Yes.



>
>>
>>
>>>>
>>>> Controller usually detects and generates data CRC/end bit error
>>>> interrupts once one block on the bus is transferred completely.
>>>> For single block transfer, since there's only one bock to transfer,
>>>> the controller will report transfer complete interrupt as well,
>>>> but until the data in controller FIFO has been successfully
>>>> transferred to memory. The time gap of TC and CRC interrupt depends on
>>>> the system busy state at that point and memory bus access speed.
>>>>
>>>> So it is possible when TC interrupt generated, host->data is already
>>>> equal to NULL due to cleared by former CRC/Data End Bit error which
>>>> is reasonable.
>>>>
>>>> Thus we DO NOT report the weird data interrupt event for this case.
>>>>
>>>> Else we may easily see warning below during SD3.0 card manually tuning
>>>> process (calling mmc_send_tuning() which is a single block transfer)
>>>> mmc0: Got data interrupt 0x00000002 even though no data operation was in progress
>>>>
>>>> The detailed command log is as follows:
>>>> [ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
>>>> [ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
>>>> [ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
>>>> [ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
>>>> [ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
>>>> [ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
>>>> [ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
>>>> [ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
>>>> [ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
>>>> [ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
>>>> [ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
>>>> [ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
>>>> [ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
>>>> [ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
>>>> [ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
>>>> [ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
>>>> [ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
>>>> [ 1657.929965] sdhci: Host ctl2: 0x000000c8
>>>> [ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
>>>> [ 1657.929995] sdhci: ===========================================
>>>> [ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
>>>> [ 1657.930179] mmc0:     0 bytes transferred: -84
>>>>
>>>> It shows we first have a data CRC error interrupt then a data transfer
>>>> complete interrupt.
>>>> Then we got the !host->data case in sdhci_data_irq().
>>>>
>>>> CC: stable <stable@vger.kernel.org>
>>>> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>>>> ---
>>>>  drivers/mmc/host/sdhci.c | 11 +++++++++++
>>>>  1 file changed, 11 insertions(+)
>>>>
>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>>> index 40e3551..2eb0e34 100644
>>>> --- a/drivers/mmc/host/sdhci.c
>>>> +++ b/drivers/mmc/host/sdhci.c
>>>> @@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
>>>>                       }
>>>>               }
>>>>
>>>> +             /*
>>>> +              * The "data complete" interrupt is possible to happen a bit
>>>> +              * later than CRC error and data end bit error interrupts
>>>> +              * separately for single block transfer or the last block of
>>>> +              * multiblock transfer. For this case, we DO NOT report the
>>>> +              * weird data interrupt event.
>>>> +              */
>>>> +             if ((intmask & SDHCI_INT_DATA_END) &&
>>>> +                 (host->mrq && host->mrq->data && host->mrq->data->error))
>>>> +                     return;
>>>
>>> This could be generalized a bit more i.e. what about:
>>>
>>>                 /*
>>>                  * After an error and before the the data circuit is reset in
>>>                  * sdhci_tasklet_finish, we could get more interrupts, but we
>>>                  * already have an error, so ignore them.
>>>                  */
>>>                 if (host->mrq && host->mrq->data && host->mrq->data->error)
>>>                         return;
>>>
>>>> +
>>>>               pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
>>>>                      mmc_hostname(host->mmc), (unsigned)intmask);
>>>>               sdhci_dumpregs(host);
>>>>
>>>
>>> --
>>> 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
>>
>

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

* Re: [PATCH 13/23] mmc: sdhci-esdhc-imx: restore watermark level setting after resume
  2016-05-10  9:30     ` Adrian Hunter
@ 2016-05-31  7:18       ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-05-31  7:18 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, ulf.hansson, chris, shawnguo,
	linux-arm-kernel, haibo.chen

On Tue, May 10, 2016 at 12:30:16PM +0300, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
> > Currently, we config the watermark_level register only in probe.
> > This will cause the mmc write operation timeout issue after system
> > resume back in LPSR mode. Because in LPSR mode, after system resume
> > back, the watermark_level register(0x44) changes to 0x08000880, which
> > set the write watermark level as 0, and set the read watermark level
> > as 128. This value is incorrect.
> > 
> > This patch restores the setting of watermark level register after
> > system resume back.
> 
> In sdhci_esdhc_imx_probe() the watermark setting is conditional on
> esdhc_is_usdhc(imx_data), but in the resume it is not.  Is that intended?
> If so, maybe explain that in the commit message.
> 

Good catch!
I think we'd probably better keep that condition check.
Will update it in V2.


> Might be worth pulling out the constant 0x10401040 and #defining it since it
> is used in more than one place too.
> 

Good point!
Will do it.

Regards
Dong Aisheng

> > 
> > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> > ---
> >  drivers/mmc/host/sdhci-esdhc-imx.c | 5 +++++
> >  1 file changed, 5 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> > index 6fef6bc..4c28fbb 100644
> > --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> > @@ -1261,6 +1261,11 @@ static int sdhci_esdhc_suspend(struct device *dev)
> >  
> >  static int sdhci_esdhc_resume(struct device *dev)
> >  {
> > +	struct sdhci_host *host = dev_get_drvdata(dev);
> > +
> > +	/* restore watermark setting in case it's lost in low power mode */
> > +	writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> > +
> >  	return sdhci_pltfm_resume(dev);
> >  }
> >  
> > 
> 

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

* [PATCH 13/23] mmc: sdhci-esdhc-imx: restore watermark level setting after resume
@ 2016-05-31  7:18       ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-05-31  7:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, May 10, 2016 at 12:30:16PM +0300, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
> > Currently, we config the watermark_level register only in probe.
> > This will cause the mmc write operation timeout issue after system
> > resume back in LPSR mode. Because in LPSR mode, after system resume
> > back, the watermark_level register(0x44) changes to 0x08000880, which
> > set the write watermark level as 0, and set the read watermark level
> > as 128. This value is incorrect.
> > 
> > This patch restores the setting of watermark level register after
> > system resume back.
> 
> In sdhci_esdhc_imx_probe() the watermark setting is conditional on
> esdhc_is_usdhc(imx_data), but in the resume it is not.  Is that intended?
> If so, maybe explain that in the commit message.
> 

Good catch!
I think we'd probably better keep that condition check.
Will update it in V2.


> Might be worth pulling out the constant 0x10401040 and #defining it since it
> is used in more than one place too.
> 

Good point!
Will do it.

Regards
Dong Aisheng

> > 
> > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> > ---
> >  drivers/mmc/host/sdhci-esdhc-imx.c | 5 +++++
> >  1 file changed, 5 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> > index 6fef6bc..4c28fbb 100644
> > --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> > @@ -1261,6 +1261,11 @@ static int sdhci_esdhc_suspend(struct device *dev)
> >  
> >  static int sdhci_esdhc_resume(struct device *dev)
> >  {
> > +	struct sdhci_host *host = dev_get_drvdata(dev);
> > +
> > +	/* restore watermark setting in case it's lost in low power mode */
> > +	writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> > +
> >  	return sdhci_pltfm_resume(dev);
> >  }
> >  
> > 
> 

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

* Re: [PATCH 10/23] mmc: core: disable auto retune during card detection process
  2016-05-10  6:55                 ` Adrian Hunter
@ 2016-05-31 10:18                   ` Dong Aisheng
  -1 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-05-31 10:18 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Dong Aisheng, linux-mmc, Ulf Hansson, Chris Ball, Shawn Guo,
	linux-arm-kernel, haibo.chen

On Tue, May 10, 2016 at 09:55:56AM +0300, Adrian Hunter wrote:
> On 29/04/16 10:42, Dong Aisheng wrote:
> > And IMX6DL ARD is even worser due to it's using common
> > mmc_send_tuning() function.
> > root@imx6qdlsolo:~# 
> > root@imx6qdlsolo:~# [  129.462564] sysrq: SysRq : Changing Loglevel
> > [  129.466902] sysrq: Loglevel set to 8
> > [  131.616078] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
> > [  131.625311] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 6
> > [  131.632133] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
> > [  131.642121] mmc0: starting CMD13 arg 59b40000 flags 00000195
> > [  131.648925] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x0 ESDHC_TUNE_CTRL_STATUS 0x0
> > [  131.657818] mmc0: starting CMD19 arg 00000000 flags 00000035
> > [  131.663518] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
> > [  131.670835] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
> 
> You should stop here because -123 is -ENOMEDIUM
> 

Hi Adrian,

This is the last issue before V2.
I just tried the way you proposed (see detailed log below).

A few questions if we decide to let tuning routine to handle
the card remove case:
1) we may have to fix it for all platforms tuning code.

Below is the example i did for IMX uSDHC and common SDHCI.
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -757,7 +757,11 @@ static void esdhc_post_tuning(struct sdhci_host *host)
 
 static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
 {
-       int min, max, avg, ret;
+       int min, max, avg, ret, present;
+
+       present = host->mmc->ops->get_cd(host->mmc);
+       if (!present)
+               return -ENOMEDIUM;
 
        /* find the mininum delay first which can pass tuning */
        min = ESDHC_TUNE_CTRL_MIN;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 0027b8707ebd..7b7545dd1a4b 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1767,6 +1767,11 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
        unsigned long flags;
        unsigned int tuning_count = 0;
        bool hs400_tuning;
+       int present;
+
+       present = mmc->ops->get_cd(mmc);
+       if (!present)
+               return -ENOMEDIUM;

And if we need fix all platforms, do you think we should
do it in MMC core mmc_execute_tuning()?

If yes, then we probably could move all the normal host CD check
before sending CMD in MMC core (__mmc_start_request()) as well?

2) MMC core will print out tuning error for card remove case
which is not before.
e.g
[   98.730597] mmc0: tuning execution failed: -123
We probably may need make it debug level since it's meaningless
for card removed case.

Detailed log below:
After the fix, card remove with calling mmc_send_tuning():
root@imx6qdlsolo:~# [   98.664049] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[   98.673280] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 6
[   98.680102] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[   98.689560] mmc0: starting CMD13 arg aaaa0000 flags 00000195
[   98.696336] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x0 ESDHC_TUNE_CTRL_STATUS 0x0
[   98.705407] mmc0: starting CMD19 arg 00000000 flags 00000035
[   98.711121] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[   98.718144] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[   98.725351] mmc0:     0 bytes transferred: 0
[   98.730597] mmc0: tuning execution failed: -123
[   98.735255] mmc0: req failed (CMD13): -123, retrying...
[   98.740921] mmc0: req failed (CMD13): -123, retrying...
[   98.746344] mmc0: req failed (CMD13): -123, retrying...
[   98.751909] mmc0: req done (CMD13): -123: 00000000 00000000 00000000 00000000
[   98.759206] mmc0: card remove detected
[   98.763514] mmc0: card aaaa removed
[   98.780475] mmc0: clock 0Hz busmode 2 powermode 0 cs 0 Vdd 0 width 1 timing 0
[   98.787730] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 0
[   99.028432] FAT-fs (mmcblk0p1): FAT read failed (blocknr 32)q


card remove with calling standard sdhci_execute_tuning():
root@imx6qdlsolo:~# [  210.555330] sysrq: SysRq : Changing Loglevel
[  210.559665] sysrq: Loglevel set to 8
[  212.244148] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[  212.253376] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 6
[  212.260199] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[  212.269637] mmc0: starting CMD13 arg aaaa0000 flags 00000195
[  212.275399] mmc0: tuning execution failed: -123
[  212.280601] mmc0: req failed (CMD13): -123, retrying...
[  212.286094] mmc0: req failed (CMD13): -123, retrying...
[  212.291763] mmc0: req failed (CMD13): -123, retrying...
[  212.297226] mmc0: req done (CMD13): -123: 00000000 00000000 00000000 00000000
[  212.304899] mmc0: card remove detected
[  212.308948] mmc0: card aaaa removed
[  212.318162] mmc0: clock 0Hz busmode 2 powermode 0 cs 0 Vdd 0 width 1 timing 0
[  212.325415] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 0
[  212.580621] FAT-fs (mmcblk0p1): FAT read failed (blocknr 32)

Regards
Dong Aisheng


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

* [PATCH 10/23] mmc: core: disable auto retune during card detection process
@ 2016-05-31 10:18                   ` Dong Aisheng
  0 siblings, 0 replies; 170+ messages in thread
From: Dong Aisheng @ 2016-05-31 10:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, May 10, 2016 at 09:55:56AM +0300, Adrian Hunter wrote:
> On 29/04/16 10:42, Dong Aisheng wrote:
> > And IMX6DL ARD is even worser due to it's using common
> > mmc_send_tuning() function.
> > root at imx6qdlsolo:~# 
> > root at imx6qdlsolo:~# [  129.462564] sysrq: SysRq : Changing Loglevel
> > [  129.466902] sysrq: Loglevel set to 8
> > [  131.616078] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
> > [  131.625311] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 6
> > [  131.632133] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
> > [  131.642121] mmc0: starting CMD13 arg 59b40000 flags 00000195
> > [  131.648925] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x0 ESDHC_TUNE_CTRL_STATUS 0x0
> > [  131.657818] mmc0: starting CMD19 arg 00000000 flags 00000035
> > [  131.663518] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
> > [  131.670835] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
> 
> You should stop here because -123 is -ENOMEDIUM
> 

Hi Adrian,

This is the last issue before V2.
I just tried the way you proposed (see detailed log below).

A few questions if we decide to let tuning routine to handle
the card remove case:
1) we may have to fix it for all platforms tuning code.

Below is the example i did for IMX uSDHC and common SDHCI.
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -757,7 +757,11 @@ static void esdhc_post_tuning(struct sdhci_host *host)
 
 static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
 {
-       int min, max, avg, ret;
+       int min, max, avg, ret, present;
+
+       present = host->mmc->ops->get_cd(host->mmc);
+       if (!present)
+               return -ENOMEDIUM;
 
        /* find the mininum delay first which can pass tuning */
        min = ESDHC_TUNE_CTRL_MIN;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 0027b8707ebd..7b7545dd1a4b 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1767,6 +1767,11 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
        unsigned long flags;
        unsigned int tuning_count = 0;
        bool hs400_tuning;
+       int present;
+
+       present = mmc->ops->get_cd(mmc);
+       if (!present)
+               return -ENOMEDIUM;

And if we need fix all platforms, do you think we should
do it in MMC core mmc_execute_tuning()?

If yes, then we probably could move all the normal host CD check
before sending CMD in MMC core (__mmc_start_request()) as well?

2) MMC core will print out tuning error for card remove case
which is not before.
e.g
[   98.730597] mmc0: tuning execution failed: -123
We probably may need make it debug level since it's meaningless
for card removed case.

Detailed log below:
After the fix, card remove with calling mmc_send_tuning():
root at imx6qdlsolo:~# [   98.664049] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[   98.673280] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 6
[   98.680102] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[   98.689560] mmc0: starting CMD13 arg aaaa0000 flags 00000195
[   98.696336] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x0 ESDHC_TUNE_CTRL_STATUS 0x0
[   98.705407] mmc0: starting CMD19 arg 00000000 flags 00000035
[   98.711121] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[   98.718144] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[   98.725351] mmc0:     0 bytes transferred: 0
[   98.730597] mmc0: tuning execution failed: -123
[   98.735255] mmc0: req failed (CMD13): -123, retrying...
[   98.740921] mmc0: req failed (CMD13): -123, retrying...
[   98.746344] mmc0: req failed (CMD13): -123, retrying...
[   98.751909] mmc0: req done (CMD13): -123: 00000000 00000000 00000000 00000000
[   98.759206] mmc0: card remove detected
[   98.763514] mmc0: card aaaa removed
[   98.780475] mmc0: clock 0Hz busmode 2 powermode 0 cs 0 Vdd 0 width 1 timing 0
[   98.787730] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 0
[   99.028432] FAT-fs (mmcblk0p1): FAT read failed (blocknr 32)q


card remove with calling standard sdhci_execute_tuning():
root at imx6qdlsolo:~# [  210.555330] sysrq: SysRq : Changing Loglevel
[  210.559665] sysrq: Loglevel set to 8
[  212.244148] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[  212.253376] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 6
[  212.260199] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[  212.269637] mmc0: starting CMD13 arg aaaa0000 flags 00000195
[  212.275399] mmc0: tuning execution failed: -123
[  212.280601] mmc0: req failed (CMD13): -123, retrying...
[  212.286094] mmc0: req failed (CMD13): -123, retrying...
[  212.291763] mmc0: req failed (CMD13): -123, retrying...
[  212.297226] mmc0: req done (CMD13): -123: 00000000 00000000 00000000 00000000
[  212.304899] mmc0: card remove detected
[  212.308948] mmc0: card aaaa removed
[  212.318162] mmc0: clock 0Hz busmode 2 powermode 0 cs 0 Vdd 0 width 1 timing 0
[  212.325415] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 0
[  212.580621] FAT-fs (mmcblk0p1): FAT read failed (blocknr 32)

Regards
Dong Aisheng

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

end of thread, other threads:[~2016-05-31 10:23 UTC | newest]

Thread overview: 170+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-15 17:29 [PATCH 00/23] a few sdhci/imx clean up and fix patches Dong Aisheng
2016-04-15 17:29 ` Dong Aisheng
2016-04-15 17:29 ` [PATCH 01/23] mmc: sdhci: removed unneeded function wrappers Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-04-22 10:27   ` Adrian Hunter
2016-04-22 10:27     ` Adrian Hunter
2016-05-10  6:32     ` Adrian Hunter
2016-05-10  6:32       ` Adrian Hunter
2016-05-10  9:46   ` Ulf Hansson
2016-05-10  9:46     ` Ulf Hansson
2016-04-15 17:29 ` [PATCH 02/23] mmc: sdhci: move sdhci_get_cd() forward to avoid declaration Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-04-22 10:27   ` Adrian Hunter
2016-04-22 10:27     ` Adrian Hunter
2016-04-24  9:17     ` Dong Aisheng
2016-04-24  9:17       ` Dong Aisheng
2016-04-27 20:26       ` Adrian Hunter
2016-04-27 20:26         ` Adrian Hunter
2016-04-15 17:29 ` [PATCH 03/23] mmc: core: fix a comment typo Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-04-22 10:28   ` Adrian Hunter
2016-04-22 10:28     ` Adrian Hunter
2016-04-15 17:29 ` [PATCH 04/23] mmc: sdhci: re-factor sdhci_start_signal_voltage() Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-04-22 11:43   ` Adrian Hunter
2016-04-22 11:43     ` Adrian Hunter
2016-04-24  9:14     ` Dong Aisheng
2016-04-24  9:14       ` Dong Aisheng
2016-04-27 20:26       ` Adrian Hunter
2016-04-27 20:26         ` Adrian Hunter
2016-04-28  3:09         ` Dong Aisheng
2016-04-28  3:09           ` Dong Aisheng
2016-04-28  6:39           ` Adrian Hunter
2016-04-28  6:39             ` Adrian Hunter
2016-04-28  7:15             ` Jaehoon Chung
2016-04-28  7:15               ` Jaehoon Chung
2016-04-28  7:44               ` Adrian Hunter
2016-04-28  7:44                 ` Adrian Hunter
2016-04-28  8:30                 ` Jaehoon Chung
2016-04-28  8:30                   ` Jaehoon Chung
2016-04-28 14:09                   ` Dong Aisheng
2016-04-28 14:09                     ` Dong Aisheng
2016-04-28 23:06                     ` Jaehoon Chung
2016-04-28 23:06                       ` Jaehoon Chung
2016-04-28 13:14             ` Dong Aisheng
2016-04-28 13:14               ` Dong Aisheng
2016-04-28 13:36               ` Adrian Hunter
2016-04-28 13:36                 ` Adrian Hunter
2016-04-28 14:28                 ` Dong Aisheng
2016-04-28 14:28                   ` Dong Aisheng
2016-04-29  7:32                   ` Adrian Hunter
2016-04-29  7:32                     ` Adrian Hunter
2016-04-29  7:57                     ` Dong Aisheng
2016-04-29  7:57                       ` Dong Aisheng
2016-04-15 17:29 ` [PATCH 05/23] mmc: core: mmc_regulator_set_vqmmc not return error if vqmmc/vmmc not exist Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-04-15 17:29 ` [PATCH 06/23] mmc: sdhci: using common mmc_regulator_set_vqmmc() Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-04-22 11:48   ` Adrian Hunter
2016-04-22 11:48     ` Adrian Hunter
2016-04-24  9:25     ` Dong Aisheng
2016-04-24  9:25       ` Dong Aisheng
2016-04-15 17:29 ` [PATCH 07/23] mmc: sdhci: check SDHCI_QUIRK2_NO_1_8_V when do voltage switch Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-04-22 12:30   ` Adrian Hunter
2016-04-22 12:30     ` Adrian Hunter
2016-04-24  9:56     ` Dong Aisheng
2016-04-24  9:56       ` Dong Aisheng
2016-04-27 20:27       ` Adrian Hunter
2016-04-27 20:27         ` Adrian Hunter
2016-04-28 13:24         ` Dong Aisheng
2016-04-28 13:24           ` Dong Aisheng
2016-04-15 17:29 ` [PATCH 08/23] mmc: sdhci: rename quirk SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-04-22 12:33   ` Adrian Hunter
2016-04-22 12:33     ` Adrian Hunter
2016-04-24 10:00     ` Dong Aisheng
2016-04-24 10:00       ` Dong Aisheng
2016-04-15 17:29 ` [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during no data transfer Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-05-10  6:51   ` Adrian Hunter
2016-05-10  6:51     ` Adrian Hunter
2016-05-17  4:31     ` Ritesh Harjani
2016-05-17  4:31       ` Ritesh Harjani
2016-05-17  5:58       ` Adrian Hunter
2016-05-17  5:58         ` Adrian Hunter
2016-05-26 14:59         ` Ritesh Harjani
2016-05-26 14:59           ` Ritesh Harjani
2016-05-26 11:41     ` Dong Aisheng
2016-05-26 11:41       ` Dong Aisheng
2016-05-26 11:59       ` Adrian Hunter
2016-05-26 11:59         ` Adrian Hunter
2016-04-15 17:29 ` [PATCH 10/23] mmc: core: disable auto retune during card detection process Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-04-22 12:48   ` Adrian Hunter
2016-04-22 12:48     ` Adrian Hunter
2016-04-24 10:47     ` Dong Aisheng
2016-04-24 10:47       ` Dong Aisheng
2016-04-28  7:04       ` Adrian Hunter
2016-04-28  7:04         ` Adrian Hunter
2016-04-28 13:22         ` Dong Aisheng
2016-04-28 13:22           ` Dong Aisheng
2016-04-29  6:54           ` Adrian Hunter
2016-04-29  6:54             ` Adrian Hunter
2016-04-29  7:42             ` Dong Aisheng
2016-04-29  7:42               ` Dong Aisheng
2016-05-10  6:55               ` Adrian Hunter
2016-05-10  6:55                 ` Adrian Hunter
2016-05-31 10:18                 ` Dong Aisheng
2016-05-31 10:18                   ` Dong Aisheng
2016-04-15 17:29 ` [PATCH 11/23] mmc: sdhci-esdhci-imx: remove SDHCI_QUIRK_BROKEN_TIMEOUT_VAL Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-05-10  9:30   ` Adrian Hunter
2016-05-10  9:30     ` Adrian Hunter
2016-04-15 17:29 ` [PATCH 12/23] mmc: sdhci-esdhc-imx: add esdhc specific suspend resume callback Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-05-10  9:35   ` Adrian Hunter
2016-05-10  9:35     ` Adrian Hunter
2016-04-15 17:29 ` [PATCH 13/23] mmc: sdhci-esdhc-imx: restore watermark level setting after resume Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-05-10  9:30   ` Adrian Hunter
2016-05-10  9:30     ` Adrian Hunter
2016-05-31  7:18     ` Dong Aisheng
2016-05-31  7:18       ` Dong Aisheng
2016-04-15 17:29 ` [PATCH 14/23] mmc: sdhci-esdhci-imx: disable DLL delay line settings explicitly Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-05-10 11:02   ` Adrian Hunter
2016-05-10 11:02     ` Adrian Hunter
2016-04-15 17:29 ` [PATCH 15/23] mmc: sdhci-esdhc-imx: support setting tuning start point Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-05-10 11:17   ` Adrian Hunter
2016-05-10 11:17     ` Adrian Hunter
2016-04-15 17:29 ` [PATCH 16/23] doc: dt: fsl-imx-esdhc: add set tuning start point binding Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-04-15 17:29 ` [PATCH 17/23] mmc: sdhci: add standard hw auto retuning support Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-05-10  8:35   ` Adrian Hunter
2016-05-10  8:35     ` Adrian Hunter
2016-05-26 12:11     ` Dong Aisheng
2016-05-26 12:11       ` Dong Aisheng
2016-04-15 17:29 ` [PATCH 18/23] mmc: sdhci-esdhc-imx: enable hw auto retuning for STD_TUNING Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-05-10 11:19   ` Adrian Hunter
2016-05-10 11:19     ` Adrian Hunter
2016-05-26 12:21     ` Dong Aisheng
2016-05-26 12:21       ` Dong Aisheng
2016-04-15 17:29 ` [PATCH 19/23] mmc: sdhci-esdhc-imx: enable hw auto retuning for MAN_TUNING Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-05-10 11:24   ` Adrian Hunter
2016-05-10 11:24     ` Adrian Hunter
2016-04-15 17:29 ` [PATCH 20/23] mmc: sdhci-esdhc-imx: fix strobe DLL lock wrong clock issue Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-05-10 12:03   ` Adrian Hunter
2016-05-10 12:03     ` Adrian Hunter
2016-05-26 11:47     ` Dong Aisheng
2016-05-26 11:47       ` Dong Aisheng
2016-04-15 17:29 ` [PATCH 21/23] mmc: sdhci-esdhc-imx: factor out hw related intialization into function Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-05-10 12:15   ` Adrian Hunter
2016-05-10 12:15     ` Adrian Hunter
2016-05-26 11:45     ` Dong Aisheng
2016-05-26 11:45       ` Dong Aisheng
2016-04-15 17:29 ` [PATCH 22/23] mmc: sdhci-esdhc-imx: move tuning static configuration into hwinit function Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-05-10 13:07   ` Adrian Hunter
2016-05-10 13:07     ` Adrian Hunter
2016-04-15 17:29 ` [PATCH 23/23] mmc: sdhci-esdhc-imx: clear tuning bits during hwinit Dong Aisheng
2016-04-15 17:29   ` Dong Aisheng
2016-05-10 13:10   ` Adrian Hunter
2016-05-10 13:10     ` Adrian Hunter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.