|
@@ -24,7 +24,7 @@
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
*/
|
|
|
-#include <linux/hrtimer.h>
|
|
|
+#include <linux/sched.h>
|
|
|
#include <linux/delay.h>
|
|
|
#include <linux/bio.h>
|
|
|
#include <linux/dma-mapping.h>
|
|
@@ -95,7 +95,7 @@
|
|
|
* reads which takes nowhere near that long. Older cards may be able to use
|
|
|
* shorter timeouts ... but why bother?
|
|
|
*/
|
|
|
-#define r1b_timeout ktime_set(3, 0)
|
|
|
+#define r1b_timeout (HZ * 3)
|
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
@@ -183,12 +183,11 @@ mmc_spi_readbytes(struct mmc_spi_host *host, unsigned len)
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
-static int
|
|
|
-mmc_spi_skip(struct mmc_spi_host *host, ktime_t timeout, unsigned n, u8 byte)
|
|
|
+static int mmc_spi_skip(struct mmc_spi_host *host, unsigned long timeout,
|
|
|
+ unsigned n, u8 byte)
|
|
|
{
|
|
|
u8 *cp = host->data->status;
|
|
|
-
|
|
|
- timeout = ktime_add(timeout, ktime_get());
|
|
|
+ unsigned long start = jiffies;
|
|
|
|
|
|
while (1) {
|
|
|
int status;
|
|
@@ -203,22 +202,26 @@ mmc_spi_skip(struct mmc_spi_host *host, ktime_t timeout, unsigned n, u8 byte)
|
|
|
return cp[i];
|
|
|
}
|
|
|
|
|
|
- /* REVISIT investigate msleep() to avoid busy-wait I/O
|
|
|
- * in at least some cases.
|
|
|
- */
|
|
|
- if (ktime_to_ns(ktime_sub(ktime_get(), timeout)) > 0)
|
|
|
+ if (time_is_before_jiffies(start + timeout))
|
|
|
break;
|
|
|
+
|
|
|
+ /* If we need long timeouts, we may release the CPU.
|
|
|
+ * We use jiffies here because we want to have a relation
|
|
|
+ * between elapsed time and the blocking of the scheduler.
|
|
|
+ */
|
|
|
+ if (time_is_before_jiffies(start+1))
|
|
|
+ schedule();
|
|
|
}
|
|
|
return -ETIMEDOUT;
|
|
|
}
|
|
|
|
|
|
static inline int
|
|
|
-mmc_spi_wait_unbusy(struct mmc_spi_host *host, ktime_t timeout)
|
|
|
+mmc_spi_wait_unbusy(struct mmc_spi_host *host, unsigned long timeout)
|
|
|
{
|
|
|
return mmc_spi_skip(host, timeout, sizeof(host->data->status), 0);
|
|
|
}
|
|
|
|
|
|
-static int mmc_spi_readtoken(struct mmc_spi_host *host, ktime_t timeout)
|
|
|
+static int mmc_spi_readtoken(struct mmc_spi_host *host, unsigned long timeout)
|
|
|
{
|
|
|
return mmc_spi_skip(host, timeout, 1, 0xff);
|
|
|
}
|
|
@@ -251,6 +254,10 @@ static int mmc_spi_response_get(struct mmc_spi_host *host,
|
|
|
u8 *cp = host->data->status;
|
|
|
u8 *end = cp + host->t.len;
|
|
|
int value = 0;
|
|
|
+ int bitshift;
|
|
|
+ u8 leftover = 0;
|
|
|
+ unsigned short rotator;
|
|
|
+ int i;
|
|
|
char tag[32];
|
|
|
|
|
|
snprintf(tag, sizeof(tag), " ... CMD%d response SPI_%s",
|
|
@@ -268,9 +275,8 @@ static int mmc_spi_response_get(struct mmc_spi_host *host,
|
|
|
|
|
|
/* Data block reads (R1 response types) may need more data... */
|
|
|
if (cp == end) {
|
|
|
- unsigned i;
|
|
|
-
|
|
|
cp = host->data->status;
|
|
|
+ end = cp+1;
|
|
|
|
|
|
/* Card sends N(CR) (== 1..8) bytes of all-ones then one
|
|
|
* status byte ... and we already scanned 2 bytes.
|
|
@@ -295,20 +301,34 @@ static int mmc_spi_response_get(struct mmc_spi_host *host,
|
|
|
}
|
|
|
|
|
|
checkstatus:
|
|
|
- if (*cp & 0x80) {
|
|
|
- dev_dbg(&host->spi->dev, "%s: INVALID RESPONSE, %02x\n",
|
|
|
- tag, *cp);
|
|
|
- value = -EBADR;
|
|
|
- goto done;
|
|
|
+ bitshift = 0;
|
|
|
+ if (*cp & 0x80) {
|
|
|
+ /* Houston, we have an ugly card with a bit-shifted response */
|
|
|
+ rotator = *cp++ << 8;
|
|
|
+ /* read the next byte */
|
|
|
+ if (cp == end) {
|
|
|
+ value = mmc_spi_readbytes(host, 1);
|
|
|
+ if (value < 0)
|
|
|
+ goto done;
|
|
|
+ cp = host->data->status;
|
|
|
+ end = cp+1;
|
|
|
+ }
|
|
|
+ rotator |= *cp++;
|
|
|
+ while (rotator & 0x8000) {
|
|
|
+ bitshift++;
|
|
|
+ rotator <<= 1;
|
|
|
+ }
|
|
|
+ cmd->resp[0] = rotator >> 8;
|
|
|
+ leftover = rotator;
|
|
|
+ } else {
|
|
|
+ cmd->resp[0] = *cp++;
|
|
|
}
|
|
|
-
|
|
|
- cmd->resp[0] = *cp++;
|
|
|
cmd->error = 0;
|
|
|
|
|
|
/* Status byte: the entire seven-bit R1 response. */
|
|
|
if (cmd->resp[0] != 0) {
|
|
|
if ((R1_SPI_PARAMETER | R1_SPI_ADDRESS
|
|
|
- | R1_SPI_ILLEGAL_COMMAND)
|
|
|
+ | R1_SPI_ILLEGAL_COMMAND)
|
|
|
& cmd->resp[0])
|
|
|
value = -EINVAL;
|
|
|
else if (R1_SPI_COM_CRC & cmd->resp[0])
|
|
@@ -336,12 +356,45 @@ checkstatus:
|
|
|
* SPI R5 == R1 + data byte; IO_RW_DIRECT
|
|
|
*/
|
|
|
case MMC_RSP_SPI_R2:
|
|
|
- cmd->resp[0] |= *cp << 8;
|
|
|
+ /* read the next byte */
|
|
|
+ if (cp == end) {
|
|
|
+ value = mmc_spi_readbytes(host, 1);
|
|
|
+ if (value < 0)
|
|
|
+ goto done;
|
|
|
+ cp = host->data->status;
|
|
|
+ end = cp+1;
|
|
|
+ }
|
|
|
+ if (bitshift) {
|
|
|
+ rotator = leftover << 8;
|
|
|
+ rotator |= *cp << bitshift;
|
|
|
+ cmd->resp[0] |= (rotator & 0xFF00);
|
|
|
+ } else {
|
|
|
+ cmd->resp[0] |= *cp << 8;
|
|
|
+ }
|
|
|
break;
|
|
|
|
|
|
/* SPI R3, R4, or R7 == R1 + 4 bytes */
|
|
|
case MMC_RSP_SPI_R3:
|
|
|
- cmd->resp[1] = get_unaligned_be32(cp);
|
|
|
+ rotator = leftover << 8;
|
|
|
+ cmd->resp[1] = 0;
|
|
|
+ for (i = 0; i < 4; i++) {
|
|
|
+ cmd->resp[1] <<= 8;
|
|
|
+ /* read the next byte */
|
|
|
+ if (cp == end) {
|
|
|
+ value = mmc_spi_readbytes(host, 1);
|
|
|
+ if (value < 0)
|
|
|
+ goto done;
|
|
|
+ cp = host->data->status;
|
|
|
+ end = cp+1;
|
|
|
+ }
|
|
|
+ if (bitshift) {
|
|
|
+ rotator |= *cp++ << bitshift;
|
|
|
+ cmd->resp[1] |= (rotator >> 8);
|
|
|
+ rotator <<= 8;
|
|
|
+ } else {
|
|
|
+ cmd->resp[1] |= *cp++;
|
|
|
+ }
|
|
|
+ }
|
|
|
break;
|
|
|
|
|
|
/* SPI R1 == just one status byte */
|
|
@@ -607,7 +660,7 @@ mmc_spi_setup_data_message(
|
|
|
*/
|
|
|
static int
|
|
|
mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t,
|
|
|
- ktime_t timeout)
|
|
|
+ unsigned long timeout)
|
|
|
{
|
|
|
struct spi_device *spi = host->spi;
|
|
|
int status, i;
|
|
@@ -717,11 +770,13 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t,
|
|
|
*/
|
|
|
static int
|
|
|
mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t,
|
|
|
- ktime_t timeout)
|
|
|
+ unsigned long timeout)
|
|
|
{
|
|
|
struct spi_device *spi = host->spi;
|
|
|
int status;
|
|
|
struct scratch *scratch = host->data;
|
|
|
+ unsigned int bitshift;
|
|
|
+ u8 leftover;
|
|
|
|
|
|
/* At least one SD card sends an all-zeroes byte when N(CX)
|
|
|
* applies, before the all-ones bytes ... just cope with that.
|
|
@@ -733,38 +788,60 @@ mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t,
|
|
|
if (status == 0xff || status == 0)
|
|
|
status = mmc_spi_readtoken(host, timeout);
|
|
|
|
|
|
- if (status == SPI_TOKEN_SINGLE) {
|
|
|
- if (host->dma_dev) {
|
|
|
- dma_sync_single_for_device(host->dma_dev,
|
|
|
- host->data_dma, sizeof(*scratch),
|
|
|
- DMA_BIDIRECTIONAL);
|
|
|
- dma_sync_single_for_device(host->dma_dev,
|
|
|
- t->rx_dma, t->len,
|
|
|
- DMA_FROM_DEVICE);
|
|
|
- }
|
|
|
+ if (status < 0) {
|
|
|
+ dev_dbg(&spi->dev, "read error %02x (%d)\n", status, status);
|
|
|
+ return status;
|
|
|
+ }
|
|
|
|
|
|
- status = spi_sync(spi, &host->m);
|
|
|
+ /* The token may be bit-shifted...
|
|
|
+ * the first 0-bit precedes the data stream.
|
|
|
+ */
|
|
|
+ bitshift = 7;
|
|
|
+ while (status & 0x80) {
|
|
|
+ status <<= 1;
|
|
|
+ bitshift--;
|
|
|
+ }
|
|
|
+ leftover = status << 1;
|
|
|
|
|
|
- if (host->dma_dev) {
|
|
|
- dma_sync_single_for_cpu(host->dma_dev,
|
|
|
- host->data_dma, sizeof(*scratch),
|
|
|
- DMA_BIDIRECTIONAL);
|
|
|
- dma_sync_single_for_cpu(host->dma_dev,
|
|
|
- t->rx_dma, t->len,
|
|
|
- DMA_FROM_DEVICE);
|
|
|
- }
|
|
|
+ if (host->dma_dev) {
|
|
|
+ dma_sync_single_for_device(host->dma_dev,
|
|
|
+ host->data_dma, sizeof(*scratch),
|
|
|
+ DMA_BIDIRECTIONAL);
|
|
|
+ dma_sync_single_for_device(host->dma_dev,
|
|
|
+ t->rx_dma, t->len,
|
|
|
+ DMA_FROM_DEVICE);
|
|
|
+ }
|
|
|
|
|
|
- } else {
|
|
|
- dev_dbg(&spi->dev, "read error %02x (%d)\n", status, status);
|
|
|
+ status = spi_sync(spi, &host->m);
|
|
|
|
|
|
- /* we've read extra garbage, timed out, etc */
|
|
|
- if (status < 0)
|
|
|
- return status;
|
|
|
+ if (host->dma_dev) {
|
|
|
+ dma_sync_single_for_cpu(host->dma_dev,
|
|
|
+ host->data_dma, sizeof(*scratch),
|
|
|
+ DMA_BIDIRECTIONAL);
|
|
|
+ dma_sync_single_for_cpu(host->dma_dev,
|
|
|
+ t->rx_dma, t->len,
|
|
|
+ DMA_FROM_DEVICE);
|
|
|
+ }
|
|
|
|
|
|
- /* low four bits are an R2 subset, fifth seems to be
|
|
|
- * vendor specific ... map them all to generic error..
|
|
|
+ if (bitshift) {
|
|
|
+ /* Walk through the data and the crc and do
|
|
|
+ * all the magic to get byte-aligned data.
|
|
|
*/
|
|
|
- return -EIO;
|
|
|
+ u8 *cp = t->rx_buf;
|
|
|
+ unsigned int len;
|
|
|
+ unsigned int bitright = 8 - bitshift;
|
|
|
+ u8 temp;
|
|
|
+ for (len = t->len; len; len--) {
|
|
|
+ temp = *cp;
|
|
|
+ *cp++ = leftover | (temp >> bitshift);
|
|
|
+ leftover = temp << bitright;
|
|
|
+ }
|
|
|
+ cp = (u8 *) &scratch->crc_val;
|
|
|
+ temp = *cp;
|
|
|
+ *cp++ = leftover | (temp >> bitshift);
|
|
|
+ leftover = temp << bitright;
|
|
|
+ temp = *cp;
|
|
|
+ *cp = leftover | (temp >> bitshift);
|
|
|
}
|
|
|
|
|
|
if (host->mmc->use_spi_crc) {
|
|
@@ -803,7 +880,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
|
|
|
unsigned n_sg;
|
|
|
int multiple = (data->blocks > 1);
|
|
|
u32 clock_rate;
|
|
|
- ktime_t timeout;
|
|
|
+ unsigned long timeout;
|
|
|
|
|
|
if (data->flags & MMC_DATA_READ)
|
|
|
direction = DMA_FROM_DEVICE;
|
|
@@ -817,8 +894,9 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
|
|
|
else
|
|
|
clock_rate = spi->max_speed_hz;
|
|
|
|
|
|
- timeout = ktime_add_ns(ktime_set(0, 0), data->timeout_ns +
|
|
|
- data->timeout_clks * 1000000 / clock_rate);
|
|
|
+ timeout = data->timeout_ns +
|
|
|
+ data->timeout_clks * 1000000 / clock_rate;
|
|
|
+ timeout = usecs_to_jiffies((unsigned int)(timeout / 1000)) + 1;
|
|
|
|
|
|
/* Handle scatterlist segments one at a time, with synch for
|
|
|
* each 512-byte block
|