From: "Matt Fleming" <mattjfleming@googlemail.com>
To: "Pierre Ossman" <drzeus-mmc@drzeus.cx>
Cc: linux-kernel@vger.kernel.org, dbrownell@users.sourceforge.net
Subject: Re: [RFC][PATCH] MMC: Use write timeout value as read from CSR
Date: Mon, 8 Sep 2008 14:28:00 +0100 [thread overview]
Message-ID: <5ff4a1e50809080628i65bd7c7blfac70659a9f9229c@mail.gmail.com> (raw)
In-Reply-To: <20080907123832.5ba79c12@mjolnir.drzeus.cx>
[-- Attachment #1: Type: text/plain, Size: 6361 bytes --]
2008/9/7 Pierre Ossman <drzeus-mmc@drzeus.cx>:
>
> This actually isn't fully correct for SD either as it only specifies
> that 250 ms is the upper bound on the timeout.
>
> I believe the proper way of solving this is to have mmc_spi respect the
> timeouts set in the request structure. Modify mmc_set_data_timeout() if
> necessary.
>
You're right, I changed the patch accordingly (I also fixed the read
timeout path).
>From 03b2d04b2e597ec073f2ff61224df1d3dee3b9de Mon Sep 17 00:00:00 2001
From: Matthew Fleming <matthew.fleming@imgtec.com>
Date: Mon, 8 Sep 2008 14:10:14 +0100
Subject: [PATCH] MMC: Use timeout values from CSR
Currently, the MMC/SD over SPI code has a hard-coded timeout value of
250ms on writes and 100ms on reads. This is correct for SDHC cards
and is specified in the spec, but it is not correct for MMC/SD cards.
For MMC cards the values that are read from the CSR should be used.
For SD cards the values from the CSR should be used as long as they
do not exceed 250ms for writes and 100ms for reads.
Signed-off-by: Matthew Fleming <matthew.fleming@imgtec.com>
---
drivers/mmc/host/mmc_spi.c | 56 +++++++++++++++++++++++++++++++++----------
1 files changed, 43 insertions(+), 13 deletions(-)
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 7503b81..35f18f5 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -34,6 +34,7 @@
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h> /* for R1_SPI_* bit values */
+#include <linux/mmc/card.h>
#include <linux/spi/spi.h>
#include <linux/spi/mmc_spi.h>
@@ -89,14 +90,12 @@
#define MMC_SPI_BLOCKSIZE 512
-/* These fixed timeouts come from the latest SD specs, which say to ignore
- * the CSD values. The R1B value is for card erase (e.g. the "I forgot the
+/*
+ * The R1B value is for card erase (e.g. the "I forgot the
* card's password" scenario); it's mostly applied to STOP_TRANSMISSION after
* reads which takes nowhere near that long. Older cards may be able to use
* shorter timeouts ... but why bother?
*/
-#define readblock_timeout ktime_set(0, 100 * 1000 * 1000)
-#define writeblock_timeout ktime_set(0, 250 * 1000 * 1000)
#define r1b_timeout ktime_set(3, 0)
@@ -214,15 +213,44 @@ mmc_spi_skip(struct mmc_spi_host *host, ktime_t
timeout, unsigned n, u8 byte)
return -ETIMEDOUT;
}
+/*
+ * Return the timeout value for this card.
+ */
+static ktime_t
+mmc_get_timeout(struct mmc_spi_host *host, struct mmc_data *data)
+{
+ unsigned int timeout_ns;
+
+ /* If card hasn't been initialised, use default timeouts. */
+ if (!host->mmc->card) {
+ if (data->flags & MMC_DATA_WRITE)
+ timeout_ns = 250000000;
+ else
+ timeout_ns = 100000000;
+ } else {
+ timeout_ns = data->timeout_ns;
+ timeout_ns += data->timeout_clks * 1000 * 1000 /
+ (host->mmc->card->host->ios.clock);
+ }
+
+ /*
+ * The reason we're adding 0 and a nanosecond value here is because
+ * the timeout_ns value may be greater than one second, which
+ * ktime_set() does not handle properly. The correct logic to handle
+ * this overflow is in ktime_add_ns() however.
+ */
+ return ktime_add_ns(ktime_set(0, 0), timeout_ns);
+}
+
static inline int
mmc_spi_wait_unbusy(struct mmc_spi_host *host, ktime_t timeout)
{
return mmc_spi_skip(host, timeout, sizeof(host->data->status), 0);
}
-static int mmc_spi_readtoken(struct mmc_spi_host *host)
+static int mmc_spi_readtoken(struct mmc_spi_host *host, ktime_t timeout)
{
- return mmc_spi_skip(host, readblock_timeout, 1, 0xff);
+ return mmc_spi_skip(host, timeout, 1, 0xff);
}
@@ -605,7 +633,8 @@ mmc_spi_setup_data_message(
* Return negative errno, else success.
*/
static int
-mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t)
+mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t,
+ struct mmc_data *data)
{
struct spi_device *spi = host->spi;
int status, i;
@@ -673,7 +702,7 @@ mmc_spi_writeblock(struct mmc_spi_host *host,
struct spi_transfer *t)
if (scratch->status[i] != 0)
return 0;
}
- return mmc_spi_wait_unbusy(host, writeblock_timeout);
+ return mmc_spi_wait_unbusy(host, mmc_get_timeout(host, data));
}
/*
@@ -693,7 +722,8 @@ mmc_spi_writeblock(struct mmc_spi_host *host,
struct spi_transfer *t)
* STOP_TRANSMISSION command.
*/
static int
-mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t)
+mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t,
+ struct mmc_data *data)
{
struct spi_device *spi = host->spi;
int status;
@@ -707,7 +737,7 @@ mmc_spi_readblock(struct mmc_spi_host *host,
struct spi_transfer *t)
return status;
status = scratch->status[0];
if (status == 0xff || status == 0)
- status = mmc_spi_readtoken(host);
+ status = mmc_spi_readtoken(host, mmc_get_timeout(host, data));
if (status == SPI_TOKEN_SINGLE) {
if (host->dma_dev) {
@@ -832,9 +862,9 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct
mmc_command *cmd,
t->len);
if (direction == DMA_TO_DEVICE)
- status = mmc_spi_writeblock(host, t);
+ status = mmc_spi_writeblock(host, t, data);
else
- status = mmc_spi_readblock(host, t);
+ status = mmc_spi_readblock(host, t, data);
if (status < 0)
break;
@@ -917,7 +947,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct
mmc_command *cmd,
if (scratch->status[tmp] != 0)
return;
}
- tmp = mmc_spi_wait_unbusy(host, writeblock_timeout);
+ tmp = mmc_spi_wait_unbusy(host, mmc_get_timeout(host, data));
if (tmp < 0 && !data->error)
data->error = tmp;
}
--
1.5.5.2
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-MMC-Use-timeout-values-from-CSR.patch --]
[-- Type: text/x-diff; name=0001-MMC-Use-timeout-values-from-CSR.patch, Size: 5163 bytes --]
From 03b2d04b2e597ec073f2ff61224df1d3dee3b9de Mon Sep 17 00:00:00 2001
From: Matthew Fleming <matthew.fleming@imgtec.com>
Date: Mon, 8 Sep 2008 14:10:14 +0100
Subject: [PATCH] MMC: Use timeout values from CSR
Currently, the MMC/SD over SPI code has a hard-coded timeout value of
250ms on writes and 100ms on reads. This is correct for SDHC cards
and is specified in the spec, but it is not correct for MMC/SD cards.
For MMC cards the values that are read from the CSR should be used.
For SD cards the values from the CSR should be used as long as they
do not exceed 250ms for writes and 100ms for reads.
Signed-off-by: Matthew Fleming <matthew.fleming@imgtec.com>
---
drivers/mmc/host/mmc_spi.c | 56 +++++++++++++++++++++++++++++++++----------
1 files changed, 43 insertions(+), 13 deletions(-)
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 7503b81..35f18f5 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -34,6 +34,7 @@
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h> /* for R1_SPI_* bit values */
+#include <linux/mmc/card.h>
#include <linux/spi/spi.h>
#include <linux/spi/mmc_spi.h>
@@ -89,14 +90,12 @@
#define MMC_SPI_BLOCKSIZE 512
-/* These fixed timeouts come from the latest SD specs, which say to ignore
- * the CSD values. The R1B value is for card erase (e.g. the "I forgot the
+/*
+ * The R1B value is for card erase (e.g. the "I forgot the
* card's password" scenario); it's mostly applied to STOP_TRANSMISSION after
* reads which takes nowhere near that long. Older cards may be able to use
* shorter timeouts ... but why bother?
*/
-#define readblock_timeout ktime_set(0, 100 * 1000 * 1000)
-#define writeblock_timeout ktime_set(0, 250 * 1000 * 1000)
#define r1b_timeout ktime_set(3, 0)
@@ -214,15 +213,44 @@ mmc_spi_skip(struct mmc_spi_host *host, ktime_t timeout, unsigned n, u8 byte)
return -ETIMEDOUT;
}
+/*
+ * Return the timeout value for this card.
+ */
+static ktime_t
+mmc_get_timeout(struct mmc_spi_host *host, struct mmc_data *data)
+{
+ unsigned int timeout_ns;
+
+ /* If card hasn't been initialised, use default timeouts. */
+ if (!host->mmc->card) {
+ if (data->flags & MMC_DATA_WRITE)
+ timeout_ns = 250000000;
+ else
+ timeout_ns = 100000000;
+ } else {
+ timeout_ns = data->timeout_ns;
+ timeout_ns += data->timeout_clks * 1000 * 1000 /
+ (host->mmc->card->host->ios.clock);
+ }
+
+ /*
+ * The reason we're adding 0 and a nanosecond value here is because
+ * the timeout_ns value may be greater than one second, which
+ * ktime_set() does not handle properly. The correct logic to handle
+ * this overflow is in ktime_add_ns() however.
+ */
+ return ktime_add_ns(ktime_set(0, 0), timeout_ns);
+}
+
static inline int
mmc_spi_wait_unbusy(struct mmc_spi_host *host, ktime_t timeout)
{
return mmc_spi_skip(host, timeout, sizeof(host->data->status), 0);
}
-static int mmc_spi_readtoken(struct mmc_spi_host *host)
+static int mmc_spi_readtoken(struct mmc_spi_host *host, ktime_t timeout)
{
- return mmc_spi_skip(host, readblock_timeout, 1, 0xff);
+ return mmc_spi_skip(host, timeout, 1, 0xff);
}
@@ -605,7 +633,8 @@ mmc_spi_setup_data_message(
* Return negative errno, else success.
*/
static int
-mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t)
+mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t,
+ struct mmc_data *data)
{
struct spi_device *spi = host->spi;
int status, i;
@@ -673,7 +702,7 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t)
if (scratch->status[i] != 0)
return 0;
}
- return mmc_spi_wait_unbusy(host, writeblock_timeout);
+ return mmc_spi_wait_unbusy(host, mmc_get_timeout(host, data));
}
/*
@@ -693,7 +722,8 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t)
* STOP_TRANSMISSION command.
*/
static int
-mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t)
+mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t,
+ struct mmc_data *data)
{
struct spi_device *spi = host->spi;
int status;
@@ -707,7 +737,7 @@ mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t)
return status;
status = scratch->status[0];
if (status == 0xff || status == 0)
- status = mmc_spi_readtoken(host);
+ status = mmc_spi_readtoken(host, mmc_get_timeout(host, data));
if (status == SPI_TOKEN_SINGLE) {
if (host->dma_dev) {
@@ -832,9 +862,9 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
t->len);
if (direction == DMA_TO_DEVICE)
- status = mmc_spi_writeblock(host, t);
+ status = mmc_spi_writeblock(host, t, data);
else
- status = mmc_spi_readblock(host, t);
+ status = mmc_spi_readblock(host, t, data);
if (status < 0)
break;
@@ -917,7 +947,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
if (scratch->status[tmp] != 0)
return;
}
- tmp = mmc_spi_wait_unbusy(host, writeblock_timeout);
+ tmp = mmc_spi_wait_unbusy(host, mmc_get_timeout(host, data));
if (tmp < 0 && !data->error)
data->error = tmp;
}
--
1.5.5.2
next prev parent reply other threads:[~2008-09-08 13:28 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-09-01 15:12 Matt Fleming
2008-09-07 10:38 ` Pierre Ossman
2008-09-08 13:28 ` Matt Fleming [this message]
2008-09-08 19:18 ` David Brownell
2008-09-09 7:22 ` Pierre Ossman
2008-09-09 7:34 ` Matt Fleming
2008-09-09 7:44 ` Pierre Ossman
2008-09-09 7:59 ` Matt Fleming
2008-09-09 8:55 ` Pierre Ossman
2008-09-09 9:07 ` Matt Fleming
2008-09-09 9:42 ` Matt Fleming
2008-09-14 13:48 ` Pierre Ossman
[not found] ` <5ff4a1e50809150103v1e250e0x4192e2fe901750a6@mail.gmail.com>
[not found] ` <20080915103821.2b618bba@mjolnir.drzeus.cx>
2008-09-15 9:24 ` Matt Fleming
2008-09-20 11:06 ` Pierre Ossman
2008-09-24 11:16 ` Matt Fleming
2008-10-02 8:26 ` Pierre Ossman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5ff4a1e50809080628i65bd7c7blfac70659a9f9229c@mail.gmail.com \
--to=mattjfleming@googlemail.com \
--cc=dbrownell@users.sourceforge.net \
--cc=drzeus-mmc@drzeus.cx \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®