From 573f7d40be086b35b25d242818ae0e9c26d05022 Mon Sep 17 00:00:00 2001 From: Stefan Reinauer Date: Tue, 21 Jul 2009 21:50:34 +0000 Subject: Intel ICH7 updates - code restructuring (move ich7 out of i945) - ACPI fixes - major SMI handler updates - make sure SMBus lives where we expect it - try to get usb debug working Signed-off-by: Stefan Reinauer Acked-by: Peter Stuge git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4456 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/southbridge/intel/i82801gx/acpi/globalnvs.asl | 161 ++++++++ src/southbridge/intel/i82801gx/acpi/ich7.asl | 22 +- src/southbridge/intel/i82801gx/acpi/ich7_ac97.asl | 40 ++ src/southbridge/intel/i82801gx/acpi/ich7_audio.asl | 6 +- src/southbridge/intel/i82801gx/acpi/ich7_lpc.asl | 90 ++++- src/southbridge/intel/i82801gx/acpi/ich7_pci.asl | 60 +-- src/southbridge/intel/i82801gx/acpi/ich7_smbus.asl | 4 +- .../intel/i82801gx/acpi/sleepstates.asl | 27 ++ src/southbridge/intel/i82801gx/i82801gx.h | 162 +++++++- src/southbridge/intel/i82801gx/i82801gx_ac97.c | 17 + src/southbridge/intel/i82801gx/i82801gx_lpc.c | 90 ++++- src/southbridge/intel/i82801gx/i82801gx_nvs.h | 159 +++++--- src/southbridge/intel/i82801gx/i82801gx_pci.c | 2 +- src/southbridge/intel/i82801gx/i82801gx_power.h | 29 ++ src/southbridge/intel/i82801gx/i82801gx_sata.c | 38 +- src/southbridge/intel/i82801gx/i82801gx_smbus.c | 15 +- src/southbridge/intel/i82801gx/i82801gx_smi.c | 19 +- .../intel/i82801gx/i82801gx_smihandler.c | 440 +++++++++++++++------ .../intel/i82801gx/i82801gx_usb_debug.c | 14 +- src/southbridge/intel/i82801gx/i82801gx_usb_ehci.c | 10 +- 20 files changed, 1110 insertions(+), 295 deletions(-) create mode 100644 src/southbridge/intel/i82801gx/acpi/globalnvs.asl create mode 100644 src/southbridge/intel/i82801gx/acpi/ich7_ac97.asl create mode 100644 src/southbridge/intel/i82801gx/acpi/sleepstates.asl create mode 100644 src/southbridge/intel/i82801gx/i82801gx_power.h (limited to 'src/southbridge/intel/i82801gx') diff --git a/src/southbridge/intel/i82801gx/acpi/globalnvs.asl b/src/southbridge/intel/i82801gx/acpi/globalnvs.asl new file mode 100644 index 0000000000..368e90679f --- /dev/null +++ b/src/southbridge/intel/i82801gx/acpi/globalnvs.asl @@ -0,0 +1,161 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +/* Global Variables */ + +Name(\PICM, 0) // IOAPIC/8259 +Name(\DSEN, 1) // Display Output Switching Enable + +/* Global ACPI memory region. This region is used for passing information + * between coreboot (aka "the system bios"), ACPI, and the SMI handler. + * Since we don't know where this will end up in memory at ACPI compile time, + * we have to fix it up in coreboot's ACPI creation phase. + */ + + +OperationRegion (GNVS, SystemMemory, 0xC0DEBABE, 0x100) +Field (GNVS, ByteAcc, NoLock, Preserve) +{ + /* Miscellaneous */ + Offset (0x00), + OSYS, 16, // 0x00 - Operating System + SMIF, 8, // 0x02 - SMI function + PRM0, 8, // 0x03 - SMI function parameter + PRM1, 8, // 0x04 - SMI function parameter + SCIF, 8, // 0x05 - SCI function + PRM2, 8, // 0x06 - SCI function parameter + PRM3, 8, // 0x07 - SCI function parameter + LCKF, 8, // 0x08 - Global Lock function for EC + PRM4, 8, // 0x09 - Lock function parameter + PRM5, 8, // 0x0a - Lock function parameter + P80D, 32, // 0x0b - Debug port (IO 0x80) value + LIDS, 8, // 0x0f - LID state (open = 1) + PWRS, 8, // 0x10 - Power State (AC = 1) + DBGS, 8, // 0x11 - Debug State + LINX, 8, // 0x12 - Linux OS + DCKN, 8, // 0x13 - PCIe docking state + /* Thermal policy */ + Offset (0x14), + ACTT, 8, // 0x14 - active trip point + PSVT, 8, // 0x15 - passive trip point + TC1V, 8, // 0x16 - passive trip point TC1 + TC2V, 8, // 0x17 - passive trip point TC2 + TSPV, 8, // 0x18 - passive trip point TSP + CRTT, 8, // 0x19 - critical trip point + DTSE, 8, // 0x1a - Digital Thermal Sensor enable + DTS1, 8, // 0x1b - DT sensor 1 + DTS2, 8, // 0x1c - DT sensor 2 + /* Battery Support */ + Offset (0x1e), + BNUM, 8, // 0x1e - number of batteries + B0SC, 8, // 0x1f - BAT0 stored capacity + B1SC, 8, // 0x20 - BAT1 stored capacity + B2SC, 8, // 0x21 - BAT2 stored capacity + B0SS, 8, // 0x22 - BAT0 stored status + B1SS, 8, // 0x23 - BAT1 stored status + B2SS, 8, // 0x24 - BAT2 stored status + /* Processor Identification */ + Offset (0x28), + APIC, 8, // 0x28 - APIC Enabled by coreboot + MPEN, 8, // 0x29 - Multi Processor Enable + PCP0, 8, // 0x2a - PDC CPU/CORE 0 + PCP1, 8, // 0x2b - PDC CPU/CORE 1 + PPCM, 8, // 0x2c - Max. PPC state + /* Super I/O & CMOS config */ + Offset (0x32), + NATP, 8, // 0x32 - ... + /* Integrated Graphics Device */ + Offset (0x3c), + IGDS, 8, // 0x3c - IGD state (primary = 1) + TLST, 8, // 0x3d - Display Toggle List pointer + CADL, 8, // 0x3e - Currently Attached Devices List + PADL, 8, // 0x3f - Previously Attached Devices List + CSTE, 16, // 0x40 - Current display state + NSTE, 16, // 0x42 - Next display state + SSTE, 16, // 0x44 - Set display state + Offset (0x46), + NDID, 8, // 0x46 - Number of Device IDs + DID1, 32, // 0x47 - Device ID 1 + DID2, 32, // 0x4b - Device ID 2 + DID3, 32, // 0x4f - Device ID 3 + DID4, 32, // 0x53 - Device ID 4 + DID5, 32, // 0x57 - Device ID 5 + /* Backlight Control */ + Offset (0x64), + BLCS, 8, // 0x64 - Backlight control possible? + BRTL, 8, // 0x65 - Brightness Level + ODDS, 8, // 0x66 + /* Ambient Light Sensors */ + Offset (0x6e), + ALSE, 8, // 0x6e - ALS enable + ALAF, 8, // 0x6f - Ambient light adjustment factor + LLOW, 8, // 0x70 - LUX Low + LHIH, 8, // 0x71 - LUX High + /* EMA */ + Offset (0x78), + EMAE, 8, // 0x78 - EMA enable + EMAP, 16, // 0x79 - EMA pointer + EMAL, 16, // 0x7b - EMA length + /* MEF */ + Offset (0x82), + MEFE, 8, // 0x82 - MEF enable + /* TPM support */ + Offset (0x8c), + TPMP, 8, // 0x8c - TPM + TPME, 8, // 0x8d - TPM enable + /* SATA */ + Offset (0x96), + GTF0, 56, // 0x96 - GTF task file buffer for port 0 + GTF1, 56, // 0x9d - GTF task file buffer for port 1 + GTF2, 56, // 0xa4 - GTF task file buffer for port 2 + IDEM, 8, // 0xab - IDE mode (compatible / enhanced) + IDET, 8, // 0xac - IDE + /* IGD OpRegion */ + Offset (0xb4), + ASLB, 32, // 0xb4 - IGD OpRegion Base Address + IBTT, 8, // 0xb8 - IGD boot panel device + IPAT, 8, // 0xb9 - IGD panel type cmos option + ITVF, 8, // 0xba - IGD TV format cmos option + ITVM, 8, // 0xbb - IGD TV minor format option + IPSC, 8, // 0xbc - IGD panel scaling + IBLC, 8, // 0xbd - IGD BLC config + IBIA, 8, // 0xbe - IGD BIA config + ISSC, 8, // 0xbf - IGD SSC config + I409, 8, // 0xc0 - IGD 0409 modified settings + I509, 8, // 0xc1 - IGD 0509 modified settings + I609, 8, // 0xc2 - IGD 0609 modified settings + I709, 8, // 0xc3 - IGD 0709 modified settings + IDMM, 8, // 0xc4 - IGD DVMT Mode + IDMS, 8, // 0xc5 - IGD DVMT memory size + IF1E, 8, // 0xc6 - IGD function 1 enable + HVCO, 8, // 0xc7 - IGD HPLL VCO + NXD1, 32, // 0xc8 - IGD _DGS next DID1 + NXD2, 32, // 0xcc - IGD _DGS next DID2 + NXD3, 32, // 0xd0 - IGD _DGS next DID3 + NXD4, 32, // 0xd4 - IGD _DGS next DID4 + NXD5, 32, // 0xd8 - IGD _DGS next DID5 + NXD6, 32, // 0xdc - IGD _DGS next DID6 + NXD7, 32, // 0xe0 - IGD _DGS next DID7 + NXD8, 32, // 0xe4 - IGD _DGS next DID8 + /* Mainboard Specific (TODO move elsewhere) */ + Offset (0xf0), + DOCK, 8, // 0xf0 - Docking Status +} diff --git a/src/southbridge/intel/i82801gx/acpi/ich7.asl b/src/southbridge/intel/i82801gx/acpi/ich7.asl index 2e7233d948..dd3bc87e2f 100644 --- a/src/southbridge/intel/i82801gx/acpi/ich7.asl +++ b/src/southbridge/intel/i82801gx/acpi/ich7.asl @@ -92,7 +92,8 @@ Scope(\) Offset(0x38), // GPIO Level 2 , 5, GP37, 1, // PATA_PWR_EN - , 2, + GP38, 1, // Battery / Power (?) + GP39, 1, // ?? GL05, 8, GL06, 8, GL07, 8 @@ -100,7 +101,7 @@ Scope(\) // ICH7 Root Complex Register Block. Memory Mapped through RCBA) - OperationRegion(RCRB, SystemMemory, 0xfff1000, 0x4000) + OperationRegion(RCRB, SystemMemory, 0xfed1c000, 0x4000) Field(RCRB, DWordAcc, Lock, Preserve) { Offset(0x0000), // Backbone @@ -111,12 +112,22 @@ Scope(\) , 5, HPTE, 1, // Address Enable Offset(0x3418), // FD (Function Disable) - , 1, + , 1, // Reserved PATD, 1, // PATA disable SATD, 1, // SATA disable SMBD, 1, // SMBUS disable HDAD, 1, // Azalia disable - , 11, // ... FIXME + A97D, 1, // AC'97 disable + M97D, 1, // AC'97 disable + ILND, 1, // Internal LAN disable + US1D, 1, // UHCI #1 disable + US2D, 1, // UHCI #2 disable + US3D, 1, // UHCI #3 disable + US4D, 1, // UHCI #4 disable + , 2, // Reserved + LPBD, 1, // LPC bridge disable + EHCD, 1, // EHCI disable + Offset(0x341a), // FD Root Ports RP1D, 1, // Root Port 1 disable RP2D, 1, // Root Port 2 disable RP3D, 1, // Root Port 3 disable @@ -139,6 +150,9 @@ Include ("../../../southbridge/intel/i82801gx/acpi/ich7_usb.asl") // PCI Bridge Include ("../../../southbridge/intel/i82801gx/acpi/ich7_pci.asl") +// AC97 Audio and Modem +Include ("../../../southbridge/intel/i82801gx/acpi/ich7_ac97.asl") + // LPC Bridge Include ("../../../southbridge/intel/i82801gx/acpi/ich7_lpc.asl") diff --git a/src/southbridge/intel/i82801gx/acpi/ich7_ac97.asl b/src/southbridge/intel/i82801gx/acpi/ich7_ac97.asl new file mode 100644 index 0000000000..7f76ccc786 --- /dev/null +++ b/src/southbridge/intel/i82801gx/acpi/ich7_ac97.asl @@ -0,0 +1,40 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +/* Intel i82801G AC'97 Audio and Modem */ + +// Intel AC'97 Audio 0:1e.2 + +Device (AUD0) +{ + Name (_ADR, 0x001e0002) +} + +// Intel AC'97 Modem 0:1e.3 + +Device (MODM) +{ + Name (_ADR, 0x001e0003) + + Name (_PRW, Package(){ 5, 4 }) +} + + diff --git a/src/southbridge/intel/i82801gx/acpi/ich7_audio.asl b/src/southbridge/intel/i82801gx/acpi/ich7_audio.asl index 01ae8c58ec..5b8b386c39 100644 --- a/src/southbridge/intel/i82801gx/acpi/ich7_audio.asl +++ b/src/southbridge/intel/i82801gx/acpi/ich7_audio.asl @@ -27,6 +27,10 @@ Device (HDEF) { Name (_ADR, 0x001b0000) - Name (_PRW, Package(){ 13, 4 }) + // Power Resources for Wake + Name (_PRW, Package(){ + 5, // Bit 5 of GPE + 4 // Can wake from S4 state. + }) } diff --git a/src/southbridge/intel/i82801gx/acpi/ich7_lpc.asl b/src/southbridge/intel/i82801gx/acpi/ich7_lpc.asl index 80ba6e73bf..d5705396ce 100644 --- a/src/southbridge/intel/i82801gx/acpi/ich7_lpc.asl +++ b/src/southbridge/intel/i82801gx/acpi/ich7_lpc.asl @@ -68,7 +68,7 @@ Device (LPCB) }) } - Device (FWHD) // Firmware Hub + Device (FWH) // Firmware Hub { Name (_HID, EISAID("INT0800")) Name (_CRS, ResourceTemplate() @@ -80,7 +80,7 @@ Device (LPCB) Device (HPET) { Name (_HID, EISAID("PNP0103")) - Name (_CID, EISAID("PNP0C01")) + Name (_CID, 0x010CD041) Name(BUF0, ResourceTemplate() { @@ -92,18 +92,32 @@ Device (LPCB) If (HPTE) { // Note: Ancient versions of Windows don't want // to see the HPET in order to work right - // Return (0xb) // Enable and don't show device - - Return (0xf) // Enable and show device + If (LGreaterEqual(OSYS, 2001)) { + Return (0xf) // Enable and show device + } Else { + Return (0xb) // Enable and don't show device + } } Return (0x0) // Not enabled, don't show. } - Method (_CRS, 0, Serialized) + Method (_CRS, 0, Serialized) // Current resources { - // Here we could do crazy stuff like move the HPET. Why - // should we? + If (HPTE) { + CreateDWordField(BUF0, \_SB.PCI0.LPCB.HPET.FED0._BAS, HPT0) + If (Lequal(HPAS, 1)) { + Store(0xfed01000, HPT0) + } + + If (Lequal(HPAS, 2)) { + Store(0xfed02000, HPT0) + } + + If (Lequal(HPAS, 3)) { + Store(0xfed03000, HPT0) + } + } Return (BUF0) } @@ -130,7 +144,7 @@ Device (LPCB) IO (Decode16, 0xb4, 0xb4, 0x01, 0x02) IO (Decode16, 0xb8, 0xb8, 0x01, 0x02) IO (Decode16, 0xbc, 0xbc, 0x01, 0x02) - IO (Decode16, 0x4d0, 0x4b0, 0x01, 0x02) + IO (Decode16, 0x4d0, 0x4d0, 0x01, 0x02) IRQNoFlags () { 2 } }) } @@ -145,7 +159,7 @@ Device (LPCB) }) } - Device(MISC) // Various other devices + Device(LDRC) // LPC device: Resource consumption { Name (_HID, EISAID("PNP0C02")) Name (_UID, 2) @@ -153,18 +167,18 @@ Device (LPCB) { IO (Decode16, 0x2e, 0x2e, 0x1, 0x02) // First SuperIO IO (Decode16, 0x4e, 0x4e, 0x1, 0x02) // Second SuperIO - IO (Decode16, 0x61, 0x61, 0x1, 0x1) // NMI Status - IO (Decode16, 0x63, 0x63, 0x1, 0x1) // CPU Reserved - IO (Decode16, 0x65, 0x65, 0x1, 0x1) // CPU Reserved - IO (Decode16, 0x67, 0x67, 0x1, 0x1) // CPU Reserved - IO (Decode16, 0x80, 0x80, 0x1, 0x1) // Port 80 Post - IO (Decode16, 0x92, 0x92, 0x1, 0x1) // CPU Reserved + IO (Decode16, 0x61, 0x61, 0x1, 0x01) // NMI Status + IO (Decode16, 0x63, 0x63, 0x1, 0x01) // CPU Reserved + IO (Decode16, 0x65, 0x65, 0x1, 0x01) // CPU Reserved + IO (Decode16, 0x67, 0x67, 0x1, 0x01) // CPU Reserved + IO (Decode16, 0x80, 0x80, 0x1, 0x01) // Port 80 Post + IO (Decode16, 0x92, 0x92, 0x1, 0x01) // CPU Reserved IO (Decode16, 0xb2, 0xb2, 0x1, 0x02) // SWSMI - IO (Decode16, 0x680, 0x680, 0x1, 0x70) // IO ??? + // IO (Decode16, 0x680, 0x680, 0x1, 0x70) // IO ??? IO (Decode16, 0x800, 0x800, 0x1, 0x10) // ACPI I/O trap IO (Decode16, 0x0500, 0x0500, 0x1, 0x80) // ICH7-M ACPI - IO (Decode16, 0x1180, 0x1180, 0x1, 0x40) // ICH7-M GPIO - IO (Decode16, 0x1640, 0x1640, 0x1, 0x10) // IO ??? + IO (Decode16, 0x0480, 0x0480, 0x1, 0x40) // ICH7-M GPIO + // IO (Decode16, 0x1640, 0x1640, 0x1, 0x10) // IO ??? }) } @@ -194,12 +208,19 @@ Device (LPCB) Device (PS2K) // Keyboard { Name(_HID, EISAID("PNP0303")) + Name(_CID, EISAID("PNP030B")) + Name(_CRS, ResourceTemplate() { IO (Decode16, 0x60, 0x60, 0x01, 0x01) IO (Decode16, 0x64, 0x64, 0x01, 0x01) IRQ (Edge, ActiveHigh, Exclusive) { 0x01 } // IRQ 1 }) + + Method (_STA, 0) + { + Return (0xf) + } } Device (PS2M) // Mouse @@ -209,5 +230,36 @@ Device (LPCB) { IRQ (Edge, ActiveHigh, Exclusive) { 0x0c } // IRQ 12 }) + + Method(_STA, 0) + { + Return (0xf) + } + } + + Device (FDC0) // Floppy controller + { + Name (_HID, EisaId ("PNP0700")) + Method (_STA, 0, NotSerialized) + { + Return (0x0f) // FIXME + } + + Name(_CRS, ResourceTemplate() + { + IO (Decode16, 0x03F0, 0x03F0, 0x01, 0x06) + IO (Decode16, 0x03F7, 0x03F7, 0x01, 0x01) + IRQNoFlags () {6} + DMA (Compatibility, NotBusMaster, Transfer8) {2} + }) + + Name(_PRS, ResourceTemplate() + { + IO (Decode16, 0x03F0, 0x03F0, 0x01, 0x06) + IO (Decode16, 0x03F7, 0x03F7, 0x01, 0x01) + IRQNoFlags () {6} + DMA (Compatibility, NotBusMaster, Transfer8) {2} + }) + } } diff --git a/src/southbridge/intel/i82801gx/acpi/ich7_pci.asl b/src/southbridge/intel/i82801gx/acpi/ich7_pci.asl index bcdf084e37..775a34dfe8 100644 --- a/src/southbridge/intel/i82801gx/acpi/ich7_pci.asl +++ b/src/southbridge/intel/i82801gx/acpi/ich7_pci.asl @@ -43,6 +43,24 @@ Device (PCIB) Name (_PRW, Package(){ 11, 4 }) } + Device (SLT6) + { + Name (_ADR, 0x00050000) + Name (_PRW, Package(){ 11, 4 }) + } + + Device (LANC) + { + Name (_ADR, 0x00080000) + Name (_PRW, Package(){ 11, 3 }) + } + + Device (LANR) + { + Name (_ADR, 0x00000000) + Name (_PRW, Package(){ 11, 3 }) + } + // TODO: How many slots, where? // PCI Interrupt Routing. @@ -52,47 +70,7 @@ Device (PCIB) Method (_PRT) { - If (PICM) { - Return (Package() { - // PCI Slot 1 routes FGHE - Package() { 0x0000ffff, 0, 0, 16}, /* Firewire */ - Package() { 0x0000ffff, 1, 0, 22}, - Package() { 0x0000ffff, 2, 0, 23}, - Package() { 0x0000ffff, 3, 0, 20}, - - // PCI Slot 2 routes GFEH (but is EFGH now, because that actually works) - Package() { 0x0001ffff, 0, 0, 20}, - Package() { 0x0001ffff, 1, 0, 21}, - Package() { 0x0001ffff, 2, 0, 22}, - Package() { 0x0001ffff, 3, 0, 23}, - - // PCI Slot 3 routes CDBA - Package() { 0x0002ffff, 0, 0, 18}, - Package() { 0x0002ffff, 1, 0, 19}, - Package() { 0x0002ffff, 2, 0, 17}, - Package() { 0x0002ffff, 3, 0, 16} - }) - } Else { - Return (Package() { - // PCI Slot 1 routes FGHE - Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKF, 0}, - Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKE, 0}, - Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKH, 0}, - Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKG, 0}, - - // PCI Slot 2 routes GFEH - Package() { 0x0001ffff, 0, \_SB.PCI0.LPCB.LNKG, 0}, - Package() { 0x0001ffff, 1, \_SB.PCI0.LPCB.LNKF, 0}, - Package() { 0x0001ffff, 2, \_SB.PCI0.LPCB.LNKE, 0}, - Package() { 0x0001ffff, 3, \_SB.PCI0.LPCB.LNKH, 0}, - - // PCI Slot 3 routes CDBA - Package() { 0x0002ffff, 0, \_SB.PCI0.LPCB.LNKC, 0}, - Package() { 0x0002ffff, 1, \_SB.PCI0.LPCB.LNKD, 0}, - Package() { 0x0002ffff, 2, \_SB.PCI0.LPCB.LNKB, 0}, - Package() { 0x0002ffff, 3, \_SB.PCI0.LPCB.LNKA, 0}, - }) - } + Include ("acpi/ich7_pci_irqs.asl") } } diff --git a/src/southbridge/intel/i82801gx/acpi/ich7_smbus.asl b/src/southbridge/intel/i82801gx/acpi/ich7_smbus.asl index d0779b75c3..6b1009c24a 100644 --- a/src/southbridge/intel/i82801gx/acpi/ich7_smbus.asl +++ b/src/southbridge/intel/i82801gx/acpi/ich7_smbus.asl @@ -33,7 +33,8 @@ Device (SBUS) I2CE, 1 } - OperationRegion (SMBI, SystemIO, 0x500, 0x20) + /* + OperationRegion (SMBI, SystemIO, 0x400, 0x20) Field (SMBI, ByteAcc, NoLock, Preserve) { HSTS, 8, // Host Status @@ -236,6 +237,7 @@ Device (SBUS) Return (0xffff) } + */ // Todo: Does anyone ever use these? // Missing: Read / Write Word diff --git a/src/southbridge/intel/i82801gx/acpi/sleepstates.asl b/src/southbridge/intel/i82801gx/acpi/sleepstates.asl new file mode 100644 index 0000000000..61595854b2 --- /dev/null +++ b/src/southbridge/intel/i82801gx/acpi/sleepstates.asl @@ -0,0 +1,27 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +Name(\_S0, Package(4){0x0,0x0,0,0}) +Name(\_S1, Package(4){0x1,0x0,0,0}) +Name(\_S3, Package(4){0x5,0x0,0,0}) +Name(\_S4, Package(4){0x6,0x0,0,0}) +Name(\_S5, Package(4){0x7,0x0,0,0}) + diff --git a/src/southbridge/intel/i82801gx/i82801gx.h b/src/southbridge/intel/i82801gx/i82801gx.h index a1771230fc..19472ed1f9 100644 --- a/src/southbridge/intel/i82801gx/i82801gx.h +++ b/src/southbridge/intel/i82801gx/i82801gx.h @@ -21,8 +21,15 @@ #ifndef SOUTHBRIDGE_INTEL_I82801GX_I82801GX_H #define SOUTHBRIDGE_INTEL_I82801GX_I82801GX_H +/* __ROMCC__ is set by auto.c to make sure + * none of the stage2 data structures are included. + */ +#ifndef __ROMCC__ #include "chip.h" extern void i82801gx_enable(device_t dev); +#endif + +/* PCI Configuration Space (D31:F0): LPC */ #define SERIRQ_CNTL 0x64 @@ -58,7 +65,31 @@ extern void i82801gx_enable(device_t dev); #define IDE_TIM_PRI 0x40 /* IDE timings, primary */ #define IDE_DECODE_ENABLE (1 << 15) #define IDE_SITRE (1 << 14) +#define IDE_ISP_5_CLOCKS (0 << 12) +#define IDE_ISP_4_CLOCKS (1 << 12) +#define IDE_ISP_3_CLOCKS (2 << 12) +#define IDE_RCT_4_CLOCKS (0 << 8) +#define IDE_RCT_3_CLOCKS (1 << 8) +#define IDE_RCT_2_CLOCKS (2 << 8) +#define IDE_RCT_1_CLOCKS (3 << 8) +#define IDE_DTE1 (1 << 7) +#define IDE_PPE1 (1 << 6) +#define IDE_IE1 (1 << 5) +#define IDE_TIME1 (1 << 4) +#define IDE_DTE0 (1 << 3) +#define IDE_PPE0 (1 << 2) +#define IDE_IE0 (1 << 1) +#define IDE_TIME0 (1 << 0) #define IDE_TIM_SEC 0x42 /* IDE timings, secondary */ + +#define IDE_SDMA_CNT 0x48 /* Synchronous DMA control */ +#define IDE_SSDE1 (1 << 3) +#define IDE_SSDE0 (1 << 2) +#define IDE_PSDE1 (1 << 1) +#define IDE_PSDE0 (1 << 0) + +#define IDE_SDMA_TIM 0x4a + #define IDE_CONFIG 0x54 /* IDE I/O Configuration Register */ #define SIG_MODE_NORMAL (0 << 16) #define SIG_MODE_TRISTATE (1 << 16) @@ -78,12 +109,13 @@ extern void i82801gx_enable(device_t dev); #define HST_EN (1 << 0) /* SMBus I/O bits. - * TODO: It does not matter where we put the SMBus IO base, as long as we keep - * consistent and don't interfere with other devices. Stage2 will relocate - * this anyways. But it's a general problem we have not solved in the brightest - * possible way. + * It does not matter where we put the SMBus I/O base, as long as we + * keep it consistent and don't interfere with other devices. Stage2 + * will relocate this anyways. + * Our solution is to have SMB initialization move the I/O to SMBUS_IO_BASE + * again. But handling static BARs is a generic problem that should be + * solved in the device allocator. */ -/* #define SMBUS_IO_BASE 0x1000 */ #define SMBUS_IO_BASE 0x0400 #define SMBHSTSTAT 0x0 @@ -103,4 +135,124 @@ extern void i82801gx_enable(device_t dev); /* HPET, if present */ #define HPET_ADDR 0xfed0000 +/* Southbridge IO BARs */ + +/* TODO Make sure these don't get changed by stage2 */ +#define GPIOBASE 0x48 +#define DEFAULT_GPIOBASE 0x480 + +#define PMBASE 0x40 +#define DEFAULT_PMBASE 0x500 + +/* Root Complex Register Block */ +#define RCBA 0xf0 +#define DEFAULT_RCBA 0xfed1c000 + +#define RCBA8(x) *((volatile u8 *)(DEFAULT_RCBA + x)) +#define RCBA16(x) *((volatile u16 *)(DEFAULT_RCBA + x)) +#define RCBA32(x) *((volatile u32 *)(DEFAULT_RCBA + x)) + +#define VCH 0x0000 /* 32bit */ +#define VCAP1 0x0004 /* 32bit */ +#define VCAP2 0x0008 /* 32bit */ +#define PVC 0x000c /* 16bit */ +#define PVS 0x000e /* 16bit */ + +#define V0CAP 0x0010 /* 32bit */ +#define V0CTL 0x0014 /* 32bit */ +#define V0STS 0x001a /* 16bit */ + +#define V1CAP 0x001c /* 32bit */ +#define V1CTL 0x0020 /* 32bit */ +#define V1STS 0x0026 /* 16bit */ + +#define RCTCL 0x0100 /* 32bit */ +#define ESD 0x0104 /* 32bit */ +#define ULD 0x0110 /* 32bit */ +#define ULBA 0x0118 /* 64bit */ + +#define RP1D 0x0120 /* 32bit */ +#define RP1BA 0x0128 /* 64bit */ +#define RP2D 0x0130 /* 32bit */ +#define RP2BA 0x0138 /* 64bit */ +#define RP3D 0x0140 /* 32bit */ +#define RP3BA 0x0148 /* 64bit */ +#define RP4D 0x0150 /* 32bit */ +#define RP4BA 0x0158 /* 64bit */ +#define HDD 0x0160 /* 32bit */ +#define HDBA 0x0168 /* 64bit */ +#define RP5D 0x0170 /* 32bit */ +#define RP5BA 0x0178 /* 64bit */ +#define RP6D 0x0180 /* 32bit */ +#define RP6BA 0x0188 /* 64bit */ + +#define ILCL 0x01a0 /* 32bit */ +#define LCAP 0x01a4 /* 32bit */ +#define LCTL 0x01a8 /* 16bit */ +#define LSTS 0x01aa /* 16bit */ + +#define RPC 0x0224 /* 32bit */ +#define RPFN 0x0238 /* 32bit */ + +#define TRSR 0x1e00 /* 8bit */ +#define TRCR 0x1e10 /* 64bit */ +#define TWDR 0x1e18 /* 64bit */ + +#define IOTR0 0x1e80 /* 64bit */ +#define IOTR1 0x1e88 /* 64bit */ +#define IOTR2 0x1e90 /* 64bit */ +#define IOTR3 0x1e98 /* 64bit */ + +#define TCTL 0x3000 /* 8bit */ + +#define D31IP 0x3100 /* 32bit */ +#define D30IP 0x3104 /* 32bit */ +#define D29IP 0x3108 /* 32bit */ +#define D28IP 0x310c /* 32bit */ +#define D27IP 0x3110 /* 32bit */ +#define D31IR 0x3140 /* 16bit */ +#define D30IR 0x3142 /* 16bit */ +#define D29IR 0x3144 /* 16bit */ +#define D28IR 0x3146 /* 16bit */ +#define D27IR 0x3148 /* 16bit */ +#define OIC 0x31ff /* 8bit */ + +#define RC 0x3400 /* 32bit */ +#define HPTC 0x3404 /* 32bit */ +#define GCS 0x3410 /* 32bit */ +#define BUC 0x3414 /* 32bit */ +#define FD 0x3418 /* 32bit */ +#define CG 0x341c /* 32bit */ + +/* Function Disable (FD) register values. + * Setting a bit disables the corresponding + * feature. + * Not all features might be disabled on + * all chipsets. Esp. ICH-7U is picky. + */ +#define FD_PCIE6 (1 << 21) +#define FD_PCIE5 (1 << 20) +#define FD_PCIE4 (1 << 19) +#define FD_PCIE3 (1 << 18) +#define FD_PCIE2 (1 << 17) +#define FD_PCIE1 (1 << 16) +#define FD_EHCI (1 << 15) +#define FD_LPCB (1 << 14) + +/* UHCI must be disabled from 4 downwards. + * If UHCI controllers get disabled, EHCI + * must know about it, too! */ +#define FD_UHCI4 (1 << 11) +#define FD_UHCI34 (1 << 10) | FD_UHCI4 +#define FD_UHCI234 (1 << 9) | FD_UHCI3 +#define FD_UHCI1234 (1 << 8) | FD_UHCI2 + +#define FD_INTLAN (1 << 7) +#define FD_ACMOD (1 << 6) +#define FD_ACAUD (1 << 5) +#define FD_HDAUD (1 << 4) +#define FD_SMBUS (1 << 3) +#define FD_SATA (1 << 2) +#define FD_PATA (1 << 1) + #endif /* SOUTHBRIDGE_INTEL_I82801GX_I82801GX_H */ diff --git a/src/southbridge/intel/i82801gx/i82801gx_ac97.c b/src/southbridge/intel/i82801gx/i82801gx_ac97.c index e78b1eb282..f447de60f1 100644 --- a/src/southbridge/intel/i82801gx/i82801gx_ac97.c +++ b/src/southbridge/intel/i82801gx/i82801gx_ac97.c @@ -251,6 +251,21 @@ static void ac97_modem_init(struct device *dev) } } +static void ac97_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + if (!vendor || !device) { + pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + pci_read_config32(dev, PCI_VENDOR_ID)); + } else { + pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + ((device & 0xffff) << 16) | (vendor & 0xffff)); + } +} + +static struct pci_operations ac97_pci_ops = { + .set_subsystem = ac97_set_subsystem, +}; + static struct device_operations ac97_audio_ops = { .read_resources = pci_dev_read_resources, .set_resources = pci_dev_set_resources, @@ -258,6 +273,7 @@ static struct device_operations ac97_audio_ops = { .init = ac97_audio_init, .scan_bus = 0, .enable = i82801gx_enable, + .ops_pci = &ac97_pci_ops, }; static struct device_operations ac97_modem_ops = { @@ -267,6 +283,7 @@ static struct device_operations ac97_modem_ops = { .init = ac97_modem_init, .scan_bus = 0, .enable = i82801gx_enable, + .ops_pci = &ac97_pci_ops, }; /* 82801GB/GR/GDH/GBM/GHM (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH) */ diff --git a/src/southbridge/intel/i82801gx/i82801gx_lpc.c b/src/southbridge/intel/i82801gx/i82801gx_lpc.c index ca2b409321..f42471f3ef 100644 --- a/src/southbridge/intel/i82801gx/i82801gx_lpc.c +++ b/src/southbridge/intel/i82801gx/i82801gx_lpc.c @@ -27,17 +27,12 @@ #include #include #include "i82801gx.h" +#include "i82801gx_power.h" -#include "../../../northbridge/intel/i945/ich7.h" +#define NMI_OFF 0 -#define MAINBOARD_POWER_OFF 0 -#define MAINBOARD_POWER_ON 1 - -#ifndef CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL -#define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON -#endif - -#define NMI_OFF 0 +#define ENABLE_ACPI_MODE_IN_COREBOOT 0 +#define TEST_SMM_FLASH_LOCKDOWN 0 typedef struct southbridge_intel_i82801gx_config config_t; @@ -78,7 +73,9 @@ static void i82801gx_enable_apic(struct device *dev) volatile u32 *ioapic_index = (volatile u32 *)0xfec00000; volatile u32 *ioapic_data = (volatile u32 *)0xfec00010; - /* Enable ACPI I/O and power management. */ + /* Enable ACPI I/O and power management. + * Set SCI IRQ to IRQ9 + */ pci_write_config8(dev, ACPI_CNTL, 0x80); *ioapic_index = 0; @@ -109,6 +106,27 @@ static void i82801gx_enable_serial_irqs(struct device *dev) (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0)); } +/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control + * 0x00 - 0000 = Reserved + * 0x01 - 0001 = Reserved + * 0x02 - 0010 = Reserved + * 0x03 - 0011 = IRQ3 + * 0x04 - 0100 = IRQ4 + * 0x05 - 0101 = IRQ5 + * 0x06 - 0110 = IRQ6 + * 0x07 - 0111 = IRQ7 + * 0x08 - 1000 = Reserved + * 0x09 - 1001 = IRQ9 + * 0x0A - 1010 = IRQ10 + * 0x0B - 1011 = IRQ11 + * 0x0C - 1100 = IRQ12 + * 0x0D - 1101 = Reserved + * 0x0E - 1110 = IRQ14 + * 0x0F - 1111 = IRQ15 + * PIRQ[n]_ROUT[7] - PIRQ Routing Control + * 0x80 - The PIRQ is not routed. + */ + static void i82801gx_pirq_init(device_t dev) { device_t irq_dev; @@ -180,10 +198,14 @@ static void i82801gx_gpi_routing(device_t dev) pci_write_config32(dev, 0xb8, reg32); } +extern u8 acpi_slp_type; + static void i82801gx_power_options(device_t dev) { u8 reg8; - u16 reg16; + u16 reg16, pmbase; + u32 reg32; + char *state; int pwr_on=CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL; int nmi_option; @@ -195,16 +217,28 @@ static void i82801gx_power_options(device_t dev) get_option(&pwr_on, "power_on_after_fail"); reg8 = pci_read_config8(dev, GEN_PMCON_3); reg8 &= 0xfe; - if (pwr_on) { - reg8 &= ~1; - } else { + switch (pwr_on) { + case MAINBOARD_POWER_OFF: reg8 |= 1; + state = "off"; + break; + case MAINBOARD_POWER_ON: + reg8 &= ~1; + state = "on"; + break; + case MAINBOARD_POWER_KEEP: + reg8 &= ~1; + state = "state keep"; + break; + default: + state = "undefined"; } + reg8 |= (3 << 4); /* avoid #S4 assertions */ reg8 &= ~(1 << 3); /* minimum asssertion is 1 to 2 RTCCLK */ pci_write_config8(dev, GEN_PMCON_3, reg8); - printk_info("Set power %s after power failure.\n", pwr_on ? "on" : "off"); + printk_info("Set power %s after power failure.\n", state); /* Set up NMI on errors. */ reg8 = inb(0x61); @@ -226,15 +260,27 @@ static void i82801gx_power_options(device_t dev) } outb(reg8, 0x70); - // Enable CPU_SLP# and Intel Speedstep, set SMI# rate down + /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */ reg16 = pci_read_config16(dev, GEN_PMCON_1); reg16 &= ~((3 << 0) | (1 << 10)); reg16 |= (1 << 3) | (1 << 5); - reg16 |= (1 << 2); // CLKRUN_EN + reg16 |= (1 << 2); // CLKRUN_EN pci_write_config16(dev, GEN_PMCON_1, reg16); // Set the board's GPI routing. i82801gx_gpi_routing(dev); + + /* Set up power management block and determine sleep mode */ + pmbase = pci_read_config16(dev, 0x40) & 0xfffe; + reg32 = inl(pmbase + 0x04); // PM1_CNT +#if HAVE_ACPI_RESUME + acpi_slp_type = (((reg32 >> 10) & 7) == 5) ? 3 : 0; + printk_debug("PM1_CNT: 0x%08x --> acpi_sleep_type: %x\n", + reg32, acpi_slp_type); +#endif + reg32 |= (1 << 1); // enable C3->C0 transition on bus master + reg32 |= 1; // SCI_EN + outl(reg32, pmbase + 0x04); } static void i82801gx_configure_cstates(device_t dev) @@ -273,9 +319,10 @@ static void enable_hpet(void) { u32 reg32; - /* Leave HPET at default address, but enable it */ + /* Move HPET to default address 0xfed00000 and enable it */ reg32 = RCBA32(0x3404); reg32 |= (1 << 7); // HPET Address Enable + reg32 &= ~(3 << 0); RCBA32(0x3404) = reg32; } @@ -467,6 +514,13 @@ static struct device_operations device_ops = { .ops_pci = &pci_ops, }; +/* 82801GH (ICH7 DH) */ +static const struct pci_driver ich7_dh_lpc __pci_driver = { + .ops = &device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x27b0, +}; + /* 82801GB/GR (ICH7/ICH7R) */ static const struct pci_driver ich7_ich7r_lpc __pci_driver = { .ops = &device_ops, diff --git a/src/southbridge/intel/i82801gx/i82801gx_nvs.h b/src/southbridge/intel/i82801gx/i82801gx_nvs.h index 3f01f2ace9..7f245dd11a 100644 --- a/src/southbridge/intel/i82801gx/i82801gx_nvs.h +++ b/src/southbridge/intel/i82801gx/i82801gx_nvs.h @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2008 coresystems GmbH + * Copyright (C) 2008-2009 coresystems GmbH * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -20,44 +20,48 @@ */ typedef struct { - u16 osys; - u8 smif; - u8 prm0; - u8 prm1; - u8 scif; - u8 prm2; - u8 prm3; - u8 lckf; - u8 prm4; - u8 prm5; - u32 p80d; - u8 lids; - u8 pwrs; - u8 dbgs; - u8 linxs; - u8 rsvd; - u8 actt; - u8 psvt; - u8 tc1v; - u8 tc2v; - u8 tspv; - u8 crtt; - u8 dtse; - u8 dts1; - u8 dts2; + /* Miscellaneous */ + u16 osys; /* 0x00 - Operating System */ + u8 smif; /* 0x02 - SMI function call ("TRAP") */ + u8 prm0; /* 0x03 - SMI function call parameter */ + u8 prm1; /* 0x04 - SMI function call parameter */ + u8 scif; /* 0x05 - SCI function call (via _L00) */ + u8 prm2; /* 0x06 - SCI function call parameter */ + u8 prm3; /* 0x07 - SCI function call parameter */ + u8 lckf; /* 0x08 - Global Lock function for EC */ + u8 prm4; /* 0x09 - Lock function parameter */ + u8 prm5; /* 0x0a - Lock function parameter */ + u32 p80d; /* 0x0b - Debug port (IO 0x80) value */ + u8 lids; /* 0x0f - LID state (open = 1) */ + u8 pwrs; /* 0x10 - Power state (AC = 1) */ + u8 dbgs; /* 0x11 - Debug state */ + u8 linx; /* 0x12 - Linux OS */ + u8 dckn; /* 0x13 - PCIe docking state */ + /* Thermal policy */ + u8 actt; /* 0x14 - active trip point */ + u8 psvt; /* 0x15 - passive trip point */ + u8 tc1v; /* 0x16 - passive trip point TC1 */ + u8 tc2v; /* 0x17 - passive trip point TC2 */ + u8 tspv; /* 0x18 - passive trip point TSP */ + u8 crtt; /* 0x19 - critical trip point */ + u8 dtse; /* 0x1a - Digital Thermal Sensor enable */ + u8 dts1; /* 0x1b - DT sensor 1 */ + u8 dts2; /* 0x1c - DT sensor 2 */ u8 rsvd2; - u8 bnum; - u8 b0sc, b1sc, b2sc; - u8 b0ss, b1ss, b2ss; + /* Battery Support */ + u8 bnum; /* 0x1e - number of batteries */ + u8 b0sc, b1sc, b2sc; /* 0x1f-0x21 - stored capacity */ + u8 b0ss, b1ss, b2ss; /* 0x22-0x24 - stored status */ u8 rsvd3[3]; - u8 apic; - u8 mpen; - u8 bten; - u8 ppcm; - u8 pcp0; - u8 pcp1; - u8 rsvd4[4]; - u8 natp; + /* Processor Identification */ + u8 apic; /* 0x28 - APIC enabled */ + u8 mpen; /* 0x29 - MP capable/enabled */ + u8 pcp0; /* 0x2a - PDC CPU/CORE 0 */ + u8 pcp1; /* 0x2b - PDC CPU/CORE 1 */ + u8 ppcm; /* 0x2c - Max. PPC state */ + u8 rsvd4[5]; + /* Super I/O & CMOS config */ + u8 natp; /* 0x32 - SIO type */ u8 cmap; u8 cmbp; u8 lptp; @@ -67,42 +71,69 @@ typedef struct { u8 rtcf; u8 util; u8 acin; - u8 igds; - u8 tlst; - u8 cadl; - u8 padl; - u16 cste; - u16 pste; - u16 nste; - u16 sste; - u8 ndid; - u32 did1; - u32 did2; - u32 did3; - u32 did4; - u32 did5; - u8 rsvd5[0xb]; + /* Integrated Graphics Device */ + u8 igds; /* 0x3c - IGD state */ + u8 tlst; /* 0x3d - Display Toggle List Pointer */ + u8 cadl; /* 0x3e - currently attached devices */ + u8 padl; /* 0x3f - previously attached devices */ + u16 cste; /* 0x40 - current display state */ + u16 nste; /* 0x42 - next display state */ + u16 sste; /* 0x44 - set display state */ + u8 ndid; /* 0x46 - number of device ids */ + u32 did[5]; /* 0x47 - 5b device id 1..5 */ + u8 rsvd5[0x9]; + /* Backlight Control */ + u8 blcs; /* 0x64 - Backlight Control possible */ u8 brtl; u8 odds; - u8 alse; + u8 rsvd6[0x7]; + /* Ambient Light Sensors*/ + u8 alse; /* 0x6e - ALS enable */ u8 alaf; u8 llow; u8 lhih; - u8 rsvd6; - u8 emae; + u8 rsvd7[0x6]; + /* EMA */ + u8 emae; /* 0x78 - EMA enable */ u16 emap; u16 emal; - u8 rsvd7; - u8 mefe; - u8 igps; - u8 rsvd8[2]; - u8 tpmp; + u8 rsvd8[0x5]; + /* MEF */ + u8 mefe; /* 0x82 - MEF enable */ + u8 rsvd9[0x9]; + /* TPM support */ + u8 tpmp; /* 0x8c - TPM */ u8 tpme; - u8 rsvd9[8]; - u8 gtf0[7]; + u8 rsvd10[8]; + /* SATA */ + u8 gtf0[7]; /* 0x96 - GTF task file buffer for port 0 */ + u8 gtf1[7]; u8 gtf2[7]; u8 idem; u8 idet; - u8 dock; -} global_nvs_t; + u8 rsvd11[7]; + /* IGD OpRegion (not implemented yet) */ + u32 aslb; /* 0xb4 - IGD OpRegion Base Address */ + u8 ibtt; + u8 ipat; + u8 itvf; + u8 itvm; + u8 ipsc; + u8 iblc; + u8 ibia; + u8 issc; + u8 i409; + u8 i509; + u8 i609; + u8 i709; + u8 idmm; + u8 idms; + u8 if1e; + u8 hvco; + u32 nxd[8]; + u8 rsvd12[8]; + /* Mainboard specific */ + u8 dock; /* 0xf0 - Docking Status */ + u8 rsvd13[15]; +} __attribute__((packed)) global_nvs_t; diff --git a/src/southbridge/intel/i82801gx/i82801gx_pci.c b/src/southbridge/intel/i82801gx/i82801gx_pci.c index bf252ec37e..2e1a251e37 100644 --- a/src/southbridge/intel/i82801gx/i82801gx_pci.c +++ b/src/southbridge/intel/i82801gx/i82801gx_pci.c @@ -81,7 +81,7 @@ static void ich_pci_dev_enable_resources(struct device *dev) command = pci_read_config16(dev, PCI_COMMAND); command |= dev->command; -#if PCI_BRIDGE_UPDATE_COMMAND +#ifdef PCI_BRIDGE_UPDATE_COMMAND /* If we write to PCI_COMMAND, on some systems * this will cause the ROM and APICs not being visible * anymore. diff --git a/src/southbridge/intel/i82801gx/i82801gx_power.h b/src/southbridge/intel/i82801gx/i82801gx_power.h new file mode 100644 index 0000000000..d2eb8b430d --- /dev/null +++ b/src/southbridge/intel/i82801gx/i82801gx_power.h @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#define MAINBOARD_POWER_OFF 0 +#define MAINBOARD_POWER_ON 1 +#define MAINBOARD_POWER_KEEP 2 + +#ifndef MAINBOARD_POWER_ON_AFTER_FAIL +#define MAINBOARD_POWER_ON_AFTER_FAIL MAINBOARD_POWER_ON +#endif + diff --git a/src/southbridge/intel/i82801gx/i82801gx_sata.c b/src/southbridge/intel/i82801gx/i82801gx_sata.c index 0f092e9204..74ba823f34 100644 --- a/src/southbridge/intel/i82801gx/i82801gx_sata.c +++ b/src/southbridge/intel/i82801gx/i82801gx_sata.c @@ -35,8 +35,10 @@ static void sata_init(struct device *dev) printk_debug("i82801gx_sata: initializing...\n"); - if (config == NULL) + if (config == NULL) { printk_err("i82801gx_sata: error: device not in Config.lb!\n"); + return; + } /* SATA configuration */ @@ -55,12 +57,15 @@ static void sata_init(struct device *dev) pci_write_config8(dev, 0x09, 0x80); /* Set timings */ - pci_write_config16(dev, IDE_TIM_PRI, 0x8000); - pci_write_config16(dev, IDE_TIM_SEC, 0xa307); + pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE | + IDE_ISP_5_CLOCKS | IDE_RCT_4_CLOCKS); + pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE | + IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS | + IDE_PPE0 | IDE_IE0 | IDE_TIME0); /* Sync DMA */ - pci_write_config16(dev, 0x48, 0x0004); - pci_write_config16(dev, 0x4a, 0x0200); + pci_write_config16(dev, IDE_SDMA_CNT, IDE_SSDE0); + pci_write_config16(dev, IDE_SDMA_TIM, 0x0200); /* Set IDE I/O Configuration */ reg32 = SIG_MODE_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0; @@ -84,12 +89,15 @@ static void sata_init(struct device *dev) pci_write_config8(dev, INTR_LN, 0x0a); /* Set timings */ - pci_write_config16(dev, IDE_TIM_PRI, 0xa307); - pci_write_config16(dev, IDE_TIM_SEC, 0x8000); + pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE | + IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS | + IDE_PPE0 | IDE_IE0 | IDE_TIME0); + pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE | + IDE_ISP_5_CLOCKS | IDE_RCT_4_CLOCKS); /* Sync DMA */ - pci_write_config16(dev, 0x48, 0x0001); - pci_write_config16(dev, 0x4a, 0x0001); + pci_write_config16(dev, IDE_SDMA_CNT, IDE_PSDE0); + pci_write_config16(dev, IDE_SDMA_TIM, 0x0001); /* Set IDE I/O Configuration */ reg32 = SIG_MODE_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0; @@ -126,12 +134,16 @@ static void sata_init(struct device *dev) pci_write_config8(dev, INTR_LN, 0xff); /* Set timings */ - pci_write_config16(dev, IDE_TIM_PRI, 0xa307); - pci_write_config16(dev, IDE_TIM_SEC, 0xe303); + pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE | + IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS | + IDE_PPE0 | IDE_IE0 | IDE_TIME0); + pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE | + IDE_SITRE | IDE_ISP_3_CLOCKS | + IDE_RCT_1_CLOCKS | IDE_IE0 | IDE_TIME0); /* Sync DMA */ - pci_write_config16(dev, 0x48, 0x0005); - pci_write_config16(dev, 0x4a, 0x0201); + pci_write_config16(dev, IDE_SDMA_CNT, IDE_SSDE0 | IDE_PSDE0); + pci_write_config16(dev, IDE_SDMA_TIM, 0x0201); /* Set IDE I/O Configuration */ reg32 = SIG_MODE_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0; diff --git a/src/southbridge/intel/i82801gx/i82801gx_smbus.c b/src/southbridge/intel/i82801gx/i82801gx_smbus.c index e9f9c7d918..ee9f47e811 100644 --- a/src/southbridge/intel/i82801gx/i82801gx_smbus.c +++ b/src/southbridge/intel/i82801gx/i82801gx_smbus.c @@ -29,6 +29,19 @@ #include "i82801gx.h" #include "i82801gx_smbus.h" +#define SMB_BASE 0x20 +static void smbus_init(struct device *dev) +{ + u32 smb_base; + + smb_base = pci_read_config32(dev, SMB_BASE); + printk_debug("Initializing SMBus device:\n"); + printk_debug(" Old SMBUS Base Address: 0x%04x\n", smb_base); + pci_write_config32(dev, SMB_BASE, 0x00000401); + smb_base = pci_read_config32(dev, SMB_BASE); + printk_debug(" New SMBUS Base Address: 0x%04x\n", smb_base); +} + static int lsmbus_read_byte(device_t dev, u8 address) { u16 device; @@ -65,7 +78,7 @@ static struct device_operations smbus_ops = { .read_resources = pci_dev_read_resources, .set_resources = pci_dev_set_resources, .enable_resources = pci_dev_enable_resources, - .init = 0, + .init = smbus_init, .scan_bus = scan_static_bus, .enable = i82801gx_enable, .ops_smbus_bus = &lops_smbus_bus, diff --git a/src/southbridge/intel/i82801gx/i82801gx_smi.c b/src/southbridge/intel/i82801gx/i82801gx_smi.c index ccbb7334e5..636d2eb3af 100644 --- a/src/southbridge/intel/i82801gx/i82801gx_smi.c +++ b/src/southbridge/intel/i82801gx/i82801gx_smi.c @@ -27,10 +27,7 @@ #include #include #include -#include "chip.h" - -// Future TODO: Move to i82801gx directory -#include "../../../northbridge/intel/i945/ich7.h" +#include "i82801gx.h" extern unsigned char smm[]; extern unsigned int smm_len; @@ -318,8 +315,12 @@ void smm_install(void) void smm_init(void) { + // FIXME is this a race condition? smm_relocate(); smm_install(); + + // We're done. Make sure SMIs can happen! + smi_set_eos(); } void smm_lock(void) @@ -333,3 +334,13 @@ void smm_lock(void) D_LCK | G_SMRAME | C_BASE_SEG); } +void smm_setup_structures(void *gnvs, void *tcg, void *smi1) +{ + /* The GDT or coreboot table is going to live here. But a long time + * after we relocated the GNVS, so this is not troublesome. + */ + *(u32 *)0x500 = (u32)gnvs; + *(u32 *)0x504 = (u32)tcg; + *(u32 *)0x508 = (u32)smi1; + outb(0xea, 0xb2); +} diff --git a/src/southbridge/intel/i82801gx/i82801gx_smihandler.c b/src/southbridge/intel/i82801gx/i82801gx_smihandler.c index d2826c6aca..94207d0e4d 100644 --- a/src/southbridge/intel/i82801gx/i82801gx_smihandler.c +++ b/src/southbridge/intel/i82801gx/i82801gx_smihandler.c @@ -19,22 +19,24 @@ * MA 02110-1301 USA */ +#include #include #include #include #include #include -//#include "chip.h" - -// Future TODO: Move to i82801gx directory -#include "../../../northbridge/intel/i945/ich7.h" +#include "i82801gx.h" +#include "i82801gx_power.h" #define DEBUG_SMI #define APM_CNT 0xb2 -#define APM_STS 0xb3 +#define CST_CONTROL 0x85 // 0x85 crashes the box +#define PST_CONTROL 0x80 // 0x80 crashes the box #define ACPI_DISABLE 0x1e #define ACPI_ENABLE 0xe1 +#define GNVS_UPDATE 0xea +#define APM_STS 0xb3 /* I945 */ #define SMRAM 0x9d @@ -48,6 +50,11 @@ #define PM1_STS 0x00 #define PM1_EN 0x02 #define PM1_CNT 0x04 +#define SLP_EN (1 << 13) +#define SLP_TYP (7 << 10) +#define GBL_RLS (1 << 2) +#define BM_RLD (1 << 1) +#define SCI_EN (1 << 0) #define PM1_TMR 0x08 #define PROC_CNT 0x10 #define LV2 0x14 @@ -56,6 +63,7 @@ #define PM2_CNT 0x20 // mobile only #define GPE0_STS 0x28 #define GPE0_EN 0x2c +#define PME_B0_EN (1 << 13) #define SMI_EN 0x30 #define EL_SMI_EN (1 << 25) // Intel Quick Resume Technology #define INTEL_USB2_EN (1 << 18) // Intel-Specific USB2 SMI logic @@ -84,7 +92,14 @@ /* While we read PMBASE dynamically in case it changed, let's * initialize it with a sane value */ -static u16 pmbase = DEFAULT_PMBASE; +u16 pmbase = DEFAULT_PMBASE; + +/* GNVS needs to be updated by an 0xEA PM Trap (B2) after it has been located + * by coreboot. + */ +global_nvs_t *gnvs = (global_nvs_t *)0x0; +void *tcg = (void *)0x0; +void *smi1 = (void *)0x0; /** * @brief read and clear PM1_STS @@ -235,7 +250,6 @@ static void dump_tco_status(u32 tco_sts) printk_debug("\n"); } - /* We are using PCIe accesses for now * 1. the chipset can do it * 2. we don't need to worry about how we leave 0xcf8/0xcfc behind @@ -244,12 +258,10 @@ static void dump_tco_status(u32 tco_sts) int southbridge_io_trap_handler(int smif) { - global_nvs_t *gnvs = (global_nvs_t *)0xc00; - switch (smif) { case 0x32: printk_debug("OS Init\n"); - //gnvs->smif = 0; + gnvs->smif = 0; break; default: /* Not handled */ @@ -278,141 +290,337 @@ void southbridge_smi_set_eos(void) outb(reg8, pmbase + SMI_EN); } -/** - * @brief Interrupt handler for SMI# - * - * @param smm_revision revision of the smm state save map - */ -void southbridge_smi_handler(unsigned int node, smm_state_save_area_t *state_save) +static void southbridge_smi_sleep(unsigned int node, smm_state_save_area_t *state_save) { u8 reg8; - u16 pmctrl; - u16 pm1_sts; - u32 smi_sts, gpe0_sts, tco_sts; + u32 reg32; + u8 slp_typ; + /* FIXME: the power state on boot should be read from + * CMOS or even better from GNVS. Right now it's hard + * coded at compile time. + */ + u8 s5pwr = MAINBOARD_POWER_ON_AFTER_FAIL; - pmbase = pcie_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc; - printk_spew("SMI#: pmbase = 0x%04x\n", pmbase); + /* First, disable further SMIs */ + reg8 = inb(pmbase + SMI_EN); + reg8 &= ~SLP_SMI_EN; + outb(reg8, pmbase + SMI_EN); - /* We need to clear the SMI status registers, or we won't see what's - * happening in the following calls. - */ - smi_sts = reset_smi_status(); - dump_smi_status(smi_sts); + /* Figure out SLP_TYP */ + reg32 = inl(pmbase + PM1_CNT); + printk_spew("SMI#: SLP = 0x%08x\n", reg32); + slp_typ = (reg32 >> 10) & 7; - if (smi_sts & (1 << 21)) { // MONITOR - global_nvs_t *gnvs = (global_nvs_t *)0xc00; - int i; - u32 reg32; + /* Next, do the deed. + */ - reg32 = RCBA32(0x1e00); // TRSR - Trap Status Register + switch (slp_typ) { + case 0: printk_debug("SMI#: Entering S0 (On)\n"); break; + case 1: printk_debug("SMI#: Entering S1 (Assert STPCLK#)\n"); break; + case 5: + printk_debug("SMI#: Entering S3 (Suspend-To-RAM)\n"); + /* Invalidate the cache before going to S3 */ + wbinvd(); + break; + case 6: printk_debug("SMI#: Entering S4 (Suspend-To-Disk)\n"); break; + case 7: + printk_debug("SMI#: Entering S5 (Soft Power off)\n"); #if 0 - /* Comment in for some useful debug */ - for (i=0; i<4; i++) { - if (reg32 & (1 << i)) { - printk_debug(" io trap #%d\n", i); - } - } + /* Set PME_B0_EN before going to S5 */ + reg32 = inl(pmbase + GPE0_EN); + reg32 |= PME_B0_EN; + outl(reg32, pmbase + GPE0_EN); #endif - RCBA32(0x1e00) = reg32; // TRSR + /* Should we keep the power state after a power loss? + * In case the setting is "ON" or "OFF" we don't have + * to do anything. But if it's "KEEP" we have to switch + * to "OFF" before entering S5. + */ + if (s5pwr == MAINBOARD_POWER_KEEP) { + reg8 = pcie_read_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_3); + reg8 |= 1; + pcie_write_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_3, reg8); + } + break; + default: printk_debug("SMI#: ERROR: SLP_TYP reserved\n"); break; + } - reg32 = RCBA32(0x1e10); + /* Write back to the SLP register to cause the originally intended + * event again. We need to set BIT13 (SLP_EN) though to make the + * sleep happen. + */ + outl(reg32 | SLP_EN, pmbase + PM1_CNT); - if ((reg32 & 0xfffc) != 0x808) { - printk_debug(" trapped io address = 0x%x\n", reg32 & 0xfffc); - printk_debug(" AHBE = %x\n", (reg32 >> 16) & 0xf); - printk_debug(" read/write: %s\n", (reg32 & (1 << 24)) ? "read" : - "write"); - } + /* In most sleep states, the code flow of this function ends at + * the line above. However, if we entered sleep state S1 and wake + * up again, we will continue to execute code in this function. + */ + reg32 = inl(pmbase + PM1_CNT); + if (reg32 & SCI_EN) { + /* The OS is not an ACPI OS, so we set the state to S0 */ + reg32 &= ~(SLP_EN | SLP_TYP); + outl(reg32, pmbase + PM1_CNT); + } +} - if (!(reg32 & (1 << 24))) { - /* Write Cycle */ - reg32 = RCBA32(0x1e18); - printk_debug(" iotrap written data = 0x%08x\n", reg32); +static void southbridge_smi_apmc(unsigned int node, smm_state_save_area_t *state_save) +{ + u32 pmctrl; + u8 reg8; - } + /* Emulate B2 register as the FADT / Linux expects it */ - if (gnvs->smif) - io_trap_handler(gnvs->smif); // call function smif + reg8 = inb(APM_CNT); + switch (reg8) { + case CST_CONTROL: + /* Calling this function seems to cause + * some kind of race condition in Linux + * and causes a kernel oops + */ + printk_debug("C-state control\n"); + break; + case PST_CONTROL: + /* Calling this function seems to cause + * some kind of race condition in Linux + * and causes a kernel oops + */ + printk_debug("P-state control\n"); + break; + case ACPI_DISABLE: + pmctrl = inl(pmbase + PM1_CNT); + pmctrl &= ~SCI_EN; + outl(pmctrl, pmbase + PM1_CNT); + printk_debug("SMI#: ACPI disabled.\n"); + break; + case ACPI_ENABLE: + pmctrl = inl(pmbase + PM1_CNT); + pmctrl |= SCI_EN; + outl(pmctrl, pmbase + PM1_CNT); + printk_debug("SMI#: ACPI enabled.\n"); + break; + case GNVS_UPDATE: + gnvs = *(global_nvs_t **)0x500; + tcg = *(void **)0x504; + smi1 = *(void **)0x508; + printk_debug("SMI#: Setting up structures to %p, %p, %p\n", gnvs, tcg, smi1); + break; + default: + printk_debug("SMI#: Unknown function APM_CNT=%02x\n", reg8); } +} - if (smi_sts & (1 << 13)) { // TCO - tco_sts = reset_tco_status(); - dump_tco_status(tco_sts); +static void southbridge_smi_pm1(unsigned int node, smm_state_save_area_t *state_save) +{ + u16 pm1_sts; - if (tco_sts & (1 << 8)) { // BIOSWR - u8 bios_cntl; - - bios_cntl = pcie_read_config16(PCI_DEV(0, 0x1f, 0), 0xdc); - - if (bios_cntl & 1) { - /* BWE is RW, so the SMI was caused by a - * write to BWE, not by a write to the BIOS - */ - - /* This is the place where we notice someone - * is trying to tinker with the BIOS. We are - * trying to be nice and just ignore it. A more - * resolute answer would be to power down the - * box. - */ - printk_debug("Switching back to RO\n"); - pcie_write_config32(PCI_DEV(0, 0x1f, 0), 0xdc, (bios_cntl & ~1)); - } /* No else for now? */ - } + pm1_sts = reset_pm1_status(); + dump_pm1_status(pm1_sts); +} + +static void southbridge_smi_gpe0(unsigned int node, smm_state_save_area_t *state_save) +{ + u32 gpe0_sts; + + gpe0_sts = reset_gpe0_status(); + dump_gpe0_status(gpe0_sts); +} + +static void southbridge_smi_mc(unsigned int node, smm_state_save_area_t *state_save) +{ + u32 reg32; + + reg32 = inl(pmbase + SMI_EN); + + /* Are periodic SMIs enabled? */ + if ((reg32 & MCSMI_EN) == 0) + return; + + printk_debug("Microcontroller SMI.\n"); +} + + + +static void southbridge_smi_tco(unsigned int node, smm_state_save_area_t *state_save) +{ + u32 tco_sts; + + tco_sts = reset_tco_status(); + + /* Any TCO event? */ + if (!tco_sts) + return; + + if (tco_sts & (1 << 8)) { // BIOSWR + u8 bios_cntl; + + bios_cntl = pcie_read_config16(PCI_DEV(0, 0x1f, 0), 0xdc); + + if (bios_cntl & 1) { + /* BWE is RW, so the SMI was caused by a + * write to BWE, not by a write to the BIOS + */ + + /* This is the place where we notice someone + * is trying to tinker with the BIOS. We are + * trying to be nice and just ignore it. A more + * resolute answer would be to power down the + * box. + */ + printk_debug("Switching back to RO\n"); + pcie_write_config32(PCI_DEV(0, 0x1f, 0), 0xdc, (bios_cntl & ~1)); + } /* No else for now? */ + } else if (tco_sts & (1 << 3)) { /* TIMEOUT */ + /* Handle TCO timeout */ + printk_debug("TCO Timeout.\n"); + } else if (!tco_sts) { + dump_tco_status(tco_sts); } +} + +static void southbridge_smi_periodic(unsigned int node, smm_state_save_area_t *state_save) +{ + u32 reg32; + + reg32 = inl(pmbase + SMI_EN); + + /* Are periodic SMIs enabled? */ + if ((reg32 & PERIODIC_EN) == 0) + return; + + printk_debug("Periodic SMI.\n"); +} + +static void southbridge_smi_monitor(unsigned int node, smm_state_save_area_t *state_save) +{ +#define IOTRAP(x) (trap_sts & (1 << x)) + u32 trap_sts, trap_cycle; + u32 data, mask = 0; + int i; - if (smi_sts & (1 << 8)) { // PM1 - pm1_sts = reset_pm1_status(); - dump_pm1_status(pm1_sts); + trap_sts = RCBA32(0x1e00); // TRSR - Trap Status Register + RCBA32(0x1e00) = trap_sts; // Clear trap(s) in TRSR + + trap_cycle = RCBA32(0x1e10); + for (i=16; i<20; i++) { + if (trap_cycle & (1 << i)) + mask |= (0xff << ((i - 16) << 2)); } - if (smi_sts & (1 << 9)) { // GPE0 - gpe0_sts = reset_gpe0_status(); - dump_gpe0_status(gpe0_sts); + + /* IOTRAP(3) SMI function call */ + if (IOTRAP(3)) { + if (gnvs && gnvs->smif) + io_trap_handler(gnvs->smif); // call function smif + return; } - if (smi_sts & (1 << 5)) { // APM - /* Emulate B2 register as the FADT / Linux expects it */ - - reg8 = inb(0xb2); - switch (reg8) { - case ACPI_DISABLE: - pmctrl = inw(pmbase + 0x04); - pmctrl |= (1 << 0); - outw(pmctrl, pmbase + 0x04); - printk_debug("SMI#: ACPI disabled.\n"); - break; - case ACPI_ENABLE: - pmctrl = inw(pmbase + 0x04); - pmctrl &= ~(1 << 0); - outw(pmctrl, pmbase + 0x04); - printk_debug("SMI#: ACPI enabled.\n"); - break; + /* IOTRAP(2) currently unused + * IOTRAP(1) currently unused */ + + /* IOTRAP(0) SMIC */ + if (IOTRAP(0)) { + if (!(trap_cycle & (1 << 24))) { // It's a write + printk_debug("SMI1 command\n"); + data = RCBA32(0x1e18); + data &= mask; + // if (smi1) + // southbridge_smi_command(data); + // return; } + // Fall through to debug } - if (smi_sts & (1 << 4)) { // SLP_SMI - u32 reg32; + printk_debug(" trapped io address = 0x%x\n", trap_cycle & 0xfffc); + for (i=0; i < 4; i++) if(IOTRAP(i)) printk_debug(" TRAPĀ = %d\n", i); + printk_debug(" AHBE = %x\n", (trap_cycle >> 16) & 0xf); + printk_debug(" MASK = 0x%08x\n", mask); + printk_debug(" read/write: %s\n", (trap_cycle & (1 << 24)) ? "read" : "write"); - /* First, disable further SMIs */ - reg8 = inb(pmbase + SMI_EN); - reg8 &= ~SLP_SMI_EN; - outb(reg8, pmbase + SMI_EN); + if (!(trap_cycle & (1 << 24))) { + /* Write Cycle */ + data = RCBA32(0x1e18); + printk_debug(" iotrap written data = 0x%08x\n", data); + } +#undef IOTRAP +} - /* Next, do the deed, we should change - * power on after power loss bits here - * if we're going to S5 - */ +typedef void (*smi_handler)(unsigned int node, + smm_state_save_area_t *state_save); + +smi_handler southbridge_smi[32] = { + NULL, // [0] reserved + NULL, // [1] reserved + NULL, // [2] BIOS_STS + NULL, // [3] LEGACY_USB_STS + southbridge_smi_sleep, // [4] SLP_SMI_STS + southbridge_smi_apmc, // [5] APM_STS + NULL, // [6] SWSMI_TMR_STS + NULL, // [7] reserved + southbridge_smi_pm1, // [8] PM1_STS + southbridge_smi_gpe0, // [9] GPE0_STS + NULL, // [10] GPI_STS + southbridge_smi_mc, // [11] MCSMI_STS + NULL, // [12] DEVMON_STS + southbridge_smi_tco, // [13] TCO_STS + southbridge_smi_periodic, // [14] PERIODIC_STS + NULL, // [15] SERIRQ_SMI_STS + NULL, // [16] SMBUS_SMI_STS + NULL, // [17] LEGACY_USB2_STS + NULL, // [18] INTEL_USB2_STS + NULL, // [19] reserved + NULL, // [20] PCI_EXP_SMI_STS + southbridge_smi_monitor, // [21] MONITOR_STS + NULL, // [22] reserved + NULL, // [23] reserved + NULL, // [24] reserved + NULL, // [25] EL_SMI_STS + NULL, // [26] SPI_STS + NULL, // [27] reserved + NULL, // [28] reserved + NULL, // [29] reserved + NULL, // [30] reserved + NULL // [31] reserved +}; - /* Write back to the SLP register to cause the - * originally intended event again. We need to set BIT13 - * (SLP_EN) though to make the sleep happen. - */ - reg32 = inl(pmbase + 0x04); - printk_debug("SMI#: SLP = 0x%08x\n", reg32); - printk_debug("SMI#: Powering off.\n"); - outl(reg32 | (1 << 13), pmbase + 0x04); +/** + * @brief Interrupt handler for SMI# + * + * @param smm_revision revision of the smm state save map + */ + +void southbridge_smi_handler(unsigned int node, smm_state_save_area_t *state_save) +{ + int i, dump = 0; + u32 smi_sts; + + /* Update global variable pmbase */ + pmbase = pcie_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc; + + /* We need to clear the SMI status registers, or we won't see what's + * happening in the following calls. + */ + smi_sts = reset_smi_status(); + + /* Filter all non-enabled SMI events */ + // FIXME Double check, this clears MONITOR + // smi_sts &= inl(pmbase + SMI_EN); + + /* Call SMI sub handler for each of the status bits */ + for (i = 0; i < 31; i++) { + if (smi_sts & (1 << i)) { + if (southbridge_smi[i]) + southbridge_smi[i](node, state_save); + else { + printk_debug("SMI_STS[%d] occured, but no " + "handler available.\n", i); + dump = 1; + } + } + } + + if(dump) { + dump_smi_status(smi_sts); } } diff --git a/src/southbridge/intel/i82801gx/i82801gx_usb_debug.c b/src/southbridge/intel/i82801gx/i82801gx_usb_debug.c index be524cabaa..9460a34c2f 100644 --- a/src/southbridge/intel/i82801gx/i82801gx_usb_debug.c +++ b/src/southbridge/intel/i82801gx/i82801gx_usb_debug.c @@ -21,16 +21,26 @@ #define EHCI_BAR 0xFEF00000 // These could be read from DEBUG_BASE (0:1d.7 R 0x5A 16bit) #define EHCI_BAR_INDEX 0x10 + +#define EHCI_CONFIG_FLAG 0x40 +#define EHCI_PORTSC 0x44 #define EHCI_DEBUG_OFFSET 0xA0 -static void set_debug_port(unsigned port) +void set_debug_port(unsigned port) { - // Nothing for now? + u32 dbgctl; + + printk_debug("Enabling OWNER_CNT\n"); + dbgctl = readl(EHCI_BAR + EHCI_DEBUG_OFFSET); + dbgctl |= (1 << 30); + writel(dbgctl, EHCI_BAR + EHCI_DEBUG_OFFSET); + } static void i82801gx_enable_usbdebug_direct(unsigned port) { pci_write_config32(PCI_DEV(0, 0x1d, 7), EHCI_BAR_INDEX, EHCI_BAR); pci_write_config8(PCI_DEV(0, 0x1d, 7), 0x04, 0x2); // Memory Space Enable + set_debug_port(port); } diff --git a/src/southbridge/intel/i82801gx/i82801gx_usb_ehci.c b/src/southbridge/intel/i82801gx/i82801gx_usb_ehci.c index 39a5799ed9..90ef28ae3a 100644 --- a/src/southbridge/intel/i82801gx/i82801gx_usb_ehci.c +++ b/src/southbridge/intel/i82801gx/i82801gx_usb_ehci.c @@ -31,7 +31,7 @@ static void usb_ehci_init(struct device *dev) { struct resource *res; - u8 *base; + u32 base; u32 reg32; u8 reg8; @@ -52,9 +52,9 @@ static void usb_ehci_init(struct device *dev) /* Clear any pending port changes */ res = find_resource(dev, 0x10); - base =(u8 *)res->base; - reg32 = readl(base + 0x24) | (1 << 2); - writel(base + 0x24, reg32); + base = res->base; + reg32 = readl((u8 *)base + 0x24) | (1 << 2); + writel(reg32, (u8 *)base + 0x24); /* workaround */ reg8 = pci_read_config8(dev, 0x84); @@ -115,7 +115,7 @@ static struct pci_operations lops_pci = { static struct device_operations usb_ehci_ops = { .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, + .set_resources = usb_ehci_set_resources, .enable_resources = pci_dev_enable_resources, .init = usb_ehci_init, .scan_bus = 0, -- cgit v1.2.3