Kyösti Mälkki (kyosti.malkki@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/302
-gerrit
commit 480d5a0e605800bba8725cc37a6b251ce309288d Author: Kyösti Mälkki kyosti.malkki@gmail.com Date: Tue Jan 31 16:40:31 2012 +0200
Refactor and clean-up i82801 LPC codes
Rewrite IOAPIC initialisation using global setup_ioapic() or setup_ioapic_novectors(). In my opinion, the _novectors() variant that is currently used is not sufficient to route IOAPIC interrupts on boot since Virtual Wire programming and/or vectors are not programmed. That takes further study and separate patch.
Select Kconfig option IOAPIC as the southbridge has one and now requires that arch/x86/lib/ioapic.c is compiled in.
Unify handling of ACPI BARs.
Enable device resources during dev->ops->enable() and not during dev->ops->init().
Change-Id: I8ad80fdd0913995471269f33293c4a4b8cf1de83 Signed-off-by: Kyösti Mälkki kyosti.malkki@gmail.com --- src/arch/x86/include/arch/ioapic.h | 1 + src/arch/x86/lib/ioapic.c | 11 +++ src/southbridge/intel/i82801ax/Kconfig | 1 + src/southbridge/intel/i82801ax/lpc.c | 59 ++++++++++------ src/southbridge/intel/i82801bx/Kconfig | 1 + src/southbridge/intel/i82801bx/lpc.c | 58 +++++++++------ src/southbridge/intel/i82801cx/Kconfig | 1 + src/southbridge/intel/i82801cx/lpc.c | 107 ++++++++++++++++------------- src/southbridge/intel/i82801dx/i82801dx.h | 1 + src/southbridge/intel/i82801dx/lpc.c | 68 +++++++++++-------- src/southbridge/intel/i82801ex/i82801ex.h | 9 +++ src/southbridge/intel/i82801ex/lpc.c | 82 +++++++++++++++------- src/southbridge/intel/i82801gx/i82801gx.h | 1 + src/southbridge/intel/i82801gx/lpc.c | 77 ++++++++++++--------- 14 files changed, 297 insertions(+), 180 deletions(-)
diff --git a/src/arch/x86/include/arch/ioapic.h b/src/arch/x86/include/arch/ioapic.h index 623f617..3eabcdc 100644 --- a/src/arch/x86/include/arch/ioapic.h +++ b/src/arch/x86/include/arch/ioapic.h @@ -40,5 +40,6 @@
void setup_ioapic(u32 ioapic_base, u8 ioapic_id); void clear_ioapic(u32 ioapic_base); +void setup_ioapic_novectors(u32 ioapic_base, u8 new_id);
#endif diff --git a/src/arch/x86/lib/ioapic.c b/src/arch/x86/lib/ioapic.c index 5e17990..1d42658 100644 --- a/src/arch/x86/lib/ioapic.c +++ b/src/arch/x86/lib/ioapic.c @@ -203,3 +203,14 @@ void setup_ioapic(u32 ioapic_base, u8 new_id) load_vectors(ioapic_base, bsp_lapicid); }
+void setup_ioapic_novectors(u32 ioapic_base, u8 new_id) +{ + 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_CRIT, "IOAPIC: Interrupt Vectors were not initialized\n"); +} + diff --git a/src/southbridge/intel/i82801ax/Kconfig b/src/southbridge/intel/i82801ax/Kconfig index 70734a7..71ae016 100644 --- a/src/southbridge/intel/i82801ax/Kconfig +++ b/src/southbridge/intel/i82801ax/Kconfig @@ -19,6 +19,7 @@
config SOUTHBRIDGE_INTEL_I82801AX bool + select IOAPIC select HAVE_HARD_RESET select USE_WATCHDOG_ON_BOOT
diff --git a/src/southbridge/intel/i82801ax/lpc.c b/src/southbridge/intel/i82801ax/lpc.c index c9404ed..c6be112 100644 --- a/src/southbridge/intel/i82801ax/lpc.c +++ b/src/southbridge/intel/i82801ax/lpc.c @@ -70,17 +70,30 @@ typedef struct southbridge_intel_i82801ax_config config_t; * Use the defined IRQ values above or set mainboard * specific IRQ values in your devicetree.cb. */ -static void i82801ax_enable_apic(struct device *dev) -{ - u32 reg32; - volatile u32 *ioapic_index = (volatile u32 *)IO_APIC_ADDR; - volatile u32 *ioapic_data = (volatile u32 *)(IO_APIC_ADDR + 0x10);
+ +/** + * Enable ACPI I/O range. + * + * @param dev PCI device with ACPI and PM BAR's + */ +static void i82801ax_enable_acpi(struct device *dev) +{ /* Set ACPI base address (I/O space). */ pci_write_config32(dev, PMBASE, (PMBASE_ADDR | 1));
/* Enable ACPI I/O range decode and ACPI power management. */ pci_write_config8(dev, ACPI_CNTL, ACPI_EN); +} + +/** + * Set miscellanous static southbridge features. + * + * @param dev PCI device with I/O APIC control registers + */ +static void i82801ax_general_cntl(struct device *dev) +{ + u32 reg32;
reg32 = pci_read_config32(dev, GEN_CNTL); reg32 |= (1 << 13); /* Coprocessor error enable (COPR_ERR_EN) */ @@ -88,20 +101,8 @@ static void i82801ax_enable_apic(struct device *dev) reg32 |= (1 << 2); /* DMA collection buffer enable (DCB_EN) */ reg32 |= (1 << 1); /* Delayed transaction enable (DTE) */ pci_write_config32(dev, GEN_CNTL, reg32); - printk(BIOS_DEBUG, "IOAPIC Southbridge enabled %x\n", reg32); - - *ioapic_index = 0; - *ioapic_data = (1 << 25); + printk(BIOS_DEBUG, "Southbridge GEN_CNTL 0x%08x\n", reg32);
- *ioapic_index = 0; - reg32 = *ioapic_data; - printk(BIOS_DEBUG, "Southbridge APIC ID = %x\n", reg32); - if (reg32 != (1 << 25)) - die("APIC Error\n"); - - /* TODO: From i82801ca, needed/useful on other ICH? */ - *ioapic_index = 3; /* Select Boot Configuration register. */ - *ioapic_data = 1; /* Use Processor System Bus to deliver interrupts. */ }
static void i82801ax_enable_serial_irqs(struct device *dev) @@ -216,11 +217,8 @@ static void i82801ax_lpc_decode_en(device_t dev)
static void lpc_init(struct device *dev) { - /* Set the value for PCI command register. */ - pci_write_config16(dev, PCI_COMMAND, 0x000f); - /* IO APIC initialization. */ - i82801ax_enable_apic(dev); + setup_ioapic_novectors(IO_APIC_ADDR, 0x02);
i82801ax_enable_serial_irqs(dev);
@@ -272,10 +270,25 @@ static void i82801ax_lpc_read_resources(device_t dev) res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; }
+static void i82801ax_lpc_enable_resources(device_t dev) +{ + /* Enable the normal PCI resources. */ + pci_dev_enable_resources(dev); + + /* Enable ACPI and GPIO BARs. */ + i82801ax_enable_acpi(dev); + + /* Set features (most important: IOAPIC). */ + i82801ax_general_cntl(dev); + + /* Set the value for PCI command register. */ + pci_write_config16(dev, PCI_COMMAND, 0x000f); +} + static struct device_operations lpc_ops = { .read_resources = i82801ax_lpc_read_resources, .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, + .enable_resources = i82801ax_lpc_enable_resources, .init = lpc_init, .scan_bus = scan_static_bus, .enable = i82801ax_enable, diff --git a/src/southbridge/intel/i82801bx/Kconfig b/src/southbridge/intel/i82801bx/Kconfig index 00cb5bf..3d725d4 100644 --- a/src/southbridge/intel/i82801bx/Kconfig +++ b/src/southbridge/intel/i82801bx/Kconfig @@ -19,6 +19,7 @@
config SOUTHBRIDGE_INTEL_I82801BX bool + select IOAPIC select HAVE_HARD_RESET select USE_WATCHDOG_ON_BOOT
diff --git a/src/southbridge/intel/i82801bx/lpc.c b/src/southbridge/intel/i82801bx/lpc.c index 0ff44e6..34eccf3 100644 --- a/src/southbridge/intel/i82801bx/lpc.c +++ b/src/southbridge/intel/i82801bx/lpc.c @@ -72,17 +72,29 @@ typedef struct southbridge_intel_i82801bx_config config_t; * Use the defined IRQ values above or set mainboard * specific IRQ values in your devicetree.cb. */ -static void i82801bx_enable_apic(struct device *dev) -{ - uint32_t reg32; - volatile uint32_t *ioapic_index = (volatile uint32_t *)IO_APIC_ADDR; - volatile uint32_t *ioapic_data = (volatile uint32_t *)(IO_APIC_ADDR + 0x10);
+/** + * Enable ACPI I/O range. + * + * @param dev PCI device with ACPI and PM BAR's + */ +static void i82801bx_enable_acpi(struct device *dev) +{ /* Set ACPI base address (I/O space). */ pci_write_config32(dev, PMBASE, (PMBASE_ADDR | 1));
/* Enable ACPI I/O range decode and ACPI power management. */ pci_write_config8(dev, ACPI_CNTL, ACPI_EN); +} + +/** + * Set miscellanous static southbridge features. + * + * @param dev PCI device with I/O APIC control registers + */ +static void i82801bx_general_cntl(struct device *dev) +{ + u32 reg32;
reg32 = pci_read_config32(dev, GEN_CNTL); reg32 |= (1 << 13); /* Coprocessor error enable (COPR_ERR_EN) */ @@ -90,20 +102,8 @@ static void i82801bx_enable_apic(struct device *dev) reg32 |= (1 << 2); /* DMA collection buffer enable (DCB_EN) */ reg32 |= (1 << 1); /* Delayed transaction enable (DTE) */ pci_write_config32(dev, GEN_CNTL, reg32); - printk(BIOS_DEBUG, "IOAPIC Southbridge enabled %x\n", reg32); - - *ioapic_index = 0; - *ioapic_data = (1 << 25); - - *ioapic_index = 0; - reg32 = *ioapic_data; - printk(BIOS_DEBUG, "Southbridge APIC ID = %x\n", reg32); - if (reg32 != (1 << 25)) - die("APIC Error\n"); + printk(BIOS_DEBUG, "Southbridge GEN_CNTL 0x%08x\n", reg32);
- /* TODO: From i82801ca, needed/useful on other ICH? */ - *ioapic_index = 3; /* Select Boot Configuration register. */ - *ioapic_data = 1; /* Use Processor System Bus to deliver interrupts. */ }
static void i82801bx_enable_serial_irqs(struct device *dev) @@ -234,11 +234,8 @@ static void lpc_init(struct device *dev) { uint16_t ich_model = pci_read_config16(dev, PCI_DEVICE_ID);
- /* Set the value for PCI command register. */ - pci_write_config16(dev, PCI_COMMAND, 0x000f); - /* IO APIC initialization. */ - i82801bx_enable_apic(dev); + setup_ioapic_novectors(IO_APIC_ADDR, 0x02);
i82801bx_enable_serial_irqs(dev);
@@ -290,10 +287,25 @@ static void i82801bx_lpc_read_resources(device_t dev) res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; }
+static void i82801bx_lpc_enable_resources(device_t dev) +{ + /* Enable the normal PCI resources. */ + pci_dev_enable_resources(dev); + + /* Enable ACPI and GPIO BARs. */ + i82801bx_enable_acpi(dev); + + /* Set features (most important: IOAPIC). */ + i82801bx_general_cntl(dev); + + /* Set the value for PCI command register. */ + pci_write_config16(dev, PCI_COMMAND, 0x000f); +} + static struct device_operations lpc_ops = { .read_resources = i82801bx_lpc_read_resources, .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, + .enable_resources = i82801bx_lpc_enable_resources, .init = lpc_init, .scan_bus = scan_static_bus, .enable = i82801bx_enable, diff --git a/src/southbridge/intel/i82801cx/Kconfig b/src/southbridge/intel/i82801cx/Kconfig index a0c775d..7534cbb 100644 --- a/src/southbridge/intel/i82801cx/Kconfig +++ b/src/southbridge/intel/i82801cx/Kconfig @@ -1,2 +1,3 @@ config SOUTHBRIDGE_INTEL_I82801CX bool + select IOAPIC diff --git a/src/southbridge/intel/i82801cx/lpc.c b/src/southbridge/intel/i82801cx/lpc.c index a1ffb8f..bacca48 100644 --- a/src/southbridge/intel/i82801cx/lpc.c +++ b/src/southbridge/intel/i82801cx/lpc.c @@ -24,34 +24,43 @@ #define MAINBOARD_POWER_ON 1
-static void i82801cx_enable_ioapic( struct device *dev) +/** + * Enable ACPI I/O range. + * + * @param dev PCI device with ACPI and PM BAR's + */ +static void i82801cx_enable_acpi(struct device *dev) +{ + // Set ACPI base address to 0x1100 (I/O space) + pci_write_config32(dev, PMBASE, 0x00001101); + + // Enable ACPI I/O and power management + pci_write_config8(dev, ACPI_CNTL, 0x10); + + // Set GPIO base address to 0x1180 (I/O space) + pci_write_config32(dev, GPIO_BASE, 0x00001181); + + // Enable GPIO + pci_write_config8(dev, GPIO_CNTL, 0x10); +} + +/** + * Set miscellanous static southbridge features. + * + * @param dev PCI device with I/O APIC control registers + */ +static void i82801cx_general_cntl(struct device *dev) { - uint32_t dword; - volatile uint32_t* ioapic_index = (volatile uint32_t*)IO_APIC_ADDR; - volatile uint32_t* ioapic_data = (volatile uint32_t*)(IO_APIC_ADDR + 0x10); - - dword = pci_read_config32(dev, GEN_CNTL); - dword |= (3 << 7); /* enable ioapic & disable SMBus interrupts */ - dword |= (1 <<13); /* coprocessor error enable */ - dword |= (1 << 1); /* delay transaction enable */ - dword |= (1 << 2); /* DMA collection buf enable */ - pci_write_config32(dev, GEN_CNTL, dword); - printk(BIOS_DEBUG, "ioapic southbridge enabled %x\n",dword); - - // Must program the APIC's ID before using it - - *ioapic_index = 0; // Select APIC ID register - *ioapic_data = (2<<24); - - // Hang if the ID didn't take (chip not present?) - *ioapic_index = 0; - dword = *ioapic_data; - printk(BIOS_DEBUG, "Southbridge apic id = %x\n", (dword>>24) & 0xF); - if(dword != (2<<24)) - die(""); - - *ioapic_index = 3; // Select Boot Configuration register - *ioapic_data = 1; // Use Processor System Bus to deliver interrupts + u32 reg32; + + reg32 = pci_read_config32(dev, GEN_CNTL); + reg32 |= (1 << 13); /* Coprocessor error enable (COPR_ERR_EN) */ + reg32 |= (3 << 7); /* IOAPIC enable (APIC_EN) */ + reg32 |= (1 << 2); /* DMA collection buffer enable (DCB_EN) */ + reg32 |= (1 << 1); /* Delayed transaction enable (DTE) */ + pci_write_config32(dev, GEN_CNTL, reg32); + printk(BIOS_DEBUG, "Southbridge GEN_CNTL 0x%08x\n", reg32); + }
// This is how interrupts are received from the Super I/O chip @@ -118,20 +127,6 @@ static void i82801cx_rtc_init(struct device *dev)
static void i82801cx_1f0_misc(struct device *dev) { - // Prevent LPC disabling, enable parity errors, and SERR# (System Error) - pci_write_config16(dev, PCI_COMMAND, 0x014f); - - // Set ACPI base address to 0x1100 (I/O space) - pci_write_config32(dev, PMBASE, 0x00001101); - - // Enable ACPI I/O and power management - pci_write_config8(dev, ACPI_CNTL, 0x10); - - // Set GPIO base address to 0x1180 (I/O space) - pci_write_config32(dev, GPIO_BASE, 0x00001181); - - // Enable GPIO - pci_write_config8(dev, GPIO_CNTL, 0x10);
// Route PIRQA to IRQ11, PIRQB to IRQ3, PIRQC to IRQ5, PIRQD to IRQ10 pci_write_config32(dev, PIRQA_ROUT, 0x0A05030B); @@ -160,8 +155,9 @@ static void lpc_init(struct device *dev) int pwr_on=-1; int nmi_option;
+ i82801cx_general_cntl(dev); /* IO APIC initialization */ - i82801cx_enable_ioapic(dev); + setup_ioapic_novectors(IO_APIC_ADDR, 0x02);
i82801cx_enable_serial_irqs(dev);
@@ -229,13 +225,28 @@ static void i82801cx_lpc_read_resources(device_t dev) res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; }
+static void i82801cx_lpc_enable_resources(device_t dev) +{ + /* Enable the normal PCI resources. */ + pci_dev_enable_resources(dev); + + /* Enable ACPI and GPIO BARs. */ + i82801cx_enable_acpi(dev); + + /* Set features (most important: IOAPIC). */ + i82801cx_general_cntl(dev); + + /* Prevent LPC disabling, enable parity errors, and SERR# (System Error). */ + pci_write_config16(dev, PCI_COMMAND, 0x014f); +} + static struct device_operations lpc_ops = { - .read_resources = i82801cx_lpc_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = lpc_init, - .scan_bus = scan_static_bus, - .enable = 0, + .read_resources = i82801cx_lpc_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = i82801cx_lpc_enable_resources, + .init = lpc_init, + .scan_bus = scan_static_bus, + .enable = 0, };
static const struct pci_driver lpc_driver __pci_driver = { diff --git a/src/southbridge/intel/i82801dx/i82801dx.h b/src/southbridge/intel/i82801dx/i82801dx.h index a38c793..2484eb1 100644 --- a/src/southbridge/intel/i82801dx/i82801dx.h +++ b/src/southbridge/intel/i82801dx/i82801dx.h @@ -86,6 +86,7 @@ extern void i82801dx_enable(device_t dev); #define PMBASE_ADDR 0x0400 #define DEFAULT_PMBASE PMBASE_ADDR #define ACPI_CNTL 0x44 +#define ACPI_EN (1 << 4) #define BIOS_CNTL 0x4E #define GPIO_BASE 0x58 #define GPIO_CNTL 0x5C diff --git a/src/southbridge/intel/i82801dx/lpc.c b/src/southbridge/intel/i82801dx/lpc.c index 768e700..eec984d 100644 --- a/src/southbridge/intel/i82801dx/lpc.c +++ b/src/southbridge/intel/i82801dx/lpc.c @@ -36,37 +36,37 @@
typedef struct southbridge_intel_i82801dx_config config_t;
-static void i82801dx_enable_ioapic(struct device *dev) +/** + * Enable ACPI I/O range. + * + * @param dev PCI device with ACPI and PM BAR's + */ +static void i82801dx_enable_acpi(struct device *dev) { - u32 reg32; - volatile u32 *ioapic_index = (volatile u32 *)(IO_APIC_ADDR); - volatile u32 *ioapic_data = (volatile u32 *)(IO_APIC_ADDR + 0x10); - /* Set ACPI base address (I/O space). */ pci_write_config32(dev, PMBASE, (PMBASE_ADDR | 1));
- /* Enable ACPI I/O and power management. */ - pci_write_config8(dev, ACPI_CNTL, 0x10); + /* Enable ACPI I/O range decode and ACPI power management. */ + pci_write_config8(dev, ACPI_CNTL, ACPI_EN); +} + +/** + * Set miscellanous static southbridge features. + * + * @param dev PCI device with I/O APIC control registers + */ +static void i82801dx_general_cntl(struct device *dev) +{ + u32 reg32;
reg32 = pci_read_config32(dev, GEN_CNTL); - reg32 |= (3 << 7); /* Enable IOAPIC */ - reg32 |= (1 << 13); /* Coprocessor error enable */ - reg32 |= (1 << 1); /* Delayed transaction enable */ - reg32 |= (1 << 2); /* DMA collection buffer enable */ + reg32 |= (1 << 13); /* Coprocessor error enable (COPR_ERR_EN) */ + reg32 |= (3 << 7); /* IOAPIC enable (APIC_EN) */ + reg32 |= (1 << 2); /* DMA collection buffer enable (DCB_EN) */ + reg32 |= (1 << 1); /* Delayed transaction enable (DTE) */ pci_write_config32(dev, GEN_CNTL, reg32); - printk(BIOS_DEBUG, "IOAPIC Southbridge enabled %x\n", reg32); - - *ioapic_index = 0; - *ioapic_data = (1 << 25); - - *ioapic_index = 0; - reg32 = *ioapic_data; - printk(BIOS_DEBUG, "Southbridge APIC ID = %x\n", reg32); - if (reg32 != (1 << 25)) - die("APIC Error\n"); + printk(BIOS_DEBUG, "Southbridge GEN_CNTL 0x%08x\n", reg32);
- *ioapic_index = 3; /* Select Boot Configuration register. */ - *ioapic_data = 1; /* Use Processor System Bus to deliver interrupts. */ }
static void i82801dx_enable_serial_irqs(struct device *dev) @@ -264,11 +264,8 @@ static void enable_hpet(struct device *dev)
static void lpc_init(struct device *dev) { - /* Set the value for PCI command register. */ - pci_write_config16(dev, PCI_COMMAND, 0x000f); - /* IO APIC initialization. */ - i82801dx_enable_ioapic(dev); + setup_ioapic_novectors(IO_APIC_ADDR, 0x02);
i82801dx_enable_serial_irqs(dev);
@@ -323,10 +320,25 @@ static void i82801dx_lpc_read_resources(device_t dev) res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; }
+static void i82801dx_lpc_enable_resources(device_t dev) +{ + /* Enable the normal PCI resources. */ + pci_dev_enable_resources(dev); + + /* Enable ACPI and GPIO BARs. */ + i82801dx_enable_acpi(dev); + + /* Set features (most important: IOAPIC). */ + i82801dx_general_cntl(dev); + + /* Set the value for PCI command register. */ + pci_write_config16(dev, PCI_COMMAND, 0x000f); +} + static struct device_operations lpc_ops = { .read_resources = i82801dx_lpc_read_resources, .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, + .enable_resources = i82801dx_lpc_enable_resources, .init = lpc_init, .scan_bus = scan_static_bus, .enable = i82801dx_enable, diff --git a/src/southbridge/intel/i82801ex/i82801ex.h b/src/southbridge/intel/i82801ex/i82801ex.h index 67fecdd..22a29f3 100644 --- a/src/southbridge/intel/i82801ex/i82801ex.h +++ b/src/southbridge/intel/i82801ex/i82801ex.h @@ -12,4 +12,13 @@ extern void i82801ex_enable(device_t dev); #define RTC_CONF 0xd8 #define GEN_PMCON_3 0xa4
+ +#define PMBASE 0x40 +#define ACPI_CNTL 0x44 +#define ACPI_EN (1 << 4) +#define GPIO_BASE 0x58 +#define GPIO_CNTL 0x5C +#define GPIO_EN (1 << 4) + + #endif /* I82801EX_H */ diff --git a/src/southbridge/intel/i82801ex/lpc.c b/src/southbridge/intel/i82801ex/lpc.c index 998360c..81d8aef 100644 --- a/src/southbridge/intel/i82801ex/lpc.c +++ b/src/southbridge/intel/i82801ex/lpc.c @@ -12,8 +12,6 @@ #include <arch/ioapic.h> #include "i82801ex.h"
-#define ACPI_BAR 0x40 -#define GPIO_BAR 0x58
#define NMI_OFF 0 #define MAINBOARD_POWER_OFF 0 @@ -23,6 +21,52 @@ #define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON #endif
+typedef struct southbridge_intel_i82801ex_config config_t; + +/** + * Enable ACPI I/O range. + * + * @param dev PCI device with ACPI and PM BAR's + */ +static void i82801ex_enable_acpi(struct device *dev) +{ + u8 gpio_cntl; +#if 0 + /* many i82801's set pmbase here */ + /* Set ACPI base address (I/O space). */ + pci_write_config32(dev, PMBASE, (PMBASE_ADDR | 1)); +#endif + + /* Enable ACPI I/O range decode and ACPI power management. */ + pci_write_config8(dev, ACPI_CNTL, ACPI_EN); + + /* Enable the GPIO bar */ + gpio_cntl = pci_read_config8(dev, GPIO_CNTL); + gpio_cntl |= GPIO_EN; + pci_write_config8(dev, GPIO_CNTL, gpio_cntl); +} + +/** + * Set miscellanous static southbridge features. + * + * @param dev PCI device with I/O APIC configuration registers + */ +static void i82801ex_general_cntl(struct device *dev) +{ + u32 reg32; + + reg32 = pci_read_config32(dev, GEN_CNTL); + reg32 |= (3 << 7); /* IOAPIC enable (APIC_EN) */ + reg32 |= (1 << 1); /* Delayed transaction enable (DTE) */ + pci_write_config32(dev, GEN_CNTL, reg32); + printk(BIOS_DEBUG, "Southbridge GEN_CNTL 0x%08x\n", reg32); + + reg32 = pci_read_config32(dev, GEN_STS); + reg32 |= (1<<1); + pci_write_config32(dev, GEN_STS, reg32); + +} + #define SERIRQ_CNTL 0x64 static void i82801ex_enable_serial_irqs(device_t dev) { @@ -45,7 +89,6 @@ static void i82801ex_enable_lpc(device_t dev) pci_write_config8(dev, LPC_EN, 0x0d); }
-typedef struct southbridge_intel_i82801ex_config config_t;
static void set_i82801ex_gpio_use_sel( device_t dev, struct resource *res, config_t *config) @@ -193,7 +236,7 @@ static void i82801ex_gpio_init(device_t dev) /* Get the chip configuration */ config = dev->chip_info; /* Find the GPIO bar */ - res = find_resource(dev, GPIO_BAR); + res = find_resource(dev, GPIO_BASE); if (!res) { return; } @@ -239,17 +282,10 @@ static void enable_hpet(struct device *dev) static void lpc_init(struct device *dev) { uint8_t byte; - uint32_t value; int pwr_on=CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
- /* IO APIC initialization */ - value = pci_read_config32(dev, 0xd0); - value |= (1 << 8)|(1<<7)|(1<<1); - pci_write_config32(dev, 0xd0, value); - value = pci_read_config32(dev, 0xd4); - value |= (1<<1); - pci_write_config32(dev, 0xd4, value); - setup_ioapic(IO_APIC_ADDR, 0); // Don't rename IO APIC ID. + /* IO APIC initialization. */ + setup_ioapic(IO_APIC_ADDR, 0); /* No APIC ID ?? */
i82801ex_enable_serial_irqs(dev);
@@ -295,10 +331,10 @@ static void i82801ex_lpc_read_resources(device_t dev) pci_dev_read_resources(dev);
/* Add the ACPI BAR */ - res = pci_get_resource(dev, ACPI_BAR); + res = pci_get_resource(dev, PMBASE);
/* Add the GPIO BAR */ - res = pci_get_resource(dev, GPIO_BAR); + res = pci_get_resource(dev, GPIO_BASE);
/* Add an extra subtractive resource for both memory and I/O. */ res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0)); @@ -321,20 +357,14 @@ static void i82801ex_lpc_read_resources(device_t dev)
static void i82801ex_lpc_enable_resources(device_t dev) { - uint8_t acpi_cntl, gpio_cntl; - - /* Enable the normal pci resources */ + /* Enable the normal PCI resources. */ pci_dev_enable_resources(dev);
- /* Enable the ACPI bar */ - acpi_cntl = pci_read_config8(dev, 0x44); - acpi_cntl |= (1 << 4); - pci_write_config8(dev, 0x44, acpi_cntl); + /* Enable ACPI and GPIO BARs. */ + i82801ex_enable_acpi(dev);
- /* Enable the GPIO bar */ - gpio_cntl = pci_read_config8(dev, 0x5c); - gpio_cntl |= (1 << 4); - pci_write_config8(dev, 0x5c, gpio_cntl); + /* Set features (most important: IOAPIC). */ + i82801ex_general_cntl(dev); }
static struct pci_operations lops_pci = { diff --git a/src/southbridge/intel/i82801gx/i82801gx.h b/src/southbridge/intel/i82801gx/i82801gx.h index 8fb5b92..7b93cbd 100644 --- a/src/southbridge/intel/i82801gx/i82801gx.h +++ b/src/southbridge/intel/i82801gx/i82801gx.h @@ -81,6 +81,7 @@ int smbus_read_byte(unsigned device, unsigned address);
#define PMBASE 0x40 #define ACPI_CNTL 0x44 +#define ACPI_EN (1 << 7) /* NOTE: was 1<<4 until ICH7 */ #define BIOS_CNTL 0xDC #define GPIO_BASE 0x48 /* LPC GPIO Base Address Register */ #define GPIO_CNTL 0x4C /* LPC GPIO Control Register */ diff --git a/src/southbridge/intel/i82801gx/lpc.c b/src/southbridge/intel/i82801gx/lpc.c index c6b76d3..882fafe 100644 --- a/src/southbridge/intel/i82801gx/lpc.c +++ b/src/southbridge/intel/i82801gx/lpc.c @@ -39,37 +39,38 @@
typedef struct southbridge_intel_i82801gx_config config_t;
-static void i82801gx_enable_apic(struct device *dev) +/** + * Enable ACPI I/O range. + * + * @param dev PCI device with ACPI and PM BAR's + */ +static void i82801gx_enable_acpi(struct device *dev) { - int i; - u32 reg32; - volatile u32 *ioapic_index = (volatile u32 *)(IO_APIC_ADDR); - volatile u32 *ioapic_data = (volatile u32 *)(IO_APIC_ADDR + 0x10); +#if 0 + /* many i82801's set pmbase here */ + /* Set ACPI base address (I/O space). */ + pci_write_config32(dev, PMBASE, (PMBASE_ADDR | 1)); +#endif
- /* Enable ACPI I/O and power management. - * Set SCI IRQ to IRQ9 + /* Enable ACPI I/O range decode and ACPI power management. + * Select SCI IRQ as IRQ9. */ - pci_write_config8(dev, ACPI_CNTL, 0x80); - - *ioapic_index = 0; - *ioapic_data = (1 << 25); - - *ioapic_index = 0; - reg32 = *ioapic_data; - printk(BIOS_DEBUG, "Southbridge APIC ID = %x\n", (reg32 >> 24) & 0x0f); - if (reg32 != (1 << 25)) - die("APIC Error\n"); - - printk(BIOS_SPEW, "Dumping IOAPIC registers\n"); - for (i=0; i<3; i++) { - *ioapic_index = i; - printk(BIOS_SPEW, " reg 0x%04x:", i); - reg32 = *ioapic_data; - printk(BIOS_SPEW, " 0x%08x\n", reg32); - } + pci_write_config8(dev, ACPI_CNTL, ACPI_EN); +} + +/** + * Set miscellanous static southbridge features. + * + * @param dev PCI device with I/O APIC configuration registers + */ +static void i82801gx_general_cntl(struct device *dev) +{ + u32 reg32 = 0xABADBEEF; + + /* FIXME: Who sets OIC register @ 0x3155 ?? + */ + printk(BIOS_DEBUG, "Southbridge OIC 0x%08x.\n", reg32);
- *ioapic_index = 3; /* Select Boot Configuration register. */ - *ioapic_data = 1; /* Use Processor System Bus to deliver interrupts. */ }
static void i82801gx_enable_serial_irqs(struct device *dev) @@ -418,11 +419,8 @@ static void lpc_init(struct device *dev) { printk(BIOS_DEBUG, "i82801gx: lpc_init\n");
- /* Set the value for PCI command register. */ - pci_write_config16(dev, PCI_COMMAND, 0x000f); - /* IO APIC initialization. */ - i82801gx_enable_apic(dev); + setup_ioapic_novectors(IO_APIC_ADDR, 0x02);
i82801gx_enable_serial_irqs(dev);
@@ -502,6 +500,21 @@ static void set_subsystem(device_t dev, unsigned vendor, unsigned device) } }
+static void i82801gx_lpc_enable_resources(device_t dev) +{ + /* Enable the normal PCI resources. */ + pci_dev_enable_resources(dev); + + /* Enable ACPI and GPIO BARs. */ + i82801gx_enable_acpi(dev); + + /* Set features (most important: IOAPIC). */ + i82801gx_general_cntl(dev); + + /* Set the value for PCI command register. */ + pci_write_config16(dev, PCI_COMMAND, 0x000f); +} + static struct pci_operations pci_ops = { .set_subsystem = set_subsystem, }; @@ -509,7 +522,7 @@ static struct pci_operations pci_ops = { static struct device_operations device_ops = { .read_resources = i82801gx_lpc_read_resources, .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, + .enable_resources = i82801gx_lpc_enable_resources, .init = lpc_init, .scan_bus = scan_static_bus, .enable = i82801gx_enable,