Kyösti Mälkki ([email protected]) just uploaded a new patch set to 
gerrit, which you can find at http://review.coreboot.org/300

-gerrit

commit fbfb2728b181dadd6d0d9ecb5b1f52d033e04cf1
Author: Kyösti Mälkki <[email protected]>
Date:   Tue Jan 31 17:24:12 2012 +0200

    IOAPIC: Divide setup_ioapic() in two parts.
    
    Currently some southbridge codes implement the init_ioapic() part
    locally and do not implement the load_vectors() part at all.
    I suspect that load_vectors() should always be called to enable
    IOAPIC interrupt routes before OS.
    
    Revised init_ioapic() to log on a critical level if one tries to
    change an already assigned (non-zero) APIC ID, or when the APIC ID
    is not assigned.
    
    Change-Id: Ic5e860b9b669ecd1e9ddac4bbb92d80bdb9c2fca
    Signed-off-by: Kyösti Mälkki <[email protected]>
---
 src/arch/x86/lib/ioapic.c |  151 +++++++++++++++++++++++++++++++++-----------
 1 files changed, 113 insertions(+), 38 deletions(-)

diff --git a/src/arch/x86/lib/ioapic.c b/src/arch/x86/lib/ioapic.c
index 81d964c..7d166b9 100644
--- a/src/arch/x86/lib/ioapic.c
+++ b/src/arch/x86/lib/ioapic.c
@@ -34,6 +34,11 @@ static void io_apic_write(u32 ioapic_base, u32 reg, u32 
value)
        write32(ioapic_base + 0x10, value);
 }
 
+/**
+ * Clear all IOAPIC vectors.
+ *
+ * @param ioapic_base          IOAPIC base address
+ */
 void clear_ioapic(u32 ioapic_base)
 {
        u32 low, high;
@@ -64,24 +69,84 @@ void clear_ioapic(u32 ioapic_base)
        }
 }
 
-void setup_ioapic(u32 ioapic_base, u8 ioapic_id)
+/**
+ * Assign IOAPIC with an ID and set delivery type.
+ *
+ * @param ioapic_base          IOAPIC base address
+ * @param new_id               If non-zero (1-15), assign new apic ID.
+ *                             If zero, use previously assigned apic ID.
+ * @param delivery             If 0x0, deliver interrupts on APIC serial bus
+ *                             If 0x1, deliver interrupts on FSB
+ */
+static void init_ioapic(u32 ioapic_base, u8 new_id, u8 delivery)
 {
-       u32 bsp_lapicid = lapicid();
-       u32 low, high;
-       u32 i, ioapic_interrupts;
+       u8 loud = 0;
+       u8 active_id;
+       u32 reg32;
 
-       printk(BIOS_DEBUG, "IOAPIC: Initializing IOAPIC at 0x%08x\n",
-              ioapic_base);
-       printk(BIOS_DEBUG, "IOAPIC: Bootstrap Processor Local APIC = 0x%02x\n",
-              bsp_lapicid);
+       reg32 = io_apic_read(ioapic_base, 0x00);
+       active_id = (reg32 >> 24) & 0xf;
+
+       /* Changing a previously assigned ID and attempting
+        * to use ID=0 here are logged at a critical level.
+        */
+       if ( ((active_id && new_id) && (active_id != new_id)) ||
+               !(active_id || new_id))
+               loud = 1;
+
+       if (!new_id) {
+               printk(loud ? BIOS_CRIT : BIOS_DEBUG,
+                       "IOAPIC: 0x%08x using old ID = %d\n",
+                       ioapic_base, active_id);
+
+       } else {
+               reg32 &= 0xf0ffffff;
+               reg32 |= (new_id & 0xf) << 24;
+               io_apic_write(ioapic_base, 0x00, reg32);
+
+               printk(loud ? BIOS_CRIT : BIOS_DEBUG,
+                       "IOAPIC: 0x%08x changing ID = %d->%d\n",
+                       ioapic_base, active_id, new_id);
+
+               reg32 = io_apic_read(ioapic_base, 0x00);
+               active_id = (reg32 >> 24) & 0xf;
+               if (active_id != new_id)
+                       printk(BIOS_CRIT,
+                               "IOAPIC: 0x%08x changing ID failed (%d!=%d)\n",
+                               ioapic_base, active_id, new_id);
+       }
 
-       if (ioapic_id) {
-               printk(BIOS_DEBUG, "IOAPIC: ID = 0x%02x\n", ioapic_id);
-               /* Set IOAPIC ID if it has been specified. */
-               io_apic_write(ioapic_base, 0x00,
-                       (io_apic_read(ioapic_base, 0x00) & 0xf0ffffff) |
-                       (ioapic_id << 24));
+       /* Assign interrupt delivery type. */
+       reg32 = io_apic_read(ioapic_base, 0x03);
+       switch (delivery) {
+               case 0:
+                       printk(BIOS_DEBUG, "IOAPIC: Delivery is on APIC serial 
bus\n");
+                       reg32 = 0x00;
+                       break;
+               case 1:
+                       printk(BIOS_DEBUG, "IOAPIC: Delivery is on FSB\n");
+                       reg32 = 0x01;
+                       break;
+               default:
+                       printk(BIOS_CRIT, "IOAPIC: Delivery is reverted to 
FSB\n");
+                       reg32 = 0x01;
+                       break;
        }
+       io_apic_write(ioapic_base, 0x03, reg32);
+}
+
+/**
+ * Fill IOAPIC vectors all targeting the same processor.
+ * Virtual Wire Mode on vector 0 is enabled, others remain disabled.
+ *
+ *
+ * @param ioapic_base          IOAPIC base address
+ * @param bsp_lapicid          APIC ID of a CPU to receive the interrupts
+ */
+static void load_vectors(u32 ioapic_base, u8 bsp_lapicid)
+{
+       u32 low, high;
+       u32 i, ioapic_interrupts;
 
        /* Read the available number of interrupts. */
        ioapic_interrupts = (io_apic_read(ioapic_base, 0x01) >> 16) & 0xff;
@@ -89,28 +154,6 @@ void setup_ioapic(u32 ioapic_base, u8 ioapic_id)
                ioapic_interrupts = 24;
        printk(BIOS_DEBUG, "IOAPIC: %d interrupts\n", ioapic_interrupts);
 
-// XXX this decision should probably be made elsewhere, and
-// it's the C3, not the EPIA this depends on.
-#if CONFIG_EPIA_VT8237R_INIT
-#define IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS
-#else
-#define IOAPIC_INTERRUPTS_ON_FSB
-#endif
-
-#ifdef IOAPIC_INTERRUPTS_ON_FSB
-       /*
-        * For the Pentium 4 and above APICs deliver their interrupts
-        * on the front side bus, enable that.
-        */
-       printk(BIOS_DEBUG, "IOAPIC: Enabling interrupts on FSB\n");
-       io_apic_write(ioapic_base, 0x03,
-                     io_apic_read(ioapic_base, 0x03) | (1 << 0));
-#endif
-#ifdef IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS
-       printk(BIOS_DEBUG, "IOAPIC: Enabling interrupts on APIC serial bus\n");
-       io_apic_write(ioapic_base, 0x03, 0);
-#endif
-
        /* Enable Virtual Wire Mode. */
        low = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
        high = bsp_lapicid << (56 - 32);
@@ -125,10 +168,8 @@ void setup_ioapic(u32 ioapic_base, u8 ioapic_id)
 
        printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n",
               0, high, low);
-
        low = DISABLED;
        high = NONE;
-
        for (i = 1; i < ioapic_interrupts; i++) {
                io_apic_write(ioapic_base, i * 2 + 0x10, low);
                io_apic_write(ioapic_base, i * 2 + 0x11, high);
@@ -137,3 +178,37 @@ void setup_ioapic(u32 ioapic_base, u8 ioapic_id)
                       i, high, low);
        }
 }
+
+// XXX this decision should probably be made elsewhere, and
+// it's the C3, not the EPIA this depends on.
+
+#if CONFIG_EPIA_VT8237R_INIT
+#define CONFIG_IOAPIC_DELIVERY_TYPE 0
+#else
+#define CONFIG_IOAPIC_DELIVERY_TYPE 1
+#endif
+
+/**
+ * Assign IOAPIC with an ID
+ *
+ * Compile-time options from mainboard Kconfig can affect the
+ * chosen IOAPIC operational mode.
+ *
+ * @param ioapic_base          IOAPIC base address
+ * @param new_id               If non-zero (1-15), assign new apic ID.
+ *                             If zero, use previously assigned apic ID.
+ */
+void setup_ioapic(u32 ioapic_base, u8 new_id)
+{
+       u8 bsp_lapicid = lapicid();
+       u8 ioapic_dt = CONFIG_IOAPIC_DELIVERY_TYPE;
+
+       printk(BIOS_DEBUG, "IOAPIC: Initializing IOAPIC at 0x%08x\n",
+              ioapic_base);
+       init_ioapic(ioapic_base, new_id, ioapic_dt);
+
+       printk(BIOS_DEBUG, "IOAPIC: Bootstrap Processor Local APIC ID = %d\n",
+              bsp_lapicid);
+       load_vectors(ioapic_base, bsp_lapicid);
+}
+

-- 
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to