Commit 7ceef5c3 authored by Len Brown's avatar Len Brown

[ACPI] "acpi_pic_sci=edge" in case platform requires Edge Triggered SCI

http://bugzilla.kernel.org/show_bug.cgi?id=1390
parent bc54efae
...@@ -91,6 +91,11 @@ running once the system is up. ...@@ -91,6 +91,11 @@ running once the system is up.
ht -- run only enough ACPI to enable Hyper Threading ht -- run only enough ACPI to enable Hyper Threading
See also Documentation/pm.txt. 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
ad1816= [HW,OSS] ad1816= [HW,OSS]
Format: <io>,<irq>,<dma>,<dma2> Format: <io>,<irq>,<dma>,<dma2>
See also Documentation/sound/oss/AD1816. See also Documentation/sound/oss/AD1816.
......
...@@ -249,29 +249,66 @@ acpi_parse_nmi_src ( ...@@ -249,29 +249,66 @@ acpi_parse_nmi_src (
#ifdef CONFIG_ACPI_BUS #ifdef CONFIG_ACPI_BUS
/* /*
* Set specified PIC IRQ to level triggered mode. * "acpi_pic_sci=level" (current default)
* programs the PIC-mode SCI to Level Trigger.
* (NO-OP if the BIOS set Level Trigger already)
*
* If a PIC-mode SCI is not recogznied or gives spurious IRQ7's
* it may require Edge Trigger -- use "acpi_pic_sci=edge"
* (NO-OP if the BIOS set Edge Trigger already)
* *
* Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers * 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. * for the 8259 PIC. bit[n] = 1 means irq[n] is Level, otherwise Edge.
* ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0) * ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0)
* ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0) * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0)
*
* As the BIOS should have done this for us,
* print a warning if the IRQ wasn't already set to level.
*/ */
void acpi_pic_set_level_irq(unsigned int irq) static __initdata acpi_pic_sci_trigger; /* 0: level, 1: edge */
void __init
acpi_pic_sci_set_trigger(unsigned int irq)
{ {
unsigned char mask = 1 << (irq & 7); unsigned char mask = 1 << (irq & 7);
unsigned int port = 0x4d0 + (irq >> 3); unsigned int port = 0x4d0 + (irq >> 3);
unsigned char val = inb(port); unsigned char val = inb(port);
printk(PREFIX "IRQ%d SCI:", irq);
if (!(val & mask)) { if (!(val & mask)) {
printk(KERN_WARNING PREFIX "IRQ %d was Edge Triggered, " printk(" Edge");
"setting to Level Triggerd\n", irq);
if (!acpi_pic_sci_trigger) {
printk(" set to Level");
outb(val | mask, port); outb(val | mask, port);
} }
} else {
printk(" Level");
if (acpi_pic_sci_trigger) {
printk(" set to Edge");
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 */ #endif /* CONFIG_ACPI_BUS */
......
...@@ -253,29 +253,66 @@ acpi_parse_hpet ( ...@@ -253,29 +253,66 @@ acpi_parse_hpet (
#ifdef CONFIG_ACPI_BUS #ifdef CONFIG_ACPI_BUS
/* /*
* Set specified PIC IRQ to level triggered mode. * "acpi_pic_sci=level" (current default)
* programs the PIC-mode SCI to Level Trigger.
* (NO-OP if the BIOS set Level Trigger already)
*
* If a PIC-mode SCI is not recogznied or gives spurious IRQ7's
* it may require Edge Trigger -- use "acpi_pic_sci=edge"
* (NO-OP if the BIOS set Edge Trigger already)
* *
* Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers * 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. * for the 8259 PIC. bit[n] = 1 means irq[n] is Level, otherwise Edge.
* ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0) * ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0)
* ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0) * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0)
*
* As the BIOS should have done this for us,
* print a warning if the IRQ wasn't already set to level.
*/ */
void acpi_pic_set_level_irq(unsigned int irq) static __initdata acpi_pic_sci_trigger; /* 0: level, 1: edge */
void __init
acpi_pic_sci_set_trigger(unsigned int irq)
{ {
unsigned char mask = 1 << (irq & 7); unsigned char mask = 1 << (irq & 7);
unsigned int port = 0x4d0 + (irq >> 3); unsigned int port = 0x4d0 + (irq >> 3);
unsigned char val = inb(port); unsigned char val = inb(port);
printk(PREFIX "IRQ%d SCI:", irq);
if (!(val & mask)) { if (!(val & mask)) {
printk(KERN_WARNING PREFIX "IRQ %d was Edge Triggered, " printk(" Edge");
"setting to Level Triggerd\n", irq);
if (!acpi_pic_sci_trigger) {
printk(" set to Level");
outb(val | mask, port); outb(val | mask, port);
} }
} else {
printk(" Level");
if (acpi_pic_sci_trigger) {
printk(" set to Edge");
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 */ #endif /* CONFIG_ACPI_BUS */
static unsigned long __init static unsigned long __init
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#define _COMPONENT ACPI_BUS_COMPONENT #define _COMPONENT ACPI_BUS_COMPONENT
ACPI_MODULE_NAME ("acpi_bus") ACPI_MODULE_NAME ("acpi_bus")
extern void acpi_pic_set_level_irq(unsigned int irq); extern void __init acpi_pic_sci_set_trigger(unsigned int irq);
FADT_DESCRIPTOR acpi_fadt; FADT_DESCRIPTOR acpi_fadt;
struct acpi_device *acpi_root; struct acpi_device *acpi_root;
...@@ -615,7 +615,7 @@ acpi_bus_init (void) ...@@ -615,7 +615,7 @@ acpi_bus_init (void)
if (acpi_ioapic) if (acpi_ioapic)
mp_config_ioapic_for_sci(acpi_fadt.sci_int); mp_config_ioapic_for_sci(acpi_fadt.sci_int);
else else
acpi_pic_set_level_irq(acpi_fadt.sci_int); acpi_pic_sci_set_trigger(acpi_fadt.sci_int);
#endif #endif
status = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION); status = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment