]> git.hungrycats.org Git - linux/commitdiff
[ACPI] ACPI SCI shall be level/low unless explicit over-ride
authorLen Brown <len.brown@intel.com>
Mon, 22 Mar 2004 11:02:16 +0000 (06:02 -0500)
committerLen Brown <lenb@dhcppc3.>
Mon, 22 Mar 2004 11:02:16 +0000 (06:02 -0500)
http://bugzilla.kernel.org/show_bug.cgi?id=1622
add "acpi_sci=edge" and "acpi_sci=high" manual over-ride

Documentation/kernel-parameters.txt
arch/i386/kernel/acpi/boot.c
arch/i386/kernel/mpparse.c
arch/i386/kernel/setup.c
drivers/acpi/bus.c
include/asm-i386/mpspec.h

index 8d3723dfc12823ec949c8598843bb7a317899672..28698bf78b1d7800235ce1de4cff4dc9a1a4e8a0 100644 (file)
@@ -99,10 +99,8 @@ running once the system is up.
 
                        See also Documentation/pm.txt.
  
-       acpi_pic_sci=   [HW,ACPI] ACPI System Control Interrupt trigger mode
-                       Format: { level | edge }
-                       level   Force PIC-mode SCI to Level Trigger (default)
-                       edge    Force PIC-mode SCI to Edge Trigge
+       acpi_sci=       [HW,ACPI] ACPI System Control Interrupt trigger mode
+                       Format: { level | edge |  high | low }
 
        acpi_irq_balance        [HW,ACPI] ACPI will balance active IRQs
                                default in APIC mode
index ba4bd13d7430ea5a1bccc43ca00bf47e90d95b10..702e85b4ea8ff3752a0935e269616aa05f0123f8 100644 (file)
@@ -50,6 +50,9 @@ int acpi_lapic;
 int acpi_ioapic;
 int acpi_strict;
 
+acpi_interrupt_flags acpi_sci_flags __initdata;
+int acpi_sci_override_gsi __initdata;
+
 #ifdef CONFIG_X86_LOCAL_APIC
 static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
 #endif
@@ -244,6 +247,34 @@ acpi_parse_ioapic (
        return 0;
 }
 
+/*
+ * Parse Interrupt Source Override for the ACPI SCI
+ */
+static void
+acpi_parse_sci_int_src_ovr(u8 bus_irq, u16 polarity, u16 trigger, u32 global_irq)
+{
+       if (trigger == 0)       /* compatible SCI trigger is level */
+               trigger = 3;
+
+       if (polarity == 0)      /* compatible SCI polarity is low */
+               polarity = 3;
+
+       /* Command-line over-ride via acpi_sci= */
+       if (acpi_sci_flags.trigger)
+               trigger = acpi_sci_flags.trigger;
+
+       if (acpi_sci_flags.polarity)
+               polarity = acpi_sci_flags.polarity;
+
+       mp_override_legacy_irq(bus_irq, polarity, trigger, global_irq);
+
+       /*
+        * stash over-ride to indicate we've been here
+        * and for later update of acpi_fadt
+        */
+       acpi_sci_override_gsi = global_irq;
+       return;
+}
 
 static int __init
 acpi_parse_int_src_ovr (
@@ -257,6 +288,13 @@ acpi_parse_int_src_ovr (
 
        acpi_table_print_madt_entry(header);
 
+       if (intsrc->bus_irq == acpi_fadt.sci_int) {
+               acpi_parse_sci_int_src_ovr(intsrc->bus_irq,
+                       intsrc->flags.polarity, intsrc->flags.trigger,
+                       intsrc->global_irq);
+               return 0;
+       }
+
        mp_override_legacy_irq (
                intsrc->bus_irq,
                intsrc->flags.polarity,
@@ -287,14 +325,14 @@ acpi_parse_nmi_src (
 #endif /* CONFIG_X86_IO_APIC */
 
 #ifdef CONFIG_ACPI_BUS
+
 /*
- * "acpi_pic_sci=level" (current default)
- * programs the PIC-mode SCI to Level Trigger.
- * (NO-OP if the BIOS set Level Trigger already)
+ * acpi_pic_sci_set_trigger()
+ * 
+ * use ELCR to set PIC-mode trigger type for SCI
  *
  * If a PIC-mode SCI is not recognized or gives spurious IRQ7's
- * it may require Edge Trigger -- use "acpi_pic_sci=edge"
- * (NO-OP if the BIOS set Edge Trigger already)
+ * it may require Edge Trigger -- use "acpi_sci=edge"
  *
  * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers
  * for the 8259 PIC.  bit[n] = 1 means irq[n] is Level, otherwise Edge.
@@ -302,10 +340,8 @@ acpi_parse_nmi_src (
  * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0)
  */
 
-static int __initdata  acpi_pic_sci_trigger;   /* 0: level, 1: edge */
-
 void __init
-acpi_pic_sci_set_trigger(unsigned int irq)
+acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
 {
        unsigned char mask = 1 << (irq & 7);
        unsigned int port = 0x4d0 + (irq >> 3);
@@ -316,37 +352,21 @@ acpi_pic_sci_set_trigger(unsigned int irq)
        if (!(val & mask)) {
                printk(" Edge");
 
-               if (!acpi_pic_sci_trigger) {
+               if (trigger == 3) {
                        printk(" set to Level");
                        outb(val | mask, port);
                }
        } else {
                printk(" Level");
 
-               if (acpi_pic_sci_trigger) {
+               if (trigger == 1) {
                        printk(" set to Edge");
-                       outb(val | mask, port);
+                       outb(val & ~mask, port);
                }
        }
        printk(" Trigger.\n");
 }
 
-int __init
-acpi_pic_sci_setup(char *str)
-{
-       while (str && *str) {
-               if (strncmp(str, "level", 5) == 0)
-                       acpi_pic_sci_trigger = 0;       /* force level trigger */
-               if (strncmp(str, "edge", 4) == 0)
-                       acpi_pic_sci_trigger = 1;       /* force edge trigger */
-               str = strchr(str, ',');
-               if (str)
-                       str += strspn(str, ", \t");
-       }
-       return 1;
-}
-
-__setup("acpi_pic_sci=", acpi_pic_sci_setup);
 
 #endif /* CONFIG_ACPI_BUS */
 
@@ -442,8 +462,6 @@ static int __init acpi_parse_hpet(unsigned long phys, unsigned long size)
 #define        acpi_parse_hpet NULL
 #endif
 
-/* detect the location of the ACPI PM Timer */
-#ifdef CONFIG_X86_PM_TIMER
 extern u32 pmtmr_ioport;
 
 static int __init acpi_parse_fadt(unsigned long phys, unsigned long size)
@@ -456,6 +474,13 @@ static int __init acpi_parse_fadt(unsigned long phys, unsigned long size)
                return 0;
        }
 
+#ifdef CONFIG_ACPI_INTERPRETER
+       /* initialize sci_int early for INT_SRC_OVR MADT parsing */
+       acpi_fadt.sci_int = fadt->sci_int;
+#endif
+
+#ifdef CONFIG_X86_PM_TIMER
+       /* detect the location of the ACPI PM Timer */
        if (fadt->revision >= FADT2_REVISION_ID) {
                /* FADT rev. 2 */
                if (fadt->xpm_tmr_blk.address_space_id != ACPI_ADR_SPACE_SYSTEM_IO)
@@ -468,11 +493,9 @@ static int __init acpi_parse_fadt(unsigned long phys, unsigned long size)
        }
        if (pmtmr_ioport)
                printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n", pmtmr_ioport);
+#endif
        return 0;
 }
-#else
-#define        acpi_parse_fadt NULL
-#endif
 
 
 unsigned long __init
@@ -592,6 +615,13 @@ acpi_parse_madt_ioapic_entries(void)
                return count;
        }
 
+       /*
+        * If BIOS did not supply an INT_SRC_OVR for the SCI
+        * pretend we got one so we can set the SCI flags.
+        */
+       if (!acpi_sci_override_gsi)
+               acpi_parse_sci_int_src_ovr(acpi_fadt.sci_int, 0, 0, acpi_fadt.sci_int);
+
        count = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, NR_IRQ_VECTORS);
        if (count < 0) {
                printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
@@ -696,12 +726,16 @@ acpi_boot_init (void)
                return error;
        }
 
+       /*
+        * set sci_int and PM timer address
+        */
+       acpi_table_parse(ACPI_FADT, acpi_parse_fadt);
+
        /*
         * Process the Multiple APIC Description Table (MADT), if present
         */
        acpi_process_madt();
 
-       acpi_table_parse(ACPI_FADT, acpi_parse_fadt);
        acpi_table_parse(ACPI_HPET, acpi_parse_hpet);
        acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
 
index de099534aa65ccd1bd0826c74dd2647983fdb453..17d1bb236547ecc789f6434d9c8189cbdf5762be 100644 (file)
@@ -1036,69 +1036,6 @@ void __init mp_config_acpi_legacy_irqs (void)
 
 extern FADT_DESCRIPTOR acpi_fadt;
 
-void __init mp_config_ioapic_for_sci(u32 gsi)
-{
-       int ioapic;
-       int ioapic_pin;
-       struct acpi_table_madt *madt;
-       struct acpi_table_int_src_ovr *entry = NULL;
-       acpi_interrupt_flags flags;
-       void *madt_end;
-       acpi_status status;
-
-       /*
-        * Ensure that if there is an interrupt source override entry
-        * for the ACPI SCI, we leave it as is. Unfortunately this involves
-        * walking the MADT again.
-        */
-       status = acpi_get_firmware_table("APIC", 1, ACPI_LOGICAL_ADDRESSING,
-               (struct acpi_table_header **) &madt);
-       if (ACPI_SUCCESS(status)) {
-               madt_end = (void *) (unsigned long)madt + madt->header.length;
-
-               entry = (struct acpi_table_int_src_ovr *)
-                ((unsigned long) madt + sizeof(struct acpi_table_madt));
-
-               while ((void *) entry < madt_end) {
-                       if (entry->header.type == ACPI_MADT_INT_SRC_OVR &&
-                           acpi_fadt.sci_int == entry->bus_irq)
-                               goto found;
-                       
-                       entry = (struct acpi_table_int_src_ovr *)
-                               ((unsigned long) entry + entry->header.length);
-               }
-       }
-       /*
-        * Although the ACPI spec says that the SCI should be level/low
-        * don't reprogram it unless there is an explicit MADT OVR entry
-        * instructing us to do so -- otherwise we break Tyan boards which
-        * have the SCI wired edge/high but no MADT OVR.
-        */
-       return;
-
-found:
-       /*
-        * See the note at the end of ACPI 2.0b section
-        * 5.2.10.8 for what this is about.
-        */
-       flags = entry->flags;
-       acpi_fadt.sci_int = entry->global_irq;
-       gsi = entry->global_irq;
-
-       ioapic = mp_find_ioapic(gsi);
-
-       ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
-
-       /*
-        * MPS INTI flags:
-        *  trigger: 0=default, 1=edge, 3=level
-        *  polarity: 0=default, 1=high, 3=low
-        * Per ACPI spec, default for SCI means level/low.
-        */
-       io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, 
-               (flags.trigger == 1 ? 0 : 1), (flags.polarity == 1 ? 0 : 1));
-}
-
 #ifdef CONFIG_ACPI_PCI
 
 void __init mp_parse_prt (void)
index b229585170eef906087c1bd400cd2917c10ecf74..faad9c4a520530bc4beb0f0d70d65d7df8633236 100644 (file)
@@ -79,6 +79,7 @@ EXPORT_SYMBOL(acpi_disabled);
 
 #ifdef CONFIG_ACPI_BOOT
 int __initdata acpi_force = 0;
+extern acpi_interrupt_flags    acpi_sci_flags;
 #endif
 
 int MCA_bus;
@@ -596,6 +597,18 @@ static void __init parse_cmdline_early (char ** cmdline_p)
                        acpi_noirq_set();
                }
 
+               else if (!memcmp(from, "acpi_sci=edge", 13))
+                       acpi_sci_flags.trigger =  1;
+
+               else if (!memcmp(from, "acpi_sci=level", 14))
+                       acpi_sci_flags.trigger = 3;
+
+               else if (!memcmp(from, "acpi_sci=high", 13))
+                       acpi_sci_flags.polarity = 1;
+
+               else if (!memcmp(from, "acpi_sci=low", 12))
+                       acpi_sci_flags.polarity = 3;
+
 #ifdef CONFIG_X86_LOCAL_APIC
                /* disable IO-APIC */
                else if (!memcmp(from, "noapic", 6))
index fb1a5efe7755f6a0e5f05c21a3aa1a1b4d9a21b5..59ed56f5d529d012282b62ba93ddd571c1bf27ab 100644 (file)
 #define _COMPONENT             ACPI_BUS_COMPONENT
 ACPI_MODULE_NAME               ("acpi_bus")
 
+#ifdef CONFIG_X86_64
 extern void __init acpi_pic_sci_set_trigger(unsigned int irq);
+#elif  defined(CONFIG_X86)
+extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger);
+#endif
 
 FADT_DESCRIPTOR                        acpi_fadt;
 struct acpi_device             *acpi_root;
@@ -609,13 +613,25 @@ acpi_bus_init (void)
                printk(KERN_ERR PREFIX "Unable to get the FADT\n");
                goto error1;
        }
-
-#ifdef CONFIG_X86
+#ifdef CONFIG_X86_64
        /* Ensure the SCI is set to level-triggered, active-low */
        if (acpi_ioapic)
                mp_config_ioapic_for_sci(acpi_fadt.sci_int);
        else
                acpi_pic_sci_set_trigger(acpi_fadt.sci_int);
+#elif defined(CONFIG_X86)
+       if (!acpi_ioapic) {
+               extern acpi_interrupt_flags acpi_sci_flags;
+               /* Set PIC-mode SCI trigger type */
+               acpi_pic_sci_set_trigger(acpi_fadt.sci_int, acpi_sci_flags.trigger);
+       } else {
+               extern int acpi_sci_override_gsi;
+               /*
+                * now that acpi_fadt is initialized,
+                * update it with result from INT_SRC_OVR parsing
+                */
+               acpi_fadt.sci_int = acpi_sci_override_gsi;
+       }
 #endif
 
        status = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION);
index 6af573bc81c0269dd32ca122a3455f615268c2f3..78bd12b7ae4221b0814526a3554d3e078f7c24d5 100644 (file)
@@ -34,13 +34,6 @@ extern void mp_register_ioapic (u8 id, u32 address, u32 gsi_base);
 extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 gsi);
 extern void mp_config_acpi_legacy_irqs (void);
 extern void mp_parse_prt (void);
-
-#ifdef CONFIG_X86_IO_APIC
-extern void mp_config_ioapic_for_sci(u32 gsi);
-#else
-static inline void mp_config_ioapic_for_sci(u32 gsi)
-{ }
-#endif
 #endif /*CONFIG_ACPI_BOOT*/
 
 #define PHYSID_ARRAY_SIZE      BITS_TO_LONGS(MAX_APICS)