Implement interrupt controller on Bonito north bridge, as well
as PCI INTx mapping as per Fuloong 2E's hardware connection.

pci_bonito_set_irq is renamed to bonito_set_irq to reflect that
it also sets other IRQs on chip.

Signed-off-by: Jiaxun Yang <jiaxun.y...@flygoat.com>
---
 hw/pci-host/bonito.c | 96 ++++++++++++++++++++++++++++++----------------------
 1 file changed, 56 insertions(+), 40 deletions(-)

diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c
index 
7d6251a78d7e2e26803dd72968ca2ea7adcfe0e5..a599a1db4c068325b8c1aa8fb4a45f6b299b581b
 100644
--- a/hw/pci-host/bonito.c
+++ b/hw/pci-host/bonito.c
@@ -157,6 +157,22 @@ FIELD(BONGENCFG, PCIQUEUE,      12, 1)
 #define BONITO_INTEN            (0x38 >> 2)      /* 0x138 */
 #define BONITO_INTISR           (0x3c >> 2)      /* 0x13c */
 
+/* ICU Pins */
+#define ICU_PIN_MBOXx(x)        (0 + (x))
+#define ICU_PIN_DMARDY          4
+#define ICU_PIN_DMAEMPTY        5
+#define ICU_PIN_COPYRDY         6
+#define ICU_PIN_COPYEMPTY       7
+#define ICU_PIN_COPYERR         8
+#define ICU_PIN_PCIIRQ          9
+#define ICU_PIN_MASTERERR       10
+#define ICU_PIN_SYSTEMERR       11
+#define ICU_PIN_DRAMPERR        12
+#define ICU_PIN_RETRYERR        13
+#define ICU_PIN_INTTIMER        14
+#define ICU_PIN_GPIOx(x)        (16 + (x))
+#define ICU_PIN_GPINx(x)        (25 + (x))
+
 /* PCI mail boxes */
 #define BONITO_PCIMAIL0_OFFSET    0x40
 #define BONITO_PCIMAIL1_OFFSET    0x44
@@ -206,6 +222,7 @@ struct PCIBonitoState {
 
     BonitoState *pcihost;
     uint32_t regs[BONITO_REGS];
+    uint32_t icu_pin_state;
 
     struct bonldma {
         uint32_t ldmactrl;
@@ -242,6 +259,40 @@ struct BonitoState {
 #define TYPE_PCI_BONITO "Bonito"
 OBJECT_DECLARE_SIMPLE_TYPE(PCIBonitoState, PCI_BONITO)
 
+static void bonito_update_irq(PCIBonitoState *s)
+{
+    BonitoState *bs = s->pcihost;
+    uint32_t inten = s->regs[BONITO_INTEN];
+    uint32_t intisr = s->regs[BONITO_INTISR];
+    uint32_t intpol = s->regs[BONITO_INTPOL];
+    uint32_t intedge = s->regs[BONITO_INTEDGE];
+    uint32_t pin_state = s->icu_pin_state;
+    uint32_t level, edge;
+
+    pin_state = (pin_state & ~intpol) | (~pin_state & intpol);
+
+    level = pin_state & ~intedge;
+    edge = (pin_state & ~intisr) & intedge;
+
+    intisr = (intisr & intedge) | level;
+    intisr |= edge;
+    intisr &= inten;
+
+    s->regs[BONITO_INTISR] = intisr;
+
+    qemu_set_irq(*bs->pic, !!intisr);
+}
+
+static void bonito_set_irq(void *opaque, int irq, int level)
+{
+    BonitoState *bs = opaque;
+    PCIBonitoState *s = bs->pci_dev;
+
+    s->icu_pin_state = deposit32(s->icu_pin_state, irq, 1, !!level);
+
+    bonito_update_irq(s);
+}
+
 static void bonito_writel(void *opaque, hwaddr addr,
                           uint64_t val, unsigned size)
 {
@@ -289,12 +340,12 @@ static void bonito_writel(void *opaque, hwaddr addr,
         }
         break;
     case BONITO_INTENSET:
-        s->regs[BONITO_INTENSET] = val;
         s->regs[BONITO_INTEN] |= val;
+        bonito_update_irq(s);
         break;
     case BONITO_INTENCLR:
-        s->regs[BONITO_INTENCLR] = val;
         s->regs[BONITO_INTEN] &= ~val;
+        bonito_update_irq(s);
         break;
     case BONITO_INTEN:
     case BONITO_INTISR:
@@ -549,45 +600,10 @@ static const MemoryRegionOps bonito_spciconf_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-#define BONITO_IRQ_BASE 32
-
-static void pci_bonito_set_irq(void *opaque, int irq_num, int level)
-{
-    BonitoState *s = opaque;
-    qemu_irq *pic = s->pic;
-    PCIBonitoState *bonito_state = s->pci_dev;
-    int internal_irq = irq_num - BONITO_IRQ_BASE;
-
-    if (bonito_state->regs[BONITO_INTEDGE] & (1 << internal_irq)) {
-        qemu_irq_pulse(*pic);
-    } else {   /* level triggered */
-        if (bonito_state->regs[BONITO_INTPOL] & (1 << internal_irq)) {
-            qemu_irq_raise(*pic);
-        } else {
-            qemu_irq_lower(*pic);
-        }
-    }
-}
-
-/* map the original irq (0~3) to bonito irq (16~47, but 16~31 are unused) */
 static int pci_bonito_map_irq(PCIDevice *pci_dev, int irq_num)
 {
-    int slot;
-
-    slot = PCI_SLOT(pci_dev->devfn);
-
-    switch (slot) {
-    case 5:   /* FULOONG2E_VIA_SLOT, SouthBridge, IDE, USB, ACPI, AC97, MC97 */
-        return irq_num % 4 + BONITO_IRQ_BASE;
-    case 6:   /* FULOONG2E_ATI_SLOT, VGA */
-        return 4 + BONITO_IRQ_BASE;
-    case 7:   /* FULOONG2E_RTL_SLOT, RTL8139 */
-        return 5 + BONITO_IRQ_BASE;
-    case 8 ... 12: /* PCI slot 1 to 4 */
-        return (slot - 8 + irq_num) + 6 + BONITO_IRQ_BASE;
-    default:  /* Unknown device, don't do any translation */
-        return irq_num;
-    }
+    /* Fuloong 2E PCI INTX are connected to Bonito GPIN[3:0] */
+    return ICU_PIN_GPINx(irq_num);
 }
 
 static void bonito_reset_hold(Object *obj, ResetType type)
@@ -633,7 +649,7 @@ static void bonito_host_realize(DeviceState *dev, Error 
**errp)
 
     memory_region_init(&bs->pci_mem, OBJECT(dev), "pci.mem", 
BONITO_PCIHI_SIZE);
     phb->bus = pci_register_root_bus(dev, "pci",
-                                     pci_bonito_set_irq, pci_bonito_map_irq,
+                                     bonito_set_irq, pci_bonito_map_irq,
                                      dev, &bs->pci_mem, get_system_io(),
                                      PCI_DEVFN(5, 0), 32, TYPE_PCI_BUS);
 

-- 
Git-154)


Reply via email to