aboutsummaryrefslogtreecommitdiff
path: root/hw/sd/pl181.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/sd/pl181.c')
-rw-r--r--hw/sd/pl181.c111
1 files changed, 62 insertions, 49 deletions
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)