Add AMD dbm690t ACPI support.

The following ACPI features are supported.
1. S1, S5 sleep and wake up (by power button or PS/2 keyboard/mouse).
2. AMD powernow-k8 driver.
3. Thermal configuration based on ADT7461.
4. IDE timing settings.
5. HPET timer.
6. Interrupt routing based on ACPI table.


Signed-off-by:  Joe Bao <zheng.bao@amd.com>
Reviewed-by:    Maggie Li <maggie.li@amd.com>
Acked-by: Ronald G. Minnich <rminnich@gmail.com>
Acked-by: Marc Jones <marcj303@gmail.com>



git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3787 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Joe Bao 2008-12-01 19:52:54 +00:00 committed by Marc Jones
parent 40d46ba383
commit 7c3d3b2027
9 changed files with 455 additions and 208 deletions

View File

@ -70,6 +70,17 @@ if HAVE_PIRQ_TABLE
object irq_tables.o
end
if HAVE_ACPI_TABLES
object acpi_tables.o
object fadt.o
makerule dsdt.c
depends "$(MAINBOARD)/acpi/*.asl"
action "iasl -p $(PWD)/dsdt -tc $(MAINBOARD)/acpi/dsdt.asl"
action "mv dsdt.hex dsdt.c"
end
object ./dsdt.o
end
#object reset.o
if USE_DCACHE_RAM
@ -272,6 +283,8 @@ chip northbridge/amd/amdk8/root_complex
device pnp 2e.6 on # Mouse
irq 0x70 = 12
end
device pnp 2e.7 off # GPIO, must be closed for unresolved reason.
end
device pnp 2e.8 off # MIDI
io 0x60 = 0x300
irq 0x70 = 9

View File

@ -130,6 +130,9 @@ default IRQ_SLOT_COUNT=11
##
default HAVE_MP_TABLE=1
## ACPI tables will be included
default HAVE_ACPI_TABLES=1
##
## Build code to export a CMOS option table
##

View File

@ -163,6 +163,7 @@ void real_main(unsigned long bist, unsigned long cpu_init_detectedx)
msr_t msr;
struct sys_info *sysinfo = (struct sys_info *)(DCACHE_RAM_BASE + DCACHE_RAM_SIZE - DCACHE_RAM_GLOBAL_VAR_SIZE);
if (bist == 0) {
bsp_apicid = init_cpus(cpu_init_detectedx, sysinfo);
}
@ -203,7 +204,7 @@ void real_main(unsigned long bist, unsigned long cpu_init_detectedx)
enable_fid_change_on_sb(sysinfo->sbbusn, sysinfo->sbdn);
init_fidvid_bsp(bsp_apicid);
// show final fid and vid
/* show final fid and vid */
msr=rdmsr(0xc0010042);
printk_debug("end msr fid, vid: hi=0x%x, lo=0x%x\n", msr.hi, msr.lo);

View File

@ -21,6 +21,6 @@ extern struct chip_operations mainboard_amd_dbm690t_ops;
struct mainboard_amd_dbm690t_config
{
unsigned long uma_size; /* How many UMA should be used in memory for TOP. */
u32 uma_size; /* How many UMA should be used in memory for TOP. */
};

View File

@ -16,81 +16,184 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* ACPI - create the Fixed ACPI Description Tables (FADT)
*/
#include <string.h>
#include <console/console.h>
#include <arch/acpi.h>
#include <arch/io.h>
/*extern*/ u16 pm_base = 0x800;
/* pm_base should be set in sb acpi */
/* pm_base should be got from bar2 of rs690. Here I compact ACPI
* registers into 32 bytes limit.
* */
#define ACPI_PM_EVT_BLK (pm_base + 0x00) /* 4 bytes */
#define ACPI_PM1_CNT_BLK (pm_base + 0x04) /* 2 bytes */
#define ACPI_PMA_CNT_BLK (pm_base + 0x0F) /* 1 byte */
#define ACPI_PM_TMR_BLK (pm_base + 0x18) /* 4 bytes */
#define ACPI_GPE0_BLK (pm_base + 0x10) /* 8 bytes */
#define ACPI_CPU_CONTORL (pm_base + 0x08) /* 6 bytes */
/**
* Create the Fixed ACPI Description Tables (FADT) for this board.
The FADT defines various fixed hardware ACPI information vital to an ACPI-compatible
OS, such as the base address for the following hardware registers blocks:
PM1a_EVT_BLK, PM1b_EVT_BLK, PM1a_CNT_BLK, PM1b_CNT_BLK,
PM2_CNT_BLK, PM_TMR_BLK, GPE0_BLK and GPE1_BLK.
The FADT also has a pointer to the DSDT that contains the Differentiated Definition Block,
which in turn provides variable information to an ACPI-compatible OS concerning the base
system design.
Not all blocks are necessary usualy only PM1a, PMTMR and GPE0 are used.
*/
void acpi_create_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt)
void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt)
{
acpi_header_t *header=&(fadt->header);
acpi_header_t *header = &(fadt->header);
pm_base &= 0xFFFF;
printk_debug("pm_base: 0x%04x\n", pm_base);
memset((void *)fadt,0,sizeof(acpi_fadt_t));
/* Prepare the header */
memcpy(header->signature,"FACP",4);
memset((void *)fadt, 0, sizeof(acpi_fadt_t));
memcpy(header->signature, "FACP", 4);
header->length = 244;
header->revision = 1;
memcpy(header->oem_id,OEM_ID,6);
memcpy(header->oem_table_id,"LXBACPI ",8);
memcpy(header->asl_compiler_id,ASLC,4);
header->asl_compiler_revision=0;
memcpy(header->oem_id, OEM_ID, 6);
memcpy(header->oem_table_id, "COREBOOT", 8);
memcpy(header->asl_compiler_id, ASLC, 4);
header->asl_compiler_revision = 0;
fadt->firmware_ctrl=(u32)facs;
fadt->dsdt= (u32)dsdt;
/*
0: unspecified
1: desktop
2: mobile
3: workstation
4: enterprise server
*/
fadt->preferred_pm_profile=0x01;
/*
System vector the SCI interrupt is wired to in 8259 mode.
On systems that do not contain the 8259, this field contains the Global
System interrupt number of the SCI interrupt. OSPM is required to treat
the ACPI SCI interrupt as a sharable, level, active low interrupt.
SB600 BDG 4.1
*/
fadt->sci_int=4;
/*
System port address of the SMI Command Port. During ACPI OS initialization,
OSPM can determine that the ACPI hardware registers are owned by SMI (by way
of the SCI_EN bit), in which case the ACPI OS issues the ACPI_ENABLE command
to the SMI_CMD port. The SCI_EN bit effectively tracks the ownership of the
ACPI hardware registers. OSPM issues commands to the SMI_CMD port
synchronously from the boot processor.
This filed is reserved and must be zero on system that does not support
System Management mode.
*/
fadt->firmware_ctrl = (u32) facs;
fadt->dsdt = (u32) dsdt;
/* 3=Workstation,4=Enterprise Server, 7=Performance Server */
fadt->preferred_pm_profile = 0x03;
fadt->sci_int = 9;
/* disable system management mode by setting to 0: */
fadt->smi_cmd = 0;
/*Those two fields are reserved and must be zero on systems that do not
support Legacy Mode.*/
fadt->acpi_enable = 0;
fadt->acpi_disable = 0;
fadt->acpi_enable = 0xf0;
fadt->acpi_disable = 0xf1;
fadt->s4bios_req = 0x0;
fadt->pstate_cnt = 0x0;
fadt->pstate_cnt = 0xe2;
pm_iowrite(0x20, ACPI_PM_EVT_BLK & 0xFF);
pm_iowrite(0x21, ACPI_PM_EVT_BLK >> 8);
pm_iowrite(0x22, ACPI_PM1_CNT_BLK & 0xFF);
pm_iowrite(0x23, ACPI_PM1_CNT_BLK >> 8);
pm_iowrite(0x24, ACPI_PM_TMR_BLK & 0xFF);
pm_iowrite(0x25, ACPI_PM_TMR_BLK >> 8);
pm_iowrite(0x28, ACPI_GPE0_BLK & 0xFF);
pm_iowrite(0x29, ACPI_GPE0_BLK >> 8);
/* CpuControl is in \_PR.CPU0, 6 bytes */
pm_iowrite(0x26, ACPI_CPU_CONTORL & 0xFF);
pm_iowrite(0x27, ACPI_CPU_CONTORL >> 8);
pm_iowrite(0x2A, 0); /* AcpiSmiCmdLo */
pm_iowrite(0x2B, 0); /* AcpiSmiCmdHi */
pm_iowrite(0x2C, ACPI_PMA_CNT_BLK & 0xFF);
pm_iowrite(0x2D, ACPI_PMA_CNT_BLK >> 8);
pm_iowrite(0x0E, 1<<3 | 0<<2); /* AcpiDecodeEnable, When set, SB uses
* the contents of the PM registers at
* index 20-2B to decode ACPI I/O address.
* AcpiSmiEn & SmiCmdEn*/
pm_iowrite(0x10, 1<<1 | 1<<3| 1<<5); /* RTC_En_En, TMR_En_En, GBL_EN_EN */
outl(0x1, ACPI_PM1_CNT_BLK); /* set SCI_EN */
fadt->pm1a_evt_blk = ACPI_PM_EVT_BLK;
fadt->pm1b_evt_blk = 0x0000;
fadt->pm1a_cnt_blk = ACPI_PM1_CNT_BLK;
fadt->pm1b_cnt_blk = 0x0000;
fadt->pm2_cnt_blk = ACPI_PMA_CNT_BLK;
fadt->pm_tmr_blk = ACPI_PM_TMR_BLK;
fadt->gpe0_blk = ACPI_GPE0_BLK;
fadt->gpe1_blk = 0x0000; /* we dont have gpe1 block, do we? */
fadt->pm1_evt_len = 4;
fadt->pm1_cnt_len = 2;
fadt->pm2_cnt_len = 1;
fadt->pm_tmr_len = 4;
fadt->gpe0_blk_len = 8;
fadt->gpe1_blk_len = 0;
fadt->gpe1_base = 0;
fadt->cst_cnt = 0xe3;
fadt->p_lvl2_lat = 101;
fadt->p_lvl3_lat = 1001;
fadt->flush_size = 0;
fadt->flush_stride = 0;
fadt->duty_offset = 1;
fadt->duty_width = 3;
fadt->day_alrm = 0; /* 0x7d these have to be */
fadt->mon_alrm = 0; /* 0x7e added to cmos.layout */
fadt->century = 0; /* 0x7f to make rtc alrm work */
fadt->iapc_boot_arch = 0x3; /* See table 5-11 */
fadt->flags = 0x0001c1a5;/* 0x25; */
fadt->res2 = 0;
fadt->reset_reg.space_id = 1;
fadt->reset_reg.bit_width = 8;
fadt->reset_reg.bit_offset = 0;
fadt->reset_reg.resv = 0;
fadt->reset_reg.addrl = 0xcf9;
fadt->reset_reg.addrh = 0x0;
fadt->reset_value = 6;
fadt->x_firmware_ctl_l = (u32) facs;
fadt->x_firmware_ctl_h = 0;
fadt->x_dsdt_l = (u32) dsdt;
fadt->x_dsdt_h = 0;
fadt->x_pm1a_evt_blk.space_id = 1;
fadt->x_pm1a_evt_blk.bit_width = 32;
fadt->x_pm1a_evt_blk.bit_offset = 0;
fadt->x_pm1a_evt_blk.resv = 0;
fadt->x_pm1a_evt_blk.addrl = ACPI_PM_EVT_BLK;
fadt->x_pm1a_evt_blk.addrh = 0x0;
fadt->x_pm1b_evt_blk.space_id = 1;
fadt->x_pm1b_evt_blk.bit_width = 4;
fadt->x_pm1b_evt_blk.bit_offset = 0;
fadt->x_pm1b_evt_blk.resv = 0;
fadt->x_pm1b_evt_blk.addrl = 0x0;
fadt->x_pm1b_evt_blk.addrh = 0x0;
fadt->x_pm1a_cnt_blk.space_id = 1;
fadt->x_pm1a_cnt_blk.bit_width = 16;
fadt->x_pm1a_cnt_blk.bit_offset = 0;
fadt->x_pm1a_cnt_blk.resv = 0;
fadt->x_pm1a_cnt_blk.addrl = ACPI_PM1_CNT_BLK;
fadt->x_pm1a_cnt_blk.addrh = 0x0;
fadt->x_pm1b_cnt_blk.space_id = 1;
fadt->x_pm1b_cnt_blk.bit_width = 2;
fadt->x_pm1b_cnt_blk.bit_offset = 0;
fadt->x_pm1b_cnt_blk.resv = 0;
fadt->x_pm1b_cnt_blk.addrl = 0x0;
fadt->x_pm1b_cnt_blk.addrh = 0x0;
fadt->x_pm2_cnt_blk.space_id = 1;
fadt->x_pm2_cnt_blk.bit_width = 0;
fadt->x_pm2_cnt_blk.bit_offset = 0;
fadt->x_pm2_cnt_blk.resv = 0;
fadt->x_pm2_cnt_blk.addrl = ACPI_PMA_CNT_BLK;
fadt->x_pm2_cnt_blk.addrh = 0x0;
fadt->x_pm_tmr_blk.space_id = 1;
fadt->x_pm_tmr_blk.bit_width = 32;
fadt->x_pm_tmr_blk.bit_offset = 0;
fadt->x_pm_tmr_blk.resv = 0;
fadt->x_pm_tmr_blk.addrl = ACPI_PM_TMR_BLK;
fadt->x_pm_tmr_blk.addrh = 0x0;
fadt->x_gpe0_blk.space_id = 1;
fadt->x_gpe0_blk.bit_width = 32;
fadt->x_gpe0_blk.bit_offset = 0;
fadt->x_gpe0_blk.resv = 0;
fadt->x_gpe0_blk.addrl = ACPI_GPE0_BLK;
fadt->x_gpe0_blk.addrh = 0x0;
fadt->x_gpe1_blk.space_id = 1;
fadt->x_gpe1_blk.bit_width = 0;
fadt->x_gpe1_blk.bit_offset = 0;
fadt->x_gpe1_blk.resv = 0;
fadt->x_gpe1_blk.addrl = 0;
fadt->x_gpe1_blk.addrh = 0x0;
header->checksum = acpi_checksum((void *)fadt, sizeof(acpi_fadt_t));
}

View File

@ -35,14 +35,14 @@
u8 bus_isa;
u8 bus_rs690[8];
u8 bus_sb600[2];
unsigned long apicid_sb600;
u32 apicid_sb600;
/*
* Here you only need to set value in pci1234 for HT-IO that could be installed or not
* You may need to preset pci1234 for HTIO board,
* please refer to src/northbridge/amd/amdk8/get_sblk_pci1234.c for detail
*/
unsigned long pci1234x[] = {
u32 pci1234x[] = {
0x0000ff0,
};
@ -50,22 +50,22 @@ unsigned long pci1234x[] = {
* HT Chain device num, actually it is unit id base of every ht device in chain,
* assume every chain only have 4 ht device at most
*/
unsigned long hcdnx[] = {
u32 hcdnx[] = {
0x20202020,
};
unsigned long bus_type[256];
u32 bus_type[256];
unsigned long sbdn_rs690;
unsigned long sbdn_sb600;
u32 sbdn_rs690;
u32 sbdn_sb600;
extern void get_sblk_pci1234(void);
static unsigned long get_bus_conf_done = 0;
static u32 get_bus_conf_done = 0;
void get_bus_conf(void)
{
unsigned long apicid_base;
u32 apicid_base;
device_t dev;
int i, j;

View File

@ -19,12 +19,25 @@
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <arch/io.h>
#include <boot/coreboot_tables.h>
#include <cpu/x86/msr.h>
#include <cpu/amd/mtrr.h>
#include <device/pci_def.h>
#include "chip.h"
#define ADT7461_ADDRESS 0x4C
#define SMBUS_IO_BASE 0x1000
extern int do_smbus_read_byte(u32 smbus_io_base, u32 device, u32 address);
extern int do_smbus_write_byte(u32 smbus_io_base, u32 device, u32 address,
u8 val);
#define ADT7461_read_byte(address) \
do_smbus_read_byte(SMBUS_IO_BASE, ADT7461_ADDRESS, address)
#define ADT7461_write_byte(address, val) \
do_smbus_write_byte(SMBUS_IO_BASE, ADT7461_ADDRESS, address, val)
/********************************************************
* dbm690t uses a BCM5789 as on-board NIC.
* It has a pin named LOW_POWER to enable it into LOW POWER state.
@ -63,6 +76,109 @@ static void enable_onboard_nic()
outb(byte, 0xC52);
}
/********************************************************
* dbm690t uses SB600 GPIO9 to detect IDE_DMA66.
* IDE_DMA66 is routed to GPIO 9. So we read Gpio 9 to
* get the cable type, 40 pin or 80 pin?
********************************************************/
static void get_ide_dma66()
{
u8 byte;
/*u32 sm_dev, ide_dev; */
device_t sm_dev, ide_dev;
struct bus pbus;
sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0));
byte =
pci_cf8_conf1.read8(&pbus, sm_dev->bus->secondary,
sm_dev->path.u.pci.devfn, 0xA9);
byte |= (1 << 5); /* Set Gpio9 as input */
pci_cf8_conf1.write8(&pbus, sm_dev->bus->secondary,
sm_dev->path.u.pci.devfn, 0xA9, byte);
ide_dev = dev_find_slot(0, PCI_DEVFN(0x14, 1));
byte =
pci_cf8_conf1.read8(&pbus, ide_dev->bus->secondary,
ide_dev->path.u.pci.devfn, 0x56);
byte &= ~(7 << 0);
if ((1 << 5) & pci_cf8_conf1.
read8(&pbus, sm_dev->bus->secondary, sm_dev->path.u.pci.devfn,
0xAA))
byte |= 2 << 0; /* mode 2 */
else
byte |= 5 << 0; /* mode 5 */
pci_cf8_conf1.write8(&pbus, ide_dev->bus->secondary,
ide_dev->path.u.pci.devfn, 0x56, byte);
}
/*
* set thermal config
*/
static void set_thermal_config()
{
u8 byte;
u16 word;
device_t sm_dev;
struct bus pbus;
/* set ADT 7461 */
ADT7461_write_byte(0x0B, 0x50); /* Local Temperature Hight limit */
ADT7461_write_byte(0x0C, 0x00); /* Local Temperature Low limit */
ADT7461_write_byte(0x0D, 0x50); /* External Temperature Hight limit High Byte */
ADT7461_write_byte(0x0E, 0x00); /* External Temperature Low limit High Byte */
ADT7461_write_byte(0x19, 0x55); /* External THERM limit */
ADT7461_write_byte(0x20, 0x55); /* Local THERM limit */
byte = ADT7461_read_byte(0x02); /* read status register to clear it */
printk_info("Init adt7461 end , status 0x02 %02x\n", byte);
/* sb600 settings for thermal config */
/* set SB600 GPIO 64 to GPIO with pull-up */
byte = pm2_ioread(0x42);
byte &= 0x3f;
pm2_iowrite(0x42, byte);
/* set GPIO 64 to input */
sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0));
word =
pci_cf8_conf1.read16(&pbus, sm_dev->bus->secondary,
sm_dev->path.u.pci.devfn, 0x56);
word |= 1 << 7;
pci_cf8_conf1.write16(&pbus, sm_dev->bus->secondary,
sm_dev->path.u.pci.devfn, 0x56, word);
/* set GPIO 64 internal pull-up */
byte = pm2_ioread(0xf0);
byte &= 0xee;
pm2_iowrite(0xf0, byte);
/* set Talert to be active low */
byte = pm_ioread(0x67);
byte &= ~(1 << 5);
pm_iowrite(0x67, byte);
/* set Talert to generate ACPI event */
byte = pm_ioread(0x3c);
byte &= 0xf3;
pm_iowrite(0x3c, byte);
/* THERMTRIP pin */
/* byte = pm_ioread(0x68);
* byte |= 1 << 3;
* pm_iowrite(0x68, byte);
*
* byte = pm_ioread(0x55);
* byte |= 1 << 0;
* pm_iowrite(0x55, byte);
*
* byte = pm_ioread(0x67);
* byte &= ~( 1 << 6);
* pm_iowrite(0x67, byte);
*/
}
/*************************************************
* enable the dedicated function in dbm690t board.
* This function called early than rs690_enable.
@ -72,16 +188,22 @@ void dbm690t_enable(device_t dev)
struct mainboard_amd_dbm690t_config *mainboard =
(struct mainboard_amd_dbm690t_config *)dev->chip_info;
printk_info("Mainboard DBM690T Enable. dev=0x%x\n", dev);
#if (CONFIG_GFXUMA == 1)
msr_t msr, msr2;
/* TOP_MEM: the top of DRAM below 4G */
msr = rdmsr(TOP_MEM);
printk_info("dbm690t_enable, TOP MEM: msr.lo = 0x%08x, msr.hi = 0x%08x\n", msr.lo, msr.hi);
printk_info
("dbm690t_enable, TOP MEM: msr.lo = 0x%08x, msr.hi = 0x%08x\n",
msr.lo, msr.hi);
/* TOP_MEM2: the top of DRAM above 4G */
msr2 = rdmsr(TOP_MEM2);
printk_info("dbm690t_enable, TOP MEM2: msr2.lo = 0x%08x, msr2.hi = 0x%08x\n", msr2.lo, msr2.hi);
printk_info
("dbm690t_enable, TOP MEM2: msr2.lo = 0x%08x, msr2.hi = 0x%08x\n",
msr2.lo, msr2.hi);
switch (msr.lo) {
case 0x10000000: /* 256M system memory */
@ -101,8 +223,9 @@ void dbm690t_enable(device_t dev)
break;
}
uma_memory_start = msr.lo - uma_memory_size;/* TOP_MEM1 */
printk_info("dbm690t_enable: uma size 0x%08x, memory start 0x%08x\n", uma_memory_size, uma_memory_start);
uma_memory_start = msr.lo - uma_memory_size; /* TOP_MEM1 */
printk_info("dbm690t_enable: uma size 0x%08x, memory start 0x%08x\n",
uma_memory_size, uma_memory_start);
/* TODO: TOP_MEM2 */
#else
@ -110,9 +233,9 @@ void dbm690t_enable(device_t dev)
uma_memory_start = 0x38000000; /* 1GB system memory supposed */
#endif
printk_info("dbm690t_enable. dev=0x%x\n", dev);
enable_onboard_nic();
get_ide_dma66();
set_thermal_config();
}
/*

View File

@ -31,11 +31,11 @@ extern u8 bus_isa;
extern u8 bus_rs690[8];
extern u8 bus_sb600[2];
extern unsigned long apicid_sb600;
extern u32 apicid_sb600;
extern unsigned long bus_type[256];
extern unsigned long sbdn_rs690;
extern unsigned long sbdn_sb600;
extern u32 bus_type[256];
extern u32 sbdn_rs690;
extern u32 sbdn_sb600;
extern void get_bus_conf(void);
@ -143,8 +143,12 @@ void *smp_write_config_table(void *v)
/* PCI interrupts are level triggered, and are
* associated with a specific bus/device/function tuple.
*/
#if HAVE_ACPI_TABLES == 0
#define PCI_INT(bus, dev, fn, pin) \
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, (bus), (((dev)<<2)|(fn)), apicid_sb600, (pin))
#else
#define PCI_INT(bus, dev, fn, pin)
#endif
/* usb */
PCI_INT(0x0, 0x13, 0x0, 0x10);