qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] sdhci: add quirk property for card insert interrupt


From: Andrew Baumann
Subject: [Qemu-devel] [PATCH] sdhci: add quirk property for card insert interrupt status on Raspberry Pi
Date: Thu, 31 Dec 2015 13:40:43 -0800

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

The implementation is relatively simple: if a card is present at power
on, remember that state as a "sticky" card insertion interrupt that
remains pending until enabled/cleared by the guest. We also need to
mask norintsts with norintstsen in sdhci_read, to avoid the interrupt
being visible before it is enabled.

Signed-off-by: Andrew Baumann <address@hidden>
---
This is a little less savoury than the previous version. The real
ugliness here is that it can't be replaced by interposing on the card
insert interrupt between sd and sdhci (once they are refactored to
support it), because the interrupt needs to be "sticky" at the SDHCI
level.

I initially considered making all interrupts sticky in this way (i.e.,
unconditionally setting interrupts in the status register and masking
it with the enable register when read, but the SDHCI spec (section
1.8) is pretty clear that the interrupt status enable register acts as
a mask before the interrupt state is latched; i.e. if the interrupt
occurs but it is disabled, then it is forever lost.

One possible interpretation to explain what I'm seeing is that card
insertion is level-triggered, i.e. it is signalled as long as a card
remains inserted, but that would require a more extensive reworking of
the card insertion/removal interrupts logic, and would require yet
another quirk for item 3 above.

If anyone has suggestions for a cleaner fix, I'm all ears!

Thanks,
Andrew

 hw/sd/sdhci.c         | 11 ++++++++++-
 include/hw/sd/sdhci.h |  1 +
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index dd83e89..6bce66a 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -892,7 +892,7 @@ static uint64_t sdhci_read(void *opaque, hwaddr offset, 
unsigned size)
         ret = s->clkcon | (s->timeoutcon << 16);
         break;
     case SDHC_NORINTSTS:
-        ret = s->norintsts | (s->errintsts << 16);
+        ret = (s->norintsts & s->norintstsen) | (s->errintsts << 16);
         break;
     case SDHC_NORINTSTSEN:
         ret = s->norintstsen | (s->errintstsen << 16);
@@ -1227,6 +1227,7 @@ static Property sdhci_pci_properties[] = {
     DEFINE_PROP_UINT32("capareg", SDHCIState, capareg,
             SDHC_CAPAB_REG_DEFAULT),
     DEFINE_PROP_UINT32("maxcurr", SDHCIState, maxcurr, 0),
+    DEFINE_PROP_BOOL("bcm2835-quirk", SDHCIState, bcm2835_quirk, false),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -1306,6 +1307,14 @@ 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);
+
+    /* Quirk for Raspberry Pi: set the card insert interrupt status.
+     * Needed to boot UEFI, which enables and then polls this bit at
+     * boot time before proceeding with card I/O.
+     */
+    if (s->bcm2835_quirk && (s->prnsts & SDHC_CARD_PRESENT)) {
+        s->norintsts |= SDHC_NIS_INSERT;
+    }
 }
 
 static void sdhci_sysbus_class_init(ObjectClass *klass, void *data)
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index e78d938..76fdd9b 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -77,6 +77,7 @@ typedef struct SDHCIState {
     uint32_t buf_maxsz;
     uint16_t data_count;   /* current element in FIFO buffer */
     uint8_t  stopped_state;/* Current SDHC state */
+    bool     bcm2835_quirk;/* Quirk for Raspberry Pi card insert status */
     /* 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 */
-- 
2.5.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]