diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h index 964570f8e8..5f3765f12d 100644 --- a/hw/sd/sdhci-internal.h +++ b/hw/sd/sdhci-internal.h @@ -308,6 +308,7 @@ extern const VMStateDescription sdhci_vmstate; #define SDHC_CAPAB_REG_DEFAULT 0x057834b4 #define DEFINE_SDHCI_COMMON_PROPERTIES(_state) \ + DEFINE_PROP_UINT8("endianness", _state, endianness, DEVICE_LITTLE_ENDIAN), \ DEFINE_PROP_UINT8("sd-spec-version", _state, sd_spec_version, 2), \ DEFINE_PROP_UINT8("uhs", _state, uhs_mode, UHS_NOT_SUPPORTED), \ DEFINE_PROP_UINT8("vendor", _state, vendor, SDHCI_VENDOR_NONE), \ diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 306070c872..6811f0f1a8 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -1329,7 +1329,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) value >> shift, value >> shift); } -static const MemoryRegionOps sdhci_mmio_ops = { +static const MemoryRegionOps sdhci_mmio_le_ops = { .read = sdhci_read, .write = sdhci_write, .valid = { @@ -1340,6 +1340,21 @@ static const MemoryRegionOps sdhci_mmio_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; +static const MemoryRegionOps sdhci_mmio_be_ops = { + .read = sdhci_read, + .write = sdhci_write, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, + .valid = { + .min_access_size = 1, + .max_access_size = 4, + .unaligned = false + }, + .endianness = DEVICE_BIG_ENDIAN, +}; + static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp) { ERRP_GUARD(); @@ -1367,8 +1382,6 @@ void sdhci_initfn(SDHCIState *s) s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_raise_insertion_irq, s); s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_data_transfer, s); - - s->io_ops = &sdhci_mmio_ops; } void sdhci_uninitfn(SDHCIState *s) @@ -1384,10 +1397,23 @@ void sdhci_common_realize(SDHCIState *s, Error **errp) { ERRP_GUARD(); + switch (s->endianness) { + case DEVICE_LITTLE_ENDIAN: + s->io_ops = &sdhci_mmio_le_ops; + break; + case DEVICE_BIG_ENDIAN: + s->io_ops = &sdhci_mmio_be_ops; + break; + default: + error_setg(errp, "Incorrect endianness"); + return; + } + sdhci_init_readonly_registers(s, errp); if (*errp) { return; } + s->buf_maxsz = sdhci_get_fifolen(s); s->fifo_buffer = g_malloc0(s->buf_maxsz); diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h index 01a64c5442..a989fca3b2 100644 --- a/include/hw/sd/sdhci.h +++ b/include/hw/sd/sdhci.h @@ -96,6 +96,7 @@ struct SDHCIState { /* Configurable properties */ bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */ uint32_t quirks; + uint8_t endianness; uint8_t sd_spec_version; uint8_t uhs_mode; uint8_t vendor; /* For vendor specific functionality */