diff mbox

[v3] mmc: add ignorance case for CMD13 CRC error

Message ID 002b01cea969$3ab56630$b0203290$%jun@samsung.com (mailing list archive)
State New, archived
Headers show

Commit Message

Seungwon Jeon Sept. 4, 2013, 12:21 p.m. UTC
While speed mode is changed, CMD13 cannot be guaranteed.
According to the spec., it is not recommended to use CMD13
to check the busy completion of the timing change.
If CMD13 is used in this case, CRC error must be ignored.

Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
---
Change in v3:
 - Adjusted condition with MMC_CAP_WAIT_WHILE_BUSY.(From Ulf Hansson) 

Change in v2:
 - Removed function declaration.(From Ulf Hansson)

 drivers/mmc/core/mmc_ops.c |   73 +++++++++++++++++++++++++++-----------------
 1 files changed, 45 insertions(+), 28 deletions(-)

Comments

Ulf Hansson Sept. 4, 2013, 12:31 p.m. UTC | #1
On 4 September 2013 14:21, Seungwon Jeon <tgih.jun@samsung.com> wrote:
> While speed mode is changed, CMD13 cannot be guaranteed.
> According to the spec., it is not recommended to use CMD13
> to check the busy completion of the timing change.
> If CMD13 is used in this case, CRC error must be ignored.
>
> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
> ---
> Change in v3:
>  - Adjusted condition with MMC_CAP_WAIT_WHILE_BUSY.(From Ulf Hansson)
>
> Change in v2:
>  - Removed function declaration.(From Ulf Hansson)
>
>  drivers/mmc/core/mmc_ops.c |   73 +++++++++++++++++++++++++++-----------------
>  1 files changed, 45 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
> index ef18348..37f7d70 100644
> --- a/drivers/mmc/core/mmc_ops.c
> +++ b/drivers/mmc/core/mmc_ops.c
> @@ -23,6 +23,40 @@
>
>  #define MMC_OPS_TIMEOUT_MS     (10 * 60 * 1000) /* 10 minute timeout */
>
> +static inline int __mmc_send_status(struct mmc_card *card, u32 *status,
> +                                   bool ignore_crc)
> +{
> +       int err;
> +       struct mmc_command cmd = {0};
> +
> +       BUG_ON(!card);
> +       BUG_ON(!card->host);
> +
> +       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;
> +       if (ignore_crc)
> +               cmd.flags &= ~MMC_RSP_CRC;
> +
> +       err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
> +       if (err)
> +               return err;
> +
> +       /* NOTE: callers are required to understand the difference
> +        * between "native" and SPI format status words!
> +        */
> +       if (status)
> +               *status = cmd.resp[0];
> +
> +       return 0;
> +}
> +
> +int mmc_send_status(struct mmc_card *card, u32 *status)
> +{
> +       return __mmc_send_status(card, status, false);
> +}
> +
>  static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
>  {
>         int err;
> @@ -380,6 +414,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
>         struct mmc_command cmd = {0};
>         unsigned long timeout;
>         u32 status;
> +       bool ignore_crc = false;
>
>         BUG_ON(!card);
>         BUG_ON(!card->host);
> @@ -408,10 +443,18 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
>         if (!use_busy_signal)
>                 return 0;
>
> -       /* Must check status to be sure of no errors */
> +       /*
> +        * Must check status to be sure of no errors
> +        * If CMD13 is to check the busy completion of the timing change,
> +        * disable the check of CRC error.
> +        */
> +       if (index == EXT_CSD_HS_TIMING &&
> +           !(card->host->caps & MMC_CAP_WAIT_WHILE_BUSY))
> +               ignore_crc = true;
> +
>         timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS);
>         do {
> -               err = mmc_send_status(card, &status);
> +               err = __mmc_send_status(card, &status, ignore_crc);
>                 if (err)
>                         return err;
>                 if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
> @@ -449,32 +492,6 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
>  }
>  EXPORT_SYMBOL_GPL(mmc_switch);
>
> -int mmc_send_status(struct mmc_card *card, u32 *status)
> -{
> -       int err;
> -       struct mmc_command cmd = {0};
> -
> -       BUG_ON(!card);
> -       BUG_ON(!card->host);
> -
> -       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, MMC_CMD_RETRIES);
> -       if (err)
> -               return err;
> -
> -       /* NOTE: callers are required to understand the difference
> -        * between "native" and SPI format status words!
> -        */
> -       if (status)
> -               *status = cmd.resp[0];
> -
> -       return 0;
> -}
> -
>  static int
>  mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
>                   u8 len)
> --
> 1.7.0.4
>
>

Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
--
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
Chris Ball Sept. 26, 2013, 1:41 a.m. UTC | #2
Hi,

On Wed, Sep 04 2013, Ulf Hansson wrote:
> On 4 September 2013 14:21, Seungwon Jeon <tgih.jun@samsung.com> wrote:
>> While speed mode is changed, CMD13 cannot be guaranteed.
>> According to the spec., it is not recommended to use CMD13
>> to check the busy completion of the timing change.
>> If CMD13 is used in this case, CRC error must be ignored.
>>
>> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
>
> Acked-by: Ulf Hansson <ulf.hansson@linaro.org>

Thanks, pushed to mmc-next for 3.13 with Ulf's ACK.

- Chris.
diff mbox

Patch

diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index ef18348..37f7d70 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -23,6 +23,40 @@ 
 
 #define MMC_OPS_TIMEOUT_MS	(10 * 60 * 1000) /* 10 minute timeout */
 
+static inline int __mmc_send_status(struct mmc_card *card, u32 *status,
+				    bool ignore_crc)
+{
+	int err;
+	struct mmc_command cmd = {0};
+
+	BUG_ON(!card);
+	BUG_ON(!card->host);
+
+	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;
+	if (ignore_crc)
+		cmd.flags &= ~MMC_RSP_CRC;
+
+	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+	if (err)
+		return err;
+
+	/* NOTE: callers are required to understand the difference
+	 * between "native" and SPI format status words!
+	 */
+	if (status)
+		*status = cmd.resp[0];
+
+	return 0;
+}
+
+int mmc_send_status(struct mmc_card *card, u32 *status)
+{
+	return __mmc_send_status(card, status, false);
+}
+
 static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
 {
 	int err;
@@ -380,6 +414,7 @@  int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 	struct mmc_command cmd = {0};
 	unsigned long timeout;
 	u32 status;
+	bool ignore_crc = false;
 
 	BUG_ON(!card);
 	BUG_ON(!card->host);
@@ -408,10 +443,18 @@  int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 	if (!use_busy_signal)
 		return 0;
 
-	/* Must check status to be sure of no errors */
+	/*
+	 * Must check status to be sure of no errors
+	 * If CMD13 is to check the busy completion of the timing change,
+	 * disable the check of CRC error.
+	 */
+	if (index == EXT_CSD_HS_TIMING &&
+	    !(card->host->caps & MMC_CAP_WAIT_WHILE_BUSY))
+		ignore_crc = true;
+
 	timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS);
 	do {
-		err = mmc_send_status(card, &status);
+		err = __mmc_send_status(card, &status, ignore_crc);
 		if (err)
 			return err;
 		if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
@@ -449,32 +492,6 @@  int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 }
 EXPORT_SYMBOL_GPL(mmc_switch);
 
-int mmc_send_status(struct mmc_card *card, u32 *status)
-{
-	int err;
-	struct mmc_command cmd = {0};
-
-	BUG_ON(!card);
-	BUG_ON(!card->host);
-
-	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, MMC_CMD_RETRIES);
-	if (err)
-		return err;
-
-	/* NOTE: callers are required to understand the difference
-	 * between "native" and SPI format status words!
-	 */
-	if (status)
-		*status = cmd.resp[0];
-
-	return 0;
-}
-
 static int
 mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
 		  u8 len)