Idwer Vollering wrote:
Updated against r6119, yet unfinished.
Here is my extended version, wip.
Index: src/southbridge/intel/i82371eb/i82371eb_fadt.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ src/southbridge/intel/i82371eb/i82371eb_fadt.c 2010-11-25 03:20:01.000000000 +0100 @@ -0,0 +1,167 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2004 Nick Barker nick.barker9@btinternet.com + * Copyright (C) 2007, 2009 Rudolf Marek r.marek@assembler.cz + * Copyright (C) 2010 Idwer Vollering vidwer@gmail.com + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + */ + +/* Based on src/southbridge/via/vt8237r/vt8237_fadt.c */ + +#include <string.h> +#include <arch/acpi.h> +#include <device/device.h> +#include <device/pci.h> +/* PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_SMB_ACPI */ +#include <device/pci_ids.h> +#include "i82371eb.h" /* PM_IO_BASE, PMCNTRL */ + +/** + * Create the Fixed ACPI Description Tables (FADT) for any board with this SB. + */ +void acpi_create_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt) +{ + acpi_header_t *header = &(fadt->header); + device_t dev; + + /* Power management controller */ + dev = dev_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB_SMB_ACPI, 0); /* pci_ids.h */ + + memset((void *) fadt, 0, sizeof(acpi_fadt_t)); + memcpy(header->signature, "FACP", 4); + header->length = 244; + header->revision = 1; + memcpy(header->oem_id, "CORE ", 6); + memcpy(header->oem_table_id, "COREBOOT", 8); + memcpy(header->asl_compiler_id, "CORE", 4); + header->asl_compiler_revision = 42; + + fadt->firmware_ctrl = (u32)facs; + fadt->dsdt = (u32)dsdt; + fadt->preferred_pm_profile = 0; + fadt->sci_int = 9; + fadt->smi_cmd = APM_CNT; + fadt->acpi_enable = ACPI_ENABLE; + fadt->acpi_disable = ACPI_DISABLE; + fadt->s4bios_req = 0x0; + fadt->pstate_cnt = 0x0; + + fadt->pm1a_evt_blk = PM_IO_BASE; /* PM_IO_BASE = 0xe400 */ + fadt->pm1b_evt_blk = 0x0; + fadt->pm1a_cnt_blk = PM_IO_BASE + PMCNTRL; /* PMCNTRL = 0x4 */ + fadt->pm1b_cnt_blk = 0x0; + + fadt->pm2_cnt_blk = 0x22; /* NB is hardwired to io 0x22 */ + fadt->pm_tmr_blk = PM_IO_BASE + PMTMR; /* PMTMR = 0x8 */ + fadt->gpe0_blk = PM_IO_BASE + GPSTS; /* GPSTS = 0xc */ + fadt->gpe1_blk = 0x0; + fadt->gpe1_base = 0; + fadt->gpe1_blk_len = 0; + + fadt->pm1_evt_len = 4; + fadt->pm1_cnt_len = 2; + fadt->pm2_cnt_len = 1; + fadt->pm_tmr_len = 4; + fadt->gpe0_blk_len = 4; + + fadt->cst_cnt = 0; + fadt->p_lvl2_lat = 101; /* >100 means not supported */ + fadt->p_lvl3_lat = 1001; /* >1000 means not supported */ + fadt->flush_size = 0; + fadt->flush_stride = 0; + fadt->duty_offset = 1; /* bit 1:3 in PCNTRL reg (pmbase+0x10) */ + fadt->duty_width = 3; /* 0 means not supported */ + fadt->day_alrm = 0x0d; + fadt->mon_alrm = 0x0; + fadt->century = 0x0; + /* We have legacy devices, 8042, VGA is ok to probe, MSI are not supported */ + fadt->iapc_boot_arch = 0xb; + /* check me */ + fadt->flags = 0xa5; + + fadt->reset_reg.space_id = 0; + fadt->reset_reg.bit_width = 0; + fadt->reset_reg.bit_offset = 0; + fadt->reset_reg.resv = 0; + fadt->reset_reg.addrl = 0x0; + fadt->reset_reg.addrh = 0x0; + + fadt->reset_value = 0; + 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 = fadt->pm1_evt_len * 8; + fadt->x_pm1a_evt_blk.bit_offset = 0; + fadt->x_pm1a_evt_blk.resv = 0; + fadt->x_pm1a_evt_blk.addrl = fadt->pm1a_evt_blk; + fadt->x_pm1a_evt_blk.addrh = 0x0; + + fadt->x_pm1b_evt_blk.space_id = 1; + fadt->x_pm1b_evt_blk.bit_width = fadt->pm1_evt_len * 8; + fadt->x_pm1b_evt_blk.bit_offset = 0; + fadt->x_pm1b_evt_blk.resv = 0; + fadt->x_pm1b_evt_blk.addrl = fadt->pm1b_evt_blk; + fadt->x_pm1b_evt_blk.addrh = 0x0; + + fadt->x_pm1a_cnt_blk.space_id = 1; + fadt->x_pm1a_cnt_blk.bit_width = fadt->pm1_cnt_len * 8; + fadt->x_pm1a_cnt_blk.bit_offset = 0; + fadt->x_pm1a_cnt_blk.resv = 0; + fadt->x_pm1a_cnt_blk.addrl = fadt->pm1a_cnt_blk; + fadt->x_pm1a_cnt_blk.addrh = 0x0; + + fadt->x_pm1b_cnt_blk.space_id = 1; + fadt->x_pm1b_cnt_blk.bit_width = fadt->pm1_cnt_len * 8; + fadt->x_pm1b_cnt_blk.bit_offset = 0; + fadt->x_pm1b_cnt_blk.resv = 0; + fadt->x_pm1b_cnt_blk.addrl = fadt->pm1b_cnt_blk; + fadt->x_pm1b_cnt_blk.addrh = 0x0; + + fadt->x_pm2_cnt_blk.space_id = 1; + fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8; + fadt->x_pm2_cnt_blk.bit_offset = 0; + fadt->x_pm2_cnt_blk.resv = 0; + fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk; + fadt->x_pm2_cnt_blk.addrh = 0x0; + + fadt->x_pm_tmr_blk.space_id = 1; + fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8; + fadt->x_pm_tmr_blk.bit_offset = 0; + fadt->x_pm_tmr_blk.resv = 0; + fadt->x_pm_tmr_blk.addrl = fadt->pm_tmr_blk; + fadt->x_pm_tmr_blk.addrh = 0x0; + + fadt->x_gpe0_blk.space_id = 1; + fadt->x_gpe0_blk.bit_width = fadt->gpe0_blk_len * 8; + fadt->x_gpe0_blk.bit_offset = 0; + fadt->x_gpe0_blk.resv = 0; + fadt->x_gpe0_blk.addrl = fadt->gpe0_blk; + fadt->x_gpe0_blk.addrh = 0x0; + + fadt->x_gpe1_blk.space_id = 1; + fadt->x_gpe1_blk.bit_width = fadt->gpe1_blk_len * 8;; + fadt->x_gpe1_blk.bit_offset = 0; + fadt->x_gpe1_blk.resv = 0; + fadt->x_gpe1_blk.addrl = fadt->gpe1_blk; + fadt->x_gpe1_blk.addrh = 0x0; + + header->checksum = acpi_checksum((void *) fadt, sizeof(acpi_fadt_t)); +} Index: src/southbridge/intel/i82371eb/Makefile.inc =================================================================== --- src/southbridge/intel/i82371eb/Makefile.inc.orig 2010-11-25 03:18:26.000000000 +0100 +++ src/southbridge/intel/i82371eb/Makefile.inc 2010-11-25 03:20:01.000000000 +0100 @@ -2,6 +2,7 @@ ## This file is part of the coreboot project. ## ## Copyright (C) 2007 Uwe Hermann uwe@hermann-uwe.de +## Copyright (C) 2010 Idwer Vollering vidwer@gmail.com ## ## 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 @@ -24,7 +25,10 @@ driver-y += i82371eb_usb.c driver-y += i82371eb_smbus.c driver-y += i82371eb_reset.c +driver-$(CONFIG_HAVE_ACPI_TABLES) += i82371eb_fadt.c
romstage-y += i82371eb_early_pm.c romstage-y += i82371eb_early_smbus.c
+ramstage-$(CONFIG_HAVE_SMI_HANDLER) += i82371eb_smi.c +smm-$(CONFIG_HAVE_SMI_HANDLER) += i82371eb_smihandler.c Index: src/southbridge/intel/i82371eb/i82371eb.h =================================================================== --- src/southbridge/intel/i82371eb/i82371eb.h.orig 2010-11-25 03:18:26.000000000 +0100 +++ src/southbridge/intel/i82371eb/i82371eb.h 2010-11-25 03:38:02.000000000 +0100 @@ -2,6 +2,9 @@ * This file is part of the coreboot project. * * Copyright (C) 2007 Uwe Hermann uwe@hermann-uwe.de + * Copyright (C) 2010 Keith Hui buurin@gmail.com + * Copyright (C) 2010 Idwer Vollering vidwer@gmail.com + * Copyright (C) 2010 Tobias Diedrich ranma+coreboot@tdiedrich.de * * 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 @@ -23,8 +26,8 @@
#if !defined(ASSEMBLY) #if !defined(__PRE_RAM__) +#if !defined(ARCH_ROMCC_IO_H)
-#include <arch/io.h> #include <device/device.h> #include "chip.h"
@@ -33,6 +36,7 @@
#endif #endif +#endif
/* If 'cond' is true this macro sets the bit(s) specified by 'bits' in the * 'reg' variable, otherwise it clears those bits. @@ -59,10 +63,55 @@ #define SMBHSTCFG 0xd2 /* SMBus host configuration */
/* Power management (ACPI) */ +#define PMSTS 0x00 /* Power Management Status */ +#define PMEN 0x02 /* Power Management Resume Enable */ +#define PWRBTN_EN (1<<8) +#define GBL_EN (1<<5) +#define PMCNTRL 0x04 /* Power Management Control */ +#define SCI_EN (1<<0) +#define PMTMR 0x08 /* Power Management Timer */ +#define GPSTS 0x0c /* General Purpose Status */ +#define GPEN 0x0e /* General Purpose Enable */ +#define THRM_EN (1<<0) +#define GLBSTS 0x18 /* Global Status */ +#define IRQ_RSM_STS (1<<11) +#define EXTSMI_STS (1<<10) +#define GSTBY_STS (1<<8) +#define GP_STS (1<<7) +#define BM1_STS (1<<6) +#define APM_STS (1<<5) +#define DEV_STS (1<<4) +#define BIOS_EN (1<<1) /* GBL_RLS write triggers SMI */ +#define LEGACY_USB_EN (1<<0) /* Keyboard controller access triggers SMI */ +#define DEVSTS 0x1c /* Device Status */ +#define GLBEN 0x20 /* Global Enable */ +#define EXTSMI_EN (1<<10) /* EXTSMI# signal triggers SMI */ +#define GSTBY_EN (1<<8) +#define BM_TRP_EN (1<<1) +#define BIOS_EN (1<<1) /* GBL_RLS write triggers SMI */ +#define LEGACY_USB_EN (1<<0) /* Keyboard controller access triggers SMI */ +#define GLBCTL 0x28 /* Global Control */ +#define EOS (1<<16) /* End of SMI */ +#define SMI_EN (1<<0) /* SMI enable */ +#define DEVCTL 0x2c /* Device Control */ +#define TRP_EN_DEV12 (1<<24) /* SMI on dev12 trap */ + #define PMBA 0x40 /* Power management base address */ +#define PM_IO_BASE 0xe400 +#define DEFAULT_PMBASE PM_IO_BASE +#define DEVACTB 0x58 +#define APMC_EN (1<<25) +#define DEVRESE 0x68 #define PMREGMISC 0x80 /* Miscellaneous power management */
-#define PM_IO_BASE 0xe400 +#define APM_CNT 0xb2 /* APM control io */ +#define CST_CONTROL 0x85 +#define PST_CONTROL 0x80 +#define ACPI_DISABLE 0x1e +#define ACPI_ENABLE 0xe1 +#define GNVS_UPDATE 0xea +#define MBI_UPDATE 0xeb +#define APM_STS 0xb3 /* APM data io */
/* Bit definitions */ #define EXT_BIOS_ENABLE_1MB (1 << 9) /* 1-Meg Extended BIOS Enable */ Index: src/southbridge/intel/i82371eb/i82371eb_smbus.c =================================================================== --- src/southbridge/intel/i82371eb/i82371eb_smbus.c.orig 2010-11-25 03:18:26.000000000 +0100 +++ src/southbridge/intel/i82371eb/i82371eb_smbus.c 2010-11-25 03:20:01.000000000 +0100 @@ -2,6 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2007 Uwe Hermann uwe@hermann-uwe.de + * Copyright (C) 2010 Keith Hui buurin@gmail.com * * 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 @@ -18,6 +19,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <arch/io.h> +#include <console/console.h> #include <stdint.h> #include <device/device.h> #include <device/pci.h> @@ -26,7 +29,90 @@ #include "i82371eb.h" #include "i82371eb_smbus.h"
-/* TODO: Needed later? */ +#define AS97127F_BASE 0x290 + +#define AS97127F_ADDR 5 +#define AS97127F_DATA 6 + +static void as97127f_write(u8 addr, u8 data) +{ + outb(addr, AS97127F_BASE+AS97127F_ADDR); + outb(data, AS97127F_BASE+AS97127F_DATA); +} + +static void pwrmgt_init(struct device *dev) +{ + u32 reg; + + /* Sets the base address of power management ports. */ + pci_write_config16(dev, PMBA, PM_IO_BASE | 1); + + /* Set Power Management IO Space Enable bit */ + u8 val = pci_read_config8(dev, PMREGMISC); + pci_write_config8(dev, PMREGMISC, val | 1); + + pci_write_config8(dev, 0x04, 0x03); + /* cnta */ + pci_write_config32(dev, 0x44, 0x20000000); + /* cntb */ + pci_write_config32(dev, 0x48, 0x0100301e); + + /* Set up pcs0# chipselect io decode on + * port 0x0290 */ + pci_write_config32(dev, 0x60, 0x00e70000|AS97127F_BASE); + + /* enable all alarm smi sources */ + as97127f_write(0x43, 0xff); + as97127f_write(0x44, 0x7f); + /* set fan divisor, gpio? */ + as97127f_write(0x47, 0xa0); + /* select 14.318MHz clock. */ + as97127f_write(0x4b, 0x40); + /* set bit 7 */ + as97127f_write(0x4d, 0x95); + + /* set global control: + * bit25 (lid_pol): 1=invert lid polarity + * bit24 (sm_freeze): 1=freeze idle and standby timers + * bit16 (end of smi): 0=disable smi assertion (cleared by hw) + * bits8-15,26: global standby timer inital count 127 * 4minutes + * bit2 (thrm_pol): 1=active low THRM# + * bit0 (smi_en): 1=disable smi generation upon smi event + */ + reg = inl(PM_IO_BASE + 0x28); + reg &= SMI_EN|EOS; /* keep smi state */ + reg |= (1<<25)|(1<<24)|(0xff<<8)|(1<<2); + outl(reg, PM_IO_BASE + 0x28); + + /* set processor control: + * bit12 (stpclk_en): 1=enable stopping of host clk on lvl3 + * bit11 (sleep_en): 1=enable slp# assertion on lvl3 + * bit9 (cc_en): 1=enable clk control with lvl2 and lvl3 regs + */ + outl(0, PM_IO_BASE + 0x10); + + /* Clear status events. */ + outw(0xffff, PM_IO_BASE + PMSTS); + outw(0xffff, PM_IO_BASE + GPSTS); + outw(0xffff, PM_IO_BASE + GLBSTS); + outl(0xffffffff, PM_IO_BASE + DEVSTS); + + int i; + for (i = 0; i < 64; i++) { + if ((i == 0x14) || (i == 0x15)) /* skip plvl2/plvl3 regs */ + continue; + printk(BIOS_SPEW, "pwrmgt_init: pm_io %02x is %02x\n", i, inb(PM_IO_BASE + i)); + } + +#if 0 +#if !defined(CONFIG_HAVE_SMI_HANDLER) + /* Set SCI_EN bit */ + u16 tmp = inw(PM_IO_BASE + 0x04); + outw(tmp|1, PM_IO_BASE + 0x04); +#endif +#endif +} + static const struct smbus_bus_operations lops_smbus_bus = { };
@@ -34,7 +120,7 @@ .read_resources = pci_dev_read_resources, .set_resources = pci_dev_set_resources, .enable_resources = pci_dev_enable_resources, - .init = 0, + .init = pwrmgt_init, .scan_bus = scan_static_bus, .enable = 0, .ops_pci = 0, /* No subsystem IDs on 82371EB! */ Index: src/mainboard/asus/p2b/Kconfig =================================================================== --- src/mainboard/asus/p2b/Kconfig.orig 2010-11-25 03:18:25.000000000 +0100 +++ src/mainboard/asus/p2b/Kconfig 2010-11-25 03:20:01.000000000 +0100 @@ -2,6 +2,7 @@ ## This file is part of the coreboot project. ## ## Copyright (C) 2009 Uwe Hermann uwe@hermann-uwe.de +## Copyright (C) 2010 Idwer Vollering vidwer@gmail.com ## ## 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 @@ -28,6 +29,8 @@ select HAVE_PIRQ_TABLE select UDELAY_TSC select BOARD_ROMSIZE_KB_256 + select HAVE_ACPI_TABLES + select HAVE_SMI_HANDLER
config MAINBOARD_DIR string Index: src/mainboard/asus/p2b/devicetree.cb =================================================================== --- src/mainboard/asus/p2b/devicetree.cb.orig 2010-11-25 03:18:26.000000000 +0100 +++ src/mainboard/asus/p2b/devicetree.cb 2010-11-25 03:20:01.000000000 +0100 @@ -39,7 +39,7 @@ end device pnp 3f0.9 on # GPIO 3 end - device pnp 3f0.a on # ACPI + device pnp 3f0.a off # ACPI end end end @@ -50,10 +50,10 @@ register "ide1_enable" = "1" register "ide_legacy_enable" = "1" # Enable UDMA/33 for higher speed if your IDE device(s) support it. - register "ide0_drive0_udma33_enable" = "0" - register "ide0_drive1_udma33_enable" = "0" - register "ide1_drive0_udma33_enable" = "0" - register "ide1_drive1_udma33_enable" = "0" + register "ide0_drive0_udma33_enable" = "1" + register "ide0_drive1_udma33_enable" = "1" + register "ide1_drive0_udma33_enable" = "1" + register "ide1_drive1_udma33_enable" = "1" end end end Index: src/mainboard/asus/p2b/acpi_tables.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ src/mainboard/asus/p2b/acpi_tables.c 2010-11-25 03:20:01.000000000 +0100 @@ -0,0 +1,118 @@ +/* + * This file is part of the coreboot project. + * + * Written by Stefan Reinauer stepan@openbios.org. + * ACPI FADT, FACS, and DSDT table support added by + * + * Copyright (C) 2004 Stefan Reinauer stepan@openbios.org + * Copyright (C) 2005 Nick Barker nick.barker9@btinternet.com + * Copyright (C) 2007 Rudolf Marek r.marek@assembler.cz + * Copyright (C) 2010 Idwer Vollering vidwer@gmail.com + * + * 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 + */ + +/* Based on src/mainboard/asus/a8v-e_se/acpi_tables.c */ + +#include <console/console.h> +#include <string.h> +#include <arch/acpi.h> +#include <arch/smp/mpspec.h> +#include <device/device.h> +#include <device/pci_ids.h> + +extern const unsigned char AmlCode[]; + +unsigned long acpi_fill_slit(unsigned long current) +{ + // Not implemented + return current; +} + +unsigned long acpi_fill_srat(unsigned long current) +{ + // Not implemented + return current; +} + +unsigned long acpi_fill_mcfg(unsigned long current) +{ + /* chipset doesn't have mmconfig */ + return current; +} + +unsigned long acpi_fill_madt(unsigned long current) +{ + /* mainboard has no ioapic */ + return current; +} + +unsigned long write_acpi_tables(unsigned long start) +{ + unsigned long current; + acpi_rsdp_t *rsdp; + acpi_rsdt_t *rsdt; + acpi_fadt_t *fadt; + acpi_facs_t *facs; + acpi_header_t *dsdt; + + /* Align ACPI tables to 16 byte. */ + start = (start + 0x0f) & -0x10; + current = start; + + printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx...\n", start); + + /* We need at least an RSDP and an RSDT table. */ + rsdp = (acpi_rsdp_t *) current; + current += sizeof(acpi_rsdp_t); + rsdt = (acpi_rsdt_t *) current; + current += sizeof(acpi_rsdt_t); + + /* Clear all table memory. */ + memset((void *) start, 0, current - start); + + acpi_write_rsdp(rsdp, rsdt, NULL); + acpi_write_rsdt(rsdt); + + /* We explicitly add these tables later on: */ + printk(BIOS_DEBUG, "ACPI: * FACS\n"); + + /* we should align FACS to 64B as per ACPI specs */ + current = ALIGN(current, 64); + facs = (acpi_facs_t *) current; + current += sizeof(acpi_facs_t); + acpi_create_facs(facs); + + dsdt = (acpi_header_t *)current; + memcpy(dsdt, &AmlCode, sizeof(acpi_header_t)); + current += dsdt->length; + memcpy(dsdt, &AmlCode, dsdt->length); + /* Don't trust iasl to get checksum right. */ + dsdt->checksum = 0; /* needs to be set to 0 first (part of csum) */ + dsdt->checksum = acpi_checksum((u8*)dsdt, dsdt->length); + printk(BIOS_DEBUG, "ACPI: * DSDT @ %p Length %x\n", dsdt, + dsdt->length); + printk(BIOS_DEBUG, "ACPI: * FADT\n"); + + fadt = (acpi_fadt_t *) current; + current += sizeof(acpi_fadt_t); + + acpi_create_fadt(fadt, facs, dsdt); + acpi_add_table(rsdp, fadt); + + /* no ioapic, so no madt */ + + printk(BIOS_INFO, "ACPI: done.\n"); + return current; +} Index: src/mainboard/asus/p2b/dsdt.asl =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ src/mainboard/asus/p2b/dsdt.asl 2010-11-25 03:20:01.000000000 +0100 @@ -0,0 +1,298 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2004 Nick Barker Nick.Barker9@btinternet.com + * Copyright (C) 2007 Rudolf Marek r.marek@assembler.cz + * Copyright (C) 2010 Idwer Vollering vidwer@gmail.com + * + * 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 + */ + +/* Based on dsdt.asl from src/mainboard/asus/a8v-e_se */ + +/* + * ISA portions taken from QEMU acpi-dsdt.dsl. + */ + +DefinitionBlock ("DSDT.aml", "DSDT", 1, "CORE ", "COREBOOT", 1) +{ + /* Define the main processor.*/ + Scope (_PR) + { + /* Looks like the P_CNT field can't be a method or name + * and has to be hardcoded to 0xe410 or generated in SSDT */ + Processor (CPU0, 0x01, 0xe410, 0x06) {} + } + + /* For now only define 2 power states: + * - S0 which is fully on + * - S5 which is soft off + * Any others would involve declaring the wake up methods. + */ + + /* intel i82371eb (piix4e) datasheet, section 7.2.3, page 142 */ + /* + 000b / 0x0: soft off/suspend to disk (soff/std) s5 + 001b / 0x1: suspend to ram (str) s3 + 010b / 0x2: powered on suspend, context lost (poscl) s1 + 011b / 0x3: powered on suspend, cpu context lost (posccl) s2 + 100b / 0x4: powered on suspend, context maintained (pos) s4 + 101b / 0x5: working (clock control) s0 + 110b / 0x6: reserved + 111b / 0x7: reserved + */ + Name (_S0, Package () { 0x05, 0x05, 0x00, 0x00 }) + Name (_S5, Package () { 0x00, 0x00, 0x00, 0x00 }) + + /* Root of the bus hierarchy */ + Scope (_SB) + { + /* Top PCI device */ + Device (PCI0) + { + Name (_HID, EisaId ("PNP0A03")) + Name (_ADR, 0x00) + Name (_UID, 0x00) + Name (_BBN, 0x00) + + /* PCI Routing Table */ + Name (_PRT, Package () { + Package (0x04) { 0x0001FFFF, 0, LNKA, 0 }, + Package (0x04) { 0x0001FFFF, 1, LNKB, 0 }, + Package (0x04) { 0x0001FFFF, 2, LNKC, 0 }, + Package (0x04) { 0x0001FFFF, 3, LNKD, 0 }, + + Package (0x04) { 0x0004FFFF, 0, LNKA, 0 }, + Package (0x04) { 0x0004FFFF, 1, LNKB, 0 }, + Package (0x04) { 0x0004FFFF, 2, LNKC, 0 }, + Package (0x04) { 0x0004FFFF, 3, LNKD, 0 }, + + Package (0x04) { 0x0009FFFF, 0, LNKD, 0 }, + Package (0x04) { 0x0009FFFF, 1, LNKA, 0 }, + Package (0x04) { 0x0009FFFF, 2, LNKB, 0 }, + Package (0x04) { 0x0009FFFF, 3, LNKC, 0 }, + + Package (0x04) { 0x000AFFFF, 0, LNKC, 0 }, + Package (0x04) { 0x000AFFFF, 1, LNKD, 0 }, + Package (0x04) { 0x000AFFFF, 2, LNKA, 0 }, + Package (0x04) { 0x000AFFFF, 3, LNKB, 0 }, + + Package (0x04) { 0x000BFFFF, 0, LNKB, 0 }, + Package (0x04) { 0x000BFFFF, 1, LNKC, 0 }, + Package (0x04) { 0x000BFFFF, 2, LNKD, 0 }, + Package (0x04) { 0x000BFFFF, 3, LNKA, 0 }, + + Package (0x04) { 0x000CFFFF, 0, LNKA, 0 }, + Package (0x04) { 0x000CFFFF, 1, LNKB, 0 }, + Package (0x04) { 0x000CFFFF, 2, LNKC, 0 }, + Package (0x04) { 0x000CFFFF, 3, LNKD, 0 }, + + }) + + /* Northbridge */ + Device (NB) + { + Name(_ADR, 0x00000000) + OperationRegion(PCIC, PCI_Config, 0x00, 0x100) + } + + // Intel LPC Bus Device - 0:4.0 + Device (LPCB) + { + Name(_ADR, 0x00040000) + + OperationRegion(PCIC, PCI_Config, 0x00, 0x100) + + /* PS/2 keyboard (seems to be important for WinXP install) */ + Device (KBD) + { + Name (_HID, EisaId ("PNP0303")) + Method (_STA, 0, NotSerialized) + { + Return (0x0f) + } + Method (_CRS, 0, NotSerialized) + { + Name (TMP, ResourceTemplate () { + IO (Decode16, 0x0060, 0x0060, 0x01, 0x01) + IO (Decode16, 0x0064, 0x0064, 0x01, 0x01) + IRQNoFlags () {1} + }) + Return (TMP) + } + } + + /* PS/2 mouse */ + Device (MOU) + { + Name (_HID, EisaId ("PNP0F13")) + Method (_STA, 0, NotSerialized) + { + Return (0x0f) + } + Method (_CRS, 0, NotSerialized) + { + Name (TMP, ResourceTemplate () { + IRQNoFlags () {12} + }) + Return (TMP) + } + } + + /* PS/2 floppy controller */ + Device (FDC0) + { + Name (_HID, EisaId ("PNP0700")) + Method (_STA, 0, NotSerialized) + { + Return (0x0f) + } + Method (_CRS, 0, NotSerialized) + { + Name (BUF0, ResourceTemplate () { + IO (Decode16, 0x03F2, 0x03F2, 0x00, 0x04) + IO (Decode16, 0x03F7, 0x03F7, 0x00, 0x01) + IRQNoFlags () {6} + DMA (Compatibility, NotBusMaster, Transfer8) {2} + }) + Return (BUF0) + } + } + } + + Field (NB.PCIC, AnyAcc, NoLock, Preserve) + { + Offset (0x67), // DRB7 + DRB7, 8, + } + + Method(TOM1, 0) { + /* Multiply by 8MB to get TOM */ + Return(ShiftLeft(DRB7, 23)) + } + + Method(_CRS, 0) { + Name(TMP, ResourceTemplate() { + WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode, + 0x0000, // Granularity + 0x0000, // Range Minimum + 0x00FF, // Range Maximum + 0x0000, // Translation Offset + 0x0100, // Length + ,, + ) + IO(Decode16, 0x0CF8, 0x0CF8, 1, 8) + + WORDIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, /* address granularity */ + 0x0000, /* range minimum */ + 0x0CF7, /* range maximum */ + 0x0000, /* translation */ + 0x0CF8 /* length */ + ) + + WORDIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, /* address granularity */ + 0x0D00, /* range minimum */ + 0xFFFF, /* range maximum */ + 0x0000, /* translation */ + 0xF300 /* length */ + ) + + /* memory space for PCI BARs below 4GB */ + Memory32Fixed(ReadOnly, 0x00000000, 0x00000000, MMIO) + }) + CreateDWordField(TMP, MMIO._BAS, MM1B) + CreateDWordField(TMP, MMIO._LEN, MM1L) + /* + * Declare memory between TOM1 and 4GB as available + * for PCI MMIO. + * + * Use ShiftLeft to avoid 64bit constant (for XP). + * This will work even if the OS does 32bit arithmetic, as + * 32bit (0x00000000 - TOM1) will wrap and give the same + * result as 64bit (0x100000000 - TOM1). + */ + Store(TOM1, MM1B) + ShiftLeft(0x10000000, 4, Local0) + Subtract(Local0, TOM1, Local0) + Store(Local0, MM1L) + + Return(TMP) + } + } + + Field (PCI0.LPCB.PCIC, AnyAcc, NoLock, Preserve) + { + Offset (0x60), // Interrupt Routing Registers + PRTA, 8, + PRTB, 8, + PRTC, 8, + PRTD, 8, + } + + Name(IRQB, ResourceTemplate(){ + IRQ(Level,ActiveLow,Shared){15} + }) + + Name(IRQP, ResourceTemplate(){ + IRQ(Level,ActiveLow,Exclusive){3, 4, 5, 6, 7, 10, 11, 12} + }) + + /* adapted from ma78gm/dsdt.asl */ +#define PCI_INTX_DEV(intx, pinx, uid) \ + Device(intx) { \ + Name(_HID, EISAID("PNP0C0F")) \ + Name(_UID, uid) \ + \ + Method(_STA, 0) { \ + If (And(pinx, 0x80)) { \ + Return(0x09) \ + } \ + Return(0x0B) \ + } \ + \ + Method(_DIS ,0) { \ + Store(0x80, pinx) \ + } \ + \ + Method(_PRS ,0) { \ + Return(IRQP) \ + } \ + \ + Method(_CRS ,0) { \ + CreateWordField(IRQB, 1, IRQN) \ + ShiftLeft(1, And(pinx, 0x0f), IRQN) \ + Return(IRQB) \ + } \ + \ + Method(_SRS, 1) { \ + CreateWordField(ARG0, 1, IRQM) \ + \ + /* Use lowest available IRQ */ \ + FindSetRightBit(IRQM, Local0) \ + if (Local0) { \ + Decrement(Local0) \ + } \ + Store(Local0, pinx) \ + } \ + } \ + +PCI_INTX_DEV(LNKA, PRTA, 1) +PCI_INTX_DEV(LNKB, PRTB, 2) +PCI_INTX_DEV(LNKC, PRTC, 3) +PCI_INTX_DEV(LNKD, PRTD, 4) + } + +} Index: src/northbridge/intel/i440bx/northbridge.c =================================================================== --- src/northbridge/intel/i440bx/northbridge.c.orig 2010-11-25 03:18:26.000000000 +0100 +++ src/northbridge/intel/i440bx/northbridge.c 2010-11-25 03:20:01.000000000 +0100 @@ -1,3 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007 Uwe Hermann uwe@hermann-uwe.de + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + */ + #include <console/console.h> #include <arch/io.h> #include <stdint.h> @@ -15,7 +35,12 @@
static void northbridge_init(device_t dev) { + u8 reg8; printk(BIOS_SPEW, "Northbridge Init\n"); + /* set bit 6 of the Power Management Control Register + * to enable PM2 register at io 0x22 */ + reg8 = pci_read_config16(dev, 0x7a); + pci_write_config8(dev, 0x7a, reg8 | 0x40); }
static struct device_operations northbridge_operations = { Index: src/southbridge/intel/i82371eb/i82371eb_isa.c =================================================================== --- src/southbridge/intel/i82371eb/i82371eb_isa.c.orig 2010-11-25 03:18:26.000000000 +0100 +++ src/southbridge/intel/i82371eb/i82371eb_isa.c 2010-11-25 03:20:01.000000000 +0100 @@ -72,7 +72,9 @@ */ reg32 = pci_read_config32(dev, GENCFG); reg32 |= ISA; /* Select ISA, not EIO. */ - pci_write_config16(dev, GENCFG, reg32); + reg32 |= (1<<15); /* GPI11 instead of SMBALERT# */ + reg32 |= (1<<19); /* GPO18 instead of PCI_STP# */ + pci_write_config32(dev, GENCFG, reg32);
/* Initialize ISA DMA. */ isa_dma_init(); Index: src/cpu/x86/smm/smmrelocate.S =================================================================== --- src/cpu/x86/smm/smmrelocate.S.orig 2010-11-25 03:18:25.000000000 +0100 +++ src/cpu/x86/smm/smmrelocate.S 2010-11-25 03:26:20.000000000 +0100 @@ -30,6 +30,8 @@ #include "../../../southbridge/intel/i82801gx/i82801gx.h" #elif defined(CONFIG_SOUTHBRIDGE_INTEL_I82801DX) #include "../../../southbridge/intel/i82801dx/i82801dx.h" +#elif defined(CONFIG_SOUTHBRIDGE_INTEL_I82371EB) +#include "../../../southbridge/intel/i82371eb/i82371eb.h" #else #error "Southbridge needs SMM handler support." #endif @@ -93,6 +95,7 @@
smm_relocation_start: /* Check revision to see if AMD64 style SMM_BASE + * Intel PIII Tualatin?: 0x30002 * Intel Core Solo/Duo: 0x30007 * Intel Core2 Solo/Duo: 0x30100 * AMD64: 0x3XX64 @@ -116,6 +119,12 @@ addr32 movl (%esi), %ecx shr $24, %ecx
+ /* Uninitalized LAPIC? */ + cmp $0xff, %cl + jne 1f + mov $0, %cl /* assume cpu 0 */ +1: + /* calculate offset by multiplying the * apic ID by 1024 (0x400) */ @@ -130,6 +139,7 @@
/* The next section of code is potentially southbridge specific */
+#if 0 /* Clear SMI status */ movw $(DEFAULT_PMBASE + 0x34), %dx inw %dx, %ax @@ -145,6 +155,23 @@ inl %dx, %eax orl $(1 << 1), %eax outl %eax, %dx +#else + /* Clear SMI status */ + movw $(DEFAULT_PMBASE + 0x18), %dx + inw %dx, %ax + outw %ax, %dx + + /* Clear PM1 status */ + movw $(DEFAULT_PMBASE + 0x00), %dx + inw %dx, %ax + outw %ax, %dx + + /* Set EOS bit so other SMIs can occur */ + movw $(DEFAULT_PMBASE + 0x28), %dx + inl %dx, %eax + orl $(1 << 16), %eax + outl %eax, %dx +#endif
/* End of southbridge specific section. */
Index: src/southbridge/intel/i82371eb/i82371eb_smi.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ src/southbridge/intel/i82371eb/i82371eb_smi.c 2010-11-25 03:20:01.000000000 +0100 @@ -0,0 +1,206 @@ +/* + * This file is part of the coreboot project. + * + * Based on src/southbridge/intel/i82801dx/i82801dx_smi.c + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2010 Idwer Vollering vidwer@gmail.com + * Copyright (C) 2010 Tobias Diedrich ranma+coreboot@tdiedrich.de + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + */ + +#include <device/device.h> +#include <device/pci.h> +#include <console/console.h> +#include <arch/io.h> +#include <cpu/cpu.h> +#include <cpu/x86/cache.h> +#include <cpu/x86/smm.h> +#include <string.h> + +#include "i82371eb.h" + +extern unsigned char _binary_smm_start; +extern unsigned char _binary_smm_size; + +/* I440BX */ +#define SMRAM 0x72 +#define D_OPEN (1 << 6) +#define D_CLS (1 << 5) +#define D_LCK (1 << 4) +#define G_SMRAME (1 << 3) +#define C_BASE_SEG ((0 << 2) | (1 << 1) | (0 << 0)) + +/* While we read PMBASE dynamically in case it changed, let's + * initialize it with a sane value + */ +static u16 pmbase = PM_IO_BASE; + +/** + * @brief Set the EOS bit + */ +static void smi_set_eos(void) +{ + u32 reg; + + reg = inl(pmbase + GLBCTL); + reg |= EOS; + outl(reg, pmbase + GLBCTL); +} + +extern uint8_t smm_relocation_start, smm_relocation_end; + +static void smm_relocate(void) +{ + u32 glb_ctl; + u32 reg; + device_t acpi_dev = dev_find_slot(0, PCI_DEVFN(4, 3)); + + printk(BIOS_DEBUG, "Initializing SMM handler..."); + + pmbase = pci_read_config16(acpi_dev, PMBA) & 0xfffc; + if (pmbase == 0) { + /* Sets the base address of power management ports. */ + pci_write_config16(acpi_dev, PMBA, PM_IO_BASE | 1); + pmbase = PM_IO_BASE; + } + printk(BIOS_SPEW, " ... pmbase = 0x%04x\n", pmbase); + + glb_ctl = inl(pmbase + GLBCTL); + if (glb_ctl & SMI_EN) { + printk(BIOS_INFO, "SMI# handler already enabled?\n"); + return; + } + + /* copy the SMM relocation code */ + memcpy((void *)0x38000, &smm_relocation_start, + &smm_relocation_end - &smm_relocation_start); + + /* Enable SMI generation: + * - on APMC writes (io 0xb2) + * - on writes to GBL_RLS (bios commands) + * - on EXTSMI# signal + * - on GSTBY and BM_TRP + */ + + reg = BIOS_EN|EXTSMI_EN|GSTBY_EN|BM_TRP_EN; +#if 0 + reg |= LEGACY_USB_EN; +#endif + outl(reg, pmbase + GLBEN); + + /* SMI on write to APMC */ + reg = pci_read_config32(acpi_dev, DEVACTB); + reg |= APMC_EN; + pci_write_config32(acpi_dev, DEVACTB, reg); + + /* SMI on write to pmbase+PMCNTRL */ + reg = 0x00110000 | (pmbase + PMCNTRL); + pci_write_config32(acpi_dev, DEVRESE, reg); + + reg = inl(pmbase + DEVCTL); + reg |= TRP_EN_DEV12; + outl(reg, pmbase + DEVCTL); + + /* SMI on power button */ + reg = inw(pmbase + PMEN); + reg |= PWRBTN_EN; + outw(reg, pmbase + PMEN); + + /* SMI on THRM# signal */ + reg = THRM_EN; + outw(reg, pmbase + GPEN); + + /* Clear status events. */ + outw(0xffff, pmbase + PMSTS); + outw(0xffff, pmbase + GPSTS); + outw(0xffff, pmbase + GLBSTS); + outl(0xffffffff, pmbase + DEVSTS); + + /* The following need to be on for SMIs to happen */ + glb_ctl |= EOS | SMI_EN; + outl(glb_ctl, pmbase + GLBCTL); + + /** + * There are several methods of raising a controlled SMI# via + * software, among them: + * - Writes to io 0xb2 (APMC) + * - Writes to the Local Apic ICR with Delivery mode SMI. + * + * Using the local apic is a bit more tricky. According to + * AMD Family 11 Processor BKDG no destination shorthand must be + * used. + * The whole SMM initialization is quite a bit hardware specific, so + * I'm not too worried about the better of the methods at the moment + */ + + /* raise an SMI interrupt */ + printk(BIOS_SPEW, " ... raise SMI#\n"); + outb(0x00, APM_CNT); +} + +static void smm_install(void) +{ + device_t dev = dev_find_slot(0, PCI_DEVFN(0, 0)); + /* enable the SMM memory window */ + pci_write_config8(dev, SMRAM, D_OPEN | G_SMRAME | C_BASE_SEG); + + /* copy the real SMM handler */ + memcpy((void *)0xa0000, &_binary_smm_start, (size_t)&_binary_smm_size); + wbinvd(); + + /* close the SMM memory window and enable normal SMM */ + pci_write_config8(dev, SMRAM, G_SMRAME | C_BASE_SEG); +} + +void smm_init(void) +{ + printk(BIOS_SPEW, "%s\n", __func__); + + /* Put SMM code to 0xa0000 */ + smm_install(); + + /* Put relocation code to 0x38000 and relocate SMBASE */ + smm_relocate(); + + /* We're done. Make sure SMIs can happen! */ + smi_set_eos(); + + printk(BIOS_SPEW, "%s done\n", __func__); +} + +void smm_lock(void) +{ + /* LOCK the SMM memory window and enable normal SMM. + * After running this function, only a full reset can + * make the SMM registers writable again. + */ + printk(BIOS_DEBUG, "Locking SMM.\n"); + pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM, + 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; + /* raise SMI to notify the SMM handler */ + outb(0xea, APM_CNT); +} Index: src/southbridge/intel/i82371eb/i82371eb_smihandler.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ src/southbridge/intel/i82371eb/i82371eb_smihandler.c 2010-11-25 03:38:18.000000000 +0100 @@ -0,0 +1,380 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Idwer Vollering vidwer@gmail.com + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + */ + +#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 <device/pci_def.h> + +#include "i82371eb.h" + + +/* While we read PMBASE dynamically in case it changed, let's + * initialize it with a sane value + */ +u16 pmbase = PM_IO_BASE; +u8 smm_initialized = 0; + +unsigned char *mbi = NULL; +u32 mbi_len; +u8 mbi_initialized = 0; + +void *tcg = (void *)0x0; +void *smi1 = (void *)0x0; + +int southbridge_io_trap_handler(int smif) +{ + switch (smif) { + case 0x32: + printk(BIOS_DEBUG, "OS Init\n"); + return 1; /* IO trap handled */ + } + + /* Not handled */ + return 0; +} + +void southbridge_smi_set_eos(void) +{ + u32 reg; + + reg = inl(pmbase + GLBCTL); + reg |= EOS; + outl(reg, pmbase + GLBCTL); +} + + +//static void busmaster_disable_on_bus(int bus) +//{ + // Not implemented +//} + +//static void southbridge_smi_sleep(unsigned int node, smm_state_save_area_t *state_save) +//{ + // Not implemented +//} + +//static void southbridge_smi_apmc(unsigned int node, smm_state_save_area_t *state_save) +//{ + // Not implemented +//} + +//static void southbridge_smi_pm1(unsigned int node, smm_state_save_area_t *state_save) +//{ + // Not implemented +// 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) +//{ + // Not implemented +// u32 gpe0_sts; + +// gpe0_sts = reset_gpe0_status(); +// dump_gpe0_status(gpe0_sts); +//} + +//static void southbridge_smi_gpi(unsigned int node, smm_state_save_area_t *state_save) +//{ + // Not implemented +//} + +//static void southbridge_smi_mc(unsigned int node, smm_state_save_area_t *state_save) +//{ + // Not implemented +//} + +//static void southbridge_smi_tco(unsigned int node, smm_state_save_area_t *state_save) +//{ + // Not implemented +// u32 tco_sts; + +// tco_sts = reset_tco_status(); + +// if (!tco_sts) { +// dump_tco_status(tco_sts); +// } +//} + +//static void southbridge_smi_periodic(unsigned int node, smm_state_save_area_t *state_save) +//{ + // Not implemented +//} + +//static void southbridge_smi_monitor(unsigned int node, smm_state_save_area_t *state_save) +//{ + // Not implemented +//} + +/** + * @brief read and clear PMSTS + * @return PMSTS register + */ +static u16 reset_pm1_status(void) +{ + u16 reg16; + + reg16 = inw(pmbase + PMSTS); + /* set status bits are cleared by writing 1 to them */ + outw(reg16, pmbase + PMSTS); + + return reg16; +} + +static void dump_pm1_status(u16 pm1_sts) +{ + printk(BIOS_DEBUG, "PMSTS: "); + if (pm1_sts & (1 << 15)) printk(BIOS_DEBUG, "RSM_STS "); + if (pm1_sts & (1 << 11)) printk(BIOS_DEBUG, "PRBTNOR "); + if (pm1_sts & (1 << 10)) printk(BIOS_DEBUG, "RTC "); + if (pm1_sts & (1 << 8)) printk(BIOS_DEBUG, "PWRBTN "); + if (pm1_sts & (1 << 5)) printk(BIOS_DEBUG, "GBL "); + if (pm1_sts & (1 << 4)) printk(BIOS_DEBUG, "BM "); + if (pm1_sts & (1 << 0)) printk(BIOS_DEBUG, "TMROF "); + printk(BIOS_DEBUG, "\n"); +} + +/** + * @brief read and clear GPSTS + * @return GPSTS register + */ +static u16 reset_gp_status(void) +{ + u16 reg; + + reg = inw(pmbase + GPSTS); + /* set status bits are cleared by writing 1 to them */ + outw(reg, pmbase + GPSTS); + + return reg; +} + +static void dump_gp_status(u16 gp_sts) +{ + printk(BIOS_DEBUG, "GPSTS: "); + if (gp_sts & (1 << 11)) printk(BIOS_DEBUG, "LID "); + if (gp_sts & (1 << 10)) printk(BIOS_DEBUG, "RI "); + if (gp_sts & (1 << 9)) printk(BIOS_DEBUG, "GPI "); + if (gp_sts & (1 << 8)) printk(BIOS_DEBUG, "USB "); + if (gp_sts & (1 << 7)) printk(BIOS_DEBUG, "THRMOR "); + if (gp_sts & (1 << 0)) printk(BIOS_DEBUG, "THRM "); + printk(BIOS_DEBUG, "\n"); +} + + +/** + * @brief read and clear GLBSTS + * @return GLBSTS register + */ +static u16 reset_glb_status(void) +{ + u16 reg; + + reg = inw(pmbase + GLBSTS); + /* set status bits are cleared by writing 1 to them */ + outw(reg, pmbase + GLBSTS); + + return reg; +} + +static void dump_glb_status(u16 glb_sts) +{ + printk(BIOS_DEBUG, "GLBSTS: "); + if (glb_sts & (1 << 11)) printk(BIOS_DEBUG, "IRQ_RSM "); + if (glb_sts & (1 << 10)) printk(BIOS_DEBUG, "EXTSMI "); + if (glb_sts & (1 << 9)) printk(BIOS_DEBUG, "GSTBY "); + if (glb_sts & (1 << 8)) printk(BIOS_DEBUG, "SMB_WAK "); + if (glb_sts & (1 << 7)) printk(BIOS_DEBUG, "GP "); + if (glb_sts & (1 << 6)) printk(BIOS_DEBUG, "PM1 "); + if (glb_sts & (1 << 5)) printk(BIOS_DEBUG, "APM "); + if (glb_sts & (1 << 4)) printk(BIOS_DEBUG, "DEV "); + if (glb_sts & (1 << 2)) printk(BIOS_DEBUG, "P4MA "); + if (glb_sts & (1 << 1)) printk(BIOS_DEBUG, "LEGACY_USB "); + if (glb_sts & (1 << 0)) printk(BIOS_DEBUG, "BIOS "); + printk(BIOS_DEBUG, "\n"); +} + + +/** + * @brief read and clear DEVSTS + * @return DEVSTS register + */ +static u16 reset_dev_status(void) +{ + u32 reg; + + reg = inl(pmbase + DEVSTS); + /* set status bits are cleared by writing 1 to them */ + outl(reg, pmbase + DEVSTS); + + return reg; +} + +static void dump_dev_status(u32 dev_sts) +{ + int i; + printk(BIOS_DEBUG, "DEV_STS (%08x): ", dev_sts); + for (i=29; i<= 16; i--) { + if (dev_sts & (1 << i)) printk(BIOS_DEBUG, "TRP%d ", (i-16)); + } + for (i=11; i<= 0; i--) { + if (dev_sts & (1 << i)) printk(BIOS_DEBUG, "IDLE%d ", i); + } + printk(BIOS_DEBUG, "\n"); +} + +static void southbridge_smi_gp(unsigned int node, smm_state_save_area_t *state_save) +{ + u32 reg = reset_gp_status(); + printk(BIOS_DEBUG, "%s: %08x\n", __func__, reg); + dump_gp_status(reg); +} + +static void southbridge_smi_pm1(unsigned int node, smm_state_save_area_t *state_save) +{ + u32 reg = reset_pm1_status(); + printk(BIOS_DEBUG, "%s: %08x\n", __func__, reg); + dump_pm1_status(reg); +} + +static void southbridge_smi_dev(unsigned int node, smm_state_save_area_t *state_save) +{ + u32 reg = reset_dev_status(); + printk(BIOS_DEBUG, "%s: %08x\n", __func__, reg); + dump_dev_status(reg); +} + +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(BIOS_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(BIOS_DEBUG, "P-state control\n"); + break; + case ACPI_DISABLE: + pmctrl = inl(pmbase + PMCNTRL); + pmctrl &= ~SCI_EN; + outl(pmctrl, pmbase + PMCNTRL); + printk(BIOS_DEBUG, "SMI#: ACPI disabled.\n"); + break; + case ACPI_ENABLE: + pmctrl = inl(pmbase + PMCNTRL); + pmctrl |= SCI_EN; + outl(pmctrl, pmbase + PMCNTRL); + printk(BIOS_DEBUG, "SMI#: ACPI enabled.\n"); + break; + case GNVS_UPDATE: + if (smm_initialized) { + printk(BIOS_DEBUG, "SMI#: SMM structures already initialized!\n"); + return; + } + tcg = *(void **)0x504; + smi1 = *(void **)0x508; + smm_initialized = 1; + printk(BIOS_DEBUG, "SMI#: Setting up structures to %p, %p\n", tcg, smi1); + break; + case MBI_UPDATE: // FIXME + if (mbi_initialized) { + printk(BIOS_DEBUG, "SMI#: mbi already registered!\n"); + return; + } + mbi = *(void **)0x500; + mbi_len = *(u32 *)0x504; + mbi_initialized = 1; + printk(BIOS_DEBUG, "SMI#: Registered MBI at %p (%d bytes)\n", mbi, mbi_len); + break; + + default: + printk(BIOS_DEBUG, "SMI#: Unknown function APM_CNT=%02x\n", reg8); + } +} + +typedef void (*smi_handler_t)(unsigned int node, + smm_state_save_area_t *state_save); + +smi_handler_t southbridge_smi[16] = { + NULL, // [0] BIOS_STS + NULL, // [1] LEGACY_USB_STS + NULL, // [2] P4MA_STS + NULL, // [3] reserved + southbridge_smi_dev, // [4] DEV_STS + southbridge_smi_apmc, // [5] APM_STS + southbridge_smi_pm1, // [6] PM1_STS + southbridge_smi_gp, // [7] GP_STS + NULL, // [8] GSTBY_STS + NULL, // [9] reserved + NULL, // [10] EXTSMI_STS + NULL, // [11] IRQ_RSM_STS + NULL, // [12] reserved + NULL, // [13] reserved + NULL, // [14] reserved + NULL, // [15] reserved +}; + +void southbridge_smi_handler(unsigned int node, smm_state_save_area_t *state_save) +{ + int i, dump=0; + u16 smi_sts; + + printk(BIOS_DEBUG, "%s\n", __func__); + + /* Update global variable pmbase */ + pmbase = pci_read_config16(PCI_DEV(0, 4, 3), PMBA) & 0xfffc; + + smi_sts = reset_glb_status(); + + /* Call SMI sub handler for each of the status bits */ + for (i = 0; i < 12; i++) { + if (smi_sts & (1 << i)) { + if (southbridge_smi[i]) + southbridge_smi[i](node, state_save); + else { + printk(BIOS_DEBUG, "SMI_STS[%d] occured, but no " + "handler available.\n", i); + dump=1; + } + } + } + + if (dump) + dump_glb_status(smi_sts); +} Index: src/cpu/x86/smm/smihandler.c =================================================================== --- src/cpu/x86/smm/smihandler.c.orig 2010-11-25 03:19:18.000000000 +0100 +++ src/cpu/x86/smm/smihandler.c 2010-11-25 03:20:01.000000000 +0100 @@ -73,8 +73,8 @@ if (southbridge_io_trap_handler(smif)) return;
- if (mainboard_io_trap_handler(smif)) - return; +// if (mainboard_io_trap_handler(smif)) +// return;
printk(BIOS_DEBUG, "Unknown function\n"); } Index: src/cpu/x86/smm/smmhandler.S =================================================================== --- src/cpu/x86/smm/smmhandler.S.orig 2010-11-25 03:19:18.000000000 +0100 +++ src/cpu/x86/smm/smmhandler.S 2010-11-25 03:26:11.000000000 +0100 @@ -102,6 +102,12 @@ movl (%esi), %ecx shr $24, %ecx
+ /* Uninitalized LAPIC? */ + cmp $0xff, %cl + jne 1f + mov $0, %cl /* assume cpu 0 */ +1: + /* calculate stack offset by multiplying the APIC ID * by 1024 (0x400), and save that offset in ebp. */