All of lore.kernel.org
 help / color / mirror / Atom feed
* [PULL 00/18] SD/MMC patches for 2021-02-20
@ 2021-02-20  0:12 Philippe Mathieu-Daudé
  2021-02-20  0:12 ` [PULL 01/18] hw/sd: ssi-sd: Support multiple block read Philippe Mathieu-Daudé
                   ` (18 more replies)
  0 siblings, 19 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Bin Meng, Philippe Mathieu-Daudé, qemu-block

The following changes since commit e90ef02389dc8b57eaea22b290244609d720a8bf:

  Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-02-18' into staging (2021-02-19 17:22:42 +0000)

are available in the Git repository at:

  https://gitlab.com/philmd/qemu.git tags/sdmmc-20210220

for you to fetch changes up to 3e0a7693be30d6a6eda8a56f3862ac2e502a9e81:

  MAINTAINERS: Add Bin Meng as co-maintainer for SD/MMC cards (2021-02-20 01:08:59 +0100)

----------------------------------------------------------------
SD/MMC patches

- Various improvements for SD cards in SPI mode (Bin Meng)
- Add Bin Meng as SD/MMC cards co-maintainer
----------------------------------------------------------------

Bin Meng (17):
  hw/sd: ssi-sd: Support multiple block read
  hw/sd: sd: Remove duplicated codes in single/multiple block read/write
  hw/sd: sd: Allow single/multiple block write for SPI mode
  hw/sd: Introduce receive_ready() callback
  hw/sd: ssi-sd: Support single block write
  hw/sd: ssi-sd: Support multiple block write
  hw/sd: ssi-sd: Fix SEND_IF_COND (CMD8) response
  hw/sd: ssi-sd: Fix STOP_TRANSMISSION (CMD12) response
  hw/sd: ssi-sd: Handle the rest commands with R1b response type
  hw/sd: sd: Fix address check in sd_erase()
  hw/sd: sd: Only SDSC cards support CMD28/29/30
  hw/sd: sd: Fix CMD30 response type
  hw/sd: sd: Move the sd_block_{read, write} and macros ahead
  hw/sd: sd: Skip write protect groups check in sd_erase() for high
    capacity cards
  hw/sd: sd: Skip write protect groups check in CMD24/25 for high
    capacity cards
  hw/sd: sd: Bypass the RCA check for CMD13 in SPI mode
  hw/sd: sdhci: Simplify updating s->prnsts in
    sdhci_sdma_transfer_multi_blocks()

Philippe Mathieu-Daudé (1):
  MAINTAINERS: Add Bin Meng as co-maintainer for SD/MMC cards

 include/hw/sd/sd.h |   2 +
 hw/sd/core.c       |  13 ++++
 hw/sd/sd.c         | 149 +++++++++++++++++++--------------------------
 hw/sd/sdhci.c      |   7 +--
 hw/sd/ssi-sd.c     | 136 +++++++++++++++++++++++++++++++++++------
 MAINTAINERS        |   1 +
 6 files changed, 199 insertions(+), 109 deletions(-)

-- 
2.26.2



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

* [PULL 01/18] hw/sd: ssi-sd: Support multiple block read
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
@ 2021-02-20  0:12 ` Philippe Mathieu-Daudé
  2021-02-20  0:12 ` [PULL 02/18] hw/sd: sd: Remove duplicated codes in single/multiple block read/write Philippe Mathieu-Daudé
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bin Meng, Alistair Francis, Philippe Mathieu-Daudé, qemu-block

From: Bin Meng <bin.meng@windriver.com>

In the case of a multiple block read operation every transferred
block has its suffix of CRC16. Update the state machine logic to
handle multiple block read.

Signed-off-by: Bin Meng <bin.meng@windriver.com>
[PMD: Change VMState version id 5 -> 6]
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Message-Id: <20210128063035.15674-2-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/ssi-sd.c | 42 +++++++++++++++++++++++++++++++++---------
 1 file changed, 33 insertions(+), 9 deletions(-)

diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index be1bb101645..6d20a240c69 100644
--- a/hw/sd/ssi-sd.c
+++ b/hw/sd/ssi-sd.c
@@ -52,6 +52,7 @@ struct ssi_sd_state {
     uint8_t cmdarg[4];
     uint8_t response[5];
     uint16_t crc16;
+    int32_t read_bytes;
     int32_t arglen;
     int32_t response_pos;
     int32_t stopping;
@@ -88,11 +89,26 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val)
 {
     ssi_sd_state *s = SSI_SD(dev);
 
-    /* Special case: allow CMD12 (STOP TRANSMISSION) while reading data.  */
-    if (s->mode == SSI_SD_DATA_READ && val == 0x4c) {
-        s->mode = SSI_SD_CMD;
-        /* There must be at least one byte delay before the card responds.  */
-        s->stopping = 1;
+    /*
+     * Special case: allow CMD12 (STOP TRANSMISSION) while reading data.
+     *
+     * See "Physical Layer Specification Version 8.00" chapter 7.5.2.2,
+     * to avoid conflict between CMD12 response and next data block,
+     * timing of CMD12 should be controlled as follows:
+     *
+     * - CMD12 issued at the timing that end bit of CMD12 and end bit of
+     *   data block is overlapped
+     * - CMD12 issued after one clock cycle after host receives a token
+     *   (either Start Block token or Data Error token)
+     *
+     * We need to catch CMD12 in all of the data read states.
+     */
+    if (s->mode >= SSI_SD_PREP_DATA && s->mode <= SSI_SD_DATA_CRC16) {
+        if (val == 0x4c) {
+            s->mode = SSI_SD_CMD;
+            /* There must be at least one byte delay before the card responds */
+            s->stopping = 1;
+        }
     }
 
     switch (s->mode) {
@@ -212,8 +228,9 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val)
         return SSI_TOKEN_SINGLE;
     case SSI_SD_DATA_READ:
         val = sdbus_read_byte(&s->sdbus);
+        s->read_bytes++;
         s->crc16 = crc_ccitt_false(s->crc16, (uint8_t *)&val, 1);
-        if (!sdbus_data_ready(&s->sdbus)) {
+        if (!sdbus_data_ready(&s->sdbus) || s->read_bytes == 512) {
             DPRINTF("Data read end\n");
             s->mode = SSI_SD_DATA_CRC16;
         }
@@ -224,7 +241,12 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val)
         s->response_pos++;
         if (s->response_pos == 2) {
             DPRINTF("CRC16 read end\n");
-            s->mode = SSI_SD_CMD;
+            if (s->read_bytes == 512 && s->cmd != 17) {
+                s->mode = SSI_SD_PREP_DATA;
+            } else {
+                s->mode = SSI_SD_CMD;
+            }
+            s->read_bytes = 0;
             s->response_pos = 0;
         }
         return val;
@@ -255,8 +277,8 @@ static int ssi_sd_post_load(void *opaque, int version_id)
 
 static const VMStateDescription vmstate_ssi_sd = {
     .name = "ssi_sd",
-    .version_id = 5,
-    .minimum_version_id = 5,
+    .version_id = 6,
+    .minimum_version_id = 6,
     .post_load = ssi_sd_post_load,
     .fields = (VMStateField []) {
         VMSTATE_UINT32(mode, ssi_sd_state),
@@ -264,6 +286,7 @@ static const VMStateDescription vmstate_ssi_sd = {
         VMSTATE_UINT8_ARRAY(cmdarg, ssi_sd_state, 4),
         VMSTATE_UINT8_ARRAY(response, ssi_sd_state, 5),
         VMSTATE_UINT16(crc16, ssi_sd_state),
+        VMSTATE_INT32(read_bytes, ssi_sd_state),
         VMSTATE_INT32(arglen, ssi_sd_state),
         VMSTATE_INT32(response_pos, ssi_sd_state),
         VMSTATE_INT32(stopping, ssi_sd_state),
@@ -316,6 +339,7 @@ static void ssi_sd_reset(DeviceState *dev)
     memset(s->cmdarg, 0, sizeof(s->cmdarg));
     memset(s->response, 0, sizeof(s->response));
     s->crc16 = 0;
+    s->read_bytes = 0;
     s->arglen = 0;
     s->response_pos = 0;
     s->stopping = 0;
-- 
2.26.2



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

* [PULL 02/18] hw/sd: sd: Remove duplicated codes in single/multiple block read/write
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
  2021-02-20  0:12 ` [PULL 01/18] hw/sd: ssi-sd: Support multiple block read Philippe Mathieu-Daudé
@ 2021-02-20  0:12 ` Philippe Mathieu-Daudé
  2021-02-20  0:12 ` [PULL 03/18] hw/sd: sd: Allow single/multiple block write for SPI mode Philippe Mathieu-Daudé
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bin Meng, Alistair Francis, Philippe Mathieu-Daudé, qemu-block

From: Bin Meng <bin.meng@windriver.com>

The single block read (CMD17) codes are the same as the multiple
block read (CMD18). Merge them into one. The same applies to single
block write (CMD24) and multiple block write (CMD25).

Signed-off-by: Bin Meng <bin.meng@windriver.com>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Message-Id: <20210128063035.15674-3-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/sd.c | 47 -----------------------------------------------
 1 file changed, 47 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 8517dbce8ba..a85a821abbe 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1181,24 +1181,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
         break;
 
     case 17:	/* CMD17:  READ_SINGLE_BLOCK */
-        switch (sd->state) {
-        case sd_transfer_state:
-
-            if (addr + sd->blk_len > sd->size) {
-                sd->card_status |= ADDRESS_ERROR;
-                return sd_r1;
-            }
-
-            sd->state = sd_sendingdata_state;
-            sd->data_start = addr;
-            sd->data_offset = 0;
-            return sd_r1;
-
-        default:
-            break;
-        }
-        break;
-
     case 18:	/* CMD18:  READ_MULTIPLE_BLOCK */
         switch (sd->state) {
         case sd_transfer_state:
@@ -1245,35 +1227,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 
     /* Block write commands (Class 4) */
     case 24:	/* CMD24:  WRITE_SINGLE_BLOCK */
-        switch (sd->state) {
-        case sd_transfer_state:
-            /* Writing in SPI mode not implemented.  */
-            if (sd->spi)
-                break;
-
-            if (addr + sd->blk_len > sd->size) {
-                sd->card_status |= ADDRESS_ERROR;
-                return sd_r1;
-            }
-
-            sd->state = sd_receivingdata_state;
-            sd->data_start = addr;
-            sd->data_offset = 0;
-            sd->blk_written = 0;
-
-            if (sd_wp_addr(sd, sd->data_start)) {
-                sd->card_status |= WP_VIOLATION;
-            }
-            if (sd->csd[14] & 0x30) {
-                sd->card_status |= WP_VIOLATION;
-            }
-            return sd_r1;
-
-        default:
-            break;
-        }
-        break;
-
     case 25:	/* CMD25:  WRITE_MULTIPLE_BLOCK */
         switch (sd->state) {
         case sd_transfer_state:
-- 
2.26.2



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

* [PULL 03/18] hw/sd: sd: Allow single/multiple block write for SPI mode
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
  2021-02-20  0:12 ` [PULL 01/18] hw/sd: ssi-sd: Support multiple block read Philippe Mathieu-Daudé
  2021-02-20  0:12 ` [PULL 02/18] hw/sd: sd: Remove duplicated codes in single/multiple block read/write Philippe Mathieu-Daudé
@ 2021-02-20  0:12 ` Philippe Mathieu-Daudé
  2021-02-20  0:12 ` [PULL 04/18] hw/sd: Introduce receive_ready() callback Philippe Mathieu-Daudé
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bin Meng, Alistair Francis, Philippe Mathieu-Daudé, qemu-block

From: Bin Meng <bin.meng@windriver.com>

At present the single/multiple block write in SPI mode is blocked
by sd_normal_command(). Remove the limitation.

Signed-off-by: Bin Meng <bin.meng@windriver.com>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20210128063035.15674-4-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/sd.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index a85a821abbe..5de9e0a6c20 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1230,9 +1230,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
     case 25:	/* CMD25:  WRITE_MULTIPLE_BLOCK */
         switch (sd->state) {
         case sd_transfer_state:
-            /* Writing in SPI mode not implemented.  */
-            if (sd->spi)
-                break;
 
             if (addr + sd->blk_len > sd->size) {
                 sd->card_status |= ADDRESS_ERROR;
-- 
2.26.2



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

* [PULL 04/18] hw/sd: Introduce receive_ready() callback
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
                   ` (2 preceding siblings ...)
  2021-02-20  0:12 ` [PULL 03/18] hw/sd: sd: Allow single/multiple block write for SPI mode Philippe Mathieu-Daudé
@ 2021-02-20  0:12 ` Philippe Mathieu-Daudé
  2021-02-20  0:12 ` [PULL 05/18] hw/sd: ssi-sd: Support single block write Philippe Mathieu-Daudé
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bin Meng, Alistair Francis, Philippe Mathieu-Daudé, qemu-block

From: Bin Meng <bin.meng@windriver.com>

At present there is a data_ready() callback for the SD data read
path. Let's add a receive_ready() for the SD data write path.

Signed-off-by: Bin Meng <bin.meng@windriver.com>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Message-Id: <20210128063035.15674-5-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 include/hw/sd/sd.h |  2 ++
 hw/sd/core.c       | 13 +++++++++++++
 hw/sd/sd.c         |  6 ++++++
 3 files changed, 21 insertions(+)

diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index 05ef9b73e56..47360ba4ee9 100644
--- a/include/hw/sd/sd.h
+++ b/include/hw/sd/sd.h
@@ -116,6 +116,7 @@ struct SDCardClass {
      * Return: byte value read
      */
     uint8_t (*read_byte)(SDState *sd);
+    bool (*receive_ready)(SDState *sd);
     bool (*data_ready)(SDState *sd);
     void (*set_voltage)(SDState *sd, uint16_t millivolts);
     uint8_t (*get_dat_lines)(SDState *sd);
@@ -187,6 +188,7 @@ void sdbus_write_data(SDBus *sdbus, const void *buf, size_t length);
  * Read multiple bytes of data on the data lines of a SD bus.
  */
 void sdbus_read_data(SDBus *sdbus, void *buf, size_t length);
+bool sdbus_receive_ready(SDBus *sd);
 bool sdbus_data_ready(SDBus *sd);
 bool sdbus_get_inserted(SDBus *sd);
 bool sdbus_get_readonly(SDBus *sd);
diff --git a/hw/sd/core.c b/hw/sd/core.c
index 08c93b59034..30ee62c5106 100644
--- a/hw/sd/core.c
+++ b/hw/sd/core.c
@@ -160,6 +160,19 @@ void sdbus_read_data(SDBus *sdbus, void *buf, size_t length)
     }
 }
 
+bool sdbus_receive_ready(SDBus *sdbus)
+{
+    SDState *card = get_card(sdbus);
+
+    if (card) {
+        SDCardClass *sc = SD_CARD_GET_CLASS(card);
+
+        return sc->receive_ready(card);
+    }
+
+    return false;
+}
+
 bool sdbus_data_ready(SDBus *sdbus)
 {
     SDState *card = get_card(sdbus);
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 5de9e0a6c20..172e83f99d9 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -2037,6 +2037,11 @@ uint8_t sd_read_byte(SDState *sd)
     return ret;
 }
 
+static bool sd_receive_ready(SDState *sd)
+{
+    return sd->state == sd_receivingdata_state;
+}
+
 static bool sd_data_ready(SDState *sd)
 {
     return sd->state == sd_sendingdata_state;
@@ -2147,6 +2152,7 @@ static void sd_class_init(ObjectClass *klass, void *data)
     sc->do_command = sd_do_command;
     sc->write_byte = sd_write_byte;
     sc->read_byte = sd_read_byte;
+    sc->receive_ready = sd_receive_ready;
     sc->data_ready = sd_data_ready;
     sc->enable = sd_enable;
     sc->get_inserted = sd_get_inserted;
-- 
2.26.2



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

* [PULL 05/18] hw/sd: ssi-sd: Support single block write
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
                   ` (3 preceding siblings ...)
  2021-02-20  0:12 ` [PULL 04/18] hw/sd: Introduce receive_ready() callback Philippe Mathieu-Daudé
@ 2021-02-20  0:12 ` Philippe Mathieu-Daudé
  2021-02-20  0:12 ` [PULL 06/18] hw/sd: ssi-sd: Support multiple " Philippe Mathieu-Daudé
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bin Meng, Alistair Francis, Philippe Mathieu-Daudé, qemu-block

From: Bin Meng <bin.meng@windriver.com>

Add 2 more states for the block write operation. The SPI host needs
to send a data start token to start the transfer, and the data block
written to the card will be acknowledged by a data response token.

Signed-off-by: Bin Meng <bin.meng@windriver.com>
[PMD: Change VMState version id 6 -> 7]
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Message-Id: <20210128063035.15674-6-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/ssi-sd.c | 44 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 40 insertions(+), 4 deletions(-)

diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index 6d20a240c69..1205ad8b52c 100644
--- a/hw/sd/ssi-sd.c
+++ b/hw/sd/ssi-sd.c
@@ -43,6 +43,8 @@ typedef enum {
     SSI_SD_DATA_START,
     SSI_SD_DATA_READ,
     SSI_SD_DATA_CRC16,
+    SSI_SD_DATA_WRITE,
+    SSI_SD_SKIP_CRC16,
 } ssi_sd_mode;
 
 struct ssi_sd_state {
@@ -53,6 +55,7 @@ struct ssi_sd_state {
     uint8_t response[5];
     uint16_t crc16;
     int32_t read_bytes;
+    int32_t write_bytes;
     int32_t arglen;
     int32_t response_pos;
     int32_t stopping;
@@ -85,6 +88,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(ssi_sd_state, SSI_SD)
 /* dummy value - don't care */
 #define SSI_DUMMY               0xff
 
+/* data accepted */
+#define DATA_RESPONSE_ACCEPTED  0x05
+
 static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val)
 {
     ssi_sd_state *s = SSI_SD(dev);
@@ -113,10 +119,17 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val)
 
     switch (s->mode) {
     case SSI_SD_CMD:
-        if (val == SSI_DUMMY) {
+        switch (val) {
+        case SSI_DUMMY:
             DPRINTF("NULL command\n");
             return SSI_DUMMY;
+            break;
+        case SSI_TOKEN_SINGLE:
+            DPRINTF("Start write block\n");
+            s->mode = SSI_SD_DATA_WRITE;
+            return SSI_DUMMY;
         }
+
         s->cmd = val & 0x3f;
         s->mode = SSI_SD_CMDARG;
         s->arglen = 0;
@@ -250,6 +263,27 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val)
             s->response_pos = 0;
         }
         return val;
+    case SSI_SD_DATA_WRITE:
+        sdbus_write_byte(&s->sdbus, val);
+        s->write_bytes++;
+        if (!sdbus_receive_ready(&s->sdbus) || s->write_bytes == 512) {
+            DPRINTF("Data write end\n");
+            s->mode = SSI_SD_SKIP_CRC16;
+            s->response_pos = 0;
+        }
+        return val;
+    case SSI_SD_SKIP_CRC16:
+        /* we don't verify the crc16 */
+        s->response_pos++;
+        if (s->response_pos == 2) {
+            DPRINTF("CRC16 receive end\n");
+            s->mode = SSI_SD_RESPONSE;
+            s->write_bytes = 0;
+            s->arglen = 1;
+            s->response[0] = DATA_RESPONSE_ACCEPTED;
+            s->response_pos = 0;
+        }
+        return SSI_DUMMY;
     }
     /* Should never happen.  */
     return SSI_DUMMY;
@@ -259,7 +293,7 @@ static int ssi_sd_post_load(void *opaque, int version_id)
 {
     ssi_sd_state *s = (ssi_sd_state *)opaque;
 
-    if (s->mode > SSI_SD_DATA_CRC16) {
+    if (s->mode > SSI_SD_SKIP_CRC16) {
         return -EINVAL;
     }
     if (s->mode == SSI_SD_CMDARG &&
@@ -277,8 +311,8 @@ static int ssi_sd_post_load(void *opaque, int version_id)
 
 static const VMStateDescription vmstate_ssi_sd = {
     .name = "ssi_sd",
-    .version_id = 6,
-    .minimum_version_id = 6,
+    .version_id = 7,
+    .minimum_version_id = 7,
     .post_load = ssi_sd_post_load,
     .fields = (VMStateField []) {
         VMSTATE_UINT32(mode, ssi_sd_state),
@@ -287,6 +321,7 @@ static const VMStateDescription vmstate_ssi_sd = {
         VMSTATE_UINT8_ARRAY(response, ssi_sd_state, 5),
         VMSTATE_UINT16(crc16, ssi_sd_state),
         VMSTATE_INT32(read_bytes, ssi_sd_state),
+        VMSTATE_INT32(write_bytes, ssi_sd_state),
         VMSTATE_INT32(arglen, ssi_sd_state),
         VMSTATE_INT32(response_pos, ssi_sd_state),
         VMSTATE_INT32(stopping, ssi_sd_state),
@@ -340,6 +375,7 @@ static void ssi_sd_reset(DeviceState *dev)
     memset(s->response, 0, sizeof(s->response));
     s->crc16 = 0;
     s->read_bytes = 0;
+    s->write_bytes = 0;
     s->arglen = 0;
     s->response_pos = 0;
     s->stopping = 0;
-- 
2.26.2



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

* [PULL 06/18] hw/sd: ssi-sd: Support multiple block write
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
                   ` (4 preceding siblings ...)
  2021-02-20  0:12 ` [PULL 05/18] hw/sd: ssi-sd: Support single block write Philippe Mathieu-Daudé
@ 2021-02-20  0:12 ` Philippe Mathieu-Daudé
  2021-02-20  0:12 ` [PULL 07/18] hw/sd: ssi-sd: Fix SEND_IF_COND (CMD8) response Philippe Mathieu-Daudé
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bin Meng, Alistair Francis, Philippe Mathieu-Daudé, qemu-block

From: Bin Meng <bin.meng@windriver.com>

For a multiple block write operation, each block begins with a multi
write start token. Unlike the SD mode that the multiple block write
ends when receiving a STOP_TRAN command (CMD12), a special stop tran
token is used to signal the card.

Emulating this by manually sending a CMD12 to the SD card core, to
bring it out of the receiving data state.

Signed-off-by: Bin Meng <bin.meng@windriver.com>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Message-Id: <20210128063035.15674-7-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/ssi-sd.c | 33 +++++++++++++++++++++++++++++++--
 1 file changed, 31 insertions(+), 2 deletions(-)

diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index 1205ad8b52c..200e885225a 100644
--- a/hw/sd/ssi-sd.c
+++ b/hw/sd/ssi-sd.c
@@ -4,6 +4,11 @@
  * Copyright (c) 2007-2009 CodeSourcery.
  * Written by Paul Brook
  *
+ * Copyright (c) 2021 Wind River Systems, Inc.
+ * Improved by Bin Meng <bin.meng@windriver.com>
+ *
+ * Validated with U-Boot v2021.01 and Linux v5.10 mmc_spi driver
+ *
  * This code is licensed under the GNU GPL v2.
  *
  * Contributions after 2012-01-13 are licensed under the terms of the
@@ -82,6 +87,10 @@ OBJECT_DECLARE_SIMPLE_TYPE(ssi_sd_state, SSI_SD)
 #define SSI_SDR_ADDRESS_ERROR   0x2000
 #define SSI_SDR_PARAMETER_ERROR 0x4000
 
+/* multiple block write */
+#define SSI_TOKEN_MULTI_WRITE   0xfc
+/* terminate multiple block write */
+#define SSI_TOKEN_STOP_TRAN     0xfd
 /* single block read/write, multiple block read */
 #define SSI_TOKEN_SINGLE        0xfe
 
@@ -94,6 +103,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(ssi_sd_state, SSI_SD)
 static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val)
 {
     ssi_sd_state *s = SSI_SD(dev);
+    SDRequest request;
+    uint8_t longresp[16];
 
     /*
      * Special case: allow CMD12 (STOP TRANSMISSION) while reading data.
@@ -125,8 +136,28 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val)
             return SSI_DUMMY;
             break;
         case SSI_TOKEN_SINGLE:
+        case SSI_TOKEN_MULTI_WRITE:
             DPRINTF("Start write block\n");
             s->mode = SSI_SD_DATA_WRITE;
+            return SSI_DUMMY;
+        case SSI_TOKEN_STOP_TRAN:
+            DPRINTF("Stop multiple write\n");
+
+            /* manually issue cmd12 to stop the transfer */
+            request.cmd = 12;
+            request.arg = 0;
+            s->arglen = sdbus_do_command(&s->sdbus, &request, longresp);
+            if (s->arglen <= 0) {
+                s->arglen = 1;
+                /* a zero value indicates the card is busy */
+                s->response[0] = 0;
+                DPRINTF("SD card busy\n");
+            } else {
+                s->arglen = 1;
+                /* a non-zero value indicates the card is ready */
+                s->response[0] = SSI_DUMMY;
+            }
+
             return SSI_DUMMY;
         }
 
@@ -136,8 +167,6 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val)
         return SSI_DUMMY;
     case SSI_SD_CMDARG:
         if (s->arglen == 4) {
-            SDRequest request;
-            uint8_t longresp[16];
             /* FIXME: Check CRC.  */
             request.cmd = s->cmd;
             request.arg = ldl_be_p(s->cmdarg);
-- 
2.26.2



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

* [PULL 07/18] hw/sd: ssi-sd: Fix SEND_IF_COND (CMD8) response
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
                   ` (5 preceding siblings ...)
  2021-02-20  0:12 ` [PULL 06/18] hw/sd: ssi-sd: Support multiple " Philippe Mathieu-Daudé
@ 2021-02-20  0:12 ` Philippe Mathieu-Daudé
  2021-02-20  0:12 ` [PULL 08/18] hw/sd: ssi-sd: Fix STOP_TRANSMISSION (CMD12) response Philippe Mathieu-Daudé
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Bin Meng, Philippe Mathieu-Daudé, qemu-block

From: Bin Meng <bin.meng@windriver.com>

The SEND_IF_COND command (CMD8) response is of format R7, but
current code returns R1 for CMD8. Fix it.

Fixes: 775616c3ae8c ("Partial SD card SPI mode support")
Signed-off-by: Bin Meng <bin.meng@windriver.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20210128063035.15674-8-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/ssi-sd.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index 200e885225a..84c873b3fd4 100644
--- a/hw/sd/ssi-sd.c
+++ b/hw/sd/ssi-sd.c
@@ -176,9 +176,9 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val)
                 s->arglen = 1;
                 s->response[0] = 4;
                 DPRINTF("SD command failed\n");
-            } else if (s->cmd == 58) {
-                /* CMD58 returns R3 response (OCR)  */
-                DPRINTF("Returned OCR\n");
+            } else if (s->cmd == 8 || s->cmd == 58) {
+                /* CMD8/CMD58 returns R3/R7 response */
+                DPRINTF("Returned R3/R7\n");
                 s->arglen = 5;
                 s->response[0] = 1;
                 memcpy(&s->response[1], longresp, 4);
-- 
2.26.2



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

* [PULL 08/18] hw/sd: ssi-sd: Fix STOP_TRANSMISSION (CMD12) response
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
                   ` (6 preceding siblings ...)
  2021-02-20  0:12 ` [PULL 07/18] hw/sd: ssi-sd: Fix SEND_IF_COND (CMD8) response Philippe Mathieu-Daudé
@ 2021-02-20  0:12 ` Philippe Mathieu-Daudé
  2021-02-20  0:13 ` [PULL 09/18] hw/sd: ssi-sd: Handle the rest commands with R1b response type Philippe Mathieu-Daudé
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Bin Meng, Philippe Mathieu-Daudé, qemu-block

From: Bin Meng <bin.meng@windriver.com>

CMD12's response type is R1b, which is basically a R1 plus optional
addition of the busy signal token that can be any number of bytes.
A zero value indicates card is busy and a non-zero value indicates
the card is ready for the next command.

Current implementation sends the busy signal token without sending
the R1 first. This does not break the U-Boot/Linux mmc_spi driver,
but it does not make the VxWorks driver happy.

Move the testing logic of s->stopping in the SSI_SD_RESPONSE state
a bit later, after the first byte of the card reponse is sent out,
to conform with the spec. After the busy signal token is sent, the
state should be transferred to SSI_SD_CMD.

Fixes: 775616c3ae8c ("Partial SD card SPI mode support")
Signed-off-by: Bin Meng <bin.meng@windriver.com>
Message-Id: <20210128063035.15674-9-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/ssi-sd.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index 84c873b3fd4..907d681d19e 100644
--- a/hw/sd/ssi-sd.c
+++ b/hw/sd/ssi-sd.c
@@ -243,14 +243,15 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val)
         s->mode = SSI_SD_RESPONSE;
         return SSI_DUMMY;
     case SSI_SD_RESPONSE:
-        if (s->stopping) {
-            s->stopping = 0;
-            return SSI_DUMMY;
-        }
         if (s->response_pos < s->arglen) {
             DPRINTF("Response 0x%02x\n", s->response[s->response_pos]);
             return s->response[s->response_pos++];
         }
+        if (s->stopping) {
+            s->stopping = 0;
+            s->mode = SSI_SD_CMD;
+            return SSI_DUMMY;
+        }
         if (sdbus_data_ready(&s->sdbus)) {
             DPRINTF("Data read\n");
             s->mode = SSI_SD_DATA_START;
-- 
2.26.2



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

* [PULL 09/18] hw/sd: ssi-sd: Handle the rest commands with R1b response type
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
                   ` (7 preceding siblings ...)
  2021-02-20  0:12 ` [PULL 08/18] hw/sd: ssi-sd: Fix STOP_TRANSMISSION (CMD12) response Philippe Mathieu-Daudé
@ 2021-02-20  0:13 ` Philippe Mathieu-Daudé
  2021-02-20  0:13 ` [PULL 10/18] hw/sd: sd: Fix address check in sd_erase() Philippe Mathieu-Daudé
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: Bin Meng, Philippe Mathieu-Daudé, qemu-block

From: Bin Meng <bin.meng@windriver.com>

Besides CMD12, the following command's reponse type is R1b:

- SET_WRITE_PROT (CMD28)
- CLR_WRITE_PROT (CMD29)
- ERASE (CMD38)

Reuse the same s->stopping to indicate a R1b reponse is needed.

Signed-off-by: Bin Meng <bin.meng@windriver.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20210128063035.15674-10-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/ssi-sd.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index 907d681d19e..97ee58e20cf 100644
--- a/hw/sd/ssi-sd.c
+++ b/hw/sd/ssi-sd.c
@@ -194,6 +194,12 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val)
                 /* CMD13 returns a 2-byte statuse work. Other commands
                    only return the first byte.  */
                 s->arglen = (s->cmd == 13) ? 2 : 1;
+
+                /* handle R1b */
+                if (s->cmd == 28 || s->cmd == 29 || s->cmd == 38) {
+                    s->stopping = 1;
+                }
+
                 cardstatus = ldl_be_p(longresp);
                 status = 0;
                 if (((cardstatus >> 9) & 0xf) < 4)
-- 
2.26.2



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

* [PULL 10/18] hw/sd: sd: Fix address check in sd_erase()
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
                   ` (8 preceding siblings ...)
  2021-02-20  0:13 ` [PULL 09/18] hw/sd: ssi-sd: Handle the rest commands with R1b response type Philippe Mathieu-Daudé
@ 2021-02-20  0:13 ` Philippe Mathieu-Daudé
  2021-02-20  0:13 ` [PULL 11/18] hw/sd: sd: Only SDSC cards support CMD28/29/30 Philippe Mathieu-Daudé
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: Bin Meng, Philippe Mathieu-Daudé, qemu-block

From: Bin Meng <bin.meng@windriver.com>

For high capacity memory cards, the erase start address and end
address are multiplied by 512, but the address check is still
based on the original block number in sd->erase_{start, end}.

Fixes: 1bd6fd8ed593 ("hw/sd/sdcard: Do not attempt to erase out of range addresses")
Signed-off-by: Bin Meng <bin.meng@windriver.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20210216150225.27996-2-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/sd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 172e83f99d9..7adcb4edfaa 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -760,7 +760,7 @@ static void sd_erase(SDState *sd)
         erase_end *= 512;
     }
 
-    if (sd->erase_start > sd->size || sd->erase_end > sd->size) {
+    if (erase_start > sd->size || erase_end > sd->size) {
         sd->card_status |= OUT_OF_RANGE;
         sd->erase_start = INVALID_ADDRESS;
         sd->erase_end = INVALID_ADDRESS;
-- 
2.26.2



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

* [PULL 11/18] hw/sd: sd: Only SDSC cards support CMD28/29/30
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
                   ` (9 preceding siblings ...)
  2021-02-20  0:13 ` [PULL 10/18] hw/sd: sd: Fix address check in sd_erase() Philippe Mathieu-Daudé
@ 2021-02-20  0:13 ` Philippe Mathieu-Daudé
  2021-02-20  0:13 ` [PULL 12/18] hw/sd: sd: Fix CMD30 response type Philippe Mathieu-Daudé
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: Bin Meng, Philippe Mathieu-Daudé, qemu-block

From: Bin Meng <bin.meng@windriver.com>

Per the "Physical Layer Specification Version 8.00", table 4-26
(SD mode) and table 7-3 (SPI mode) command descriptions, the
following commands:

- CMD28 (SET_WRITE_PROT)
- CMD29 (CLR_WRITE_PROT)
- CMD30 (SEND_WRITE_PROT)

are only supported by SDSC cards.

Signed-off-by: Bin Meng <bin.meng@windriver.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20210216150225.27996-3-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/sd.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 7adcb4edfaa..dd1ce0bdae4 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1284,6 +1284,10 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 
     /* Write protection (Class 6) */
     case 28:	/* CMD28:  SET_WRITE_PROT */
+        if (sd->size > SDSC_MAX_CAPACITY) {
+            return sd_illegal;
+        }
+
         switch (sd->state) {
         case sd_transfer_state:
             if (addr >= sd->size) {
@@ -1303,6 +1307,10 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
         break;
 
     case 29:	/* CMD29:  CLR_WRITE_PROT */
+        if (sd->size > SDSC_MAX_CAPACITY) {
+            return sd_illegal;
+        }
+
         switch (sd->state) {
         case sd_transfer_state:
             if (addr >= sd->size) {
@@ -1322,6 +1330,10 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
         break;
 
     case 30:	/* CMD30:  SEND_WRITE_PROT */
+        if (sd->size > SDSC_MAX_CAPACITY) {
+            return sd_illegal;
+        }
+
         switch (sd->state) {
         case sd_transfer_state:
             sd->state = sd_sendingdata_state;
-- 
2.26.2



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

* [PULL 12/18] hw/sd: sd: Fix CMD30 response type
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
                   ` (10 preceding siblings ...)
  2021-02-20  0:13 ` [PULL 11/18] hw/sd: sd: Only SDSC cards support CMD28/29/30 Philippe Mathieu-Daudé
@ 2021-02-20  0:13 ` Philippe Mathieu-Daudé
  2021-02-20  0:13 ` [PULL 13/18] hw/sd: sd: Move the sd_block_{read, write} and macros ahead Philippe Mathieu-Daudé
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: Bin Meng, Philippe Mathieu-Daudé, qemu-block

From: Bin Meng <bin.meng@windriver.com>

Per the "Physical Layer Specification Version 8.00", table 4-26
(SD mode) and table 7-3 (SPI mode) command descriptions, CMD30
response type is R1, not R1b.

Fixes: a1bb27b1e98a ("SD card emulation initial implementation")
Signed-off-by: Bin Meng <bin.meng@windriver.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20210216150225.27996-4-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/sd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index dd1ce0bdae4..47ac0c51a8e 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1340,7 +1340,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
             *(uint32_t *) sd->data = sd_wpbits(sd, req.arg);
             sd->data_start = addr;
             sd->data_offset = 0;
-            return sd_r1b;
+            return sd_r1;
 
         default:
             break;
-- 
2.26.2



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

* [PULL 13/18] hw/sd: sd: Move the sd_block_{read, write} and macros ahead
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
                   ` (11 preceding siblings ...)
  2021-02-20  0:13 ` [PULL 12/18] hw/sd: sd: Fix CMD30 response type Philippe Mathieu-Daudé
@ 2021-02-20  0:13 ` Philippe Mathieu-Daudé
  2021-02-20  0:13 ` [PULL 14/18] hw/sd: sd: Skip write protect groups check in sd_erase() for high capacity cards Philippe Mathieu-Daudé
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: Bin Meng, Philippe Mathieu-Daudé, qemu-block

From: Bin Meng <bin.meng@windriver.com>

These APIs and macros may be referenced by functions that are
currently before them. Move them ahead a little bit.

Signed-off-by: Bin Meng <bin.meng@windriver.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20210216150225.27996-5-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/sd.c | 42 +++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 47ac0c51a8e..4c6e7c2a33e 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -739,6 +739,27 @@ void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert)
     qemu_set_irq(insert, sd->blk ? blk_is_inserted(sd->blk) : 0);
 }
 
+static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len)
+{
+    trace_sdcard_read_block(addr, len);
+    if (!sd->blk || blk_pread(sd->blk, addr, sd->data, len) < 0) {
+        fprintf(stderr, "sd_blk_read: read error on host side\n");
+    }
+}
+
+static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len)
+{
+    trace_sdcard_write_block(addr, len);
+    if (!sd->blk || blk_pwrite(sd->blk, addr, sd->data, len, 0) < 0) {
+        fprintf(stderr, "sd_blk_write: write error on host side\n");
+    }
+}
+
+#define BLK_READ_BLOCK(a, len)  sd_blk_read(sd, a, len)
+#define BLK_WRITE_BLOCK(a, len) sd_blk_write(sd, a, len)
+#define APP_READ_BLOCK(a, len)  memset(sd->data, 0xec, len)
+#define APP_WRITE_BLOCK(a, len)
+
 static void sd_erase(SDState *sd)
 {
     int i;
@@ -1754,27 +1775,6 @@ send_response:
     return rsplen;
 }
 
-static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len)
-{
-    trace_sdcard_read_block(addr, len);
-    if (!sd->blk || blk_pread(sd->blk, addr, sd->data, len) < 0) {
-        fprintf(stderr, "sd_blk_read: read error on host side\n");
-    }
-}
-
-static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len)
-{
-    trace_sdcard_write_block(addr, len);
-    if (!sd->blk || blk_pwrite(sd->blk, addr, sd->data, len, 0) < 0) {
-        fprintf(stderr, "sd_blk_write: write error on host side\n");
-    }
-}
-
-#define BLK_READ_BLOCK(a, len)	sd_blk_read(sd, a, len)
-#define BLK_WRITE_BLOCK(a, len)	sd_blk_write(sd, a, len)
-#define APP_READ_BLOCK(a, len)	memset(sd->data, 0xec, len)
-#define APP_WRITE_BLOCK(a, len)
-
 void sd_write_byte(SDState *sd, uint8_t value)
 {
     int i;
-- 
2.26.2



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

* [PULL 14/18] hw/sd: sd: Skip write protect groups check in sd_erase() for high capacity cards
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
                   ` (12 preceding siblings ...)
  2021-02-20  0:13 ` [PULL 13/18] hw/sd: sd: Move the sd_block_{read, write} and macros ahead Philippe Mathieu-Daudé
@ 2021-02-20  0:13 ` Philippe Mathieu-Daudé
  2021-02-20  0:13 ` [PULL 15/18] hw/sd: sd: Skip write protect groups check in CMD24/25 " Philippe Mathieu-Daudé
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: Bin Meng, Philippe Mathieu-Daudé, qemu-block

From: Bin Meng <bin.meng@windriver.com>

High capacity cards don't support write protection hence we should
not perform the write protect groups check in sd_erase() for them.

Signed-off-by: Bin Meng <bin.meng@windriver.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20210216150225.27996-6-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/sd.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 4c6e7c2a33e..883c04de028 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -765,6 +765,7 @@ static void sd_erase(SDState *sd)
     int i;
     uint64_t erase_start = sd->erase_start;
     uint64_t erase_end = sd->erase_end;
+    bool sdsc = true;
 
     trace_sdcard_erase(sd->erase_start, sd->erase_end);
     if (sd->erase_start == INVALID_ADDRESS
@@ -779,6 +780,7 @@ static void sd_erase(SDState *sd)
         /* High capacity memory card: erase units are 512 byte blocks */
         erase_start *= 512;
         erase_end *= 512;
+        sdsc = false;
     }
 
     if (erase_start > sd->size || erase_end > sd->size) {
@@ -788,16 +790,20 @@ static void sd_erase(SDState *sd)
         return;
     }
 
-    erase_start = sd_addr_to_wpnum(erase_start);
-    erase_end = sd_addr_to_wpnum(erase_end);
     sd->erase_start = INVALID_ADDRESS;
     sd->erase_end = INVALID_ADDRESS;
     sd->csd[14] |= 0x40;
 
-    for (i = erase_start; i <= erase_end; i++) {
-        assert(i < sd->wpgrps_size);
-        if (test_bit(i, sd->wp_groups)) {
-            sd->card_status |= WP_ERASE_SKIP;
+    /* Only SDSC cards support write protect groups */
+    if (sdsc) {
+        erase_start = sd_addr_to_wpnum(erase_start);
+        erase_end = sd_addr_to_wpnum(erase_end);
+
+        for (i = erase_start; i <= erase_end; i++) {
+            assert(i < sd->wpgrps_size);
+            if (test_bit(i, sd->wp_groups)) {
+                sd->card_status |= WP_ERASE_SKIP;
+            }
         }
     }
 }
-- 
2.26.2



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

* [PULL 15/18] hw/sd: sd: Skip write protect groups check in CMD24/25 for high capacity cards
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
                   ` (13 preceding siblings ...)
  2021-02-20  0:13 ` [PULL 14/18] hw/sd: sd: Skip write protect groups check in sd_erase() for high capacity cards Philippe Mathieu-Daudé
@ 2021-02-20  0:13 ` Philippe Mathieu-Daudé
  2021-02-20  0:13 ` [PULL 16/18] hw/sd: sd: Bypass the RCA check for CMD13 in SPI mode Philippe Mathieu-Daudé
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: Bin Meng, Philippe Mathieu-Daudé, qemu-block

From: Bin Meng <bin.meng@windriver.com>

High capacity cards don't support write protection hence we should
not perform the write protect groups check in CMD24/25 for them.

Signed-off-by: Bin Meng <bin.meng@windriver.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20210216150225.27996-8-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/sd.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 883c04de028..3a515a5365f 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1268,8 +1268,10 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
             sd->data_offset = 0;
             sd->blk_written = 0;
 
-            if (sd_wp_addr(sd, sd->data_start)) {
-                sd->card_status |= WP_VIOLATION;
+            if (sd->size <= SDSC_MAX_CAPACITY) {
+                if (sd_wp_addr(sd, sd->data_start)) {
+                    sd->card_status |= WP_VIOLATION;
+                }
             }
             if (sd->csd[14] & 0x30) {
                 sd->card_status |= WP_VIOLATION;
@@ -1821,9 +1823,11 @@ void sd_write_byte(SDState *sd, uint8_t value)
                 sd->card_status |= ADDRESS_ERROR;
                 break;
             }
-            if (sd_wp_addr(sd, sd->data_start)) {
-                sd->card_status |= WP_VIOLATION;
-                break;
+            if (sd->size <= SDSC_MAX_CAPACITY) {
+                if (sd_wp_addr(sd, sd->data_start)) {
+                    sd->card_status |= WP_VIOLATION;
+                    break;
+                }
             }
         }
         sd->data[sd->data_offset++] = value;
-- 
2.26.2



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

* [PULL 16/18] hw/sd: sd: Bypass the RCA check for CMD13 in SPI mode
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
                   ` (14 preceding siblings ...)
  2021-02-20  0:13 ` [PULL 15/18] hw/sd: sd: Skip write protect groups check in CMD24/25 " Philippe Mathieu-Daudé
@ 2021-02-20  0:13 ` Philippe Mathieu-Daudé
  2021-02-20  0:13 ` [PULL 17/18] hw/sd: sdhci: Simplify updating s->prnsts in sdhci_sdma_transfer_multi_blocks() Philippe Mathieu-Daudé
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: Bin Meng, Philippe Mathieu-Daudé, qemu-block

From: Bin Meng <bin.meng@windriver.com>

Unlike SD mode, when SD card is working in SPI mode, the argument
of CMD13 is stuff bits. Hence we should bypass the RCA check.

See "Physical Layer Specification Version 8.00", chapter 7.3.1.3
Detailed Command Description (SPI mode):

  "The card shall ignore stuff bits and reserved bits in an argument"

and Table 7-3 Commands and Arguments (SPI mode):

  "CMD13 Argument [31:0] stuff bits"

Signed-off-by: Bin Meng <bin.meng@windriver.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20210216150225.27996-9-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/sd.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 3a515a5365f..8b397effbcc 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1163,8 +1163,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
     case 13:	/* CMD13:  SEND_STATUS */
         switch (sd->mode) {
         case sd_data_transfer_mode:
-            if (sd->rca != rca)
+            if (!sd->spi && sd->rca != rca) {
                 return sd_r0;
+            }
 
             return sd_r1;
 
-- 
2.26.2



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

* [PULL 17/18] hw/sd: sdhci: Simplify updating s->prnsts in sdhci_sdma_transfer_multi_blocks()
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
                   ` (15 preceding siblings ...)
  2021-02-20  0:13 ` [PULL 16/18] hw/sd: sd: Bypass the RCA check for CMD13 in SPI mode Philippe Mathieu-Daudé
@ 2021-02-20  0:13 ` Philippe Mathieu-Daudé
  2021-02-20  0:13 ` [PULL 18/18] MAINTAINERS: Add Bin Meng as co-maintainer for SD/MMC cards Philippe Mathieu-Daudé
  2021-02-21 11:45 ` [PULL 00/18] SD/MMC patches for 2021-02-20 Peter Maydell
  18 siblings, 0 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Bulekov, Bin Meng, Philippe Mathieu-Daudé,
	qemu-block, Bin Meng

From: Bin Meng <bmeng.cn@gmail.com>

s->prnsts is updated in both branches of the if () else () statement.
Move the common bits outside so that it is cleaner.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Tested-by: Alexander Bulekov <alxndr@bu.edu>
Reviewed-by: Alexander Bulekov <alxndr@bu.edu>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <1613447214-81951-5-git-send-email-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/sdhci.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 8ffa53999d8..9acf4467a32 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -596,9 +596,9 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
         page_aligned = true;
     }
 
+    s->prnsts |= SDHC_DATA_INHIBIT | SDHC_DAT_LINE_ACTIVE;
     if (s->trnmod & SDHC_TRNS_READ) {
-        s->prnsts |= SDHC_DOING_READ | SDHC_DATA_INHIBIT |
-                SDHC_DAT_LINE_ACTIVE;
+        s->prnsts |= SDHC_DOING_READ;
         while (s->blkcnt) {
             if (s->data_count == 0) {
                 sdbus_read_data(&s->sdbus, s->fifo_buffer, block_size);
@@ -625,8 +625,7 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
             }
         }
     } else {
-        s->prnsts |= SDHC_DOING_WRITE | SDHC_DATA_INHIBIT |
-                SDHC_DAT_LINE_ACTIVE;
+        s->prnsts |= SDHC_DOING_WRITE;
         while (s->blkcnt) {
             begin = s->data_count;
             if (((boundary_count + begin) < block_size) && page_aligned) {
-- 
2.26.2



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

* [PULL 18/18] MAINTAINERS: Add Bin Meng as co-maintainer for SD/MMC cards
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
                   ` (16 preceding siblings ...)
  2021-02-20  0:13 ` [PULL 17/18] hw/sd: sdhci: Simplify updating s->prnsts in sdhci_sdma_transfer_multi_blocks() Philippe Mathieu-Daudé
@ 2021-02-20  0:13 ` Philippe Mathieu-Daudé
  2021-02-21 11:45 ` [PULL 00/18] SD/MMC patches for 2021-02-20 Peter Maydell
  18 siblings, 0 replies; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-20  0:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: Bin Meng, Philippe Mathieu-Daudé, qemu-block

There is new interest in the SD/MMC device emulation, so it
would be good to have more than only one maintainer / reviewer
for it.

Bin Meng proved by his contributions a deep understanding of the
SD cards internals, so let's add him to the corresponding section
in the MAINTAINERS file.

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Acked-by: Bin Meng <bin.meng@windriver.com>
Message-Id: <20210216132841.1121653-1-f4bug@amsat.org>
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 66354e6e495..5eeba79c5a3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1754,6 +1754,7 @@ F: hw/ssi/xilinx_*
 
 SD (Secure Card)
 M: Philippe Mathieu-Daudé <f4bug@amsat.org>
+M: Bin Meng <bin.meng@windriver.com>
 L: qemu-block@nongnu.org
 S: Odd Fixes
 F: include/hw/sd/sd*
-- 
2.26.2



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

* Re: [PULL 00/18] SD/MMC patches for 2021-02-20
  2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
                   ` (17 preceding siblings ...)
  2021-02-20  0:13 ` [PULL 18/18] MAINTAINERS: Add Bin Meng as co-maintainer for SD/MMC cards Philippe Mathieu-Daudé
@ 2021-02-21 11:45 ` Peter Maydell
  18 siblings, 0 replies; 20+ messages in thread
From: Peter Maydell @ 2021-02-21 11:45 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé; +Cc: Bin Meng, QEMU Developers, Qemu-block

On Sat, 20 Feb 2021 at 00:15, Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> The following changes since commit e90ef02389dc8b57eaea22b290244609d720a8bf:
>
>   Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-02-18' into staging (2021-02-19 17:22:42 +0000)
>
> are available in the Git repository at:
>
>   https://gitlab.com/philmd/qemu.git tags/sdmmc-20210220
>
> for you to fetch changes up to 3e0a7693be30d6a6eda8a56f3862ac2e502a9e81:
>
>   MAINTAINERS: Add Bin Meng as co-maintainer for SD/MMC cards (2021-02-20 01:08:59 +0100)
>
> ----------------------------------------------------------------
> SD/MMC patches
>
> - Various improvements for SD cards in SPI mode (Bin Meng)
> - Add Bin Meng as SD/MMC cards co-maintainer
> ----------------------------------------------------------------


Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/6.0
for any user-visible changes.

-- PMM


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

end of thread, other threads:[~2021-02-21 11:49 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-20  0:12 [PULL 00/18] SD/MMC patches for 2021-02-20 Philippe Mathieu-Daudé
2021-02-20  0:12 ` [PULL 01/18] hw/sd: ssi-sd: Support multiple block read Philippe Mathieu-Daudé
2021-02-20  0:12 ` [PULL 02/18] hw/sd: sd: Remove duplicated codes in single/multiple block read/write Philippe Mathieu-Daudé
2021-02-20  0:12 ` [PULL 03/18] hw/sd: sd: Allow single/multiple block write for SPI mode Philippe Mathieu-Daudé
2021-02-20  0:12 ` [PULL 04/18] hw/sd: Introduce receive_ready() callback Philippe Mathieu-Daudé
2021-02-20  0:12 ` [PULL 05/18] hw/sd: ssi-sd: Support single block write Philippe Mathieu-Daudé
2021-02-20  0:12 ` [PULL 06/18] hw/sd: ssi-sd: Support multiple " Philippe Mathieu-Daudé
2021-02-20  0:12 ` [PULL 07/18] hw/sd: ssi-sd: Fix SEND_IF_COND (CMD8) response Philippe Mathieu-Daudé
2021-02-20  0:12 ` [PULL 08/18] hw/sd: ssi-sd: Fix STOP_TRANSMISSION (CMD12) response Philippe Mathieu-Daudé
2021-02-20  0:13 ` [PULL 09/18] hw/sd: ssi-sd: Handle the rest commands with R1b response type Philippe Mathieu-Daudé
2021-02-20  0:13 ` [PULL 10/18] hw/sd: sd: Fix address check in sd_erase() Philippe Mathieu-Daudé
2021-02-20  0:13 ` [PULL 11/18] hw/sd: sd: Only SDSC cards support CMD28/29/30 Philippe Mathieu-Daudé
2021-02-20  0:13 ` [PULL 12/18] hw/sd: sd: Fix CMD30 response type Philippe Mathieu-Daudé
2021-02-20  0:13 ` [PULL 13/18] hw/sd: sd: Move the sd_block_{read, write} and macros ahead Philippe Mathieu-Daudé
2021-02-20  0:13 ` [PULL 14/18] hw/sd: sd: Skip write protect groups check in sd_erase() for high capacity cards Philippe Mathieu-Daudé
2021-02-20  0:13 ` [PULL 15/18] hw/sd: sd: Skip write protect groups check in CMD24/25 " Philippe Mathieu-Daudé
2021-02-20  0:13 ` [PULL 16/18] hw/sd: sd: Bypass the RCA check for CMD13 in SPI mode Philippe Mathieu-Daudé
2021-02-20  0:13 ` [PULL 17/18] hw/sd: sdhci: Simplify updating s->prnsts in sdhci_sdma_transfer_multi_blocks() Philippe Mathieu-Daudé
2021-02-20  0:13 ` [PULL 18/18] MAINTAINERS: Add Bin Meng as co-maintainer for SD/MMC cards Philippe Mathieu-Daudé
2021-02-21 11:45 ` [PULL 00/18] SD/MMC patches for 2021-02-20 Peter Maydell

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.