sdhci: add quirk property for card insert interrupt status on Raspberry Pi
This quirk is a workaround for the following hardware behaviour, on which UEFI (specifically, the bootloader for Windows on Pi2) depends: 1. at boot with an SD card present, the interrupt status/enable registers are initially zero 2. upon enabling it in the interrupt enable register, the card insert bit in the interrupt status register is immediately set 3. after a subsequent controller reset, the card insert interrupt does not fire, even if enabled in the interrupt enable register Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com> Message-id: 1456436130-7048-3-git-send-email-Andrew.Baumann@microsoft.com Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
5c1bc9a234
commit
0a7ac9f9e7
@ -204,6 +204,7 @@ static void sdhci_reset(SDHCIState *s)
|
||||
|
||||
s->data_count = 0;
|
||||
s->stopped_state = sdhc_not_stopped;
|
||||
s->pending_insert_state = false;
|
||||
}
|
||||
|
||||
static void sdhci_data_transfer(void *opaque);
|
||||
@ -1095,6 +1096,13 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
|
||||
} else {
|
||||
s->norintsts &= ~SDHC_NIS_ERR;
|
||||
}
|
||||
/* Quirk for Raspberry Pi: pending card insert interrupt
|
||||
* appears when first enabled after power on */
|
||||
if ((s->norintstsen & SDHC_NISEN_INSERT) && s->pending_insert_state) {
|
||||
assert(s->pending_insert_quirk);
|
||||
s->norintsts |= SDHC_NIS_INSERT;
|
||||
s->pending_insert_state = false;
|
||||
}
|
||||
sdhci_update_irq(s);
|
||||
break;
|
||||
case SDHC_NORINTSIGEN:
|
||||
@ -1181,6 +1189,24 @@ static void sdhci_uninitfn(SDHCIState *s)
|
||||
s->fifo_buffer = NULL;
|
||||
}
|
||||
|
||||
static bool sdhci_pending_insert_vmstate_needed(void *opaque)
|
||||
{
|
||||
SDHCIState *s = opaque;
|
||||
|
||||
return s->pending_insert_state;
|
||||
}
|
||||
|
||||
static const VMStateDescription sdhci_pending_insert_vmstate = {
|
||||
.name = "sdhci/pending-insert",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = sdhci_pending_insert_vmstate_needed,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_BOOL(pending_insert_state, SDHCIState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
};
|
||||
|
||||
const VMStateDescription sdhci_vmstate = {
|
||||
.name = "sdhci",
|
||||
.version_id = 1,
|
||||
@ -1215,7 +1241,11 @@ const VMStateDescription sdhci_vmstate = {
|
||||
VMSTATE_TIMER_PTR(insert_timer, SDHCIState),
|
||||
VMSTATE_TIMER_PTR(transfer_timer, SDHCIState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
},
|
||||
.subsections = (const VMStateDescription*[]) {
|
||||
&sdhci_pending_insert_vmstate,
|
||||
NULL
|
||||
},
|
||||
};
|
||||
|
||||
/* Capabilities registers provide information on supported features of this
|
||||
@ -1273,6 +1303,8 @@ static Property sdhci_sysbus_properties[] = {
|
||||
DEFINE_PROP_UINT32("capareg", SDHCIState, capareg,
|
||||
SDHC_CAPAB_REG_DEFAULT),
|
||||
DEFINE_PROP_UINT32("maxcurr", SDHCIState, maxcurr, 0),
|
||||
DEFINE_PROP_BOOL("pending-insert-quirk", SDHCIState, pending_insert_quirk,
|
||||
false),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@ -1300,6 +1332,10 @@ static void sdhci_sysbus_realize(DeviceState *dev, Error ** errp)
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &sdhci_mmio_ops, s, "sdhci",
|
||||
SDHC_REGISTERS_MAP_SIZE);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
|
||||
if (s->pending_insert_quirk) {
|
||||
s->pending_insert_state = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void sdhci_sysbus_class_init(ObjectClass *klass, void *data)
|
||||
|
@ -76,6 +76,8 @@ typedef struct SDHCIState {
|
||||
uint32_t buf_maxsz;
|
||||
uint16_t data_count; /* current element in FIFO buffer */
|
||||
uint8_t stopped_state;/* Current SDHC state */
|
||||
bool pending_insert_quirk;/* Quirk for Raspberry Pi card insert int */
|
||||
bool pending_insert_state;
|
||||
/* Buffer Data Port Register - virtual access point to R and W buffers */
|
||||
/* Software Reset Register - always reads as 0 */
|
||||
/* Force Event Auto CMD12 Error Interrupt Reg - write only */
|
||||
|
Loading…
Reference in New Issue
Block a user