aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/sd/bcm2835_sdhost.c46
1 files changed, 26 insertions, 20 deletions
diff --git a/hw/sd/bcm2835_sdhost.c b/hw/sd/bcm2835_sdhost.c
index 79f3c5ceeb..ebf3b926c2 100644
--- a/hw/sd/bcm2835_sdhost.c
+++ b/hw/sd/bcm2835_sdhost.c
@@ -137,6 +137,12 @@ static void bcm2835_sdhost_send_command(BCM2835SDHostState *s)
}
#undef RWORD
}
+ /* We never really delay commands, so if this was a 'busywait' command
+ * then we've completed it now and can raise the interrupt.
+ */
+ if ((s->cmd & SDCMD_BUSYWAIT) && (s->config & SDHCFG_BUSY_IRPT_EN)) {
+ s->status |= SDHSTS_BUSY_IRPT;
+ }
return;
error:
@@ -187,18 +193,27 @@ static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s)
n++;
if (n == 4) {
bcm2835_sdhost_fifo_push(s, value);
+ s->status |= SDHSTS_DATA_FLAG;
+ if (s->config & SDHCFG_DATA_IRPT_EN) {
+ s->status |= SDHSTS_SDIO_IRPT;
+ }
n = 0;
value = 0;
}
}
if (n != 0) {
bcm2835_sdhost_fifo_push(s, value);
+ s->status |= SDHSTS_DATA_FLAG;
}
} else { /* write */
n = 0;
while (s->datacnt > 0 && (s->fifo_len > 0 || n > 0)) {
if (n == 0) {
value = bcm2835_sdhost_fifo_pop(s);
+ s->status |= SDHSTS_DATA_FLAG;
+ if (s->config & SDHCFG_DATA_IRPT_EN) {
+ s->status |= SDHSTS_SDIO_IRPT;
+ }
n = 4;
}
n--;
@@ -207,29 +222,20 @@ static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s)
value >>= 8;
}
}
- }
- if (s->datacnt == 0) {
- s->status |= SDHSTS_DATA_FLAG;
-
- s->edm &= ~0xf;
- s->edm |= SDEDM_FSM_DATAMODE;
- trace_bcm2835_sdhost_edm_change("datacnt 0", s->edm);
-
- if (s->config & SDHCFG_DATA_IRPT_EN) {
- s->status |= SDHSTS_SDIO_IRPT;
- }
-
- if ((s->cmd & SDCMD_BUSYWAIT) && (s->config & SDHCFG_BUSY_IRPT_EN)) {
- s->status |= SDHSTS_BUSY_IRPT;
- }
-
- if ((s->cmd & SDCMD_WRITE_CMD) && (s->config & SDHCFG_BLOCK_IRPT_EN)) {
- s->status |= SDHSTS_BLOCK_IRPT;
+ if (s->datacnt == 0) {
+ 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) &&
+ (s->config & SDHCFG_BLOCK_IRPT_EN)) {
+ s->status |= SDHSTS_BLOCK_IRPT;
+ }
}
-
- bcm2835_sdhost_update_irq(s);
}
+ bcm2835_sdhost_update_irq(s);
+
s->edm &= ~(0x1f << 4);
s->edm |= ((s->fifo_len & 0x1f) << 4);
trace_bcm2835_sdhost_edm_change("fifo run", s->edm);