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 <stepan@coresystems.de>
Acked-by: Peter Stuge <peter@stuge.se>



git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4456 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Stefan Reinauer 2009-07-21 21:50:34 +00:00 committed by Stefan Reinauer
parent 71a3d96bc4
commit 573f7d40be
20 changed files with 1119 additions and 304 deletions

View File

@ -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
}

View File

@ -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")

View File

@ -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 })
}

View File

@ -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.
})
}

View File

@ -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}
})
}
}

View File

@ -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")
}
}

View File

@ -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

View File

@ -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})

View File

@ -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 */

View File

@ -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) */

View File

@ -27,17 +27,12 @@
#include <pc80/i8259.h>
#include <arch/io.h>
#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,

View File

@ -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;

View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -27,10 +27,7 @@
#include <cpu/x86/cache.h>
#include <cpu/x86/smm.h>
#include <string.h>
#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);
}

View File

@ -19,22 +19,24 @@
* MA 02110-1301 USA
*/
#include <types.h>
#include <arch/io.h>
#include <arch/romcc_io.h>
#include <console/console.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/smm.h>
//#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,6 +290,299 @@ void southbridge_smi_set_eos(void)
outb(reg8, pmbase + SMI_EN);
}
static void southbridge_smi_sleep(unsigned int node, smm_state_save_area_t *state_save)
{
u8 reg8;
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;
/* First, disable further SMIs */
reg8 = inb(pmbase + SMI_EN);
reg8 &= ~SLP_SMI_EN;
outb(reg8, pmbase + SMI_EN);
/* Figure out SLP_TYP */
reg32 = inl(pmbase + PM1_CNT);
printk_spew("SMI#: SLP = 0x%08x\n", reg32);
slp_typ = (reg32 >> 10) & 7;
/* Next, do the deed.
*/
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
/* Set PME_B0_EN before going to S5 */
reg32 = inl(pmbase + GPE0_EN);
reg32 |= PME_B0_EN;
outl(reg32, pmbase + GPE0_EN);
#endif
/* 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;
}
/* 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);
/* 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);
}
}
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 */
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);
}
}
static void southbridge_smi_pm1(unsigned int node, smm_state_save_area_t *state_save)
{
u16 pm1_sts;
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;
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));
}
/* IOTRAP(3) SMI function call */
if (IOTRAP(3)) {
if (gnvs && gnvs->smif)
io_trap_handler(gnvs->smif); // call function smif
return;
}
/* 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
}
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");
if (!(trap_cycle & (1 << 24))) {
/* Write Cycle */
data = RCBA32(0x1e18);
printk_debug(" iotrap written data = 0x%08x\n", data);
}
#undef IOTRAP
}
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
};
/**
* @brief Interrupt handler for SMI#
*
@ -286,133 +591,36 @@ void southbridge_smi_set_eos(void)
void southbridge_smi_handler(unsigned int node, smm_state_save_area_t *state_save)
{
u8 reg8;
u16 pmctrl;
u16 pm1_sts;
u32 smi_sts, gpe0_sts, tco_sts;
int i, dump = 0;
u32 smi_sts;
/* Update global variable pmbase */
pmbase = pcie_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
printk_spew("SMI#: pmbase = 0x%04x\n", pmbase);
/* 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);
if (smi_sts & (1 << 21)) { // MONITOR
global_nvs_t *gnvs = (global_nvs_t *)0xc00;
int i;
u32 reg32;
/* Filter all non-enabled SMI events */
// FIXME Double check, this clears MONITOR
// smi_sts &= inl(pmbase + SMI_EN);
reg32 = RCBA32(0x1e00); // TRSR - Trap Status Register
#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);
/* 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;
}
}
#endif
RCBA32(0x1e00) = reg32; // TRSR
reg32 = RCBA32(0x1e10);
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");
}
if (!(reg32 & (1 << 24))) {
/* Write Cycle */
reg32 = RCBA32(0x1e18);
printk_debug(" iotrap written data = 0x%08x\n", reg32);
}
if (gnvs->smif)
io_trap_handler(gnvs->smif); // call function smif
}
if (smi_sts & (1 << 13)) { // TCO
tco_sts = reset_tco_status();
dump_tco_status(tco_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? */
}
}
if (smi_sts & (1 << 8)) { // PM1
pm1_sts = reset_pm1_status();
dump_pm1_status(pm1_sts);
}
if (smi_sts & (1 << 9)) { // GPE0
gpe0_sts = reset_gpe0_status();
dump_gpe0_status(gpe0_sts);
}
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;
}
}
if (smi_sts & (1 << 4)) { // SLP_SMI
u32 reg32;
/* First, disable further SMIs */
reg8 = inb(pmbase + SMI_EN);
reg8 &= ~SLP_SMI_EN;
outb(reg8, pmbase + SMI_EN);
/* Next, do the deed, we should change
* power on after power loss bits here
* if we're going to S5
*/
/* 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);
if(dump) {
dump_smi_status(smi_sts);
}
}

View File

@ -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);
}

View File

@ -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,