aboutsummaryrefslogtreecommitdiff
path: root/hw/sd
diff options
context:
space:
mode:
Diffstat (limited to 'hw/sd')
-rw-r--r--hw/sd/allwinner-sdhost.c24
-rw-r--r--hw/sd/bcm2835_sdhost.c4
-rw-r--r--hw/sd/core.c38
-rw-r--r--hw/sd/milkymist-memcard.c71
-rw-r--r--hw/sd/omap_mmc.c10
-rw-r--r--hw/sd/pl181.c111
-rw-r--r--hw/sd/pxa2xx_mmci.c19
-rw-r--r--hw/sd/sd.c28
-rw-r--r--hw/sd/sdhci.c46
-rw-r--r--hw/sd/ssi-sd.c2
-rw-r--r--hw/sd/trace-events10
11 files changed, 193 insertions, 170 deletions
diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c
index f404e1fdb4..f9eb92c09e 100644
--- a/hw/sd/allwinner-sdhost.c
+++ b/hw/sd/allwinner-sdhost.c
@@ -333,16 +333,11 @@ static uint32_t allwinner_sdhost_process_desc(AwSdHostState *s,
if (is_write) {
cpu_physical_memory_read((desc->addr & DESC_SIZE_MASK) + num_done,
buf, buf_bytes);
-
- for (uint32_t i = 0; i < buf_bytes; i++) {
- sdbus_write_data(&s->sdbus, buf[i]);
- }
+ sdbus_write_data(&s->sdbus, buf, buf_bytes);
/* Read from SD bus */
} else {
- for (uint32_t i = 0; i < buf_bytes; i++) {
- buf[i] = sdbus_read_data(&s->sdbus);
- }
+ sdbus_read_data(&s->sdbus, buf, buf_bytes);
cpu_physical_memory_write((desc->addr & DESC_SIZE_MASK) + num_done,
buf, buf_bytes);
}
@@ -521,10 +516,8 @@ static uint64_t allwinner_sdhost_read(void *opaque, hwaddr offset,
break;
case REG_SD_FIFO: /* Read/Write FIFO */
if (sdbus_data_ready(&s->sdbus)) {
- res = sdbus_read_data(&s->sdbus);
- res |= sdbus_read_data(&s->sdbus) << 8;
- res |= sdbus_read_data(&s->sdbus) << 16;
- res |= sdbus_read_data(&s->sdbus) << 24;
+ sdbus_read_data(&s->sdbus, &res, sizeof(uint32_t));
+ le32_to_cpus(&res);
allwinner_sdhost_update_transfer_cnt(s, sizeof(uint32_t));
allwinner_sdhost_auto_stop(s);
allwinner_sdhost_update_irq(s);
@@ -548,6 +541,7 @@ static void allwinner_sdhost_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
AwSdHostState *s = AW_SDHOST(opaque);
+ uint32_t u32;
trace_allwinner_sdhost_write(offset, value, size);
@@ -654,11 +648,9 @@ static void allwinner_sdhost_write(void *opaque, hwaddr offset,
s->startbit_detect = value;
break;
case REG_SD_FIFO: /* Read/Write FIFO */
- sdbus_write_data(&s->sdbus, value & 0xff);
- sdbus_write_data(&s->sdbus, (value >> 8) & 0xff);
- sdbus_write_data(&s->sdbus, (value >> 16) & 0xff);
- sdbus_write_data(&s->sdbus, (value >> 24) & 0xff);
- allwinner_sdhost_update_transfer_cnt(s, sizeof(uint32_t));
+ u32 = cpu_to_le32(value);
+ sdbus_write_data(&s->sdbus, &u32, sizeof(u32));
+ allwinner_sdhost_update_transfer_cnt(s, sizeof(u32));
allwinner_sdhost_auto_stop(s);
allwinner_sdhost_update_irq(s);
break;
diff --git a/hw/sd/bcm2835_sdhost.c b/hw/sd/bcm2835_sdhost.c
index 4a80fbcc86..2c7a675a2d 100644
--- a/hw/sd/bcm2835_sdhost.c
+++ b/hw/sd/bcm2835_sdhost.c
@@ -190,7 +190,7 @@ static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s)
if (is_read) {
n = 0;
while (s->datacnt && s->fifo_len < BCM2835_SDHOST_FIFO_LEN) {
- value |= (uint32_t)sdbus_read_data(&s->sdbus) << (n * 8);
+ value |= (uint32_t)sdbus_read_byte(&s->sdbus) << (n * 8);
s->datacnt--;
n++;
if (n == 4) {
@@ -223,7 +223,7 @@ static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s)
}
n--;
s->datacnt--;
- sdbus_write_data(&s->sdbus, value & 0xff);
+ sdbus_write_byte(&s->sdbus, value & 0xff);
value >>= 8;
}
}
diff --git a/hw/sd/core.c b/hw/sd/core.c
index abec48bccb..957d116f1a 100644
--- a/hw/sd/core.c
+++ b/hw/sd/core.c
@@ -102,7 +102,7 @@ int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t *response)
return 0;
}
-void sdbus_write_data(SDBus *sdbus, uint8_t value)
+void sdbus_write_byte(SDBus *sdbus, uint8_t value)
{
SDState *card = get_card(sdbus);
@@ -110,11 +110,26 @@ void sdbus_write_data(SDBus *sdbus, uint8_t value)
if (card) {
SDCardClass *sc = SD_CARD_GET_CLASS(card);
- sc->write_data(card, value);
+ sc->write_byte(card, value);
}
}
-uint8_t sdbus_read_data(SDBus *sdbus)
+void sdbus_write_data(SDBus *sdbus, const void *buf, size_t length)
+{
+ SDState *card = get_card(sdbus);
+ const uint8_t *data = buf;
+
+ if (card) {
+ SDCardClass *sc = SD_CARD_GET_CLASS(card);
+
+ for (size_t i = 0; i < length; i++) {
+ trace_sdbus_write(sdbus_name(sdbus), data[i]);
+ sc->write_byte(card, data[i]);
+ }
+ }
+}
+
+uint8_t sdbus_read_byte(SDBus *sdbus)
{
SDState *card = get_card(sdbus);
uint8_t value = 0;
@@ -122,13 +137,28 @@ uint8_t sdbus_read_data(SDBus *sdbus)
if (card) {
SDCardClass *sc = SD_CARD_GET_CLASS(card);
- value = sc->read_data(card);
+ value = sc->read_byte(card);
}
trace_sdbus_read(sdbus_name(sdbus), value);
return value;
}
+void sdbus_read_data(SDBus *sdbus, void *buf, size_t length)
+{
+ SDState *card = get_card(sdbus);
+ uint8_t *data = buf;
+
+ if (card) {
+ SDCardClass *sc = SD_CARD_GET_CLASS(card);
+
+ for (size_t i = 0; i < length; i++) {
+ data[i] = sc->read_byte(card);
+ trace_sdbus_read(sdbus_name(sdbus), data[i]);
+ }
+ }
+}
+
bool sdbus_data_ready(SDBus *sdbus)
{
SDState *card = get_card(sdbus);
diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
index 11f61294fc..be89a93876 100644
--- a/hw/sd/milkymist-memcard.c
+++ b/hw/sd/milkymist-memcard.c
@@ -66,6 +66,8 @@ enum {
#define MILKYMIST_MEMCARD(obj) \
OBJECT_CHECK(MilkymistMemcardState, (obj), TYPE_MILKYMIST_MEMCARD)
+#define TYPE_MILKYMIST_SDBUS "milkymist-sdbus"
+
struct MilkymistMemcardState {
SysBusDevice parent_obj;
@@ -149,11 +151,8 @@ static uint64_t memcard_read(void *opaque, hwaddr addr,
if (!s->enabled) {
r = 0xffffffff;
} else {
- r = 0;
- r |= sdbus_read_data(&s->sdbus) << 24;
- r |= sdbus_read_data(&s->sdbus) << 16;
- r |= sdbus_read_data(&s->sdbus) << 8;
- r |= sdbus_read_data(&s->sdbus);
+ sdbus_read_data(&s->sdbus, &r, sizeof(r));
+ be32_to_cpus(&r);
}
break;
case R_CLK2XDIV:
@@ -179,6 +178,7 @@ static void memcard_write(void *opaque, hwaddr addr, uint64_t value,
unsigned size)
{
MilkymistMemcardState *s = opaque;
+ uint32_t val32;
trace_milkymist_memcard_memory_write(addr, value);
@@ -207,10 +207,8 @@ static void memcard_write(void *opaque, hwaddr addr, uint64_t value,
if (!s->enabled) {
break;
}
- sdbus_write_data(&s->sdbus, (value >> 24) & 0xff);
- sdbus_write_data(&s->sdbus, (value >> 16) & 0xff);
- sdbus_write_data(&s->sdbus, (value >> 8) & 0xff);
- sdbus_write_data(&s->sdbus, value & 0xff);
+ val32 = cpu_to_be32(value);
+ sdbus_write_data(&s->sdbus, &val32, sizeof(val32));
break;
case R_ENABLE:
s->regs[addr] = value;
@@ -253,6 +251,19 @@ static void milkymist_memcard_reset(DeviceState *d)
}
}
+static void milkymist_memcard_set_readonly(DeviceState *dev, bool level)
+{
+ qemu_log_mask(LOG_UNIMP,
+ "milkymist_memcard: read-only mode not supported\n");
+}
+
+static void milkymist_memcard_set_inserted(DeviceState *dev, bool level)
+{
+ MilkymistMemcardState *s = MILKYMIST_MEMCARD(dev);
+
+ s->enabled = !!level;
+}
+
static void milkymist_memcard_init(Object *obj)
{
MilkymistMemcardState *s = MILKYMIST_MEMCARD(obj);
@@ -261,30 +272,9 @@ static void milkymist_memcard_init(Object *obj)
memory_region_init_io(&s->regs_region, OBJECT(s), &memcard_mmio_ops, s,
"milkymist-memcard", R_MAX * 4);
sysbus_init_mmio(dev, &s->regs_region);
-}
-
-static void milkymist_memcard_realize(DeviceState *dev, Error **errp)
-{
- MilkymistMemcardState *s = MILKYMIST_MEMCARD(dev);
- DeviceState *carddev;
- BlockBackend *blk;
- DriveInfo *dinfo;
- Error *err = NULL;
qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), TYPE_SD_BUS,
- dev, "sd-bus");
-
- /* Create and plug in the sd card */
- /* FIXME use a qdev drive property instead of drive_get_next() */
- dinfo = drive_get_next(IF_SD);
- blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
- carddev = qdev_new(TYPE_SD_CARD);
- qdev_prop_set_drive(carddev, "drive", blk);
- if (!qdev_realize_and_unref(carddev, BUS(&s->sdbus), &err)) {
- error_propagate_prepend(errp, err, "failed to init SD card");
- return;
- }
- s->enabled = blk && blk_is_inserted(blk);
+ DEVICE(obj), "sd-bus");
}
static const VMStateDescription vmstate_milkymist_memcard = {
@@ -308,10 +298,9 @@ static void milkymist_memcard_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- dc->realize = milkymist_memcard_realize;
dc->reset = milkymist_memcard_reset;
dc->vmsd = &vmstate_milkymist_memcard;
- /* Reason: init() method uses drive_get_next() */
+ /* Reason: output IRQs should be wired up */
dc->user_creatable = false;
}
@@ -323,9 +312,25 @@ static const TypeInfo milkymist_memcard_info = {
.class_init = milkymist_memcard_class_init,
};
+static void milkymist_sdbus_class_init(ObjectClass *klass, void *data)
+{
+ SDBusClass *sbc = SD_BUS_CLASS(klass);
+
+ sbc->set_inserted = milkymist_memcard_set_inserted;
+ sbc->set_readonly = milkymist_memcard_set_readonly;
+}
+
+static const TypeInfo milkymist_sdbus_info = {
+ .name = TYPE_MILKYMIST_SDBUS,
+ .parent = TYPE_SD_BUS,
+ .instance_size = sizeof(SDBus),
+ .class_init = milkymist_sdbus_class_init,
+};
+
static void milkymist_memcard_register_types(void)
{
type_register_static(&milkymist_memcard_info);
+ type_register_static(&milkymist_sdbus_info);
}
type_init(milkymist_memcard_register_types)
diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
index 4088a8a80b..1f946908fe 100644
--- a/hw/sd/omap_mmc.c
+++ b/hw/sd/omap_mmc.c
@@ -23,7 +23,7 @@
#include "qemu/log.h"
#include "hw/irq.h"
#include "hw/arm/omap.h"
-#include "hw/sd/sd.h"
+#include "hw/sd/sdcard_legacy.h"
struct omap_mmc_s {
qemu_irq irq;
@@ -232,10 +232,10 @@ static void omap_mmc_transfer(struct omap_mmc_s *host)
if (host->fifo_len > host->af_level)
break;
- value = sd_read_data(host->card);
+ value = sd_read_byte(host->card);
host->fifo[(host->fifo_start + host->fifo_len) & 31] = value;
if (-- host->blen_counter) {
- value = sd_read_data(host->card);
+ value = sd_read_byte(host->card);
host->fifo[(host->fifo_start + host->fifo_len) & 31] |=
value << 8;
host->blen_counter --;
@@ -247,10 +247,10 @@ static void omap_mmc_transfer(struct omap_mmc_s *host)
break;
value = host->fifo[host->fifo_start] & 0xff;
- sd_write_data(host->card, value);
+ sd_write_byte(host->card, value);
if (-- host->blen_counter) {
value = host->fifo[host->fifo_start] >> 8;
- sd_write_data(host->card, value);
+ sd_write_byte(host->card, value);
host->blen_counter --;
}
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index 2b3776a6a0..579d68ad83 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -15,27 +15,22 @@
#include "hw/sd/sd.h"
#include "qemu/log.h"
#include "qemu/module.h"
+#include "qemu/error-report.h"
#include "qapi/error.h"
-
-//#define DEBUG_PL181 1
-
-#ifdef DEBUG_PL181
-#define DPRINTF(fmt, ...) \
-do { printf("pl181: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#endif
+#include "trace.h"
#define PL181_FIFO_LEN 16
#define TYPE_PL181 "pl181"
#define PL181(obj) OBJECT_CHECK(PL181State, (obj), TYPE_PL181)
+#define TYPE_PL181_BUS "pl181-bus"
+
typedef struct PL181State {
SysBusDevice parent_obj;
MemoryRegion iomem;
- SDState *card;
+ SDBus sdbus;
uint32_t clock;
uint32_t power;
uint32_t cmdarg;
@@ -56,10 +51,11 @@ typedef struct PL181State {
http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=4446/1
*/
int32_t linux_hack;
- uint32_t fifo[PL181_FIFO_LEN];
+ uint32_t fifo[PL181_FIFO_LEN]; /* TODO use Fifo32 */
qemu_irq irq[2];
/* GPIO outputs for 'card is readonly' and 'card inserted' */
- qemu_irq cardstatus[2];
+ qemu_irq card_readonly;
+ qemu_irq card_inserted;
} PL181State;
static const VMStateDescription vmstate_pl181 = {
@@ -148,13 +144,13 @@ static void pl181_fifo_push(PL181State *s, uint32_t value)
int n;
if (s->fifo_len == PL181_FIFO_LEN) {
- fprintf(stderr, "pl181: FIFO overflow\n");
+ error_report("%s: FIFO overflow", __func__);
return;
}
n = (s->fifo_pos + s->fifo_len) & (PL181_FIFO_LEN - 1);
s->fifo_len++;
s->fifo[n] = value;
- DPRINTF("FIFO push %08x\n", (int)value);
+ trace_pl181_fifo_push(value);
}
static uint32_t pl181_fifo_pop(PL181State *s)
@@ -162,17 +158,17 @@ static uint32_t pl181_fifo_pop(PL181State *s)
uint32_t value;
if (s->fifo_len == 0) {
- fprintf(stderr, "pl181: FIFO underflow\n");
+ error_report("%s: FIFO underflow", __func__);
return 0;
}
value = s->fifo[s->fifo_pos];
s->fifo_len--;
s->fifo_pos = (s->fifo_pos + 1) & (PL181_FIFO_LEN - 1);
- DPRINTF("FIFO pop %08x\n", (int)value);
+ trace_pl181_fifo_pop(value);
return value;
}
-static void pl181_send_command(PL181State *s)
+static void pl181_do_command(PL181State *s)
{
SDRequest request;
uint8_t response[16];
@@ -180,8 +176,8 @@ static void pl181_send_command(PL181State *s)
request.cmd = s->cmd & PL181_CMD_INDEX;
request.arg = s->cmdarg;
- DPRINTF("Command %d %08x\n", request.cmd, request.arg);
- rlen = sd_do_command(s->card, &request, response);
+ trace_pl181_command_send(request.cmd, request.arg);
+ rlen = sdbus_do_command(&s->sdbus, &request, response);
if (rlen < 0)
goto error;
if (s->cmd & PL181_CMD_RESPONSE) {
@@ -197,16 +193,16 @@ static void pl181_send_command(PL181State *s)
s->response[2] = ldl_be_p(&response[8]);
s->response[3] = ldl_be_p(&response[12]) & ~1;
}
- DPRINTF("Response received\n");
+ trace_pl181_command_response_pending();
s->status |= PL181_STATUS_CMDRESPEND;
} else {
- DPRINTF("Command sent\n");
+ trace_pl181_command_sent();
s->status |= PL181_STATUS_CMDSENT;
}
return;
error:
- DPRINTF("Timeout\n");
+ trace_pl181_command_timeout();
s->status |= PL181_STATUS_CMDTIMEOUT;
}
@@ -222,12 +218,12 @@ static void pl181_fifo_run(PL181State *s)
int is_read;
is_read = (s->datactrl & PL181_DATA_DIRECTION) != 0;
- if (s->datacnt != 0 && (!is_read || sd_data_ready(s->card))
+ if (s->datacnt != 0 && (!is_read || sdbus_data_ready(&s->sdbus))
&& !s->linux_hack) {
if (is_read) {
n = 0;
while (s->datacnt && s->fifo_len < PL181_FIFO_LEN) {
- value |= (uint32_t)sd_read_data(s->card) << (n * 8);
+ value |= (uint32_t)sdbus_read_byte(&s->sdbus) << (n * 8);
s->datacnt--;
n++;
if (n == 4) {
@@ -248,7 +244,7 @@ static void pl181_fifo_run(PL181State *s)
}
n--;
s->datacnt--;
- sd_write_data(s->card, value & 0xff);
+ sdbus_write_byte(&s->sdbus, value & 0xff);
value >>= 8;
}
}
@@ -258,11 +254,11 @@ static void pl181_fifo_run(PL181State *s)
s->status |= PL181_STATUS_DATAEND;
/* HACK: */
s->status |= PL181_STATUS_DATABLOCKEND;
- DPRINTF("Transfer Complete\n");
+ trace_pl181_fifo_transfer_complete();
}
if (s->datacnt == 0 && s->fifo_len == 0) {
s->datactrl &= ~PL181_DATA_ENABLE;
- DPRINTF("Data engine idle\n");
+ trace_pl181_data_engine_idle();
} else {
/* Update FIFO bits. */
bits = PL181_STATUS_TXACTIVE | PL181_STATUS_RXACTIVE;
@@ -401,7 +397,7 @@ static void pl181_write(void *opaque, hwaddr offset,
qemu_log_mask(LOG_UNIMP,
"pl181: Pending commands not implemented\n");
} else {
- pl181_send_command(s);
+ pl181_do_command(s);
pl181_fifo_run(s);
}
/* The command has completed one way or the other. */
@@ -454,6 +450,20 @@ static const MemoryRegionOps pl181_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
+static void pl181_set_readonly(DeviceState *dev, bool level)
+{
+ PL181State *s = (PL181State *)dev;
+
+ qemu_set_irq(s->card_readonly, level);
+}
+
+static void pl181_set_inserted(DeviceState *dev, bool level)
+{
+ PL181State *s = (PL181State *)dev;
+
+ qemu_set_irq(s->card_inserted, level);
+}
+
static void pl181_reset(DeviceState *d)
{
PL181State *s = PL181(d);
@@ -477,12 +487,9 @@ static void pl181_reset(DeviceState *d)
s->mask[0] = 0;
s->mask[1] = 0;
- /* We can assume our GPIO outputs have been wired up now */
- sd_set_cb(s->card, s->cardstatus[0], s->cardstatus[1]);
- /* Since we're still using the legacy SD API the card is not plugged
- * into any bus, and we must reset it manually.
- */
- device_legacy_reset(DEVICE(s->card));
+ /* Reset other state based on current card insertion/readonly status */
+ pl181_set_inserted(DEVICE(s), sdbus_get_inserted(&s->sdbus));
+ pl181_set_readonly(DEVICE(s), sdbus_get_readonly(&s->sdbus));
}
static void pl181_init(Object *obj)
@@ -495,20 +502,11 @@ static void pl181_init(Object *obj)
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq[0]);
sysbus_init_irq(sbd, &s->irq[1]);
- qdev_init_gpio_out(dev, s->cardstatus, 2);
-}
+ qdev_init_gpio_out_named(dev, &s->card_readonly, "card-read-only", 1);
+ qdev_init_gpio_out_named(dev, &s->card_inserted, "card-inserted", 1);
-static void pl181_realize(DeviceState *dev, Error **errp)
-{
- PL181State *s = PL181(dev);
- DriveInfo *dinfo;
-
- /* FIXME use a qdev drive property instead of drive_get_next() */
- dinfo = drive_get_next(IF_SD);
- s->card = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, false);
- if (s->card == NULL) {
- error_setg(errp, "sd_init failed");
- }
+ qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
+ TYPE_PL181_BUS, dev, "sd-bus");
}
static void pl181_class_init(ObjectClass *klass, void *data)
@@ -517,9 +515,8 @@ static void pl181_class_init(ObjectClass *klass, void *data)
k->vmsd = &vmstate_pl181;
k->reset = pl181_reset;
- /* Reason: init() method uses drive_get_next() */
+ /* Reason: output IRQs should be wired up */
k->user_creatable = false;
- k->realize = pl181_realize;
}
static const TypeInfo pl181_info = {
@@ -530,9 +527,25 @@ static const TypeInfo pl181_info = {
.class_init = pl181_class_init,
};
+static void pl181_bus_class_init(ObjectClass *klass, void *data)
+{
+ SDBusClass *sbc = SD_BUS_CLASS(klass);
+
+ sbc->set_inserted = pl181_set_inserted;
+ sbc->set_readonly = pl181_set_readonly;
+}
+
+static const TypeInfo pl181_bus_info = {
+ .name = TYPE_PL181_BUS,
+ .parent = TYPE_SD_BUS,
+ .instance_size = sizeof(SDBus),
+ .class_init = pl181_bus_class_init,
+};
+
static void pl181_register_types(void)
{
type_register_static(&pl181_info);
+ type_register_static(&pl181_bus_info);
}
type_init(pl181_register_types)
diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c
index 68bed24480..04f0a98f81 100644
--- a/hw/sd/pxa2xx_mmci.c
+++ b/hw/sd/pxa2xx_mmci.c
@@ -184,7 +184,7 @@ static void pxa2xx_mmci_fifo_update(PXA2xxMMCIState *s)
if (s->cmdat & CMDAT_WR_RD) {
while (s->bytesleft && s->tx_len) {
- sdbus_write_data(&s->sdbus, s->tx_fifo[s->tx_start++]);
+ sdbus_write_byte(&s->sdbus, s->tx_fifo[s->tx_start++]);
s->tx_start &= 0x1f;
s->tx_len --;
s->bytesleft --;
@@ -194,7 +194,7 @@ static void pxa2xx_mmci_fifo_update(PXA2xxMMCIState *s)
} else
while (s->bytesleft && s->rx_len < 32) {
s->rx_fifo[(s->rx_start + (s->rx_len ++)) & 0x1f] =
- sdbus_read_data(&s->sdbus);
+ sdbus_read_byte(&s->sdbus);
s->bytesleft --;
s->intreq |= INT_RXFIFO_REQ;
}
@@ -476,15 +476,12 @@ static const MemoryRegionOps pxa2xx_mmci_ops = {
PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
hwaddr base,
- BlockBackend *blk, qemu_irq irq,
- qemu_irq rx_dma, qemu_irq tx_dma)
+ qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma)
{
- DeviceState *dev, *carddev;
+ DeviceState *dev;
SysBusDevice *sbd;
- PXA2xxMMCIState *s;
dev = qdev_new(TYPE_PXA2XX_MMCI);
- s = PXA2XX_MMCI(dev);
sbd = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(sbd, 0, base);
sysbus_connect_irq(sbd, 0, irq);
@@ -492,13 +489,7 @@ PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
qdev_connect_gpio_out_named(dev, "tx-dma", 0, tx_dma);
sysbus_realize_and_unref(sbd, &error_fatal);
- /* Create and plug in the sd card */
- carddev = qdev_new(TYPE_SD_CARD);
- qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
- qdev_realize_and_unref(carddev, qdev_get_child_bus(dev, "sd-bus"),
- &error_fatal);
-
- return s;
+ return PXA2XX_MMCI(dev);
}
static void pxa2xx_mmci_set_inserted(DeviceState *dev, bool inserted)
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index fad9cf1ee7..483c4f1720 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -37,6 +37,7 @@
#include "hw/registerfields.h"
#include "sysemu/block-backend.h"
#include "hw/sd/sd.h"
+#include "hw/sd/sdcard_legacy.h"
#include "migration/vmstate.h"
#include "qapi/error.h"
#include "qemu/bitmap.h"
@@ -50,6 +51,8 @@
//#define DEBUG_SD 1
+#define SDSC_MAX_CAPACITY (2 * GiB)
+
typedef enum {
sd_r0 = 0, /* no response */
sd_r1, /* normal response command */
@@ -313,7 +316,7 @@ static void sd_ocr_powerup(void *opaque)
/* card power-up OK */
sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_POWER_UP, 1);
- if (sd->size > 1 * GiB) {
+ if (sd->size > SDSC_MAX_CAPACITY) {
sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_CAPACITY, 1);
}
}
@@ -385,7 +388,7 @@ static void sd_set_csd(SDState *sd, uint64_t size)
uint32_t sectsize = (1 << (SECTOR_SHIFT + 1)) - 1;
uint32_t wpsize = (1 << (WPGROUP_SHIFT + 1)) - 1;
- if (size <= 1 * GiB) { /* Standard Capacity SD */
+ if (size <= SDSC_MAX_CAPACITY) { /* Standard Capacity SD */
sd->csd[0] = 0x00; /* CSD structure */
sd->csd[1] = 0x26; /* Data read access-time-1 */
sd->csd[2] = 0x00; /* Data read access-time-2 */
@@ -806,11 +809,12 @@ static void sd_function_switch(SDState *sd, uint32_t arg)
sd->data[11] = 0x43;
sd->data[12] = 0x80; /* Supported group 1 functions */
sd->data[13] = 0x03;
+
for (i = 0; i < 6; i ++) {
new_func = (arg >> (i * 4)) & 0x0f;
if (mode && new_func != 0x0f)
sd->function_group[i] = new_func;
- sd->data[14 + (i >> 1)] = new_func << ((i * 4) & 4);
+ sd->data[16 - (i >> 1)] |= new_func << ((i % 2) * 4);
}
memset(&sd->data[17], 0, 47);
stw_be_p(sd->data + 64, sd_crc16(sd->data, 64));
@@ -1808,7 +1812,7 @@ static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len)
#define APP_READ_BLOCK(a, len) memset(sd->data, 0xec, len)
#define APP_WRITE_BLOCK(a, len)
-void sd_write_data(SDState *sd, uint8_t value)
+void sd_write_byte(SDState *sd, uint8_t value)
{
int i;
@@ -1817,7 +1821,7 @@ void sd_write_data(SDState *sd, uint8_t value)
if (sd->state != sd_receivingdata_state) {
qemu_log_mask(LOG_GUEST_ERROR,
- "sd_write_data: not in Receiving-Data state\n");
+ "%s: not in Receiving-Data state\n", __func__);
return;
}
@@ -1939,7 +1943,7 @@ void sd_write_data(SDState *sd, uint8_t value)
break;
default:
- qemu_log_mask(LOG_GUEST_ERROR, "sd_write_data: unknown command\n");
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: unknown command\n", __func__);
break;
}
}
@@ -1958,7 +1962,7 @@ static const uint8_t sd_tuning_block_pattern[SD_TUNING_BLOCK_SIZE] = {
0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
};
-uint8_t sd_read_data(SDState *sd)
+uint8_t sd_read_byte(SDState *sd)
{
/* TODO: Append CRCs */
uint8_t ret;
@@ -1969,7 +1973,7 @@ uint8_t sd_read_data(SDState *sd)
if (sd->state != sd_sendingdata_state) {
qemu_log_mask(LOG_GUEST_ERROR,
- "sd_read_data: not in Sending-Data state\n");
+ "%s: not in Sending-Data state\n", __func__);
return 0x00;
}
@@ -2075,14 +2079,14 @@ uint8_t sd_read_data(SDState *sd)
break;
default:
- qemu_log_mask(LOG_GUEST_ERROR, "sd_read_data: unknown command\n");
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: unknown command\n", __func__);
return 0x00;
}
return ret;
}
-bool sd_data_ready(SDState *sd)
+static bool sd_data_ready(SDState *sd)
{
return sd->state == sd_sendingdata_state;
}
@@ -2191,8 +2195,8 @@ static void sd_class_init(ObjectClass *klass, void *data)
sc->get_dat_lines = sd_get_dat_lines;
sc->get_cmd_line = sd_get_cmd_line;
sc->do_command = sd_do_command;
- sc->write_data = sd_write_data;
- sc->read_data = sd_read_data;
+ sc->write_byte = sd_write_byte;
+ sc->read_byte = sd_read_byte;
sc->data_ready = sd_data_ready;
sc->enable = sd_enable;
sc->get_inserted = sd_get_inserted;
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index deac181865..1785d7e1f7 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -399,8 +399,6 @@ static void sdhci_end_transfer(SDHCIState *s)
/* Fill host controller's read buffer with BLKSIZE bytes of data from card */
static void sdhci_read_block_from_card(SDHCIState *s)
{
- int index = 0;
- uint8_t data;
const uint16_t blk_size = s->blksize & BLOCK_SIZE_MASK;
if ((s->trnmod & SDHC_TRNS_MULTI) &&
@@ -408,12 +406,9 @@ static void sdhci_read_block_from_card(SDHCIState *s)
return;
}
- for (index = 0; index < blk_size; index++) {
- data = sdbus_read_data(&s->sdbus);
- if (!FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) {
- /* Device is not in tuning */
- s->fifo_buffer[index] = data;
- }
+ if (!FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) {
+ /* Device is not in tuning */
+ sdbus_read_data(&s->sdbus, s->fifo_buffer, blk_size);
}
if (FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) {
@@ -496,8 +491,6 @@ static uint32_t sdhci_read_dataport(SDHCIState *s, unsigned size)
/* Write data from host controller FIFO to card */
static void sdhci_write_block_to_card(SDHCIState *s)
{
- int index = 0;
-
if (s->prnsts & SDHC_SPACE_AVAILABLE) {
if (s->norintstsen & SDHC_NISEN_WBUFRDY) {
s->norintsts |= SDHC_NIS_WBUFRDY;
@@ -514,9 +507,7 @@ static void sdhci_write_block_to_card(SDHCIState *s)
}
}
- for (index = 0; index < (s->blksize & BLOCK_SIZE_MASK); index++) {
- sdbus_write_data(&s->sdbus, s->fifo_buffer[index]);
- }
+ sdbus_write_data(&s->sdbus, s->fifo_buffer, s->blksize & BLOCK_SIZE_MASK);
/* Next data can be written through BUFFER DATORT register */
s->prnsts |= SDHC_SPACE_AVAILABLE;
@@ -578,7 +569,7 @@ static void sdhci_write_dataport(SDHCIState *s, uint32_t value, unsigned size)
static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
{
bool page_aligned = false;
- unsigned int n, begin;
+ unsigned int begin;
const uint16_t block_size = s->blksize & BLOCK_SIZE_MASK;
uint32_t boundary_chk = 1 << (((s->blksize & ~BLOCK_SIZE_MASK) >> 12) + 12);
uint32_t boundary_count = boundary_chk - (s->sdmasysad % boundary_chk);
@@ -600,9 +591,7 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
SDHC_DAT_LINE_ACTIVE;
while (s->blkcnt) {
if (s->data_count == 0) {
- for (n = 0; n < block_size; n++) {
- s->fifo_buffer[n] = sdbus_read_data(&s->sdbus);
- }
+ sdbus_read_data(&s->sdbus, s->fifo_buffer, block_size);
}
begin = s->data_count;
if (((boundary_count + begin) < block_size) && page_aligned) {
@@ -641,9 +630,7 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
&s->fifo_buffer[begin], s->data_count - begin);
s->sdmasysad += s->data_count - begin;
if (s->data_count == block_size) {
- for (n = 0; n < block_size; n++) {
- sdbus_write_data(&s->sdbus, s->fifo_buffer[n]);
- }
+ sdbus_write_data(&s->sdbus, s->fifo_buffer, block_size);
s->data_count = 0;
if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) {
s->blkcnt--;
@@ -668,19 +655,14 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
/* single block SDMA transfer */
static void sdhci_sdma_transfer_single_block(SDHCIState *s)
{
- int n;
uint32_t datacnt = s->blksize & BLOCK_SIZE_MASK;
if (s->trnmod & SDHC_TRNS_READ) {
- for (n = 0; n < datacnt; n++) {
- s->fifo_buffer[n] = sdbus_read_data(&s->sdbus);
- }
+ sdbus_read_data(&s->sdbus, s->fifo_buffer, datacnt);
dma_memory_write(s->dma_as, s->sdmasysad, s->fifo_buffer, datacnt);
} else {
dma_memory_read(s->dma_as, s->sdmasysad, s->fifo_buffer, datacnt);
- for (n = 0; n < datacnt; n++) {
- sdbus_write_data(&s->sdbus, s->fifo_buffer[n]);
- }
+ sdbus_write_data(&s->sdbus, s->fifo_buffer, datacnt);
}
s->blkcnt--;
@@ -739,7 +721,7 @@ static void get_adma_description(SDHCIState *s, ADMADescr *dscr)
static void sdhci_do_adma(SDHCIState *s)
{
- unsigned int n, begin, length;
+ unsigned int begin, length;
const uint16_t block_size = s->blksize & BLOCK_SIZE_MASK;
ADMADescr dscr = {};
int i;
@@ -773,9 +755,7 @@ static void sdhci_do_adma(SDHCIState *s)
if (s->trnmod & SDHC_TRNS_READ) {
while (length) {
if (s->data_count == 0) {
- for (n = 0; n < block_size; n++) {
- s->fifo_buffer[n] = sdbus_read_data(&s->sdbus);
- }
+ sdbus_read_data(&s->sdbus, s->fifo_buffer, block_size);
}
begin = s->data_count;
if ((length + begin) < block_size) {
@@ -814,9 +794,7 @@ static void sdhci_do_adma(SDHCIState *s)
s->data_count - begin);
dscr.addr += s->data_count - begin;
if (s->data_count == block_size) {
- for (n = 0; n < block_size; n++) {
- sdbus_write_data(&s->sdbus, s->fifo_buffer[n]);
- }
+ sdbus_write_data(&s->sdbus, s->fifo_buffer, block_size);
s->data_count = 0;
if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) {
s->blkcnt--;
diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index 9210ef567f..a7ef9cb922 100644
--- a/hw/sd/ssi-sd.c
+++ b/hw/sd/ssi-sd.c
@@ -190,7 +190,7 @@ static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val)
s->mode = SSI_SD_DATA_READ;
return 0xfe;
case SSI_SD_DATA_READ:
- val = sdbus_read_data(&s->sdbus);
+ val = sdbus_read_byte(&s->sdbus);
if (!sdbus_data_ready(&s->sdbus)) {
DPRINTF("Data read end\n");
s->mode = SSI_SD_CMD;
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index 5f09d32eb2..a87d7355fb 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -62,3 +62,13 @@ milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value
# pxa2xx_mmci.c
pxa2xx_mmci_read(uint8_t size, uint32_t addr, uint32_t value) "size %d addr 0x%02x value 0x%08x"
pxa2xx_mmci_write(uint8_t size, uint32_t addr, uint32_t value) "size %d addr 0x%02x value 0x%08x"
+
+# pl181.c
+pl181_command_send(uint8_t cmd, uint32_t arg) "sending CMD%02d arg 0x%08" PRIx32
+pl181_command_sent(void) "command sent"
+pl181_command_response_pending(void) "response received"
+pl181_command_timeout(void) "command timeouted"
+pl181_fifo_push(uint32_t data) "FIFO push 0x%08" PRIx32
+pl181_fifo_pop(uint32_t data) "FIFO pop 0x%08" PRIx32
+pl181_fifo_transfer_complete(void) "FIFO transfer complete"
+pl181_data_engine_idle(void) "data engine idle"