summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--hw/sd/bcm2835_sdhost.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/hw/sd/bcm2835_sdhost.c b/hw/sd/bcm2835_sdhost.c
index 4df4de7d67..1b760b2a7c 100644
--- a/hw/sd/bcm2835_sdhost.c
+++ b/hw/sd/bcm2835_sdhost.c
@@ -179,9 +179,11 @@ static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s)
     uint32_t value = 0;
     int n;
     int is_read;
+    int is_write;
 
     is_read = (s->cmd & SDCMD_READ_CMD) != 0;
-    if (s->datacnt != 0 && (!is_read || sdbus_data_ready(&s->sdbus))) {
+    is_write = (s->cmd & SDCMD_WRITE_CMD) != 0;
+    if (s->datacnt != 0 && (is_write || sdbus_data_ready(&s->sdbus))) {
         if (is_read) {
             n = 0;
             while (s->datacnt && s->fifo_len < BCM2835_SDHOST_FIFO_LEN) {
@@ -201,8 +203,11 @@ static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s)
             if (n != 0) {
                 bcm2835_sdhost_fifo_push(s, value);
                 s->status |= SDHSTS_DATA_FLAG;
+                if (s->config & SDHCFG_DATA_IRPT_EN) {
+                    s->status |= SDHSTS_SDIO_IRPT;
+                }
             }
-        } else { /* write */
+        } else if (is_write) { /* write */
             n = 0;
             while (s->datacnt > 0 && (s->fifo_len > 0 || n > 0)) {
                 if (n == 0) {
@@ -223,11 +228,18 @@ static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s)
             s->edm &= ~SDEDM_FSM_MASK;
             s->edm |= SDEDM_FSM_DATAMODE;
             trace_bcm2835_sdhost_edm_change("datacnt 0", s->edm);
-
-            if ((s->cmd & SDCMD_WRITE_CMD) &&
+        }
+        if (is_write) {
+            /* set block interrupt at end of each block transfer */
+            if (s->hbct && s->datacnt % s->hbct == 0 &&
                 (s->config & SDHCFG_BLOCK_IRPT_EN)) {
                 s->status |= SDHSTS_BLOCK_IRPT;
             }
+            /* set data interrupt after each transfer */
+            s->status |= SDHSTS_DATA_FLAG;
+            if (s->config & SDHCFG_DATA_IRPT_EN) {
+                s->status |= SDHSTS_SDIO_IRPT;
+            }
         }
     }