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
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 (
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,
#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.
* 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);
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 */
#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)
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)
}
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
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");
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);
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)
#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;
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);