aboutsummaryrefslogtreecommitdiff
path: root/drivers/mmc/mmc_spi.c
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-02-19 11:56:14 -0500
committerTom Rini <trini@konsulko.com>2021-02-19 11:56:14 -0500
commita1a652e8016426e2d67148cab225cd5ec45189fb (patch)
treebe761ff6a8b75f866ea2ff21195d843becfacbc7 /drivers/mmc/mmc_spi.c
parent766927a7595a6f18fef460a06fdac370fd9e02cf (diff)
parent144d0574d5f3652008ef400e86cc66db5ef88736 (diff)
Merge tag 'mmc-2021-2-19' of https://gitlab.denx.de/u-boot/custodians/u-boot-mmc
- mmc_spi improvement - added mmc-pwrseq to remove duplicated code - fix response timeout after switch command - sdhci: skip cache invalidation if DMA is not used
Diffstat (limited to 'drivers/mmc/mmc_spi.c')
-rw-r--r--drivers/mmc/mmc_spi.c80
1 files changed, 59 insertions, 21 deletions
diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c
index 46800bbed2..e2d78794f2 100644
--- a/drivers/mmc/mmc_spi.c
+++ b/drivers/mmc/mmc_spi.c
@@ -37,7 +37,8 @@
#define SPI_RESPONSE_CRC_ERR ((5 << 1)|1)
#define SPI_RESPONSE_WRITE_ERR ((6 << 1)|1)
-/* Read and write blocks start with these tokens and end with crc;
+/*
+ * Read and write blocks start with these tokens and end with crc;
* on error, read tokens act like a subset of R2_SPI_* values.
*/
/* single block write multiblock read */
@@ -70,6 +71,20 @@ struct mmc_spi_priv {
struct spi_slave *spi;
};
+/**
+ * mmc_spi_sendcmd() - send a command to the SD card
+ *
+ * @dev: mmc_spi device
+ * @cmdidx: command index
+ * @cmdarg: command argument
+ * @resp_type: card response type
+ * @resp: buffer to store the card response
+ * @resp_size: size of the card response
+ * @resp_match: if true, compare each of received bytes with @resp_match_value
+ * @resp_match_value: a value to be compared with each of received bytes
+ * @r1b: if true, receive additional bytes for busy signal token
+ * @return 0 if OK, -ETIMEDOUT if no card response is received, -ve on error
+ */
static int mmc_spi_sendcmd(struct udevice *dev,
ushort cmdidx, u32 cmdarg, u32 resp_type,
u8 *resp, u32 resp_size,
@@ -78,6 +93,9 @@ static int mmc_spi_sendcmd(struct udevice *dev,
int i, rpos = 0, ret = 0;
u8 cmdo[7], r;
+ if (!resp || !resp_size)
+ return 0;
+
debug("%s: cmd%d cmdarg=0x%x resp_type=0x%x "
"resp_size=%d resp_match=%d resp_match_value=0x%x\n",
__func__, cmdidx, cmdarg, resp_type,
@@ -98,34 +116,33 @@ static int mmc_spi_sendcmd(struct udevice *dev,
if (ret)
return ret;
- if (!resp || !resp_size)
- return 0;
-
debug("%s: cmd%d", __func__, cmdidx);
- if (resp_match) {
+ if (resp_match)
r = ~resp_match_value;
- i = CMD_TIMEOUT;
- while (i) {
- ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
- if (ret)
- return ret;
- debug(" resp%d=0x%x", rpos, r);
- rpos++;
- i--;
+ i = CMD_TIMEOUT;
+ while (i) {
+ ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
+ if (ret)
+ return ret;
+ debug(" resp%d=0x%x", rpos, r);
+ rpos++;
+ i--;
+ if (resp_match) {
if (r == resp_match_value)
break;
+ } else {
+ if (!(r & 0x80))
+ break;
}
- if (!i && (r != resp_match_value))
+
+ if (!i)
return -ETIMEDOUT;
}
- for (i = 0; i < resp_size; i++) {
- if (i == 0 && resp_match) {
- resp[i] = resp_match_value;
- continue;
- }
+ resp[0] = r;
+ for (i = 1; i < resp_size; i++) {
ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
if (ret)
return ret;
@@ -157,6 +174,15 @@ static int mmc_spi_sendcmd(struct udevice *dev,
return 0;
}
+/**
+ * mmc_spi_readdata() - read data block(s) from the SD card
+ *
+ * @dev: mmc_spi device
+ * @xbuf: buffer of the actual data (excluding token and crc) to read
+ * @bcnt: number of data blocks to transfer
+ * @bsize: size of the actual data (excluding token and crc) in bytes
+ * @return 0 if OK, -ECOMM if crc error, -ETIMEDOUT on other errors
+ */
static int mmc_spi_readdata(struct udevice *dev,
void *xbuf, u32 bcnt, u32 bsize)
{
@@ -181,8 +207,10 @@ static int mmc_spi_readdata(struct udevice *dev,
if (ret)
return ret;
#ifdef CONFIG_MMC_SPI_CRC_ON
- if (be16_to_cpu(crc16_ccitt(0, buf, bsize)) != crc) {
- debug("%s: data crc error\n", __func__);
+ u16 crc_ok = be16_to_cpu(crc16_ccitt(0, buf, bsize));
+ if (crc_ok != crc) {
+ debug("%s: data crc error, expected %04x got %04x\n",
+ __func__, crc_ok, crc);
r1 = R1_SPI_COM_CRC;
break;
}
@@ -203,6 +231,16 @@ static int mmc_spi_readdata(struct udevice *dev,
return ret;
}
+/**
+ * mmc_spi_writedata() - write data block(s) to the SD card
+ *
+ * @dev: mmc_spi device
+ * @xbuf: buffer of the actual data (excluding token and crc) to write
+ * @bcnt: number of data blocks to transfer
+ * @bsize: size of actual data (excluding token and crc) in bytes
+ * @multi: indicate a transfer by multiple block write command (CMD25)
+ * @return 0 if OK, -ECOMM if crc error, -ETIMEDOUT on other errors
+ */
static int mmc_spi_writedata(struct udevice *dev, const void *xbuf,
u32 bcnt, u32 bsize, int multi)
{