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 0bccb851b436f1d319494a613a477c5fe1279911
Author: Kyösti Mälkki <[email protected]>
Date:   Wed Oct 19 01:29:03 2011 +0300

    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.
    I can push cleaned i82801 variants for testing.
    
    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 |  148 +++++++++++++++++++++++++++++++++------------
 1 files changed, 110 insertions(+), 38 deletions(-)

diff --git a/src/arch/x86/lib/ioapic.c b/src/arch/x86/lib/ioapic.c
index 3f64209..94f796b 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.
+ *
+ * @ioapic_base                IOAPIC base address
+ */
 void clear_ioapic(u32 ioapic_base)
 {
        u32 low, high;
@@ -64,24 +69,82 @@ void clear_ioapic(u32 ioapic_base)
        }
 }
 
-void setup_ioapic(u32 ioapic_base, u8 ioapic_id)
+/**
+ * Assign IOAPIC with an ID and set delivery type.
+ *
+ * @ioapic_base                IOAPIC base address
+ * @new_id             If non-zero (1-15), assign new apic ID. 
+ *                     If zero, use previously assigned apic ID.
+ * @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 loglvl = BIOS_DEBUG;
+       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;
 
-       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) & 0xfff0ffff) |
-                       (ioapic_id << 24));
+       /* 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))
+               loglvl=BIOS_CRIT;
+
+       if (!new_id) {
+               printk(loglvl, "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(loglvl, "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(loglvl, "IOAPIC: 0x%08x changing ID failed 
(%d!=%d)\n",
+                               ioapic_base, active_id, new_id);
+       }       
+
+       /* 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.
+ * 
+ *
+ * @ioapic_base                IOAPIC base address
+ * @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 +152,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 +166,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 +176,36 @@ 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.
+ *
+ * @ioapic_base                IOAPIC base address
+ * @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();
+
+       printk(BIOS_DEBUG, "IOAPIC: Initializing IOAPIC at 0x%08x\n",
+              ioapic_base);
+       init_ioapic(ioapic_base, new_id, CONFIG_IOAPIC_DELIVERY_TYPE);
+
+       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