aboutsummaryrefslogtreecommitdiff
path: root/hw/sd/sdhci.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/sd/sdhci.c')
-rw-r--r--hw/sd/sdhci.c63
1 files changed, 36 insertions, 27 deletions
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 299cd4b..226ff13 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -274,6 +274,10 @@ static void sdhci_set_readonly(DeviceState *dev, bool level)
{
SDHCIState *s = (SDHCIState *)dev;
+ if (s->wp_inverted) {
+ level = !level;
+ }
+
if (level) {
s->prnsts &= ~SDHC_WRITE_PROTECT;
} else {
@@ -303,6 +307,10 @@ static void sdhci_reset(SDHCIState *s)
s->data_count = 0;
s->stopped_state = sdhc_not_stopped;
s->pending_insert_state = false;
+ if (s->vendor == SDHCI_VENDOR_FSL) {
+ s->norintstsen = 0x013f;
+ s->errintstsen = 0x117f;
+ }
}
static void sdhci_poweron_reset(DeviceState *dev)
@@ -665,12 +673,13 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
}
}
+ if (s->norintstsen & SDHC_NISEN_DMA) {
+ s->norintsts |= SDHC_NIS_DMA;
+ }
+
if (s->blkcnt == 0) {
sdhci_end_transfer(s);
} else {
- if (s->norintstsen & SDHC_NISEN_DMA) {
- s->norintsts |= SDHC_NIS_DMA;
- }
sdhci_update_irq(s);
}
}
@@ -691,9 +700,22 @@ static void sdhci_sdma_transfer_single_block(SDHCIState *s)
}
s->blkcnt--;
+ if (s->norintstsen & SDHC_NISEN_DMA) {
+ s->norintsts |= SDHC_NIS_DMA;
+ }
+
sdhci_end_transfer(s);
}
+static void sdhci_sdma_transfer(SDHCIState *s)
+{
+ if ((s->blkcnt == 1) || !(s->trnmod & SDHC_TRNS_MULTI)) {
+ sdhci_sdma_transfer_single_block(s);
+ } else {
+ sdhci_sdma_transfer_multi_blocks(s);
+ }
+}
+
typedef struct ADMADescr {
hwaddr addr;
uint16_t length;
@@ -925,12 +947,7 @@ static void sdhci_data_transfer(void *opaque)
if (s->trnmod & SDHC_TRNS_DMA) {
switch (SDHC_DMA_TYPE(s->hostctl1)) {
case SDHC_CTRL_SDMA:
- if ((s->blkcnt == 1) || !(s->trnmod & SDHC_TRNS_MULTI)) {
- sdhci_sdma_transfer_single_block(s);
- } else {
- sdhci_sdma_transfer_multi_blocks(s);
- }
-
+ sdhci_sdma_transfer(s);
break;
case SDHC_CTRL_ADMA1_32:
if (!(s->capareg & R_SDHC_CAPAB_ADMA1_MASK)) {
@@ -1174,11 +1191,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
if (!(mask & 0xFF000000) && s->blkcnt &&
(s->blksize & BLOCK_SIZE_MASK) &&
SDHC_DMA_TYPE(s->hostctl1) == SDHC_CTRL_SDMA) {
- if (s->trnmod & SDHC_TRNS_MULTI) {
- sdhci_sdma_transfer_multi_blocks(s);
- } else {
- sdhci_sdma_transfer_single_block(s);
- }
+ sdhci_sdma_transfer(s);
}
}
break;
@@ -1533,7 +1546,7 @@ const VMStateDescription sdhci_vmstate = {
},
};
-void sdhci_common_class_init(ObjectClass *klass, void *data)
+void sdhci_common_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -1550,6 +1563,8 @@ static const Property sdhci_sysbus_properties[] = {
false),
DEFINE_PROP_LINK("dma", SDHCIState,
dma_mr, TYPE_MEMORY_REGION, MemoryRegion *),
+ DEFINE_PROP_BOOL("wp-inverted", SDHCIState,
+ wp_inverted, false),
};
static void sdhci_sysbus_init(Object *obj)
@@ -1605,7 +1620,7 @@ static void sdhci_sysbus_unrealize(DeviceState *dev)
}
}
-static void sdhci_sysbus_class_init(ObjectClass *klass, void *data)
+static void sdhci_sysbus_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -1618,7 +1633,7 @@ static void sdhci_sysbus_class_init(ObjectClass *klass, void *data)
/* --- qdev bus master --- */
-static void sdhci_bus_class_init(ObjectClass *klass, void *data)
+static void sdhci_bus_class_init(ObjectClass *klass, const void *data)
{
SDBusClass *sbc = SD_BUS_CLASS(klass);
@@ -1720,16 +1735,10 @@ usdhc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
case USDHC_VENDOR_SPEC:
s->vendor_spec = value;
- switch (s->vendor) {
- case SDHCI_VENDOR_IMX:
- if (value & USDHC_IMX_FRC_SDCLK_ON) {
- s->prnsts &= ~SDHC_IMX_CLOCK_GATE_OFF;
- } else {
- s->prnsts |= SDHC_IMX_CLOCK_GATE_OFF;
- }
- break;
- default:
- break;
+ if (value & USDHC_IMX_FRC_SDCLK_ON) {
+ s->prnsts &= ~SDHC_IMX_CLOCK_GATE_OFF;
+ } else {
+ s->prnsts |= SDHC_IMX_CLOCK_GATE_OFF;
}
break;