All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] mmc: core: hw_reset changes
@ 2014-10-24 12:46 Johan Rudholm
  2014-10-24 12:46 ` [PATCH 1/4] mmc: core: use mmc_send_status to check hw_reset Johan Rudholm
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Johan Rudholm @ 2014-10-24 12:46 UTC (permalink / raw)
  To: linux-mmc, Chris Ball, Ulf Hansson
  Cc: Adrian Hunter, Guennadi Liakhovetski, David Lanzendörfer,
	Jesper Nilsson, Johan Rudholm

Make the mmc_hw_reset routines more generic, so we can easily add a
power cycle of SD cards as well. Also simplify the (e)MMC specific
parts of the reset code.

As I don't have an eMMC device myself, much less one with a reset line,
I'd be very happy if someone could help me test the code with an eMMC?

Johan Rudholm (4):
  mmc: core: use mmc_send_status to check hw_reset
  mmc: core: use mmc_power_up in hw_reset
  mmc: core: make hw_reset generic
  mmc: sd: add power_reset callback

 drivers/mmc/card/block.c    |    2 +-
 drivers/mmc/card/mmc_test.c |    5 +--
 drivers/mmc/core/core.c     |   73 ++++++++-----------------------------------
 drivers/mmc/core/core.h     |    4 ++
 drivers/mmc/core/mmc.c      |   40 +++++++++++++++++++++++
 drivers/mmc/core/sd.c       |   16 +++++++++
 include/linux/mmc/core.h    |    5 +--
 7 files changed, 77 insertions(+), 68 deletions(-)

-- 
1.7.2.5


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

* [PATCH 1/4] mmc: core: use mmc_send_status to check hw_reset
  2014-10-24 12:46 [PATCH 0/4] mmc: core: hw_reset changes Johan Rudholm
@ 2014-10-24 12:46 ` Johan Rudholm
  2014-10-24 12:46 ` [PATCH 2/4] mmc: core: use mmc_power_up in hw_reset Johan Rudholm
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Johan Rudholm @ 2014-10-24 12:46 UTC (permalink / raw)
  To: linux-mmc, Chris Ball, Ulf Hansson
  Cc: Adrian Hunter, Guennadi Liakhovetski, David Lanzendörfer,
	Jesper Nilsson, Johan Rudholm

Signed-off-by: Johan Rudholm <johanru@axis.com>
---
 drivers/mmc/core/core.c |   10 ++--------
 1 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 7dc0c85..5d215ee 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2265,15 +2265,9 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)
 
 	/* If the reset has happened, then a status command will fail */
 	if (check) {
-		struct mmc_command cmd = {0};
-		int err;
+		u32 status;
 
-		cmd.opcode = MMC_SEND_STATUS;
-		if (!mmc_host_is_spi(card->host))
-			cmd.arg = card->rca << 16;
-		cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
-		err = mmc_wait_for_cmd(card->host, &cmd, 0);
-		if (!err) {
+		if (!mmc_send_status(card, &status)) {
 			mmc_host_clk_release(host);
 			return -ENOSYS;
 		}
-- 
1.7.2.5


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

* [PATCH 2/4] mmc: core: use mmc_power_up in hw_reset
  2014-10-24 12:46 [PATCH 0/4] mmc: core: hw_reset changes Johan Rudholm
  2014-10-24 12:46 ` [PATCH 1/4] mmc: core: use mmc_send_status to check hw_reset Johan Rudholm
@ 2014-10-24 12:46 ` Johan Rudholm
  2014-11-03  9:21   ` Adrian Hunter
  2014-10-24 12:46 ` [PATCH 3/4] mmc: core: make hw_reset generic Johan Rudholm
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Johan Rudholm @ 2014-10-24 12:46 UTC (permalink / raw)
  To: linux-mmc, Chris Ball, Ulf Hansson
  Cc: Adrian Hunter, Guennadi Liakhovetski, David Lanzendörfer,
	Jesper Nilsson, Johan Rudholm

The steps performed in mmc_do_hw_reset for eMMC:s after the hardware
reset are very similar to those performed by mmc_power_up, so do a call
to this function instead.

Signed-off-by: Johan Rudholm <johanru@axis.com>
---
 drivers/mmc/core/core.c |   11 +----------
 1 files changed, 1 insertions(+), 10 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 5d215ee..d56e222 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2273,16 +2273,7 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)
 		}
 	}
 
-	if (mmc_host_is_spi(host)) {
-		host->ios.chip_select = MMC_CS_HIGH;
-		host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
-	} else {
-		host->ios.chip_select = MMC_CS_DONTCARE;
-		host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-	}
-	host->ios.bus_width = MMC_BUS_WIDTH_1;
-	host->ios.timing = MMC_TIMING_LEGACY;
-	mmc_set_ios(host);
+	mmc_power_up(host, card->ocr);
 
 	mmc_host_clk_release(host);
 
-- 
1.7.2.5


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

* [PATCH 3/4] mmc: core: make hw_reset generic
  2014-10-24 12:46 [PATCH 0/4] mmc: core: hw_reset changes Johan Rudholm
  2014-10-24 12:46 ` [PATCH 1/4] mmc: core: use mmc_send_status to check hw_reset Johan Rudholm
  2014-10-24 12:46 ` [PATCH 2/4] mmc: core: use mmc_power_up in hw_reset Johan Rudholm
@ 2014-10-24 12:46 ` Johan Rudholm
  2014-11-03  9:20   ` Adrian Hunter
  2014-10-24 12:46 ` [PATCH 4/4] mmc: sd: add power_reset callback Johan Rudholm
  2014-11-03  8:46 ` [PATCH 0/4] mmc: core: hw_reset changes Johan Rudholm
  4 siblings, 1 reply; 12+ messages in thread
From: Johan Rudholm @ 2014-10-24 12:46 UTC (permalink / raw)
  To: linux-mmc, Chris Ball, Ulf Hansson
  Cc: Adrian Hunter, Guennadi Liakhovetski, David Lanzendörfer,
	Jesper Nilsson, Johan Rudholm

Move the (e)MMC specific hw_reset code from core.c into mmc.c and call
it from the new bus_ops member power_reset. This also lets us add code
for reseting SD cards as well.

Rename the mmc_hw_reset* functions into mmc_reset*, since what they
now actually do depends on the device type (and it may be something else
than doing a hw_reset).

Signed-off-by: Johan Rudholm <johanru@axis.com>
---
 drivers/mmc/card/block.c    |    2 +-
 drivers/mmc/card/mmc_test.c |    5 +---
 drivers/mmc/core/core.c     |   58 +++++++++---------------------------------
 drivers/mmc/core/core.h     |    4 +++
 drivers/mmc/core/mmc.c      |   40 +++++++++++++++++++++++++++++
 include/linux/mmc/core.h    |    5 +--
 6 files changed, 61 insertions(+), 53 deletions(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 452782b..8c4fa46 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1001,7 +1001,7 @@ static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
 		return -EEXIST;
 
 	md->reset_done |= type;
-	err = mmc_hw_reset(host);
+	err = mmc_reset(host);
 	/* Ensure we switch back to the correct partition */
 	if (err != -EOPNOTSUPP) {
 		struct mmc_blk_data *main_md = mmc_get_drvdata(host->card);
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index 0c0fc52..599c683 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -2339,7 +2339,7 @@ static int mmc_test_hw_reset(struct mmc_test_card *test)
 	struct mmc_host *host = card->host;
 	int err;
 
-	err = mmc_hw_reset_check(host);
+	err = mmc_reset_check(host);
 	if (!err)
 		return RESULT_OK;
 
@@ -2349,9 +2349,6 @@ static int mmc_test_hw_reset(struct mmc_test_card *test)
 	if (err != -EOPNOTSUPP)
 		return err;
 
-	if (!mmc_can_reset(card))
-		return RESULT_UNSUP_CARD;
-
 	return RESULT_UNSUP_HOST;
 }
 
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index d56e222..486cda8 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2232,65 +2232,33 @@ static void mmc_hw_reset_for_init(struct mmc_host *host)
 	mmc_host_clk_release(host);
 }
 
-int mmc_can_reset(struct mmc_card *card)
+/* Reset card in a bus-specific way */
+static int mmc_do_reset(struct mmc_host *host, int check)
 {
-	u8 rst_n_function;
-
-	if (!mmc_card_mmc(card))
-		return 0;
-	rst_n_function = card->ext_csd.rst_n_function;
-	if ((rst_n_function & EXT_CSD_RST_N_EN_MASK) != EXT_CSD_RST_N_ENABLED)
-		return 0;
-	return 1;
-}
-EXPORT_SYMBOL(mmc_can_reset);
-
-static int mmc_do_hw_reset(struct mmc_host *host, int check)
-{
-	struct mmc_card *card = host->card;
-
-	if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
-		return -EOPNOTSUPP;
-
-	if (!card)
-		return -EINVAL;
+	int ret;
 
-	if (!mmc_can_reset(card))
+	if (!host->bus_ops || !host->bus_ops->power_reset ||
+			host->bus_ops->power_reset(host, MMC_POWER_RESET_TEST))
 		return -EOPNOTSUPP;
 
-	mmc_host_clk_hold(host);
-	mmc_set_clock(host, host->f_init);
-
-	host->ops->hw_reset(host);
-
-	/* If the reset has happened, then a status command will fail */
-	if (check) {
-		u32 status;
-
-		if (!mmc_send_status(card, &status)) {
-			mmc_host_clk_release(host);
-			return -ENOSYS;
-		}
-	}
-
-	mmc_power_up(host, card->ocr);
+	ret = host->bus_ops->power_reset(host, check);
 
-	mmc_host_clk_release(host);
+	pr_warning("%s: tried to reset card (%d)\n", mmc_hostname(host), ret);
 
 	return host->bus_ops->power_restore(host);
 }
 
-int mmc_hw_reset(struct mmc_host *host)
+int mmc_reset(struct mmc_host *host)
 {
-	return mmc_do_hw_reset(host, 0);
+	return mmc_do_reset(host, MMC_POWER_RESET_RESET);
 }
-EXPORT_SYMBOL(mmc_hw_reset);
+EXPORT_SYMBOL(mmc_reset);
 
-int mmc_hw_reset_check(struct mmc_host *host)
+int mmc_reset_check(struct mmc_host *host)
 {
-	return mmc_do_hw_reset(host, 1);
+	return mmc_do_reset(host, MMC_POWER_RESET_CHECK);
 }
-EXPORT_SYMBOL(mmc_hw_reset_check);
+EXPORT_SYMBOL(mmc_reset_check);
 
 static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
 {
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 443a584..6a0420b 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -25,6 +25,10 @@ struct mmc_bus_ops {
 	int (*runtime_resume)(struct mmc_host *);
 	int (*power_save)(struct mmc_host *);
 	int (*power_restore)(struct mmc_host *);
+	int (*power_reset)(struct mmc_host *, int);
+#define MMC_POWER_RESET_RESET	0
+#define MMC_POWER_RESET_TEST	1
+#define MMC_POWER_RESET_CHECK	2
 	int (*alive)(struct mmc_host *);
 	int (*shutdown)(struct mmc_host *);
 };
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 793c6f7..ac5192c 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1762,6 +1762,45 @@ static int mmc_runtime_resume(struct mmc_host *host)
 	return 0;
 }
 
+static int mmc_power_reset(struct mmc_host *host, int test)
+{
+	struct mmc_card *card = host->card;
+	u8 rst_n_function;
+
+	if (!card)
+		return -EINVAL;
+
+	if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
+		return -EOPNOTSUPP;
+
+	rst_n_function = card->ext_csd.rst_n_function;
+	if ((rst_n_function & EXT_CSD_RST_N_EN_MASK) != EXT_CSD_RST_N_ENABLED)
+		return -EOPNOTSUPP;
+
+	if (test == MMC_POWER_RESET_TEST)
+		return 0;
+
+	mmc_host_clk_hold(host);
+	mmc_set_clock(host, host->f_init);
+
+	host->ops->hw_reset(host);
+
+	if (test == MMC_POWER_RESET_CHECK) {
+		u32 status;
+
+		if (!mmc_send_status(card, &status)) {
+			mmc_host_clk_release(host);
+			return -ENOSYS;
+		}
+	}
+
+	mmc_power_up(host, card->ocr);
+
+	mmc_host_clk_release(host);
+
+	return 0;
+}
+
 static int mmc_power_restore(struct mmc_host *host)
 {
 	int ret;
@@ -1781,6 +1820,7 @@ static const struct mmc_bus_ops mmc_ops = {
 	.runtime_suspend = mmc_runtime_suspend,
 	.runtime_resume = mmc_runtime_resume,
 	.power_restore = mmc_power_restore,
+	.power_reset = mmc_power_reset,
 	.alive = mmc_alive,
 	.shutdown = mmc_shutdown,
 };
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index f206e29..4f7a76e 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -180,9 +180,8 @@ extern unsigned int mmc_calc_max_discard(struct mmc_card *card);
 extern int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen);
 extern int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount,
 			      bool is_rel_write);
-extern int mmc_hw_reset(struct mmc_host *host);
-extern int mmc_hw_reset_check(struct mmc_host *host);
-extern int mmc_can_reset(struct mmc_card *card);
+extern int mmc_reset(struct mmc_host *host);
+extern int mmc_reset_check(struct mmc_host *host);
 
 extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *);
 extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int);
-- 
1.7.2.5


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

* [PATCH 4/4] mmc: sd: add power_reset callback
  2014-10-24 12:46 [PATCH 0/4] mmc: core: hw_reset changes Johan Rudholm
                   ` (2 preceding siblings ...)
  2014-10-24 12:46 ` [PATCH 3/4] mmc: core: make hw_reset generic Johan Rudholm
@ 2014-10-24 12:46 ` Johan Rudholm
  2014-11-03  8:46 ` [PATCH 0/4] mmc: core: hw_reset changes Johan Rudholm
  4 siblings, 0 replies; 12+ messages in thread
From: Johan Rudholm @ 2014-10-24 12:46 UTC (permalink / raw)
  To: linux-mmc, Chris Ball, Ulf Hansson
  Cc: Adrian Hunter, Guennadi Liakhovetski, David Lanzendörfer,
	Jesper Nilsson, Johan Rudholm

Enable power cycle and re-initialization of SD cards via the mmc_reset
function. Power cycling a buggy SD card sometimes helps it get back on
track.

Signed-off-by: Johan Rudholm <johanru@axis.com>
---
 drivers/mmc/core/sd.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 0c44510..9ad46b2 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1177,6 +1177,21 @@ static int mmc_sd_runtime_resume(struct mmc_host *host)
 	return 0;
 }
 
+static int mmc_sd_power_reset(struct mmc_host *host, int test)
+{
+	struct mmc_card *card = host->card;
+
+	if (!card)
+		return -EINVAL;
+
+	if (test == MMC_POWER_RESET_TEST)
+		return 0;
+
+	mmc_power_cycle(host, card->ocr);
+
+	return 0;
+}
+
 static int mmc_sd_power_restore(struct mmc_host *host)
 {
 	int ret;
@@ -1196,6 +1211,7 @@ static const struct mmc_bus_ops mmc_sd_ops = {
 	.suspend = mmc_sd_suspend,
 	.resume = mmc_sd_resume,
 	.power_restore = mmc_sd_power_restore,
+	.power_reset = mmc_sd_power_reset,
 	.alive = mmc_sd_alive,
 	.shutdown = mmc_sd_suspend,
 };
-- 
1.7.2.5


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

* Re: [PATCH 0/4] mmc: core: hw_reset changes
  2014-10-24 12:46 [PATCH 0/4] mmc: core: hw_reset changes Johan Rudholm
                   ` (3 preceding siblings ...)
  2014-10-24 12:46 ` [PATCH 4/4] mmc: sd: add power_reset callback Johan Rudholm
@ 2014-11-03  8:46 ` Johan Rudholm
  4 siblings, 0 replies; 12+ messages in thread
From: Johan Rudholm @ 2014-11-03  8:46 UTC (permalink / raw)
  To: Johan Rudholm
  Cc: linux-mmc, Chris Ball, Ulf Hansson, Adrian Hunter,
	Guennadi Liakhovetski, David Lanzendörfer, Jesper Nilsson

Hi all,

any comments on this patch set?

//Johan

2014-10-24 14:46 GMT+02:00 Johan Rudholm <johan.rudholm@axis.com>:
> Make the mmc_hw_reset routines more generic, so we can easily add a
> power cycle of SD cards as well. Also simplify the (e)MMC specific
> parts of the reset code.
>
> As I don't have an eMMC device myself, much less one with a reset line,
> I'd be very happy if someone could help me test the code with an eMMC?
>
> Johan Rudholm (4):
>   mmc: core: use mmc_send_status to check hw_reset
>   mmc: core: use mmc_power_up in hw_reset
>   mmc: core: make hw_reset generic
>   mmc: sd: add power_reset callback
>
>  drivers/mmc/card/block.c    |    2 +-
>  drivers/mmc/card/mmc_test.c |    5 +--
>  drivers/mmc/core/core.c     |   73 ++++++++-----------------------------------
>  drivers/mmc/core/core.h     |    4 ++
>  drivers/mmc/core/mmc.c      |   40 +++++++++++++++++++++++
>  drivers/mmc/core/sd.c       |   16 +++++++++
>  include/linux/mmc/core.h    |    5 +--
>  7 files changed, 77 insertions(+), 68 deletions(-)
>
> --
> 1.7.2.5
>
> --
> 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] 12+ messages in thread

* Re: [PATCH 3/4] mmc: core: make hw_reset generic
  2014-10-24 12:46 ` [PATCH 3/4] mmc: core: make hw_reset generic Johan Rudholm
@ 2014-11-03  9:20   ` Adrian Hunter
  2014-11-03 10:19     ` Johan Rudholm
  0 siblings, 1 reply; 12+ messages in thread
From: Adrian Hunter @ 2014-11-03  9:20 UTC (permalink / raw)
  To: Johan Rudholm, linux-mmc, Chris Ball, Ulf Hansson
  Cc: Guennadi Liakhovetski, David Lanzendörfer, Jesper Nilsson,
	Johan Rudholm

On 24/10/14 15:46, Johan Rudholm wrote:
> Move the (e)MMC specific hw_reset code from core.c into mmc.c and call
> it from the new bus_ops member power_reset. This also lets us add code

power_reset is not a good name because it does not necessarily have
anything to do with power.  I am not sure why you don't stick with
hw_reset.

> for reseting SD cards as well.
> 
> Rename the mmc_hw_reset* functions into mmc_reset*, since what they
> now actually do depends on the device type (and it may be something else
> than doing a hw_reset).

I don't follow your reasoning about the rename.  Cycling the power is
a kind of hardware reset isn't it.

> 
> Signed-off-by: Johan Rudholm <johanru@axis.com>
> ---
>  drivers/mmc/card/block.c    |    2 +-
>  drivers/mmc/card/mmc_test.c |    5 +---
>  drivers/mmc/core/core.c     |   58 +++++++++---------------------------------
>  drivers/mmc/core/core.h     |    4 +++
>  drivers/mmc/core/mmc.c      |   40 +++++++++++++++++++++++++++++
>  include/linux/mmc/core.h    |    5 +--
>  6 files changed, 61 insertions(+), 53 deletions(-)
> 
> diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
> index 452782b..8c4fa46 100644
> --- a/drivers/mmc/card/block.c
> +++ b/drivers/mmc/card/block.c
> @@ -1001,7 +1001,7 @@ static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
>  		return -EEXIST;
>  
>  	md->reset_done |= type;
> -	err = mmc_hw_reset(host);
> +	err = mmc_reset(host);
>  	/* Ensure we switch back to the correct partition */
>  	if (err != -EOPNOTSUPP) {
>  		struct mmc_blk_data *main_md = mmc_get_drvdata(host->card);
> diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
> index 0c0fc52..599c683 100644
> --- a/drivers/mmc/card/mmc_test.c
> +++ b/drivers/mmc/card/mmc_test.c
> @@ -2339,7 +2339,7 @@ static int mmc_test_hw_reset(struct mmc_test_card *test)
>  	struct mmc_host *host = card->host;
>  	int err;
>  
> -	err = mmc_hw_reset_check(host);
> +	err = mmc_reset_check(host);
>  	if (!err)
>  		return RESULT_OK;
>  
> @@ -2349,9 +2349,6 @@ static int mmc_test_hw_reset(struct mmc_test_card *test)
>  	if (err != -EOPNOTSUPP)
>  		return err;
>  
> -	if (!mmc_can_reset(card))
> -		return RESULT_UNSUP_CARD;
> -
>  	return RESULT_UNSUP_HOST;
>  }
>  
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index d56e222..486cda8 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -2232,65 +2232,33 @@ static void mmc_hw_reset_for_init(struct mmc_host *host)
>  	mmc_host_clk_release(host);
>  }
>  
> -int mmc_can_reset(struct mmc_card *card)
> +/* Reset card in a bus-specific way */
> +static int mmc_do_reset(struct mmc_host *host, int check)
>  {
> -	u8 rst_n_function;
> -
> -	if (!mmc_card_mmc(card))
> -		return 0;
> -	rst_n_function = card->ext_csd.rst_n_function;
> -	if ((rst_n_function & EXT_CSD_RST_N_EN_MASK) != EXT_CSD_RST_N_ENABLED)
> -		return 0;
> -	return 1;
> -}
> -EXPORT_SYMBOL(mmc_can_reset);
> -
> -static int mmc_do_hw_reset(struct mmc_host *host, int check)
> -{
> -	struct mmc_card *card = host->card;
> -
> -	if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
> -		return -EOPNOTSUPP;
> -
> -	if (!card)
> -		return -EINVAL;
> +	int ret;
>  
> -	if (!mmc_can_reset(card))
> +	if (!host->bus_ops || !host->bus_ops->power_reset ||
> +			host->bus_ops->power_reset(host, MMC_POWER_RESET_TEST))
>  		return -EOPNOTSUPP;
>  
> -	mmc_host_clk_hold(host);
> -	mmc_set_clock(host, host->f_init);
> -
> -	host->ops->hw_reset(host);
> -
> -	/* If the reset has happened, then a status command will fail */
> -	if (check) {
> -		u32 status;
> -
> -		if (!mmc_send_status(card, &status)) {
> -			mmc_host_clk_release(host);
> -			return -ENOSYS;
> -		}
> -	}
> -
> -	mmc_power_up(host, card->ocr);
> +	ret = host->bus_ops->power_reset(host, check);
>  
> -	mmc_host_clk_release(host);
> +	pr_warning("%s: tried to reset card (%d)\n", mmc_hostname(host), ret);
>  
>  	return host->bus_ops->power_restore(host);
>  }
>  
> -int mmc_hw_reset(struct mmc_host *host)
> +int mmc_reset(struct mmc_host *host)
>  {
> -	return mmc_do_hw_reset(host, 0);
> +	return mmc_do_reset(host, MMC_POWER_RESET_RESET);
>  }
> -EXPORT_SYMBOL(mmc_hw_reset);
> +EXPORT_SYMBOL(mmc_reset);
>  
> -int mmc_hw_reset_check(struct mmc_host *host)
> +int mmc_reset_check(struct mmc_host *host)
>  {
> -	return mmc_do_hw_reset(host, 1);
> +	return mmc_do_reset(host, MMC_POWER_RESET_CHECK);
>  }
> -EXPORT_SYMBOL(mmc_hw_reset_check);
> +EXPORT_SYMBOL(mmc_reset_check);
>  
>  static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
>  {
> diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
> index 443a584..6a0420b 100644
> --- a/drivers/mmc/core/core.h
> +++ b/drivers/mmc/core/core.h
> @@ -25,6 +25,10 @@ struct mmc_bus_ops {
>  	int (*runtime_resume)(struct mmc_host *);
>  	int (*power_save)(struct mmc_host *);
>  	int (*power_restore)(struct mmc_host *);
> +	int (*power_reset)(struct mmc_host *, int);
> +#define MMC_POWER_RESET_RESET	0
> +#define MMC_POWER_RESET_TEST	1
> +#define MMC_POWER_RESET_CHECK	2
>  	int (*alive)(struct mmc_host *);
>  	int (*shutdown)(struct mmc_host *);
>  };
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 793c6f7..ac5192c 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -1762,6 +1762,45 @@ static int mmc_runtime_resume(struct mmc_host *host)
>  	return 0;
>  }
>  
> +static int mmc_power_reset(struct mmc_host *host, int test)
> +{
> +	struct mmc_card *card = host->card;
> +	u8 rst_n_function;
> +
> +	if (!card)
> +		return -EINVAL;
> +
> +	if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
> +		return -EOPNOTSUPP;
> +
> +	rst_n_function = card->ext_csd.rst_n_function;
> +	if ((rst_n_function & EXT_CSD_RST_N_EN_MASK) != EXT_CSD_RST_N_ENABLED)
> +		return -EOPNOTSUPP;
> +
> +	if (test == MMC_POWER_RESET_TEST)
> +		return 0;
> +
> +	mmc_host_clk_hold(host);
> +	mmc_set_clock(host, host->f_init);
> +
> +	host->ops->hw_reset(host);
> +
> +	if (test == MMC_POWER_RESET_CHECK) {
> +		u32 status;
> +
> +		if (!mmc_send_status(card, &status)) {
> +			mmc_host_clk_release(host);
> +			return -ENOSYS;
> +		}
> +	}
> +
> +	mmc_power_up(host, card->ocr);
> +
> +	mmc_host_clk_release(host);
> +
> +	return 0;
> +}
> +
>  static int mmc_power_restore(struct mmc_host *host)
>  {
>  	int ret;
> @@ -1781,6 +1820,7 @@ static const struct mmc_bus_ops mmc_ops = {
>  	.runtime_suspend = mmc_runtime_suspend,
>  	.runtime_resume = mmc_runtime_resume,
>  	.power_restore = mmc_power_restore,
> +	.power_reset = mmc_power_reset,
>  	.alive = mmc_alive,
>  	.shutdown = mmc_shutdown,
>  };
> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
> index f206e29..4f7a76e 100644
> --- a/include/linux/mmc/core.h
> +++ b/include/linux/mmc/core.h
> @@ -180,9 +180,8 @@ extern unsigned int mmc_calc_max_discard(struct mmc_card *card);
>  extern int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen);
>  extern int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount,
>  			      bool is_rel_write);
> -extern int mmc_hw_reset(struct mmc_host *host);
> -extern int mmc_hw_reset_check(struct mmc_host *host);
> -extern int mmc_can_reset(struct mmc_card *card);
> +extern int mmc_reset(struct mmc_host *host);
> +extern int mmc_reset_check(struct mmc_host *host);
>  
>  extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *);
>  extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int);
> 


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

* Re: [PATCH 2/4] mmc: core: use mmc_power_up in hw_reset
  2014-10-24 12:46 ` [PATCH 2/4] mmc: core: use mmc_power_up in hw_reset Johan Rudholm
@ 2014-11-03  9:21   ` Adrian Hunter
  2014-11-03 10:13     ` Johan Rudholm
  0 siblings, 1 reply; 12+ messages in thread
From: Adrian Hunter @ 2014-11-03  9:21 UTC (permalink / raw)
  To: Johan Rudholm, linux-mmc, Chris Ball, Ulf Hansson
  Cc: Guennadi Liakhovetski, David Lanzendörfer, Jesper Nilsson,
	Johan Rudholm

On 24/10/14 15:46, Johan Rudholm wrote:
> The steps performed in mmc_do_hw_reset for eMMC:s after the hardware
> reset are very similar to those performed by mmc_power_up, so do a call

They perform different functions.  mmc_power_up() does nothing if the card
is powered up.  To share the common code you need to create a function for
the common functionality which is setting the initial state e.g.

int mmc_set_initial_state(struct mmc_host *host)
{
	...
}

And call that from mmc_do_hw_reset and mmc_power_up.

> to this function instead.
> 
> Signed-off-by: Johan Rudholm <johanru@axis.com>
> ---
>  drivers/mmc/core/core.c |   11 +----------
>  1 files changed, 1 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index 5d215ee..d56e222 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -2273,16 +2273,7 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)
>  		}
>  	}
>  
> -	if (mmc_host_is_spi(host)) {
> -		host->ios.chip_select = MMC_CS_HIGH;
> -		host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
> -	} else {
> -		host->ios.chip_select = MMC_CS_DONTCARE;
> -		host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
> -	}
> -	host->ios.bus_width = MMC_BUS_WIDTH_1;
> -	host->ios.timing = MMC_TIMING_LEGACY;
> -	mmc_set_ios(host);
> +	mmc_power_up(host, card->ocr);
>  
>  	mmc_host_clk_release(host);
>  
> 


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

* Re: [PATCH 2/4] mmc: core: use mmc_power_up in hw_reset
  2014-11-03  9:21   ` Adrian Hunter
@ 2014-11-03 10:13     ` Johan Rudholm
  2014-11-03 10:59       ` Adrian Hunter
  0 siblings, 1 reply; 12+ messages in thread
From: Johan Rudholm @ 2014-11-03 10:13 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Johan Rudholm, linux-mmc, Chris Ball, Ulf Hansson,
	Guennadi Liakhovetski, David Lanzendörfer, Jesper Nilsson

2014-11-03 10:21 GMT+01:00 Adrian Hunter <adrian.hunter@intel.com>:
> On 24/10/14 15:46, Johan Rudholm wrote:
>> The steps performed in mmc_do_hw_reset for eMMC:s after the hardware
>> reset are very similar to those performed by mmc_power_up, so do a call
>
> They perform different functions.  mmc_power_up() does nothing if the card
> is powered up.  To share the common code you need to create a function for
> the common functionality which is setting the initial state e.g.
>
> int mmc_set_initial_state(struct mmc_host *host)
> {
>         ...
> }
>
> And call that from mmc_do_hw_reset and mmc_power_up.

Thank you for the comment. What do you think of doing a complete
mmc_power_cycle after having performed a (successful) reset? In this
way we can simplify the SD card reset and we don't have to break out
the common code from mmc_power_up. Naming discussion apart, something
like this:

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 486cda8..941f631 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2236,12 +2236,15 @@ static void mmc_hw_reset_for_init(struct mmc_host *host)
 static int mmc_do_reset(struct mmc_host *host, int check)
 {
        int ret;
+       struct mmc_card *card = host->card;

        if (!host->bus_ops || !host->bus_ops->power_reset ||
                        host->bus_ops->power_reset(host, MMC_POWER_RESET_TEST))
                return -EOPNOTSUPP;

        ret = host->bus_ops->power_reset(host, check);
+       if (!ret && card)
+               mmc_power_cycle(host, card->ocr);

        pr_warning("%s: tried to reset card (%d)\n", mmc_hostname(host), ret);

diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index ac5192c..900133a 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1794,8 +1794,6 @@ static int mmc_power_reset(struct mmc_host
*host, int test)
                }
        }

-       mmc_power_up(host, card->ocr);
-
        mmc_host_clk_release(host);

        return 0;
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 9ad46b2..d5b8ee7 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1187,8 +1187,6 @@ static int mmc_sd_power_reset(struct mmc_host
*host, int test)
        if (test == MMC_POWER_RESET_TEST)
                return 0;

-       mmc_power_cycle(host, card->ocr);
-
        return 0;
 }

//Johan

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

* Re: [PATCH 3/4] mmc: core: make hw_reset generic
  2014-11-03  9:20   ` Adrian Hunter
@ 2014-11-03 10:19     ` Johan Rudholm
  2014-11-03 10:56       ` Adrian Hunter
  0 siblings, 1 reply; 12+ messages in thread
From: Johan Rudholm @ 2014-11-03 10:19 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Johan Rudholm, linux-mmc, Chris Ball, Ulf Hansson,
	Guennadi Liakhovetski, David Lanzendörfer, Jesper Nilsson

2014-11-03 10:20 GMT+01:00 Adrian Hunter <adrian.hunter@intel.com>:
> On 24/10/14 15:46, Johan Rudholm wrote:
>> Move the (e)MMC specific hw_reset code from core.c into mmc.c and call
>> it from the new bus_ops member power_reset. This also lets us add code
>
> power_reset is not a good name because it does not necessarily have
> anything to do with power.  I am not sure why you don't stick with
> hw_reset.
>
>> for reseting SD cards as well.
>>
>> Rename the mmc_hw_reset* functions into mmc_reset*, since what they
>> now actually do depends on the device type (and it may be something else
>> than doing a hw_reset).
>
> I don't follow your reasoning about the rename.  Cycling the power is
> a kind of hardware reset isn't it.

Since we finalize the reset by calling bus_ops->power_restore, I was
looking for something symmetrical. Ulf mentioned perhaps extending
bus_ops->power_save, but I couldn't find a reasonable way of doing
this. Do you propose simply calling it bus_ops->hw_reset ?

//Johan

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

* Re: [PATCH 3/4] mmc: core: make hw_reset generic
  2014-11-03 10:19     ` Johan Rudholm
@ 2014-11-03 10:56       ` Adrian Hunter
  0 siblings, 0 replies; 12+ messages in thread
From: Adrian Hunter @ 2014-11-03 10:56 UTC (permalink / raw)
  To: Johan Rudholm
  Cc: Johan Rudholm, linux-mmc, Chris Ball, Ulf Hansson,
	Guennadi Liakhovetski, David Lanzendörfer, Jesper Nilsson

On 03/11/14 12:19, Johan Rudholm wrote:
> 2014-11-03 10:20 GMT+01:00 Adrian Hunter <adrian.hunter@intel.com>:
>> On 24/10/14 15:46, Johan Rudholm wrote:
>>> Move the (e)MMC specific hw_reset code from core.c into mmc.c and call
>>> it from the new bus_ops member power_reset. This also lets us add code
>>
>> power_reset is not a good name because it does not necessarily have
>> anything to do with power.  I am not sure why you don't stick with
>> hw_reset.
>>
>>> for reseting SD cards as well.
>>>
>>> Rename the mmc_hw_reset* functions into mmc_reset*, since what they
>>> now actually do depends on the device type (and it may be something else
>>> than doing a hw_reset).
>>
>> I don't follow your reasoning about the rename.  Cycling the power is
>> a kind of hardware reset isn't it.
> 
> Since we finalize the reset by calling bus_ops->power_restore, I was
> looking for something symmetrical. Ulf mentioned perhaps extending
> bus_ops->power_save, but I couldn't find a reasonable way of doing
> this. Do you propose simply calling it bus_ops->hw_reset ?

Yes



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

* Re: [PATCH 2/4] mmc: core: use mmc_power_up in hw_reset
  2014-11-03 10:13     ` Johan Rudholm
@ 2014-11-03 10:59       ` Adrian Hunter
  0 siblings, 0 replies; 12+ messages in thread
From: Adrian Hunter @ 2014-11-03 10:59 UTC (permalink / raw)
  To: Johan Rudholm
  Cc: Johan Rudholm, linux-mmc, Chris Ball, Ulf Hansson,
	Guennadi Liakhovetski, David Lanzendörfer, Jesper Nilsson

On 03/11/14 12:13, Johan Rudholm wrote:
> 2014-11-03 10:21 GMT+01:00 Adrian Hunter <adrian.hunter@intel.com>:
>> On 24/10/14 15:46, Johan Rudholm wrote:
>>> The steps performed in mmc_do_hw_reset for eMMC:s after the hardware
>>> reset are very similar to those performed by mmc_power_up, so do a call
>>
>> They perform different functions.  mmc_power_up() does nothing if the card
>> is powered up.  To share the common code you need to create a function for
>> the common functionality which is setting the initial state e.g.
>>
>> int mmc_set_initial_state(struct mmc_host *host)
>> {
>>         ...
>> }
>>
>> And call that from mmc_do_hw_reset and mmc_power_up.
> 
> Thank you for the comment. What do you think of doing a complete
> mmc_power_cycle after having performed a (successful) reset? In this
> way we can simplify the SD card reset and we don't have to break out
> the common code from mmc_power_up. Naming discussion apart, something
> like this:

I would keep the concept of hw_reset separate from how that is
implemented i.e. whether it has anything to do with power.

> 
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index 486cda8..941f631 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -2236,12 +2236,15 @@ static void mmc_hw_reset_for_init(struct mmc_host *host)
>  static int mmc_do_reset(struct mmc_host *host, int check)
>  {
>         int ret;
> +       struct mmc_card *card = host->card;
> 
>         if (!host->bus_ops || !host->bus_ops->power_reset ||
>                         host->bus_ops->power_reset(host, MMC_POWER_RESET_TEST))
>                 return -EOPNOTSUPP;
> 
>         ret = host->bus_ops->power_reset(host, check);
> +       if (!ret && card)
> +               mmc_power_cycle(host, card->ocr);
> 
>         pr_warning("%s: tried to reset card (%d)\n", mmc_hostname(host), ret);
> 
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index ac5192c..900133a 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -1794,8 +1794,6 @@ static int mmc_power_reset(struct mmc_host
> *host, int test)
>                 }
>         }
> 
> -       mmc_power_up(host, card->ocr);
> -
>         mmc_host_clk_release(host);
> 
>         return 0;
> diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
> index 9ad46b2..d5b8ee7 100644
> --- a/drivers/mmc/core/sd.c
> +++ b/drivers/mmc/core/sd.c
> @@ -1187,8 +1187,6 @@ static int mmc_sd_power_reset(struct mmc_host
> *host, int test)
>         if (test == MMC_POWER_RESET_TEST)
>                 return 0;
> 
> -       mmc_power_cycle(host, card->ocr);
> -
>         return 0;
>  }
> 
> //Johan
> 
> 


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

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

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-24 12:46 [PATCH 0/4] mmc: core: hw_reset changes Johan Rudholm
2014-10-24 12:46 ` [PATCH 1/4] mmc: core: use mmc_send_status to check hw_reset Johan Rudholm
2014-10-24 12:46 ` [PATCH 2/4] mmc: core: use mmc_power_up in hw_reset Johan Rudholm
2014-11-03  9:21   ` Adrian Hunter
2014-11-03 10:13     ` Johan Rudholm
2014-11-03 10:59       ` Adrian Hunter
2014-10-24 12:46 ` [PATCH 3/4] mmc: core: make hw_reset generic Johan Rudholm
2014-11-03  9:20   ` Adrian Hunter
2014-11-03 10:19     ` Johan Rudholm
2014-11-03 10:56       ` Adrian Hunter
2014-10-24 12:46 ` [PATCH 4/4] mmc: sd: add power_reset callback Johan Rudholm
2014-11-03  8:46 ` [PATCH 0/4] mmc: core: hw_reset changes Johan Rudholm

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.