soc/intel/skylake: Use Broadwell as comparision base for Skylake SOC

Use the Broadwell implementation as the comparison base for Skylake.

BRANCH=none
BUG=None
TEST=None

Change-Id: I22eb55ea89eb0d6883f98e4c72a6d243e819e6d8
Signed-off-by: Lee Leahy <leroy.p.leahy@intel.com>
Reviewed-on: http://review.coreboot.org/10340
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
This commit is contained in:
Lee Leahy
2015-05-12 18:19:47 -07:00
committed by Leroy P Leahy
parent 741a0dd89c
commit b000513741
110 changed files with 19612 additions and 0 deletions

View File

@@ -0,0 +1,278 @@
config SOC_INTEL_SKYLAKE
bool
help
Intel Skylake support
if SOC_INTEL_SKYLAKE
config CPU_SPECIFIC_OPTIONS
def_bool y
select ARCH_BOOTBLOCK_X86_32
select ARCH_VERSTAGE_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_RAMSTAGE_X86_32
select ALT_CBFS_LOAD_PAYLOAD
select ALWAYS_LOAD_OPROM
select BACKUP_DEFAULT_SMM_REGION
select CACHE_MRC_BIN
select CACHE_MRC_SETTINGS
select MRC_SETTINGS_PROTECT
select CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM
select CACHE_ROM
select CAR_MIGRATION
select COLLECT_TIMESTAMPS
select CPU_INTEL_FIRMWARE_INTERFACE_TABLE
select SUPPORT_CPU_UCODE_IN_CBFS
select HAVE_MONOTONIC_TIMER
select HAVE_SMI_HANDLER
select HAVE_HARD_RESET
select HAVE_USBDEBUG
select IOAPIC
select MMCONF_SUPPORT
select MMCONF_SUPPORT_DEFAULT
select RELOCATABLE_MODULES
select RELOCATABLE_RAMSTAGE
select REG_SCRIPT
select PARALLEL_MP
select PCIEXP_ASPM
select PCIEXP_COMMON_CLOCK
select PCIEXP_CLK_PM
select PCIEXP_L1_SUB_STATE
select SMM_MODULES
select SMM_TSEG
select SMP
select SPI_FLASH
select SSE2
select SUPPORT_CPU_UCODE_IN_CBFS
select TSC_CONSTANT_RATE
select TSC_SYNC_MFENCE
select UDELAY_TSC
select PER_DEVICE_ACPI_TABLES
select SOC_INTEL_COMMON
config BOOTBLOCK_CPU_INIT
string
default "soc/intel/skylake/bootblock/cpu.c"
config BOOTBLOCK_NORTHBRIDGE_INIT
string
default "soc/intel/skylake/bootblock/systemagent.c"
config BOOTBLOCK_SOUTHBRIDGE_INIT
string
default "soc/intel/skylake/bootblock/pch.c"
config MMCONF_BASE_ADDRESS
hex
default 0xf0000000
config SERIAL_CPU_INIT
bool
default n
config SMM_TSEG_SIZE
hex
default 0x800000
config IED_REGION_SIZE
hex
default 0x400000
config SMM_RESERVED_SIZE
hex
default 0x100000
config VGA_BIOS_ID
string
default "8086,0406"
config CACHE_MRC_SIZE_KB
int
default 512
config DCACHE_RAM_BASE
hex
default 0xff7c0000
config DCACHE_RAM_SIZE
hex
default 0x10000
help
The size of the cache-as-ram region required during bootblock
and/or romstage. Note DCACHE_RAM_SIZE and DCACHE_RAM_MRC_VAR_SIZE
must add up to a power of 2.
config DCACHE_RAM_MRC_VAR_SIZE
hex
default 0x30000
help
The amount of cache-as-ram region required by the reference code.
config DCACHE_RAM_ROMSTAGE_STACK_SIZE
hex
default 0x2000
help
The amount of anticipated stack usage from the data cache
during pre-ram rom stage execution.
config HAVE_MRC
bool "Add a Memory Reference Code binary"
help
Select this option to add a Memory Reference Code binary to
the resulting coreboot image.
Note: Without this binary coreboot will not work
if HAVE_MRC
config MRC_FILE
string "Intel Memory Reference Code path and filename"
depends on HAVE_MRC
default "mrc.bin"
help
The filename of the file to use as Memory Reference Code binary.
config MRC_BIN_ADDRESS
hex
default 0xfffa0000
config CACHE_MRC_SETTINGS
bool "Save cached MRC settings"
default y
endif # HAVE_MRC
config CBFS_SIZE
hex "Size of CBFS filesystem in ROM"
default 0x100000
help
The firmware image has to store more than just coreboot, including:
- a firmware descriptor
- Intel Management Engine firmware
- MRC cache information
This option allows to limit the size of the CBFS portion in the
firmware image.
config PRE_GRAPHICS_DELAY
int "Graphics initialization delay in ms"
default 0
help
On some systems, coreboot boots so fast that connected monitors
(mostly TVs) won't be able to wake up fast enough to talk to the
VBIOS. On those systems we need to wait for a bit before executing
the VBIOS.
config RESET_ON_INVALID_RAMSTAGE_CACHE
bool "Reset the system on S3 wake when ramstage cache invalid."
default n
depends on RELOCATABLE_RAMSTAGE
help
The romstage code caches the loaded ramstage program in SMM space.
On S3 wake the romstage will copy over a fresh ramstage that was
cached in the SMM space. This option determines the action to take
when the ramstage cache is invalid. If selected the system will
reset otherwise the ramstage will be reloaded from cbfs.
config INTEL_PCH_UART_CONSOLE
bool "Use Serial IO UART for console"
default n
select HAVE_UART_MEMORY_MAPPED
select CONSOLE_SERIAL8250MEM
depends on !CONFIG_DRIVERS_OXFORD_OXPCIE
config INTEL_PCH_UART_CONSOLE_NUMBER
hex "Serial IO UART number to use for console"
default "0x0"
depends on INTEL_PCH_UART_CONSOLE
config TTYS0_BASE
hex
default 0xd6000000
depends on INTEL_PCH_UART_CONSOLE
config EHCI_BAR
hex
default 0xd8000000
config EHCI_DEBUG_OFFSET
hex
default 0xa0
config SERIRQ_CONTINUOUS_MODE
bool
default y
help
If you set this option to y, the serial IRQ machine will be
operated in continuous mode.
config HAVE_ME_BIN
bool "Add Intel Management Engine firmware"
default y
help
The Intel processor in the selected system requires a special firmware
for an integrated controller called Management Engine (ME). The ME
firmware might be provided in coreboot's 3rdparty/blobs repository. If
not and if you don't have the firmware elsewhere, you can still
build coreboot without it. In this case however, you'll have to make
sure that you don't overwrite your ME firmware on your flash ROM.
config ME_BIN_PATH
string "Path to management engine firmware"
depends on HAVE_ME_BIN
default "3rdparty/blobs/mainboard/$(MAINBOARDDIR)/me.bin"
config HAVE_IFD_BIN
bool "Use Intel Firmware Descriptor from existing binary"
default n
config BUILD_WITH_FAKE_IFD
bool "Build with a fake IFD"
default y if !HAVE_IFD_BIN
help
If you don't have an Intel Firmware Descriptor (ifd.bin) for your
board, you can select this option and coreboot will build without it.
Though, the resulting coreboot.rom will not contain all parts required
to get coreboot running on your board. You can however write only the
BIOS section to your board's flash ROM and keep the other sections
untouched. Unfortunately the current version of flashrom doesn't
support this yet. But there is a patch pending [1].
WARNING: Never write a complete coreboot.rom to your flash ROM if it
was built with a fake IFD. It just won't work.
[1] http://www.flashrom.org/pipermail/flashrom/2013-June/011083.html
config IFD_BIOS_SECTION
depends on BUILD_WITH_FAKE_IFD
string
default ""
config IFD_ME_SECTION
depends on BUILD_WITH_FAKE_IFD
string
default ""
config IFD_PLATFORM_SECTION
depends on BUILD_WITH_FAKE_IFD
string
default ""
config IFD_BIN_PATH
string "Path to intel firmware descriptor"
depends on !BUILD_WITH_FAKE_IFD
default "3rdparty/blobs/mainboard/$(MAINBOARDDIR)/descriptor.bin"
config LOCK_MANAGEMENT_ENGINE
bool "Lock Management Engine section"
default n
help
The Intel Management Engine supports preventing write accesses
from the host to the Management Engine section in the firmware
descriptor. If the ME section is locked, it can only be overwritten
with an external SPI flash programmer. You will want this if you
want to increase security of your ROM image once you are sure
that the ME firmware is no longer going to change.
If unsure, say N.
endif

View File

@@ -0,0 +1,134 @@
ifeq ($(CONFIG_SOC_INTEL_SKYLAKE),y)
subdirs-y += bootblock
subdirs-y += microcode
subdirs-y += romstage
subdirs-y += ../../../cpu/x86/lapic
subdirs-y += ../../../cpu/x86/mtrr
subdirs-y += ../../../cpu/x86/smm
subdirs-y += ../../../cpu/x86/tsc
subdirs-y += ../../../cpu/intel/microcode
subdirs-y += ../../../cpu/intel/turbo
ramstage-y += acpi.c
ramstage-y += adsp.c
ramstage-y += chip.c
ramstage-y += cpu.c
ramstage-y += cpu_info.c
smm-y += cpu_info.c
ramstage-$(CONFIG_ELOG) += elog.c
ramstage-y += finalize.c
ramstage-y += gpio.c
romstage-y += gpio.c
smm-y += gpio.c
ramstage-y += hda.c
ramstage-y += igd.c
ramstage-y += iobp.c
romstage-y += iobp.c
ramstage-y += lpc.c
ramstage-y += me.c
ramstage-y += me_status.c
romstage-y += me_status.c
ramstage-y += memmap.c
romstage-y += memmap.c
ramstage-y += minihd.c
ramstage-y += monotonic_timer.c
smm-y += monotonic_timer.c
ramstage-y += pch.c
romstage-y += pch.c
ramstage-y += pcie.c
ramstage-y += pei_data.c
romstage-y += pei_data.c
ramstage-y += pmutil.c
romstage-y += pmutil.c
smm-y += pmutil.c
ramstage-y += ramstage.c
ramstage-$(CONFIG_HAVE_REFCODE_BLOB) += refcode.c
ramstage-y += reset.c
romstage-y += reset.c
ramstage-y += sata.c
ramstage-y += serialio.c
ramstage-y += smbus.c
ramstage-y += smbus_common.c
romstage-y += smbus_common.c
ramstage-y += smi.c
smm-y += smihandler.c
ramstage-y += smmrelocate.c
ramstage-y += spi.c
smm-$(CONFIG_SPI_FLASH_SMM) += spi.c
ramstage-y += stage_cache.c
romstage-y += stage_cache.c
ramstage-y += systemagent.c
ramstage-y += tsc_freq.c
romstage-y += tsc_freq.c
smm-y += tsc_freq.c
ramstage-y += ehci.c
ramstage-y += xhci.c
smm-y += xhci.c
ifeq ($(CONFIG_USBDEBUG),y)
ramstage-y += usbdebug.c
romstage-y += usbdebug.c
smm-y += usbdebug.c
endif
CPPFLAGS_common += -Isrc/soc/intel/broadwell/include
# Run an intermediate step when producing coreboot.rom
# that adds additional components to the final firmware
# image outside of CBFS
INTERMEDIATE := broadwell_add_me
ifeq ($(CONFIG_BUILD_WITH_FAKE_IFD),y)
IFD_BIN_PATH := $(objgenerated)/ifdfake.bin
IFD_SECTIONS := $(addprefix -b ,$(CONFIG_IFD_BIOS_SECTION:"%"=%)) \
$(addprefix -m ,$(CONFIG_IFD_ME_SECTION:"%"=%)) \
$(addprefix -p ,$(CONFIG_IFD_PLATFORM_SECTION:"%"=%))
else
IFD_BIN_PATH := $(CONFIG_IFD_BIN_PATH)
endif
broadwell_add_me: $(obj)/coreboot.pre $(IFDTOOL) $(IFDFAKE)
ifeq ($(CONFIG_BUILD_WITH_FAKE_IFD),y)
printf "\n** WARNING **\n"
printf "Coreboot will be built with a fake Intel Firmware Descriptor (IFD).\n"
printf "Never write a complete coreboot.rom with a fake IFD to your board's\n"
printf "flash ROM! Make sure that you only write valid flash regions.\n\n"
printf " IFDFAKE Building a fake Intel Firmware Descriptor\n"
$(IFDFAKE) $(IFD_SECTIONS) $(IFD_BIN_PATH)
endif
printf " DD Adding Intel Firmware Descriptor\n"
dd if=$(IFD_BIN_PATH) \
of=$(obj)/coreboot.pre conv=notrunc >/dev/null 2>&1
ifeq ($(CONFIG_HAVE_ME_BIN),y)
printf " IFDTOOL me.bin -> coreboot.pre\n"
$(objutil)/ifdtool/ifdtool \
-i ME:$(CONFIG_ME_BIN_PATH) \
$(obj)/coreboot.pre
mv $(obj)/coreboot.pre.new $(obj)/coreboot.pre
ifeq ($(CONFIG_LOCK_MANAGEMENT_ENGINE),y)
printf " IFDTOOL Locking Management Engine\n"
$(objutil)/ifdtool/ifdtool -l $(obj)/coreboot.pre
mv $(obj)/coreboot.pre.new $(obj)/coreboot.pre
else
printf " IFDTOOL Unlocking Management Engine\n"
$(objutil)/ifdtool/ifdtool -u $(obj)/coreboot.pre
mv $(obj)/coreboot.pre.new $(obj)/coreboot.pre
endif
endif
PHONY += broadwell_add_me
# If an MRC file is an ELF file determine the entry address and first loadable
# section offset in the file. Subtract the offset from the entry address to
# determine the final location.
mrcelfoffset = $(shell $(READELF_x86_32) -S -W $(CONFIG_MRC_FILE) | sed -e 's/\[ /[0/' | awk '$$3 ~ /PROGBITS/ { print "0x"$$5; exit }' )
mrcelfentry = $(shell $(READELF_x86_32) -h -W $(CONFIG_MRC_FILE) | grep 'Entry point address' | awk '{print $$NF }')
# Add memory reference code blob.
cbfs-files-$(CONFIG_HAVE_MRC) += mrc.bin
mrc.bin-file := $(call strip_quotes,$(CONFIG_MRC_FILE))
mrc.bin-position := $(if $(findstring elf,$(CONFIG_MRC_FILE)),$(shell printf "0x%x" $$(( $(mrcelfentry) - $(mrcelfoffset) )) ),$(CONFIG_MRC_BIN_ADDRESS))
mrc.bin-type := mrc
endif

View File

@@ -0,0 +1,602 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/acpi.h>
#include <arch/acpigen.h>
#include <arch/io.h>
#include <arch/smp/mpspec.h>
#include <cbmem.h>
#include <console/console.h>
#include <cpu/x86/smm.h>
#include <console/console.h>
#include <types.h>
#include <string.h>
#include <arch/cpu.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/tsc.h>
#include <cpu/intel/turbo.h>
#include <ec/google/chromeec/ec.h>
#include <vendorcode/google/chromeos/gnvs.h>
#include <soc/acpi.h>
#include <soc/cpu.h>
#include <soc/iomap.h>
#include <soc/lpc.h>
#include <soc/msr.h>
#include <soc/pci_devs.h>
#include <soc/pm.h>
#include <soc/intel/broadwell/chip.h>
/*
* List of supported C-states in this processor. Only the ULT parts support C8,
* C9, and C10.
*/
enum {
C_STATE_C0, /* 0 */
C_STATE_C1, /* 1 */
C_STATE_C1E, /* 2 */
C_STATE_C3, /* 3 */
C_STATE_C6_SHORT_LAT, /* 4 */
C_STATE_C6_LONG_LAT, /* 5 */
C_STATE_C7_SHORT_LAT, /* 6 */
C_STATE_C7_LONG_LAT, /* 7 */
C_STATE_C7S_SHORT_LAT, /* 8 */
C_STATE_C7S_LONG_LAT, /* 9 */
C_STATE_C8, /* 10 */
C_STATE_C9, /* 11 */
C_STATE_C10, /* 12 */
NUM_C_STATES
};
#define MWAIT_RES(state, sub_state) \
{ \
.addrl = (((state) << 4) | (sub_state)), \
.space_id = ACPI_ADDRESS_SPACE_FIXED, \
.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL, \
.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT, \
.access_size = ACPI_FFIXEDHW_FLAG_HW_COORD, \
}
static acpi_cstate_t cstate_map[NUM_C_STATES] = {
[C_STATE_C0] = { },
[C_STATE_C1] = {
.latency = 0,
.power = 1000,
.resource = MWAIT_RES(0,0),
},
[C_STATE_C1E] = {
.latency = 0,
.power = 1000,
.resource = MWAIT_RES(0,1),
},
[C_STATE_C3] = {
.latency = C_STATE_LATENCY_FROM_LAT_REG(0),
.power = 900,
.resource = MWAIT_RES(1, 0),
},
[C_STATE_C6_SHORT_LAT] = {
.latency = C_STATE_LATENCY_FROM_LAT_REG(1),
.power = 800,
.resource = MWAIT_RES(2, 0),
},
[C_STATE_C6_LONG_LAT] = {
.latency = C_STATE_LATENCY_FROM_LAT_REG(2),
.power = 800,
.resource = MWAIT_RES(2, 1),
},
[C_STATE_C7_SHORT_LAT] = {
.latency = C_STATE_LATENCY_FROM_LAT_REG(1),
.power = 700,
.resource = MWAIT_RES(3, 0),
},
[C_STATE_C7_LONG_LAT] = {
.latency = C_STATE_LATENCY_FROM_LAT_REG(2),
.power = 700,
.resource = MWAIT_RES(3, 1),
},
[C_STATE_C7S_SHORT_LAT] = {
.latency = C_STATE_LATENCY_FROM_LAT_REG(1),
.power = 700,
.resource = MWAIT_RES(3, 2),
},
[C_STATE_C7S_LONG_LAT] = {
.latency = C_STATE_LATENCY_FROM_LAT_REG(2),
.power = 700,
.resource = MWAIT_RES(3, 3),
},
[C_STATE_C8] = {
.latency = C_STATE_LATENCY_FROM_LAT_REG(3),
.power = 600,
.resource = MWAIT_RES(4, 0),
},
[C_STATE_C9] = {
.latency = C_STATE_LATENCY_FROM_LAT_REG(4),
.power = 500,
.resource = MWAIT_RES(5, 0),
},
[C_STATE_C10] = {
.latency = C_STATE_LATENCY_FROM_LAT_REG(5),
.power = 400,
.resource = MWAIT_RES(6, 0),
},
};
static int cstate_set_s0ix[3] = {
C_STATE_C1E,
C_STATE_C7S_LONG_LAT,
C_STATE_C10
};
static int cstate_set_non_s0ix[3] = {
C_STATE_C1E,
C_STATE_C3,
C_STATE_C7S_LONG_LAT
};
static int get_cores_per_package(void)
{
struct cpuinfo_x86 c;
struct cpuid_result result;
int cores = 1;
get_fms(&c, cpuid_eax(1));
if (c.x86 != 6)
return 1;
result = cpuid_ext(0xb, 1);
cores = result.ebx & 0xff;
return cores;
}
void acpi_init_gnvs(global_nvs_t *gnvs)
{
/* Set unknown wake source */
gnvs->pm1i = -1;
/* CPU core count */
gnvs->pcnt = dev_count_cpu();
#if CONFIG_CONSOLE_CBMEM
/* Update the mem console pointer. */
gnvs->cbmc = (u32)cbmem_find(CBMEM_ID_CONSOLE);
#endif
#if CONFIG_CHROMEOS
/* Initialize Verified Boot data */
chromeos_init_vboot(&(gnvs->chromeos));
#if CONFIG_EC_GOOGLE_CHROMEEC
gnvs->chromeos.vbt2 = google_ec_running_ro() ?
ACTIVE_ECFW_RO : ACTIVE_ECFW_RW;
#endif
gnvs->chromeos.vbt2 = ACTIVE_ECFW_RO;
#endif
}
void acpi_create_intel_hpet(acpi_hpet_t * hpet)
{
acpi_header_t *header = &(hpet->header);
acpi_addr_t *addr = &(hpet->addr);
memset((void *) hpet, 0, sizeof(acpi_hpet_t));
/* fill out header fields */
memcpy(header->signature, "HPET", 4);
memcpy(header->oem_id, OEM_ID, 6);
memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
memcpy(header->asl_compiler_id, ASLC, 4);
header->length = sizeof(acpi_hpet_t);
header->revision = 1;
/* fill out HPET address */
addr->space_id = 0; /* Memory */
addr->bit_width = 64;
addr->bit_offset = 0;
addr->addrl = (unsigned long long)HPET_BASE_ADDRESS & 0xffffffff;
addr->addrh = (unsigned long long)HPET_BASE_ADDRESS >> 32;
hpet->id = 0x8086a201; /* Intel */
hpet->number = 0x00;
hpet->min_tick = 0x0080;
header->checksum =
acpi_checksum((void *) hpet, sizeof(acpi_hpet_t));
}
unsigned long acpi_fill_mcfg(unsigned long current)
{
current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)current,
MCFG_BASE_ADDRESS, 0, 0, 255);
return current;
}
void acpi_fill_in_fadt(acpi_fadt_t *fadt)
{
const uint16_t pmbase = ACPI_BASE_ADDRESS;
fadt->sci_int = acpi_sci_irq();
fadt->smi_cmd = APM_CNT;
fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
fadt->s4bios_req = 0x0;
fadt->pstate_cnt = 0;
fadt->pm1a_evt_blk = pmbase + PM1_STS;
fadt->pm1b_evt_blk = 0x0;
fadt->pm1a_cnt_blk = pmbase + PM1_CNT;
fadt->pm1b_cnt_blk = 0x0;
fadt->pm2_cnt_blk = pmbase + PM2_CNT;
fadt->pm_tmr_blk = pmbase + PM1_TMR;
fadt->gpe0_blk = pmbase + GPE0_STS(0);
fadt->gpe1_blk = 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 = 32;
fadt->gpe1_blk_len = 0;
fadt->gpe1_base = 0;
fadt->cst_cnt = 0;
fadt->p_lvl2_lat = 1;
fadt->p_lvl3_lat = 87;
fadt->flush_size = 1024;
fadt->flush_stride = 16;
fadt->duty_offset = 1;
fadt->duty_width = 0;
fadt->day_alrm = 0xd;
fadt->mon_alrm = 0x00;
fadt->century = 0x00;
fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON |
ACPI_FADT_RESET_REGISTER | ACPI_FADT_SEALED_CASE |
ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK;
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 = 0;
fadt->reset_value = 6;
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 = pmbase + PM1_STS;
fadt->x_pm1a_evt_blk.addrh = 0x0;
fadt->x_pm1b_evt_blk.space_id = 1;
fadt->x_pm1b_evt_blk.bit_width = 0;
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 = 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 = pmbase + PM1_CNT;
fadt->x_pm1a_cnt_blk.addrh = 0x0;
fadt->x_pm1b_cnt_blk.space_id = 1;
fadt->x_pm1b_cnt_blk.bit_width = 0;
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 = 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 = pmbase + PM2_CNT;
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 = pmbase + PM1_TMR;
fadt->x_pm_tmr_blk.addrh = 0x0;
fadt->x_gpe0_blk.space_id = 0;
fadt->x_gpe0_blk.bit_width = 0;
fadt->x_gpe0_blk.bit_offset = 0;
fadt->x_gpe0_blk.resv = 0;
fadt->x_gpe0_blk.addrl = 0;
fadt->x_gpe0_blk.addrh = 0;
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 = 0x0;
fadt->x_gpe1_blk.addrh = 0x0;
}
static acpi_tstate_t tss_table_fine[] = {
{ 100, 1000, 0, 0x00, 0 },
{ 94, 940, 0, 0x1f, 0 },
{ 88, 880, 0, 0x1e, 0 },
{ 82, 820, 0, 0x1d, 0 },
{ 75, 760, 0, 0x1c, 0 },
{ 69, 700, 0, 0x1b, 0 },
{ 63, 640, 0, 0x1a, 0 },
{ 57, 580, 0, 0x19, 0 },
{ 50, 520, 0, 0x18, 0 },
{ 44, 460, 0, 0x17, 0 },
{ 38, 400, 0, 0x16, 0 },
{ 32, 340, 0, 0x15, 0 },
{ 25, 280, 0, 0x14, 0 },
{ 19, 220, 0, 0x13, 0 },
{ 13, 160, 0, 0x12, 0 },
};
static acpi_tstate_t tss_table_coarse[] = {
{ 100, 1000, 0, 0x00, 0 },
{ 88, 875, 0, 0x1f, 0 },
{ 75, 750, 0, 0x1e, 0 },
{ 63, 625, 0, 0x1d, 0 },
{ 50, 500, 0, 0x1c, 0 },
{ 38, 375, 0, 0x1b, 0 },
{ 25, 250, 0, 0x1a, 0 },
{ 13, 125, 0, 0x19, 0 },
};
static int generate_T_state_entries(int core, int cores_per_package)
{
int len;
/* Indicate SW_ALL coordination for T-states */
len = acpigen_write_TSD_package(core, cores_per_package, SW_ALL);
/* Indicate FFixedHW so OS will use MSR */
len += acpigen_write_empty_PTC();
/* Set a T-state limit that can be modified in NVS */
len += acpigen_write_TPC("\\TLVL");
/*
* CPUID.(EAX=6):EAX[5] indicates support
* for extended throttle levels.
*/
if (cpuid_eax(6) & (1 << 5))
len += acpigen_write_TSS_package(
ARRAY_SIZE(tss_table_fine), tss_table_fine);
else
len += acpigen_write_TSS_package(
ARRAY_SIZE(tss_table_coarse), tss_table_coarse);
return len;
}
static int generate_C_state_entries(void)
{
device_t dev = SA_DEV_ROOT;
config_t *config = dev->chip_info;
acpi_cstate_t map[3];
int *set;
int i;
if (config->s0ix_enable)
set = cstate_set_s0ix;
else
set = cstate_set_non_s0ix;
for (i = 0; i < 3; i++) {
memcpy(&map[i], &cstate_map[set[i]], sizeof(acpi_cstate_t));
map[i].ctype = i + 1;
}
/* Generate C-state tables */
return acpigen_write_CST_package(map, ARRAY_SIZE(map));
}
static int calculate_power(int tdp, int p1_ratio, int ratio)
{
u32 m;
u32 power;
/*
* M = ((1.1 - ((p1_ratio - ratio) * 0.00625)) / 1.1) ^ 2
*
* Power = (ratio / p1_ratio) * m * tdp
*/
m = (110000 - ((p1_ratio - ratio) * 625)) / 11;
m = (m * m) / 1000;
power = ((ratio * 100000 / p1_ratio) / 100);
power *= (m / 100) * (tdp / 1000);
power /= 1000;
return (int)power;
}
static void generate_P_state_entries(int core, int cores_per_package)
{
int ratio_min, ratio_max, ratio_turbo, ratio_step;
int coord_type, power_max, power_unit, num_entries;
int ratio, power, clock, clock_max;
msr_t msr;
/* Determine P-state coordination type from MISC_PWR_MGMT[0] */
msr = rdmsr(MSR_MISC_PWR_MGMT);
if (msr.lo & MISC_PWR_MGMT_EIST_HW_DIS)
coord_type = SW_ANY;
else
coord_type = HW_ALL;
/* Get bus ratio limits and calculate clock speeds */
msr = rdmsr(MSR_PLATFORM_INFO);
ratio_min = (msr.hi >> (40-32)) & 0xff; /* Max Efficiency Ratio */
/* Determine if this CPU has configurable TDP */
if (cpu_config_tdp_levels()) {
/* Set max ratio to nominal TDP ratio */
msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
ratio_max = msr.lo & 0xff;
} else {
/* Max Non-Turbo Ratio */
ratio_max = (msr.lo >> 8) & 0xff;
}
clock_max = ratio_max * CPU_BCLK;
/* Calculate CPU TDP in mW */
msr = rdmsr(MSR_PKG_POWER_SKU_UNIT);
power_unit = 2 << ((msr.lo & 0xf) - 1);
msr = rdmsr(MSR_PKG_POWER_SKU);
power_max = ((msr.lo & 0x7fff) / power_unit) * 1000;
/* Write _PCT indicating use of FFixedHW */
acpigen_write_empty_PCT();
/* Write _PPC with no limit on supported P-state */
acpigen_write_PPC_NVS();
/* Write PSD indicating configured coordination type */
acpigen_write_PSD_package(core, 1, coord_type);
/* Add P-state entries in _PSS table */
acpigen_write_name("_PSS");
/* Determine ratio points */
ratio_step = PSS_RATIO_STEP;
num_entries = (ratio_max - ratio_min) / ratio_step;
while (num_entries > PSS_MAX_ENTRIES-1) {
ratio_step <<= 1;
num_entries >>= 1;
}
/* P[T] is Turbo state if enabled */
if (get_turbo_state() == TURBO_ENABLED) {
/* _PSS package count including Turbo */
acpigen_write_package(num_entries + 2);
msr = rdmsr(MSR_TURBO_RATIO_LIMIT);
ratio_turbo = msr.lo & 0xff;
/* Add entry for Turbo ratio */
acpigen_write_PSS_package(
clock_max + 1, /*MHz*/
power_max, /*mW*/
PSS_LATENCY_TRANSITION, /*lat1*/
PSS_LATENCY_BUSMASTER, /*lat2*/
ratio_turbo << 8, /*control*/
ratio_turbo << 8); /*status*/
} else {
/* _PSS package count without Turbo */
acpigen_write_package(num_entries + 1);
}
/* First regular entry is max non-turbo ratio */
acpigen_write_PSS_package(
clock_max, /*MHz*/
power_max, /*mW*/
PSS_LATENCY_TRANSITION, /*lat1*/
PSS_LATENCY_BUSMASTER, /*lat2*/
ratio_max << 8, /*control*/
ratio_max << 8); /*status*/
/* Generate the remaining entries */
for (ratio = ratio_min + ((num_entries - 1) * ratio_step);
ratio >= ratio_min; ratio -= ratio_step) {
/* Calculate power at this ratio */
power = calculate_power(power_max, ratio_max, ratio);
clock = ratio * CPU_BCLK;
acpigen_write_PSS_package(
clock, /*MHz*/
power, /*mW*/
PSS_LATENCY_TRANSITION, /*lat1*/
PSS_LATENCY_BUSMASTER, /*lat2*/
ratio << 8, /*control*/
ratio << 8); /*status*/
}
/* Fix package length */
acpigen_pop_len();
}
void generate_cpu_entries(void)
{
int coreID, cpuID, pcontrol_blk = ACPI_BASE_ADDRESS, plen = 6;
int totalcores = dev_count_cpu();
int cores_per_package = get_cores_per_package();
int numcpus = totalcores/cores_per_package;
printk(BIOS_DEBUG, "Found %d CPU(s) with %d core(s) each.\n",
numcpus, cores_per_package);
for (cpuID=1; cpuID <=numcpus; cpuID++) {
for (coreID=1; coreID<=cores_per_package; coreID++) {
if (coreID>1) {
pcontrol_blk = 0;
plen = 0;
}
/* Generate processor \_PR.CPUx */
acpigen_write_processor(
(cpuID-1)*cores_per_package+coreID-1,
pcontrol_blk, plen);
/* Generate P-state tables */
generate_P_state_entries(
coreID-1, cores_per_package);
/* Generate C-state tables */
generate_C_state_entries();
/* Generate T-state tables */
generate_T_state_entries(
cpuID-1, cores_per_package);
acpigen_pop_len();
}
}
}
unsigned long acpi_madt_irq_overrides(unsigned long current)
{
int sci = acpi_sci_irq();
acpi_madt_irqoverride_t *irqovr;
uint16_t flags = MP_IRQ_TRIGGER_LEVEL;
/* INT_SRC_OVR */
irqovr = (void *)current;
current += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0);
if (sci >= 20)
flags |= MP_IRQ_POLARITY_LOW;
else
flags |= MP_IRQ_POLARITY_HIGH;
/* SCI */
irqovr = (void *)current;
current += acpi_create_madt_irqoverride(irqovr, 0, sci, sci, flags);
return current;
}

View File

@@ -0,0 +1,73 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
Device (ADSP)
{
Method (_HID, 0, Serialized)
{
If (\ISWP ()) {
// WildcatPoint
Return ("INT3438")
}
// LynxPoint-LP
Return ("INT33C8")
}
Name (_UID, 1)
Name (_DDN, "Intel Smart Sound Technology")
Name (RBUF, ResourceTemplate ()
{
Memory32Fixed (ReadWrite, 0x00000000, 0x00100000, BAR0)
Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR1)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {3}
})
Method (_CRS, 0, NotSerialized)
{
// Update BAR address and length if set in NVS
If (LNotEqual (\S8B0, Zero)) {
CreateDwordField (^RBUF, ^BAR0._BAS, B8A0)
CreateDwordField (^RBUF, ^BAR1._BAS, B8A1)
Store (\S8B0, B8A0)
Store (\S8B1, B8A1)
}
Return (RBUF)
}
Method (_STA, 0, NotSerialized)
{
If (LEqual (\S8EN, 0)) {
Return (0x0)
} Else {
Return (0xF)
}
}
Device (I2S0)
{
Name (_ADR, 0)
}
Device (I2S1)
{
Name (_ADR, 1)
}
}

View File

@@ -0,0 +1,122 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
/* These devices are created at runtime */
External (\_PR.CP00, DeviceObj)
External (\_PR.CP01, DeviceObj)
External (\_PR.CP02, DeviceObj)
External (\_PR.CP03, DeviceObj)
External (\_PR.CP04, DeviceObj)
External (\_PR.CP05, DeviceObj)
External (\_PR.CP06, DeviceObj)
External (\_PR.CP07, DeviceObj)
/* Notify OS to re-read CPU tables, assuming ^2 CPU count */
Method (PNOT)
{
If (LGreaterEqual (\PCNT, 2)) {
Notify (\_PR.CP00, 0x81) // _CST
Notify (\_PR.CP01, 0x81) // _CST
}
If (LGreaterEqual (\PCNT, 4)) {
Notify (\_PR.CP02, 0x81) // _CST
Notify (\_PR.CP03, 0x81) // _CST
}
If (LGreaterEqual (\PCNT, 8)) {
Notify (\_PR.CP04, 0x81) // _CST
Notify (\_PR.CP05, 0x81) // _CST
Notify (\_PR.CP06, 0x81) // _CST
Notify (\_PR.CP07, 0x81) // _CST
}
}
/* Notify OS to re-read CPU _PPC limit, assuming ^2 CPU count */
Method (PPCN)
{
If (LGreaterEqual (\PCNT, 2)) {
Notify (\_PR.CP00, 0x80) // _PPC
Notify (\_PR.CP01, 0x80) // _PPC
}
If (LGreaterEqual (\PCNT, 4)) {
Notify (\_PR.CP02, 0x80) // _PPC
Notify (\_PR.CP03, 0x80) // _PPC
}
If (LGreaterEqual (\PCNT, 8)) {
Notify (\_PR.CP04, 0x80) // _PPC
Notify (\_PR.CP05, 0x80) // _PPC
Notify (\_PR.CP06, 0x80) // _PPC
Notify (\_PR.CP07, 0x80) // _PPC
}
}
/* Notify OS to re-read Throttle Limit tables, assuming ^2 CPU count */
Method (TNOT)
{
If (LGreaterEqual (\PCNT, 2)) {
Notify (\_PR.CP00, 0x82) // _TPC
Notify (\_PR.CP01, 0x82) // _TPC
}
If (LGreaterEqual (\PCNT, 4)) {
Notify (\_PR.CP02, 0x82) // _TPC
Notify (\_PR.CP03, 0x82) // _TPC
}
If (LGreaterEqual (\PCNT, 8)) {
Notify (\_PR.CP04, 0x82) // _TPC
Notify (\_PR.CP05, 0x82) // _TPC
Notify (\_PR.CP06, 0x82) // _TPC
Notify (\_PR.CP07, 0x82) // _TPC
}
}
/* Return a package containing enabled processor entries */
Method (PPKG)
{
If (LGreaterEqual (\PCNT, 8)) {
Return (Package()
{
\_PR.CP00,
\_PR.CP01,
\_PR.CP02,
\_PR.CP03,
\_PR.CP04,
\_PR.CP05,
\_PR.CP06,
\_PR.CP07
})
} ElseIf (LGreaterEqual (\PCNT, 4)) {
Return (Package ()
{
\_PR.CP00,
\_PR.CP01,
\_PR.CP02,
\_PR.CP03
})
} ElseIf (LGreaterEqual (\PCNT, 2)) {
Return (Package ()
{
\_PR.CP00,
\_PR.CP01
})
} Else {
Return (Package ()
{
\_PR.CP00
})
}
}

View File

@@ -0,0 +1,237 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
Scope (\_SB.PCI0.MCHC)
{
Mutex (CTCM, 1) /* CTDP Switch Mutex (sync level 1) */
Name (CTCC, 0) /* CTDP Current Selection */
Name (CTCN, 0) /* CTDP Nominal Select */
Name (CTCD, 1) /* CTDP Down Select */
Name (CTCU, 2) /* CTDP Up Select */
Name (SPL1, 0) /* Saved PL1 value */
OperationRegion (MCHB, SystemMemory,
Add (MCH_BASE_ADDRESS, 0x5000), 0x1000)
Field (MCHB, DWordAcc, Lock, Preserve)
{
Offset (0x930), /* PACKAGE_POWER_SKU */
CTDN, 15, /* CTDP Nominal PL1 */
Offset (0x938), /* PACKAGE_POWER_SKU_UNIT */
PUNI, 4, /* Power Units */
, 4,
EUNI, 5, /* Energy Units */
, 3,
TUNI, 4, /* Time Units */
Offset (0x958), /* PLATFORM_INFO */
, 40,
LFM_, 8, /* Maximum Efficiency Ratio (LFM) */
Offset (0x9a0), /* TURBO_POWER_LIMIT1 */
PL1V, 15, /* Power Limit 1 Value */
PL1E, 1, /* Power Limit 1 Enable */
PL1C, 1, /* Power Limit 1 Clamp */
PL1T, 7, /* Power Limit 1 Time */
Offset (0x9a4), /* TURBO_POWER_LIMIT2 */
PL2V, 15, /* Power Limit 2 Value */
PL2E, 1, /* Power Limit 2 Enable */
PL2C, 1, /* Power Limit 2 Clamp */
PL2T, 7, /* Power Limit 2 Time */
Offset (0xf3c), /* CONFIG_TDP_NOMINAL */
TARN, 8, /* CTDP Nominal Turbo Activation Ratio */
Offset (0xf40), /* CONFIG_TDP_LEVEL1 */
CTDD, 15, /* CTDP Down PL1 */
, 1,
TARD, 8, /* CTDP Down Turbo Activation Ratio */
Offset (0xf48), /* MSR_CONFIG_TDP_LEVEL2 */
CTDU, 15, /* CTDP Up PL1 */
, 1,
TARU, 8, /* CTDP Up Turbo Activation Ratio */
Offset (0xf50), /* CONFIG_TDP_CONTROL */
CTCS, 2, /* CTDP Select */
Offset (0xf54), /* TURBO_ACTIVATION_RATIO */
TARS, 8, /* Turbo Activation Ratio Select */
}
/*
* Search CPU0 _PSS looking for control=arg0 and then
* return previous P-state entry number for new _PPC
*
* Format of _PSS:
* Name (_PSS, Package () {
* Package (6) { freq, power, tlat, blat, control, status }
* }
*/
External (\_PR.CP00._PSS)
Method (PSSS, 1, NotSerialized)
{
Store (One, Local0) /* Start at P1 */
Store (SizeOf (\_PR.CP00._PSS), Local1)
While (LLess (Local0, Local1)) {
/* Store _PSS entry Control value to Local2 */
ShiftRight (DeRefOf (Index (DeRefOf (Index
(\_PR.CP00._PSS, Local0)), 4)), 8, Local2)
If (LEqual (Local2, Arg0)) {
Return (Subtract (Local0, 1))
}
Increment (Local0)
}
Return (0)
}
/* Calculate PL2 based on chip type */
Method (CPL2, 1, NotSerialized)
{
/* Haswell ULT PL2 = 25W */
/* FIXME: update for broadwell */
Return (Multiply (25, 8))
}
/* Set Config TDP Down */
Method (STND, 0, Serialized)
{
If (Acquire (CTCM, 100)) {
Return (0)
}
If (LEqual (CTCD, CTCC)) {
Release (CTCM)
Return (0)
}
Store ("Set TDP Down", Debug)
/* Set CTC */
Store (CTCD, CTCS)
/* Set TAR */
Store (TARD, TARS)
/* Set PPC limit and notify OS */
Store (PSSS (TARD), PPCM)
PPCN ()
/* Set PL2 */
Store (CPL2 (CTDD), PL2V)
/* Set PL1 */
Store (CTDD, PL1V)
/* Store the new TDP Down setting */
Store (CTCD, CTCC)
Release (CTCM)
Return (1)
}
/* Set Config TDP Nominal from Down */
Method (STDN, 0, Serialized)
{
If (Acquire (CTCM, 100)) {
Return (0)
}
If (LEqual (CTCN, CTCC)) {
Release (CTCM)
Return (0)
}
Store ("Set TDP Nominal", Debug)
/* Set PL1 */
Store (CTDN, PL1V)
/* Set PL2 */
Store (CPL2 (CTDN), PL2V)
/* Set PPC limit and notify OS */
Store (PSSS (TARN), PPCM)
PPCN ()
/* Set TAR */
Store (TARN, TARS)
/* Set CTC */
Store (CTCN, CTCS)
/* Store the new TDP Nominal setting */
Store (CTCN, CTCC)
Release (CTCM)
Return (1)
}
/* Calculate PL1 value based on requested TDP */
Method (TDPP, 1, NotSerialized)
{
Return (Multiply (ShiftLeft (Subtract (PUNI, 1), 2), Arg0))
}
/* Enable Controllable TDP to limit PL1 to requested value */
Method (CTLE, 1, Serialized)
{
If (Acquire (CTCM, 100)) {
Return (0)
}
Store ("Enable PL1 Limit", Debug)
/* Set _PPC to LFM */
Store (PSSS (LFM_), Local0)
Add (Local0, 1, PPCM)
\PPCN ()
/* Set TAR to LFM-1 */
Subtract (LFM_, 1, TARS)
/* Set PL1 to desired value */
Store (PL1V, SPL1)
Store (TDPP (Arg0), PL1V)
/* Set PL1 CLAMP bit */
Store (One, PL1C)
Release (CTCM)
Return (1)
}
/* Disable Controllable TDP */
Method (CTLD, 0, Serialized)
{
If (Acquire (CTCM, 100)) {
Return (0)
}
Store ("Disable PL1 Limit", Debug)
/* Clear PL1 CLAMP bit */
Store (Zero, PL1C)
/* Set PL1 to normal value */
Store (SPL1, PL1V)
/* Set TAR to 0 */
Store (Zero, TARS)
/* Set _PPC to 0 */
Store (Zero, PPCM)
\PPCN ()
Release (CTCM)
Return (1)
}
}

View File

@@ -0,0 +1,54 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
/* Device Enabled in ACPI Mode */
S0EN, 8, // DMA Enable
S1EN, 8, // I2C0 Enable
S2EN, 8, // I2C1 Enable
S3EN, 8, // SPI0 Enable
S4EN, 8, // SPI1 Enable
S5EN, 8, // UART0 Enable
S6EN, 8, // UART1 Enable
S7EN, 8, // SDIO Enable
S8EN, 8, // ADSP Enable
/* BAR 0 */
S0B0, 32, // DMA BAR0
S1B0, 32, // I2C0 BAR0
S2B0, 32, // I2C1 BAR0
S3B0, 32, // SPI0 BAR0
S4B0, 32, // SPI1 BAR0
S5B0, 32, // UART0 BAR0
S6B0, 32, // UART1 BAR0
S7B0, 32, // SDIO BAR0
S8B0, 32, // ADSP BAR0
/* BAR 1 */
S0B1, 32, // DMA BAR1
S1B1, 32, // I2C0 BAR1
S2B1, 32, // I2C1 BAR1
S3B1, 32, // SPI0 BAR1
S4B1, 32, // SPI1 BAR1
S5B1, 32, // UART0 BAR1
S6B1, 32, // UART1 BAR1
S7B1, 32, // SDIO BAR1
S8B1, 32, // ADSP BAR1

View File

@@ -0,0 +1,51 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
// EHCI Controller 0:1d.0
Device (EHCI)
{
Name(_ADR, 0x001d0000)
Name (_PRW, Package(){ 0x6d, 3 })
// Leave USB ports on for to allow Wake from USB
Method(_S3D,0) // Highest D State in S3 State
{
Return (2)
}
Method(_S4D,0) // Highest D State in S4 State
{
Return (2)
}
Device (HUB7)
{
Name (_ADR, 0x00000000)
// How many are there?
Device (PRT1) { Name (_ADR, 1) } // USB Port 0
Device (PRT2) { Name (_ADR, 2) } // USB Port 1
Device (PRT3) { Name (_ADR, 3) } // USB Port 2
Device (PRT4) { Name (_ADR, 4) } // USB Port 3
Device (PRT5) { Name (_ADR, 5) } // USB Port 4
Device (PRT6) { Name (_ADR, 6) } // USB Port 5
}
}

View File

@@ -0,0 +1,109 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
/*
* 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.
*/
External(NVSA)
OperationRegion (GNVS, SystemMemory, NVSA, 0x2000)
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
PCNT, 8, // 0x0b - Processor Count
PPCM, 8, // 0x0c - Max PPC State
TMPS, 8, // 0x0d - Temperature Sensor ID
TLVL, 8, // 0x0e - Throttle Level Limit
FLVL, 8, // 0x0f - Current FAN Level
TCRT, 8, // 0x10 - Critical Threshold
TPSV, 8, // 0x11 - Passive Threshold
TMAX, 8, // 0x12 - CPU Tj_max
S5U0, 8, // 0x13 - Enable USB in S5
S3U0, 8, // 0x14 - Enable USB in S3
S33G, 8, // 0x15 - Enable 3G in S3
LIDS, 8, // 0x16 - LID State
PWRS, 8, // 0x17 - AC Power State
CMEM, 32, // 0x18 - 0x1b - CBMEM TOC
CBMC, 32, // 0x1c - 0x1f - Coreboot Memory Console
PM1I, 64, // 0x20 - 0x27 - PM1 wake status bit
GPEI, 64, // 0x28 - 0x2f - GPE wake status bit
/* ChromeOS specific */
Offset (0x100),
#include <vendorcode/google/chromeos/acpi/gnvs.asl>
/* Device specific */
Offset (0x1000),
#include "device_nvs.asl"
}
/* Set flag to enable USB charging in S3 */
Method (S3UE)
{
Store (One, \S3U0)
}
/* Set flag to disable USB charging in S3 */
Method (S3UD)
{
Store (Zero, \S3U0)
}
/* Set flag to enable USB charging in S5 */
Method (S5UE)
{
Store (One, \S5U0)
}
/* Set flag to disable USB charging in S5 */
Method (S5UD)
{
Store (Zero, \S5U0)
}
/* Set flag to enable 3G module in S3 */
Method (S3GE)
{
Store (One, \S33G)
}
/* Set flag to disable 3G module in S3 */
Method (S3GD)
{
Store (Zero, \S33G)
}

View File

@@ -0,0 +1,142 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
Device (GPIO)
{
// GPIO Controller
Method (_HID)
{
If (\ISWP ()) {
// WildcatPoint
Return ("INT3437")
}
// LynxPoint-LP
Return ("INT33C7")
}
Name (_UID, 1)
Name (RBUF, ResourceTemplate()
{
DWordIo (ResourceProducer,
MinFixed, // IsMinFixed
MaxFixed, // IsMaxFixed
PosDecode, // Decode
EntireRange, // ISARanges
0x00000000, // AddressGranularity
0x00000000, // AddressMinimum
0x00000000, // AddressMaximum
0x00000000, // AddressTranslation
0x00000000, // RangeLength
, // ResourceSourceIndex
, // ResourceSource
BAR0)
// Disabled due to IRQ storm: http://crosbug.com/p/29548
//Interrupt (ResourceConsumer,
// Level, ActiveHigh, Shared, , , ) {14}
})
Method (_CRS, 0, NotSerialized)
{
CreateDwordField (^RBUF, ^BAR0._MIN, BMIN)
CreateDwordField (^RBUF, ^BAR0._MAX, BMAX)
CreateDwordField (^RBUF, ^BAR0._LEN, BLEN)
Store (GPIO_BASE_SIZE, BLEN)
Store (GPIO_BASE_ADDRESS, BMIN)
Store (Subtract (Add (GPIO_BASE_ADDRESS,
GPIO_BASE_SIZE), 1), BMAX)
Return (RBUF)
}
Method (_STA, 0, NotSerialized)
{
Return (0xF)
}
// GWAK: Setup GPIO as ACPI GPE for Wake
// Arg0: GPIO Number
Method (GWAK, 1, NotSerialized)
{
// Local0 = GPIO Base Address
Store (And (GPBS, Not(0x1)), Local0)
// Local1 = BANK, Local2 = OFFSET
Divide (Arg0, 32, Local2, Local1)
//
// Set OWNER to ACPI
//
// Local3 = GPIOBASE + GPIO_OWN(BANK)
Store (Add (Local0, Multiply (Local1, 0x4)), Local3)
// GPIO_OWN(BANK)
OperationRegion (IOWN, SystemIO, Local3, 4)
Field (IOWN, AnyAcc, NoLock, Preserve) {
GOWN, 32,
}
// GPIO_OWN[GPIO] = 0 (ACPI)
Store (And (GOWN, Not (ShiftLeft (0x1, Local2))), GOWN)
//
// Set ROUTE to SCI
//
// Local3 = GPIOBASE + GPIO_ROUTE(BANK)
Store (Add (Add (Local0, 0x30), Multiply (Local1, 0x4)), Local3)
// GPIO_ROUTE(BANK)
OperationRegion (IROU, SystemIO, Local3, 4)
Field (IROU, AnyAcc, NoLock, Preserve) {
GROU, 32,
}
// GPIO_ROUTE[GPIO] = 0 (SCI)
Store (And (GROU, Not (ShiftLeft (0x1, Local2))), GROU)
//
// Set GPnCONFIG to GPIO|INPUT|INVERT
//
// Local3 = GPIOBASE + GPnCONFIG0(GPIO)
Store (Add (Add (Local0, 0x100), Multiply (Arg0, 0x8)), Local3)
// GPnCONFIG(GPIO)
OperationRegion (GPNC, SystemIO, Local3, 8)
Field (GPNC, AnyAcc, NoLock, Preserve) {
GMOD, 1, // MODE: 0=NATIVE 1=GPIO
, 1,
GIOS, 1, // IO_SEL: 0=OUTPUT 1=INPUT
GINV, 1, // INVERT: 0=NORMAL 1=INVERT
GLES, 1, // LxEB: 0=EDGE 1=LEVEL
, 24,
ILVL, 1, // INPUT: 0=LOW 1=HIGH
OLVL, 1, // OUTPUT: 0=LOW 1=HIGH
GPWP, 2, // PULLUP: 00=NONE 01=DOWN 10=UP 11=INVALID
ISEN, 1, // SENSE: 0=ENABLE 1=DISABLE
}
Store (0x1, GMOD) // GPIO
Store (0x1, GIOS) // INPUT
Store (0x1, GINV) // INVERT
}
}

View File

@@ -0,0 +1,29 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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 PCH HDA */
// Intel High Definition Audio (Azalia) 0:1b.0
Device (HDEF)
{
Name (_ADR, 0x001b0000)
Name (_PRW, Package () { 0x6d, 3 })
}

View File

@@ -0,0 +1,492 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
Device (LNKA)
{
Name (_HID, EISAID("PNP0C0F"))
Name (_UID, 1)
// Disable method
Method (_DIS, 0, Serialized)
{
Store (0x80, PRTA)
}
// Possible Resource Settings for this Link
Name (_PRS, ResourceTemplate()
{
IRQ (Level, ActiveLow, Shared)
{ 3, 4, 5, 6, 7, 10, 12, 14, 15 }
})
// Current Resource Settings for this link
Method (_CRS, 0, Serialized)
{
Name (RTLA, ResourceTemplate()
{
IRQ (Level, ActiveLow, Shared) {}
})
CreateWordField (RTLA, 1, IRQ0)
// Clear the WordField
Store (Zero, IRQ0)
// Set the bit from PRTA
ShiftLeft (1, And (PRTA, 0x0f), IRQ0)
Return (RTLA)
}
// Set Resource Setting for this IRQ link
Method (_SRS, 1, Serialized)
{
CreateWordField (Arg0, 1, IRQ0)
// Which bit is set?
FindSetRightBit (IRQ0, Local0)
Decrement(Local0)
Store (Local0, PRTA)
}
// Status
Method (_STA, 0, Serialized)
{
If(And (PRTA, 0x80)) {
Return (0x9)
} Else {
Return (0xb)
}
}
}
Device (LNKB)
{
Name (_HID, EISAID("PNP0C0F"))
Name (_UID, 2)
// Disable method
Method (_DIS, 0, Serialized)
{
Store (0x80, PRTB)
}
// Possible Resource Settings for this Link
Name (_PRS, ResourceTemplate()
{
IRQ (Level, ActiveLow, Shared)
{ 3, 4, 5, 6, 7, 11, 12, 14, 15 }
})
// Current Resource Settings for this link
Method (_CRS, 0, Serialized)
{
Name (RTLB, ResourceTemplate()
{
IRQ (Level, ActiveLow, Shared) {}
})
CreateWordField (RTLB, 1, IRQ0)
// Clear the WordField
Store (Zero, IRQ0)
// Set the bit from PRTB
ShiftLeft (1, And (PRTB, 0x0f), IRQ0)
Return (RTLB)
}
// Set Resource Setting for this IRQ link
Method (_SRS, 1, Serialized)
{
CreateWordField (Arg0, 1, IRQ0)
// Which bit is set?
FindSetRightBit (IRQ0, Local0)
Decrement(Local0)
Store (Local0, PRTB)
}
// Status
Method (_STA, 0, Serialized)
{
If(And (PRTB, 0x80)) {
Return (0x9)
} Else {
Return (0xb)
}
}
}
Device (LNKC)
{
Name (_HID, EISAID("PNP0C0F"))
Name (_UID, 3)
// Disable method
Method (_DIS, 0, Serialized)
{
Store (0x80, PRTC)
}
// Possible Resource Settings for this Link
Name (_PRS, ResourceTemplate()
{
IRQ (Level, ActiveLow, Shared)
{ 3, 4, 5, 6, 7, 10, 12, 14, 15 }
})
// Current Resource Settings for this link
Method (_CRS, 0, Serialized)
{
Name (RTLC, ResourceTemplate()
{
IRQ (Level, ActiveLow, Shared) {}
})
CreateWordField (RTLC, 1, IRQ0)
// Clear the WordField
Store (Zero, IRQ0)
// Set the bit from PRTC
ShiftLeft (1, And (PRTC, 0x0f), IRQ0)
Return (RTLC)
}
// Set Resource Setting for this IRQ link
Method (_SRS, 1, Serialized)
{
CreateWordField (Arg0, 1, IRQ0)
// Which bit is set?
FindSetRightBit (IRQ0, Local0)
Decrement(Local0)
Store (Local0, PRTC)
}
// Status
Method (_STA, 0, Serialized)
{
If(And (PRTC, 0x80)) {
Return (0x9)
} Else {
Return (0xb)
}
}
}
Device (LNKD)
{
Name (_HID, EISAID("PNP0C0F"))
Name (_UID, 4)
// Disable method
Method (_DIS, 0, Serialized)
{
Store (0x80, PRTD)
}
// Possible Resource Settings for this Link
Name (_PRS, ResourceTemplate()
{
IRQ (Level, ActiveLow, Shared)
{ 3, 4, 5, 6, 7, 11, 12, 14, 15 }
})
// Current Resource Settings for this link
Method (_CRS, 0, Serialized)
{
Name (RTLD, ResourceTemplate()
{
IRQ (Level, ActiveLow, Shared) {}
})
CreateWordField (RTLD, 1, IRQ0)
// Clear the WordField
Store (Zero, IRQ0)
// Set the bit from PRTD
ShiftLeft (1, And (PRTD, 0x0f), IRQ0)
Return (RTLD)
}
// Set Resource Setting for this IRQ link
Method (_SRS, 1, Serialized)
{
CreateWordField (Arg0, 1, IRQ0)
// Which bit is set?
FindSetRightBit (IRQ0, Local0)
Decrement(Local0)
Store (Local0, PRTD)
}
// Status
Method (_STA, 0, Serialized)
{
If(And (PRTD, 0x80)) {
Return (0x9)
} Else {
Return (0xb)
}
}
}
Device (LNKE)
{
Name (_HID, EISAID("PNP0C0F"))
Name (_UID, 5)
// Disable method
Method (_DIS, 0, Serialized)
{
Store (0x80, PRTE)
}
// Possible Resource Settings for this Link
Name (_PRS, ResourceTemplate()
{
IRQ (Level, ActiveLow, Shared)
{ 3, 4, 5, 6, 7, 10, 12, 14, 15 }
})
// Current Resource Settings for this link
Method (_CRS, 0, Serialized)
{
Name (RTLE, ResourceTemplate()
{
IRQ (Level, ActiveLow, Shared) {}
})
CreateWordField (RTLE, 1, IRQ0)
// Clear the WordField
Store (Zero, IRQ0)
// Set the bit from PRTE
ShiftLeft (1, And (PRTE, 0x0f), IRQ0)
Return (RTLE)
}
// Set Resource Setting for this IRQ link
Method (_SRS, 1, Serialized)
{
CreateWordField (Arg0, 1, IRQ0)
// Which bit is set?
FindSetRightBit (IRQ0, Local0)
Decrement(Local0)
Store (Local0, PRTE)
}
// Status
Method (_STA, 0, Serialized)
{
If(And (PRTE, 0x80)) {
Return (0x9)
} Else {
Return (0xb)
}
}
}
Device (LNKF)
{
Name (_HID, EISAID("PNP0C0F"))
Name (_UID, 6)
// Disable method
Method (_DIS, 0, Serialized)
{
Store (0x80, PRTF)
}
// Possible Resource Settings for this Link
Name (_PRS, ResourceTemplate()
{
IRQ (Level, ActiveLow, Shared)
{ 3, 4, 5, 6, 7, 11, 12, 14, 15 }
})
// Current Resource Settings for this link
Method (_CRS, 0, Serialized)
{
Name (RTLF, ResourceTemplate()
{
IRQ (Level, ActiveLow, Shared) {}
})
CreateWordField (RTLF, 1, IRQ0)
// Clear the WordField
Store (Zero, IRQ0)
// Set the bit from PRTF
ShiftLeft (1, And (PRTF, 0x0f), IRQ0)
Return (RTLF)
}
// Set Resource Setting for this IRQ link
Method (_SRS, 1, Serialized)
{
CreateWordField (Arg0, 1, IRQ0)
// Which bit is set?
FindSetRightBit (IRQ0, Local0)
Decrement(Local0)
Store (Local0, PRTF)
}
// Status
Method (_STA, 0, Serialized)
{
If(And (PRTF, 0x80)) {
Return (0x9)
} Else {
Return (0xb)
}
}
}
Device (LNKG)
{
Name (_HID, EISAID("PNP0C0F"))
Name (_UID, 7)
// Disable method
Method (_DIS, 0, Serialized)
{
Store (0x80, PRTG)
}
// Possible Resource Settings for this Link
Name (_PRS, ResourceTemplate()
{
IRQ (Level, ActiveLow, Shared)
{ 3, 4, 5, 6, 7, 10, 12, 14, 15 }
})
// Current Resource Settings for this link
Method (_CRS, 0, Serialized)
{
Name (RTLG, ResourceTemplate()
{
IRQ (Level, ActiveLow, Shared) {}
})
CreateWordField (RTLG, 1, IRQ0)
// Clear the WordField
Store (Zero, IRQ0)
// Set the bit from PRTG
ShiftLeft (1, And (PRTG, 0x0f), IRQ0)
Return (RTLG)
}
// Set Resource Setting for this IRQ link
Method (_SRS, 1, Serialized)
{
CreateWordField (Arg0, 1, IRQ0)
// Which bit is set?
FindSetRightBit (IRQ0, Local0)
Decrement(Local0)
Store (Local0, PRTG)
}
// Status
Method (_STA, 0, Serialized)
{
If(And (PRTG, 0x80)) {
Return (0x9)
} Else {
Return (0xb)
}
}
}
Device (LNKH)
{
Name (_HID, EISAID("PNP0C0F"))
Name (_UID, 8)
// Disable method
Method (_DIS, 0, Serialized)
{
Store (0x80, PRTH)
}
// Possible Resource Settings for this Link
Name (_PRS, ResourceTemplate()
{
IRQ (Level, ActiveLow, Shared)
{ 3, 4, 5, 6, 7, 11, 12, 14, 15 }
})
// Current Resource Settings for this link
Method (_CRS, 0, Serialized)
{
Name (RTLH, ResourceTemplate()
{
IRQ (Level, ActiveLow, Shared) {}
})
CreateWordField (RTLH, 1, IRQ0)
// Clear the WordField
Store (Zero, IRQ0)
// Set the bit from PRTH
ShiftLeft (1, And (PRTH, 0x0f), IRQ0)
Return (RTLH)
}
// Set Resource Setting for this IRQ link
Method (_SRS, 1, Serialized)
{
CreateWordField (Arg0, 1, IRQ0)
// Which bit is set?
FindSetRightBit (IRQ0, Local0)
Decrement(Local0)
Store (Local0, PRTH)
}
// Status
Method (_STA, 0, Serialized)
{
If(And (PRTH, 0x80)) {
Return (0x9)
} Else {
Return (0xb)
}
}
}

View File

@@ -0,0 +1,208 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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 LPC Bus Device - 0:1f.0
Device (LPCB)
{
Name (_ADR, 0x001f0000)
OperationRegion(LPC0, PCI_Config, 0x00, 0x100)
Field (LPC0, AnyAcc, NoLock, Preserve)
{
Offset (0x02),
PDID, 16, // Device ID
Offset (0x40),
PMBS, 16, // PMBASE
Offset (0x48),
GPBS, 16, // GPIOBASE
Offset (0x60), // Interrupt Routing Registers
PRTA, 8,
PRTB, 8,
PRTC, 8,
PRTD, 8,
Offset (0x68),
PRTE, 8,
PRTF, 8,
PRTG, 8,
PRTH, 8,
Offset (0x80), // IO Decode Ranges
IOD0, 8,
IOD1, 8,
}
Device (DMAC) // DMA Controller
{
Name (_HID, EISAID("PNP0200"))
Name (_CRS, ResourceTemplate()
{
IO (Decode16, 0x00, 0x00, 0x01, 0x20)
IO (Decode16, 0x81, 0x81, 0x01, 0x11)
IO (Decode16, 0x93, 0x93, 0x01, 0x0d)
IO (Decode16, 0xc0, 0xc0, 0x01, 0x20)
DMA (Compatibility, NotBusMaster, Transfer8_16) { 4 }
})
}
Device (FWH) // Firmware Hub
{
Name (_HID, EISAID("INT0800"))
Name (_CRS, ResourceTemplate()
{
Memory32Fixed(ReadOnly, 0xff000000, 0x01000000)
})
}
Device (HPET)
{
Name (_HID, EISAID("PNP0103"))
Name (_CID, 0x010CD041)
Name (BUF0, ResourceTemplate()
{
Memory32Fixed(ReadOnly, 0xfed00000, 0x400, FED0)
})
Method (_STA, 0) // Device Status
{
If (HPTE) {
// Note: Ancient versions of Windows don't want
// to see the HPET in order to work right
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) // Current resources
{
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)
}
}
Device(PIC) // 8259 Interrupt Controller
{
Name (_HID,EISAID("PNP0000"))
Name (_CRS, ResourceTemplate()
{
IO (Decode16, 0x20, 0x20, 0x01, 0x02)
IO (Decode16, 0x24, 0x24, 0x01, 0x02)
IO (Decode16, 0x28, 0x28, 0x01, 0x02)
IO (Decode16, 0x2c, 0x2c, 0x01, 0x02)
IO (Decode16, 0x30, 0x30, 0x01, 0x02)
IO (Decode16, 0x34, 0x34, 0x01, 0x02)
IO (Decode16, 0x38, 0x38, 0x01, 0x02)
IO (Decode16, 0x3c, 0x3c, 0x01, 0x02)
IO (Decode16, 0xa0, 0xa0, 0x01, 0x02)
IO (Decode16, 0xa4, 0xa4, 0x01, 0x02)
IO (Decode16, 0xa8, 0xa8, 0x01, 0x02)
IO (Decode16, 0xac, 0xac, 0x01, 0x02)
IO (Decode16, 0xb0, 0xb0, 0x01, 0x02)
IO (Decode16, 0xb4, 0xb4, 0x01, 0x02)
IO (Decode16, 0xb8, 0xb8, 0x01, 0x02)
IO (Decode16, 0xbc, 0xbc, 0x01, 0x02)
IO (Decode16, 0x4d0, 0x4d0, 0x01, 0x02)
IRQNoFlags () { 2 }
})
}
Device(MATH) // FPU
{
Name (_HID, EISAID("PNP0C04"))
Name (_CRS, ResourceTemplate()
{
IO (Decode16, 0xf0, 0xf0, 0x01, 0x01)
IRQNoFlags() { 13 }
})
}
Device(LDRC) // LPC device: Resource consumption
{
Name (_HID, EISAID("PNP0C02"))
Name (_UID, 2)
Name (RBUF, ResourceTemplate()
{
IO (Decode16, 0x2e, 0x2e, 0x1, 0x02) // First SuperIO
IO (Decode16, 0x4e, 0x4e, 0x1, 0x02) // Second SuperIO
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, ACPI_BASE_ADDRESS, ACPI_BASE_ADDRESS,
0x1, 0xff)
})
Method (_CRS, 0, NotSerialized)
{
Return (RBUF)
}
}
Device (RTC) // Real Time Clock
{
Name (_HID, EISAID("PNP0B00"))
Name (_CRS, ResourceTemplate()
{
IO (Decode16, 0x70, 0x70, 1, 8)
//IRQNoFlags() { 8 }
})
}
Device (TIMR) // Intel 8254 timer
{
Name (_HID, EISAID("PNP0100"))
Name (_CRS, ResourceTemplate() {
IO (Decode16, 0x40, 0x40, 0x01, 0x04)
IO (Decode16, 0x50, 0x50, 0x10, 0x04)
IRQNoFlags() {0}
})
}
#include "gpio.asl"
#include "irqlinks.asl"
#include <acpi/ec.asl>
#include <acpi/superio.asl>
}

View File

@@ -0,0 +1,101 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <soc/iomap.h>
Scope (\)
{
// IO-Trap at 0x800. This is the ACPI->SMI communication interface.
OperationRegion (IO_T, SystemIO, 0x800, 0x10)
Field (IO_T, ByteAcc, NoLock, Preserve)
{
Offset (0x8),
TRP0, 8 // IO-Trap at 0x808
}
// Root Complex Register Block
OperationRegion (RCRB, SystemMemory, RCBA_BASE_ADDRESS, RCBA_BASE_SIZE)
Field (RCRB, DWordAcc, Lock, Preserve)
{
Offset (0x3404), // High Performance Timer Configuration
HPAS, 2, // Address Select
, 5,
HPTE, 1, // Address Enable
}
/*
* Check PCH type
* Return 1 if PCH is WildcatPoint
* Return 0 if PCH is LynxPoint
*/
Method (ISWP)
{
And (\_SB.PCI0.LPCB.PDID, 0xfff0, Local0)
If (LEqual (Local0, 0x9cc0)) {
Return (1)
} Else {
Return (0)
}
}
}
// High Definition Audio (Azalia) 0:1b.0
#include "hda.asl"
// ADSP/SST 0:13.0
#include "adsp.asl"
// PCI Express Ports 0:1c.x
#include "pcie.asl"
// USB EHCI 0:1d.0
#include "ehci.asl"
// USB XHCI 0:14.0
#include "xhci.asl"
// LPC Bridge 0:1f.0
#include "lpc.asl"
// SATA 0:1f.2
#include "sata.asl"
// SMBus 0:1f.3
#include "smbus.asl"
// Serial IO
#include "serialio.asl"
Method (_OSC, 4)
{
/* Check for proper GUID */
If (LEqual (Arg0, ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766")))
{
/* Let OS control everything */
Return (Arg3)
}
Else
{
/* Unrecognized UUID */
CreateDWordField (Arg3, 0, CDW1)
Or (CDW1, 4, CDW1)
Return (Arg3)
}
}

View File

@@ -0,0 +1,89 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
Method(_PRT)
{
If (PICM) {
Return (Package() {
// Onboard graphics (IGD) 0:2.0
Package() { 0x0002ffff, 0, 0, 16 },
// Mini-HD Audio 0:3.0
Package() { 0x0003ffff, 0, 0, 16 },
// High Definition Audio 0:1b.0
Package() { 0x001bffff, 0, 0, 22 },
// PCIe Root Ports 0:1c.x
Package() { 0x001cffff, 0, 0, 16 },
Package() { 0x001cffff, 1, 0, 17 },
Package() { 0x001cffff, 2, 0, 18 },
Package() { 0x001cffff, 3, 0, 19 },
// EHCI 0:1d.0
Package() { 0x001dffff, 0, 0, 19 },
// Audio DSP (Smart Sound) 0:13.0
Package() { 0x0013ffff, 0, 0, 23 },
// XHCI 0:14.0
Package() { 0x0014ffff, 0, 0, 18 },
// LPC devices 0:1f.0
Package() { 0x001fffff, 0, 0, 22 },
Package() { 0x001fffff, 1, 0, 18 },
Package() { 0x001fffff, 2, 0, 17 },
Package() { 0x001fffff, 3, 0, 16 },
// Serial IO 0:15.0
Package() { 0x0015ffff, 0, 0, 20 },
Package() { 0x0015ffff, 1, 0, 21 },
Package() { 0x0015ffff, 2, 0, 21 },
Package() { 0x0015ffff, 3, 0, 21 },
// SDIO 0:17.0
Package() { 0x0017ffff, 0, 0, 23 },
})
} Else {
Return (Package() {
// Onboard graphics (IGD) 0:2.0
Package() { 0x0002ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },
// Mini-HD Audio 0:3.0
Package() { 0x0003ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },
// High Definition Audio 0:1b.0
Package() { 0x001bffff, 0, \_SB.PCI0.LPCB.LNKG, 0 },
// PCIe Root Ports 0:1c.x
Package() { 0x001cffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },
Package() { 0x001cffff, 1, \_SB.PCI0.LPCB.LNKB, 0 },
Package() { 0x001cffff, 2, \_SB.PCI0.LPCB.LNKC, 0 },
Package() { 0x001cffff, 3, \_SB.PCI0.LPCB.LNKD, 0 },
// EHCI 0:1d.0
Package() { 0x001dffff, 0, \_SB.PCI0.LPCB.LNKD, 0 },
// Audio DSP (Smart Sound) 0:13.0
Package() { 0x0013ffff, 0, \_SB.PCI0.LPCB.LNKH, 0 },
// XHCI 0:14.0
Package() { 0x0014ffff, 0, \_SB.PCI0.LPCB.LNKC, 0 },
// LPC device 0:1f.0
Package() { 0x001fffff, 0, \_SB.PCI0.LPCB.LNKG, 0 },
Package() { 0x001fffff, 1, \_SB.PCI0.LPCB.LNKC, 0 },
Package() { 0x001fffff, 2, \_SB.PCI0.LPCB.LNKB, 0 },
Package() { 0x001fffff, 3, \_SB.PCI0.LPCB.LNKA, 0 },
// Serial IO 0:15.0
Package() { 0x0015ffff, 0, \_SB.PCI0.LPCB.LNKE, 0 },
Package() { 0x0015ffff, 1, \_SB.PCI0.LPCB.LNKF, 0 },
Package() { 0x0015ffff, 2, \_SB.PCI0.LPCB.LNKF, 0 },
Package() { 0x0015ffff, 3, \_SB.PCI0.LPCB.LNKF, 0 },
// SDIO 0:17.0
Package() { 0x0017ffff, 0, \_SB.PCI0.LPCB.LNKH, 0 },
})
}
}

View File

@@ -0,0 +1,214 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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 PCH PCIe support */
Method (IRQM, 1, Serialized) {
/* Interrupt Map INTA->INTA, INTB->INTB, INTC->INTC, INTD->INTD */
Name (IQAA, Package() {
Package() { 0x0000ffff, 0, 0, 16 },
Package() { 0x0000ffff, 1, 0, 17 },
Package() { 0x0000ffff, 2, 0, 18 },
Package() { 0x0000ffff, 3, 0, 19 } })
Name (IQAP, Package() {
Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },
Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKB, 0 },
Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKC, 0 },
Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKD, 0 } })
/* Interrupt Map INTA->INTB, INTB->INTC, INTC->INTD, INTD->INTA */
Name (IQBA, Package() {
Package() { 0x0000ffff, 0, 0, 17 },
Package() { 0x0000ffff, 1, 0, 18 },
Package() { 0x0000ffff, 2, 0, 19 },
Package() { 0x0000ffff, 3, 0, 16 } })
Name (IQBP, Package() {
Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKB, 0 },
Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKC, 0 },
Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKD, 0 },
Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKA, 0 } })
/* Interrupt Map INTA->INTC, INTB->INTD, INTC->INTA, INTD->INTB */
Name (IQCA, Package() {
Package() { 0x0000ffff, 0, 0, 18 },
Package() { 0x0000ffff, 1, 0, 19 },
Package() { 0x0000ffff, 2, 0, 16 },
Package() { 0x0000ffff, 3, 0, 17 } })
Name (IQCP, Package() {
Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKC, 0 },
Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKD, 0 },
Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKA, 0 },
Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKB, 0 } })
/* Interrupt Map INTA->INTD, INTB->INTA, INTC->INTB, INTD->INTC */
Name (IQDA, Package() {
Package() { 0x0000ffff, 0, 0, 19 },
Package() { 0x0000ffff, 1, 0, 16 },
Package() { 0x0000ffff, 2, 0, 17 },
Package() { 0x0000ffff, 3, 0, 18 } })
Name (IQDP, Package() {
Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKD, 0 },
Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKA, 0 },
Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKB, 0 },
Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKC, 0 } })
Switch (ToInteger (Arg0)) {
/* PCIe Root Port 1 and 5 */
Case (Package() { 1, 5 }) {
If (PICM) {
Return (IQAA)
} Else {
Return (IQAP)
}
}
/* PCIe Root Port 2 and 6 */
Case (Package() { 2, 6 }) {
If (PICM) {
Return (IQBA)
} Else {
Return (IQBP)
}
}
/* PCIe Root Port 3 and 7 */
Case (Package() { 3, 7 }) {
If (PICM) {
Return (IQCA)
} Else {
Return (IQCP)
}
}
/* PCIe Root Port 4 and 8 */
Case (Package() { 4, 8 }) {
If (PICM) {
Return (IQDA)
} Else {
Return (IQDP)
}
}
Default {
If (PICM) {
Return (IQDA)
} Else {
Return (IQDP)
}
}
}
}
Device (RP01)
{
Name (_ADR, 0x001c0000)
#include "pcie_port.asl"
Method (_PRT)
{
Return (IRQM (RPPN))
}
}
Device (RP02)
{
Name (_ADR, 0x001c0001)
#include "pcie_port.asl"
Method (_PRT)
{
Return (IRQM (RPPN))
}
}
Device (RP03)
{
Name (_ADR, 0x001c0002)
#include "pcie_port.asl"
Method (_PRT)
{
Return (IRQM (RPPN))
}
}
Device (RP04)
{
Name (_ADR, 0x001c0003)
#include "pcie_port.asl"
Method (_PRT)
{
Return (IRQM (RPPN))
}
}
Device (RP05)
{
Name (_ADR, 0x001c0004)
#include "pcie_port.asl"
Method (_PRT)
{
Return (IRQM (RPPN))
}
}
Device (RP06)
{
Name (_ADR, 0x001c0005)
#include "pcie_port.asl"
Method (_PRT)
{
Return (IRQM (RPPN))
}
}
Device (RP07)
{
Name (_ADR, 0x001c0006)
#include "pcie_port.asl"
Method (_PRT)
{
Return (IRQM (RPPN))
}
}
Device (RP08)
{
Name (_ADR, 0x001c0007)
#include "pcie_port.asl"
Method (_PRT)
{
Return (IRQM (RPPN))
}
}

View File

@@ -0,0 +1,28 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
/* Included in each PCIe Root Port device */
OperationRegion (RPCS, PCI_Config, 0x00, 0xFF)
Field (RPCS, AnyAcc, NoLock, Preserve)
{
Offset (0x4c), // Link Capabilities
, 24,
RPPN, 8, // Root Port Number
}

View File

@@ -0,0 +1,91 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
/* The APM port can be used for generating software SMIs */
OperationRegion (APMP, SystemIO, 0xb2, 2)
Field (APMP, ByteAcc, NoLock, Preserve)
{
APMC, 8, // APM command
APMS, 8 // APM status
}
/* Port 80 POST */
OperationRegion (POST, SystemIO, 0x80, 1)
Field (POST, ByteAcc, Lock, Preserve)
{
DBG0, 8
}
/* SMI I/O Trap */
Method (TRAP, 1, Serialized)
{
Store (Arg0, SMIF) // SMI Function
Store (0, TRP0) // Generate trap
Return (SMIF) // Return value of SMI handler
}
/* The _PIC method is called by the OS to choose between interrupt
* routing via the i8259 interrupt controller or the APIC.
*
* _PIC is called with a parameter of 0 for i8259 configuration and
* with a parameter of 1 for Local Apic/IOAPIC configuration.
*/
Method (_PIC, 1)
{
/* Remember the OS' IRQ routing choice. */
Store (Arg0, PICM)
}
/*
* The _PTS method (Prepare To Sleep) is called before the OS is
* entering a sleep state. The sleep state number is passed in Arg0
*/
Method (_PTS, 1)
{
}
/* The _WAK method is called on system wakeup */
Method (_WAK, 1)
{
Return (Package (){ 0, 0 })
}
Scope (\_SB)
{
Method (_SWS)
{
/* Index into PM1 for device that caused wake */
Return (\PM1I)
}
}
Scope (\_GPE)
{
Method (_SWS)
{
/* Index into GPE for device that caused wake */
Return (\GPEI)
}
}

View File

@@ -0,0 +1,25 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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 SATA Controller 0:1f.2
Device (SATA)
{
Name (_ADR, 0x001f0002)
}

View File

@@ -0,0 +1,627 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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 Serial IO Devices in ACPI Mode
// Serial IO Device BAR0 and BAR1 is 4KB
#define SIO_BAR_LEN 0x1000
// Put SerialIO device in D0 state
// Arg0 - BAR1 of device
// Arg1 - Set if device is in ACPI mode
Method (LPD0, 2, Serialized)
{
// PCI mode devices will be handled by OS PCI bus driver
If (LEqual (Arg1, 0)) {
Return
}
OperationRegion (SPRT, SystemMemory, Add (Arg0, 0x84), 4)
Field (SPRT, DWordAcc, NoLock, Preserve)
{
SPCS, 32
}
And (SPCS, 0xFFFFFFFC, SPCS)
Store (SPCS, Local0) // Read back after writing
}
// Put SerialIO device in D3 state
// Arg0 - BAR1 of device
// Arg1 - Set if device is in ACPI mode
Method (LPD3, 2, Serialized)
{
// PCI mode devices will be handled by OS PCI bus driver
If (LEqual (Arg1, 0)) {
Return
}
OperationRegion (SPRT, SystemMemory, Add (Arg0, 0x84), 4)
Field (SPRT, DWordAcc, NoLock, Preserve)
{
SPCS, 32
}
Or (SPCS, 0x3, SPCS)
Store (SPCS, Local0) // Read back after writing
}
// Serial IO Resource Consumption for BAR1
Device (SIOR)
{
Name (_HID, EISAID("PNP0C02"))
Name (_UID, 4)
Name (RBUF, ResourceTemplate()
{
// Serial IO BAR1 (PCI config space) resources
Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, B1D0) // SDMA
Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, B1D1) // I2C0
Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, B1D2) // I2C1
Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, B1D3) // SPI0
Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, B1D4) // SPI1
Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, B1D5) // UART0
Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, B1D6) // UART1
Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, B1D7) // SDIO
})
// Update BAR1 address and length if set in NVS
Method (_CRS, 0, NotSerialized)
{
// SDMA
If (LNotEqual (\S0B1, Zero)) {
CreateDwordField (^RBUF, ^B1D0._BAS, B0AD)
CreateDwordField (^RBUF, ^B1D0._LEN, B0LN)
Store (\S0B1, B0AD)
Store (SIO_BAR_LEN, B0LN)
}
// I2C0
If (LNotEqual (\S1B1, Zero)) {
CreateDwordField (^RBUF, ^B1D1._BAS, B1AD)
CreateDwordField (^RBUF, ^B1D1._LEN, B1LN)
Store (\S1B1, B1AD)
Store (SIO_BAR_LEN, B1LN)
}
// I2C1
If (LNotEqual (\S2B1, Zero)) {
CreateDwordField (^RBUF, ^B1D2._BAS, B2AD)
CreateDwordField (^RBUF, ^B1D2._LEN, B2LN)
Store (\S2B1, B2AD)
Store (SIO_BAR_LEN, B2LN)
}
// SPI0
If (LNotEqual (\S3B1, Zero)) {
CreateDwordField (^RBUF, ^B1D3._BAS, B3AD)
CreateDwordField (^RBUF, ^B1D3._LEN, B3LN)
Store (\S3B1, B3AD)
Store (SIO_BAR_LEN, B3LN)
}
// SPI1
If (LNotEqual (\S4B1, Zero)) {
CreateDwordField (^RBUF, ^B1D4._BAS, B4AD)
CreateDwordField (^RBUF, ^B1D4._LEN, B4LN)
Store (\S4B1, B4AD)
Store (SIO_BAR_LEN, B4LN)
}
// UART0
If (LNotEqual (\S5B1, Zero)) {
CreateDwordField (^RBUF, ^B1D5._BAS, B5AD)
CreateDwordField (^RBUF, ^B1D5._LEN, B5LN)
Store (\S5B1, B5AD)
Store (SIO_BAR_LEN, B5LN)
}
// UART1
If (LNotEqual (\S6B1, Zero)) {
CreateDwordField (^RBUF, ^B1D6._BAS, B6AD)
CreateDwordField (^RBUF, ^B1D6._LEN, B6LN)
Store (\S6B1, B6AD)
Store (SIO_BAR_LEN, B6LN)
}
// SDIO
If (LNotEqual (\S7B1, Zero)) {
CreateDwordField (^RBUF, ^B1D7._BAS, B7AD)
CreateDwordField (^RBUF, ^B1D7._LEN, B7LN)
Store (\S7B1, B7AD)
Store (SIO_BAR_LEN, B7LN)
}
Return (RBUF)
}
}
Device (SDMA)
{
// Serial IO DMA Controller
Name (_HID, "INTL9C60")
Name (_UID, 1)
Name (_ADR, 0x00150000)
// BAR0 is assigned during PCI enumeration and saved into NVS
Name (RBUF, ResourceTemplate ()
{
Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , ) {7}
})
Method (_CRS, 0, NotSerialized)
{
// Update BAR0 address and length if set in NVS
If (LNotEqual (\S0B0, Zero)) {
CreateDwordField (^RBUF, ^BAR0._BAS, B0AD)
CreateDwordField (^RBUF, ^BAR0._LEN, B0LN)
Store (\S0B0, B0AD)
Store (SIO_BAR_LEN, B0LN)
}
Return (RBUF)
}
Method (_STA, 0, NotSerialized)
{
If (LEqual (\S0EN, 0)) {
Return (0x0)
} Else {
Return (0xF)
}
}
}
Device (I2C0)
{
// Serial IO I2C0 Controller
Method (_HID)
{
If (\ISWP ()) {
// WildcatPoint
Return ("INT3432")
}
// LynxPoint-LP
Return ("INT33C2")
}
Name (_UID, 1)
Name (_ADR, 0x00150001)
Name (SSCN, Package () { 432, 507, 30 })
Name (FMCN, Package () { 72, 160, 30 })
// BAR0 is assigned during PCI enumeration and saved into NVS
Name (RBUF, ResourceTemplate ()
{
Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , ) {7}
})
// DMA channels are only used if Serial IO DMA controller is enabled
Name (DBUF, ResourceTemplate ()
{
FixedDMA (0x18, 4, Width32Bit, DMA1) // Tx
FixedDMA (0x19, 5, Width32Bit, DMA2) // Rx
})
Method (_CRS, 0, NotSerialized)
{
// Update BAR0 address and length if set in NVS
If (LNotEqual (\S1B0, Zero)) {
CreateDwordField (^RBUF, ^BAR0._BAS, B0AD)
CreateDwordField (^RBUF, ^BAR0._LEN, B0LN)
Store (\S1B0, B0AD)
Store (SIO_BAR_LEN, B0LN)
}
// Check if Serial IO DMA Controller is enabled
If (LNotEqual (\_SB.PCI0.SDMA._STA, Zero)) {
Return (ConcatenateResTemplate (RBUF, DBUF))
} Else {
Return (RBUF)
}
}
Method (_STA, 0, NotSerialized)
{
If (LEqual (\S1EN, 0)) {
Return (0x0)
} Else {
Return (0xF)
}
}
Method (_PS0, 0, Serialized)
{
^^LPD0 (\S1B1, \S1EN)
}
Method (_PS3, 0, Serialized)
{
^^LPD3 (\S1B1, \S1EN)
}
}
Device (I2C1)
{
// Serial IO I2C1 Controller
Method (_HID)
{
If (\ISWP ()) {
// WildcatPoint
Return ("INT3433")
}
// LynxPoint-LP
Return ("INT33C3")
}
Name (_UID, 1)
Name (_ADR, 0x00150002)
Name (SSCN, Package () { 432, 507, 30 })
Name (FMCN, Package () { 72, 160, 30 })
// BAR0 is assigned during PCI enumeration and saved into NVS
Name (RBUF, ResourceTemplate ()
{
Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , ) {7}
})
// DMA channels are only used if Serial IO DMA controller is enabled
Name (DBUF, ResourceTemplate ()
{
FixedDMA (0x1A, 6, Width32Bit, DMA1) // Tx
FixedDMA (0x1B, 7, Width32Bit, DMA2) // Rx
})
Method (_CRS, 0, NotSerialized)
{
// Update BAR0 address and length if set in NVS
If (LNotEqual (\S2B0, Zero)) {
CreateDwordField (^RBUF, ^BAR0._BAS, B0AD)
CreateDwordField (^RBUF, ^BAR0._LEN, B0LN)
Store (\S2B0, B0AD)
Store (SIO_BAR_LEN, B0LN)
}
// Check if Serial IO DMA Controller is enabled
If (LNotEqual (\_SB.PCI0.SDMA._STA, Zero)) {
Return (ConcatenateResTemplate (RBUF, DBUF))
} Else {
Return (RBUF)
}
}
Method (_STA, 0, NotSerialized)
{
If (LEqual (\S2EN, 0)) {
Return (0x0)
} Else {
Return (0xF)
}
}
Method (_PS0, 0, Serialized)
{
^^LPD0 (\S2B1, \S2EN)
}
Method (_PS3, 0, Serialized)
{
^^LPD3 (\S2B1, \S2EN)
}
}
Device (SPI0)
{
// Serial IO SPI0 Controller
Method (_HID)
{
If (\ISWP ()) {
// WildcatPoint
Return ("INT3430")
}
// LynxPoint-LP
Return ("INT33C0")
}
Name (_UID, 1)
Name (_ADR, 0x00150003)
// BAR0 is assigned during PCI enumeration and saved into NVS
Name (RBUF, ResourceTemplate ()
{
Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , ) {7}
})
Method (_CRS, 0, NotSerialized)
{
// Update BAR0 address and length if set in NVS
If (LNotEqual (\S3B0, Zero)) {
CreateDwordField (^RBUF, ^BAR0._BAS, B0AD)
CreateDwordField (^RBUF, ^BAR0._LEN, B0LN)
Store (\S3B0, B0AD)
Store (SIO_BAR_LEN, B0LN)
}
Return (RBUF)
}
Method (_STA, 0, NotSerialized)
{
If (LEqual (\S3EN, 0)) {
Return (0x0)
} Else {
Return (0xF)
}
}
Method (_PS0, 0, Serialized)
{
^^LPD0 (\S3B1, \S3EN)
}
Method (_PS3, 0, Serialized)
{
^^LPD3 (\S3B1, \S3EN)
}
}
Device (SPI1)
{
// Serial IO SPI1 Controller
Method (_HID)
{
If (\ISWP ()) {
// WildcatPoint
Return ("INT3431")
}
// LynxPoint-LP
Return ("INT33C1")
}
Name (_UID, 1)
Name (_ADR, 0x00150004)
// BAR0 is assigned during PCI enumeration and saved into NVS
Name (RBUF, ResourceTemplate ()
{
Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , ) {7}
})
// DMA channels are only used if Serial IO DMA controller is enabled
Name (DBUF, ResourceTemplate ()
{
FixedDMA (0x10, 0, Width32Bit, DMA1) // Tx
FixedDMA (0x11, 1, Width32Bit, DMA2) // Rx
})
Method (_CRS, 0, NotSerialized)
{
// Update BAR0 address and length if set in NVS
If (LNotEqual (\S4B0, Zero)) {
CreateDwordField (^RBUF, ^BAR0._BAS, B0AD)
CreateDwordField (^RBUF, ^BAR0._LEN, B0LN)
Store (\S4B0, B0AD)
Store (SIO_BAR_LEN, B0LN)
}
// Check if Serial IO DMA Controller is enabled
If (LNotEqual (\_SB.PCI0.SDMA._STA, Zero)) {
Return (ConcatenateResTemplate (RBUF, DBUF))
} Else {
Return (RBUF)
}
}
Method (_STA, 0, NotSerialized)
{
If (LEqual (\S4EN, 0)) {
Return (0x0)
} Else {
Return (0xF)
}
}
Method (_PS0, 0, Serialized)
{
^^LPD0 (\S4B1, \S4EN)
}
Method (_PS3, 0, Serialized)
{
^^LPD3 (\S4B1, \S4EN)
}
}
Device (UAR0)
{
// Serial IO UART0 Controller
Method (_HID)
{
If (\ISWP ()) {
// WildcatPoint
Return ("INT3434")
}
// LynxPoint-LP
Return ("INT33C4")
}
Name (_UID, 1)
Name (_ADR, 0x00150005)
// BAR0 is assigned during PCI enumeration and saved into NVS
Name (RBUF, ResourceTemplate ()
{
Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , ) {13}
})
// DMA channels are only used if Serial IO DMA controller is enabled
Name (DBUF, ResourceTemplate ()
{
FixedDMA (0x16, 2, Width32Bit, DMA1) // Tx
FixedDMA (0x17, 3, Width32Bit, DMA2) // Rx
})
Method (_CRS, 0, NotSerialized)
{
// Update BAR0 address and length if set in NVS
If (LNotEqual (\S5B0, Zero)) {
CreateDwordField (^RBUF, ^BAR0._BAS, B0AD)
CreateDwordField (^RBUF, ^BAR0._LEN, B0LN)
Store (\S5B0, B0AD)
Store (SIO_BAR_LEN, B0LN)
}
// Check if Serial IO DMA Controller is enabled
If (LNotEqual (\_SB.PCI0.SDMA._STA, Zero)) {
Return (ConcatenateResTemplate (RBUF, DBUF))
} Else {
Return (RBUF)
}
}
Method (_STA, 0, NotSerialized)
{
If (LEqual (\S5EN, 0)) {
Return (0x0)
} Else {
Return (0xF)
}
}
Method (_PS0, 0, Serialized)
{
^^LPD0 (\S5B1, \S5EN)
}
Method (_PS3, 0, Serialized)
{
^^LPD3 (\S5B1, \S5EN)
}
}
Device (UAR1)
{
// Serial IO UART1 Controller
Method (_HID)
{
If (\ISWP ()) {
// WildcatPoint
Return ("INT3435")
}
// LynxPoint-LP
Return ("INT33C5")
}
Name (_UID, 1)
Name (_ADR, 0x00150006)
// BAR0 is assigned during PCI enumeration and saved into NVS
Name (RBUF, ResourceTemplate ()
{
Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , ) {13}
})
Method (_CRS, 0, NotSerialized)
{
// Update BAR0 address and length if set in NVS
If (LNotEqual (\S6B0, Zero)) {
CreateDwordField (^RBUF, ^BAR0._BAS, B0AD)
CreateDwordField (^RBUF, ^BAR0._LEN, B0LN)
Store (\S6B0, B0AD)
Store (SIO_BAR_LEN, B0LN)
}
Return (RBUF)
}
Method (_STA, 0, NotSerialized)
{
If (LEqual (\S6EN, 0)) {
Return (0x0)
} Else {
Return (0xF)
}
}
Method (_PS0, 0, Serialized)
{
^^LPD0 (\S6B1, \S6EN)
}
Method (_PS3, 0, Serialized)
{
^^LPD3 (\S6B1, \S6EN)
}
}
Device (SDIO)
{
// Serial IO SDIO Controller
Method (_HID)
{
If (\ISWP ()) {
// WildcatPoint
Return ("INT3436")
}
// LynxPoint-LP
Return ("INT33C6")
}
Name (_CID, "PNP0D40")
Name (_UID, 1)
Name (_ADR, 0x00170000)
// BAR0 is assigned during PCI enumeration and saved into NVS
Name (RBUF, ResourceTemplate ()
{
Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , ) {5}
})
Method (_CRS, 0, NotSerialized)
{
// Update BAR0 address and length if set in NVS
If (LNotEqual (\S7B0, Zero)) {
CreateDwordField (^RBUF, ^BAR0._BAS, B0AD)
CreateDwordField (^RBUF, ^BAR0._LEN, B0LN)
Store (\S7B0, B0AD)
Store (SIO_BAR_LEN, B0LN)
}
Return (RBUF)
}
Method (_STA, 0, NotSerialized)
{
If (LEqual (\S7EN, 0)) {
Return (0x0)
} Else {
Return (0xF)
}
}
}

View File

@@ -0,0 +1,26 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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 () { 0x0, 0x0, 0x0, 0x0 })
Name (\_S1, Package () { 0x1, 0x1, 0x0, 0x0 })
Name (\_S2, Package () { 0x1, 0x1, 0x0, 0x0 })
Name (\_S3, Package () { 0x5, 0x5, 0x0, 0x0 })
Name (\_S4, Package () { 0x6, 0x6, 0x0, 0x0 })
Name (\_S5, Package () { 0x7, 0x7, 0x0, 0x0 })

View File

@@ -0,0 +1,241 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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 SMBus Controller 0:1f.3
Device (SBUS)
{
Name (_ADR, 0x001f0003)
#ifdef ENABLE_SMBUS_METHODS
OperationRegion (SMBP, PCI_Config, 0x00, 0x100)
Field(SMBP, DWordAcc, NoLock, Preserve)
{
Offset(0x40),
, 2,
I2CE, 1
}
OperationRegion (SMBI, SystemIO, SMBUS_IO_BASE, 0x20)
Field (SMBI, ByteAcc, NoLock, Preserve)
{
HSTS, 8, // Host Status
, 8,
HCNT, 8, // Host Control
HCMD, 8, // Host Command
TXSA, 8, // Transmit Slave Address
DAT0, 8, // Host Data 0
DAT1, 8, // Host Data 1
HBDB, 8, // Host Block Data Byte
PECK, 8, // Packet Error Check
RXSA, 8, // Receive Slave Address
RXDA, 16, // Receive Slave Data
AUXS, 8, // Auxiliary Status
AUXC, 8, // Auxiliary Control
SLPC, 8, // SMLink Pin Control
SBPC, 8, // SMBus Pin Control
SSTS, 8, // Slave Status
SCMD, 8, // Slave Command
NADR, 8, // Notify Device Address
NDLB, 8, // Notify Data Low Byte
NDLH, 8, // Notify Data High Byte
}
// Kill all SMBus communication
Method (KILL, 0, Serialized)
{
Or (HCNT, 0x02, HCNT) // Send Kill
Or (HSTS, 0xff, HSTS) // Clean Status
}
// Check if last operation completed
// return Failure = 0, Success = 1
Method (CMPL, 0, Serialized)
{
Store (4000, Local0) // Timeout 200ms in 50us steps
While (Local0) {
If (And(HSTS, 0x02)) { // Completion Status?
Return (1) // Operation Completed
} Else {
Stall (50)
Decrement (Local0)
If (LEqual(Local0, 0)) {
KILL()
}
}
}
Return (0) // Failure
}
// Wait for SMBus to become ready
Method (SRDY, 0, Serialized)
{
Store (200, Local0) // Timeout 200ms
While (Local0) {
If (And(HSTS, 0x40)) { // IN_USE?
Sleep(1) // Wait 1ms
Decrement(Local0) // timeout--
If (LEqual(Local0, 0)) {
Return (1)
}
} Else {
Store (0, Local0) // We're ready
}
}
Store (4000, Local0) // Timeout 200ms (50us * 4000)
While (Local0) {
If (And (HSTS, 0x01)) { // Host Busy?
Stall(50) // Wait 50us
Decrement(Local0) // timeout--
If (LEqual(Local0, 0)) {
KILL()
}
} Else {
Return (0) // Success
}
}
Return (1) // Failure
}
// SMBus Send Byte
// Arg0: Address
// Arg1: Data
// Return: 1 = Success, 0=Failure
Method (SSXB, 2, Serialized)
{
// Is the SMBus Controller Ready?
If (SRDY()) {
Return (0)
}
// Send Byte
Store (0, I2CE) // SMBus Enable
Store (0xbf, HSTS)
Store (Arg0, TXSA) // Write Address
Store (Arg1, HCMD) // Write Data
Store (0x48, HCNT) // Start + Byte Data Protocol
If (CMPL()) {
Or (HSTS, 0xff, HSTS) // Clean up
Return (1) // Success
}
Return (0)
}
// SMBus Receive Byte
// Arg0: Address
// Return: 0xffff = Failure, Data (8bit) = Success
Method (SRXB, 2, Serialized)
{
// Is the SMBus Controller Ready?
If (SRDY()) {
Return (0xffff)
}
// Receive Byte
Store (0, I2CE) // SMBus Enable
Store (0xbf, HSTS)
Store (Or (Arg0, 1), TXSA) // Write Address
Store (0x44, HCNT) // Start
If (CMPL()) {
Or (HSTS, 0xff, HSTS) // Clean up
Return (DAT0) // Success
}
Return (0xffff)
}
// SMBus Write Byte
// Arg0: Address
// Arg1: Command
// Arg2: Data
// Return: 1 = Success, 0=Failure
Method (SWRB, 3, Serialized)
{
// Is the SMBus Controller Ready?
If (SRDY()) {
Return (0)
}
// Send Byte
Store (0, I2CE) // SMBus Enable
Store (0xbf, HSTS)
Store (Arg0, TXSA) // Write Address
Store (Arg1, HCMD) // Write Command
Store (Arg2, DAT0) // Write Data
Store (0x48, HCNT) // Start + Byte Protocol
If (CMPL()) {
Or (HSTS, 0xff, HSTS) // Clean up
Return (1) // Success
}
Return (0)
}
// SMBus Read Byte
// Arg0: Address
// Arg1: Command
// Return: 0xffff = Failure, Data (8bit) = Success
Method (SRDB, 2, Serialized)
{
// Is the SMBus Controller Ready?
If (SRDY()) {
Return (0xffff)
}
// Receive Byte
Store (0, I2CE) // SMBus Enable
Store (0xbf, HSTS)
Store (Or (Arg0, 1), TXSA) // Write Address
Store (Arg1, HCMD) // Command
Store (0x48, HCNT) // Start
If (CMPL()) {
Or (HSTS, 0xff, HSTS) // Clean up
Return (DAT0) // Success
}
Return (0xffff)
}
#endif
}

View File

@@ -0,0 +1,213 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <soc/iomap.h>
Name (_HID, EISAID ("PNP0A08")) // PCIe
Name (_CID, EISAID ("PNP0A03")) // PCI
Name (_ADR, 0)
Name (_BBN, 0)
Device (MCHC)
{
Name (_ADR, 0x00000000) // 0:0.0
OperationRegion (MCHP, PCI_Config, 0x00, 0x100)
Field (MCHP, DWordAcc, NoLock, Preserve)
{
Offset (0x70), // ME Base Address
MEBA, 64,
Offset (0xa0), // Top of Used Memory
TOM, 64,
Offset (0xbc), // Top of Low Used Memory
TLUD, 32,
}
}
// Current Resource Settings
Method (_CRS, 0, Serialized)
{
Name (MCRS, ResourceTemplate()
{
// Bus Numbers
WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
0x0000, 0x0000, 0x00ff, 0x0000, 0x0100,,, PB00)
// IO Region 0
DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
0x0000, 0x0000, 0x0cf7, 0x0000, 0x0cf8,,, PI00)
// PCI Config Space
Io (Decode16, 0x0cf8, 0x0cf8, 0x0001, 0x0008)
// IO Region 1
DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
0x0000, 0x0d00, 0xffff, 0x0000, 0xf300,,, PI01)
// VGA memory (0xa0000-0xbffff)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000a0000, 0x000bffff, 0x00000000,
0x00020000,,, ASEG)
// OPROM reserved (0xc0000-0xc3fff)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000c0000, 0x000c3fff, 0x00000000,
0x00004000,,, OPR0)
// OPROM reserved (0xc4000-0xc7fff)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000c4000, 0x000c7fff, 0x00000000,
0x00004000,,, OPR1)
// OPROM reserved (0xc8000-0xcbfff)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000c8000, 0x000cbfff, 0x00000000,
0x00004000,,, OPR2)
// OPROM reserved (0xcc000-0xcffff)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000cc000, 0x000cffff, 0x00000000,
0x00004000,,, OPR3)
// OPROM reserved (0xd0000-0xd3fff)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000d0000, 0x000d3fff, 0x00000000,
0x00004000,,, OPR4)
// OPROM reserved (0xd4000-0xd7fff)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000d4000, 0x000d7fff, 0x00000000,
0x00004000,,, OPR5)
// OPROM reserved (0xd8000-0xdbfff)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000d8000, 0x000dbfff, 0x00000000,
0x00004000,,, OPR6)
// OPROM reserved (0xdc000-0xdffff)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000dc000, 0x000dffff, 0x00000000,
0x00004000,,, OPR7)
// BIOS Extension (0xe0000-0xe3fff)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000e0000, 0x000e3fff, 0x00000000,
0x00004000,,, ESG0)
// BIOS Extension (0xe4000-0xe7fff)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000e4000, 0x000e7fff, 0x00000000,
0x00004000,,, ESG1)
// BIOS Extension (0xe8000-0xebfff)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000e8000, 0x000ebfff, 0x00000000,
0x00004000,,, ESG2)
// BIOS Extension (0xec000-0xeffff)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000ec000, 0x000effff, 0x00000000,
0x00004000,,, ESG3)
// System BIOS (0xf0000-0xfffff)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000f0000, 0x000fffff, 0x00000000,
0x00010000,,, FSEG)
// PCI Memory Region (Top of memory-CONFIG_MMCONF_BASE_ADDRESS)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000,,, PM01)
// TPM Area (0xfed40000-0xfed44fff)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0xfed40000, 0xfed44fff, 0x00000000,
0x00005000,,, TPMR)
})
// Find PCI resource area in MCRS
CreateDwordField(MCRS, PM01._MIN, PMIN)
CreateDwordField(MCRS, PM01._MAX, PMAX)
CreateDwordField(MCRS, PM01._LEN, PLEN)
// Fix up PCI memory region
// Start with Top of Lower Usable DRAM
Store (^MCHC.TLUD, Local0)
Store (^MCHC.MEBA, Local1)
// Check if ME base is equal
If (LEqual (Local0, Local1)) {
// Use Top Of Memory instead
Store (^MCHC.TOM, Local0)
}
Store (Local0, PMIN)
Store (Subtract(CONFIG_MMCONF_BASE_ADDRESS, 1), PMAX)
Add(Subtract(PMAX, PMIN), 1, PLEN)
Return (MCRS)
}
/* PCI Device Resource Consumption */
Device (PDRC)
{
Name (_HID, EISAID("PNP0C02"))
Name (_UID, 1)
Name (PDRS, ResourceTemplate() {
Memory32Fixed (ReadWrite, RCBA_BASE_ADDRESS, RCBA_BASE_SIZE)
Memory32Fixed (ReadWrite, MCH_BASE_ADDRESS, MCH_BASE_SIZE)
Memory32Fixed (ReadWrite, DMI_BASE_ADDRESS, DMI_BASE_SIZE)
Memory32Fixed (ReadWrite, EP_BASE_ADDRESS, EP_BASE_SIZE)
Memory32Fixed (ReadWrite, MCFG_BASE_ADDRESS, MCFG_BASE_SIZE)
Memory32Fixed (ReadWrite, EDRAM_BASE_ADDRESS, EDRAM_BASE_SIZE)
Memory32Fixed (ReadWrite, GDXC_BASE_ADDRESS, GDXC_BASE_SIZE)
})
// Current Resource Settings
Method (_CRS, 0, Serialized)
{
Return (PDRS)
}
}
/* PCI IRQ assignment */
#include "pci_irqs.asl"
/* Configurable TDP */
#include "ctdp.asl"

View File

@@ -0,0 +1,371 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
// XHCI Controller 0:14.0
Device (XHCI)
{
Name (_ADR, 0x00140000)
Name (PLSD, 5) // Port Link State - RxDetect
Name (PLSP, 7) // Port Link State - Polling
OperationRegion (XPRT, PCI_Config, 0x00, 0x100)
Field (XPRT, AnyAcc, NoLock, Preserve)
{
Offset (0x0),
DVID, 16,
Offset (0x10),
, 16,
XMEM, 16, // MEM_BASE
Offset (0x40),
, 11,
SWAI, 1,
, 20,
Offset (0x44),
, 12,
SAIP, 2,
, 18,
Offset (0x74),
D0D3, 2,
, 6,
PMEE, 1, // PME_EN
, 6,
PMES, 1, // PME_STS
Offset (0xb0),
, 13,
MB13, 1,
MB14, 1,
Offset (0xd0),
PR2R, 32, // USB2PR
PR2M, 32, // USB2PRM
PR3R, 32, // USB3PR
PR3M, 32, // USB3PRM
}
// Clear status bits
Method (LPCL, 0, Serialized)
{
OperationRegion (XREG, SystemMemory,
ShiftLeft (^XMEM, 16), 0x600)
Field (XREG, DWordAcc, Lock, Preserve)
{
Offset (0x510), // PORTSCNUSB3[0]
PSC0, 32,
Offset (0x520), // PORTSCNUSB3[1]
PSC1, 32,
Offset (0x530), // PORTSCNUSB3[2]
PSC2, 32,
Offset (0x540), // PORTSCNUSB3[3]
PSC3, 32,
}
// Port Enabled/Disabled (Bit 1)
Name (PEDB, ShiftLeft (1, 1))
// Change Status (Bits 23:17)
Name (CHST, ShiftLeft (0x7f, 17))
// Port 0
And (PSC0, Not (PEDB), Local0)
Or (Local0, CHST, PSC0)
// Port 1
And (PSC1, Not (PEDB), Local0)
Or (Local0, CHST, PSC1)
// Port 2
And (PSC2, Not (PEDB), Local0)
Or (Local0, CHST, PSC2)
// Port 3
And (PSC3, Not (PEDB), Local0)
Or (Local0, CHST, PSC3)
}
Method (LPS0, 0, Serialized)
{
OperationRegion (XREG, SystemMemory,
ShiftLeft (^XMEM, 16), 0x600)
Field (XREG, DWordAcc, Lock, Preserve)
{
Offset (0x510), // PORTSCNUSB3
, 5,
PLS1, 4, // [8:5] Port Link State
PPR1, 1, // [9] Port Power
, 7,
CSC1, 1, // [17] Connect Status Change
, 1,
WRC1, 1, // [19] Warm Port Reset Change
, 11,
WPR1, 1, // [31] Warm Port Reset
Offset (0x520), // PORTSCNUSB3
, 5,
PLS2, 4, // [8:5] Port Link State
PPR2, 1, // [9] Port Power
, 7,
CSC2, 1, // [17] Connect Status Change
, 1,
WRC2, 1, // [19] Warm Port Reset Change
, 11,
WPR2, 1, // [31] Warm Port Reset
Offset (0x530), // PORTSCNUSB3
, 5,
PLS3, 4, // [8:5] Port Link State
PPR3, 1, // [9] Port Power
, 7,
CSC3, 1, // [17] Connect Status Change
, 1,
WRC3, 1, // [19] Warm Port Reset Change
, 11,
WPR3, 1, // [31] Warm Port Reset
Offset (0x540), // PORTSCNUSB3
, 5,
PLS4, 4, // [8:5] Port Link State
PPR4, 1, // [9] Port Power
, 7,
CSC4, 1, // [17] Connect Status Change
, 1,
WRC4, 1, // [19] Warm Port Reset Change
, 11,
WPR4, 1, // [31] Warm Port Reset
}
// Wait for all powered ports to finish polling
Store (10, Local0)
While (LOr (LOr (LAnd (LEqual (PPR1, 1), LEqual (PLS1, PLSP)),
LAnd (LEqual (PPR2, 1), LEqual (PLS2, PLSP))),
LOr (LAnd (LEqual (PPR3, 1), LEqual (PLS3, PLSP)),
LAnd (LEqual (PPR4, 1), LEqual (PLS4, PLSP)))))
{
If (LEqual (Local0, 0)) {
Break
}
Decrement (Local0)
Stall (10)
}
// For each USB3 Port:
// If port is disconnected (PLS=5 PP=1 CSC=0)
// 1) Issue warm reset (WPR=1)
// 2) Poll for warm reset complete (WRC=0)
// 3) Write 1 to port status to clear
// Local# indicate if port is reset
Store (0, Local1)
Store (0, Local2)
Store (0, Local3)
Store (0, Local4)
If (LAnd (LEqual (PLS1, PLSD),
LAnd (LEqual (CSC1, 0), LEqual (PPR1, 1)))) {
Store (1, WPR1) // Issue warm reset
Store (1, Local1)
}
If (LAnd (LEqual (PLS2, PLSD),
LAnd (LEqual (CSC2, 0), LEqual (PPR2, 1)))) {
Store (1, WPR2) // Issue warm reset
Store (1, Local2)
}
If (LAnd (LEqual (PLS3, PLSD),
LAnd (LEqual (CSC3, 0), LEqual (PPR3, 1)))) {
Store (1, WPR3) // Issue warm reset
Store (1, Local3)
}
If (LAnd (LEqual (PLS4, PLSD),
LAnd (LEqual (CSC4, 0), LEqual (PPR4, 1)))) {
Store (1, WPR4) // Issue warm reset
Store (1, Local4)
}
// Poll for warm reset complete on all ports that were reset
Store (10, Local0)
While (LOr (LOr (LAnd (LEqual (Local1, 1), LEqual (WRC1, 0)),
LAnd (LEqual (Local2, 1), LEqual (WRC2, 0))),
LOr (LAnd (LEqual (Local3, 1), LEqual (WRC3, 0)),
LAnd (LEqual (Local4, 1), LEqual (WRC4, 0)))))
{
If (LEqual (Local0, 0)) {
Break
}
Decrement (Local0)
Stall (10)
}
// Clear status bits in all ports
LPCL ()
}
Method (_PSC, 0, NotSerialized)
{
Return (^D0D3)
}
Method (_PS0, 0, Serialized)
{
If (LEqual (^DVID, 0xFFFF)) {
Return ()
}
If (LOr (LEqual (^XMEM, 0xFFFF), LEqual (^XMEM, 0x0000))) {
Return ()
}
OperationRegion (XREG, SystemMemory,
Add (ShiftLeft (^XMEM, 16), 0x8000), 0x200)
Field (XREG, DWordAcc, Lock, Preserve)
{
Offset (0x0e0), // AUX Reset Control 1
, 15,
AX15, 1,
Offset (0x154), // AUX Domain PM Control Register 2
, 31,
CLK2, 1,
Offset (0x16c), // AUX Clock Control
, 2,
CLK0, 1,
, 11,
CLK1, 1, // USB3 Port Aux/Core Clock Gating Enable
}
// If device is in D3, set back to D0
Store (^D0D3, Local0)
if (LEqual (Local0, 3)) {
Store (0, ^D0D3)
}
if (LNot (\ISWP())) {
// Clear PCI 0xB0[14:13]
Store (0, ^MB13)
Store (0, ^MB14)
// Clear MMIO 0x816C[14,2]
Store (0, CLK0)
Store (0, CLK1)
// Set MMIO 0x8154[31]
Store (1, CLK2)
// Handle per-port reset if needed
LPS0 ()
// Set MMIO 0x80e0[15]
Store (1, AX15)
// Clear PCI CFG offset 0x40[11]
Store (0, ^SWAI)
// Clear PCI CFG offset 0x44[13:12]
Store (0, ^SAIP)
}
Return ()
}
Method (_PS3, 0, Serialized)
{
If (LEqual (^DVID, 0xFFFF)) {
Return ()
}
If (LOr (LEqual (^XMEM, 0xFFFF), LEqual (^XMEM, 0x0000))) {
Return ()
}
OperationRegion (XREG, SystemMemory,
Add (ShiftLeft (^XMEM, 16), 0x8000), 0x200)
Field (XREG, DWordAcc, Lock, Preserve)
{
Offset (0x0e0), // AUX Reset Control 1
, 15,
AX15, 1,
Offset (0x154), // AUX Domain PM Control Register 2
, 31,
CLK2, 1,
Offset (0x16c), // AUX Clock Control
, 2,
CLK0, 1,
, 11,
CLK1, 1, // USB3 Port Aux/Core Clock Gating Enable
}
Store (1, ^PMES) // Clear PME Status
Store (1, ^PMEE) // Enable PME
// If device is in D3, set back to D0
Store (^D0D3, Local0)
if (LEqual (Local0, 3)) {
Store (0, ^D0D3)
}
if (LNot (\ISWP())) {
// Set PCI 0xB0[14:13]
Store (1, ^MB13)
Store (1, ^MB14)
// Set MMIO 0x816C[14,2]
Store (1, CLK0)
Store (1, CLK1)
// Clear MMIO 0x8154[31]
Store (0, CLK2)
// Clear MMIO 0x80e0[15]
Store (0, AX15)
// Set PCI CFG offset 0x40[11]
Store (1, ^SWAI)
// Set PCI CFG offset 0x44[13:12]
Store (1, ^SAIP)
}
// Put device in D3
Store (3, ^D0D3)
Return ()
}
Name (_PRW, Package(){ 0x6d, 3 })
// Leave USB ports on for to allow Wake from USB
Method(_S3D,0) // Highest D State in S3 State
{
Return (3)
}
Method(_S4D,0) // Highest D State in S4 State
{
Return (3)
}
Device (HUB7)
{
Name (_ADR, 0x00000000)
// How many are there?
Device (PRT1) { Name (_ADR, 1) } // USB Port 0
Device (PRT2) { Name (_ADR, 2) } // USB Port 1
Device (PRT3) { Name (_ADR, 3) } // USB Port 2
Device (PRT4) { Name (_ADR, 4) } // USB Port 3
Device (PRT5) { Name (_ADR, 5) } // USB Port 4
Device (PRT6) { Name (_ADR, 6) } // USB Port 5
}
}

View File

@@ -0,0 +1,167 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <cbmem.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <arch/io.h>
#include <delay.h>
#include <soc/adsp.h>
#include <soc/device_nvs.h>
#include <soc/iobp.h>
#include <soc/nvs.h>
#include <soc/pch.h>
#include <soc/ramstage.h>
#include <soc/rcba.h>
#include <soc/intel/broadwell/chip.h>
static void adsp_init(struct device *dev)
{
config_t *config = dev->chip_info;
struct resource *bar0, *bar1;
u32 tmp32;
/* Ensure memory and bus master are enabled */
tmp32 = pci_read_config32(dev, PCI_COMMAND);
tmp32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
pci_write_config32(dev, PCI_COMMAND, tmp32);
/* Find BAR0 and BAR1 */
bar0 = find_resource(dev, PCI_BASE_ADDRESS_0);
if (!bar0)
return;
bar1 = find_resource(dev, PCI_BASE_ADDRESS_1);
if (!bar1)
return;
/*
* Set LTR value in DSP shim LTR control register to 3ms
* SNOOP_REQ[13]=1b SNOOP_SCALE[12:10]=100b (1ms) SNOOP_VAL[9:0]=3h
*/
tmp32 = pch_is_wpt() ? ADSP_SHIM_BASE_WPT : ADSP_SHIM_BASE_LPT;
write32(res2mmio(bar0, tmp32 + ADSP_SHIM_LTRC, 0),
ADSP_SHIM_LTRC_VALUE);
/* Program VDRTCTL2 D19:F0:A8[31:0] = 0x00000fff */
pci_write_config32(dev, ADSP_PCI_VDRTCTL2, ADSP_VDRTCTL2_VALUE);
/* Program ADSP IOBP VDLDAT1 to 0x040100 */
pch_iobp_write(ADSP_IOBP_VDLDAT1, ADSP_VDLDAT1_VALUE);
/* Set D3 Power Gating Enable in D19:F0:A0 based on PCH type */
tmp32 = pci_read_config32(dev, ADSP_PCI_VDRTCTL0);
if (pch_is_wpt()) {
if (config->adsp_d3_pg_enable) {
tmp32 &= ~ADSP_VDRTCTL0_D3PGD_WPT;
if (config->adsp_sram_pg_enable)
tmp32 &= ~ADSP_VDRTCTL0_D3SRAMPGD_WPT;
else
tmp32 |= ADSP_VDRTCTL0_D3SRAMPGD_WPT;
} else {
tmp32 |= ADSP_VDRTCTL0_D3PGD_WPT;
}
} else {
if (config->adsp_d3_pg_enable) {
tmp32 &= ~ADSP_VDRTCTL0_D3PGD_LPT;
if (config->adsp_sram_pg_enable)
tmp32 &= ~ADSP_VDRTCTL0_D3SRAMPGD_LPT;
else
tmp32 |= ADSP_VDRTCTL0_D3SRAMPGD_LPT;
} else {
tmp32 |= ADSP_VDRTCTL0_D3PGD_LPT;
}
}
pci_write_config32(dev, ADSP_PCI_VDRTCTL0, tmp32);
/* Set PSF Snoop to SA, RCBA+0x3350[10]=1b */
RCBA32_OR(0x3350, (1 << 10));
/* Set DSP IOBP PMCTL 0x1e0=0x3f */
pch_iobp_write(ADSP_IOBP_PMCTL, ADSP_PMCTL_VALUE);
if (config->sio_acpi_mode) {
/* Configure for ACPI mode */
global_nvs_t *gnvs;
printk(BIOS_INFO, "ADSP: Enable ACPI Mode IRQ3\n");
/* Find ACPI NVS to update BARs */
gnvs = (global_nvs_t *)cbmem_find(CBMEM_ID_ACPI_GNVS);
if (!gnvs) {
printk(BIOS_ERR, "Unable to locate Global NVS\n");
return;
}
/* Save BAR0 and BAR1 to ACPI NVS */
gnvs->dev.bar0[SIO_NVS_ADSP] = (u32)bar0->base;
gnvs->dev.bar1[SIO_NVS_ADSP] = (u32)bar1->base;
gnvs->dev.enable[SIO_NVS_ADSP] = 1;
/* Set PCI Config Disable Bit */
pch_iobp_update(ADSP_IOBP_PCICFGCTL, ~0, ADSP_PCICFGCTL_PCICD);
/* Set interrupt de-assert/assert opcode override to IRQ3 */
pch_iobp_write(ADSP_IOBP_VDLDAT2, ADSP_IOBP_ACPI_IRQ3);
/* Enable IRQ3 in RCBA */
RCBA32_OR(ACPIIRQEN, ADSP_ACPI_IRQEN);
/* Set ACPI Interrupt Enable Bit */
pch_iobp_update(ADSP_IOBP_PCICFGCTL, ~ADSP_PCICFGCTL_SPCBAD,
ADSP_PCICFGCTL_ACPIIE);
/* Put ADSP in D3hot */
tmp32 = read32(res2mmio(bar1, PCH_PCS, 0));
tmp32 |= PCH_PCS_PS_D3HOT;
write32(res2mmio(bar1, PCH_PCS, 0), tmp32);
} else {
printk(BIOS_INFO, "ADSP: Enable PCI Mode IRQ23\n");
/* Configure for PCI mode */
pci_write_config32(dev, PCI_INTERRUPT_LINE, ADSP_PCI_IRQ);
/* Clear ACPI Interrupt Enable Bit */
pch_iobp_update(ADSP_IOBP_PCICFGCTL,
~(ADSP_PCICFGCTL_SPCBAD | ADSP_PCICFGCTL_ACPIIE), 0);
}
}
static struct device_operations adsp_ops = {
.read_resources = &pci_dev_read_resources,
.set_resources = &pci_dev_set_resources,
.enable_resources = &pci_dev_enable_resources,
.init = &adsp_init,
.ops_pci = &broadwell_pci_ops,
};
static const unsigned short pci_device_ids[] = {
0x9c36, /* LynxPoint */
0x9cb6, /* WildcatPoint */
0
};
static const struct pci_driver pch_adsp __pci_driver = {
.ops = &adsp_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.devices = pci_device_ids,
};

View File

@@ -0,0 +1 @@
chipset_bootblock_inc += $(src)/soc/intel/broadwell/bootblock/timestamp.inc

View File

@@ -0,0 +1,142 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <stdint.h>
#include <arch/cpu.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/mtrr.h>
#include <arch/io.h>
#include <halt.h>
#include <cpu/intel/microcode/microcode.c>
#include <soc/rcba.h>
#include <soc/msr.h>
static void set_var_mtrr(
unsigned reg, unsigned base, unsigned size, unsigned type)
{
/* Bit Bit 32-35 of MTRRphysMask should be set to 1 */
msr_t basem, maskm;
basem.lo = base | type;
basem.hi = 0;
wrmsr(MTRRphysBase_MSR(reg), basem);
maskm.lo = ~(size - 1) | MTRRphysMaskValid;
maskm.hi = (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1;
wrmsr(MTRRphysMask_MSR(reg), maskm);
}
static void enable_rom_caching(void)
{
msr_t msr;
disable_cache();
/* Why only top 4MiB ? */
set_var_mtrr(1, CACHE_ROM_BASE, CACHE_ROM_SIZE, MTRR_TYPE_WRPROT);
enable_cache();
/* Enable Variable MTRRs */
msr.hi = 0x00000000;
msr.lo = 0x00000800;
wrmsr(MTRRdefType_MSR, msr);
}
static void bootblock_mdelay(int ms)
{
u32 target = ms * 24 * 1000;
msr_t current;
msr_t start = rdmsr(MSR_COUNTER_24_MHZ);
do {
current = rdmsr(MSR_COUNTER_24_MHZ);
} while ((current.lo - start.lo) < target);
}
static void set_flex_ratio_to_tdp_nominal(void)
{
msr_t flex_ratio, msr;
u32 soft_reset;
u8 nominal_ratio;
/* Check for Flex Ratio support */
flex_ratio = rdmsr(MSR_FLEX_RATIO);
if (!(flex_ratio.lo & FLEX_RATIO_EN))
return;
/* Check for >0 configurable TDPs */
msr = rdmsr(MSR_PLATFORM_INFO);
if (((msr.hi >> 1) & 3) == 0)
return;
/* Use nominal TDP ratio for flex ratio */
msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
nominal_ratio = msr.lo & 0xff;
/* See if flex ratio is already set to nominal TDP ratio */
if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio)
return;
/* Set flex ratio to nominal TDP ratio */
flex_ratio.lo &= ~0xff00;
flex_ratio.lo |= nominal_ratio << 8;
flex_ratio.lo |= FLEX_RATIO_LOCK;
wrmsr(MSR_FLEX_RATIO, flex_ratio);
/* Set flex ratio in soft reset data register bits 11:6.
* RCBA region is enabled in southbridge bootblock */
soft_reset = RCBA32(SOFT_RESET_DATA);
soft_reset &= ~(0x3f << 6);
soft_reset |= (nominal_ratio & 0x3f) << 6;
RCBA32(SOFT_RESET_DATA) = soft_reset;
/* Set soft reset control to use register value */
RCBA32_OR(SOFT_RESET_CTRL, 1);
/* Delay before reset to avoid potential TPM lockout */
bootblock_mdelay(30);
/* Issue warm reset, will be "CPU only" due to soft reset data */
outb(0x0, 0xcf9);
outb(0x6, 0xcf9);
halt();
}
static void check_for_clean_reset(void)
{
msr_t msr;
msr = rdmsr(MTRRdefType_MSR);
/* Use the MTRR default type MSR as a proxy for detecting INIT#.
* Reset the system if any known bits are set in that MSR. That is
* an indication of the CPU not being properly reset. */
if (msr.lo & (MTRRdefTypeEn | MTRRdefTypeFixEn)) {
outb(0x0, 0xcf9);
outb(0x6, 0xcf9);
halt();
}
}
static void bootblock_cpu_init(void)
{
/* Set flex ratio and reset if needed */
set_flex_ratio_to_tdp_nominal();
check_for_clean_reset();
enable_rom_caching();
intel_update_microcode_from_cbfs();
}

View File

@@ -0,0 +1,79 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/io.h>
#include <soc/iomap.h>
#include <soc/lpc.h>
#include <soc/pci_devs.h>
#include <soc/rcba.h>
#include <soc/spi.h>
/*
* Enable Prefetching and Caching.
*/
static void enable_spi_prefetch(void)
{
u8 reg8 = pci_read_config8(PCH_DEV_LPC, 0xdc);
reg8 &= ~(3 << 2);
reg8 |= (2 << 2); /* Prefetching and Caching Enabled */
pci_write_config8(PCH_DEV_LPC, 0xdc, reg8);
}
static void map_rcba(void)
{
pci_write_config32(PCH_DEV_LPC, RCBA, RCBA_BASE_ADDRESS | 1);
}
static void enable_port80_on_lpc(void)
{
/* Enable port 80 POST on LPC. The chipset does this by default,
* but it doesn't appear to hurt anything. */
u32 gcs = RCBA32(GCS);
gcs = gcs & ~0x4;
RCBA32(GCS) = gcs;
}
static void set_spi_speed(void)
{
u32 fdod;
u8 ssfc;
/* Observe SPI Descriptor Component Section 0 */
SPIBAR32(SPIBAR_FDOC) = 0x1000;
/* Extract the Write/Erase SPI Frequency from descriptor */
fdod = SPIBAR32(SPIBAR_FDOD);
fdod >>= 24;
fdod &= 7;
/* Set Software Sequence frequency to match */
ssfc = SPIBAR8(SPIBAR_SSFC + 2);
ssfc &= ~7;
ssfc |= fdod;
SPIBAR8(SPIBAR_SSFC + 2) = ssfc;
}
static void bootblock_southbridge_init(void)
{
map_rcba();
enable_spi_prefetch();
enable_port80_on_lpc();
set_spi_speed();
}

View File

@@ -0,0 +1,44 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/io.h>
#include <soc/pci_devs.h>
#include <soc/systemagent.h>
static void bootblock_northbridge_init(void)
{
uint32_t reg;
/*
* The "io" variant of the config access is explicitly used to
* setup the PCIEXBAR because CONFIG_MMCONF_SUPPORT_DEFAULT is set to
* to true. That way all subsequent non-explicit config accesses use
* MCFG. This code also assumes that bootblock_northbridge_init() is
* the first thing called in the non-asm boot block code. The final
* assumption is that no assembly code is using the
* CONFIG_MMCONF_SUPPORT_DEFAULT option to do PCI config accesses.
*
* The PCIEXBAR is assumed to live in the memory mapped IO space under
* 4GiB.
*/
reg = 0;
pci_io_write_config32(SA_DEV_ROOT, PCIEXBAR + 4, reg);
reg = CONFIG_MMCONF_BASE_ADDRESS | 4 | 1; /* 64MiB - 0-63 buses. */
pci_io_write_config32(SA_DEV_ROOT, PCIEXBAR, reg);
}

View File

@@ -0,0 +1,19 @@
/* Store the initial timestamp for booting in mmx registers. This works
* because the bootblock isn't being compiled with MMX support so mm0 and
* mm1 will be preserved into romstage. */
.code32
.global stash_timestamp
stash_timestamp:
/* Save the BIST value */
movl %eax, %ebp
finit
rdtsc
movd %eax, %mm0
movd %edx, %mm1
/* Restore the BIST value to %eax */
movl %ebp, %eax

View File

@@ -0,0 +1,80 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <soc/pci_devs.h>
#include <soc/ramstage.h>
#include <soc/intel/broadwell/chip.h>
static void pci_domain_set_resources(device_t dev)
{
assign_resources(dev->link_list);
}
static struct device_operations pci_domain_ops = {
.read_resources = &pci_domain_read_resources,
.set_resources = &pci_domain_set_resources,
.scan_bus = &pci_domain_scan_bus,
.ops_pci_bus = &pci_bus_default_ops,
};
static struct device_operations cpu_bus_ops = {
.read_resources = DEVICE_NOOP,
.set_resources = DEVICE_NOOP,
.enable_resources = DEVICE_NOOP,
.init = &broadwell_init_cpus,
};
static void broadwell_enable(device_t dev)
{
/* Set the operations if it is a special bus type */
if (dev->path.type == DEVICE_PATH_DOMAIN) {
dev->ops = &pci_domain_ops;
} else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
dev->ops = &cpu_bus_ops;
} else if (dev->path.type == DEVICE_PATH_PCI) {
/* Handle PCH device enable */
if (PCI_SLOT(dev->path.pci.devfn) > SA_DEV_SLOT_MINIHD &&
(dev->ops == NULL || dev->ops->enable == NULL)) {
broadwell_pch_enable_dev(dev);
}
}
}
struct chip_operations soc_intel_broadwell_ops = {
CHIP_NAME("Intel Broadwell")
.enable_dev = &broadwell_enable,
.init = &broadwell_init_pre_device,
};
static void pci_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 << 16) | vendor);
}
struct pci_operations broadwell_pci_ops = {
.set_subsystem = &pci_set_subsystem
};

View File

@@ -0,0 +1,167 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2008 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _SOC_INTEL_BROADWELL_CHIP_H_
#define _SOC_INTEL_BROADWELL_CHIP_H_
struct soc_intel_broadwell_config {
/*
* Interrupt Routing configuration
* If bit7 is 1, the interrupt is disabled.
*/
uint8_t pirqa_routing;
uint8_t pirqb_routing;
uint8_t pirqc_routing;
uint8_t pirqd_routing;
uint8_t pirqe_routing;
uint8_t pirqf_routing;
uint8_t pirqg_routing;
uint8_t pirqh_routing;
/* GPE configuration */
uint32_t gpe0_en_1;
uint32_t gpe0_en_2;
uint32_t gpe0_en_3;
uint32_t gpe0_en_4;
/* GPIO SMI configuration */
uint32_t alt_gp_smi_en;
/* IDE configuration */
uint8_t sata_port_map;
uint32_t sata_port0_gen3_tx;
uint32_t sata_port1_gen3_tx;
uint32_t sata_port0_gen3_dtle;
uint32_t sata_port1_gen3_dtle;
/*
* SATA DEVSLP Mux
* 0 = port 0 DEVSLP on DEVSLP0/GPIO33
* 1 = port 3 DEVSLP on DEVSLP0/GPIO33
*/
uint8_t sata_devslp_mux;
/*
* DEVSLP Disable
* 0: DEVSLP is enabled
* 1: DEVSLP is disabled
*/
uint8_t sata_devslp_disable;
/* Generic IO decode ranges */
uint32_t gen1_dec;
uint32_t gen2_dec;
uint32_t gen3_dec;
uint32_t gen4_dec;
/* Enable linear PCIe Root Port function numbers starting at zero */
uint8_t pcie_port_coalesce;
/* Force root port ASPM configuration with port bitmap */
uint8_t pcie_port_force_aspm;
/* Put SerialIO devices into ACPI mode instead of a PCI device */
uint8_t sio_acpi_mode;
/* I2C voltage select: 0=3.3V 1=1.8V */
uint8_t sio_i2c0_voltage;
uint8_t sio_i2c1_voltage;
/* Enable ADSP power gating features */
uint8_t adsp_d3_pg_enable;
uint8_t adsp_sram_pg_enable;
/*
* Clock Disable Map:
* [21:16] = CLKOUT_PCIE# 5-0
* [24] = CLKOUT_ITPXDP
*/
uint32_t icc_clock_disable;
/*
* Digital Port Hotplug Enable:
* 0x04 = Enabled, 2ms short pulse
* 0x05 = Enabled, 4.5ms short pulse
* 0x06 = Enabled, 6ms short pulse
* 0x07 = Enabled, 100ms short pulse
*/
u8 gpu_dp_b_hotplug;
u8 gpu_dp_c_hotplug;
u8 gpu_dp_d_hotplug;
/* Panel power sequence timings */
u8 gpu_panel_port_select;
u8 gpu_panel_power_cycle_delay;
u16 gpu_panel_power_up_delay;
u16 gpu_panel_power_down_delay;
u16 gpu_panel_power_backlight_on_delay;
u16 gpu_panel_power_backlight_off_delay;
/* Panel backlight settings */
u32 gpu_cpu_backlight;
u32 gpu_pch_backlight;
/*
* Graphics CD Clock Frequency
* 0 = 337.5MHz
* 1 = 450MHz
* 2 = 540MHz
* 3 = 675MHz
*/
int cdclk;
/* Enable S0iX support */
int s0ix_enable;
/*
* Minimum voltage for C6/C7 state:
* 0x67 = 1.6V (full swing)
* ...
* 0x79 = 1.7V
* ...
* 0x83 = 1.8V (no swing)
*/
int vr_cpu_min_vid;
/*
* Set slow VR ramp rate on C-state exit:
* 0 = Fast VR ramp rate / 2
* 1 = Fast VR ramp rate / 4
* 2 = Fast VR ramp rate / 8
* 3 = Fast VR ramp rate / 16
*/
int vr_slow_ramp_rate_set;
/* Enable slow VR ramp rate */
int vr_slow_ramp_rate_enable;
/* Deep SX enable */
int deep_sx_enable_ac;
int deep_sx_enable_dc;
/* TCC activation offset */
int tcc_offset;
};
typedef struct soc_intel_broadwell_config config_t;
extern struct chip_operations soc_ops;
#endif

735
src/soc/intel/skylake/cpu.c Normal file
View File

@@ -0,0 +1,735 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <string.h>
#include <arch/acpi.h>
#include <cpu/cpu.h>
#include <cpu/x86/mtrr.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/lapic.h>
#include <cpu/x86/mp.h>
#include <cpu/intel/microcode.h>
#include <cpu/intel/speedstep.h>
#include <cpu/intel/turbo.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/name.h>
#include <cpu/x86/smm.h>
#include <delay.h>
#include <pc80/mc146818rtc.h>
#include <soc/cpu.h>
#include <soc/msr.h>
#include <soc/pci_devs.h>
#include <soc/ramstage.h>
#include <soc/rcba.h>
#include <soc/smm.h>
#include <soc/systemagent.h>
#include <soc/intel/broadwell/chip.h>
/* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */
static const u8 power_limit_time_sec_to_msr[] = {
[0] = 0x00,
[1] = 0x0a,
[2] = 0x0b,
[3] = 0x4b,
[4] = 0x0c,
[5] = 0x2c,
[6] = 0x4c,
[7] = 0x6c,
[8] = 0x0d,
[10] = 0x2d,
[12] = 0x4d,
[14] = 0x6d,
[16] = 0x0e,
[20] = 0x2e,
[24] = 0x4e,
[28] = 0x6e,
[32] = 0x0f,
[40] = 0x2f,
[48] = 0x4f,
[56] = 0x6f,
[64] = 0x10,
[80] = 0x30,
[96] = 0x50,
[112] = 0x70,
[128] = 0x11,
};
/* Convert POWER_LIMIT_1_TIME MSR value to seconds */
static const u8 power_limit_time_msr_to_sec[] = {
[0x00] = 0,
[0x0a] = 1,
[0x0b] = 2,
[0x4b] = 3,
[0x0c] = 4,
[0x2c] = 5,
[0x4c] = 6,
[0x6c] = 7,
[0x0d] = 8,
[0x2d] = 10,
[0x4d] = 12,
[0x6d] = 14,
[0x0e] = 16,
[0x2e] = 20,
[0x4e] = 24,
[0x6e] = 28,
[0x0f] = 32,
[0x2f] = 40,
[0x4f] = 48,
[0x6f] = 56,
[0x10] = 64,
[0x30] = 80,
[0x50] = 96,
[0x70] = 112,
[0x11] = 128,
};
/* The core 100MHz BLCK is disabled in deeper c-states. One needs to calibrate
* the 100MHz BCLCK against the 24MHz BLCK to restore the clocks properly
* when a core is woken up. */
static int pcode_ready(void)
{
int wait_count;
const int delay_step = 10;
wait_count = 0;
do {
if (!(MCHBAR32(BIOS_MAILBOX_INTERFACE) & MAILBOX_RUN_BUSY))
return 0;
wait_count += delay_step;
udelay(delay_step);
} while (wait_count < 1000);
return -1;
}
static void calibrate_24mhz_bclk(void)
{
int err_code;
if (pcode_ready() < 0) {
printk(BIOS_ERR, "PCODE: mailbox timeout on wait ready.\n");
return;
}
/* A non-zero value initiates the PCODE calibration. */
MCHBAR32(BIOS_MAILBOX_DATA) = ~0;
MCHBAR32(BIOS_MAILBOX_INTERFACE) =
MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_FSM_MEASURE_INTVL;
if (pcode_ready() < 0) {
printk(BIOS_ERR, "PCODE: mailbox timeout on completion.\n");
return;
}
err_code = MCHBAR32(BIOS_MAILBOX_INTERFACE) & 0xff;
printk(BIOS_DEBUG, "PCODE: 24MHz BLCK calibration response: %d\n",
err_code);
/* Read the calibrated value. */
MCHBAR32(BIOS_MAILBOX_INTERFACE) =
MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_READ_CALIBRATION;
if (pcode_ready() < 0) {
printk(BIOS_ERR, "PCODE: mailbox timeout on read.\n");
return;
}
printk(BIOS_DEBUG, "PCODE: 24MHz BLCK calibration value: 0x%08x\n",
MCHBAR32(BIOS_MAILBOX_DATA));
}
static u32 pcode_mailbox_read(u32 command)
{
if (pcode_ready() < 0) {
printk(BIOS_ERR, "PCODE: mailbox timeout on wait ready.\n");
return 0;
}
/* Send command and start transaction */
MCHBAR32(BIOS_MAILBOX_INTERFACE) = command | MAILBOX_RUN_BUSY;
if (pcode_ready() < 0) {
printk(BIOS_ERR, "PCODE: mailbox timeout on completion.\n");
return 0;
}
/* Read mailbox */
return MCHBAR32(BIOS_MAILBOX_DATA);
}
static int pcode_mailbox_write(u32 command, u32 data)
{
if (pcode_ready() < 0) {
printk(BIOS_ERR, "PCODE: mailbox timeout on wait ready.\n");
return -1;
}
MCHBAR32(BIOS_MAILBOX_DATA) = data;
/* Send command and start transaction */
MCHBAR32(BIOS_MAILBOX_INTERFACE) = command | MAILBOX_RUN_BUSY;
if (pcode_ready() < 0) {
printk(BIOS_ERR, "PCODE: mailbox timeout on completion.\n");
return -1;
}
return 0;
}
static void initialize_vr_config(void)
{
device_t dev = SA_DEV_ROOT;
config_t *conf = dev->chip_info;
msr_t msr;
printk(BIOS_DEBUG, "Initializing VR config.\n");
/* Configure VR_CURRENT_CONFIG. */
msr = rdmsr(MSR_VR_CURRENT_CONFIG);
/* Preserve bits 63 and 62. Bit 62 is PSI4 enable, but it is only valid
* on ULT systems. */
msr.hi &= 0xc0000000;
msr.hi |= (0x01 << (52 - 32)); /* PSI3 threshold - 1A. */
msr.hi |= (0x05 << (42 - 32)); /* PSI2 threshold - 5A. */
msr.hi |= (0x14 << (32 - 32)); /* PSI1 threshold - 20A. */
msr.hi |= (1 << (62 - 32)); /* Enable PSI4 */
/* Leave the max instantaneous current limit (12:0) to default. */
wrmsr(MSR_VR_CURRENT_CONFIG, msr);
/* Configure VR_MISC_CONFIG MSR. */
msr = rdmsr(MSR_VR_MISC_CONFIG);
/* Set the IOUT_SLOPE scalar applied to dIout in U10.1.9 format. */
msr.hi &= ~(0x3ff << (40 - 32));
msr.hi |= (0x200 << (40 - 32)); /* 1.0 */
/* Set IOUT_OFFSET to 0. */
msr.hi &= ~0xff;
/* Set entry ramp rate to slow. */
msr.hi &= ~(1 << (51 - 32));
/* Enable decay mode on C-state entry. */
msr.hi |= (1 << (52 - 32));
/* Set the slow ramp rate */
msr.hi &= ~(0x3 << (53 - 32));
/* Configure the C-state exit ramp rate. */
if (conf->vr_slow_ramp_rate_enable) {
/* Configured slow ramp rate. */
msr.hi |= ((conf->vr_slow_ramp_rate_set & 0x3) << (53 - 32));
/* Set exit ramp rate to slow. */
msr.hi &= ~(1 << (50 - 32));
} else {
/* Fast ramp rate / 4. */
msr.hi |= (0x01 << (53 - 32));
/* Set exit ramp rate to fast. */
msr.hi |= (1 << (50 - 32));
}
/* Set MIN_VID (31:24) to allow CPU to have full control. */
msr.lo &= ~0xff000000;
msr.lo |= (conf->vr_cpu_min_vid & 0xff) << 24;
wrmsr(MSR_VR_MISC_CONFIG, msr);
/* Configure VR_MISC_CONFIG2 MSR. */
msr = rdmsr(MSR_VR_MISC_CONFIG2);
msr.lo &= ~0xffff;
/* Allow CPU to control minimum voltage completely (15:8) and
* set the fast ramp voltage in 10mV steps. */
if (cpu_family_model() == BROADWELL_FAMILY_ULT)
msr.lo |= 0x006a; /* 1.56V */
else
msr.lo |= 0x006f; /* 1.60V */
wrmsr(MSR_VR_MISC_CONFIG2, msr);
/* Set C9/C10 VCC Min */
pcode_mailbox_write(MAILBOX_BIOS_CMD_WRITE_C9C10_VOLTAGE, 0x1f1f);
}
static void configure_pch_power_sharing(void)
{
u32 pch_power, pch_power_ext, pmsync, pmsync2;
int i;
/* Read PCH Power levels from PCODE */
pch_power = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_PCH_POWER);
pch_power_ext = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_PCH_POWER_EXT);
printk(BIOS_INFO, "PCH Power: PCODE Levels 0x%08x 0x%08x\n",
pch_power, pch_power_ext);
pmsync = RCBA32(PMSYNC_CONFIG);
pmsync2 = RCBA32(PMSYNC_CONFIG2);
/* Program PMSYNC_TPR_CONFIG PCH power limit values
* pmsync[0:4] = mailbox[0:5]
* pmsync[8:12] = mailbox[6:11]
* pmsync[16:20] = mailbox[12:17]
*/
for (i = 0; i < 3; i++) {
u32 level = pch_power & 0x3f;
pch_power >>= 6;
pmsync &= ~(0x1f << (i * 8));
pmsync |= (level & 0x1f) << (i * 8);
}
RCBA32(PMSYNC_CONFIG) = pmsync;
/* Program PMSYNC_TPR_CONFIG2 Extended PCH power limit values
* pmsync2[0:4] = mailbox[23:18]
* pmsync2[8:12] = mailbox_ext[6:11]
* pmsync2[16:20] = mailbox_ext[12:17]
* pmsync2[24:28] = mailbox_ext[18:22]
*/
pmsync2 &= ~0x1f;
pmsync2 |= pch_power & 0x1f;
for (i = 1; i < 4; i++) {
u32 level = pch_power_ext & 0x3f;
pch_power_ext >>= 6;
pmsync2 &= ~(0x1f << (i * 8));
pmsync2 |= (level & 0x1f) << (i * 8);
}
RCBA32(PMSYNC_CONFIG2) = pmsync2;
}
int cpu_config_tdp_levels(void)
{
msr_t platform_info;
/* Bits 34:33 indicate how many levels supported */
platform_info = rdmsr(MSR_PLATFORM_INFO);
return (platform_info.hi >> 1) & 3;
}
/*
* Configure processor power limits if possible
* This must be done AFTER set of BIOS_RESET_CPL
*/
void set_power_limits(u8 power_limit_1_time)
{
msr_t msr = rdmsr(MSR_PLATFORM_INFO);
msr_t limit;
unsigned power_unit;
unsigned tdp, min_power, max_power, max_time;
u8 power_limit_1_val;
if (power_limit_1_time > ARRAY_SIZE(power_limit_time_sec_to_msr))
power_limit_1_time = 28;
if (!(msr.lo & PLATFORM_INFO_SET_TDP))
return;
/* Get units */
msr = rdmsr(MSR_PKG_POWER_SKU_UNIT);
power_unit = 2 << ((msr.lo & 0xf) - 1);
/* Get power defaults for this SKU */
msr = rdmsr(MSR_PKG_POWER_SKU);
tdp = msr.lo & 0x7fff;
min_power = (msr.lo >> 16) & 0x7fff;
max_power = msr.hi & 0x7fff;
max_time = (msr.hi >> 16) & 0x7f;
printk(BIOS_DEBUG, "CPU TDP: %u Watts\n", tdp / power_unit);
if (power_limit_time_msr_to_sec[max_time] > power_limit_1_time)
power_limit_1_time = power_limit_time_msr_to_sec[max_time];
if (min_power > 0 && tdp < min_power)
tdp = min_power;
if (max_power > 0 && tdp > max_power)
tdp = max_power;
power_limit_1_val = power_limit_time_sec_to_msr[power_limit_1_time];
/* Set long term power limit to TDP */
limit.lo = 0;
limit.lo |= tdp & PKG_POWER_LIMIT_MASK;
limit.lo |= PKG_POWER_LIMIT_EN;
limit.lo |= (power_limit_1_val & PKG_POWER_LIMIT_TIME_MASK) <<
PKG_POWER_LIMIT_TIME_SHIFT;
/* Set short term power limit to 1.25 * TDP */
limit.hi = 0;
limit.hi |= ((tdp * 125) / 100) & PKG_POWER_LIMIT_MASK;
limit.hi |= PKG_POWER_LIMIT_EN;
/* Power limit 2 time is only programmable on server SKU */
wrmsr(MSR_PKG_POWER_LIMIT, limit);
/* Set power limit values in MCHBAR as well */
MCHBAR32(MCH_PKG_POWER_LIMIT_LO) = limit.lo;
MCHBAR32(MCH_PKG_POWER_LIMIT_HI) = limit.hi;
/* Set DDR RAPL power limit by copying from MMIO to MSR */
msr.lo = MCHBAR32(MCH_DDR_POWER_LIMIT_LO);
msr.hi = MCHBAR32(MCH_DDR_POWER_LIMIT_HI);
wrmsr(MSR_DDR_RAPL_LIMIT, msr);
/* Use nominal TDP values for CPUs with configurable TDP */
if (cpu_config_tdp_levels()) {
msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
limit.hi = 0;
limit.lo = msr.lo & 0xff;
wrmsr(MSR_TURBO_ACTIVATION_RATIO, limit);
}
}
static void configure_c_states(void)
{
msr_t msr;
msr = rdmsr(MSR_PMG_CST_CONFIG_CONTROL);
msr.lo |= (1 << 31); // Timed MWAIT Enable
msr.lo |= (1 << 30); // Package c-state Undemotion Enable
msr.lo |= (1 << 29); // Package c-state Demotion Enable
msr.lo |= (1 << 28); // C1 Auto Undemotion Enable
msr.lo |= (1 << 27); // C3 Auto Undemotion Enable
msr.lo |= (1 << 26); // C1 Auto Demotion Enable
msr.lo |= (1 << 25); // C3 Auto Demotion Enable
msr.lo &= ~(1 << 10); // Disable IO MWAIT redirection
/* The deepest package c-state defaults to factory-configured value. */
wrmsr(MSR_PMG_CST_CONFIG_CONTROL, msr);
msr = rdmsr(MSR_MISC_PWR_MGMT);
msr.lo &= ~(1 << 0); // Enable P-state HW_ALL coordination
wrmsr(MSR_MISC_PWR_MGMT, msr);
msr = rdmsr(MSR_POWER_CTL);
msr.lo |= (1 << 18); // Enable Energy Perf Bias MSR 0x1b0
msr.lo |= (1 << 1); // C1E Enable
msr.lo |= (1 << 0); // Bi-directional PROCHOT#
wrmsr(MSR_POWER_CTL, msr);
/* C-state Interrupt Response Latency Control 0 - package C3 latency */
msr.hi = 0;
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_0_LIMIT;
wrmsr(MSR_C_STATE_LATENCY_CONTROL_0, msr);
/* C-state Interrupt Response Latency Control 1 */
msr.hi = 0;
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_1_LIMIT;
wrmsr(MSR_C_STATE_LATENCY_CONTROL_1, msr);
/* C-state Interrupt Response Latency Control 2 - package C6/C7 short */
msr.hi = 0;
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_2_LIMIT;
wrmsr(MSR_C_STATE_LATENCY_CONTROL_2, msr);
/* C-state Interrupt Response Latency Control 3 - package C8 */
msr.hi = 0;
msr.lo = IRTL_VALID | IRTL_1024_NS |
C_STATE_LATENCY_CONTROL_3_LIMIT;
wrmsr(MSR_C_STATE_LATENCY_CONTROL_3, msr);
/* C-state Interrupt Response Latency Control 4 - package C9 */
msr.hi = 0;
msr.lo = IRTL_VALID | IRTL_1024_NS |
C_STATE_LATENCY_CONTROL_4_LIMIT;
wrmsr(MSR_C_STATE_LATENCY_CONTROL_4, msr);
/* C-state Interrupt Response Latency Control 5 - package C10 */
msr.hi = 0;
msr.lo = IRTL_VALID | IRTL_1024_NS |
C_STATE_LATENCY_CONTROL_5_LIMIT;
wrmsr(MSR_C_STATE_LATENCY_CONTROL_5, msr);
}
static void configure_thermal_target(void)
{
device_t dev = SA_DEV_ROOT;
config_t *conf = dev->chip_info;
msr_t msr;
/* Set TCC activation offset if supported */
msr = rdmsr(MSR_PLATFORM_INFO);
if ((msr.lo & (1 << 30)) && conf->tcc_offset) {
msr = rdmsr(MSR_TEMPERATURE_TARGET);
msr.lo &= ~(0xf << 24); /* Bits 27:24 */
msr.lo |= (conf->tcc_offset & 0xf) << 24;
wrmsr(MSR_TEMPERATURE_TARGET, msr);
}
}
static void configure_misc(void)
{
msr_t msr;
msr = rdmsr(IA32_MISC_ENABLE);
msr.lo |= (1 << 0); /* Fast String enable */
msr.lo |= (1 << 3); /* TM1/TM2/EMTTM enable */
msr.lo |= (1 << 16); /* Enhanced SpeedStep Enable */
wrmsr(IA32_MISC_ENABLE, msr);
/* Disable Thermal interrupts */
msr.lo = 0;
msr.hi = 0;
wrmsr(IA32_THERM_INTERRUPT, msr);
/* Enable package critical interrupt only */
msr.lo = 1 << 4;
msr.hi = 0;
wrmsr(IA32_PACKAGE_THERM_INTERRUPT, msr);
}
static void enable_lapic_tpr(void)
{
msr_t msr;
msr = rdmsr(MSR_PIC_MSG_CONTROL);
msr.lo &= ~(1 << 10); /* Enable APIC TPR updates */
wrmsr(MSR_PIC_MSG_CONTROL, msr);
}
static void configure_dca_cap(void)
{
struct cpuid_result cpuid_regs;
msr_t msr;
/* Check feature flag in CPUID.(EAX=1):ECX[18]==1 */
cpuid_regs = cpuid(1);
if (cpuid_regs.ecx & (1 << 18)) {
msr = rdmsr(IA32_PLATFORM_DCA_CAP);
msr.lo |= 1;
wrmsr(IA32_PLATFORM_DCA_CAP, msr);
}
}
static void set_max_ratio(void)
{
msr_t msr, perf_ctl;
perf_ctl.hi = 0;
/* Check for configurable TDP option */
if (get_turbo_state() == TURBO_ENABLED) {
msr = rdmsr(MSR_TURBO_RATIO_LIMIT);
perf_ctl.lo = (msr.lo & 0xff) << 8;
} else if (cpu_config_tdp_levels()) {
/* Set to nominal TDP ratio */
msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
perf_ctl.lo = (msr.lo & 0xff) << 8;
} else {
/* Platform Info bits 15:8 give max ratio */
msr = rdmsr(MSR_PLATFORM_INFO);
perf_ctl.lo = msr.lo & 0xff00;
}
wrmsr(IA32_PERF_CTL, perf_ctl);
printk(BIOS_DEBUG, "cpu: frequency set to %d\n",
((perf_ctl.lo >> 8) & 0xff) * CPU_BCLK);
}
static void set_energy_perf_bias(u8 policy)
{
msr_t msr;
int ecx;
/* Determine if energy efficient policy is supported. */
ecx = cpuid_ecx(0x6);
if (!(ecx & (1 << 3)))
return;
/* Energy Policy is bits 3:0 */
msr = rdmsr(IA32_ENERGY_PERFORMANCE_BIAS);
msr.lo &= ~0xf;
msr.lo |= policy & 0xf;
wrmsr(IA32_ENERGY_PERFORMANCE_BIAS, msr);
printk(BIOS_DEBUG, "cpu: energy policy set to %u\n", policy);
}
static void configure_mca(void)
{
msr_t msr;
const unsigned int mcg_cap_msr = 0x179;
int i;
int num_banks;
msr = rdmsr(mcg_cap_msr);
num_banks = msr.lo & 0xff;
msr.lo = msr.hi = 0;
/* TODO(adurbin): This should only be done on a cold boot. Also, some
* of these banks are core vs package scope. For now every CPU clears
* every bank. */
for (i = 0; i < num_banks; i++)
wrmsr(IA32_MC0_STATUS + (i * 4), msr);
}
#if CONFIG_USBDEBUG
static unsigned ehci_debug_addr;
#endif
static void bsp_init_before_ap_bringup(struct bus *cpu_bus)
{
#if CONFIG_USBDEBUG
if(!ehci_debug_addr)
ehci_debug_addr = get_ehci_debug();
set_ehci_debug(0);
#endif
/* Setup MTRRs based on physical address size. */
x86_setup_fixed_mtrrs();
x86_setup_var_mtrrs(cpuid_eax(0x80000008) & 0xff, 2);
x86_mtrr_check();
#if CONFIG_USBDEBUG
set_ehci_debug(ehci_debug_addr);
#endif
initialize_vr_config();
calibrate_24mhz_bclk();
configure_pch_power_sharing();
}
/* All CPUs including BSP will run the following function. */
static void cpu_core_init(device_t cpu)
{
/* Clear out pending MCEs */
configure_mca();
/* Enable the local cpu apics */
enable_lapic_tpr();
setup_lapic();
/* Configure C States */
configure_c_states();
/* Configure Enhanced SpeedStep and Thermal Sensors */
configure_misc();
/* Thermal throttle activation offset */
configure_thermal_target();
/* Enable Direct Cache Access */
configure_dca_cap();
/* Set energy policy */
set_energy_perf_bias(ENERGY_POLICY_NORMAL);
/* Enable Turbo */
enable_turbo();
}
/* MP initialization support. */
static const void *microcode_patch;
int ht_disabled;
static int adjust_apic_id_ht_disabled(int index, int apic_id)
{
return 2 * index;
}
static void relocate_and_load_microcode(void *unused)
{
/* Relocate the SMM handler. */
smm_relocate();
/* After SMM relocation a 2nd microcode load is required. */
intel_microcode_load_unlocked(microcode_patch);
}
static void enable_smis(void *unused)
{
/* Now that all APs have been relocated as well as the BSP let SMIs
* start flowing. */
southbridge_smm_enable_smi();
/* Lock down the SMRAM space. */
smm_lock();
}
static struct mp_flight_record mp_steps[] = {
MP_FR_NOBLOCK_APS(relocate_and_load_microcode, NULL,
relocate_and_load_microcode, NULL),
MP_FR_BLOCK_APS(mp_initialize_cpu, NULL, mp_initialize_cpu, NULL),
/* Wait for APs to finish initialization before proceeding. */
MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL),
};
static struct device_operations cpu_dev_ops = {
.init = cpu_core_init,
};
static struct cpu_device_id cpu_table[] = {
{ X86_VENDOR_INTEL, CPUID_HASWELL_ULT },
{ X86_VENDOR_INTEL, CPUID_BROADWELL_C0 },
{ X86_VENDOR_INTEL, CPUID_BROADWELL_D0 },
{ X86_VENDOR_INTEL, CPUID_BROADWELL_E0 },
{ 0, 0 },
};
static const struct cpu_driver driver __cpu_driver = {
.ops = &cpu_dev_ops,
.id_table = cpu_table,
};
void broadwell_init_cpus(device_t dev)
{
struct bus *cpu_bus = dev->link_list;
int num_threads;
int num_cores;
msr_t msr;
struct mp_params mp_params;
void *smm_save_area;
msr = rdmsr(CORE_THREAD_COUNT_MSR);
num_threads = (msr.lo >> 0) & 0xffff;
num_cores = (msr.lo >> 16) & 0xffff;
printk(BIOS_DEBUG, "CPU has %u cores, %u threads enabled.\n",
num_cores, num_threads);
ht_disabled = num_threads == num_cores;
/* Perform any necessary BSP initialization before APs are brought up.
* This call also allows the BSP to prepare for any secondary effects
* from calling cpu_initialize() such as smm_init(). */
bsp_init_before_ap_bringup(cpu_bus);
microcode_patch = intel_microcode_find();
/* Save default SMM area before relocation occurs. */
smm_save_area = backup_default_smm_area();
mp_params.num_cpus = num_threads;
mp_params.parallel_microcode_load = 1;
if (ht_disabled)
mp_params.adjust_apic_id = adjust_apic_id_ht_disabled;
else
mp_params.adjust_apic_id = NULL;
mp_params.flight_plan = &mp_steps[0];
mp_params.num_records = ARRAY_SIZE(mp_steps);
mp_params.microcode_pointer = microcode_patch;
/* Load relocation and permanent handlers. Then initiate relocation. */
if (smm_initialize())
printk(BIOS_CRIT, "SMM initialization failed...\n");
if (mp_init(cpu_bus, &mp_params)) {
printk(BIOS_ERR, "MP initialization failure.\n");
}
/* Set Max Ratio */
set_max_ratio();
/* Restore the default SMM region. */
restore_default_smm_area(smm_save_area);
}

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <console/console.h>
#include <cpu/cpu.h>
#include <cpu/x86/msr.h>
#include <soc/cpu.h>
#include <soc/msr.h>
#include <soc/systemagent.h>
u32 cpu_family_model(void)
{
return cpuid_eax(1) & 0x0fff0ff0;
}
u32 cpu_stepping(void)
{
return cpuid_eax(1) & 0xf;
}
/* Dynamically determine if the part is ULT. */
int cpu_is_ult(void)
{
static int ult = -1;
if (ult < 0) {
u32 fm = cpu_family_model();
if (fm == BROADWELL_FAMILY_ULT || fm == HASWELL_FAMILY_ULT)
ult = 1;
else
ult = 0;
}
return ult;
}

View File

@@ -0,0 +1,103 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <console/console.h>
#include <delay.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <arch/io.h>
#include <soc/ehci.h>
#include <soc/pch.h>
static void usb_ehci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
{
u8 access_cntl;
access_cntl = pci_read_config8(dev, 0x80);
/* Enable writes to protected registers. */
pci_write_config8(dev, 0x80, access_cntl | 1);
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));
}
/* Restore protection. */
pci_write_config8(dev, 0x80, access_cntl);
}
static void usb_ehci_set_resources(struct device *dev)
{
#if CONFIG_USBDEBUG
struct resource *res;
u32 base;
u32 usb_debug;
usb_debug = get_ehci_debug();
set_ehci_debug(0);
#endif
pci_dev_set_resources(dev);
#if CONFIG_USBDEBUG
res = find_resource(dev, 0x10);
set_ehci_debug(usb_debug);
if (!res) return;
base = res->base;
set_ehci_base(base);
report_resource_stored(dev, res, "");
#endif
}
static void ehci_enable(struct device *dev)
{
if (CONFIG_USBDEBUG)
dev->enabled = 1;
else
pch_disable_devfn(dev);
}
static struct pci_operations ehci_ops_pci = {
.set_subsystem = &usb_ehci_set_subsystem,
};
static struct device_operations usb_ehci_ops = {
.read_resources = &pci_dev_read_resources,
.set_resources = &usb_ehci_set_resources,
.enable_resources = &pci_dev_enable_resources,
.ops_pci = &ehci_ops_pci,
.enable = &ehci_enable,
};
static const unsigned short pci_device_ids[] = {
0x9c26, /* LynxPoint-LP */
0x9ca6, /* WildcatPoint */
0
};
static const struct pci_driver pch_usb_ehci __pci_driver = {
.ops = &usb_ehci_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.devices = pci_device_ids,
};

View File

@@ -0,0 +1,141 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <bootstate.h>
#include <cbmem.h>
#include <console/console.h>
#include <stdint.h>
#include <elog.h>
#include <soc/lpc.h>
#include <soc/pm.h>
static void pch_log_gpio_gpe(u32 gpe0_sts, u32 gpe0_en, int start)
{
int i;
gpe0_sts &= gpe0_en;
for (i = 0; i <= 31; i++) {
if (gpe0_sts & (1 << i))
elog_add_event_wake(ELOG_WAKE_SOURCE_GPIO, i + start);
}
}
static void pch_log_wake_source(struct chipset_power_state *ps)
{
/* Power Button */
if (ps->pm1_sts & PWRBTN_STS)
elog_add_event_wake(ELOG_WAKE_SOURCE_PWRBTN, 0);
/* RTC */
if (ps->pm1_sts & RTC_STS)
elog_add_event_wake(ELOG_WAKE_SOURCE_RTC, 0);
/* PCI Express (TODO: determine wake device) */
if (ps->pm1_sts & PCIEXPWAK_STS)
elog_add_event_wake(ELOG_WAKE_SOURCE_PCIE, 0);
/* PME (TODO: determine wake device) */
if (ps->gpe0_sts[GPE_STD] & PME_STS)
elog_add_event_wake(ELOG_WAKE_SOURCE_PME, 0);
/* Internal PME (TODO: determine wake device) */
if (ps->gpe0_sts[GPE_STD] & PME_B0_STS)
elog_add_event_wake(ELOG_WAKE_SOURCE_PME_INTERNAL, 0);
/* SMBUS Wake */
if (ps->gpe0_sts[GPE_STD] & SMB_WAK_STS)
elog_add_event_wake(ELOG_WAKE_SOURCE_SMBUS, 0);
/* GPIO27 */
if (ps->gpe0_sts[GPE_STD] & GP27_STS)
elog_add_event_wake(ELOG_WAKE_SOURCE_GPIO, 27);
/* Log GPIO events in set 1-3 */
pch_log_gpio_gpe(ps->gpe0_sts[GPE_31_0], ps->gpe0_en[GPE_31_0], 0);
pch_log_gpio_gpe(ps->gpe0_sts[GPE_63_32], ps->gpe0_en[GPE_63_32], 32);
pch_log_gpio_gpe(ps->gpe0_sts[GPE_94_64], ps->gpe0_en[GPE_94_64], 64);
}
static void pch_log_power_and_resets(struct chipset_power_state *ps)
{
/* Thermal Trip Status */
if (ps->gen_pmcon2 & THERMTRIP_STS)
elog_add_event(ELOG_TYPE_THERM_TRIP);
/* PWR_FLR Power Failure */
if (ps->gen_pmcon2 & PWROK_FLR)
elog_add_event(ELOG_TYPE_POWER_FAIL);
/* SUS Well Power Failure */
if (ps->gen_pmcon3 & SUS_PWR_FLR)
elog_add_event(ELOG_TYPE_SUS_POWER_FAIL);
/* SYS_PWROK Failure */
if (ps->gen_pmcon2 & SYSPWR_FLR)
elog_add_event(ELOG_TYPE_SYS_PWROK_FAIL);
/* PWROK Failure */
if (ps->gen_pmcon2 & PWROK_FLR)
elog_add_event(ELOG_TYPE_PWROK_FAIL);
/* TCO Timeout */
if (ps->prev_sleep_state != 3 &&
ps->tco2_sts & TCO2_STS_SECOND_TO)
elog_add_event(ELOG_TYPE_TCO_RESET);
/* Power Button Override */
if (ps->pm1_sts & PRBTNOR_STS)
elog_add_event(ELOG_TYPE_POWER_BUTTON_OVERRIDE);
/* RTC reset */
if (ps->gen_pmcon3 & RTC_BATTERY_DEAD)
elog_add_event(ELOG_TYPE_RTC_RESET);
/* System Reset Status (reset button pushed) */
if (ps->gen_pmcon2 & SYSTEM_RESET_STS)
elog_add_event(ELOG_TYPE_RESET_BUTTON);
/* General Reset Status */
if (ps->gen_pmcon3 & GEN_RST_STS)
elog_add_event(ELOG_TYPE_SYSTEM_RESET);
/* ACPI Wake Event */
if (ps->prev_sleep_state != SLEEP_STATE_S0)
elog_add_event_byte(ELOG_TYPE_ACPI_WAKE, ps->prev_sleep_state);
}
static void pch_log_state(void *unused)
{
struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE);
if (ps == NULL) {
printk(BIOS_ERR, "Not logging power state information. "
"Power state not found in cbmem.\n");
return;
}
/* Power and Reset */
pch_log_power_and_resets(ps);
/* Wake Sources */
pch_log_wake_source(ps);
}
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, pch_log_state, NULL);

View File

@@ -0,0 +1,126 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/io.h>
#include <bootstate.h>
#include <console/console.h>
#include <console/post_codes.h>
#include <cpu/x86/smm.h>
#include <reg_script.h>
#include <spi-generic.h>
#include <stdlib.h>
#include <soc/pci_devs.h>
#include <soc/lpc.h>
#include <soc/me.h>
#include <soc/rcba.h>
#include <soc/spi.h>
#include <soc/systemagent.h>
const struct reg_script system_agent_finalize_script[] = {
REG_PCI_OR16(0x50, 1 << 0), /* GGC */
REG_PCI_OR32(0x5c, 1 << 0), /* DPR */
REG_PCI_OR32(0x78, 1 << 10), /* ME */
REG_PCI_OR32(0x90, 1 << 0), /* REMAPBASE */
REG_PCI_OR32(0x98, 1 << 0), /* REMAPLIMIT */
REG_PCI_OR32(0xa0, 1 << 0), /* TOM */
REG_PCI_OR32(0xa8, 1 << 0), /* TOUUD */
REG_PCI_OR32(0xb0, 1 << 0), /* BDSM */
REG_PCI_OR32(0xb4, 1 << 0), /* BGSM */
REG_PCI_OR32(0xb8, 1 << 0), /* TSEGMB */
REG_PCI_OR32(0xbc, 1 << 0), /* TOLUD */
REG_MMIO_OR32(MCH_BASE_ADDRESS + 0x5500, 1 << 0), /* PAVP */
REG_MMIO_OR32(MCH_BASE_ADDRESS + 0x5f00, 1 << 31), /* SA PM */
REG_MMIO_OR32(MCH_BASE_ADDRESS + 0x6020, 1 << 0), /* UMA GFX */
REG_MMIO_OR32(MCH_BASE_ADDRESS + 0x63fc, 1 << 0), /* VTDTRK */
REG_MMIO_OR32(MCH_BASE_ADDRESS + 0x6800, 1 << 31),
REG_MMIO_OR32(MCH_BASE_ADDRESS + 0x7000, 1 << 31),
REG_MMIO_OR32(MCH_BASE_ADDRESS + 0x77fc, 1 << 0),
REG_MMIO_OR32(MCH_BASE_ADDRESS + 0x50fc, 0x8f),
REG_MMIO_OR32(MCH_BASE_ADDRESS + 0x7ffc, 1 << 0),
REG_MMIO_OR32(MCH_BASE_ADDRESS + 0x5880, 1 << 5),
REG_MMIO_WRITE8(MCH_BASE_ADDRESS + 0x50fc, 0x8f), /* MC */
REG_SCRIPT_END
};
const struct reg_script pch_finalize_script[] = {
/* Set SPI opcode menu */
REG_MMIO_WRITE16(RCBA_BASE_ADDRESS + SPIBAR_OFFSET + SPIBAR_PREOP,
SPI_OPPREFIX),
REG_MMIO_WRITE16(RCBA_BASE_ADDRESS + SPIBAR_OFFSET + SPIBAR_OPTYPE,
SPI_OPTYPE),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + SPIBAR_OFFSET +
SPIBAR_OPMENU_LOWER, SPI_OPMENU_LOWER),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + SPIBAR_OFFSET +
SPIBAR_OPMENU_UPPER, SPI_OPMENU_UPPER),
/* Lock SPIBAR */
REG_MMIO_OR32(RCBA_BASE_ADDRESS + SPIBAR_OFFSET + SPIBAR_HSFS,
SPIBAR_HSFS_FLOCKDN),
/* TC Lockdown */
REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x0050, (1 << 31)),
/* BIOS Interface Lockdown */
REG_MMIO_OR32(RCBA_BASE_ADDRESS + GCS, (1 << 0)),
/* Function Disable SUS Well Lockdown */
REG_MMIO_OR8(RCBA_BASE_ADDRESS + FDSW, (1 << 7)),
/* Global SMI Lock */
REG_PCI_OR16(GEN_PMCON_1, SMI_LOCK),
/* GEN_PMCON Lock */
REG_PCI_OR8(GEN_PMCON_LOCK, SLP_STR_POL_LOCK | ACPI_BASE_LOCK),
/* PMSYNC */
REG_MMIO_OR32(RCBA_BASE_ADDRESS + PMSYNC_CONFIG, (1 << 31)),
REG_SCRIPT_END
};
static void broadwell_finalize(void *unused)
{
printk(BIOS_DEBUG, "Finalizing chipset.\n");
reg_script_run_on_dev(SA_DEV_ROOT, system_agent_finalize_script);
reg_script_run_on_dev(PCH_DEV_LPC, pch_finalize_script);
/* Lock */
RCBA32_OR(0x3a6c, 0x00000001);
/* Read+Write the following registers */
MCHBAR32(0x6030) = MCHBAR32(0x6030);
MCHBAR32(0x6034) = MCHBAR32(0x6034);
MCHBAR32(0x6008) = MCHBAR32(0x6008);
RCBA32(0x21a4) = RCBA32(0x21a4);
/* Re-init SPI after lockdown */
spi_init();
printk(BIOS_DEBUG, "Finalizing SMM.\n");
outb(APM_CNT_FINALIZE, APM_CNT);
/* Indicate finalize step with post code */
post_code(POST_OS_BOOT);
}
BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, broadwell_finalize, NULL);
BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, broadwell_finalize, NULL);

View File

@@ -0,0 +1,199 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <stdint.h>
#include <string.h>
#include <arch/io.h>
#include <device/device.h>
#include <device/pci.h>
#include <soc/gpio.h>
#include <soc/iomap.h>
#include <soc/pm.h>
/*
* This function will return a number that indicates which PIRQ
* this GPIO maps to. If this is not a PIRQ capable GPIO then
* it will return -1. The GPIO to PIRQ mapping is not linear.
*/
static int gpio_to_pirq(int gpio)
{
switch (gpio) {
case 8: return 0; /* PIRQI */
case 9: return 1; /* PIRQJ */
case 10: return 2; /* PIRQK */
case 13: return 3; /* PIRQL */
case 14: return 4; /* PIRQM */
case 45: return 5; /* PIRQN */
case 46: return 6; /* PIRQO */
case 47: return 7; /* PIRQP */
case 48: return 8; /* PIRQQ */
case 49: return 9; /* PIRQR */
case 50: return 10; /* PIRQS */
case 51: return 11; /* PIRQT */
case 52: return 12; /* PIRQU */
case 53: return 13; /* PIRQV */
case 54: return 14; /* PIRQW */
case 55: return 15; /* PIRQX */
default: return -1;
};
}
void init_one_gpio(int gpio_num, struct gpio_config *config)
{
u32 owner, route, irqen, reset;
int set, bit;
if (gpio_num > MAX_GPIO_NUMBER || !config)
return;
outl(config->conf0, GPIO_BASE_ADDRESS + GPIO_CONFIG0(gpio_num));
outl(config->conf1, GPIO_BASE_ADDRESS + GPIO_CONFIG1(gpio_num));
/* Determine set and bit based on GPIO number */
set = gpio_num >> 5;
bit = gpio_num % 32;
/* Save settings from current GPIO config */
owner = inl(GPIO_BASE_ADDRESS + GPIO_OWNER(set));
route = inl(GPIO_BASE_ADDRESS + GPIO_ROUTE(set));
irqen = inl(GPIO_BASE_ADDRESS + GPIO_IRQ_IE(set));
reset = inl(GPIO_BASE_ADDRESS + GPIO_RESET(set));
owner |= config->owner << bit;
route |= config->route << bit;
irqen |= config->irqen << bit;
reset |= config->reset << bit;
outl(owner, GPIO_BASE_ADDRESS + GPIO_OWNER(set));
outl(route, GPIO_BASE_ADDRESS + GPIO_ROUTE(set));
outl(irqen, GPIO_BASE_ADDRESS + GPIO_IRQ_IE(set));
outl(reset, GPIO_BASE_ADDRESS + GPIO_RESET(set));
if (set == 0) {
u32 blink = inl(GPIO_BASE_ADDRESS + GPIO_BLINK);
blink |= config->blink << bit;
outl(blink, GPIO_BASE_ADDRESS + GPIO_BLINK);
}
/* PIRQ to IO-APIC map */
if (config->pirq == GPIO_PIRQ_APIC_ROUTE) {
u32 pirq2apic = inl(GPIO_BASE_ADDRESS + GPIO_PIRQ_APIC_EN);
set = gpio_to_pirq(gpio_num);
if (set >= 0) {
pirq2apic |= 1 << set;
outl(pirq2apic, GPIO_BASE_ADDRESS + GPIO_PIRQ_APIC_EN);
}
}
}
void init_gpios(const struct gpio_config config[])
{
const struct gpio_config *entry;
u32 owner[3] = {0};
u32 route[3] = {0};
u32 irqen[3] = {0};
u32 reset[3] = {0};
u32 blink = 0;
u16 pirq2apic = 0;
int set, bit, gpio = 0;
for (entry = config; entry->conf0 != GPIO_LIST_END; entry++, gpio++) {
if (gpio > MAX_GPIO_NUMBER)
break;
/* Setup Configuration registers 1 and 2 */
outl(entry->conf0, GPIO_BASE_ADDRESS + GPIO_CONFIG0(gpio));
outl(entry->conf1, GPIO_BASE_ADDRESS + GPIO_CONFIG1(gpio));
/* Determine set and bit based on GPIO number */
set = gpio >> 5;
bit = gpio % 32;
/* Apply settings to set specific bits */
owner[set] |= entry->owner << bit;
route[set] |= entry->route << bit;
irqen[set] |= entry->irqen << bit;
reset[set] |= entry->reset << bit;
if (set == 0)
blink |= entry->blink << bit;
/* PIRQ to IO-APIC map */
if (entry->pirq == GPIO_PIRQ_APIC_ROUTE) {
set = gpio_to_pirq(gpio);
if (set >= 0)
pirq2apic |= 1 << set;
}
}
for (set = 0; set <= 2; set++) {
outl(owner[set], GPIO_BASE_ADDRESS + GPIO_OWNER(set));
outl(route[set], GPIO_BASE_ADDRESS + GPIO_ROUTE(set));
outl(irqen[set], GPIO_BASE_ADDRESS + GPIO_IRQ_IE(set));
outl(reset[set], GPIO_BASE_ADDRESS + GPIO_RESET(set));
}
outl(blink, GPIO_BASE_ADDRESS + GPIO_BLINK);
outl(pirq2apic, GPIO_BASE_ADDRESS + GPIO_PIRQ_APIC_EN);
}
int get_gpio(int gpio_num)
{
if (gpio_num > MAX_GPIO_NUMBER)
return 0;
return !!(inl(GPIO_BASE_ADDRESS + GPIO_CONFIG0(gpio_num)) & GPI_LEVEL);
}
/*
* get a number comprised of multiple GPIO values. gpio_num_array points to
* the array of gpio pin numbers to scan, terminated by -1.
*/
unsigned get_gpios(const int *gpio_num_array)
{
int gpio;
unsigned bitmask = 1;
unsigned vector = 0;
while (bitmask &&
((gpio = *gpio_num_array++) != -1)) {
if (get_gpio(gpio))
vector |= bitmask;
bitmask <<= 1;
}
return vector;
}
void set_gpio(int gpio_num, int value)
{
u32 conf0;
if (gpio_num > MAX_GPIO_NUMBER)
return;
conf0 = inl(GPIO_BASE_ADDRESS + GPIO_CONFIG0(gpio_num));
conf0 &= ~GPO_LEVEL_MASK;
conf0 |= value << GPO_LEVEL_SHIFT;
outl(conf0, GPIO_BASE_ADDRESS + GPIO_CONFIG0(gpio_num));
}
int gpio_is_native(int gpio_num)
{
return !(inl(GPIO_BASE_ADDRESS + GPIO_CONFIG0(gpio_num)) & 1);
}

181
src/soc/intel/skylake/hda.c Normal file
View File

@@ -0,0 +1,181 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008 Advanced Micro Devices, Inc.
* Copyright (C) 2008-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <arch/io.h>
#include <delay.h>
#include <soc/intel/common/hda_verb.h>
#include <soc/pch.h>
#include <soc/ramstage.h>
#include <soc/rcba.h>
const u32 * cim_verb_data = NULL;
u32 cim_verb_data_size = 0;
const u32 * pc_beep_verbs = NULL;
u32 pc_beep_verbs_size = 0;
static void codecs_init(u8 *base, u32 codec_mask)
{
int i;
/* Can support up to 4 codecs */
for (i = 3; i >= 0; i--) {
if (codec_mask & (1 << i))
hda_codec_init(base, i,
cim_verb_data_size,
cim_verb_data);
}
if (pc_beep_verbs_size && pc_beep_verbs)
hda_codec_write(base, pc_beep_verbs_size, pc_beep_verbs);
}
static void hda_pch_init(struct device *dev, u8 *base)
{
u8 reg8;
u16 reg16;
u32 reg32;
if (RCBA32(0x2030) & (1 << 31)) {
reg32 = pci_read_config32(dev, 0x120);
reg32 &= 0xf8ffff01;
reg32 |= (1 << 25);
reg32 |= RCBA32(0x2030) & 0xfe;
pci_write_config32(dev, 0x120, reg32);
} else
printk(BIOS_DEBUG, "HDA: V1CTL disabled.\n");
reg32 = pci_read_config32(dev, 0x114);
reg32 &= ~0xfe;
pci_write_config32(dev, 0x114, reg32);
// Set VCi enable bit
if (pci_read_config32(dev, 0x120) & ((1 << 24) |
(1 << 25) | (1 << 26))) {
reg32 = pci_read_config32(dev, 0x120);
reg32 &= ~(1 << 31);
pci_write_config32(dev, 0x120, reg32);
}
/* Additional programming steps */
reg32 = pci_read_config32(dev, 0xc4);
reg32 |= (1 << 24);
pci_write_config32(dev, 0xc4, reg32);
reg8 = pci_read_config8(dev, 0x40); // Audio Control
reg8 |= 1; // Select HDA mode
pci_write_config8(dev, 0x40, reg8);
reg8 = pci_read_config8(dev, 0x4d); // Docking Status
reg8 &= ~(1 << 7); // Docking not supported
pci_write_config8(dev, 0x4d, reg8);
reg16 = read32(base + 0x0012);
reg16 |= (1 << 0);
write32(base + 0x0012, reg16);
/* disable Auto Voltage Detector */
reg8 = pci_read_config8(dev, 0x42);
reg8 |= (1 << 2);
pci_write_config8(dev, 0x42, reg8);
}
static void hda_init(struct device *dev)
{
u8 *base;
struct resource *res;
u32 codec_mask;
u32 reg32;
/* Find base address */
res = find_resource(dev, PCI_BASE_ADDRESS_0);
if (!res)
return;
base = res2mmio(res, 0, 0);
printk(BIOS_DEBUG, "HDA: base = %p\n", base);
/* Set Bus Master */
reg32 = pci_read_config32(dev, PCI_COMMAND);
pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER);
hda_pch_init(dev, base);
codec_mask = hda_codec_detect(base);
if (codec_mask) {
printk(BIOS_DEBUG, "HDA: codec_mask = %02x\n", codec_mask);
codecs_init(base, codec_mask);
}
}
static void hda_enable(struct device *dev)
{
u32 reg32;
u8 reg8;
reg8 = pci_read_config8(dev, 0x43);
reg8 |= 0x6f;
pci_write_config8(dev, 0x43, reg8);
if (!dev->enabled) {
/* Route I/O buffers to ADSP function */
reg8 = pci_read_config8(dev, 0x42);
reg8 |= (1 << 7) | (1 << 6);
pci_write_config8(dev, 0x42, reg8);
printk(BIOS_INFO, "HDA disabled, I/O buffers routed to ADSP\n");
/* Ensure memory, io, and bus master are all disabled */
reg32 = pci_read_config32(dev, PCI_COMMAND);
reg32 &= ~(PCI_COMMAND_MASTER |
PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
pci_write_config32(dev, PCI_COMMAND, reg32);
/* Disable this device */
pch_disable_devfn(dev);
}
}
static struct device_operations hda_ops = {
.read_resources = &pci_dev_read_resources,
.set_resources = &pci_dev_set_resources,
.enable_resources = &pci_dev_enable_resources,
.init = &hda_init,
.enable = &hda_enable,
.ops_pci = &broadwell_pci_ops,
};
static const unsigned short pci_device_ids[] = {
0x9c20, /* LynxPoint-LP */
0x9ca0, /* WildcatPoint */
0
};
static const struct pci_driver pch_hda __pci_driver = {
.ops = &hda_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.devices = pci_device_ids,
};

584
src/soc/intel/skylake/igd.c Normal file
View File

@@ -0,0 +1,584 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/acpi.h>
#include <arch/io.h>
#include <bootmode.h>
#include <console/console.h>
#include <delay.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <stdlib.h>
#include <string.h>
#include <reg_script.h>
#include <drivers/intel/gma/i915_reg.h>
#include <soc/cpu.h>
#include <soc/pm.h>
#include <soc/ramstage.h>
#include <soc/systemagent.h>
#include <soc/intel/broadwell/chip.h>
#include <vendorcode/google/chromeos/chromeos.h>
#define GT_RETRY 1000
#define GT_CDCLK_337 0
#define GT_CDCLK_450 1
#define GT_CDCLK_540 2
#define GT_CDCLK_675 3
struct reg_script haswell_early_init_script[] = {
/* Enable Force Wake */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa180, 0x00000020),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa188, 0x00010001),
REG_RES_POLL32(PCI_BASE_ADDRESS_0, FORCEWAKE_ACK_HSW, 1, 1, GT_RETRY),
/* Enable Counters */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa248, 0x00000016),
/* GFXPAUSE settings */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa000, 0x00070020),
/* ECO Settings */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0xa180, 0xff3fffff, 0x15000000),
/* Enable DOP Clock Gating */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9424, 0x000003fd),
/* Enable Unit Level Clock Gating */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9400, 0x00000080),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9404, 0x40401000),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9408, 0x00000000),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x940c, 0x02000001),
/*
* RC6 Settings
*/
/* Wake Rate Limits */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa090, 0x00000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa098, 0x03e80000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa09c, 0x00280000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa0a8, 0x0001e848),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa0ac, 0x00000019),
/* Render/Video/Blitter Idle Max Count */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x02054, 0x0000000a),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x12054, 0x0000000a),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x22054, 0x0000000a),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x1a054, 0x0000000a),
/* RC Sleep / RCx Thresholds */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa0b0, 0x00000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa0b4, 0x000003e8),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa0b8, 0x0000c350),
/* RP Settings */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa010, 0x000f4240),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa014, 0x12060000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa02c, 0x0000e808),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa030, 0x0003bd08),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa068, 0x000101d0),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa06c, 0x00055730),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa070, 0x0000000a),
/* RP Control */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa024, 0x00000b92),
/* HW RC6 Control */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa090, 0x88040000),
/* Video Frequency Request */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa00c, 0x08000000),
/* Set RC6 VIDs */
REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x138124, (1 << 31), 0, GT_RETRY),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x138128, 0),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x138124, 0x80000004),
REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x138124, (1 << 31), 0, GT_RETRY),
/* Enable PM Interrupts */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x4402c, 0x03000076),
/* Enable RC6 in idle */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa094, 0x00040000),
REG_SCRIPT_END
};
static const struct reg_script haswell_late_init_script[] = {
/* Lock settings */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a248, (1 << 31)),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a004, (1 << 4)),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a080, (1 << 2)),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a180, (1 << 31)),
/* Disable Force Wake */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa188, 0x00010000),
REG_RES_POLL32(PCI_BASE_ADDRESS_0, FORCEWAKE_ACK_HSW, 1, 0, GT_RETRY),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa188, 0x00000001),
/* Enable power well for DP and Audio */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x45400, (1 << 31)),
REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x45400,
(1 << 30), (1 << 30), GT_RETRY),
REG_SCRIPT_END
};
static const struct reg_script broadwell_early_init_script[] = {
/* Enable Force Wake */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa188, 0x00010001),
REG_RES_POLL32(PCI_BASE_ADDRESS_0, FORCEWAKE_ACK_HSW, 1, 1, GT_RETRY),
/* Enable push bus metric control and shift */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa248, 0x00000004),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa250, 0x000000ff),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa25c, 0x00000010),
/* GFXPAUSE settings (set based on stepping) */
/* ECO Settings */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa180, 0x45200000),
/* Enable DOP Clock Gating */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9424, 0x000000fd),
/* Enable Unit Level Clock Gating */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9400, 0x00000000),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9404, 0x40401000),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9408, 0x00000000),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x940c, 0x02000001),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x1a054, 0x0000000a),
/* Video Frequency Request */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa00c, 0x08000000),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x138158, 0x00000009),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x13815c, 0x0000000d),
/*
* RC6 Settings
*/
/* Wake Rate Limits */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x0a090, 0, 0),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a098, 0x03e80000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a09c, 0x00280000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a0a8, 0x0001e848),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a0ac, 0x00000019),
/* Render/Video/Blitter Idle Max Count */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x02054, 0x0000000a),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x12054, 0x0000000a),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x22054, 0x0000000a),
/* RC Sleep / RCx Thresholds */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a0b0, 0x00000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a0b8, 0x00000271),
/* RP Settings */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a010, 0x000f4240),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a014, 0x12060000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a02c, 0x0000e808),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a030, 0x0003bd08),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a068, 0x000101d0),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a06c, 0x00055730),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a070, 0x0000000a),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a168, 0x00000006),
/* RP Control */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa024, 0x00000b92),
/* HW RC6 Control */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa090, 0x90040000),
/* Set RC6 VIDs */
REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x138124, (1 << 31), 0, GT_RETRY),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x138128, 0),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x138124, 0x80000004),
REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x138124, (1 << 31), 0, GT_RETRY),
/* Enable PM Interrupts */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x4402c, 0x03000076),
/* Enable RC6 in idle */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa094, 0x00040000),
REG_SCRIPT_END
};
static const struct reg_script broadwell_late_init_script[] = {
/* Lock settings */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a248, (1 << 31)),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a000, (1 << 18)),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a180, (1 << 31)),
/* Disable Force Wake */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa188, 0x00010000),
REG_RES_POLL32(PCI_BASE_ADDRESS_0, FORCEWAKE_ACK_HSW, 1, 0, GT_RETRY),
/* Enable power well for DP and Audio */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x45400, (1 << 31)),
REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x45400,
(1 << 30), (1 << 30), GT_RETRY),
REG_SCRIPT_END
};
u32 map_oprom_vendev(u32 vendev)
{
return SA_IGD_OPROM_VENDEV;
}
static struct resource *gtt_res = NULL;
static unsigned long gtt_read(unsigned long reg)
{
u32 val;
val = read32(res2mmio(gtt_res, reg, 0));
return val;
}
static void gtt_write(unsigned long reg, unsigned long data)
{
write32(res2mmio(gtt_res, reg, 0), data);
}
static inline void gtt_rmw(u32 reg, u32 andmask, u32 ormask)
{
u32 val = gtt_read(reg);
val &= andmask;
val |= ormask;
gtt_write(reg, val);
}
static int gtt_poll(u32 reg, u32 mask, u32 value)
{
unsigned try = GT_RETRY;
u32 data;
while (try--) {
data = gtt_read(reg);
if ((data & mask) == value)
return 1;
udelay(10);
}
printk(BIOS_ERR, "GT init timeout\n");
return 0;
}
static void igd_setup_panel(struct device *dev)
{
config_t *conf = dev->chip_info;
u32 reg32;
/* Setup Digital Port Hotplug */
reg32 = gtt_read(PCH_PORT_HOTPLUG);
if (!reg32) {
reg32 = (conf->gpu_dp_b_hotplug & 0x7) << 2;
reg32 |= (conf->gpu_dp_c_hotplug & 0x7) << 10;
reg32 |= (conf->gpu_dp_d_hotplug & 0x7) << 18;
gtt_write(PCH_PORT_HOTPLUG, reg32);
}
/* Setup Panel Power On Delays */
reg32 = gtt_read(PCH_PP_ON_DELAYS);
if (!reg32) {
reg32 = (conf->gpu_panel_port_select & 0x3) << 30;
reg32 |= (conf->gpu_panel_power_up_delay & 0x1fff) << 16;
reg32 |= (conf->gpu_panel_power_backlight_on_delay & 0x1fff);
gtt_write(PCH_PP_ON_DELAYS, reg32);
}
/* Setup Panel Power Off Delays */
reg32 = gtt_read(PCH_PP_OFF_DELAYS);
if (!reg32) {
reg32 = (conf->gpu_panel_power_down_delay & 0x1fff) << 16;
reg32 |= (conf->gpu_panel_power_backlight_off_delay & 0x1fff);
gtt_write(PCH_PP_OFF_DELAYS, reg32);
}
/* Setup Panel Power Cycle Delay */
if (conf->gpu_panel_power_cycle_delay) {
reg32 = gtt_read(PCH_PP_DIVISOR);
reg32 &= ~0xff;
reg32 |= conf->gpu_panel_power_cycle_delay & 0xff;
gtt_write(PCH_PP_DIVISOR, reg32);
}
/* Enable Backlight if needed */
if (conf->gpu_cpu_backlight) {
gtt_write(BLC_PWM_CPU_CTL2, BLC_PWM2_ENABLE);
gtt_write(BLC_PWM_CPU_CTL, conf->gpu_cpu_backlight);
}
if (conf->gpu_pch_backlight) {
gtt_write(BLC_PWM_PCH_CTL1, BLM_PCH_PWM_ENABLE);
gtt_write(BLC_PWM_PCH_CTL2, conf->gpu_pch_backlight);
}
}
static void igd_cdclk_init_haswell(struct device *dev)
{
config_t *conf = dev->chip_info;
int cdclk = conf->cdclk;
int devid = pci_read_config16(dev, PCI_DEVICE_ID);
int gpu_is_ulx = 0;
u32 dpdiv, lpcll;
/* Check for ULX GT1 or GT2 */
if (devid == 0x0a0e || devid == 0x0a1e)
gpu_is_ulx = 1;
/* 675MHz is not supported on haswell */
if (cdclk == GT_CDCLK_675)
cdclk = GT_CDCLK_337;
/* If CD clock is fixed or ULT then set to 450MHz */
if ((gtt_read(0x42014) & 0x1000000) || cpu_is_ult())
cdclk = GT_CDCLK_450;
/* 540MHz is not supported on ULX */
if (gpu_is_ulx && cdclk == GT_CDCLK_540)
cdclk = GT_CDCLK_337;
/* 337.5MHz is not supported on non-ULT/ULX */
if (!gpu_is_ulx && !cpu_is_ult() && cdclk == GT_CDCLK_337)
cdclk = GT_CDCLK_450;
/* Set variables based on CD Clock setting */
switch (cdclk) {
case GT_CDCLK_337:
dpdiv = 169;
lpcll = (1 << 26);
break;
case GT_CDCLK_450:
dpdiv = 225;
lpcll = 0;
break;
case GT_CDCLK_540:
dpdiv = 270;
lpcll = (1 << 26);
break;
default:
return;
}
/* Set LPCLL_CTL CD Clock Frequency Select */
gtt_rmw(0x130040, 0xf3ffffff, lpcll);
/* ULX: Inform power controller of selected frequency */
if (gpu_is_ulx) {
if (cdclk == GT_CDCLK_450)
gtt_write(0x138128, 0x00000000); /* 450MHz */
else
gtt_write(0x138128, 0x00000001); /* 337.5MHz */
gtt_write(0x13812c, 0x00000000);
gtt_write(0x138124, 0x80000017);
}
/* Set CPU DP AUX 2X bit clock dividers */
gtt_rmw(0x64010, 0xfffff800, dpdiv);
gtt_rmw(0x64810, 0xfffff800, dpdiv);
}
static void igd_cdclk_init_broadwell(struct device *dev)
{
config_t *conf = dev->chip_info;
int cdclk = conf->cdclk;
u32 dpdiv, lpcll, pwctl, cdset;
/* Inform power controller of upcoming frequency change */
gtt_write(0x138128, 0);
gtt_write(0x13812c, 0);
gtt_write(0x138124, 0x80000018);
/* Poll GT driver mailbox for run/busy clear */
if (!gtt_poll(0x138124, (1 << 31), (0 << 31)))
cdclk = GT_CDCLK_450;
if (gtt_read(0x42014) & 0x1000000) {
/* If CD clock is fixed then set to 450MHz */
cdclk = GT_CDCLK_450;
} else {
/* Program CD clock to highest supported freq */
if (cpu_is_ult())
cdclk = GT_CDCLK_540;
else
cdclk = GT_CDCLK_675;
}
/* CD clock frequency 675MHz not supported on ULT */
if (cpu_is_ult() && cdclk == GT_CDCLK_675)
cdclk = GT_CDCLK_540;
/* Set variables based on CD Clock setting */
switch (cdclk) {
case GT_CDCLK_337:
cdset = 337;
lpcll = (1 << 27);
pwctl = 2;
dpdiv = 169;
break;
case GT_CDCLK_450:
cdset = 449;
lpcll = 0;
pwctl = 0;
dpdiv = 225;
break;
case GT_CDCLK_540:
cdset = 539;
lpcll = (1 << 26);
pwctl = 1;
dpdiv = 270;
break;
case GT_CDCLK_675:
cdset = 674;
lpcll = (1 << 26) | (1 << 27);
pwctl = 3;
dpdiv = 338;
default:
return;
}
/* Set LPCLL_CTL CD Clock Frequency Select */
gtt_rmw(0x130040, 0xf3ffffff, lpcll);
/* Inform power controller of selected frequency */
gtt_write(0x138128, pwctl);
gtt_write(0x13812c, 0);
gtt_write(0x138124, 0x80000017);
/* Program CD Clock Frequency */
gtt_rmw(0x46200, 0xfffffc00, cdset);
/* Set CPU DP AUX 2X bit clock dividers */
gtt_rmw(0x64010, 0xfffff800, dpdiv);
gtt_rmw(0x64810, 0xfffff800, dpdiv);
}
static void igd_init(struct device *dev)
{
int is_broadwell = !!(cpu_family_model() == BROADWELL_FAMILY_ULT);
u32 rp1_gfx_freq;
/* IGD needs to be Bus Master */
u32 reg32 = pci_read_config32(dev, PCI_COMMAND);
reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
pci_write_config32(dev, PCI_COMMAND, reg32);
gtt_res = find_resource(dev, PCI_BASE_ADDRESS_0);
if (!gtt_res || !gtt_res->base)
return;
/* Wait for any configured pre-graphics delay */
if (acpi_slp_type != SLEEP_STATE_S3) {
#if IS_ENABLED(CONFIG_CHROMEOS)
if (developer_mode_enabled() || recovery_mode_enabled() ||
vboot_wants_oprom())
mdelay(CONFIG_PRE_GRAPHICS_DELAY);
#else
mdelay(CONFIG_PRE_GRAPHICS_DELAY);
#endif
}
/* Early init steps */
if (is_broadwell) {
reg_script_run_on_dev(dev, broadwell_early_init_script);
/* Set GFXPAUSE based on stepping */
if (cpu_stepping() <= (CPUID_BROADWELL_E0 & 0xf) &&
systemagent_revision() <= 9) {
gtt_write(0xa000, 0x300ff);
} else {
gtt_write(0xa000, 0x30020);
}
} else {
reg_script_run_on_dev(dev, haswell_early_init_script);
}
/* Set RP1 graphics frequency */
rp1_gfx_freq = (MCHBAR32(0x5998) >> 8) & 0xff;
gtt_write(0xa008, rp1_gfx_freq << 24);
/* Post VBIOS panel setup */
igd_setup_panel(dev);
/* Initialize PCI device, load/execute BIOS Option ROM */
pci_dev_init(dev);
/* Late init steps */
if (is_broadwell) {
igd_cdclk_init_broadwell(dev);
reg_script_run_on_dev(dev, broadwell_late_init_script);
} else {
igd_cdclk_init_haswell(dev);
reg_script_run_on_dev(dev, haswell_late_init_script);
}
if (gfx_get_init_done()) {
/*
* Work around VBIOS issue that is not clearing first 64
* bytes of the framebuffer during VBE mode set.
*/
struct resource *fb = find_resource(dev, PCI_BASE_ADDRESS_2);
memset((void *)((u32)fb->base), 0, 64);
}
if (!gfx_get_init_done() && acpi_slp_type != 3) {
/*
* Enable DDI-A if the Option ROM did not execute:
*
* bit 0: Display detected (RO)
* bit 4: DDI A supports 4 lanes and DDI E is not used
* bit 7: DDI buffer is idle
*/
gtt_write(DDI_BUF_CTL_A, DDI_BUF_IS_IDLE | DDI_A_4_LANES |
DDI_INIT_DISPLAY_DETECTED);
}
}
static struct device_operations igd_ops = {
.read_resources = &pci_dev_read_resources,
.set_resources = &pci_dev_set_resources,
.enable_resources = &pci_dev_enable_resources,
.init = &igd_init,
.ops_pci = &broadwell_pci_ops,
};
static const unsigned short pci_device_ids[] = {
IGD_HASWELL_ULT_GT1,
IGD_HASWELL_ULT_GT2,
IGD_HASWELL_ULT_GT3,
IGD_BROADWELL_U_GT1,
IGD_BROADWELL_U_GT2,
IGD_BROADWELL_U_GT3_15W,
IGD_BROADWELL_U_GT3_28W,
IGD_BROADWELL_Y_GT2,
IGD_BROADWELL_H_GT2,
IGD_BROADWELL_H_GT3,
0,
};
static const struct pci_driver igd_driver __pci_driver = {
.ops = &igd_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.devices = pci_device_ids,
};

View File

@@ -0,0 +1,37 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_ACPI_H_
#define _BROADWELL_ACPI_H_
#include <arch/acpi.h>
#include <soc/nvs.h>
/* P-state configuration */
#define PSS_MAX_ENTRIES 8
#define PSS_RATIO_STEP 2
#define PSS_LATENCY_TRANSITION 10
#define PSS_LATENCY_BUSMASTER 10
void acpi_create_intel_hpet(acpi_hpet_t *hpet);
void acpi_fill_in_fadt(acpi_fadt_t *fadt);
unsigned long acpi_madt_irq_overrides(unsigned long current);
void acpi_init_gnvs(global_nvs_t *gnvs);
#endif

View File

@@ -0,0 +1,56 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_ADSP_H_
#define _BROADWELL_ADSP_H_
#define ADSP_PCI_IRQ 23
#define ADSP_ACPI_IRQ 3
#define ADSP_ACPI_IRQEN (1 << 3)
#define ADSP_SHIM_BASE_LPT 0xe7000
#define ADSP_SHIM_BASE_WPT 0xfb000
#define ADSP_SHIM_LTRC 0xe0
#define ADSP_SHIM_LTRC_VALUE 0x3003
#define ADSP_SHIM_IMC 0x28
#define ADSP_SHIM_IPCD 0x40
#define ADSP_PCI_VDRTCTL0 0xa0
#define ADSP_VDRTCTL0_D3PGD_LPT (1 << 1)
#define ADSP_VDRTCTL0_D3PGD_WPT (1 << 0)
#define ADSP_VDRTCTL0_D3SRAMPGD_LPT (1 << 2)
#define ADSP_VDRTCTL0_D3SRAMPGD_WPT (1 << 1)
#define ADSP_PCI_VDRTCTL1 0xa4
#define ADSP_PCI_VDRTCTL2 0xa8
#define ADSP_VDRTCTL2_VALUE 0x00000fff
#define ADSP_IOBP_VDLDAT1 0xd7000624
#define ADSP_VDLDAT1_VALUE 0x00040100
#define ADSP_IOBP_VDLDAT2 0xd7000628
#define ADSP_IOBP_ACPI_IRQ3 0xd9d8
#define ADSP_IOBP_ACPI_IRQ3I 0xd8d9
#define ADSP_IOBP_ACPI_IRQ4 0xdbda
#define ADSP_IOBP_PMCTL 0xd70001e0
#define ADSP_PMCTL_VALUE 0x3f
#define ADSP_IOBP_PCICFGCTL 0xd7000500
#define ADSP_PCICFGCTL_PCICD (1 << 0)
#define ADSP_PCICFGCTL_ACPIIE (1 << 1)
#define ADSP_PCICFGCTL_SPCBAD (1 << 7)
#endif

View File

@@ -0,0 +1,73 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_CPU_H_
#define _BROADWELL_CPU_H_
#include <arch/cpu.h>
#include <device/device.h>
/* CPU types */
#define HASWELL_FAMILY_ULT 0x40650
#define BROADWELL_FAMILY_ULT 0x306d0
/* Supported CPUIDs */
#define CPUID_HASWELL_A0 0x306c1
#define CPUID_HASWELL_B0 0x306c2
#define CPUID_HASWELL_C0 0x306c3
#define CPUID_HASWELL_ULT_B0 0x40650
#define CPUID_HASWELL_ULT 0x40651
#define CPUID_HASWELL_HALO 0x40661
#define CPUID_BROADWELL_C0 0x306d2
#define CPUID_BROADWELL_D0 0x306d3
#define CPUID_BROADWELL_E0 0x306d4
/* CPU bus clock is fixed at 100MHz */
#define CPU_BCLK 100
/* Latency times in units of 1024ns. */
#define C_STATE_LATENCY_CONTROL_0_LIMIT 0x42
#define C_STATE_LATENCY_CONTROL_1_LIMIT 0x73
#define C_STATE_LATENCY_CONTROL_2_LIMIT 0x91
#define C_STATE_LATENCY_CONTROL_3_LIMIT 0xe4
#define C_STATE_LATENCY_CONTROL_4_LIMIT 0x145
#define C_STATE_LATENCY_CONTROL_5_LIMIT 0x1ef
#define C_STATE_LATENCY_MICRO_SECONDS(limit, base) \
(((1 << ((base)*5)) * (limit)) / 1000)
#define C_STATE_LATENCY_FROM_LAT_REG(reg) \
C_STATE_LATENCY_MICRO_SECONDS(C_STATE_LATENCY_CONTROL_ ##reg## _LIMIT, \
(IRTL_1024_NS >> 10))
/* Configure power limits for turbo mode */
void set_power_limits(u8 power_limit_1_time);
int cpu_config_tdp_levels(void);
/*
* Determine if HyperThreading is disabled.
* The variable is not valid until setup_ap_init() has been called.
*/
extern int ht_disabled;
/* CPU identification */
u32 cpu_family_model(void);
u32 cpu_stepping(void);
int cpu_is_ult(void);
#endif

View File

@@ -0,0 +1,44 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_DEVICE_NVS_H_
#define _BROADWELL_DEVICE_NVS_H_
#include <stdint.h>
/* Offset in Global NVS where this structure lives */
#define DEVICE_NVS_OFFSET 0x1000
#define SIO_NVS_DMA 0
#define SIO_NVS_I2C0 1
#define SIO_NVS_I2C1 2
#define SIO_NVS_SPI0 3
#define SIO_NVS_SPI1 4
#define SIO_NVS_UART0 5
#define SIO_NVS_UART1 6
#define SIO_NVS_SDIO 7
#define SIO_NVS_ADSP 8
typedef struct {
u8 enable[9];
u32 bar0[9];
u32 bar1[9];
} __attribute__((packed)) device_nvs_t;
#endif

View File

@@ -0,0 +1,32 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_EHCI_H_
#define _BROADWELL_EHCI_H_
/* EHCI Memory Registers */
#define EHCI_USB_CMD 0x20
#define EHCI_USB_CMD_RUN (1 << 0)
#define EHCI_USB_CMD_PSE (1 << 4)
#define EHCI_USB_CMD_ASE (1 << 5)
#define EHCI_PORTSC(port) (0x64 + (port * 4))
#define EHCI_PORTSC_ENABLED (1 << 2)
#define EHCI_PORTSC_SUSPEND (1 << 7)
#endif

View File

@@ -0,0 +1,192 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_GPIO_H_
#define _BROADWELL_GPIO_H_
#include <stdint.h>
/* PCH-LP GPIOBASE Registers */
#define GPIO_OWNER(set) (0x00 + ((set) * 4))
#define GPIO_PIRQ_APIC_EN 0x10
#define GPIO_BLINK 0x18
#define GPIO_SER_BLINK 0x1c
#define GPIO_SER_BLINK_CS 0x20
#define GPIO_SER_BLINK_DATA 0x24
#define GPIO_ROUTE(set) (0x30 + ((set) * 4))
#define GPIO_ALT_GPI_SMI_STS 0x50
#define GPIO_ALT_GPI_SMI_EN 0x54
#define GPIO_RESET(set) (0x60 + ((set) * 4))
#define GPIO_GLOBAL_CONFIG 0x7c
#define GPIO_IRQ_IS(set) (0x80 + ((set) * 4))
#define GPIO_IRQ_IE(set) (0x90 + ((set) * 4))
#define GPIO_CONFIG0(gpio) (0x100 + ((gpio) * 8))
#define GPIO_CONFIG1(gpio) (0x104 + ((gpio) * 8))
#define MAX_GPIO_NUMBER 94 /* zero based */
#define GPIO_LIST_END 0xffffffff
/* conf0 */
#define GPIO_MODE_NATIVE (0 << 0)
#define GPIO_MODE_GPIO (1 << 0)
#define GPIO_DIR_OUTPUT (0 << 2)
#define GPIO_DIR_INPUT (1 << 2)
#define GPIO_NO_INVERT (0 << 3)
#define GPIO_INVERT (1 << 3)
#define GPIO_IRQ_EDGE (0 << 4)
#define GPIO_IRQ_LEVEL (1 << 4)
#define GPI_LEVEL (1 << 30)
#define GPIO_OUT_LOW 0
#define GPIO_OUT_HIGH 1
#define GPO_LEVEL_SHIFT 31
#define GPO_LEVEL_MASK (1 << GPO_LEVEL_SHIFT)
#define GPO_LEVEL_LOW (GPIO_OUT_LOW << GPO_LEVEL_SHIFT)
#define GPO_LEVEL_HIGH (GPIO_OUT_HIGH << GPO_LEVEL_SHIFT)
/* conf1 */
#define GPIO_PULL_NONE (0 << 0)
#define GPIO_PULL_DOWN (1 << 0)
#define GPIO_PULL_UP (2 << 0)
#define GPIO_SENSE_ENABLE (0 << 2)
#define GPIO_SENSE_DISABLE (1 << 2)
/* owner */
#define GPIO_OWNER_ACPI 0
#define GPIO_OWNER_GPIO 1
/* route */
#define GPIO_ROUTE_SCI 0
#define GPIO_ROUTE_SMI 1
/* irqen */
#define GPIO_IRQ_DISABLE 0
#define GPIO_IRQ_ENABLE 1
/* blink */
#define GPO_NO_BLINK 0
#define GPO_BLINK 1
/* reset */
#define GPIO_RESET_PWROK 0
#define GPIO_RESET_RSMRST 1
/* pirq route to io-apic */
#define GPIO_PIRQ_APIC_MASK 0
#define GPIO_PIRQ_APIC_ROUTE 1
#define PCH_GPIO_END \
{ .conf0 = GPIO_LIST_END }
#define PCH_GPIO_NATIVE \
{ .conf0 = GPIO_MODE_NATIVE }
#define PCH_GPIO_UNUSED \
{ .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, \
.owner = GPIO_OWNER_GPIO, \
.conf1 = GPIO_SENSE_DISABLE }
#define PCH_GPIO_ACPI_SCI \
{ .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_INVERT, \
.owner = GPIO_OWNER_ACPI, \
.route = GPIO_ROUTE_SCI }
#define PCH_GPIO_ACPI_SMI \
{ .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_INVERT, \
.owner = GPIO_OWNER_ACPI, \
.route = GPIO_ROUTE_SMI }
#define PCH_GPIO_INPUT \
{ .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, \
.owner = GPIO_OWNER_GPIO }
#define PCH_GPIO_INPUT_INVERT \
{ .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_INVERT, \
.owner = GPIO_OWNER_GPIO }
#define PCH_GPIO_IRQ_EDGE \
{ .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_IRQ_EDGE, \
.owner = GPIO_OWNER_GPIO, \
.irqen = GPIO_IRQ_ENABLE }
#define PCH_GPIO_IRQ_LEVEL \
{ .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_IRQ_LEVEL, \
.owner = GPIO_OWNER_GPIO, \
.irqen = GPIO_IRQ_ENABLE }
#define PCH_GPIO_PIRQ \
{ .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, \
.owner = GPIO_OWNER_GPIO, \
.pirq = GPIO_PIRQ_APIC_ROUTE }
#define PCH_GPIO_OUT_HIGH \
{ .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, \
.owner = GPIO_OWNER_GPIO, \
.conf1 = GPIO_SENSE_DISABLE }
#define PCH_GPIO_OUT_LOW \
{ .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, \
.owner = GPIO_OWNER_GPIO, \
.conf1 = GPIO_SENSE_DISABLE }
struct gpio_config {
u8 gpio;
u32 conf0;
u32 conf1;
u8 owner;
u8 route;
u8 irqen;
u8 reset;
u8 blink;
u8 pirq;
} __attribute__ ((packed));
/* Configure GPIOs with mainboard provided settings */
void init_one_gpio(int gpio_num, struct gpio_config *config);
void init_gpios(const struct gpio_config config[]);
/* Get GPIO pin value */
int get_gpio(int gpio_num);
/* Set GPIO pin value */
void set_gpio(int gpio_num, int value);
/* Return non-zero if gpio is set to native function. 0 otherwise. */
int gpio_is_native(int gpio_num);
/*
* Get a number comprised of multiple GPIO values. gpio_num_array points to
* the array of gpio pin numbers to scan, terminated by -1.
*/
unsigned get_gpios(const int *gpio_num_array);
#endif

View File

@@ -0,0 +1,28 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_IOBP_H_
#define _BROADWELL_IOBP_H_
u32 pch_iobp_read(u32 address);
void pch_iobp_write(u32 address, u32 data);
void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue);
void pch_iobp_exec(u32 addr, u16 op_dcode, u8 route_id, u32 *data, u8 *resp);
#endif

View File

@@ -0,0 +1,62 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_IOMAP_H_
#define _BROADWELL_IOMAP_H_
#define MCFG_BASE_ADDRESS CONFIG_MMCONF_BASE_ADDRESS
#define MCFG_BASE_SIZE 0x4000000
#define MCH_BASE_ADDRESS 0xfed10000
#define MCH_BASE_SIZE 0x8000
#define DMI_BASE_ADDRESS 0xfed18000
#define DMI_BASE_SIZE 0x1000
#define EP_BASE_ADDRESS 0xfed19000
#define EP_BASE_SIZE 0x1000
#define EDRAM_BASE_ADDRESS 0xfed80000
#define EDRAM_BASE_SIZE 0x4000
#define GDXC_BASE_ADDRESS 0xfed84000
#define GDXC_BASE_SIZE 0x1000
#define RCBA_BASE_ADDRESS 0xfed1c000
#define RCBA_BASE_SIZE 0x4000
#define HPET_BASE_ADDRESS 0xfed00000
#define ACPI_BASE_ADDRESS 0x1000
#define ACPI_BASE_SIZE 0x100
#define GPIO_BASE_ADDRESS 0x1400
#define GPIO_BASE_SIZE 0x400
#define SMBUS_BASE_ADDRESS 0x0400
#define SMBUS_BASE_SIZE 0x10
/* Temporary addresses used in romstage */
#define EARLY_GTT_BAR 0xe0000000
#define EARLY_XHCI_BAR 0xd7000000
#define EARLY_EHCI_BAR CONFIG_EHCI_BAR
#define EARLY_UART_BAR CONFIG_TTYS0_BASE
#define EARLY_TEMP_MMIO 0xfed08000
#endif

View File

@@ -0,0 +1,93 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_LPC_H_
#define _BROADWELL_LPC_H_
/* PCI Configuration Space (D31:F0): LPC */
#define SERIRQ_CNTL 0x64
#define PMBASE 0x40
#define ACPI_CNTL 0x44
#define ACPI_EN (1 << 7)
#define SCI_IRQ_SEL (7 << 0)
#define SCIS_IRQ9 0
#define SCIS_IRQ10 1
#define SCIS_IRQ11 2
#define SCIS_IRQ20 4
#define SCIS_IRQ21 5
#define SCIS_IRQ22 6
#define SCIS_IRQ23 7
#define GPIOBASE 0x48
#define BIOS_CNTL 0xdc
#define GPIO_BASE 0x48 /* LPC GPIO Base Address Register */
#define GPIO_CNTL 0x4C /* LPC GPIO Control Register */
#define GPIO_EN (1 << 4)
#define GPIO_ROUT 0xb8
#define PIRQA_ROUT 0x60
#define PIRQB_ROUT 0x61
#define PIRQC_ROUT 0x62
#define PIRQD_ROUT 0x63
#define PIRQE_ROUT 0x68
#define PIRQF_ROUT 0x69
#define PIRQG_ROUT 0x6A
#define PIRQH_ROUT 0x6B
#define LPC_IO_DEC 0x80 /* IO Decode Ranges Register */
#define LPC_EN 0x82 /* LPC IF Enables Register */
#define CNF2_LPC_EN (1 << 13) /* 0x4e/0x4f */
#define CNF1_LPC_EN (1 << 12) /* 0x2e/0x2f */
#define MC_LPC_EN (1 << 11) /* 0x62/0x66 */
#define KBC_LPC_EN (1 << 10) /* 0x60/0x64 */
#define GAMEH_LPC_EN (1 << 9) /* 0x208/0x20f */
#define GAMEL_LPC_EN (1 << 8) /* 0x200/0x207 */
#define FDD_LPC_EN (1 << 3) /* LPC_IO_DEC[12] */
#define LPT_LPC_EN (1 << 2) /* LPC_IO_DEC[9:8] */
#define COMB_LPC_EN (1 << 1) /* LPC_IO_DEC[6:4] */
#define COMA_LPC_EN (1 << 0) /* LPC_IO_DEC[2:0] */
#define LPC_GEN1_DEC 0x84 /* LPC IF Generic Decode Range 1 */
#define LPC_GEN2_DEC 0x88 /* LPC IF Generic Decode Range 2 */
#define LPC_GEN3_DEC 0x8c /* LPC IF Generic Decode Range 3 */
#define LPC_GEN4_DEC 0x90 /* LPC IF Generic Decode Range 4 */
#define LGMR 0x98 /* LPC Generic Memory Range */
#define RCBA 0xf0 /* Root Complex Register Block */
/* Power Management */
#define GEN_PMCON_1 0xa0
#define SMI_LOCK (1 << 4)
#define GEN_PMCON_2 0xa2
#define SYSTEM_RESET_STS (1 << 4)
#define THERMTRIP_STS (1 << 3)
#define SYSPWR_FLR (1 << 1)
#define PWROK_FLR (1 << 0)
#define GEN_PMCON_3 0xa4
#define SUS_PWR_FLR (1 << 14)
#define GEN_RST_STS (1 << 9)
#define RTC_BATTERY_DEAD (1 << 2)
#define PWR_FLR (1 << 1)
#define SLEEP_AFTER_POWER_FAIL (1 << 0)
#define GEN_PMCON_LOCK 0xa6
#define SLP_STR_POL_LOCK (1 << 2)
#define ACPI_BASE_LOCK (1 << 1)
#define PMIR 0xac
#define PMIR_CF9LOCK (1 << 31)
#define PMIR_CF9GR (1 << 20)
#endif

View File

@@ -0,0 +1,507 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_ME_H_
#define _BROADWELL_ME_H_
#include <console/loglevel.h>
#define ME_RETRY 100000 /* 1 second */
#define ME_DELAY 10 /* 10 us */
/*
* Management Engine PCI registers
*/
#define PCI_CPU_MEBASE_L 0x70 /* Set by MRC */
#define PCI_CPU_MEBASE_H 0x74 /* Set by MRC */
#define PCI_ME_HFS 0x40
#define ME_HFS_CWS_RESET 0
#define ME_HFS_CWS_INIT 1
#define ME_HFS_CWS_REC 2
#define ME_HFS_CWS_NORMAL 5
#define ME_HFS_CWS_WAIT 6
#define ME_HFS_CWS_TRANS 7
#define ME_HFS_CWS_INVALID 8
#define ME_HFS_STATE_PREBOOT 0
#define ME_HFS_STATE_M0_UMA 1
#define ME_HFS_STATE_M3 4
#define ME_HFS_STATE_M0 5
#define ME_HFS_STATE_BRINGUP 6
#define ME_HFS_STATE_ERROR 7
#define ME_HFS_ERROR_NONE 0
#define ME_HFS_ERROR_UNCAT 1
#define ME_HFS_ERROR_IMAGE 3
#define ME_HFS_ERROR_DEBUG 4
#define ME_HFS_MODE_NORMAL 0
#define ME_HFS_MODE_DEBUG 2
#define ME_HFS_MODE_DIS 3
#define ME_HFS_MODE_OVER_JMPR 4
#define ME_HFS_MODE_OVER_MEI 5
#define ME_HFS_BIOS_DRAM_ACK 1
#define ME_HFS_ACK_NO_DID 0
#define ME_HFS_ACK_RESET 1
#define ME_HFS_ACK_PWR_CYCLE 2
#define ME_HFS_ACK_S3 3
#define ME_HFS_ACK_S4 4
#define ME_HFS_ACK_S5 5
#define ME_HFS_ACK_GBL_RESET 6
#define ME_HFS_ACK_CONTINUE 7
struct me_hfs {
u32 working_state: 4;
u32 mfg_mode: 1;
u32 fpt_bad: 1;
u32 operation_state: 3;
u32 fw_init_complete: 1;
u32 ft_bup_ld_flr: 1;
u32 update_in_progress: 1;
u32 error_code: 4;
u32 operation_mode: 4;
u32 reserved: 4;
u32 boot_options_present: 1;
u32 ack_data: 3;
u32 bios_msg_ack: 4;
} __attribute__ ((packed));
#define PCI_ME_UMA 0x44
struct me_uma {
u32 size: 6;
u32 reserved_1: 10;
u32 valid: 1;
u32 reserved_0: 14;
u32 set_to_one: 1;
} __attribute__ ((packed));
#define PCI_ME_H_GS 0x4c
#define ME_INIT_DONE 1
#define ME_INIT_STATUS_SUCCESS 0
#define ME_INIT_STATUS_NOMEM 1
#define ME_INIT_STATUS_ERROR 2
#define ME_INIT_STATUS_SUCCESS_OTHER 3 /* SEE ME9 BWG */
#define ME_HSIO_MESSAGE (7 << 28)
#define ME_HSIO_CMD_GETHSIOVER 1
#define ME_HSIO_CMD_CLOSE 0
struct me_did {
u32 uma_base: 16;
u32 reserved: 7;
u32 rapid_start: 1;
u32 status: 4;
u32 init_done: 4;
} __attribute__ ((packed));
/*
* Apparently the GMES register is renamed to HFS2 (or HFSTS2 according
* to ME9 BWG). Sadly the PCH EDS and the ME BWG do not match on nomenclature.
*/
#define PCI_ME_HFS2 0x48
/* Infrastructure Progress Values */
#define ME_HFS2_PHASE_ROM 0
#define ME_HFS2_PHASE_BUP 1
#define ME_HFS2_PHASE_UKERNEL 2
#define ME_HFS2_PHASE_POLICY 3
#define ME_HFS2_PHASE_MODULE_LOAD 4
#define ME_HFS2_PHASE_UNKNOWN 5
#define ME_HFS2_PHASE_HOST_COMM 6
/* Current State - Based on Infra Progress values. */
/* ROM State */
#define ME_HFS2_STATE_ROM_BEGIN 0
#define ME_HFS2_STATE_ROM_DISABLE 6
/* BUP State */
#define ME_HFS2_STATE_BUP_INIT 0
#define ME_HFS2_STATE_BUP_DIS_HOST_WAKE 1
#define ME_HFS2_STATE_BUP_FLOW_DET 4
#define ME_HFS2_STATE_BUP_VSCC_ERR 8
#define ME_HFS2_STATE_BUP_CHECK_STRAP 0xa
#define ME_HFS2_STATE_BUP_PWR_OK_TIMEOUT 0xb
#define ME_HFS2_STATE_BUP_MANUF_OVRD_STRAP 0xd
#define ME_HFS2_STATE_BUP_M3 0x11
#define ME_HFS2_STATE_BUP_M0 0x12
#define ME_HFS2_STATE_BUP_FLOW_DET_ERR 0x13
#define ME_HFS2_STATE_BUP_M3_CLK_ERR 0x15
#define ME_HFS2_STATE_BUP_CPU_RESET_DID_TIMEOUT_MEM_MISSING 0x17
#define ME_HFS2_STATE_BUP_M3_KERN_LOAD 0x18
#define ME_HFS2_STATE_BUP_T32_MISSING 0x1c
#define ME_HFS2_STATE_BUP_WAIT_DID 0x1f
#define ME_HFS2_STATE_BUP_WAIT_DID_FAIL 0x20
#define ME_HFS2_STATE_BUP_DID_NO_FAIL 0x21
#define ME_HFS2_STATE_BUP_ENABLE_UMA 0x22
#define ME_HFS2_STATE_BUP_ENABLE_UMA_ERR 0x23
#define ME_HFS2_STATE_BUP_SEND_DID_ACK 0x24
#define ME_HFS2_STATE_BUP_SEND_DID_ACK_ERR 0x25
#define ME_HFS2_STATE_BUP_M0_CLK 0x26
#define ME_HFS2_STATE_BUP_M0_CLK_ERR 0x27
#define ME_HFS2_STATE_BUP_TEMP_DIS 0x28
#define ME_HFS2_STATE_BUP_M0_KERN_LOAD 0x32
/* Policy Module State */
#define ME_HFS2_STATE_POLICY_ENTRY 0
#define ME_HFS2_STATE_POLICY_RCVD_S3 3
#define ME_HFS2_STATE_POLICY_RCVD_S4 4
#define ME_HFS2_STATE_POLICY_RCVD_S5 5
#define ME_HFS2_STATE_POLICY_RCVD_UPD 6
#define ME_HFS2_STATE_POLICY_RCVD_PCR 7
#define ME_HFS2_STATE_POLICY_RCVD_NPCR 8
#define ME_HFS2_STATE_POLICY_RCVD_HOST_WAKE 9
#define ME_HFS2_STATE_POLICY_RCVD_AC_DC 0xa
#define ME_HFS2_STATE_POLICY_RCVD_DID 0xb
#define ME_HFS2_STATE_POLICY_VSCC_NOT_FOUND 0xc
#define ME_HFS2_STATE_POLICY_VSCC_INVALID 0xd
#define ME_HFS2_STATE_POLICY_FPB_ERR 0xe
#define ME_HFS2_STATE_POLICY_DESCRIPTOR_ERR 0xf
#define ME_HFS2_STATE_POLICY_VSCC_NO_MATCH 0x10
/* Current PM Event Values */
#define ME_HFS2_PMEVENT_CLEAN_MOFF_MX_WAKE 0
#define ME_HFS2_PMEVENT_MOFF_MX_WAKE_ERROR 1
#define ME_HFS2_PMEVENT_CLEAN_GLOBAL_RESET 2
#define ME_HFS2_PMEVENT_CLEAN_GLOBAL_RESET_ERROR 3
#define ME_HFS2_PMEVENT_CLEAN_ME_RESET 4
#define ME_HFS2_PMEVENT_ME_RESET_EXCEPTION 5
#define ME_HFS2_PMEVENT_PSEUDO_ME_RESET 6
#define ME_HFS2_PMEVENT_S0MO_SXM3 7
#define ME_HFS2_PMEVENT_SXM3_S0M0 8
#define ME_HFS2_PMEVENT_NON_PWR_CYCLE_RESET 9
#define ME_HFS2_PMEVENT_PWR_CYCLE_RESET_M3 0xa
#define ME_HFS2_PMEVENT_PWR_CYCLE_RESET_MOFF 0xb
#define ME_HFS2_PMEVENT_SXMX_SXMOFF 0xc
struct me_hfs2 {
u32 bist_in_progress: 1;
u32 reserved1: 2;
u32 invoke_mebx: 1;
u32 cpu_replaced_sts: 1;
u32 mbp_rdy: 1;
u32 mfs_failure: 1;
u32 warm_reset_request: 1;
u32 cpu_replaced_valid: 1;
u32 reserved2: 4;
u32 mbp_cleared: 1;
u32 reserved3: 2;
u32 current_state: 8;
u32 current_pmevent: 4;
u32 progress_code: 4;
} __attribute__ ((packed));
#define PCI_ME_HFS5 0x68
#define PCI_ME_H_GS2 0x70
#define PCI_ME_MBP_GIVE_UP 0x01
#define PCI_ME_HERES 0xbc
#define PCI_ME_EXT_SHA1 0x00
#define PCI_ME_EXT_SHA256 0x02
#define PCI_ME_HER(x) (0xc0+(4*(x)))
struct me_heres {
u32 extend_reg_algorithm: 4;
u32 reserved: 26;
u32 extend_feature_present: 1;
u32 extend_reg_valid: 1;
} __attribute__ ((packed));
/*
* Management Engine MEI registers
*/
#define MEI_H_CB_WW 0x00
#define MEI_H_CSR 0x04
#define MEI_ME_CB_RW 0x08
#define MEI_ME_CSR_HA 0x0c
struct mei_csr {
u32 interrupt_enable: 1;
u32 interrupt_status: 1;
u32 interrupt_generate: 1;
u32 ready: 1;
u32 reset: 1;
u32 reserved: 3;
u32 buffer_read_ptr: 8;
u32 buffer_write_ptr: 8;
u32 buffer_depth: 8;
} __attribute__ ((packed));
#define MEI_ADDRESS_CORE 0x01
#define MEI_ADDRESS_AMT 0x02
#define MEI_ADDRESS_RESERVED 0x03
#define MEI_ADDRESS_WDT 0x04
#define MEI_ADDRESS_MKHI 0x07
#define MEI_ADDRESS_ICC 0x08
#define MEI_ADDRESS_THERMAL 0x09
#define MEI_HOST_ADDRESS 0
struct mei_header {
u32 client_address: 8;
u32 host_address: 8;
u32 length: 9;
u32 reserved: 6;
u32 is_complete: 1;
} __attribute__ ((packed));
#define MKHI_GROUP_ID_CBM 0x00
#define MKHI_GLOBAL_RESET 0x0b
#define MKHI_GROUP_ID_FWCAPS 0x03
#define MKHI_FWCAPS_GET_RULE 0x02
#define MKHI_GROUP_ID_HMRFPO 0x05
#define MKHI_HMRFPO_LOCK 0x02
#define MKHI_HMRFPO_LOCK_NOACK 0x05
#define MKHI_GROUP_ID_MDES 0x08
#define MKHI_MDES_ENABLE 0x09
#define MKHI_GROUP_ID_GEN 0xff
#define MKHI_GET_FW_VERSION 0x02
#define MKHI_END_OF_POST 0x0c
#define MKHI_FEATURE_OVERRIDE 0x14
#define MKHI_END_OF_POST_NOACK 0x1a
struct mkhi_header {
u32 group_id: 8;
u32 command: 7;
u32 is_response: 1;
u32 reserved: 8;
u32 result: 8;
} __attribute__ ((packed));
struct me_fw_version {
u16 code_minor;
u16 code_major;
u16 code_build_number;
u16 code_hot_fix;
u16 recovery_minor;
u16 recovery_major;
u16 recovery_build_number;
u16 recovery_hot_fix;
} __attribute__ ((packed));
/* ICC Messages */
#define ICC_SET_CLOCK_ENABLES 0x3
#define ICC_API_VERSION_LYNXPOINT 0x00030000
struct icc_header {
u32 api_version;
u32 icc_command;
u32 icc_status;
u32 length;
u32 reserved;
} __attribute__ ((packed));
struct icc_clock_enables_msg {
u32 clock_enables;
u32 clock_mask;
u32 no_response: 1;
u32 reserved: 31;
} __attribute__ ((packed));
#define HECI_EOP_STATUS_SUCCESS 0x0
#define HECI_EOP_PERFORM_GLOBAL_RESET 0x1
#define CBM_RR_GLOBAL_RESET 0x01
#define GLOBAL_RESET_BIOS_MRC 0x01
#define GLOBAL_RESET_BIOS_POST 0x02
#define GLOBAL_RESET_MEBX 0x03
struct me_global_reset {
u8 request_origin;
u8 reset_type;
} __attribute__ ((packed));
typedef enum {
ME_NORMAL_BIOS_PATH,
ME_S3WAKE_BIOS_PATH,
ME_ERROR_BIOS_PATH,
ME_RECOVERY_BIOS_PATH,
ME_DISABLE_BIOS_PATH,
ME_FIRMWARE_UPDATE_BIOS_PATH,
} me_bios_path;
/*
* ME to BIOS Payload Datastructures and definitions. The ordering of the
* structures follows the ordering in the ME9 BWG.
*/
#define MBP_APPID_KERNEL 1
#define MBP_APPID_INTEL_AT 3
#define MBP_APPID_HWA 4
#define MBP_APPID_ICC 5
#define MBP_APPID_NFC 6
/* Kernel items: */
#define MBP_KERNEL_FW_VER_ITEM 1
#define MBP_KERNEL_FW_CAP_ITEM 2
#define MBP_KERNEL_ROM_BIST_ITEM 3
#define MBP_KERNEL_PLAT_KEY_ITEM 4
#define MBP_KERNEL_FW_TYPE_ITEM 5
#define MBP_KERNEL_MFS_FAILURE_ITEM 6
#define MBP_KERNEL_PLAT_TIME_ITEM 7
/* Intel AT items: */
#define MBP_INTEL_AT_STATE_ITEM 1
/* ICC Items: */
#define MBP_ICC_PROFILE_ITEM 1
/* HWA Items: */
#define MBP_HWA_REQUEST_ITEM 1
/* NFC Items: */
#define MBP_NFC_SUPPORT_DATA_ITEM 1
#define MBP_MAKE_IDENT(appid, item) ((appid << 8) | item)
#define MBP_IDENT(appid, item) \
MBP_MAKE_IDENT(MBP_APPID_##appid, MBP_##appid##_##item##_ITEM)
typedef struct {
u32 mbp_size : 8;
u32 num_entries : 8;
u32 rsvd : 16;
} __attribute__ ((packed)) mbp_header;
typedef struct {
u32 app_id : 8;
u32 item_id : 8;
u32 length : 8;
u32 rsvd : 8;
} __attribute__ ((packed)) mbp_item_header;
typedef struct {
u32 major_version : 16;
u32 minor_version : 16;
u32 hotfix_version : 16;
u32 build_version : 16;
} __attribute__ ((packed)) mbp_fw_version_name;
typedef struct {
u32 full_net : 1;
u32 std_net : 1;
u32 manageability : 1;
u32 reserved_2 : 2;
u32 intel_at : 1;
u32 intel_cls : 1;
u32 reserved : 3;
u32 intel_mpc : 1;
u32 icc_over_clocking : 1;
u32 pavp : 1;
u32 reserved_1 : 4;
u32 ipv6 : 1;
u32 kvm : 1;
u32 och : 1;
u32 vlan : 1;
u32 tls : 1;
u32 reserved_4 : 1;
u32 wlan : 1;
u32 reserved_5 : 8;
} __attribute__ ((packed)) mbp_mefwcaps;
typedef struct {
u16 device_id;
u16 fuse_test_flags;
u32 umchid[4];
} __attribute__ ((packed)) mbp_rom_bist_data;
typedef struct {
u32 key[8];
} mbp_platform_key;
typedef struct {
u32 mobile: 1;
u32 desktop: 1;
u32 server: 1;
u32 workstation: 1;
u32 corporate: 1;
u32 consumer: 1;
u32 regular_super_sku: 1;
u32 rsvd: 1;
u32 image_type: 4;
u32 brand: 4;
u32 rsvd1: 16;
} __attribute__ ((packed)) mbp_me_firmware_type;
typedef struct {
mbp_me_firmware_type rule_data;
u8 available;
} mbp_plat_type;
typedef struct {
u16 icc_start_address;
u16 mask;
} __attribute__ ((packed)) icc_address_mask;
typedef struct {
u8 num_icc_profiles;
u8 icc_profile_soft_strap;
u8 icc_profile_index;
u8 reserved;
u32 icc_reg_bundles;
icc_address_mask icc_address_mask[0];
} __attribute__ ((packed)) mbp_icc_profile;
typedef struct {
u16 lock_state : 1;
u16 authenticate_module : 1;
u16 s3authentication : 1;
u16 flash_wear_out : 1;
u16 flash_variable_security : 1;
u16 reserved : 11;
} __attribute__ ((packed)) tdt_state_flag;
typedef struct {
u8 state;
u8 last_theft_trigger;
tdt_state_flag flags;
} __attribute__ ((packed)) mbp_at_state;
typedef struct {
u32 wake_event_mrst_time_ms;
u32 mrst_pltrst_time_ms;
u32 pltrst_cpurst_time_ms;
} __attribute__ ((packed)) mbp_plat_time;
typedef struct {
u32 device_type : 2;
u32 reserved : 30;
} __attribute__ ((packed)) mbp_nfc_data;
typedef struct {
mbp_fw_version_name *fw_version_name;
mbp_mefwcaps *fw_capabilities;
mbp_rom_bist_data *rom_bist_data;
mbp_platform_key *platform_key;
mbp_plat_type *fw_plat_type;
mbp_icc_profile *icc_profile;
mbp_at_state *at_state;
u32 *mfsintegrity;
mbp_plat_time *plat_time;
mbp_nfc_data *nfc_data;
} me_bios_payload;
struct me_fwcaps {
u32 id;
u8 length;
mbp_mefwcaps caps_sku;
u8 reserved[3];
} __attribute__ ((packed));
void intel_me_hsio_version(uint16_t *version, uint16_t *checksum);
#if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG)
/* Defined in me_status.c for both romstage and ramstage */
void intel_me_status(void);
#else
static inline void intel_me_status(void) { }
#endif
#endif

View File

@@ -0,0 +1,109 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_MSR_H_
#define _BROADWELL_MSR_H_
#define MSR_PIC_MSG_CONTROL 0x2e
#define CORE_THREAD_COUNT_MSR 0x35
#define IA32_FEATURE_CONTROL 0x3a
#define CPUID_VMX (1 << 5)
#define CPUID_SMX (1 << 6)
#define MSR_PLATFORM_INFO 0xce
#define PLATFORM_INFO_SET_TDP (1 << 29)
#define MSR_PMG_CST_CONFIG_CONTROL 0xe2
#define MSR_PMG_IO_CAPTURE_BASE 0xe4
#define MSR_FEATURE_CONFIG 0x13c
#define SMM_MCA_CAP_MSR 0x17d
#define SMM_CPU_SVRSTR_BIT 57
#define SMM_CPU_SVRSTR_MASK (1 << (SMM_CPU_SVRSTR_BIT - 32))
#define MSR_FLEX_RATIO 0x194
#define FLEX_RATIO_LOCK (1 << 20)
#define FLEX_RATIO_EN (1 << 16)
#define IA32_MISC_ENABLE 0x1a0
#define MSR_MISC_PWR_MGMT 0x1aa
#define MISC_PWR_MGMT_EIST_HW_DIS (1 << 0)
#define MSR_TURBO_RATIO_LIMIT 0x1ad
#define MSR_TEMPERATURE_TARGET 0x1a2
#define IA32_PERF_CTL 0x199
#define IA32_THERM_INTERRUPT 0x19b
#define IA32_ENERGY_PERFORMANCE_BIAS 0x1b0
#define ENERGY_POLICY_PERFORMANCE 0
#define ENERGY_POLICY_NORMAL 6
#define ENERGY_POLICY_POWERSAVE 15
#define IA32_PACKAGE_THERM_INTERRUPT 0x1b2
#define EMRRphysBase_MSR 0x1f4
#define EMRRphysMask_MSR 0x1f5
#define IA32_PLATFORM_DCA_CAP 0x1f8
#define MSR_POWER_CTL 0x1fc
#define MSR_LT_LOCK_MEMORY 0x2e7
#define UNCORE_EMRRphysBase_MSR 0x2f4
#define UNCORE_EMRRphysMask_MSR 0x2f5
#define IA32_MC0_STATUS 0x401
#define SMM_FEATURE_CONTROL_MSR 0x4e0
#define SMM_CPU_SAVE_EN (1 << 1)
#define MSR_C_STATE_LATENCY_CONTROL_0 0x60a
#define MSR_C_STATE_LATENCY_CONTROL_1 0x60b
#define MSR_C_STATE_LATENCY_CONTROL_2 0x60c
#define MSR_C_STATE_LATENCY_CONTROL_3 0x633
#define MSR_C_STATE_LATENCY_CONTROL_4 0x634
#define MSR_C_STATE_LATENCY_CONTROL_5 0x635
#define IRTL_VALID (1 << 15)
#define IRTL_1_NS (0 << 10)
#define IRTL_32_NS (1 << 10)
#define IRTL_1024_NS (2 << 10)
#define IRTL_32768_NS (3 << 10)
#define IRTL_1048576_NS (4 << 10)
#define IRTL_33554432_NS (5 << 10)
#define IRTL_RESPONSE_MASK (0x3ff)
#define MSR_COUNTER_24_MHZ 0x637
/* long duration in low dword, short duration in high dword */
#define MSR_PKG_POWER_LIMIT 0x610
#define PKG_POWER_LIMIT_MASK 0x7fff
#define PKG_POWER_LIMIT_EN (1 << 15)
#define PKG_POWER_LIMIT_CLAMP (1 << 16)
#define PKG_POWER_LIMIT_TIME_SHIFT 17
#define PKG_POWER_LIMIT_TIME_MASK 0x7f
#define MSR_VR_CURRENT_CONFIG 0x601
#define MSR_VR_MISC_CONFIG 0x603
#define MSR_PKG_POWER_SKU_UNIT 0x606
#define MSR_PKG_POWER_SKU 0x614
#define MSR_DDR_RAPL_LIMIT 0x618
#define MSR_VR_MISC_CONFIG2 0x636
#define MSR_PP0_POWER_LIMIT 0x638
#define MSR_PP1_POWER_LIMIT 0x640
#define MSR_CONFIG_TDP_NOMINAL 0x648
#define MSR_CONFIG_TDP_LEVEL1 0x649
#define MSR_CONFIG_TDP_LEVEL2 0x64a
#define MSR_CONFIG_TDP_CONTROL 0x64b
#define MSR_TURBO_ACTIVATION_RATIO 0x64c
/* SMM save state MSRs */
#define SMBASE_MSR 0xc20
#define IEDBASE_MSR 0xc22
/* MTRRcap_MSR bits */
#define SMRR_SUPPORTED (1<<11)
#define EMRR_SUPPORTED (1<<12)
#endif

View File

@@ -0,0 +1,71 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_NVS_H_
#define _BROADWELL_NVS_H_
#include <vendorcode/google/chromeos/gnvs.h>
#include <soc/device_nvs.h>
typedef struct {
/* 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 */
u8 pcnt; /* 0x0b - Processor Count */
u8 ppcm; /* 0x0c - Max PPC State */
u8 tmps; /* 0x0d - Temperature Sensor ID */
u8 tlvl; /* 0x0e - Throttle Level Limit */
u8 flvl; /* 0x0f - Current FAN Level */
u8 tcrt; /* 0x10 - Critical Threshold */
u8 tpsv; /* 0x11 - Passive Threshold */
u8 tmax; /* 0x12 - CPU Tj_max */
u8 s5u0; /* 0x13 - Enable USB in S5 */
u8 s3u0; /* 0x14 - Enable USB in S3 */
u8 s33g; /* 0x15 - Enable 3G in S3 */
u8 lids; /* 0x16 - LID State */
u8 pwrs; /* 0x17 - AC Power State */
u32 cmem; /* 0x18 - 0x1b - CBMEM TOC */
u32 cbmc; /* 0x1c - 0x1f - Coreboot Memory Console */
u64 pm1i; /* 0x20 - 0x27 - PM1 wake status bit */
u64 gpei; /* 0x28 - 0x2f - GPE wake status bit */
u8 unused[208];
/* ChromeOS specific (0x100 - 0xfff) */
chromeos_acpi_t chromeos;
/* Device specific (0x1000) */
device_nvs_t dev;
} __attribute__((packed)) global_nvs_t;
void acpi_create_gnvs(global_nvs_t *gnvs);
#ifdef __SMM__
/* Used in SMM to find the ACPI GNVS address */
global_nvs_t *smm_get_gnvs(void);
#endif
#endif

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_PCH_H_
#define _BROADWELL_PCH_H_
/* Haswell ULT Pch (LynxPoint-LP) */
#define PCH_LPT_LP_SAMPLE 0x9c41
#define PCH_LPT_LP_PREMIUM 0x9c43
#define PCH_LPT_LP_MAINSTREAM 0x9c45
#define PCH_LPT_LP_VALUE 0x9c47
/* Broadwell PCH (WildatPoint) */
#define PCH_WPT_HSW_U_SAMPLE 0x9cc1
#define PCH_WPT_BDW_U_SAMPLE 0x9cc2
#define PCH_WPT_BDW_U_PREMIUM 0x9cc3
#define PCH_WPT_BDW_U_BASE 0x9cc5
#define PCH_WPT_BDW_Y_SAMPLE 0x9cc6
#define PCH_WPT_BDW_Y_PREMIUM 0x9cc7
#define PCH_WPT_BDW_Y_BASE 0x9cc9
#define PCH_WPT_BDW_H 0x9ccb
/* Power Management Control and Status */
#define PCH_PCS 0x84
#define PCH_PCS_PS_D3HOT 3
u8 pch_revision(void);
u16 pch_type(void);
int pch_is_wpt(void);
int pch_is_wpt_ulx(void);
u32 pch_read_soft_strap(int id);
void pch_log_state(void);
void pch_disable_devfn(device_t dev);
#endif

View File

@@ -0,0 +1,119 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_PCI_DEVS_H_
#define _BROADWELL_PCI_DEVS_H_
#define _SA_DEVFN(slot) PCI_DEVFN(SA_DEV_SLOT_ ## slot, 0)
#define _PCH_DEVFN(slot,func) PCI_DEVFN(PCH_DEV_SLOT_ ## slot, func)
#if defined(__PRE_RAM__) || defined(__SMM__) || defined(__ROMCC__)
#include <arch/io.h>
#define _SA_DEV(slot) PCI_DEV(0, SA_DEV_SLOT_ ## slot, 0)
#define _PCH_DEV(slot,func) PCI_DEV(0, PCH_DEV_SLOT_ ## slot, func)
#else
#include <device/device.h>
#include <device/pci_def.h>
#define _SA_DEV(slot) dev_find_slot(0, _SA_DEVFN(slot))
#define _PCH_DEV(slot,func) dev_find_slot(0, _PCH_DEVFN(slot, func))
#endif
/* System Agent Devices */
#define SA_DEV_SLOT_ROOT 0x00
#define SA_DEVFN_ROOT _SA_DEVFN(ROOT)
#define SA_DEV_ROOT _SA_DEV(ROOT)
#define SA_DEV_SLOT_IGD 0x02
#define SA_DEVFN_IGD _SA_DEVFN(IGD)
#define SA_DEV_IGD _SA_DEV(IGD)
#define SA_DEV_SLOT_MINIHD 0x03
#define SA_DEVFN_MINIHD _SA_DEVFN(MINIHD)
#define SA_DEV_MINIHD _SA_DEV(MINIHD)
/* PCH Devices */
#define PCH_DEV_SLOT_ADSP 0x13
#define PCH_DEVFN_ADSP _PCH_DEVFN(ADSP, 0)
#define PCH_DEV_ADSP _PCH_DEV(ADSP, 0)
#define PCH_DEV_SLOT_XHCI 0x14
#define PCH_DEVFN_XHCI _PCH_DEVFN(XHCI, 0)
#define PCH_DEV_XHCI _PCH_DEV(XHCI, 0)
#define PCH_DEV_SLOT_SIO 0x15
#define PCH_DEV_SDMA _PCH_DEV(SIO, 0)
#define PCH_DEV_I2C0 _PCH_DEV(SIO, 1)
#define PCH_DEV_I2C1 _PCH_DEV(SIO, 2)
#define PCH_DEV_SPI0 _PCH_DEV(SIO, 3)
#define PCH_DEV_SPI1 _PCH_DEV(SIO, 4)
#define PCH_DEV_UART0 _PCH_DEV(SIO, 5)
#define PCH_DEV_UART1 _PCH_DEV(SIO, 6)
#define PCH_DEVFN_SDMA _PCH_DEVFN(SIO, 0)
#define PCH_DEVFN_I2C0 _PCH_DEVFN(SIO, 1)
#define PCH_DEVFN_I2C1 _PCH_DEVFN(SIO, 2)
#define PCH_DEVFN_SPI0 _PCH_DEVFN(SIO, 3)
#define PCH_DEVFN_SPI1 _PCH_DEVFN(SIO, 4)
#define PCH_DEVFN_UART0 _PCH_DEVFN(SIO, 5)
#define PCH_DEVFN_UART1 _PCH_DEVFN(SIO, 6)
#define PCH_DEV_SLOT_ME 0x16
#define PCH_DEVFN_ME _PCH_DEVFN(ME, 0)
#define PCH_DEVFN_ME_2 _PCH_DEVFN(ME, 1)
#define PCH_DEVFN_ME_IDER _PCH_DEVFN(ME, 2)
#define PCH_DEVFN_ME_KT _PCH_DEVFN(ME, 3)
#define PCH_DEV_ME _PCH_DEV(ME, 0)
#define PCH_DEV_ME_2 _PCH_DEV(ME, 1)
#define PCH_DEV_ME_IDER _PCH_DEV(ME, 2)
#define PCH_DEV_ME_KT _PCH_DEV(ME, 3)
#define PCH_DEV_SLOT_SDIO 0x17
#define PCH_DEVFN_SDIO _PCH_DEVFN(SDIO, 0)
#define PCH_DEV_SDIO _PCH_DEV(SDIO, 0)
#define PCH_DEV_SLOT_GBE 0x19
#define PCH_DEVFN_GBE _PCH_DEVFN(GBE, 0)
#define PCH_DEV_GBE _PCH_DEV(GBE, 0)
#define PCH_DEV_SLOT_HDA 0x1b
#define PCH_DEVFN_HDA _PCH_DEVFN(HDA, 0)
#define PCH_DEV_HDA _PCH_DEV(HDA, 0)
#define PCH_DEV_SLOT_PCIE 0x1c
#define PCH_DEV_SLOT_EHCI 0x1d
#define PCH_DEVFN_EHCI _PCH_DEVFN(EHCI, 0)
#define PCH_DEV_EHCI _PCH_DEV(EHCI, 0)
#define PCH_DEV_SLOT_LPC 0x1f
#define PCH_DEVFN_LPC _PCH_DEVFN(LPC, 0)
#define PCH_DEVFN_IDE _PCH_DEVFN(LPC, 1)
#define PCH_DEVFN_SATA _PCH_DEVFN(LPC, 2)
#define PCH_DEVFN_SMBUS _PCH_DEVFN(LPC, 3)
#define PCH_DEVFN_SATA2 _PCH_DEVFN(LPC, 5)
#define PCH_DEVFN_THERMAL _PCH_DEVFN(LPC, 6)
#define PCH_DEV_LPC _PCH_DEV(LPC, 0)
#define PCH_DEV_IDE _PCH_DEV(LPC, 1)
#define PCH_DEV_SATA _PCH_DEV(LPC, 2)
#define PCH_DEV_SMBUS _PCH_DEV(LPC, 3)
#define PCH_DEV_SATA2 _PCH_DEV(LPC, 5)
#define PCH_DEV_THERMAL _PCH_DEV(LPC, 6)
#endif

View File

@@ -0,0 +1,199 @@
/*
* Broadwell UEFI PEI wrapper
*
* Copyright (C) 2014 Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Google Inc. nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PEI_DATA_H
#define PEI_DATA_H
#include <types.h>
#include <memory_info.h>
#define PEI_VERSION 22
#define ABI_X86 __attribute__((regparm(0)))
typedef void ABI_X86 (*tx_byte_func)(unsigned char byte);
enum board_type {
BOARD_TYPE_CRB_MOBILE = 0, /* CRB Mobile */
BOARD_TYPE_CRB_DESKTOP, /* CRB Desktop */
BOARD_TYPE_USER1, /* SV mobile */
BOARD_TYPE_USER2, /* SV desktop */
BOARD_TYPE_USER3, /* SV server */
BOARD_TYPE_ULT, /* ULT */
BOARD_TYPE_CRB_EMBDEDDED, /* CRB Embedded */
BOARD_TYPE_UNKNOWN,
};
#define MAX_USB2_PORTS 14
#define MAX_USB3_PORTS 6
#define USB_OC_PIN_SKIP 8
enum usb2_port_location {
USB_PORT_BACK_PANEL = 0,
USB_PORT_FRONT_PANEL,
USB_PORT_DOCK,
USB_PORT_MINI_PCIE,
USB_PORT_FLEX,
USB_PORT_INTERNAL,
USB_PORT_SKIP,
USB_PORT_NGFF_DEVICE_DOWN,
};
struct usb2_port_setting {
/*
* Usb Port Length:
* [16:4] = length in inches in octal format
* [3:0] = decimal point
*/
uint16_t length;
uint8_t enable;
uint8_t oc_pin;
uint8_t location;
} __attribute__((packed));
struct usb3_port_setting {
uint8_t enable;
uint8_t oc_pin;
/*
* Set to 0 if trace length is > 5 inches
* Set to 1 if trace length is <= 5 inches
*/
uint8_t fixed_eq;
} __attribute__((packed));
struct pei_data
{
uint32_t pei_version;
enum board_type board_type;
int boot_mode;
int ec_present;
int usbdebug;
/* Base addresses */
uint32_t pciexbar;
uint16_t smbusbar;
uint32_t xhcibar;
uint32_t ehcibar;
uint32_t gttbar;
uint32_t rcba;
uint32_t pmbase;
uint32_t gpiobase;
uint32_t temp_mmio_base;
uint32_t tseg_size;
/*
* 0 = leave channel enabled
* 1 = disable dimm 0 on channel
* 2 = disable dimm 1 on channel
* 3 = disable dimm 0+1 on channel
*/
int dimm_channel0_disabled;
int dimm_channel1_disabled;
/* Set to 0 for memory down */
uint8_t spd_addresses[4];
/* Enable 2x Refresh Mode */
int ddr_refresh_2x;
/* DQ pins are interleaved on board */
int dq_pins_interleaved;
/* Limit DDR3 frequency */
int max_ddr3_freq;
/* Disable self refresh */
int disable_self_refresh;
/* Disable cmd power/CKEPD */
int disable_cmd_pwr;
/* USB port configuration */
struct usb2_port_setting usb2_ports[MAX_USB2_PORTS];
struct usb3_port_setting usb3_ports[MAX_USB3_PORTS];
/*
* USB3 board specific PHY tuning
*/
/* Valid range: 0x69 - 0x80 */
uint8_t usb3_txout_volt_dn_amp_adj[MAX_USB3_PORTS];
/* Valid range: 0x80 - 0x9c */
uint8_t usb3_txout_imp_sc_volt_amp_adj[MAX_USB3_PORTS];
/* Valid range: 0x39 - 0x80 */
uint8_t usb3_txout_de_emp_adj[MAX_USB3_PORTS];
/* Valid range: 0x3d - 0x4a */
uint8_t usb3_txout_imp_adj_volt_amp[MAX_USB3_PORTS];
/* Console output function */
tx_byte_func tx_byte;
/*
* DIMM SPD data for memory down configurations
* [CHANNEL][SLOT][SPD]
*/
uint8_t spd_data[2][2][512];
/*
* LPDDR3 DQ byte map
* [CHANNEL][ITERATION][2]
*
* Maps which PI clocks are used by what LPDDR DQ Bytes (from CPU side)
* DQByteMap[0] - ClkDQByteMap:
* - If clock is per rank, program to [0xFF, 0xFF]
* - If clock is shared by 2 ranks, program to [0xFF, 0] or [0, 0xFF]
* - If clock is shared by 2 ranks but does not go to all bytes,
* Entry[i] defines which DQ bytes Group i services
* DQByteMap[1] - CmdNDQByteMap: [0] is CmdN/CAA and [1] is CmdN/CAB
* DQByteMap[2] - CmdSDQByteMap: [0] is CmdS/CAA and [1] is CmdS/CAB
* DQByteMap[3] - CkeDQByteMap : [0] is CKE /CAA and [1] is CKE /CAB
* For DDR, DQByteMap[3:1] = [0xFF, 0]
* DQByteMap[4] - CtlDQByteMap : Always program to [0xFF, 0]
* since we have 1 CTL / rank
* DQByteMap[5] - CmdVDQByteMap: Always program to [0xFF, 0]
* since we have 1 CA Vref
*/
uint8_t dq_map[2][6][2];
/*
* LPDDR3 Map from CPU DQS pins to SDRAM DQS pins
* [CHANNEL][MAX_BYTES]
*/
uint8_t dqs_map[2][8];
/* Data read from flash and passed into MRC */
const void *saved_data;
int saved_data_size;
/* Disable use of saved data (can be set by mainboard) */
int disable_saved_data;
/* Data from MRC that should be saved to flash */
void *data_to_save;
int data_to_save_size;
struct memory_info meminfo;
} __attribute__((packed));
typedef struct pei_data PEI_DATA;
#endif

View File

@@ -0,0 +1,49 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_PEI_WRAPPER_H_
#define _BROADWELL_PEI_WRAPPER_H_
#include <soc/pei_data.h>
typedef int ABI_X86 (*pei_wrapper_entry_t)(struct pei_data *pei_data);
static inline void pei_data_usb2_port(struct pei_data *pei_data, int port,
uint16_t length, uint8_t enable,
uint8_t oc_pin, uint8_t location)
{
pei_data->usb2_ports[port].length = length;
pei_data->usb2_ports[port].enable = enable;
pei_data->usb2_ports[port].oc_pin = oc_pin;
pei_data->usb2_ports[port].location = location;
}
static inline void pei_data_usb3_port(struct pei_data *pei_data, int port,
uint8_t enable, uint8_t oc_pin,
uint8_t fixed_eq)
{
pei_data->usb3_ports[port].enable = enable;
pei_data->usb3_ports[port].oc_pin = oc_pin;
pei_data->usb3_ports[port].fixed_eq = fixed_eq;
}
void broadwell_fill_pei_data(struct pei_data *pei_data);
void mainboard_fill_pei_data(struct pei_data *pei_data);
#endif

View File

@@ -0,0 +1,172 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_PM_H_
#define _BROADWELL_PM_H_
/* ACPI_BASE_ADDRESS / PMBASE */
#define PM1_STS 0x00
#define WAK_STS (1 << 15)
#define PCIEXPWAK_STS (1 << 14)
#define PRBTNOR_STS (1 << 11)
#define RTC_STS (1 << 10)
#define PWRBTN_STS (1 << 8)
#define GBL_STS (1 << 5)
#define BM_STS (1 << 4)
#define TMROF_STS (1 << 0)
#define PM1_EN 0x02
#define PCIEXPWAK_DIS (1 << 14)
#define RTC_EN (1 << 10)
#define PWRBTN_EN (1 << 8)
#define GBL_EN (1 << 5)
#define TMROF_EN (1 << 0)
#define PM1_CNT 0x04
#define SLP_EN (1 << 13)
#define SLP_TYP (7 << 10)
#define SLP_TYP_SHIFT 10
#define SLP_TYP_S0 0
#define SLP_TYP_S1 1
#define SLP_TYP_S3 5
#define SLP_TYP_S4 6
#define SLP_TYP_S5 7
#define GBL_RLS (1 << 2)
#define BM_RLD (1 << 1)
#define SCI_EN (1 << 0)
#define PM1_TMR 0x08
#define SMI_EN 0x30
#define XHCI_SMI_EN (1 << 31)
#define ME_SMI_EN (1 << 30)
#define GPIO_UNLOCK_SMI_EN (1 << 27)
#define INTEL_USB2_EN (1 << 18)
#define LEGACY_USB2_EN (1 << 17)
#define PERIODIC_EN (1 << 14)
#define TCO_EN (1 << 13)
#define MCSMI_EN (1 << 11)
#define BIOS_RLS (1 << 7)
#define SWSMI_TMR_EN (1 << 6)
#define APMC_EN (1 << 5)
#define SLP_SMI_EN (1 << 4)
#define LEGACY_USB_EN (1 << 3)
#define BIOS_EN (1 << 2)
#define EOS (1 << 1)
#define GBL_SMI_EN (1 << 0)
#define SMI_STS 0x34
#define UPWRC 0x3c
#define UPWRC_WS (1 << 8)
#define UPWRC_WE (1 << 1)
#define UPWRC_SMI (1 << 0)
#define GPE_CNTL 0x42
#define SWGPE_CTRL (1 << 1)
#define DEVACT_STS 0x44
#define PM2_CNT 0x50
#define TCO1_CNT 0x60
#define TCO_TMR_HLT (1 << 11)
#define TCO1_STS 0x64
#define DMISCI_STS (1 << 9)
#define TCO2_STS 0x66
#define TCO2_STS_SECOND_TO (1 << 1)
#define GPE0_REG_MAX 4
#define GPE0_REG_SIZE 32
#define GPE0_STS(x) (0x80 + (x * 4))
#define GPE_31_0 0 /* 0x80/0x90 = GPE[31:0] */
#define GPE_63_32 1 /* 0x84/0x94 = GPE[63:32] */
#define GPE_94_64 2 /* 0x88/0x98 = GPE[94:64] */
#define GPE_STD 3 /* 0x8c/0x9c = Standard GPE */
#define WADT_STS (1 << 18)
#define GP27_STS (1 << 16)
#define PME_B0_STS (1 << 13)
#define ME_SCI_STS (1 << 12)
#define PME_STS (1 << 11)
#define BATLOW_STS (1 << 10)
#define PCI_EXP_STS (1 << 9)
#define SMB_WAK_STS (1 << 7)
#define TCOSCI_STS (1 << 6)
#define SWGPE_STS (1 << 2)
#define HOT_PLUG_STS (1 << 1)
#define GPE0_EN(x) (0x90 + (x * 4))
#define WADT_en (1 << 18)
#define GP27_EN (1 << 16)
#define PME_B0_EN (1 << 13)
#define ME_SCI_EN (1 << 12)
#define PME_EN (1 << 11)
#define BATLOW_EN (1 << 10)
#define PCI_EXP_EN (1 << 9)
#define TCOSCI_EN (1 << 6)
#define SWGPE_EN (1 << 2)
#define HOT_PLUG_EN (1 << 1)
#define MAINBOARD_POWER_OFF 0
#define MAINBOARD_POWER_ON 1
#define MAINBOARD_POWER_KEEP 2
#define SLEEP_STATE_S0 0
#define SLEEP_STATE_S3 3
#define SLEEP_STATE_S5 5
struct chipset_power_state {
uint16_t pm1_sts;
uint16_t pm1_en;
uint32_t pm1_cnt;
uint16_t tco1_sts;
uint16_t tco2_sts;
uint32_t gpe0_sts[4];
uint32_t gpe0_en[4];
uint16_t gen_pmcon1;
uint16_t gen_pmcon2;
uint16_t gen_pmcon3;
int prev_sleep_state;
uint16_t hsio_version;
uint16_t hsio_checksum;
};
/* PM1_CNT */
void enable_pm1_control(uint32_t mask);
void disable_pm1_control(uint32_t mask);
/* PM1 */
uint16_t clear_pm1_status(void);
void enable_pm1(uint16_t events);
uint32_t clear_smi_status(void);
/* SMI */
void enable_smi(uint32_t mask);
void disable_smi(uint32_t mask);
/* ALT_GP_SMI */
uint32_t clear_alt_smi_status(void);
void enable_alt_smi(uint32_t mask);
/* TCO */
uint32_t clear_tco_status(void);
void enable_tco_sci(void);
/* GPE0 */
uint32_t clear_gpe_status(void);
void clear_gpe_enable(void);
void enable_all_gpe(uint32_t set1, uint32_t set2, uint32_t set3, uint32_t set4);
void disable_all_gpe(void);
void enable_gpe(uint32_t mask);
void disable_gpe(uint32_t mask);
/* Return the selected ACPI SCI IRQ */
int acpi_sci_irq(void);
#endif

View File

@@ -0,0 +1,38 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_RAMSTAGE_H_
#define _BROADWELL_RAMSTAGE_H_
#include <device/device.h>
#include <soc/intel/broadwell/chip.h>
void broadwell_init_pre_device(void *chip_info);
void broadwell_init_cpus(device_t dev);
void broadwell_pch_enable_dev(device_t dev);
#if CONFIG_HAVE_REFCODE_BLOB
void broadwell_run_reference_code(void);
#else
static inline void broadwell_run_reference_code(void) { }
#endif
extern struct pci_operations broadwell_pci_ops;
#endif

View File

@@ -0,0 +1,178 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_RCBA_H_
#define _BROADWELL_RCBA_H_
#include <soc/iomap.h>
#define RCBA8(x) *((volatile u8 *)(RCBA_BASE_ADDRESS + x))
#define RCBA16(x) *((volatile u16 *)(RCBA_BASE_ADDRESS + x))
#define RCBA32(x) *((volatile u32 *)(RCBA_BASE_ADDRESS + x))
#define RCBA_AND_OR(bits, x, and, or) \
RCBA##bits(x) = ((RCBA##bits(x) & (and)) | (or))
#define RCBA8_AND_OR(x, and, or) RCBA_AND_OR(8, x, and, or)
#define RCBA16_AND_OR(x, and, or) RCBA_AND_OR(16, x, and, or)
#define RCBA32_AND_OR(x, and, or) RCBA_AND_OR(32, x, and, or)
#define RCBA32_OR(x, or) RCBA_AND_OR(32, x, ~0UL, or)
#define RPC 0x0400 /* 32bit */
#define RPFN 0x0404 /* 32bit */
/* Root Port configuration space hide */
#define RPFN_HIDE(port) (1 << (((port) * 4) + 3))
/* Get the function number assigned to a Root Port */
#define RPFN_FNGET(reg,port) (((reg) >> ((port) * 4)) & 7)
/* Set the function number for a Root Port */
#define RPFN_FNSET(port,func) (((func) & 7) << ((port) * 4))
/* Root Port function number mask */
#define RPFN_FNMASK(port) (7 << ((port) * 4))
#define NOINT 0
#define INTA 1
#define INTB 2
#define INTC 3
#define INTD 4
#define DIR_IDR 12 /* Interrupt D Pin Offset */
#define DIR_ICR 8 /* Interrupt C Pin Offset */
#define DIR_IBR 4 /* Interrupt B Pin Offset */
#define DIR_IAR 0 /* Interrupt A Pin Offset */
#define PIRQA 0
#define PIRQB 1
#define PIRQC 2
#define PIRQD 3
#define PIRQE 4
#define PIRQF 5
#define PIRQG 6
#define PIRQH 7
/* IO Buffer Programming */
#define IOBPIRI 0x2330
#define IOBPD 0x2334
#define IOBPS 0x2338
#define IOBPS_READY 0x0001
#define IOBPS_TX_MASK 0x0006
#define IOBPS_MASK 0xff00
#define IOBPS_READ 0x0600
#define IOBPS_WRITE 0x0700
#define IOBPU 0x233a
#define IOBPU_MAGIC 0xf000
#define IOBP_PCICFG_READ 0x0400
#define IOBP_PCICFG_WRITE 0x0500
#define D31IP 0x3100 /* 32bit */
#define D31IP_TTIP 24 /* Thermal Throttle Pin */
#define D31IP_SIP2 20 /* SATA Pin 2 */
#define D31IP_SMIP 12 /* SMBUS Pin */
#define D31IP_SIP 8 /* SATA Pin */
#define D30IP 0x3104 /* 32bit */
#define D30IP_PIP 0 /* PCI Bridge Pin */
#define D29IP 0x3108 /* 32bit */
#define D29IP_E1P 0 /* EHCI #1 Pin */
#define D28IP 0x310c /* 32bit */
#define D28IP_P8IP 28 /* PCI Express Port 8 */
#define D28IP_P7IP 24 /* PCI Express Port 7 */
#define D28IP_P6IP 20 /* PCI Express Port 6 */
#define D28IP_P5IP 16 /* PCI Express Port 5 */
#define D28IP_P4IP 12 /* PCI Express Port 4 */
#define D28IP_P3IP 8 /* PCI Express Port 3 */
#define D28IP_P2IP 4 /* PCI Express Port 2 */
#define D28IP_P1IP 0 /* PCI Express Port 1 */
#define D27IP 0x3110 /* 32bit */
#define D27IP_ZIP 0 /* HD Audio Pin */
#define D26IP 0x3114 /* 32bit */
#define D26IP_E2P 0 /* EHCI #2 Pin */
#define D25IP 0x3118 /* 32bit */
#define D25IP_LIP 0 /* GbE LAN Pin */
#define D22IP 0x3124 /* 32bit */
#define D22IP_KTIP 12 /* KT Pin */
#define D22IP_IDERIP 8 /* IDE-R Pin */
#define D22IP_MEI2IP 4 /* MEI #2 Pin */
#define D22IP_MEI1IP 0 /* MEI #1 Pin */
#define D20IP 0x3128 /* 32bit */
#define D20IP_XHCI 0 /* XHCI Pin */
#define D31IR 0x3140 /* 16bit */
#define D30IR 0x3142 /* 16bit */
#define D29IR 0x3144 /* 16bit */
#define D28IR 0x3146 /* 16bit */
#define D27IR 0x3148 /* 16bit */
#define D26IR 0x314c /* 16bit */
#define D25IR 0x3150 /* 16bit */
#define D23IR 0x3158 /* 16bit */
#define D22IR 0x315c /* 16bit */
#define D20IR 0x3160 /* 16bit */
#define D21IR 0x3164 /* 16bit */
#define D19IR 0x3168 /* 16bit */
#define ACPIIRQEN 0x31e0 /* 32bit */
#define OIC 0x31fe /* 16bit */
#define DEEP_S3_POL 0x3328 /* 32bit */
#define DEEP_S3_EN_AC (1 << 0)
#define DEEP_S3_EN_DC (1 << 1)
#define DEEP_S5_POL 0x3330 /* 32bit */
#define DEEP_S5_EN_AC (1 << 14)
#define DEEP_S5_EN_DC (1 << 15)
#define DEEP_SX_CONFIG 0x3334 /* 32bit */
#define DEEP_SX_WAKE_PIN_EN (1 << 2)
#define DEEP_SX_ACPRESENT_PD (1 << 1)
#define DEEP_SX_GP27_PIN_EN (1 << 0)
#define PMSYNC_CONFIG 0x33c4 /* 32bit */
#define PMSYNC_CONFIG2 0x33cc /* 32bit */
#define SOFT_RESET_CTRL 0x38f4
#define SOFT_RESET_DATA 0x38f8
#define DIR_ROUTE(a,b,c,d) \
(((d) << DIR_IDR) | ((c) << DIR_ICR) | \
((b) << DIR_IBR) | ((a) << DIR_IAR))
#define RC 0x3400 /* 32bit */
#define HPTC 0x3404 /* 32bit */
#define GCS 0x3410 /* 32bit */
#define BUC 0x3414 /* 32bit */
#define PCH_DISABLE_GBE (1 << 5)
#define FD 0x3418 /* 32bit */
#define FDSW 0x3420 /* 8bit */
#define DISPBDF 0x3424 /* 16bit */
#define FD2 0x3428 /* 32bit */
#define CG 0x341c /* 32bit */
/* Function Disable 1 RCBA 0x3418 */
#define PCH_DISABLE_ALWAYS (1 << 0)
#define PCH_DISABLE_ADSPD (1 << 1)
#define PCH_DISABLE_SATA1 (1 << 2)
#define PCH_DISABLE_SMBUS (1 << 3)
#define PCH_DISABLE_HD_AUDIO (1 << 4)
#define PCH_DISABLE_EHCI2 (1 << 13)
#define PCH_DISABLE_LPC (1 << 14)
#define PCH_DISABLE_EHCI1 (1 << 15)
#define PCH_DISABLE_PCIE(x) (1 << (16 + x))
#define PCH_DISABLE_THERMAL (1 << 24)
#define PCH_DISABLE_SATA2 (1 << 25)
#define PCH_DISABLE_XHCI (1 << 27)
/* Function Disable 2 RCBA 0x3428 */
#define PCH_DISABLE_KT (1 << 4)
#define PCH_DISABLE_IDER (1 << 3)
#define PCH_DISABLE_MEI2 (1 << 2)
#define PCH_DISABLE_MEI1 (1 << 1)
#define PCH_ENABLE_DBDF (1 << 0)
#endif

View File

@@ -0,0 +1,25 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_RESET_H_
#define _BROADWELL_RESET_H_
void reset_system(void);
#endif

View File

@@ -0,0 +1,61 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_ROMSTAGE_H_
#define _BROADWELL_ROMSTAGE_H_
#include <stdint.h>
#include <arch/cpu.h>
struct chipset_power_state;
struct pei_data;
struct romstage_params {
unsigned long bist;
struct chipset_power_state *power_state;
struct pei_data *pei_data;
};
void mainboard_romstage_entry(struct romstage_params *params);
void romstage_common(struct romstage_params *params);
void *asmlinkage romstage_main(unsigned long bist, uint32_t tsc_lo,
uint32_t tsc_high);
void asmlinkage romstage_after_car(void);
void raminit(struct pei_data *pei_data);
void *setup_stack_and_mttrs(void);
struct chipset_power_state;
struct chipset_power_state *fill_power_state(void);
void report_platform_info(void);
void report_memory_config(void);
void set_max_freq(void);
void systemagent_early_init(void);
void pch_early_init(void);
void pch_uart_init(void);
void intel_early_me_status(void);
void enable_smbus(void);
int smbus_read_byte(unsigned device, unsigned address);
int early_spi_read(u32 offset, u32 size, u8 *buffer);
int early_spi_read_wpsr(u8 *sr);
void mainboard_pre_console_init(void);
#endif

View File

@@ -0,0 +1,89 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_SATA_H_
#define _BROADWELL_SATA_H_
#define SATA_SIRI 0xa0 /* SATA Indexed Register Index */
#define SATA_SIRD 0xa4 /* SATA Indexed Register Data */
#define SATA_SP 0xd0 /* Scratchpad */
/* SATA IOBP Registers */
#define SATA_IOBP_SP0_SECRT88 0xea002688
#define SATA_IOBP_SP1_SECRT88 0xea002488
#define SATA_SECRT88_VADJ_MASK 0xff
#define SATA_SECRT88_VADJ_SHIFT 16
#define SATA_IOBP_SP0DTLE_DATA 0xea002550
#define SATA_IOBP_SP0DTLE_EDGE 0xea002554
#define SATA_IOBP_SP1DTLE_DATA 0xea002750
#define SATA_IOBP_SP1DTLE_EDGE 0xea002754
#define SATA_DTLE_MASK 0xF
#define SATA_DTLE_DATA_SHIFT 24
#define SATA_DTLE_EDGE_SHIFT 16
/* PCI Configuration Space (D31:F1): IDE */
#define INTR_LN 0x3c
#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_SEC_NORMAL (0 << 18)
#define SIG_MODE_SEC_TRISTATE (1 << 18)
#define SIG_MODE_SEC_DRIVELOW (2 << 18)
#define SIG_MODE_PRI_NORMAL (0 << 16)
#define SIG_MODE_PRI_TRISTATE (1 << 16)
#define SIG_MODE_PRI_DRIVELOW (2 << 16)
#define FAST_SCB1 (1 << 15)
#define FAST_SCB0 (1 << 14)
#define FAST_PCB1 (1 << 13)
#define FAST_PCB0 (1 << 12)
#define SCB1 (1 << 3)
#define SCB0 (1 << 2)
#define PCB1 (1 << 1)
#define PCB0 (1 << 0)
#endif

View File

@@ -0,0 +1,94 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_SERIALIO_H_
#define _BROADWELL_SERIALIO_H_
/* Serial IO IOBP Registers */
#define SIO_IOBP_PORTCTRL0 0xcb000000 /* SDIO D23:F0 */
#define SIO_IOBP_PORTCTRL0_ACPI_IRQ_EN (1 << 5)
#define SIO_IOBP_PORTCTRL0_PCI_CONF_DIS (1 << 4)
#define SIO_IOBP_PORTCTRL1 0xcb000014 /* SDIO D23:F0 */
#define SIO_IOBP_PORTCTRL1_SNOOP_SELECT(x) (((x) & 3) << 13)
#define SIO_IOBP_GPIODF 0xcb000154
#define SIO_IOBP_GPIODF_SDIO_IDLE_DET_EN (1 << 4)
#define SIO_IOBP_GPIODF_DMA_IDLE_DET_EN (1 << 3)
#define SIO_IOBP_GPIODF_UART_IDLE_DET_EN (1 << 2)
#define SIO_IOBP_GPIODF_I2C_IDLE_DET_EN (1 << 1)
#define SIO_IOBP_GPIODF_SPI_IDLE_DET_EN (1 << 0)
#define SIO_IOBP_GPIODF_UART0_BYTE_ACCESS (1 << 10)
#define SIO_IOBP_GPIODF_UART1_BYTE_ACCESS (1 << 11)
#define SIO_IOBP_PORTCTRL2 0xcb000240 /* DMA D21:F0 */
#define SIO_IOBP_PORTCTRL3 0xcb000248 /* I2C0 D21:F1 */
#define SIO_IOBP_PORTCTRL4 0xcb000250 /* I2C1 D21:F2 */
#define SIO_IOBP_PORTCTRL5 0xcb000258 /* SPI0 D21:F3 */
#define SIO_IOBP_PORTCTRL6 0xcb000260 /* SPI1 D21:F4 */
#define SIO_IOBP_PORTCTRL7 0xcb000268 /* UART0 D21:F5 */
#define SIO_IOBP_PORTCTRL8 0xcb000270 /* UART1 D21:F6 */
#define SIO_IOBP_PORTCTRLX(x) (0xcb000240 + ((x) * 8))
/* PORTCTRL 2-8 have the same layout */
#define SIO_IOBP_PORTCTRL_ACPI_IRQ_EN (1 << 21)
#define SIO_IOBP_PORTCTRL_PCI_CONF_DIS (1 << 20)
#define SIO_IOBP_PORTCTRL_SNOOP_SELECT(x) (((x) & 3) << 18)
#define SIO_IOBP_PORTCTRL_INT_PIN(x) (((x) & 0xf) << 2)
#define SIO_IOBP_PORTCTRL_PM_CAP_PRSNT (1 << 1)
#define SIO_IOBP_FUNCDIS0 0xce00aa07 /* DMA D21:F0 */
#define SIO_IOBP_FUNCDIS1 0xce00aa47 /* I2C0 D21:F1 */
#define SIO_IOBP_FUNCDIS2 0xce00aa87 /* I2C1 D21:F2 */
#define SIO_IOBP_FUNCDIS3 0xce00aac7 /* SPI0 D21:F3 */
#define SIO_IOBP_FUNCDIS4 0xce00ab07 /* SPI1 D21:F4 */
#define SIO_IOBP_FUNCDIS5 0xce00ab47 /* UART0 D21:F5 */
#define SIO_IOBP_FUNCDIS6 0xce00ab87 /* UART1 D21:F6 */
#define SIO_IOBP_FUNCDIS7 0xce00ae07 /* SDIO D23:F0 */
#define SIO_IOBP_FUNCDIS_DIS (1 << 8)
/* Serial IO Devices */
#define SIO_ID_SDMA 0 /* D21:F0 */
#define SIO_ID_I2C0 1 /* D21:F1 */
#define SIO_ID_I2C1 2 /* D21:F2 */
#define SIO_ID_SPI0 3 /* D21:F3 */
#define SIO_ID_SPI1 4 /* D21:F4 */
#define SIO_ID_UART0 5 /* D21:F5 */
#define SIO_ID_UART1 6 /* D21:F6 */
#define SIO_ID_SDIO 7 /* D23:F0 */
#define SIO_REG_PPR_CLOCK 0x800
#define SIO_REG_PPR_CLOCK_EN (1 << 0)
#define SIO_REG_PPR_CLOCK_UPDATE (1 << 31)
#define SIO_REG_PPR_CLOCK_M_DIV 0x25a
#define SIO_REG_PPR_CLOCK_N_DIV 0x7fff
#define SIO_REG_PPR_RST 0x804
#define SIO_REG_PPR_RST_ASSERT 0x3
#define SIO_REG_PPR_GEN 0x808
#define SIO_REG_PPR_GEN_LTR_MODE_MASK (1 << 2)
#define SIO_REG_PPR_GEN_VOLTAGE_MASK (1 << 3)
#define SIO_REG_PPR_GEN_VOLTAGE(x) ((x & 1) << 3)
#define SIO_REG_AUTO_LTR 0x814
#define SIO_REG_SDIO_PPR_GEN 0x1008
#define SIO_REG_SDIO_PPR_SW_LTR 0x1010
#define SIO_REG_SDIO_PPR_CMD12 0x3c
#define SIO_REG_SDIO_PPR_CMD12_B30 (1 << 30)
#define SIO_PIN_INTA 1 /* IRQ5 in ACPI mode */
#define SIO_PIN_INTB 2 /* IRQ6 in ACPI mode */
#define SIO_PIN_INTC 3 /* IRQ7 in ACPI mode */
#define SIO_PIN_INTD 4 /* IRQ13 in ACPI mode */
#endif

View File

@@ -0,0 +1,52 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
* Copyright (C) 2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_SMBUS_H_
#define _BROADWELL_SMBUS_H_
/* PCI Configuration Space (D31:F3): SMBus */
#define SMB_BASE 0x20
#define HOSTC 0x40
#define HST_EN (1 << 0)
#define SMB_RCV_SLVA 0x09
/* SMBus I/O bits. */
#define SMBHSTSTAT 0x0
#define SMBHSTCTL 0x2
#define SMBHSTCMD 0x3
#define SMBXMITADD 0x4
#define SMBHSTDAT0 0x5
#define SMBHSTDAT1 0x6
#define SMBBLKDAT 0x7
#define SMBTRNSADD 0x9
#define SMBSLVDATA 0xa
#define SMLINK_PIN_CTL 0xe
#define SMBUS_PIN_CTL 0xf
#define SMBUS_TIMEOUT (10 * 1000 * 100)
#define SMBUS_SLAVE_ADDR 0x24
int do_smbus_read_byte(unsigned smbus_base, unsigned device,
unsigned address);
int do_smbus_write_byte(unsigned smbus_base, unsigned device,
unsigned address, unsigned data);
#endif

View File

@@ -0,0 +1,73 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_SMM_H_
#define _BROADWELL_SMM_H_
#include <stdint.h>
#include <cpu/x86/msr.h>
struct ied_header {
char signature[10];
u32 size;
u8 reserved[34];
} __attribute__ ((packed));
struct smm_relocation_params {
u32 smram_base;
u32 smram_size;
u32 ied_base;
u32 ied_size;
msr_t smrr_base;
msr_t smrr_mask;
msr_t emrr_base;
msr_t emrr_mask;
msr_t uncore_emrr_base;
msr_t uncore_emrr_mask;
/* The smm_save_state_in_msrs field indicates if SMM save state
* locations live in MSRs. This indicates to the CPUs how to adjust
* the SMMBASE and IEDBASE */
int smm_save_state_in_msrs;
};
/* There is a bug in the order of Kconfig includes in that arch/x86/Kconfig
* is included after chipset code. This causes the chipset's Kconfig to be
* clobbered by the arch/x86/Kconfig if they have the same name. */
static inline int smm_region_size(void)
{
/* Make it 8MiB by default. */
if (CONFIG_SMM_TSEG_SIZE == 0)
return (8 << 20);
return CONFIG_SMM_TSEG_SIZE;
}
int smm_initialize(void);
void smm_relocate(void);
/* These helpers are for performing SMM relocation. */
void southbridge_trigger_smi(void);
void southbridge_clear_smi_status(void);
/* The initialization of the southbridge is split into 2 components. One is
* for clearing the state in the SMM registers. The other is for enabling
* SMIs. They are split so that other work between the 2 actions. */
void southbridge_smm_clear_state(void);
void southbridge_smm_enable_smi(void);
#endif

View File

@@ -0,0 +1,110 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_SPI_H_
#define _BROADWELL_SPI_H_
/*
* SPI Opcode Menu setup for SPIBAR lockdown
* should support most common flash chips.
*/
#define SPIBAR_OFFSET 0x3800
#define SPIBAR8(x) RCBA8(x + SPIBAR_OFFSET)
#define SPIBAR16(x) RCBA16(x + SPIBAR_OFFSET)
#define SPIBAR32(x) RCBA32(x + SPIBAR_OFFSET)
/* Registers within the SPIBAR */
#define SPIBAR_SSFC 0x91
#define SPIBAR_FDOC 0xb0
#define SPIBAR_FDOD 0xb4
#define SPI_PRR_MAX 5
#define SPI_PRR(x) (0x74 + ((x) * 4))
#define SPI_PRR_SHIFT 12
#define SPI_PRR_MASK 0x1fff
#define SPI_PRR_BASE_SHIFT 0
#define SPI_PRR_LIMIT_SHIFT 16
#define SPI_PRR_WPE (1 << 31)
#define SPIBAR_PREOP 0x94
#define SPIBAR_OPTYPE 0x96
#define SPIBAR_OPMENU_LOWER 0x98
#define SPIBAR_OPMENU_UPPER 0x9c
#define SPI_OPMENU_0 0x01 /* WRSR: Write Status Register */
#define SPI_OPTYPE_0 0x01 /* Write, no address */
#define SPI_OPMENU_1 0x02 /* BYPR: Byte Program */
#define SPI_OPTYPE_1 0x03 /* Write, address required */
#define SPI_OPMENU_2 0x03 /* READ: Read Data */
#define SPI_OPTYPE_2 0x02 /* Read, address required */
#define SPI_OPMENU_3 0x05 /* RDSR: Read Status Register */
#define SPI_OPTYPE_3 0x00 /* Read, no address */
#define SPI_OPMENU_4 0x20 /* SE20: Sector Erase 0x20 */
#define SPI_OPTYPE_4 0x03 /* Write, address required */
#define SPI_OPMENU_5 0x9f /* RDID: Read ID */
#define SPI_OPTYPE_5 0x00 /* Read, no address */
#define SPI_OPMENU_6 0xd8 /* BED8: Block Erase 0xd8 */
#define SPI_OPTYPE_6 0x03 /* Write, address required */
#define SPI_OPMENU_7 0x0b /* FAST: Fast Read */
#define SPI_OPTYPE_7 0x02 /* Read, address required */
#define SPI_OPMENU_UPPER ((SPI_OPMENU_7 << 24) | (SPI_OPMENU_6 << 16) | \
(SPI_OPMENU_5 << 8) | SPI_OPMENU_4)
#define SPI_OPMENU_LOWER ((SPI_OPMENU_3 << 24) | (SPI_OPMENU_2 << 16) | \
(SPI_OPMENU_1 << 8) | SPI_OPMENU_0)
#define SPI_OPTYPE ((SPI_OPTYPE_7 << 14) | (SPI_OPTYPE_6 << 12) | \
(SPI_OPTYPE_5 << 10) | (SPI_OPTYPE_4 << 8) | \
(SPI_OPTYPE_3 << 6) | (SPI_OPTYPE_2 << 4) | \
(SPI_OPTYPE_1 << 2) | (SPI_OPTYPE_0))
#define SPI_OPPREFIX ((0x50 << 8) | 0x06) /* EWSR and WREN */
#define SPIBAR_HSFS 0x04 /* SPI hardware sequence status */
#define SPIBAR_HSFS_FLOCKDN (1 << 15)/* Flash Configuration Lock-Down */
#define SPIBAR_HSFS_SCIP (1 << 5) /* SPI Cycle In Progress */
#define SPIBAR_HSFS_AEL (1 << 2) /* SPI Access Error Log */
#define SPIBAR_HSFS_FCERR (1 << 1) /* SPI Flash Cycle Error */
#define SPIBAR_HSFS_FDONE (1 << 0) /* SPI Flash Cycle Done */
#define SPIBAR_HSFC 0x06 /* SPI hardware sequence control */
#define SPIBAR_HSFC_BYTE_COUNT(c) (((c - 1) & 0x3f) << 8)
#define SPIBAR_HSFC_CYCLE_READ (0 << 1) /* Read cycle */
#define SPIBAR_HSFC_CYCLE_WRITE (2 << 1) /* Write cycle */
#define SPIBAR_HSFC_CYCLE_ERASE (3 << 1) /* Erase cycle */
#define SPIBAR_HSFC_GO (1 << 0) /* GO: start SPI transaction */
#define SPIBAR_FADDR 0x08 /* SPI flash address */
#define SPIBAR_FDATA(n) (0x10 + (4 * n)) /* SPI flash data */
#define SPIBAR_SSFS 0x90
#define SPIBAR_SSFS_ERROR (1 << 3)
#define SPIBAR_SSFS_DONE (1 << 2)
#define SPIBAR_SSFC 0x91
#define SPIBAR_SSFC_DATA (1 << 14)
#define SPIBAR_SSFC_GO (1 << 1)
int spi_flash_protect(u32 start, u32 size);
#endif

View File

@@ -0,0 +1,135 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2008 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_SYSTEMAGENT_H_
#define _BROADWELL_SYSTEMAGENT_H_
#include <soc/iomap.h>
#define SA_IGD_OPROM_VENDEV 0x80860406
#define IGD_HASWELL_ULT_GT1 0x0a06
#define IGD_HASWELL_ULT_GT2 0x0a16
#define IGD_HASWELL_ULT_GT3 0x0a26
#define IGD_BROADWELL_U_GT1 0x1606
#define IGD_BROADWELL_U_GT2 0x1616
#define IGD_BROADWELL_U_GT3_15W 0x1626
#define IGD_BROADWELL_U_GT3_28W 0x162b
#define IGD_BROADWELL_Y_GT2 0x161e
#define IGD_BROADWELL_H_GT2 0x1612
#define IGD_BROADWELL_H_GT3 0x1622
#define MCH_BROADWELL_ID_U_Y 0x1604
#define MCH_BROADWELL_REV_D0 0x06
#define MCH_BROADWELL_REV_E0 0x08
#define MCH_BROADWELL_REV_F0 0x09
/* Device 0:0.0 PCI configuration space */
#define EPBAR 0x40
#define MCHBAR 0x48
#define PCIEXBAR 0x60
#define DMIBAR 0x68
#define GGC 0x50 /* GMCH Graphics Control */
#define DEVEN 0x54 /* Device Enable */
#define DEVEN_D7EN (1 << 14)
#define DEVEN_D4EN (1 << 7)
#define DEVEN_D3EN (1 << 5)
#define DEVEN_D2EN (1 << 4)
#define DEVEN_D1F0EN (1 << 3)
#define DEVEN_D1F1EN (1 << 2)
#define DEVEN_D1F2EN (1 << 1)
#define DEVEN_D0EN (1 << 0)
#define DPR 0x5c
#define DPR_EPM (1 << 2)
#define DPR_PRS (1 << 1)
#define DPR_SIZE_MASK 0xff0
#define PAM0 0x80
#define PAM1 0x81
#define PAM2 0x82
#define PAM3 0x83
#define PAM4 0x84
#define PAM5 0x85
#define PAM6 0x86
#define SMRAM 0x88 /* System Management RAM Control */
#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))
#define MESEG_BASE 0x70 /* Management Engine Base. */
#define MESEG_LIMIT 0x78 /* Management Engine Limit. */
#define REMAPBASE 0x90 /* Remap base. */
#define REMAPLIMIT 0x98 /* Remap limit. */
#define TOM 0xa0 /* Top of DRAM in memory controller space. */
#define TOUUD 0xa8 /* Top of Upper Usable DRAM */
#define BDSM 0xb0 /* Base Data Stolen Memory */
#define BGSM 0xb4 /* Base GTT Stolen Memory */
#define TSEG 0xb8 /* TSEG base */
#define TOLUD 0xbc /* Top of Low Used Memory */
#define SKPAD 0xdc /* Scratchpad Data */
/* MCHBAR */
#define MCHBAR8(x) *((volatile u8 *)(MCH_BASE_ADDRESS + x))
#define MCHBAR16(x) *((volatile u16 *)(MCH_BASE_ADDRESS + x))
#define MCHBAR32(x) *((volatile u32 *)(MCH_BASE_ADDRESS + x))
#define MCHBAR_PEI_VERSION 0x5034
#define BIOS_RESET_CPL 0x5da8
#define EDRAMBAR 0x5408
#define MCH_PAIR 0x5418
#define GDXCBAR 0x5420
#define MCH_PKG_POWER_LIMIT_LO 0x59a0
#define MCH_PKG_POWER_LIMIT_HI 0x59a4
#define MCH_DDR_POWER_LIMIT_LO 0x58e0
#define MCH_DDR_POWER_LIMIT_HI 0x58e4
/* PCODE MMIO communications live in the MCHBAR. */
#define BIOS_MAILBOX_INTERFACE 0x5da4
#define MAILBOX_RUN_BUSY (1 << 31)
#define MAILBOX_BIOS_CMD_READ_PCS 1
#define MAILBOX_BIOS_CMD_WRITE_PCS 2
#define MAILBOX_BIOS_CMD_READ_CALIBRATION 0x509
#define MAILBOX_BIOS_CMD_FSM_MEASURE_INTVL 0x909
#define MAILBOX_BIOS_CMD_READ_PCH_POWER 0xa
#define MAILBOX_BIOS_CMD_READ_PCH_POWER_EXT 0xb
#define MAILBOX_BIOS_CMD_READ_C9C10_VOLTAGE 0x26
#define MAILBOX_BIOS_CMD_WRITE_C9C10_VOLTAGE 0x27
/* Errors are returned back in bits 7:0. */
#define MAILBOX_BIOS_ERROR_NONE 0
#define MAILBOX_BIOS_ERROR_INVALID_COMMAND 1
#define MAILBOX_BIOS_ERROR_TIMEOUT 2
#define MAILBOX_BIOS_ERROR_ILLEGAL_DATA 3
#define MAILBOX_BIOS_ERROR_RESERVED 4
#define MAILBOX_BIOS_ERROR_ILLEGAL_VR_ID 5
#define MAILBOX_BIOS_ERROR_VR_INTERFACE_LOCKED 6
#define MAILBOX_BIOS_ERROR_VR_ERROR 7
/* Data is passed through bits 31:0 of the data register. */
#define BIOS_MAILBOX_DATA 0x5da0
/* System Agent identification */
u8 systemagent_revision(void);
#endif

View File

@@ -0,0 +1,61 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#ifndef _BROADWELL_XHCI_H_
#define _BROADWELL_XHCI_H_
/* XHCI PCI Registers */
#define XHCI_PWR_CTL_STS 0x74
#define XHCI_PWR_CTL_SET_MASK 0x3
#define XHCI_PWR_CTL_SET_D0 0x0
#define XHCI_PWR_CTL_SET_D3 0x3
#define XHCI_PWR_CTL_ENABLE_PME (1 << 8)
#define XHCI_PWR_CTL_STATUS_PME (1 << 15)
#define XHCI_USB2PR 0xd0
#define XHCI_USB2PRM 0xd4
#define XHCI_USB2PR_HCSEL 0x7fff
#define XHCI_USB3PR 0xd8
#define XHCI_USB3PR_SSEN 0x3f
#define XHCI_USB3PRM 0xdc
#define XHCI_USB3FUS 0xe0
#define XHCI_USB3FUS_SS_MASK 3
#define XHCI_USB3FUS_SS_SHIFT 3
#define XHCI_USB3PDO 0xe8
/* XHCI Memory Registers */
#define XHCI_USB3_PORTSC(port) (0x530 + (port * 0x10))
#define XHCI_USB3_PORTSC_CHST (0x7f << 17)
#define XHCI_USB3_PORTSC_WCE (1 << 25) /* Wake on Connect */
#define XHCI_USB3_PORTSC_WDE (1 << 26) /* Wake on Disconnect */
#define XHCI_USB3_PORTSC_WOE (1 << 27) /* Wake on Overcurrent */
#define XHCI_USB3_PORTSC_WRC (1 << 19) /* Warm Reset Complete */
#define XHCI_USB3_PORTSC_LWS (1 << 16) /* Link Write Strobe */
#define XHCI_USB3_PORTSC_PED (1 << 1) /* Port Enabled/Disabled */
#define XHCI_USB3_PORTSC_WPR (1 << 31) /* Warm Port Reset */
#define XHCI_USB3_PORTSC_PLS (0xf << 5) /* Port Link State */
#define XHCI_PLSR_DISABLED (4 << 5) /* Port is disabled */
#define XHCI_PLSR_RXDETECT (5 << 5) /* Port is disconnected */
#define XHCI_PLSR_POLLING (7 << 5) /* Port is polling */
#define XHCI_PLSW_ENABLE (5 << 5) /* Transition from disabled */
#ifdef __SMM__
void usb_xhci_sleep_prepare(device_t dev, u8 slp_typ);
#endif
#endif

View File

@@ -0,0 +1,152 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <console/console.h>
#include <delay.h>
#include <arch/io.h>
#include <soc/iobp.h>
#include <soc/rcba.h>
#define IOBP_RETRY 1000
static inline int iobp_poll(void)
{
unsigned try;
for (try = IOBP_RETRY; try > 0; try--) {
u16 status = RCBA16(IOBPS);
if ((status & IOBPS_READY) == 0)
return 1;
udelay(10);
}
printk(BIOS_ERR, "IOBP: timeout waiting for transaction to complete\n");
return 0;
}
u32 pch_iobp_read(u32 address)
{
u16 status;
if (!iobp_poll())
return 0;
/* Set the address */
RCBA32(IOBPIRI) = address;
/* READ OPCODE */
status = RCBA16(IOBPS);
status &= ~IOBPS_MASK;
status |= IOBPS_READ;
RCBA16(IOBPS) = status;
/* Undocumented magic */
RCBA16(IOBPU) = IOBPU_MAGIC;
/* Set ready bit */
status = RCBA16(IOBPS);
status |= IOBPS_READY;
RCBA16(IOBPS) = status;
if (!iobp_poll())
return 0;
/* Check for successful transaction */
status = RCBA16(IOBPS);
if (status & IOBPS_TX_MASK) {
printk(BIOS_ERR, "IOBP: read 0x%08x failed\n", address);
return 0;
}
/* Read IOBP data */
return RCBA32(IOBPD);
}
void pch_iobp_write(u32 address, u32 data)
{
u16 status;
if (!iobp_poll())
return;
/* Set the address */
RCBA32(IOBPIRI) = address;
/* WRITE OPCODE */
status = RCBA16(IOBPS);
status &= ~IOBPS_MASK;
status |= IOBPS_WRITE;
RCBA16(IOBPS) = status;
RCBA32(IOBPD) = data;
/* Undocumented magic */
RCBA16(IOBPU) = IOBPU_MAGIC;
/* Set ready bit */
status = RCBA16(IOBPS);
status |= IOBPS_READY;
RCBA16(IOBPS) = status;
if (!iobp_poll())
return;
/* Check for successful transaction */
status = RCBA16(IOBPS);
if (status & IOBPS_TX_MASK)
printk(BIOS_ERR, "IOBP: write 0x%08x failed\n", address);
}
void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue)
{
u32 data = pch_iobp_read(address);
/* Update the data */
data &= andvalue;
data |= orvalue;
pch_iobp_write(address, data);
}
void pch_iobp_exec(u32 addr, u16 op_code, u8 route_id, u32 *data, u8 *resp)
{
if (!data || !resp)
return;
*resp = -1;
if (!iobp_poll())
return;
/* RCBA2330[31:0] = Address */
RCBA32(IOBPIRI) = addr;
/* RCBA2338[15:8] = opcode */
RCBA16(IOBPS) = (RCBA16(IOBPS) & 0x00ff) | op_code;
/* RCBA233A[15:8] = 0xf0 RCBA233A[7:0] = Route ID */
RCBA16(IOBPU) = IOBPU_MAGIC | route_id;
RCBA32(IOBPD) = *data;
/* Set RCBA2338[0] to trigger IOBP transaction*/
RCBA16(IOBPS) = RCBA16(IOBPS) | 0x1;
if (!iobp_poll())
return;
*resp = (RCBA16(IOBPS) & IOBPS_TX_MASK) >> 1;
*data = RCBA32(IOBPD);
}

670
src/soc/intel/skylake/lpc.c Normal file
View File

@@ -0,0 +1,670 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <console/console.h>
#include <delay.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <pc80/mc146818rtc.h>
#include <pc80/isa-dma.h>
#include <pc80/i8259.h>
#include <arch/io.h>
#include <arch/ioapic.h>
#include <arch/acpi.h>
#include <cpu/cpu.h>
#include <cpu/x86/smm.h>
#include <cbmem.h>
#include <reg_script.h>
#include <string.h>
#include <soc/gpio.h>
#include <soc/iobp.h>
#include <soc/iomap.h>
#include <soc/lpc.h>
#include <soc/nvs.h>
#include <soc/pch.h>
#include <soc/pci_devs.h>
#include <soc/pm.h>
#include <soc/ramstage.h>
#include <soc/rcba.h>
#include <soc/intel/broadwell/chip.h>
#include <arch/acpi.h>
#include <arch/acpigen.h>
#include <cpu/cpu.h>
#if IS_ENABLED(CONFIG_CHROMEOS)
#include <vendorcode/google/chromeos/chromeos.h>
#endif
static void pch_enable_ioapic(struct device *dev)
{
u32 reg32;
set_ioapic_id(VIO_APIC_VADDR, 0x02);
/* affirm full set of redirection table entries ("write once") */
reg32 = io_apic_read(VIO_APIC_VADDR, 0x01);
/* PCH-LP has 39 redirection entries */
reg32 &= ~0x00ff0000;
reg32 |= 0x00270000;
io_apic_write(VIO_APIC_VADDR, 0x01, reg32);
/*
* Select Boot Configuration register (0x03) and
* use Processor System Bus (0x01) to deliver interrupts.
*/
io_apic_write(VIO_APIC_VADDR, 0x03, 0x01);
}
/* 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 pch_pirq_init(device_t dev)
{
device_t irq_dev;
config_t *config = dev->chip_info;
pci_write_config8(dev, PIRQA_ROUT, config->pirqa_routing);
pci_write_config8(dev, PIRQB_ROUT, config->pirqb_routing);
pci_write_config8(dev, PIRQC_ROUT, config->pirqc_routing);
pci_write_config8(dev, PIRQD_ROUT, config->pirqd_routing);
pci_write_config8(dev, PIRQE_ROUT, config->pirqe_routing);
pci_write_config8(dev, PIRQF_ROUT, config->pirqf_routing);
pci_write_config8(dev, PIRQG_ROUT, config->pirqg_routing);
pci_write_config8(dev, PIRQH_ROUT, config->pirqh_routing);
for(irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
u8 int_pin=0, int_line=0;
if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
continue;
int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
switch (int_pin) {
case 1: /* INTA# */ int_line = config->pirqa_routing; break;
case 2: /* INTB# */ int_line = config->pirqb_routing; break;
case 3: /* INTC# */ int_line = config->pirqc_routing; break;
case 4: /* INTD# */ int_line = config->pirqd_routing; break;
}
if (!int_line)
continue;
pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, int_line);
}
}
static void pch_power_options(device_t dev)
{
u16 reg16;
const char *state;
/* Get the chip configuration */
config_t *config = dev->chip_info;
int pwr_on=CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
/* Which state do we want to goto after g3 (power restored)?
* 0 == S0 Full On
* 1 == S5 Soft Off
*
* If the option is not existent (Laptops), use Kconfig setting.
*/
get_option(&pwr_on, "power_on_after_fail");
reg16 = pci_read_config16(dev, GEN_PMCON_3);
reg16 &= 0xfffe;
switch (pwr_on) {
case MAINBOARD_POWER_OFF:
reg16 |= 1;
state = "off";
break;
case MAINBOARD_POWER_ON:
reg16 &= ~1;
state = "on";
break;
case MAINBOARD_POWER_KEEP:
reg16 &= ~1;
state = "state keep";
break;
default:
state = "undefined";
}
pci_write_config16(dev, GEN_PMCON_3, reg16);
printk(BIOS_INFO, "Set power %s after power failure.\n", state);
/* GPE setup based on device tree configuration */
enable_all_gpe(config->gpe0_en_1, config->gpe0_en_2,
config->gpe0_en_3, config->gpe0_en_4);
/* SMI setup based on device tree configuration */
enable_alt_smi(config->alt_gp_smi_en);
}
#if IS_ENABLED(CONFIG_CHROMEOS) && IS_ENABLED(CONFIG_CHROMEOS_VBNV_CMOS)
/*
* Preserve Vboot NV data when clearing CMOS as it will
* have been re-initialized already by Vboot firmware init.
*/
static void pch_cmos_init_preserve(int reset)
{
uint8_t vbnv[CONFIG_VBNV_SIZE];
if (reset)
read_vbnv(vbnv);
cmos_init(reset);
if (reset)
save_vbnv(vbnv);
}
#endif
static void pch_rtc_init(struct device *dev)
{
u8 reg8;
int rtc_failed;
reg8 = pci_read_config8(dev, GEN_PMCON_3);
rtc_failed = reg8 & RTC_BATTERY_DEAD;
if (rtc_failed) {
reg8 &= ~RTC_BATTERY_DEAD;
pci_write_config8(dev, GEN_PMCON_3, reg8);
printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
}
#if IS_ENABLED(CONFIG_CHROMEOS) && IS_ENABLED(CONFIG_CHROMEOS_VBNV_CMOS)
pch_cmos_init_preserve(rtc_failed);
#else
cmos_init(rtc_failed);
#endif
}
static const struct reg_script pch_misc_init_script[] = {
/* Setup SLP signal assertion, SLP_S4=4s, SLP_S3=50ms */
REG_PCI_RMW16(GEN_PMCON_3, ~((3 << 4)|(1 << 10)),
(1 << 3)|(1 << 11)|(1 << 12)),
/* Prepare sleep mode */
REG_IO_RMW32(ACPI_BASE_ADDRESS + PM1_CNT, ~SLP_TYP, SCI_EN),
/* Setup NMI on errors, disable SERR */
REG_IO_RMW8(0x61, ~0xf0, (1 << 2)),
/* Disable NMI sources */
REG_IO_OR8(0x70, (1 << 7)),
/* Indicate DRAM init done for MRC */
REG_PCI_OR8(GEN_PMCON_2, (1 << 7)),
/* Enable BIOS updates outside of SMM */
REG_PCI_RMW8(0xdc, ~(1 << 5), 0),
/* Clear status bits to prevent unexpected wake */
REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x3310, 0x0000002f),
REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x3f02, ~0x0000000f, 0),
/* Enable PCIe Releaxed Order */
REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x2314, (1 << 31) | (1 << 7)),
REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x1114, (1 << 15) | (1 << 14)),
/* Setup SERIRQ, enable continuous mode */
REG_PCI_OR8(SERIRQ_CNTL, (1 << 7) | (1 << 6)),
#if !CONFIG_SERIRQ_CONTINUOUS_MODE
REG_PCI_RMW8(SERIRQ_CNTL, ~(1 << 6), 0),
#endif
REG_SCRIPT_END
};
/* Magic register settings for power management */
static const struct reg_script pch_pm_init_script[] = {
REG_PCI_WRITE8(0xa9, 0x46),
REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x232c, ~1, 0),
REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x1100, 0x0000c13f),
REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x2320, ~0x60, 0x10),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3314, 0x00012fff),
REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x3318, ~0x000f0330, 0x0dcf0400),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3324, 0x04000000),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3368, 0x00041400),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3388, 0x3f8ddbff),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x33ac, 0x00007001),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x33b0, 0x00181900),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x33c0, 0x00060A00),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x33d0, 0x06200840),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3a28, 0x01010101),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3a2c, 0x040c0404),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3a9c, 0x9000000a),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x2b1c, 0x03808033),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x2b34, 0x80000009),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3348, 0x022ddfff),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x334c, 0x00000001),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3358, 0x0001c000),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3380, 0x3f8ddbff),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3384, 0x0001c7e1),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x338c, 0x0001c7e1),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3398, 0x0001c000),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x33a8, 0x00181900),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x33dc, 0x00080000),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x33e0, 0x00000001),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3a20, 0x0000040c),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3a24, 0x01010101),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3a30, 0x01010101),
REG_PCI_RMW32(0xac, ~0x00200000, 0),
REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x0410, 0x00000003),
REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x2618, 0x08000000),
REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x2300, 0x00000002),
REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x2600, 0x00000008),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x33b4, 0x00007001),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3350, 0x022ddfff),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3354, 0x00000001),
/* Power Optimizer */
REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x33d4, 0x08000000),
REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x33c8, 0x08000080),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x2b10, 0x0000883c),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x2b14, 0x1e0a4616),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x2b24, 0x40000005),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x2b20, 0x0005db01),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3a80, 0x05145005),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3a84, 0x00001005),
REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x33d4, 0x2fff2fb1),
REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x33c8, 0x00008000),
REG_SCRIPT_END
};
static void pch_enable_mphy(void)
{
u32 gpio71_native = gpio_is_native(71);
u32 data_and = 0xffffffff;
u32 data_or = (1 << 14) | (1 << 13) | (1 << 12);
if (gpio71_native) {
data_or |= (1 << 0);
if (pch_is_wpt()) {
data_and &= ~((1 << 7) | (1 << 6) | (1 << 3));
data_or |= (1 << 5) | (1 << 4);
if (pch_is_wpt_ulx()) {
/* Check if SATA and USB3 MPHY are enabled */
u32 strap19 = pch_read_soft_strap(19);
strap19 &= ((1 << 31) | (1 << 30));
strap19 >>= 30;
if (strap19 == 3) {
data_or |= (1 << 3);
printk(BIOS_DEBUG, "Enable ULX MPHY PG "
"control in single domain\n");
} else if (strap19 == 0) {
printk(BIOS_DEBUG, "Enable ULX MPHY PG "
"control in split domains\n");
} else {
printk(BIOS_DEBUG, "Invalid PCH Soft "
"Strap 19 configuration\n");
}
} else {
data_or |= (1 << 3);
}
}
}
pch_iobp_update(0xCF000000, data_and, data_or);
}
static void pch_init_deep_sx(struct device *dev)
{
config_t *config = dev->chip_info;
if (config->deep_sx_enable_ac) {
RCBA32_OR(DEEP_S3_POL, DEEP_S3_EN_AC);
RCBA32_OR(DEEP_S5_POL, DEEP_S5_EN_AC);
}
if (config->deep_sx_enable_dc) {
RCBA32_OR(DEEP_S3_POL, DEEP_S3_EN_DC);
RCBA32_OR(DEEP_S5_POL, DEEP_S5_EN_DC);
}
if (config->deep_sx_enable_ac || config->deep_sx_enable_dc)
RCBA32_OR(DEEP_SX_CONFIG,
DEEP_SX_WAKE_PIN_EN | DEEP_SX_GP27_PIN_EN);
}
/* Power Management init */
static void pch_pm_init(struct device *dev)
{
printk(BIOS_DEBUG, "PCH PM init\n");
pch_init_deep_sx(dev);
pch_enable_mphy();
reg_script_run_on_dev(dev, pch_pm_init_script);
if (pch_is_wpt()) {
RCBA32_OR(0x33e0, (1 << 4) | (1 << 1));
RCBA32_OR(0x2b1c, (1 << 22) | (1 << 14) | (1 << 13));
RCBA32(0x33e4) = 0x16bf0002;
RCBA32_OR(0x33e4, 0x1);
}
pch_iobp_update(0xCA000000, ~0UL, 0x00000009);
/* Set RCBA 0x2b1c[29]=1 if DSP disabled */
if (RCBA32(FD) & PCH_DISABLE_ADSPD)
RCBA32_OR(0x2b1c, (1 << 29));
}
static void pch_cg_init(device_t dev)
{
u32 reg32;
u16 reg16;
/* DMI */
RCBA32_OR(0x2234, 0xf);
reg16 = pci_read_config16(dev, GEN_PMCON_1);
reg16 &= ~(1 << 10); /* Disable BIOS_PCI_EXP_EN for native PME */
if (pch_is_wpt())
reg16 &= ~(1 << 11);
else
reg16 |= (1 << 11);
reg16 |= (1 << 5) | (1 << 6) | (1 << 7) | (1 << 12);
reg16 |= (1 << 2); // PCI CLKRUN# Enable
pci_write_config16(dev, GEN_PMCON_1, reg16);
/*
* RCBA + 0x2614[27:25,14:13,10,8] = 101,11,1,1
* RCBA + 0x2614[23:16] = 0x20
* RCBA + 0x2614[30:28] = 0x0
* RCBA + 0x2614[26] = 1 (IF 0:2.0@0x08 >= 0x0b)
*/
RCBA32_AND_OR(0x2614, ~0x64ff0000, 0x0a206500);
/* Check for 0:2.0@0x08 >= 0x0b */
if (pch_is_wpt() || pci_read_config8(SA_DEV_IGD, 0x8) >= 0x0b)
RCBA32_OR(0x2614, (1 << 26));
RCBA32_OR(0x900, 0x0000031f);
reg32 = RCBA32(CG);
if (RCBA32(0x3454) & (1 << 4))
reg32 &= ~(1 << 29); // LPC Dynamic
else
reg32 |= (1 << 29); // LPC Dynamic
reg32 |= (1 << 31); // LP LPC
reg32 |= (1 << 30); // LP BLA
if (RCBA32(0x3454) & (1 << 4))
reg32 &= ~(1 << 29);
else
reg32 |= (1 << 29);
reg32 |= (1 << 28); // GPIO Dynamic
reg32 |= (1 << 27); // HPET Dynamic
reg32 |= (1 << 26); // Generic Platform Event Clock
if (RCBA32(BUC) & PCH_DISABLE_GBE)
reg32 |= (1 << 23); // GbE Static
if (RCBA32(FD) & PCH_DISABLE_HD_AUDIO)
reg32 |= (1 << 21); // HDA Static
reg32 |= (1 << 22); // HDA Dynamic
RCBA32(CG) = reg32;
/* PCH-LP LPC */
if (pch_is_wpt())
RCBA32_AND_OR(0x3434, ~0x1f, 0x17);
else
RCBA32_OR(0x3434, 0x7);
/* SPI */
RCBA32_OR(0x38c0, 0x3c07);
pch_iobp_update(0xCE00C000, ~1UL, 0x00000000);
}
static void pch_set_acpi_mode(void)
{
#if CONFIG_HAVE_SMI_HANDLER
if (!acpi_is_wakeup_s3()) {
printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
outb(APM_CNT_ACPI_DISABLE, APM_CNT);
printk(BIOS_DEBUG, "done.\n");
}
#endif /* CONFIG_HAVE_SMI_HANDLER */
}
static void lpc_init(struct device *dev)
{
/* Legacy initialization */
isa_dma_init();
pch_rtc_init(dev);
reg_script_run_on_dev(dev, pch_misc_init_script);
/* Interrupt configuration */
pch_enable_ioapic(dev);
pch_pirq_init(dev);
setup_i8259();
i8259_configure_irq_trigger(9, 1);
/* Initialize power management */
pch_power_options(dev);
pch_pm_init(dev);
pch_cg_init(dev);
pch_set_acpi_mode();
}
static void pch_lpc_add_mmio_resources(device_t dev)
{
u32 reg;
struct resource *res;
const u32 default_decode_base = IO_APIC_ADDR;
/*
* Just report all resources from IO-APIC base to 4GiB. Don't mark
* them reserved as that may upset the OS if this range is marked
* as reserved in the e820.
*/
res = new_resource(dev, OIC);
res->base = default_decode_base;
res->size = 0 - default_decode_base;
res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
/* RCBA */
if (RCBA_BASE_ADDRESS < default_decode_base) {
res = new_resource(dev, RCBA);
res->base = RCBA_BASE_ADDRESS;
res->size = 16 * 1024;
res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED |
IORESOURCE_FIXED | IORESOURCE_RESERVE;
}
/* Check LPC Memory Decode register. */
reg = pci_read_config32(dev, LGMR);
if (reg & 1) {
reg &= ~0xffff;
if (reg < default_decode_base) {
res = new_resource(dev, LGMR);
res->base = reg;
res->size = 16 * 1024;
res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED |
IORESOURCE_FIXED | IORESOURCE_RESERVE;
}
}
}
/* Default IO range claimed by the LPC device. The upper bound is exclusive. */
#define LPC_DEFAULT_IO_RANGE_LOWER 0
#define LPC_DEFAULT_IO_RANGE_UPPER 0x1000
static inline int pch_io_range_in_default(u16 base, u16 size)
{
/* Does it start above the range? */
if (base >= LPC_DEFAULT_IO_RANGE_UPPER)
return 0;
/* Is it entirely contained? */
if (base >= LPC_DEFAULT_IO_RANGE_LOWER &&
(base + size) < LPC_DEFAULT_IO_RANGE_UPPER)
return 1;
/* This will return not in range for partial overlaps. */
return 0;
}
/*
* Note: this function assumes there is no overlap with the default LPC device's
* claimed range: LPC_DEFAULT_IO_RANGE_LOWER -> LPC_DEFAULT_IO_RANGE_UPPER.
*/
static void pch_lpc_add_io_resource(device_t dev, u16 base, u16 size, int index)
{
struct resource *res;
if (pch_io_range_in_default(base, size))
return;
res = new_resource(dev, index);
res->base = base;
res->size = size;
res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
}
static void pch_lpc_add_gen_io_resources(device_t dev, int reg_value, int index)
{
/*
* Check if the register is enabled. If so and the base exceeds the
* device's default claim range add the resource.
*/
if (reg_value & 1) {
u16 base = reg_value & 0xfffc;
u16 size = (0x3 | ((reg_value >> 16) & 0xfc)) + 1;
pch_lpc_add_io_resource(dev, base, size, index);
}
}
static void pch_lpc_add_io_resources(device_t dev)
{
struct resource *res;
config_t *config = dev->chip_info;
/* Add the default claimed IO range for the LPC device. */
res = new_resource(dev, 0);
res->base = LPC_DEFAULT_IO_RANGE_LOWER;
res->size = LPC_DEFAULT_IO_RANGE_UPPER - LPC_DEFAULT_IO_RANGE_LOWER;
res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
/* GPIOBASE */
pch_lpc_add_io_resource(dev, GPIO_BASE_ADDRESS,
GPIO_BASE_SIZE, GPIO_BASE);
/* PMBASE */
pch_lpc_add_io_resource(dev, ACPI_BASE_ADDRESS, ACPI_BASE_SIZE, PMBASE);
/* LPC Generic IO Decode range. */
pch_lpc_add_gen_io_resources(dev, config->gen1_dec, LPC_GEN1_DEC);
pch_lpc_add_gen_io_resources(dev, config->gen2_dec, LPC_GEN2_DEC);
pch_lpc_add_gen_io_resources(dev, config->gen3_dec, LPC_GEN3_DEC);
pch_lpc_add_gen_io_resources(dev, config->gen4_dec, LPC_GEN4_DEC);
}
static void pch_lpc_read_resources(device_t dev)
{
global_nvs_t *gnvs;
/* Get the normal PCI resources of this device. */
pci_dev_read_resources(dev);
/* Add non-standard MMIO resources. */
pch_lpc_add_mmio_resources(dev);
/* Add IO resources. */
pch_lpc_add_io_resources(dev);
/* Allocate ACPI NVS in CBMEM */
gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(global_nvs_t));
if (!acpi_is_wakeup_s3() && gnvs)
memset(gnvs, 0, sizeof(global_nvs_t));
}
static void southcluster_inject_dsdt(void)
{
global_nvs_t *gnvs;
gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
if (!gnvs) {
gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof (*gnvs));
if (gnvs)
memset(gnvs, 0, sizeof(*gnvs));
}
if (gnvs) {
memset(gnvs, 0, sizeof(*gnvs));
acpi_create_gnvs(gnvs);
acpi_save_gnvs((unsigned long)gnvs);
/* And tell SMI about it */
smm_setup_structures(gnvs, NULL, NULL);
/* Add it to DSDT. */
acpigen_write_scope("\\");
acpigen_write_name_dword("NVSA", (u32) gnvs);
acpigen_pop_len();
}
}
static struct device_operations device_ops = {
.read_resources = &pch_lpc_read_resources,
.set_resources = &pci_dev_set_resources,
.enable_resources = &pci_dev_enable_resources,
.acpi_inject_dsdt_generator = southcluster_inject_dsdt,
.write_acpi_tables = acpi_write_hpet,
.init = &lpc_init,
.scan_bus = &scan_static_bus,
.ops_pci = &broadwell_pci_ops,
};
static const unsigned short pci_device_ids[] = {
PCH_LPT_LP_SAMPLE,
PCH_LPT_LP_PREMIUM,
PCH_LPT_LP_MAINSTREAM,
PCH_LPT_LP_VALUE,
PCH_WPT_HSW_U_SAMPLE,
PCH_WPT_BDW_U_SAMPLE,
PCH_WPT_BDW_U_PREMIUM,
PCH_WPT_BDW_U_BASE,
PCH_WPT_BDW_Y_SAMPLE,
PCH_WPT_BDW_Y_PREMIUM,
PCH_WPT_BDW_Y_BASE,
PCH_WPT_BDW_H,
0
};
static const struct pci_driver pch_lpc __pci_driver = {
.ops = &device_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.devices = pci_device_ids,
};

1085
src/soc/intel/skylake/me.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,321 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/io.h>
#include <console/console.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <stdlib.h>
#include <string.h>
#include <soc/pci_devs.h>
#include <soc/me.h>
#include <delay.h>
static inline void me_read_dword_ptr(void *ptr, int offset)
{
u32 dword = pci_read_config32(PCH_DEV_ME, offset);
memcpy(ptr, &dword, sizeof(dword));
}
#if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG)
/* HFS1[3:0] Current Working State Values */
static const char *me_cws_values[] = {
[ME_HFS_CWS_RESET] = "Reset",
[ME_HFS_CWS_INIT] = "Initializing",
[ME_HFS_CWS_REC] = "Recovery",
[3] = "Unknown (3)",
[4] = "Unknown (4)",
[ME_HFS_CWS_NORMAL] = "Normal",
[ME_HFS_CWS_WAIT] = "Platform Disable Wait",
[ME_HFS_CWS_TRANS] = "OP State Transition",
[ME_HFS_CWS_INVALID] = "Invalid CPU Plugged In",
[9] = "Unknown (9)",
[10] = "Unknown (10)",
[11] = "Unknown (11)",
[12] = "Unknown (12)",
[13] = "Unknown (13)",
[14] = "Unknown (14)",
[15] = "Unknown (15)",
};
/* HFS1[8:6] Current Operation State Values */
static const char *me_opstate_values[] = {
[ME_HFS_STATE_PREBOOT] = "Preboot",
[ME_HFS_STATE_M0_UMA] = "M0 with UMA",
[ME_HFS_STATE_M3] = "M3 without UMA",
[ME_HFS_STATE_M0] = "M0 without UMA",
[ME_HFS_STATE_BRINGUP] = "Bring up",
[ME_HFS_STATE_ERROR] = "M0 without UMA but with error"
};
/* HFS[19:16] Current Operation Mode Values */
static const char *me_opmode_values[] = {
[ME_HFS_MODE_NORMAL] = "Normal",
[ME_HFS_MODE_DEBUG] = "Debug",
[ME_HFS_MODE_DIS] = "Soft Temporary Disable",
[ME_HFS_MODE_OVER_JMPR] = "Security Override via Jumper",
[ME_HFS_MODE_OVER_MEI] = "Security Override via MEI Message"
};
/* HFS[15:12] Error Code Values */
static const char *me_error_values[] = {
[ME_HFS_ERROR_NONE] = "No Error",
[ME_HFS_ERROR_UNCAT] = "Uncategorized Failure",
[ME_HFS_ERROR_IMAGE] = "Image Failure",
[ME_HFS_ERROR_DEBUG] = "Debug Failure"
};
/* HFS2[31:28] ME Progress Code */
static const char *me_progress_values[] = {
[ME_HFS2_PHASE_ROM] = "ROM Phase",
[ME_HFS2_PHASE_BUP] = "BUP Phase",
[ME_HFS2_PHASE_UKERNEL] = "uKernel Phase",
[ME_HFS2_PHASE_POLICY] = "Policy Module",
[ME_HFS2_PHASE_MODULE_LOAD] = "Module Loading",
[ME_HFS2_PHASE_UNKNOWN] = "Unknown",
[ME_HFS2_PHASE_HOST_COMM] = "Host Communication"
};
/* HFS2[27:24] Power Management Event */
static const char *me_pmevent_values[] = {
[ME_HFS2_PMEVENT_CLEAN_MOFF_MX_WAKE] =
"Clean Moff->Mx wake",
[ME_HFS2_PMEVENT_MOFF_MX_WAKE_ERROR] =
"Moff->Mx wake after an error",
[ME_HFS2_PMEVENT_CLEAN_GLOBAL_RESET] =
"Clean global reset",
[ME_HFS2_PMEVENT_CLEAN_GLOBAL_RESET_ERROR] =
"Global reset after an error",
[ME_HFS2_PMEVENT_CLEAN_ME_RESET] =
"Clean Intel ME reset",
[ME_HFS2_PMEVENT_ME_RESET_EXCEPTION] =
"Intel ME reset due to exception",
[ME_HFS2_PMEVENT_PSEUDO_ME_RESET] =
"Pseudo-global reset",
[ME_HFS2_PMEVENT_S0MO_SXM3] =
"S0/M0->Sx/M3",
[ME_HFS2_PMEVENT_SXM3_S0M0] =
"Sx/M3->S0/M0",
[ME_HFS2_PMEVENT_NON_PWR_CYCLE_RESET] =
"Non-power cycle reset",
[ME_HFS2_PMEVENT_PWR_CYCLE_RESET_M3] =
"Power cycle reset through M3",
[ME_HFS2_PMEVENT_PWR_CYCLE_RESET_MOFF] =
"Power cycle reset through Moff",
[ME_HFS2_PMEVENT_SXMX_SXMOFF] =
"Sx/Mx->Sx/Moff"
};
/* Progress Code 0 states */
static const char *me_progress_rom_values[] = {
[ME_HFS2_STATE_ROM_BEGIN] = "BEGIN",
[ME_HFS2_STATE_ROM_DISABLE] = "DISABLE"
};
/* Progress Code 1 states */
static const char *me_progress_bup_values[] = {
[ME_HFS2_STATE_BUP_INIT] =
"Initialization starts",
[ME_HFS2_STATE_BUP_DIS_HOST_WAKE] =
"Disable the host wake event",
[ME_HFS2_STATE_BUP_FLOW_DET] =
"Flow determination start process",
[ME_HFS2_STATE_BUP_VSCC_ERR] =
"Error reading/matching the VSCC table in the descriptor",
[ME_HFS2_STATE_BUP_CHECK_STRAP] =
"Check to see if straps say ME DISABLED",
[ME_HFS2_STATE_BUP_PWR_OK_TIMEOUT] =
"Timeout waiting for PWROK",
[ME_HFS2_STATE_BUP_MANUF_OVRD_STRAP] =
"Possibly handle BUP manufacturing override strap",
[ME_HFS2_STATE_BUP_M3] =
"Bringup in M3",
[ME_HFS2_STATE_BUP_M0] =
"Bringup in M0",
[ME_HFS2_STATE_BUP_FLOW_DET_ERR] =
"Flow detection error",
[ME_HFS2_STATE_BUP_M3_CLK_ERR] =
"M3 clock switching error",
[ME_HFS2_STATE_BUP_CPU_RESET_DID_TIMEOUT_MEM_MISSING] =
"Host error - CPU reset timeout, DID timeout, memory missing",
[ME_HFS2_STATE_BUP_M3_KERN_LOAD] =
"M3 kernel load",
[ME_HFS2_STATE_BUP_T32_MISSING] =
"T34 missing - cannot program ICC",
[ME_HFS2_STATE_BUP_WAIT_DID] =
"Waiting for DID BIOS message",
[ME_HFS2_STATE_BUP_WAIT_DID_FAIL] =
"Waiting for DID BIOS message failure",
[ME_HFS2_STATE_BUP_DID_NO_FAIL] =
"DID reported no error",
[ME_HFS2_STATE_BUP_ENABLE_UMA] =
"Enabling UMA",
[ME_HFS2_STATE_BUP_ENABLE_UMA_ERR] =
"Enabling UMA error",
[ME_HFS2_STATE_BUP_SEND_DID_ACK] =
"Sending DID Ack to BIOS",
[ME_HFS2_STATE_BUP_SEND_DID_ACK_ERR] =
"Sending DID Ack to BIOS error",
[ME_HFS2_STATE_BUP_M0_CLK] =
"Switching clocks in M0",
[ME_HFS2_STATE_BUP_M0_CLK_ERR] =
"Switching clocks in M0 error",
[ME_HFS2_STATE_BUP_TEMP_DIS] =
"ME in temp disable",
[ME_HFS2_STATE_BUP_M0_KERN_LOAD] =
"M0 kernel load",
};
/* Progress Code 3 states */
static const char *me_progress_policy_values[] = {
[ME_HFS2_STATE_POLICY_ENTRY] = "Entry into Policy Module",
[ME_HFS2_STATE_POLICY_RCVD_S3] = "Received S3 entry",
[ME_HFS2_STATE_POLICY_RCVD_S4] = "Received S4 entry",
[ME_HFS2_STATE_POLICY_RCVD_S5] = "Received S5 entry",
[ME_HFS2_STATE_POLICY_RCVD_UPD] = "Received UPD entry",
[ME_HFS2_STATE_POLICY_RCVD_PCR] = "Received PCR entry",
[ME_HFS2_STATE_POLICY_RCVD_NPCR] = "Received NPCR entry",
[ME_HFS2_STATE_POLICY_RCVD_HOST_WAKE] = "Received host wake",
[ME_HFS2_STATE_POLICY_RCVD_AC_DC] = "Received AC<>DC switch",
[ME_HFS2_STATE_POLICY_RCVD_DID] = "Received DRAM Init Done",
[ME_HFS2_STATE_POLICY_VSCC_NOT_FOUND] =
"VSCC Data not found for flash device",
[ME_HFS2_STATE_POLICY_VSCC_INVALID] =
"VSCC Table is not valid",
[ME_HFS2_STATE_POLICY_FPB_ERR] =
"Flash Partition Boundary is outside address space",
[ME_HFS2_STATE_POLICY_DESCRIPTOR_ERR] =
"ME cannot access the chipset descriptor region",
[ME_HFS2_STATE_POLICY_VSCC_NO_MATCH] =
"Required VSCC values for flash parts do not match",
};
void intel_me_status(void)
{
struct me_hfs _hfs, *hfs = &_hfs;
struct me_hfs2 _hfs2, *hfs2 = &_hfs2;
me_read_dword_ptr(hfs, PCI_ME_HFS);
me_read_dword_ptr(hfs2, PCI_ME_HFS2);
/* Check Current States */
printk(BIOS_DEBUG, "ME: FW Partition Table : %s\n",
hfs->fpt_bad ? "BAD" : "OK");
printk(BIOS_DEBUG, "ME: Bringup Loader Failure : %s\n",
hfs->ft_bup_ld_flr ? "YES" : "NO");
printk(BIOS_DEBUG, "ME: Firmware Init Complete : %s\n",
hfs->fw_init_complete ? "YES" : "NO");
printk(BIOS_DEBUG, "ME: Manufacturing Mode : %s\n",
hfs->mfg_mode ? "YES" : "NO");
printk(BIOS_DEBUG, "ME: Boot Options Present : %s\n",
hfs->boot_options_present ? "YES" : "NO");
printk(BIOS_DEBUG, "ME: Update In Progress : %s\n",
hfs->update_in_progress ? "YES" : "NO");
printk(BIOS_DEBUG, "ME: Current Working State : %s\n",
me_cws_values[hfs->working_state]);
printk(BIOS_DEBUG, "ME: Current Operation State : %s\n",
me_opstate_values[hfs->operation_state]);
printk(BIOS_DEBUG, "ME: Current Operation Mode : %s\n",
me_opmode_values[hfs->operation_mode]);
printk(BIOS_DEBUG, "ME: Error Code : %s\n",
me_error_values[hfs->error_code]);
printk(BIOS_DEBUG, "ME: Progress Phase : %s\n",
me_progress_values[hfs2->progress_code]);
printk(BIOS_DEBUG, "ME: Power Management Event : %s\n",
me_pmevent_values[hfs2->current_pmevent]);
printk(BIOS_DEBUG, "ME: Progress Phase State : ");
switch (hfs2->progress_code) {
case ME_HFS2_PHASE_ROM: /* ROM Phase */
printk(BIOS_DEBUG, "%s",
me_progress_rom_values[hfs2->current_state]);
break;
case ME_HFS2_PHASE_UKERNEL: /* uKernel Phase */
printk(BIOS_DEBUG, "0x%02x", hfs2->current_state);
break;
case ME_HFS2_PHASE_BUP: /* Bringup Phase */
if (hfs2->current_state < ARRAY_SIZE(me_progress_bup_values)
&& me_progress_bup_values[hfs2->current_state])
printk(BIOS_DEBUG, "%s",
me_progress_bup_values[hfs2->current_state]);
else
printk(BIOS_DEBUG, "0x%02x", hfs2->current_state);
break;
case ME_HFS2_PHASE_POLICY: /* Policy Module Phase */
if (hfs2->current_state < ARRAY_SIZE(me_progress_policy_values)
&& me_progress_policy_values[hfs2->current_state])
printk(BIOS_DEBUG, "%s",
me_progress_policy_values[hfs2->current_state]);
else
printk(BIOS_DEBUG, "0x%02x", hfs2->current_state);
break;
case ME_HFS2_PHASE_HOST_COMM: /* Host Communication Phase */
if (!hfs2->current_state)
printk(BIOS_DEBUG, "Host communication established");
else
printk(BIOS_DEBUG, "0x%02x", hfs2->current_state);
break;
default:
printk(BIOS_DEBUG, "Unknown phase: 0x%02x state: 0x%02x",
hfs2->progress_code, hfs2->current_state);
}
printk(BIOS_DEBUG, "\n");
}
#endif
void intel_me_hsio_version(uint16_t *version, uint16_t *checksum)
{
int count;
u32 hsiover;
struct me_hfs hfs;
/* Query for HSIO version, overloads H_GS and HFS */
pci_write_config32(PCH_DEV_ME, PCI_ME_H_GS,
ME_HSIO_MESSAGE | ME_HSIO_CMD_GETHSIOVER);
/* Must wait for ME acknowledgement */
for (count = ME_RETRY; count > 0; --count) {
me_read_dword_ptr(&hfs, PCI_ME_HFS);
if (hfs.bios_msg_ack)
break;
udelay(ME_DELAY);
}
if (!count) {
printk(BIOS_ERR, "ERROR: ME failed to respond\n");
return;
}
/* HSIO version should be in HFS_5 */
hsiover = pci_read_config32(PCH_DEV_ME, PCI_ME_HFS5);
*version = hsiover >> 16;
*checksum = hsiover & 0xffff;
printk(BIOS_DEBUG, "ME: HSIO Version : %d (CRC 0x%04x)\n",
*version, *checksum);
/* Reset registers to normal behavior */
pci_write_config32(PCH_DEV_ME, PCI_ME_H_GS,
ME_HSIO_MESSAGE | ME_HSIO_CMD_GETHSIOVER);
}

View File

@@ -0,0 +1,46 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/io.h>
#include <cbmem.h>
#include <device/pci.h>
#include <soc/pci_devs.h>
#include <soc/systemagent.h>
static uintptr_t dpr_region_start(void)
{
/*
* Base of DPR is top of usable DRAM below 4GiB. The register has
* 1 MiB alignment and reports the TOP of the range, the base
* must be calculated from the size in MiB in bits 11:4.
*/
uintptr_t dpr = pci_read_config32(SA_DEV_ROOT, DPR);
uintptr_t tom = dpr & ~((1 << 20) - 1);
/* Subtract DMA Protected Range size if enabled */
if (dpr & DPR_EPM)
tom -= (dpr & DPR_SIZE_MASK) << 16;
return tom;
}
void *cbmem_top(void)
{
return (void *) dpr_region_start();
}

View File

@@ -0,0 +1 @@
cpu_microcode-y += microcode_blob.c

View File

@@ -0,0 +1,23 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
unsigned microcode[] = {
#include "../../../../../3rdparty/blobs/soc/intel/broadwell/microcode_blob.h"
};

View File

@@ -0,0 +1,128 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008 Advanced Micro Devices, Inc.
* Copyright (C) 2008-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <arch/io.h>
#include <delay.h>
#include <stdlib.h>
#include <soc/intel/common/hda_verb.h>
#include <soc/ramstage.h>
static const u32 minihd_verb_table[] = {
/* coreboot specific header */
0x80862807, // Codec Vendor / Device ID: Intel Mini-HD
0x00000000, // Subsystem ID
0x00000004, // Number of jacks
/* Enable 3rd Pin and Converter Widget */
0x00878101,
/* Pin Widget 5 - PORT B */
0x00571C10,
0x00571D00,
0x00571E56,
0x00571F18,
/* Pin Widget 6 - PORT C */
0x00671C20,
0x00671D00,
0x00671E56,
0x00671F18,
/* Pin Widget 7 - PORT D */
0x00771C30,
0x00771D00,
0x00771E56,
0x00771F18,
/* Disable 3rd Pin and Converter Widget */
0x00878100,
/* Dummy entries to fill out the table */
0x00878100,
0x00878100,
};
static void minihd_init(struct device *dev)
{
struct resource *res;
u8 *base, reg32;
int codec_mask, i;
/* Find base address */
res = find_resource(dev, PCI_BASE_ADDRESS_0);
if (!res)
return;
base = res2mmio(res, 0, 0);
printk(BIOS_DEBUG, "Mini-HD: base = %p\n", base);
/* Set Bus Master */
reg32 = pci_read_config32(dev, PCI_COMMAND);
pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER);
/* Mini-HD configuration */
reg32 = read32(base + 0x100c);
reg32 &= 0xfffc0000;
reg32 |= 0x4;
write32(base + 0x100c, reg32);
reg32 = read32(base + 0x1010);
reg32 &= 0xfffc0000;
reg32 |= 0x4b;
write32(base + 0x1010, reg32);
/* Init the codec and write the verb table */
codec_mask = hda_codec_detect(base);
if (codec_mask) {
for (i = 3; i >= 0; i--) {
if (codec_mask & (1 << i))
hda_codec_init(base, i,
sizeof(minihd_verb_table),
minihd_verb_table);
}
}
}
static struct device_operations minihd_ops = {
.read_resources = &pci_dev_read_resources,
.set_resources = &pci_dev_set_resources,
.enable_resources = &pci_dev_enable_resources,
.init = &minihd_init,
.ops_pci = &broadwell_pci_ops,
};
static const unsigned short pci_device_ids[] = {
0x0a0c, /* Haswell */
0x160c, /* Broadwell */
0
};
static const struct pci_driver minihd_driver __pci_driver = {
.ops = &minihd_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.devices = pci_device_ids,
};

View File

@@ -0,0 +1,63 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <stdint.h>
#include <cpu/x86/msr.h>
#include <timer.h>
#include <soc/msr.h>
static struct monotonic_counter {
int initialized;
struct mono_time time;
uint32_t last_value;
} mono_counter;
static inline uint32_t read_counter_msr(void)
{
/* Even though the MSR is 64-bit it is assumed that the hardware
* is polled frequently enough to only use the lower 32-bits. */
msr_t counter_msr;
counter_msr = rdmsr(MSR_COUNTER_24_MHZ);
return counter_msr.lo;
}
void timer_monotonic_get(struct mono_time *mt)
{
uint32_t current_tick;
uint32_t usecs_elapsed;
if (!mono_counter.initialized) {
mono_counter.last_value = read_counter_msr();
mono_counter.initialized = 1;
}
current_tick = read_counter_msr();
usecs_elapsed = (current_tick - mono_counter.last_value) / 24;
/* Update current time and tick values only if a full tick occurred. */
if (usecs_elapsed) {
mono_time_add_usecs(&mono_counter.time, usecs_elapsed);
mono_counter.last_value = current_tick;
}
/* Save result. */
*mt = mono_counter.time;
}

221
src/soc/intel/skylake/pch.c Normal file
View File

@@ -0,0 +1,221 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <console/console.h>
#include <delay.h>
#include <arch/io.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_def.h>
#include <soc/iobp.h>
#include <soc/pch.h>
#include <soc/pci_devs.h>
#include <soc/ramstage.h>
#include <soc/rcba.h>
#include <soc/serialio.h>
#include <soc/spi.h>
u8 pch_revision(void)
{
return pci_read_config8(PCH_DEV_LPC, PCI_REVISION_ID);
}
u16 pch_type(void)
{
return pci_read_config16(PCH_DEV_LPC, PCI_DEVICE_ID);
}
/* Return 1 if PCH type is WildcatPoint */
int pch_is_wpt(void)
{
return ((pch_type() & 0xfff0) == 0x9cc0) ? 1 : 0;
}
/* Return 1 if PCH type is WildcatPoint ULX */
int pch_is_wpt_ulx(void)
{
u16 lpcid = pch_type();
switch (lpcid) {
case PCH_WPT_BDW_Y_SAMPLE:
case PCH_WPT_BDW_Y_PREMIUM:
case PCH_WPT_BDW_Y_BASE:
return 1;
}
return 0;
}
u32 pch_read_soft_strap(int id)
{
u32 fdoc;
fdoc = SPIBAR32(SPIBAR_FDOC);
fdoc &= ~0x00007ffc;
SPIBAR32(SPIBAR_FDOC) = fdoc;
fdoc |= 0x00004000;
fdoc |= id * 4;
SPIBAR32(SPIBAR_FDOC) = fdoc;
return SPIBAR32(SPIBAR_FDOD);
}
#ifndef __PRE_RAM__
/* Put device in D3Hot Power State */
static void pch_enable_d3hot(device_t dev)
{
u32 reg32 = pci_read_config32(dev, PCH_PCS);
reg32 |= PCH_PCS_PS_D3HOT;
pci_write_config32(dev, PCH_PCS, reg32);
}
/* RCBA function disable and posting read to flush the transaction */
static void rcba_function_disable(u32 reg, u32 bit)
{
RCBA32_OR(reg, bit);
RCBA32(reg);
}
/* Set bit in Function Disable register to hide this device */
void pch_disable_devfn(device_t dev)
{
switch (dev->path.pci.devfn) {
case PCH_DEVFN_ADSP: /* Audio DSP */
rcba_function_disable(FD, PCH_DISABLE_ADSPD);
break;
case PCH_DEVFN_XHCI: /* XHCI */
rcba_function_disable(FD, PCH_DISABLE_XHCI);
break;
case PCH_DEVFN_SDMA: /* DMA */
pch_enable_d3hot(dev);
pch_iobp_update(SIO_IOBP_FUNCDIS0, ~0UL, SIO_IOBP_FUNCDIS_DIS);
break;
case PCH_DEVFN_I2C0: /* I2C0 */
pch_enable_d3hot(dev);
pch_iobp_update(SIO_IOBP_FUNCDIS1, ~0UL, SIO_IOBP_FUNCDIS_DIS);
break;
case PCH_DEVFN_I2C1: /* I2C1 */
pch_enable_d3hot(dev);
pch_iobp_update(SIO_IOBP_FUNCDIS2, ~0UL, SIO_IOBP_FUNCDIS_DIS);
break;
case PCH_DEVFN_SPI0: /* SPI0 */
pch_enable_d3hot(dev);
pch_iobp_update(SIO_IOBP_FUNCDIS3, ~0UL, SIO_IOBP_FUNCDIS_DIS);
break;
case PCH_DEVFN_SPI1: /* SPI1 */
pch_enable_d3hot(dev);
pch_iobp_update(SIO_IOBP_FUNCDIS4, ~0UL, SIO_IOBP_FUNCDIS_DIS);
break;
case PCH_DEVFN_UART0: /* UART0 */
pch_enable_d3hot(dev);
pch_iobp_update(SIO_IOBP_FUNCDIS5, ~0UL, SIO_IOBP_FUNCDIS_DIS);
break;
case PCH_DEVFN_UART1: /* UART1 */
pch_enable_d3hot(dev);
pch_iobp_update(SIO_IOBP_FUNCDIS6, ~0UL, SIO_IOBP_FUNCDIS_DIS);
break;
case PCH_DEVFN_ME: /* MEI #1 */
rcba_function_disable(FD2, PCH_DISABLE_MEI1);
break;
case PCH_DEVFN_ME_2: /* MEI #2 */
rcba_function_disable(FD2, PCH_DISABLE_MEI2);
break;
case PCH_DEVFN_ME_IDER: /* IDE-R */
rcba_function_disable(FD2, PCH_DISABLE_IDER);
break;
case PCH_DEVFN_ME_KT: /* KT */
rcba_function_disable(FD2, PCH_DISABLE_KT);
break;
case PCH_DEVFN_SDIO: /* SDIO */
pch_enable_d3hot(dev);
pch_iobp_update(SIO_IOBP_FUNCDIS7, ~0UL, SIO_IOBP_FUNCDIS_DIS);
break;
case PCH_DEVFN_GBE: /* Gigabit Ethernet */
rcba_function_disable(BUC, PCH_DISABLE_GBE);
break;
case PCH_DEVFN_HDA: /* HD Audio Controller */
rcba_function_disable(FD, PCH_DISABLE_HD_AUDIO);
break;
case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 0): /* PCI Express Root Port 1 */
case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 1): /* PCI Express Root Port 2 */
case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 2): /* PCI Express Root Port 3 */
case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 3): /* PCI Express Root Port 4 */
case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 4): /* PCI Express Root Port 5 */
case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 5): /* PCI Express Root Port 6 */
case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 6): /* PCI Express Root Port 7 */
case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 7): /* PCI Express Root Port 8 */
rcba_function_disable(FD,
PCH_DISABLE_PCIE(PCI_FUNC(dev->path.pci.devfn)));
break;
case PCH_DEVFN_EHCI: /* EHCI #1 */
rcba_function_disable(FD, PCH_DISABLE_EHCI1);
break;
case PCH_DEVFN_LPC: /* LPC */
rcba_function_disable(FD, PCH_DISABLE_LPC);
break;
case PCH_DEVFN_SATA: /* SATA #1 */
rcba_function_disable(FD, PCH_DISABLE_SATA1);
break;
case PCH_DEVFN_SMBUS: /* SMBUS */
rcba_function_disable(FD, PCH_DISABLE_SMBUS);
break;
case PCH_DEVFN_SATA2: /* SATA #2 */
rcba_function_disable(FD, PCH_DISABLE_SATA2);
break;
case PCH_DEVFN_THERMAL: /* Thermal Subsystem */
rcba_function_disable(FD, PCH_DISABLE_THERMAL);
break;
}
}
void broadwell_pch_enable_dev(device_t dev)
{
u32 reg32;
/* These devices need special enable/disable handling */
switch (PCI_SLOT(dev->path.pci.devfn)) {
case PCH_DEV_SLOT_PCIE:
case PCH_DEV_SLOT_EHCI:
case PCH_DEV_SLOT_HDA:
return;
}
if (!dev->enabled) {
printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev));
/* Ensure memory, io, and bus master are all disabled */
reg32 = pci_read_config32(dev, PCI_COMMAND);
reg32 &= ~(PCI_COMMAND_MASTER |
PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
pci_write_config32(dev, PCI_COMMAND, reg32);
/* Disable this device if possible */
pch_disable_devfn(dev);
} else {
/* Enable SERR */
reg32 = pci_read_config32(dev, PCI_COMMAND);
reg32 |= PCI_COMMAND_SERR;
pci_write_config32(dev, PCI_COMMAND, reg32);
}
}
#endif

View File

@@ -0,0 +1,710 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pciexp.h>
#include <device/pci_def.h>
#include <device/pci_ids.h>
#include <soc/gpio.h>
#include <soc/lpc.h>
#include <soc/iobp.h>
#include <soc/pch.h>
#include <soc/pci_devs.h>
#include <soc/rcba.h>
#include <soc/intel/broadwell/chip.h>
#include <soc/cpu.h>
#include <delay.h>
static void pcie_update_cfg8(device_t dev, int reg, u8 mask, u8 or);
static void pcie_update_cfg(device_t dev, int reg, u32 mask, u32 or);
/* Low Power variant has 6 root ports. */
#define NUM_ROOT_PORTS 6
struct root_port_config {
/* RPFN is a write-once register so keep a copy until it is written */
u32 orig_rpfn;
u32 new_rpfn;
u32 pin_ownership;
u32 strpfusecfg1;
u32 strpfusecfg2;
u32 strpfusecfg3;
u32 b0d28f0_32c;
u32 b0d28f4_32c;
u32 b0d28f5_32c;
int coalesce;
int gbe_port;
int num_ports;
device_t ports[NUM_ROOT_PORTS];
};
static struct root_port_config rpc;
static inline int root_port_is_first(device_t dev)
{
return PCI_FUNC(dev->path.pci.devfn) == 0;
}
static inline int root_port_is_last(device_t dev)
{
return PCI_FUNC(dev->path.pci.devfn) == (rpc.num_ports - 1);
}
/* Root ports are numbered 1..N in the documentation. */
static inline int root_port_number(device_t dev)
{
return PCI_FUNC(dev->path.pci.devfn) + 1;
}
static void root_port_config_update_gbe_port(void)
{
/* Is the Gbe Port enabled? */
if (!((rpc.strpfusecfg1 >> 19) & 1))
return;
switch ((rpc.strpfusecfg1 >> 16) & 0x7) {
case 0:
rpc.gbe_port = 3;
break;
case 1:
rpc.gbe_port = 4;
break;
case 2:
case 3:
case 4:
case 5:
/* Lanes 0-4 of Root Port 5. */
rpc.gbe_port = 5;
break;
default:
printk(BIOS_DEBUG, "Invalid GbE Port Selection.\n");
}
}
static void pcie_iosf_port_grant_count(device_t dev)
{
u8 update_val;
u32 rpcd = (pci_read_config32(dev, 0xfc) > 14) & 0x3;
switch (rpcd) {
case 1:
case 3:
update_val = 0x02;
break;
case 2:
update_val = 0x22;
break;
default:
update_val = 0x00;
break;
}
RCBA32(0x103C) = (RCBA32(0x103C) & (~0xff)) | update_val;
}
static void root_port_init_config(device_t dev)
{
int rp;
u32 data;
u8 resp, id;
if (root_port_is_first(dev)) {
rpc.orig_rpfn = RCBA32(RPFN);
rpc.new_rpfn = rpc.orig_rpfn;
rpc.num_ports = NUM_ROOT_PORTS;
rpc.gbe_port = -1;
/* RP0 f5[3:0] = 0101b*/
pcie_update_cfg8(dev, 0xf5, ~0xa, 0x5);
pcie_iosf_port_grant_count(dev);
rpc.pin_ownership = pci_read_config32(dev, 0x410);
root_port_config_update_gbe_port();
pcie_update_cfg8(dev, 0xe2, ~(3 << 4), (3 << 4));
if (dev->chip_info != NULL) {
config_t *config = dev->chip_info;
rpc.coalesce = config->pcie_port_coalesce;
}
}
rp = root_port_number(dev);
if (rp > rpc.num_ports) {
printk(BIOS_ERR, "Found Root Port %d, expecting %d\n",
rp, rpc.num_ports);
return;
}
/* Read the fuse configuration and pin ownership. */
switch (rp) {
case 1:
rpc.strpfusecfg1 = pci_read_config32(dev, 0xfc);
rpc.b0d28f0_32c = pci_read_config32(dev, 0x32c);
break;
case 5:
rpc.strpfusecfg2 = pci_read_config32(dev, 0xfc);
rpc.b0d28f4_32c = pci_read_config32(dev, 0x32c);
break;
case 6:
rpc.b0d28f5_32c = pci_read_config32(dev, 0x32c);
rpc.strpfusecfg3 = pci_read_config32(dev, 0xfc);
break;
default:
break;
}
pcie_update_cfg(dev, 0x418, 0, 0x02000430);
if (root_port_is_first(dev)) {
/*
* set RP0 PCICFG E2h[5:4] = 11b and E1h[6] = 1
* before configuring ASPM
*/
id = 0xe0 + (u8)(RCBA32(RPFN) & 0x07);
pch_iobp_exec(0xE00000E0, IOBP_PCICFG_READ, id, &data, &resp);
data |= ((0x30 << 16) | (0x40 << 8));
pch_iobp_exec(0xE00000E0, IOBP_PCICFG_WRITE, id, &data, &resp);
}
/* Cache pci device. */
rpc.ports[rp - 1] = dev;
}
/* Update devicetree with new Root Port function number assignment */
static void pch_pcie_device_set_func(int index, int pci_func)
{
device_t dev;
unsigned new_devfn;
dev = rpc.ports[index];
/* Set the new PCI function field for this Root Port. */
rpc.new_rpfn &= ~RPFN_FNMASK(index);
rpc.new_rpfn |= RPFN_FNSET(index, pci_func);
/* Determine the new devfn for this port */
new_devfn = PCI_DEVFN(PCH_DEV_SLOT_PCIE, pci_func);
if (dev->path.pci.devfn != new_devfn) {
printk(BIOS_DEBUG,
"PCH: PCIe map %02x.%1x -> %02x.%1x\n",
PCI_SLOT(dev->path.pci.devfn),
PCI_FUNC(dev->path.pci.devfn),
PCI_SLOT(new_devfn), PCI_FUNC(new_devfn));
dev->path.pci.devfn = new_devfn;
}
}
static void pcie_enable_clock_gating(void)
{
int i;
int enabled_ports = 0;
int is_broadwell = !!(cpu_family_model() == BROADWELL_FAMILY_ULT);
for (i = 0; i < rpc.num_ports; i++) {
device_t dev;
int rp;
dev = rpc.ports[i];
rp = root_port_number(dev);
if (!dev->enabled) {
/* Configure shared resource clock gating. */
if (rp == 1 || rp == 5 || rp == 6)
pcie_update_cfg8(dev, 0xe1, 0xc3, 0x3c);
pcie_update_cfg8(dev, 0xe2, ~(3 << 4), (3 << 4));
pcie_update_cfg(dev, 0x420, ~(1 << 31), (1 << 31));
/* Per-Port CLKREQ# handling. */
if (gpio_is_native(18 + rp - 1))
pcie_update_cfg(dev, 0x420, ~0, (3 << 29));
/* Enable static clock gating. */
if (rp == 1 && !rpc.ports[1]->enabled &&
!rpc.ports[2]->enabled && !rpc.ports[3]->enabled) {
pcie_update_cfg8(dev, 0xe2, ~1, 1);
pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80);
} else if (rp == 5 || rp == 6) {
pcie_update_cfg8(dev, 0xe2, ~1, 1);
pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80);
}
continue;
}
enabled_ports++;
/* Enable dynamic clock gating. */
pcie_update_cfg8(dev, 0xe1, 0xfc, 0x03);
pcie_update_cfg8(dev, 0xe2, ~(1 << 6), (1 << 6));
pcie_update_cfg8(dev, 0xe8, ~(3 << 2), (2 << 2));
/* Update PECR1 register. */
pcie_update_cfg8(dev, 0xe8, ~0, 3);
if (is_broadwell) {
pcie_update_cfg(dev, 0x324, ~((1 << 5) | (1 << 14)),
((1 << 5) | (1 << 14)));
} else {
pcie_update_cfg(dev, 0x324, ~(1 << 5), (1 << 5));
}
/* Per-Port CLKREQ# handling. */
if (gpio_is_native(18 + rp - 1))
/*
* In addition to D28Fx PCICFG 420h[30:29] = 11b,
* set 420h[17] = 0b and 420[0] = 1b for L1 SubState.
*/
pcie_update_cfg(dev, 0x420, ~0x20000, (3 << 29) | 1);
/* Configure shared resource clock gating. */
if (rp == 1 || rp == 5 || rp == 6)
pcie_update_cfg8(dev, 0xe1, 0xc3, 0x3c);
/* CLKREQ# VR Idle Enable */
RCBA32_OR(0x2b1c, (1 << (16 + i)));
}
if (!enabled_ports)
pcie_update_cfg8(rpc.ports[0], 0xe1, ~(1 << 6), (1 << 6));
}
static void root_port_commit_config(void)
{
int i;
/* If the first root port is disabled the coalesce ports. */
if (!rpc.ports[0]->enabled)
rpc.coalesce = 1;
/* Perform clock gating configuration. */
pcie_enable_clock_gating();
for (i = 0; i < rpc.num_ports; i++) {
device_t dev;
u32 reg32;
int n = 0;
dev = rpc.ports[i];
if (dev == NULL) {
printk(BIOS_ERR, "Root Port %d device is NULL?\n", i+1);
continue;
}
if (dev->enabled)
continue;
printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev));
/* 8.2 Configuration of PCI Express Root Ports */
pcie_update_cfg(dev, 0x338, ~(1 << 26), 1 << 26);
do {
reg32 = pci_read_config32(dev, 0x328);
n++;
if (((reg32 & 0xff000000) == 0x01000000) || (n > 50))
break;
udelay(100);
} while (1);
if (n > 50)
printk(BIOS_DEBUG, "%s: Timeout waiting for 328h\n",
dev_path(dev));
pcie_update_cfg(dev, 0x408, ~(1 << 27), 1 << 27);
/* Disable this device if possible */
pch_disable_devfn(dev);
}
if (rpc.coalesce) {
int current_func;
/* For all Root Ports N enabled ports get assigned the lower
* PCI function number. The disabled ones get upper PCI
* function numbers. */
current_func = 0;
for (i = 0; i < rpc.num_ports; i++) {
if (!rpc.ports[i]->enabled)
continue;
pch_pcie_device_set_func(i, current_func);
current_func++;
}
/* Allocate the disabled devices' PCI function number. */
for (i = 0; i < rpc.num_ports; i++) {
if (rpc.ports[i]->enabled)
continue;
pch_pcie_device_set_func(i, current_func);
current_func++;
}
}
printk(BIOS_SPEW, "PCH: RPFN 0x%08x -> 0x%08x\n",
rpc.orig_rpfn, rpc.new_rpfn);
RCBA32(RPFN) = rpc.new_rpfn;
}
static void root_port_mark_disable(device_t dev)
{
/* Mark device as disabled. */
dev->enabled = 0;
/* Mark device to be hidden. */
rpc.new_rpfn |= RPFN_HIDE(PCI_FUNC(dev->path.pci.devfn));
}
static void root_port_check_disable(device_t dev)
{
int rp;
/* Device already disabled. */
if (!dev->enabled) {
root_port_mark_disable(dev);
return;
}
rp = root_port_number(dev);
/* Is the GbE port mapped to this Root Port? */
if (rp == rpc.gbe_port) {
root_port_mark_disable(dev);
return;
}
/* Check Root Port Configuration. */
switch (rp) {
case 2:
/* Root Port 2 is disabled for all lane configurations
* but config 00b (4x1 links). */
if ((rpc.strpfusecfg1 >> 14) & 0x3) {
root_port_mark_disable(dev);
return;
}
break;
case 3:
/* Root Port 3 is disabled in config 11b (1x4 links). */
if (((rpc.strpfusecfg1 >> 14) & 0x3) == 0x3) {
root_port_mark_disable(dev);
return;
}
break;
case 4:
/* Root Port 4 is disabled in configs 11b (1x4 links)
* and 10b (2x2 links). */
if ((rpc.strpfusecfg1 >> 14) & 0x2) {
root_port_mark_disable(dev);
return;
}
break;
}
/* Check Pin Ownership. */
switch (rp) {
case 1:
/* Bit 0 is Root Port 1 ownership. */
if ((rpc.pin_ownership & 0x1) == 0) {
root_port_mark_disable(dev);
return;
}
break;
case 2:
/* Bit 2 is Root Port 2 ownership. */
if ((rpc.pin_ownership & 0x4) == 0) {
root_port_mark_disable(dev);
return;
}
break;
case 6:
/* Bits 7:4 are Root Port 6 pin-lane ownership. */
if ((rpc.pin_ownership & 0xf0) == 0) {
root_port_mark_disable(dev);
return;
}
break;
}
}
static void pcie_update_cfg8(device_t dev, int reg, u8 mask, u8 or)
{
u8 reg8;
reg8 = pci_read_config8(dev, reg);
reg8 &= mask;
reg8 |= or;
pci_write_config8(dev, reg, reg8);
}
static void pcie_update_cfg(device_t dev, int reg, u32 mask, u32 or)
{
u32 reg32;
reg32 = pci_read_config32(dev, reg);
reg32 &= mask;
reg32 |= or;
pci_write_config32(dev, reg, reg32);
}
static void pcie_add_0x0202000_iobp(u32 reg)
{
u32 reg32;
reg32 = pch_iobp_read(reg);
reg32 += (0x2 << 16) | (0x2 << 8);
pch_iobp_write(reg, reg32);
}
static void pch_pcie_early(struct device *dev)
{
config_t *config = dev->chip_info;
int do_aspm = 0;
int rp = root_port_number(dev);
switch (rp) {
case 1:
case 2:
case 3:
case 4:
/*
* Bits 31:28 of b0d28f0 0x32c register correspond to
* Root Ports 4:1.
*/
do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1)));
break;
case 5:
/*
* Bit 28 of b0d28f4 0x32c register correspond to
* Root Ports 4:1.
*/
do_aspm = !!(rpc.b0d28f4_32c & (1 << 28));
break;
case 6:
/*
* Bit 28 of b0d28f5 0x32c register correspond to
* Root Ports 4:1.
*/
do_aspm = !!(rpc.b0d28f5_32c & (1 << 28));
break;
}
/* Allow ASPM to be forced on in devicetree */
if (config && (config->pcie_port_force_aspm & (1 << (rp - 1))))
do_aspm = 1;
printk(BIOS_DEBUG, "PCIe Root Port %d ASPM is %sabled\n",
rp, do_aspm ? "en" : "dis");
if (do_aspm) {
/* Set ASPM bits in MPC2 register. */
pcie_update_cfg(dev, 0xd4, ~(0x3 << 2), (1 << 4) | (0x2 << 2));
/* Set unique clock exit latency in MPC register. */
pcie_update_cfg(dev, 0xd8, ~(0x7 << 18), (0x7 << 18));
switch (rp) {
case 1:
pcie_add_0x0202000_iobp(0xe9002440);
break;
case 2:
pcie_add_0x0202000_iobp(0xe9002640);
break;
case 3:
pcie_add_0x0202000_iobp(0xe9000840);
break;
case 4:
pcie_add_0x0202000_iobp(0xe9000a40);
break;
case 5:
pcie_add_0x0202000_iobp(0xe9000c40);
pcie_add_0x0202000_iobp(0xe9000e40);
pcie_add_0x0202000_iobp(0xe9001040);
pcie_add_0x0202000_iobp(0xe9001240);
break;
case 6:
/* Update IOBP based on lane ownership. */
if (rpc.pin_ownership & (1 << 4))
pcie_add_0x0202000_iobp(0xea002040);
if (rpc.pin_ownership & (1 << 5))
pcie_add_0x0202000_iobp(0xea002240);
if (rpc.pin_ownership & (1 << 6))
pcie_add_0x0202000_iobp(0xea002440);
if (rpc.pin_ownership & (1 << 7))
pcie_add_0x0202000_iobp(0xea002640);
break;
}
pcie_update_cfg(dev, 0x338, ~(1 << 26), 0);
}
/* Enable LTR in Root Port. Disable OBFF. */
pcie_update_cfg(dev, 0x64, ~(1 << 11) & ~(3 << 18), (1 << 11));
pcie_update_cfg(dev, 0x68, ~(1 << 10), (1 << 10));
pcie_update_cfg(dev, 0x318, ~(0xffff << 16), (0x1414 << 16));
/* Set L1 exit latency in LCAP register. */
if (!do_aspm && (pci_read_config8(dev, 0xf5) & 0x1))
pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x4 << 15));
else
pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x2 << 15));
pcie_update_cfg(dev, 0x314, 0x0, 0x743a361b);
/* Set Common Clock Exit Latency in MPC register. */
pcie_update_cfg(dev, 0xd8, ~(0x7 << 15), (0x3 << 15));
pcie_update_cfg(dev, 0x33c, ~0x00ffffff, 0x854d74);
/* Set Invalid Receive Range Check Enable in MPC register. */
pcie_update_cfg(dev, 0xd8, ~0, (1 << 25));
pcie_update_cfg8(dev, 0xf5, 0x0f, 0);
/* Set AER Extended Cap ID to 01h and Next Cap Pointer to 200h. */
pcie_update_cfg(dev, 0x100, ~(1 << 29) & ~0xfffff, (1 << 29) | 0x10001);
/* Set L1 Sub-State Cap ID to 1Eh and Next Cap Pointer to None. */
pcie_update_cfg(dev, 0x200, ~0xffff, 0x001e);
pcie_update_cfg(dev, 0x320, ~(3 << 20) & ~(7 << 6),
(1 << 20) | (3 << 6));
/* Enable Relaxed Order from Root Port. */
pcie_update_cfg(dev, 0x320, ~(3 << 23), (3 << 23));
if (rp == 1 || rp == 5 || rp == 6)
pcie_update_cfg8(dev, 0xf7, ~0xc, 0);
/* Set EOI forwarding disable. */
pcie_update_cfg(dev, 0xd4, ~0, (1 << 1));
/* Read and write back write-once capability registers. */
pcie_update_cfg(dev, 0x34, ~0, 0);
pcie_update_cfg(dev, 0x40, ~0, 0);
pcie_update_cfg(dev, 0x80, ~0, 0);
pcie_update_cfg(dev, 0x90, ~0, 0);
}
static void pch_pcie_init(struct device *dev)
{
u16 reg16;
u32 reg32;
printk(BIOS_DEBUG, "Initializing PCH PCIe bridge.\n");
/* Enable SERR */
reg32 = pci_read_config32(dev, PCI_COMMAND);
reg32 |= PCI_COMMAND_SERR;
pci_write_config32(dev, PCI_COMMAND, reg32);
/* Enable Bus Master */
reg32 = pci_read_config32(dev, PCI_COMMAND);
reg32 |= PCI_COMMAND_MASTER;
pci_write_config32(dev, PCI_COMMAND, reg32);
/* Set Cache Line Size to 0x10 */
pci_write_config8(dev, 0x0c, 0x10);
reg16 = pci_read_config16(dev, 0x3e);
reg16 &= ~(1 << 0); /* disable parity error response */
reg16 |= (1 << 2); /* ISA enable */
pci_write_config16(dev, 0x3e, reg16);
#ifdef EVEN_MORE_DEBUG
reg32 = pci_read_config32(dev, 0x20);
printk(BIOS_SPEW, " MBL = 0x%08x\n", reg32);
reg32 = pci_read_config32(dev, 0x24);
printk(BIOS_SPEW, " PMBL = 0x%08x\n", reg32);
reg32 = pci_read_config32(dev, 0x28);
printk(BIOS_SPEW, " PMBU32 = 0x%08x\n", reg32);
reg32 = pci_read_config32(dev, 0x2c);
printk(BIOS_SPEW, " PMLU32 = 0x%08x\n", reg32);
#endif
/* Clear errors in status registers */
reg16 = pci_read_config16(dev, 0x06);
pci_write_config16(dev, 0x06, reg16);
reg16 = pci_read_config16(dev, 0x1e);
pci_write_config16(dev, 0x1e, reg16);
}
static void pch_pcie_enable(device_t dev)
{
/* Add this device to the root port config structure. */
root_port_init_config(dev);
/* Check to see if this Root Port should be disabled. */
root_port_check_disable(dev);
/* Power Management init before enumeration */
if (dev->enabled)
pch_pcie_early(dev);
/*
* When processing the last PCIe root port we can now
* update the Root Port Function Number and Hide register.
*/
if (root_port_is_last(dev))
root_port_commit_config();
}
static void pcie_set_subsystem(device_t dev, unsigned vendor, unsigned device)
{
/* NOTE: This is not the default position! */
if (!vendor || !device)
pci_write_config32(dev, 0x94, pci_read_config32(dev, 0));
else
pci_write_config32(dev, 0x94, (device << 16) | vendor);
}
static void pcie_set_L1_ss_max_latency(device_t dev, unsigned int off)
{
/* Set max snoop and non-snoop latency for Broadwell */
pci_mmio_write_config32(dev, off, 0x10031003);
}
static struct pci_operations pcie_ops = {
.set_subsystem = pcie_set_subsystem,
.set_L1_ss_latency = pcie_set_L1_ss_max_latency,
};
static struct device_operations device_ops = {
.read_resources = pci_bus_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_bus_enable_resources,
.init = pch_pcie_init,
.enable = pch_pcie_enable,
.scan_bus = pciexp_scan_bridge,
.ops_pci = &pcie_ops,
};
static const unsigned short pcie_device_ids[] = {
/* Lynxpoint-LP */
0x9c10, 0x9c12, 0x9c14, 0x9c16, 0x9c18, 0x9c1a,
/* WildcatPoint */
0x9c90, 0x9c92, 0x9c94, 0x9c96, 0x9c98, 0x9c9a, 0x2448,
0
};
static const struct pci_driver pch_pcie __pci_driver = {
.ops = &device_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.devices = pcie_device_ids,
};

View File

@@ -0,0 +1,49 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <stdlib.h>
#include <stdint.h>
#include <console/streams.h>
#include <soc/iomap.h>
#include <soc/pei_data.h>
#include <soc/pei_wrapper.h>
#include <soc/smm.h>
static void ABI_X86 send_to_console(unsigned char b)
{
console_tx_byte(b);
}
void broadwell_fill_pei_data(struct pei_data *pei_data)
{
pei_data->pei_version = PEI_VERSION;
pei_data->board_type = BOARD_TYPE_ULT;
pei_data->usbdebug = CONFIG_USBDEBUG;
pei_data->pciexbar = MCFG_BASE_ADDRESS;
pei_data->smbusbar = SMBUS_BASE_ADDRESS;
pei_data->ehcibar = EARLY_EHCI_BAR;
pei_data->xhcibar = EARLY_XHCI_BAR;
pei_data->gttbar = EARLY_GTT_BAR;
pei_data->pmbase = ACPI_BASE_ADDRESS;
pei_data->gpiobase = GPIO_BASE_ADDRESS;
pei_data->tseg_size = smm_region_size();
pei_data->temp_mmio_base = EARLY_TEMP_MMIO;
pei_data->tx_byte = &send_to_console;
pei_data->ddr_refresh_2x = 1;
}

View File

@@ -0,0 +1,452 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
/*
* Helper functions for dealing with power management registers
* and the differences between PCH variants.
*/
#include <arch/io.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_def.h>
#include <console/console.h>
#include <soc/iomap.h>
#include <soc/lpc.h>
#include <soc/pci_devs.h>
#include <soc/pm.h>
#include <soc/gpio.h>
/* Print status bits with descriptive names */
static void print_status_bits(u32 status, const char *bit_names[])
{
int i;
if (!status)
return;
for (i=31; i>=0; i--) {
if (status & (1 << i)) {
if (bit_names[i])
printk(BIOS_DEBUG, "%s ", bit_names[i]);
else
printk(BIOS_DEBUG, "BIT%d ", i);
}
}
}
/* Print status bits as GPIO numbers */
static void print_gpio_status(u32 status, int start)
{
int i;
if (!status)
return;
for (i=31; i>=0; i--) {
if (status & (1 << i))
printk(BIOS_DEBUG, "GPIO%d ", start + i);
}
}
/*
* PM1_CNT
*/
/* Enable events in PM1 control register */
void enable_pm1_control(u32 mask)
{
u32 pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
pm1_cnt |= mask;
outl(pm1_cnt, ACPI_BASE_ADDRESS + PM1_CNT);
}
/* Disable events in PM1 control register */
void disable_pm1_control(u32 mask)
{
u32 pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
pm1_cnt &= ~mask;
outl(pm1_cnt, ACPI_BASE_ADDRESS + PM1_CNT);
}
/*
* PM1
*/
/* Clear and return PM1 status register */
static u16 reset_pm1_status(void)
{
u16 pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS);
outw(pm1_sts, ACPI_BASE_ADDRESS + PM1_STS);
return pm1_sts;
}
/* Print PM1 status bits */
static u16 print_pm1_status(u16 pm1_sts)
{
const char *pm1_sts_bits[] = {
[0] = "TMROF",
[4] = "BM",
[5] = "GBL",
[8] = "PWRBTN",
[10] = "RTC",
[11] = "PRBTNOR",
[14] = "PCIEXPWAK",
[15] = "WAK",
};
if (!pm1_sts)
return 0;
printk(BIOS_SPEW, "PM1_STS: ");
print_status_bits(pm1_sts, pm1_sts_bits);
printk(BIOS_SPEW, "\n");
return pm1_sts;
}
/* Print, clear, and return PM1 status */
u16 clear_pm1_status(void)
{
return print_pm1_status(reset_pm1_status());
}
/* Set the PM1 register to events */
void enable_pm1(u16 events)
{
outw(events, ACPI_BASE_ADDRESS + PM1_EN);
}
/*
* SMI
*/
/* Clear and return SMI status register */
static u32 reset_smi_status(void)
{
u32 smi_sts = inl(ACPI_BASE_ADDRESS + SMI_STS);
outl(smi_sts, ACPI_BASE_ADDRESS + SMI_STS);
return smi_sts;
}
/* Print SMI status bits */
static u32 print_smi_status(u32 smi_sts)
{
const char *smi_sts_bits[] = {
[2] = "BIOS",
[3] = "LEGACY_USB",
[4] = "SLP_SMI",
[5] = "APM",
[6] = "SWSMI_TMR",
[8] = "PM1",
[9] = "GPE0",
[10] = "GPI",
[11] = "MCSMI",
[12] = "DEVMON",
[13] = "TCO",
[14] = "PERIODIC",
[15] = "SERIRQ_SMI",
[16] = "SMBUS_SMI",
[17] = "LEGACY_USB2",
[18] = "INTEL_USB2",
[20] = "PCI_EXP_SMI",
[21] = "MONITOR",
[26] = "SPI",
[27] = "GPIO_UNLOCK"
};
if (!smi_sts)
return 0;
printk(BIOS_DEBUG, "SMI_STS: ");
print_status_bits(smi_sts, smi_sts_bits);
printk(BIOS_DEBUG, "\n");
return smi_sts;
}
/* Print, clear, and return SMI status */
u32 clear_smi_status(void)
{
return print_smi_status(reset_smi_status());
}
/* Enable SMI event */
void enable_smi(u32 mask)
{
u32 smi_en = inl(ACPI_BASE_ADDRESS + SMI_EN);
smi_en |= mask;
outl(smi_en, ACPI_BASE_ADDRESS + SMI_EN);
}
/* Disable SMI event */
void disable_smi(u32 mask)
{
u32 smi_en = inl(ACPI_BASE_ADDRESS + SMI_EN);
smi_en &= ~mask;
outl(smi_en, ACPI_BASE_ADDRESS + SMI_EN);
}
/*
* ALT_GP_SMI
*/
/* Clear GPIO SMI status and return events that are enabled and active */
static u32 reset_alt_smi_status(void)
{
u32 alt_sts, alt_en;
/* Low Power variant moves this to GPIO region as dword */
alt_sts = inl(GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_STS);
outl(alt_sts, GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_STS);
alt_en = inl(GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_EN);
/* Only report enabled events */
return alt_sts & alt_en;
}
/* Print GPIO SMI status bits */
static u32 print_alt_smi_status(u32 alt_sts)
{
if (!alt_sts)
return 0;
printk(BIOS_DEBUG, "ALT_STS: ");
/* First 16 events are GPIO 32-47 */
print_gpio_status(alt_sts & 0xffff, 32);
printk(BIOS_DEBUG, "\n");
return alt_sts;
}
/* Print, clear, and return GPIO SMI status */
u32 clear_alt_smi_status(void)
{
return print_alt_smi_status(reset_alt_smi_status());
}
/* Enable GPIO SMI events */
void enable_alt_smi(u32 mask)
{
u32 alt_en;
alt_en = inl(GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_EN);
alt_en |= mask;
outl(alt_en, GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_EN);
}
/*
* TCO
*/
/* Clear TCO status and return events that are enabled and active */
static u32 reset_tco_status(void)
{
u32 tcobase = ACPI_BASE_ADDRESS + 0x60;
u32 tco_sts = inl(tcobase + 0x04);
u32 tco_en = inl(ACPI_BASE_ADDRESS + 0x68);
/* Don't clear BOOT_STS before SECOND_TO_STS */
outl(tco_sts & ~(1 << 18), tcobase + 0x04);
/* Clear BOOT_STS */
if (tco_sts & (1 << 18))
outl(tco_sts & (1 << 18), tcobase + 0x04);
return tco_sts & tco_en;
}
/* Print TCO status bits */
static u32 print_tco_status(u32 tco_sts)
{
const char *tco_sts_bits[] = {
[0] = "NMI2SMI",
[1] = "SW_TCO",
[2] = "TCO_INT",
[3] = "TIMEOUT",
[7] = "NEWCENTURY",
[8] = "BIOSWR",
[9] = "DMISCI",
[10] = "DMISMI",
[12] = "DMISERR",
[13] = "SLVSEL",
[16] = "INTRD_DET",
[17] = "SECOND_TO",
[18] = "BOOT",
[20] = "SMLINK_SLV"
};
if (!tco_sts)
return 0;
printk(BIOS_DEBUG, "TCO_STS: ");
print_status_bits(tco_sts, tco_sts_bits);
printk(BIOS_DEBUG, "\n");
return tco_sts;
}
/* Print, clear, and return TCO status */
u32 clear_tco_status(void)
{
return print_tco_status(reset_tco_status());
}
/* Enable TCO SCI */
void enable_tco_sci(void)
{
/* Clear pending events */
outl(ACPI_BASE_ADDRESS + GPE0_STS(3), TCOSCI_STS);
/* Enable TCO SCI events */
enable_gpe(TCOSCI_EN);
}
/*
* GPE0
*/
/* Clear a GPE0 status and return events that are enabled and active */
static u32 reset_gpe(u16 sts_reg, u16 en_reg)
{
u32 gpe0_sts = inl(ACPI_BASE_ADDRESS + sts_reg);
u32 gpe0_en = inl(ACPI_BASE_ADDRESS + en_reg);
outl(gpe0_sts, ACPI_BASE_ADDRESS + sts_reg);
/* Only report enabled events */
return gpe0_sts & gpe0_en;
}
/* Print GPE0 status bits */
static u32 print_gpe_status(u32 gpe0_sts, const char *bit_names[])
{
if (!gpe0_sts)
return 0;
printk(BIOS_DEBUG, "GPE0_STS: ");
print_status_bits(gpe0_sts, bit_names);
printk(BIOS_DEBUG, "\n");
return gpe0_sts;
}
/* Print GPE0 GPIO status bits */
static u32 print_gpe_gpio(u32 gpe0_sts, int start)
{
if (!gpe0_sts)
return 0;
printk(BIOS_DEBUG, "GPE0_STS: ");
print_gpio_status(gpe0_sts, start);
printk(BIOS_DEBUG, "\n");
return gpe0_sts;
}
/* Clear all GPE status and return "standard" GPE event status */
u32 clear_gpe_status(void)
{
const char *gpe0_sts_3_bits[] = {
[1] = "HOTPLUG",
[2] = "SWGPE",
[6] = "TCO_SCI",
[7] = "SMB_WAK",
[9] = "PCI_EXP",
[10] = "BATLOW",
[11] = "PME",
[12] = "ME",
[13] = "PME_B0",
[16] = "GPIO27",
[18] = "WADT"
};
print_gpe_gpio(reset_gpe(GPE0_STS(GPE_31_0), GPE0_EN(GPE_31_0)), 0);
print_gpe_gpio(reset_gpe(GPE0_STS(GPE_63_32), GPE0_EN(GPE_63_32)), 32);
print_gpe_gpio(reset_gpe(GPE0_STS(GPE_94_64), GPE0_EN(GPE_94_64)), 64);
return print_gpe_status(reset_gpe(GPE0_STS(GPE_STD), GPE0_EN(GPE_STD)),
gpe0_sts_3_bits);
}
/* Enable all requested GPE */
void enable_all_gpe(u32 set1, u32 set2, u32 set3, u32 set4)
{
outl(set1, ACPI_BASE_ADDRESS + GPE0_EN(GPE_31_0));
outl(set2, ACPI_BASE_ADDRESS + GPE0_EN(GPE_63_32));
outl(set3, ACPI_BASE_ADDRESS + GPE0_EN(GPE_94_64));
outl(set4, ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD));
}
/* Disable all GPE */
void disable_all_gpe(void)
{
enable_all_gpe(0, 0, 0, 0);
}
/* Enable a standard GPE */
void enable_gpe(u32 mask)
{
u32 gpe0_en = inl(ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD));
gpe0_en |= mask;
outl(gpe0_en, ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD));
}
/* Disable a standard GPE */
void disable_gpe(u32 mask)
{
u32 gpe0_en = inl(ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD));
gpe0_en &= ~mask;
outl(gpe0_en, ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD));
}
int acpi_sci_irq(void)
{
int scis = pci_read_config32(PCH_DEV_LPC, ACPI_CNTL) & SCI_IRQ_SEL;
int sci_irq = 9;
/* Determine how SCI is routed. */
switch (scis) {
case SCIS_IRQ9:
case SCIS_IRQ10:
case SCIS_IRQ11:
sci_irq = scis - SCIS_IRQ9 + 9;
break;
case SCIS_IRQ20:
case SCIS_IRQ21:
case SCIS_IRQ22:
case SCIS_IRQ23:
sci_irq = scis - SCIS_IRQ20 + 20;
break;
default:
printk(BIOS_DEBUG, "Invalid SCI route! Defaulting to IRQ9.\n");
sci_irq = 9;
break;
}
printk(BIOS_DEBUG, "SCI is IRQ%d\n", sci_irq);
return sci_irq;
}

View File

@@ -0,0 +1,100 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/acpi.h>
#include <cbmem.h>
#include <console/console.h>
#include <device/device.h>
#include <stdlib.h>
#include <string.h>
#include <soc/nvs.h>
#include <soc/pm.h>
#include <soc/ramstage.h>
#include <soc/intel/broadwell/chip.h>
/* Save bit index for PM1_STS and GPE_STS for ACPI _SWS */
static void save_acpi_wake_source(global_nvs_t *gnvs)
{
struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE);
uint16_t pm1;
int gpe_reg;
if (!ps)
return;
pm1 = ps->pm1_sts & ps->pm1_en;
/* Scan for first set bit in PM1 */
for (gnvs->pm1i = 0; gnvs->pm1i < 16; gnvs->pm1i++) {
if (pm1 & 1)
break;
pm1 >>= 1;
}
/* If unable to determine then return -1 */
if (gnvs->pm1i >= 16)
gnvs->pm1i = -1;
/* Scan for first set bit in GPE registers */
gnvs->gpei = -1;
for (gpe_reg = 0; gpe_reg < GPE0_REG_MAX; gpe_reg++) {
u32 gpe = ps->gpe0_sts[gpe_reg] & ps->gpe0_en[gpe_reg];
int start = gpe_reg * GPE0_REG_SIZE;
int end = start + GPE0_REG_SIZE;
if (gpe == 0) {
if (!gnvs->gpei)
gnvs->gpei = end;
continue;
}
for (gnvs->gpei = start; gnvs->gpei < end; gnvs->gpei++) {
if (gpe & 1)
break;
gpe >>= 1;
}
}
/* If unable to determine then return -1 */
if (gnvs->gpei >= (GPE0_REG_MAX * GPE0_REG_SIZE))
gnvs->gpei = -1;
printk(BIOS_DEBUG, "ACPI _SWS is PM1 Index %lld GPE Index %lld\n",
gnvs->pm1i, gnvs->gpei);
}
static void s3_resume_prepare(void)
{
global_nvs_t *gnvs;
gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(global_nvs_t));
if (gnvs == NULL)
return;
if (!acpi_is_wakeup_s3())
memset(gnvs, 0, sizeof(global_nvs_t));
else
save_acpi_wake_source(gnvs);
}
void broadwell_init_pre_device(void *chip_info)
{
s3_resume_prepare();
broadwell_run_reference_code();
}

View File

@@ -0,0 +1,146 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <string.h>
#include <arch/acpi.h>
#include <cbmem.h>
#include <console/console.h>
#include <console/streams.h>
#include <cpu/x86/tsc.h>
#include <program_loading.h>
#include <rmodule.h>
#include <stage_cache.h>
#include <string.h>
#if IS_ENABLED(CONFIG_CHROMEOS)
#include <vendorcode/google/chromeos/vboot_handoff.h>
#endif
#include <soc/pei_data.h>
#include <soc/pei_wrapper.h>
#include <soc/ramstage.h>
static pei_wrapper_entry_t load_refcode_from_cache(void)
{
struct prog refcode;
printk(BIOS_DEBUG, "refcode loading from cache.\n");
stage_cache_load_stage(STAGE_REFCODE, &refcode);
return (pei_wrapper_entry_t)prog_entry(&refcode);
}
static void cache_refcode(const struct rmod_stage_load *rsl)
{
stage_cache_add(STAGE_REFCODE, rsl->prog);
}
#if IS_ENABLED(CONFIG_CHROMEOS)
static int load_refcode_from_vboot(struct rmod_stage_load *refcode)
{
struct vboot_handoff *vboot_handoff;
const struct firmware_component *fwc;
struct cbfs_stage *stage;
vboot_handoff = cbmem_find(CBMEM_ID_VBOOT_HANDOFF);
fwc = &vboot_handoff->components[CONFIG_VBOOT_REFCODE_INDEX];
if (vboot_handoff == NULL ||
vboot_handoff->selected_firmware == VB_SELECT_FIRMWARE_READONLY ||
CONFIG_VBOOT_REFCODE_INDEX >= MAX_PARSED_FW_COMPONENTS ||
fwc->size == 0 || fwc->address == 0)
return -1;
printk(BIOS_DEBUG, "refcode loading from vboot rw area.\n");
stage = (void *)(uintptr_t)fwc->address;
if (rmodule_stage_load(refcode, stage)) {
printk(BIOS_DEBUG, "Error loading reference code.\n");
return -1;
}
return 0;
}
#else
static int load_refcode_from_vboot(struct rmod_stage_load *refcode)
{
return -1;
}
#endif
static int load_refcode_from_cbfs(struct rmod_stage_load *refcode)
{
printk(BIOS_DEBUG, "refcode loading from cbfs.\n");
if (rmodule_stage_load_from_cbfs(refcode)) {
printk(BIOS_DEBUG, "Error loading reference code.\n");
return -1;
}
return 0;
}
static pei_wrapper_entry_t load_reference_code(void)
{
struct prog prog = {
.name = CONFIG_CBFS_PREFIX "/refcode",
};
struct rmod_stage_load refcode = {
.cbmem_id = CBMEM_ID_REFCODE,
.prog = &prog,
};
if (acpi_is_wakeup_s3()) {
return load_refcode_from_cache();
}
if (load_refcode_from_vboot(&refcode) ||
load_refcode_from_cbfs(&refcode))
return NULL;
/* Cache loaded reference code. */
cache_refcode(&refcode);
return prog_entry(&prog);
}
void broadwell_run_reference_code(void)
{
int ret, dummy;
struct pei_data pei_data;
pei_wrapper_entry_t entry;
memset(&pei_data, 0, sizeof(pei_data));
mainboard_fill_pei_data(&pei_data);
broadwell_fill_pei_data(&pei_data);
pei_data.boot_mode = acpi_slp_type;
pei_data.saved_data = (void *) &dummy;
entry = load_reference_code();
if (entry == NULL) {
printk(BIOS_ERR, "Reference code not found\n");
return;
}
/* Call into reference code. */
ret = entry(&pei_data);
if (ret != 0) {
printk(BIOS_ERR, "Reference code returned %d\n", ret);
return;
}
}

View File

@@ -0,0 +1,49 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/io.h>
#include <halt.h>
#include <reset.h>
#include <soc/reset.h>
/*
* Soft reset (INIT# to cpu) - write 0x1 to I/O 0x92
* Soft reset (INIT# to cpu)- write 0x4 to I/0 0xcf9
* Cold reset (S0->S5->S0) - write 0xe to I/0 0xcf9
* Warm reset (PLTRST# assertion) - write 0x6 to I/O 0xcf9
* Global reset (S0->S5->S0 with ME reset) - write 0x6 or 0xe to 0xcf9 but
* with ETR[20] set.
*/
void soft_reset(void)
{
outb(0x04, 0xcf9);
}
void hard_reset(void)
{
outb(0x06, 0xcf9);
}
void reset_system(void)
{
hard_reset();
halt();
}

View File

@@ -0,0 +1,13 @@
cpu_incs += $(src)/soc/intel/broadwell/romstage/cache_as_ram.inc
romstage-y += cpu.c
romstage-y += pch.c
romstage-y += power_state.c
romstage-y += raminit.c
romstage-y += report_platform.c
romstage-y += romstage.c
romstage-y += smbus.c
romstage-y += spi.c
romstage-y += stack.c
romstage-y += systemagent.c
romstage-$(CONFIG_DRIVERS_UART_8250MEM) += uart.c

View File

@@ -0,0 +1,341 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com>
* Copyright (C) 2007-2008 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <cpu/x86/mtrr.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/post_code.h>
#include <cbmem.h>
/* The full cache-as-ram size includes the cache-as-ram portion from coreboot
* and the space used by the reference code. These 2 values combined should
* be a power of 2 because the MTRR setup assumes that. */
#define CACHE_AS_RAM_SIZE \
(CONFIG_DCACHE_RAM_SIZE + CONFIG_DCACHE_RAM_MRC_VAR_SIZE)
#define CACHE_AS_RAM_BASE CONFIG_DCACHE_RAM_BASE
#define CACHE_AS_RAM_LIMIT (CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE)
#define USBDEBUG_VAR_SIZE 36 /* sizeof(struct ehci_debug_info) */
/* Cache 4GB - MRC_SIZE_KB for MRC */
#define CACHE_MRC_BYTES ((CONFIG_CACHE_MRC_SIZE_KB << 10) - 1)
#define CACHE_MRC_BASE (0xFFFFFFFF - CACHE_MRC_BYTES)
#define CACHE_MRC_MASK (~CACHE_MRC_BYTES)
#define CPU_MAXPHYSADDR CONFIG_CPU_ADDR_BITS
#define CPU_PHYSMASK_HI (1 << (CPU_MAXPHYSADDR - 32) - 1)
#define NoEvictMod_MSR 0x2e0
/* Save the BIST result. */
movl %eax, %ebp
cache_as_ram:
post_code(0x20)
/* Send INIT IPI to all excluding ourself. */
movl $0x000C4500, %eax
movl $0xFEE00300, %esi
movl %eax, (%esi)
/* All CPUs need to be in Wait for SIPI state */
wait_for_sipi:
movl (%esi), %eax
bt $12, %eax
jc wait_for_sipi
post_code(0x21)
/* Zero out all fixed range and variable range MTRRs. */
movl $mtrr_table, %esi
movl $((mtrr_table_end - mtrr_table) / 2), %edi
xorl %eax, %eax
xorl %edx, %edx
clear_mtrrs:
movw (%esi), %bx
movzx %bx, %ecx
wrmsr
add $2, %esi
dec %edi
jnz clear_mtrrs
post_code(0x22)
/* Configure the default memory type to uncacheable. */
movl $MTRRdefType_MSR, %ecx
rdmsr
andl $(~0x00000cff), %eax
wrmsr
post_code(0x23)
/* Set Cache-as-RAM base address. */
movl $(MTRRphysBase_MSR(0)), %ecx
movl $(CACHE_AS_RAM_BASE | MTRR_TYPE_WRBACK), %eax
xorl %edx, %edx
wrmsr
post_code(0x24)
/* Set Cache-as-RAM mask. */
movl $(MTRRphysMask_MSR(0)), %ecx
movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRRphysMaskValid), %eax
movl $CPU_PHYSMASK_HI, %edx
wrmsr
post_code(0x25)
/* Enable MTRR. */
movl $MTRRdefType_MSR, %ecx
rdmsr
orl $MTRRdefTypeEn, %eax
wrmsr
/* Enable cache (CR0.CD = 0, CR0.NW = 0). */
movl %cr0, %eax
andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax
invd
movl %eax, %cr0
/* enable the 'no eviction' mode */
movl $NoEvictMod_MSR, %ecx
rdmsr
orl $1, %eax
andl $~2, %eax
wrmsr
/* Clear the cache memory region. This will also fill up the cache */
movl $CACHE_AS_RAM_BASE, %esi
movl %esi, %edi
movl $(CACHE_AS_RAM_SIZE / 4), %ecx
xorl %eax, %eax
rep stosl
/* enable the 'no eviction run' state */
movl $NoEvictMod_MSR, %ecx
rdmsr
orl $3, %eax
wrmsr
post_code(0x26)
/* Enable Cache-as-RAM mode by disabling cache. */
movl %cr0, %eax
orl $CR0_CacheDisable, %eax
movl %eax, %cr0
/* Enable cache for our code in Flash because we do XIP here */
movl $MTRRphysBase_MSR(1), %ecx
xorl %edx, %edx
/*
* IMPORTANT: The following calculation _must_ be done at runtime. See
* http://www.coreboot.org/pipermail/coreboot/2010-October/060855.html
*/
movl $copy_and_run, %eax
andl $(~(CONFIG_XIP_ROM_SIZE - 1)), %eax
orl $MTRR_TYPE_WRPROT, %eax
wrmsr
movl $MTRRphysMask_MSR(1), %ecx
movl $CPU_PHYSMASK_HI, %edx
movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRRphysMaskValid), %eax
wrmsr
post_code(0x27)
#if CONFIG_CACHE_MRC_BIN
/* Enable caching for ram init code to run faster */
movl $MTRRphysBase_MSR(2), %ecx
movl $(CACHE_MRC_BASE | MTRR_TYPE_WRPROT), %eax
xorl %edx, %edx
wrmsr
movl $MTRRphysMask_MSR(2), %ecx
movl $(CACHE_MRC_MASK | MTRRphysMaskValid), %eax
movl $CPU_PHYSMASK_HI, %edx
wrmsr
#endif
post_code(0x28)
/* Enable cache. */
movl %cr0, %eax
andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax
movl %eax, %cr0
/* Setup the stack. */
movl $(CACHE_AS_RAM_LIMIT), %eax
#if CONFIG_USBDEBUG
sub $(USBDEBUG_VAR_SIZE), %eax
#endif
movl %eax, %esp
/* Restore the BIST result. */
movl %ebp, %eax
/* Build the call frame. */
movl %esp, %ebp
movd %mm1, %ebx
pushl %ebx
movd %mm0, %ebx
pushl %ebx
pushl %eax
before_romstage:
post_code(0x29)
/* Call romstage.c main function. */
call romstage_main
/* Save return value from romstage_main. It contains the stack to use
* after cache-as-ram is torn down. It also contains the information
* for setting up MTRRs. */
movl %eax, %ebx
post_code(0x2f)
/* Copy global variable space (for USBDEBUG) to memory */
#if CONFIG_USBDEBUG
cld
movl $(CACHE_AS_RAM_LIMIT - USBDEBUG_VAR_SIZE), %esi
movl $(CONFIG_RAMTOP - USBDEBUG_VAR_SIZE), %edi
movl $USBDEBUG_VAR_SIZE, %ecx
rep movsb
#endif
post_code(0x30)
/* Disable cache. */
movl %cr0, %eax
orl $CR0_CacheDisable, %eax
movl %eax, %cr0
post_code(0x31)
/* Disable MTRR. */
movl $MTRRdefType_MSR, %ecx
rdmsr
andl $(~MTRRdefTypeEn), %eax
wrmsr
post_code(0x31)
/* Disable the no eviction run state */
movl $NoEvictMod_MSR, %ecx
rdmsr
andl $~2, %eax
wrmsr
invd
/* Disable the no eviction mode */
rdmsr
andl $~1, %eax
wrmsr
#if CONFIG_CACHE_MRC_BIN
/* Clear MTRR that was used to cache MRC */
xorl %eax, %eax
xorl %edx, %edx
movl $MTRRphysBase_MSR(2), %ecx
wrmsr
movl $MTRRphysMask_MSR(2), %ecx
wrmsr
#endif
post_code(0x33)
/* Enable cache. */
movl %cr0, %eax
andl $~(CR0_CacheDisable | CR0_NoWriteThrough), %eax
movl %eax, %cr0
post_code(0x36)
/* Disable cache. */
movl %cr0, %eax
orl $CR0_CacheDisable, %eax
movl %eax, %cr0
post_code(0x38)
/* Setup stack as indicated by return value from ramstage_main(). */
movl %ebx, %esp
/* Get number of MTRRs. */
popl %ebx
movl $MTRRphysBase_MSR(0), %ecx
1:
testl %ebx, %ebx
jz 1f
/* Low 32 bits of MTRR base. */
popl %eax
/* Upper 32 bits of MTRR base. */
popl %edx
/* Write MTRR base. */
wrmsr
inc %ecx
/* Low 32 bits of MTRR mask. */
popl %eax
/* Upper 32 bits of MTRR mask. */
popl %edx
/* Write MTRR mask. */
wrmsr
inc %ecx
dec %ebx
jmp 1b
1:
post_code(0x39)
/* And enable cache again after setting MTRRs. */
movl %cr0, %eax
andl $~(CR0_CacheDisable | CR0_NoWriteThrough), %eax
movl %eax, %cr0
post_code(0x3a)
/* Enable MTRR. */
movl $MTRRdefType_MSR, %ecx
rdmsr
orl $MTRRdefTypeEn, %eax
wrmsr
post_code(0x3b)
/* Invalidate the cache again. */
invd
post_code(0x3c)
__main:
post_code(POST_PREPARE_RAMSTAGE)
cld /* Clear direction flag. */
call romstage_after_car
.Lhlt:
post_code(POST_DEAD_CODE)
hlt
jmp .Lhlt
mtrr_table:
/* Fixed MTRRs */
.word 0x250, 0x258, 0x259
.word 0x268, 0x269, 0x26A
.word 0x26B, 0x26C, 0x26D
.word 0x26E, 0x26F
/* Variable MTRRs */
.word 0x200, 0x201, 0x202, 0x203
.word 0x204, 0x205, 0x206, 0x207
.word 0x208, 0x209, 0x20A, 0x20B
.word 0x20C, 0x20D, 0x20E, 0x20F
.word 0x210, 0x211, 0x212, 0x213
mtrr_table_end:

View File

@@ -0,0 +1,55 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/cpu.h>
#include <stdlib.h>
#include <console/console.h>
#include <cpu/x86/msr.h>
#include <soc/cpu.h>
#include <soc/msr.h>
#include <soc/romstage.h>
u32 cpu_family_model(void)
{
return cpuid_eax(1) & 0x0fff0ff0;
}
void set_max_freq(void)
{
msr_t msr, perf_ctl, platform_info;
/* Check for configurable TDP option */
platform_info = rdmsr(MSR_PLATFORM_INFO);
if ((platform_info.hi >> 1) & 3) {
/* Set to nominal TDP ratio */
msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
perf_ctl.lo = (msr.lo & 0xff) << 8;
} else {
/* Platform Info bits 15:8 give max ratio */
msr = rdmsr(MSR_PLATFORM_INFO);
perf_ctl.lo = msr.lo & 0xff00;
}
perf_ctl.hi = 0;
wrmsr(IA32_PERF_CTL, perf_ctl);
printk(BIOS_DEBUG, "CPU: frequency set to %d MHz\n",
((perf_ctl.lo >> 8) & 0xff) * CPU_BCLK);
}

View File

@@ -0,0 +1,161 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/io.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci_def.h>
#include <reg_script.h>
#include <soc/iomap.h>
#include <soc/lpc.h>
#include <soc/pch.h>
#include <soc/pci_devs.h>
#include <soc/pm.h>
#include <soc/rcba.h>
#include <soc/romstage.h>
#include <soc/smbus.h>
#include <soc/intel/broadwell/chip.h>
const struct reg_script pch_early_init_script[] = {
/* Setup southbridge BARs */
REG_PCI_WRITE32(RCBA, RCBA_BASE_ADDRESS | 1),
REG_PCI_WRITE32(PMBASE, ACPI_BASE_ADDRESS | 1),
REG_PCI_WRITE8(ACPI_CNTL, ACPI_EN),
REG_PCI_WRITE32(GPIO_BASE, GPIO_BASE_ADDRESS | 1),
REG_PCI_WRITE8(GPIO_CNTL, GPIO_EN),
/* Set COM1/COM2 decode range */
REG_PCI_WRITE16(LPC_IO_DEC, 0x0010),
/* Enable legacy decode ranges */
REG_PCI_WRITE16(LPC_EN, CNF1_LPC_EN | CNF2_LPC_EN | GAMEL_LPC_EN |
COMA_LPC_EN | KBC_LPC_EN | MC_LPC_EN),
/* Enable IOAPIC */
REG_MMIO_WRITE16(RCBA_BASE_ADDRESS + OIC, 0x0100),
/* Read back for posted write */
REG_MMIO_READ16(RCBA_BASE_ADDRESS + OIC),
/* Set HPET address and enable it */
REG_MMIO_RMW32(RCBA_BASE_ADDRESS + HPTC, ~3, (1 << 7)),
/* Read back for posted write */
REG_MMIO_READ32(RCBA_BASE_ADDRESS + HPTC),
/* Enable HPET to start counter */
REG_MMIO_OR32(HPET_BASE_ADDRESS + 0x10, (1 << 0)),
/* Disable reset */
REG_MMIO_OR32(RCBA_BASE_ADDRESS + GCS, (1 << 5)),
/* TCO timer halt */
REG_IO_OR16(ACPI_BASE_ADDRESS + TCO1_CNT, TCO_TMR_HLT),
/* Enable upper 128 bytes of CMOS */
REG_MMIO_OR32(RCBA_BASE_ADDRESS + RC, (1 << 2)),
/* Disable unused device (always) */
REG_MMIO_OR32(RCBA_BASE_ADDRESS + FD, PCH_DISABLE_ALWAYS),
REG_SCRIPT_END
};
const struct reg_script pch_interrupt_init_script[] = {
/*
* GFX INTA -> PIRQA (MSI)
* D28IP_P1IP PCIE INTA -> PIRQA
* D29IP_E1P EHCI INTA -> PIRQD
* D20IP_XHCI XHCI INTA -> PIRQC (MSI)
* D31IP_SIP SATA INTA -> PIRQF (MSI)
* D31IP_SMIP SMBUS INTB -> PIRQG
* D31IP_TTIP THRT INTC -> PIRQA
* D27IP_ZIP HDA INTA -> PIRQG (MSI)
*/
/* Device interrupt pin register (board specific) */
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D31IP,
(INTC << D31IP_TTIP) | (NOINT << D31IP_SIP2) |
(INTB << D31IP_SMIP) | (INTA << D31IP_SIP)),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D29IP, (INTA << D29IP_E1P)),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D28IP,
(INTA << D28IP_P1IP) | (INTC << D28IP_P3IP) |
(INTB << D28IP_P4IP)),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D27IP, (INTA << D27IP_ZIP)),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D26IP, (INTA << D26IP_E2P)),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D22IP, (NOINT << D22IP_MEI1IP)),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D20IP, (INTA << D20IP_XHCI)),
/* Device interrupt route registers */
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D31IR, /* LPC */
DIR_ROUTE(PIRQG, PIRQC, PIRQB, PIRQA)),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D29IR, /* EHCI */
DIR_ROUTE(PIRQD, PIRQD, PIRQD, PIRQD)),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D28IR, /* PCIE */
DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD)),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D27IR, /* HDA */
DIR_ROUTE(PIRQG, PIRQG, PIRQG, PIRQG)),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D22IR, /* ME */
DIR_ROUTE(PIRQA, PIRQA, PIRQA, PIRQA)),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D21IR, /* SIO */
DIR_ROUTE(PIRQE, PIRQF, PIRQF, PIRQF)),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D20IR, /* XHCI */
DIR_ROUTE(PIRQC, PIRQC, PIRQC, PIRQC)),
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D23IR, /* SDIO */
DIR_ROUTE(PIRQH, PIRQH, PIRQH, PIRQH)),
REG_SCRIPT_END
};
static void pch_enable_lpc(void)
{
/* Lookup device tree in romstage */
const struct device *dev;
const config_t *config;
dev = dev_find_slot(0, PCI_DEVFN(PCH_DEV_SLOT_LPC, 0));
if (!dev || !dev->chip_info)
return;
config = dev->chip_info;
pci_write_config32(PCH_DEV_LPC, LPC_GEN1_DEC, config->gen1_dec);
pci_write_config32(PCH_DEV_LPC, LPC_GEN2_DEC, config->gen2_dec);
pci_write_config32(PCH_DEV_LPC, LPC_GEN3_DEC, config->gen3_dec);
pci_write_config32(PCH_DEV_LPC, LPC_GEN4_DEC, config->gen4_dec);
}
static void pcie_update_cfg(device_t dev, int reg, u32 mask, u32 or)
{
u32 reg32;
reg32 = pci_read_config32(dev, reg);
reg32 &= mask;
reg32 |= or;
pci_write_config32(dev, reg, reg32);
}
void pch_early_init(void)
{
reg_script_run_on_dev(PCH_DEV_LPC, pch_early_init_script);
reg_script_run_on_dev(PCH_DEV_LPC, pch_interrupt_init_script);
pch_enable_lpc();
enable_smbus();
/* 8.14 Additional PCI Express Programming Steps, step #1 */
pcie_update_cfg(_PCH_DEV(PCIE, 0), 0xf4, ~0x60, 0);
pcie_update_cfg(_PCH_DEV(PCIE, 0), 0xf4, ~0x80, 0x80);
pcie_update_cfg(_PCH_DEV(PCIE, 0), 0xe2, ~0x30, 0x30);
}

View File

@@ -0,0 +1,132 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/early_variables.h>
#include <arch/io.h>
#include <cbmem.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_def.h>
#include <reg_script.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <soc/iomap.h>
#include <soc/lpc.h>
#include <soc/pci_devs.h>
#include <soc/pm.h>
#include <soc/romstage.h>
static struct chipset_power_state power_state CAR_GLOBAL;
static void migrate_power_state(void)
{
struct chipset_power_state *ps_cbmem;
struct chipset_power_state *ps_car;
ps_car = car_get_var_ptr(&power_state);
ps_cbmem = cbmem_add(CBMEM_ID_POWER_STATE, sizeof(*ps_cbmem));
if (ps_cbmem == NULL) {
printk(BIOS_DEBUG, "Not adding power state to cbmem!\n");
return;
}
memcpy(ps_cbmem, ps_car, sizeof(*ps_cbmem));
}
CAR_MIGRATE(migrate_power_state);
/* Return 0, 3, or 5 to indicate the previous sleep state. */
static int prev_sleep_state(struct chipset_power_state *ps)
{
/* Default to S0. */
int prev_sleep_state = SLEEP_STATE_S0;
if (ps->pm1_sts & WAK_STS) {
switch ((ps->pm1_cnt & SLP_TYP) >> SLP_TYP_SHIFT) {
#if CONFIG_HAVE_ACPI_RESUME
case SLP_TYP_S3:
prev_sleep_state = SLEEP_STATE_S3;
break;
#endif
case SLP_TYP_S5:
prev_sleep_state = SLEEP_STATE_S5;
break;
}
/* Clear SLP_TYP. */
outl(ps->pm1_cnt & ~(SLP_TYP), ACPI_BASE_ADDRESS + PM1_CNT);
}
if (ps->gen_pmcon3 & (PWR_FLR | SUS_PWR_FLR))
prev_sleep_state = SLEEP_STATE_S5;
return prev_sleep_state;
}
static void dump_power_state(struct chipset_power_state *ps)
{
printk(BIOS_DEBUG, "PM1_STS: %04x\n", ps->pm1_sts);
printk(BIOS_DEBUG, "PM1_EN: %04x\n", ps->pm1_en);
printk(BIOS_DEBUG, "PM1_CNT: %08x\n", ps->pm1_cnt);
printk(BIOS_DEBUG, "TCO_STS: %04x %04x\n",
ps->tco1_sts, ps->tco2_sts);
printk(BIOS_DEBUG, "GPE0_STS: %08x %08x %08x %08x\n",
ps->gpe0_sts[0], ps->gpe0_sts[1],
ps->gpe0_sts[2], ps->gpe0_sts[3]);
printk(BIOS_DEBUG, "GPE0_EN: %08x %08x %08x %08x\n",
ps->gpe0_en[0], ps->gpe0_en[1],
ps->gpe0_en[2], ps->gpe0_en[3]);
printk(BIOS_DEBUG, "GEN_PMCON: %04x %04x %04x\n",
ps->gen_pmcon1, ps->gen_pmcon2, ps->gen_pmcon3);
printk(BIOS_DEBUG, "Previous Sleep State: S%d\n",
ps->prev_sleep_state);
}
/* Fill power state structure from ACPI PM registers */
struct chipset_power_state *fill_power_state(void)
{
struct chipset_power_state *ps = car_get_var_ptr(&power_state);
ps->pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS);
ps->pm1_en = inw(ACPI_BASE_ADDRESS + PM1_EN);
ps->pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
ps->tco1_sts = inw(ACPI_BASE_ADDRESS + TCO1_STS);
ps->tco2_sts = inw(ACPI_BASE_ADDRESS + TCO2_STS);
ps->gpe0_sts[0] = inl(ACPI_BASE_ADDRESS + GPE0_STS(0));
ps->gpe0_sts[1] = inl(ACPI_BASE_ADDRESS + GPE0_STS(1));
ps->gpe0_sts[2] = inl(ACPI_BASE_ADDRESS + GPE0_STS(2));
ps->gpe0_sts[3] = inl(ACPI_BASE_ADDRESS + GPE0_STS(3));
ps->gpe0_en[0] = inl(ACPI_BASE_ADDRESS + GPE0_EN(0));
ps->gpe0_en[1] = inl(ACPI_BASE_ADDRESS + GPE0_EN(1));
ps->gpe0_en[2] = inl(ACPI_BASE_ADDRESS + GPE0_EN(2));
ps->gpe0_en[3] = inl(ACPI_BASE_ADDRESS + GPE0_EN(3));
ps->gen_pmcon1 = pci_read_config16(PCH_DEV_LPC, GEN_PMCON_1);
ps->gen_pmcon2 = pci_read_config16(PCH_DEV_LPC, GEN_PMCON_2);
ps->gen_pmcon3 = pci_read_config16(PCH_DEV_LPC, GEN_PMCON_3);
ps->prev_sleep_state = prev_sleep_state(ps);
dump_power_state(ps);
return ps;
}

View File

@@ -0,0 +1,138 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/cbfs.h>
#include <arch/io.h>
#include <cbfs.h>
#include <cbmem.h>
#include <console/console.h>
#include <device/pci_def.h>
#include <lib.h>
#include <string.h>
#if CONFIG_EC_GOOGLE_CHROMEEC
#include <ec/google/chromeec/ec.h>
#include <ec/google/chromeec/ec_commands.h>
#endif
#include <stage_cache.h>
#include <vendorcode/google/chromeos/chromeos.h>
#include <soc/intel/common/mrc_cache.h>
#include <soc/iomap.h>
#include <soc/pei_data.h>
#include <soc/pei_wrapper.h>
#include <soc/pm.h>
#include <soc/reset.h>
#include <soc/romstage.h>
#include <soc/smm.h>
#include <soc/systemagent.h>
/*
* Find PEI executable in coreboot filesystem and execute it.
*/
void raminit(struct pei_data *pei_data)
{
const struct mrc_saved_data *cache;
struct memory_info* mem_info;
pei_wrapper_entry_t entry;
int ret;
broadwell_fill_pei_data(pei_data);
if (recovery_mode_enabled()) {
/* Recovery mode does not use MRC cache */
printk(BIOS_DEBUG, "Recovery mode: not using MRC cache.\n");
} else if (!mrc_cache_get_current(&cache)) {
/* MRC cache found */
pei_data->saved_data_size = cache->size;
pei_data->saved_data = &cache->data[0];
} else if (pei_data->boot_mode == SLEEP_STATE_S3) {
/* Waking from S3 and no cache. */
printk(BIOS_DEBUG, "No MRC cache found in S3 resume path.\n");
post_code(POST_RESUME_FAILURE);
reset_system();
} else {
printk(BIOS_DEBUG, "No MRC cache found.\n");
#if CONFIG_EC_GOOGLE_CHROMEEC
if (pei_data->boot_mode == SLEEP_STATE_S0) {
/* Ensure EC is running RO firmware. */
google_chromeec_check_ec_image(EC_IMAGE_RO);
}
#endif
}
/*
* Do not use saved pei data. Can be set by mainboard romstage
* to force a full train of memory on every boot.
*/
if (pei_data->disable_saved_data) {
printk(BIOS_DEBUG, "Disabling PEI saved data by request\n");
pei_data->saved_data = NULL;
pei_data->saved_data_size = 0;
}
/* Determine if mrc.bin is in the cbfs. */
entry = (pei_wrapper_entry_t)cbfs_get_file_content(
CBFS_DEFAULT_MEDIA, "mrc.bin", CBFS_TYPE_MRC, NULL);
if (entry == NULL) {
printk(BIOS_DEBUG, "Couldn't find mrc.bin\n");
return;
}
printk(BIOS_DEBUG, "Starting Memory Reference Code\n");
ret = entry(pei_data);
if (ret < 0)
die("pei_data version mismatch\n");
/* Print the MRC version after executing the UEFI PEI stage. */
u32 version = MCHBAR32(MCHBAR_PEI_VERSION);
printk(BIOS_DEBUG, "MRC Version %d.%d.%d Build %d\n",
version >> 24 , (version >> 16) & 0xff,
(version >> 8) & 0xff, version & 0xff);
report_memory_config();
/* Basic memory sanity test */
quick_ram_check();
if (pei_data->boot_mode != SLEEP_STATE_S3) {
cbmem_initialize_empty();
stage_cache_create_empty();
} else {
stage_cache_recover();
if (cbmem_initialize()) {
#if CONFIG_HAVE_ACPI_RESUME
printk(BIOS_DEBUG, "Failed to recover CBMEM in S3 resume.\n");
/* Failed S3 resume, reset to come up cleanly */
reset_system();
#endif
}
}
printk(BIOS_DEBUG, "MRC data at %p %d bytes\n", pei_data->data_to_save,
pei_data->data_to_save_size);
if (pei_data->data_to_save != NULL && pei_data->data_to_save_size > 0)
mrc_cache_stash_data(pei_data->data_to_save,
pei_data->data_to_save_size);
printk(BIOS_DEBUG, "create cbmem for dimm information\n");
mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(struct memory_info));
memcpy(mem_info, &pei_data->meminfo, sizeof(struct memory_info));
}

View File

@@ -0,0 +1,243 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/cpu.h>
#include <arch/io.h>
#include <console/console.h>
#include <device/pci.h>
#include <string.h>
#include <cpu/x86/msr.h>
#include <soc/cpu.h>
#include <soc/pch.h>
#include <soc/pci_devs.h>
#include <soc/romstage.h>
#include <soc/systemagent.h>
static struct {
u32 cpuid;
const char *name;
} cpu_table[] = {
{ CPUID_HASWELL_A0, "Haswell A0" },
{ CPUID_HASWELL_B0, "Haswell B0" },
{ CPUID_HASWELL_C0, "Haswell C0" },
{ CPUID_HASWELL_ULT_B0, "Haswell ULT B0" },
{ CPUID_HASWELL_ULT, "Haswell ULT C0 or D0" },
{ CPUID_HASWELL_HALO, "Haswell Perf Halo" },
{ CPUID_BROADWELL_C0, "Broadwell C0" },
{ CPUID_BROADWELL_D0, "Broadwell D0" },
{ CPUID_BROADWELL_E0, "Broadwell E0 or F0" },
};
static struct {
u8 revid;
const char *name;
} mch_rev_table[] = {
{ MCH_BROADWELL_REV_D0, "Broadwell D0" },
{ MCH_BROADWELL_REV_E0, "Broadwell E0" },
{ MCH_BROADWELL_REV_F0, "Broadwell F0" },
};
static struct {
u16 lpcid;
const char *name;
} pch_table[] = {
{ PCH_LPT_LP_SAMPLE, "LynxPoint LP Sample" },
{ PCH_LPT_LP_PREMIUM, "LynxPoint LP Premium" },
{ PCH_LPT_LP_MAINSTREAM, "LynxPoint LP Mainstream" },
{ PCH_LPT_LP_VALUE, "LynxPoint LP Value" },
{ PCH_WPT_HSW_U_SAMPLE, "Haswell U Sample" },
{ PCH_WPT_BDW_U_SAMPLE, "Broadwell U Sample" },
{ PCH_WPT_BDW_U_PREMIUM, "Broadwell U Premium" },
{ PCH_WPT_BDW_U_BASE, "Broadwell U Base" },
{ PCH_WPT_BDW_Y_SAMPLE, "Broadwell Y Sample" },
{ PCH_WPT_BDW_Y_PREMIUM, "Broadwell Y Premium" },
{ PCH_WPT_BDW_Y_BASE, "Broadwell Y Base" },
{ PCH_WPT_BDW_H, "Broadwell H" },
};
static struct {
u16 igdid;
const char *name;
} igd_table[] = {
{ IGD_HASWELL_ULT_GT1, "Haswell ULT GT1" },
{ IGD_HASWELL_ULT_GT2, "Haswell ULT GT2" },
{ IGD_HASWELL_ULT_GT3, "Haswell ULT GT3" },
{ IGD_BROADWELL_U_GT1, "Broadwell U GT1" },
{ IGD_BROADWELL_U_GT2, "Broadwell U GT2" },
{ IGD_BROADWELL_U_GT3_15W, "Broadwell U GT3 (15W)" },
{ IGD_BROADWELL_U_GT3_28W, "Broadwell U GT3 (28W)" },
{ IGD_BROADWELL_Y_GT2, "Broadwell Y GT2" },
{ IGD_BROADWELL_H_GT2, "Broadwell U GT2" },
{ IGD_BROADWELL_H_GT3, "Broadwell U GT3" },
};
static void report_cpu_info(void)
{
struct cpuid_result cpuidr;
u32 i, index;
char cpu_string[50], *cpu_name = cpu_string; /* 48 bytes are reported */
int vt, txt, aes;
msr_t microcode_ver;
const char *mode[] = {"NOT ", ""};
const char *cpu_type = "Unknown";
index = 0x80000000;
cpuidr = cpuid(index);
if (cpuidr.eax < 0x80000004) {
strcpy(cpu_string, "Platform info not available");
} else {
u32 *p = (u32*) cpu_string;
for (i = 2; i <= 4 ; i++) {
cpuidr = cpuid(index + i);
*p++ = cpuidr.eax;
*p++ = cpuidr.ebx;
*p++ = cpuidr.ecx;
*p++ = cpuidr.edx;
}
}
/* Skip leading spaces in CPU name string */
while (cpu_name[0] == ' ')
cpu_name++;
microcode_ver.lo = 0;
microcode_ver.hi = 0;
wrmsr(0x8B, microcode_ver);
cpuidr = cpuid(1);
microcode_ver = rdmsr(0x8b);
/* Look for string to match the name */
for (i = 0; i < ARRAY_SIZE(cpu_table); i++) {
if (cpu_table[i].cpuid == cpuidr.eax) {
cpu_type = cpu_table[i].name;
break;
}
}
printk(BIOS_DEBUG, "CPU: %s\n", cpu_name);
printk(BIOS_DEBUG, "CPU: ID %x, %s, ucode: %08x\n",
cpuidr.eax, cpu_type, microcode_ver.hi);
aes = (cpuidr.ecx & (1 << 25)) ? 1 : 0;
txt = (cpuidr.ecx & (1 << 6)) ? 1 : 0;
vt = (cpuidr.ecx & (1 << 5)) ? 1 : 0;
printk(BIOS_DEBUG, "CPU: AES %ssupported, TXT %ssupported, "
"VT %ssupported\n", mode[aes], mode[txt], mode[vt]);
}
static void report_mch_info(void)
{
int i;
u16 mch_device = pci_read_config16(SA_DEV_ROOT, PCI_DEVICE_ID);
u8 mch_revision = pci_read_config8(SA_DEV_ROOT, PCI_REVISION_ID);
const char *mch_type = "Unknown";
/* Look for string to match the revision for Broadwell U/Y */
if (mch_device == MCH_BROADWELL_ID_U_Y) {
for (i = 0; i < ARRAY_SIZE(mch_rev_table); i++) {
if (mch_rev_table[i].revid == mch_revision) {
mch_type = mch_rev_table[i].name;
break;
}
}
}
printk(BIOS_DEBUG, "MCH: device id %04x (rev %02x) is %s\n",
mch_device, mch_revision, mch_type);
}
static void report_pch_info(void)
{
int i;
u16 lpcid = pch_type();
const char *pch_type = "Unknown";
for (i = 0; i < ARRAY_SIZE(pch_table); i++) {
if (pch_table[i].lpcid == lpcid) {
pch_type = pch_table[i].name;
break;
}
}
printk(BIOS_DEBUG, "PCH: device id %04x (rev %02x) is %s\n",
lpcid, pch_revision(), pch_type);
}
static void report_igd_info(void)
{
int i;
u16 igdid = pci_read_config16(SA_DEV_IGD, PCI_DEVICE_ID);
const char *igd_type = "Unknown";
for (i = 0; i < ARRAY_SIZE(igd_table); i++) {
if (igd_table[i].igdid == igdid) {
igd_type = igd_table[i].name;
break;
}
}
printk(BIOS_DEBUG, "IGD: device id %04x (rev %02x) is %s\n",
igdid, pci_read_config8(SA_DEV_IGD, PCI_REVISION_ID), igd_type);
}
void report_platform_info(void)
{
report_cpu_info();
report_mch_info();
report_pch_info();
report_igd_info();
}
/*
* Dump in the log memory controller configuration as read from the memory
* controller registers.
*/
void report_memory_config(void)
{
u32 addr_decoder_common, addr_decode_ch[2];
int i;
addr_decoder_common = MCHBAR32(0x5000);
addr_decode_ch[0] = MCHBAR32(0x5004);
addr_decode_ch[1] = MCHBAR32(0x5008);
printk(BIOS_DEBUG, "memcfg DDR3 clock %d MHz\n",
(MCHBAR32(0x5e04) * 13333 * 2 + 50)/100);
printk(BIOS_DEBUG, "memcfg channel assignment: A: %d, B % d, C % d\n",
addr_decoder_common & 3,
(addr_decoder_common >> 2) & 3,
(addr_decoder_common >> 4) & 3);
for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) {
u32 ch_conf = addr_decode_ch[i];
printk(BIOS_DEBUG, "memcfg channel[%d] config (%8.8x):\n",
i, ch_conf);
printk(BIOS_DEBUG, " enhanced interleave mode %s\n",
((ch_conf >> 22) & 1) ? "on" : "off");
printk(BIOS_DEBUG, " rank interleave %s\n",
((ch_conf >> 21) & 1) ? "on" : "off");
printk(BIOS_DEBUG, " DIMMA %d MB width %s %s rank%s\n",
((ch_conf >> 0) & 0xff) * 256,
((ch_conf >> 19) & 1) ? "x16" : "x8 or x32",
((ch_conf >> 17) & 1) ? "dual" : "single",
((ch_conf >> 16) & 1) ? "" : ", selected");
printk(BIOS_DEBUG, " DIMMB %d MB width %s %s rank%s\n",
((ch_conf >> 8) & 0xff) * 256,
((ch_conf >> 19) & 1) ? "x16" : "x8 or x32",
((ch_conf >> 18) & 1) ? "dual" : "single",
((ch_conf >> 16) & 1) ? ", selected" : "");
}
}

View File

@@ -0,0 +1,164 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <stddef.h>
#include <stdint.h>
#include <arch/cpu.h>
#include <arch/io.h>
#include <arch/cbfs.h>
#include <arch/stages.h>
#include <arch/early_variables.h>
#include <console/console.h>
#include <cbfs.h>
#include <cbmem.h>
#include <cpu/x86/mtrr.h>
#include <elog.h>
#include <romstage_handoff.h>
#include <stage_cache.h>
#include <timestamp.h>
#include <soc/me.h>
#include <soc/pei_data.h>
#include <soc/pm.h>
#include <soc/reset.h>
#include <soc/romstage.h>
#include <soc/spi.h>
#include <vendorcode/google/chromeos/chromeos.h>
/* Entry from cache-as-ram.inc. */
void * asmlinkage romstage_main(unsigned long bist,
uint32_t tsc_low, uint32_t tsc_hi)
{
struct romstage_params rp = {
.bist = bist,
.pei_data = NULL,
};
post_code(0x30);
/* Save initial timestamp from bootblock. */
timestamp_init((((uint64_t)tsc_hi) << 32) | (uint64_t)tsc_low);
/* Save romstage begin */
timestamp_add_now(TS_START_ROMSTAGE);
/* System Agent Early Initialization */
systemagent_early_init();
/* PCH Early Initialization */
pch_early_init();
/* Call into mainboard pre console init. Needed to enable serial port
on IT8772 */
mainboard_pre_console_init();
/* Start console drivers */
console_init();
/* Get power state */
rp.power_state = fill_power_state();
/* Print useful platform information */
report_platform_info();
/* Set CPU frequency to maximum */
set_max_freq();
/* Call into mainboard. */
mainboard_romstage_entry(&rp);
#if CONFIG_CHROMEOS
save_chromeos_gpios();
#endif
return setup_stack_and_mttrs();
}
static inline void chromeos_init(int prev_sleep_state)
{
#if CONFIG_CHROMEOS
/* Normalize the sleep state to what init_chromeos() wants for S3: 2 */
init_chromeos(prev_sleep_state == SLEEP_STATE_S3 ? 2 : 0);
#endif
}
/* Entry from the mainboard. */
void romstage_common(struct romstage_params *params)
{
struct romstage_handoff *handoff;
post_code(0x32);
timestamp_add_now(TS_BEFORE_INITRAM);
params->pei_data->boot_mode = params->power_state->prev_sleep_state;
#if CONFIG_ELOG_BOOT_COUNT
if (params->power_state->prev_sleep_state != SLEEP_STATE_S3)
boot_count_increment();
#endif
/* Print ME state before MRC */
intel_me_status();
/* Save ME HSIO version */
intel_me_hsio_version(&params->power_state->hsio_version,
&params->power_state->hsio_checksum);
/* Initialize RAM */
raminit(params->pei_data);
timestamp_add_now(TS_AFTER_INITRAM);
handoff = romstage_handoff_find_or_add();
if (handoff != NULL)
handoff->s3_resume = (params->power_state->prev_sleep_state ==
SLEEP_STATE_S3);
else
printk(BIOS_DEBUG, "Romstage handoff structure not added!\n");
chromeos_init(params->power_state->prev_sleep_state);
}
void asmlinkage romstage_after_car(void)
{
timestamp_add_now(TS_END_ROMSTAGE);
/* Load the ramstage. */
copy_and_run();
while (1);
}
void ramstage_cache_invalid(void)
{
#if CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE
/* Perform cold reset on invalid ramstage cache. */
reset_system();
#endif
}
#if CONFIG_CHROMEOS
int vboot_get_sw_write_protect(void)
{
u8 status;
/* Return unprotected status if status read fails. */
return (early_spi_read_wpsr(&status) ? 0 : !!(status & 0x80));
}
#endif
void __attribute__((weak)) mainboard_pre_console_init(void) {}

View File

@@ -0,0 +1,54 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/io.h>
#include <console/console.h>
#include <device/pci_ids.h>
#include <device/pci_def.h>
#include <reg_script.h>
#include <soc/iomap.h>
#include <soc/pci_devs.h>
#include <soc/smbus.h>
#include <soc/romstage.h>
static const struct reg_script smbus_init_script[] = {
/* Set SMBUS I/O base address */
REG_PCI_WRITE32(SMB_BASE, SMBUS_BASE_ADDRESS | 1),
/* Set SMBUS enable */
REG_PCI_WRITE8(HOSTC, HST_EN),
/* Enable I/O access */
REG_PCI_WRITE16(PCI_COMMAND, PCI_COMMAND_IO),
/* Disable interrupts */
REG_IO_WRITE8(SMBUS_BASE_ADDRESS + SMBHSTCTL, 0),
/* Clear errors */
REG_IO_WRITE8(SMBUS_BASE_ADDRESS + SMBHSTSTAT, 0xff),
/* Indicate the end of this array by REG_SCRIPT_END */
REG_SCRIPT_END,
};
void enable_smbus(void)
{
reg_script_run_on_dev(PCH_DEV_SMBUS, smbus_init_script);
}
int smbus_read_byte(unsigned device, unsigned address)
{
return do_smbus_read_byte(SMBUS_BASE_ADDRESS, device, address);
}

View File

@@ -0,0 +1,149 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/io.h>
#include <console/console.h>
#include <device/pci_ids.h>
#include <device/pci_def.h>
#include <delay.h>
#include <soc/spi.h>
#include <soc/rcba.h>
#include <soc/romstage.h>
#define SPI_DELAY 10 /* 10us */
#define SPI_RETRY 200000 /* 2s */
static int early_spi_read_block(u32 offset, u8 size, u8 *buffer)
{
u32 *ptr32 = (u32*)buffer;
u32 i;
/* Clear status bits */
SPIBAR16(SPIBAR_HSFS) |= SPIBAR_HSFS_AEL | SPIBAR_HSFS_FCERR |
SPIBAR_HSFS_FDONE;
if (SPIBAR16(SPIBAR_HSFS) & SPIBAR_HSFS_SCIP) {
printk(BIOS_ERR, "SPI ERROR: transaction in progress\n");
return -1;
}
/* Set flash address */
SPIBAR32(SPIBAR_FADDR) = offset;
/* Setup read transaction */
SPIBAR16(SPIBAR_HSFC) = SPIBAR_HSFC_BYTE_COUNT(size) |
SPIBAR_HSFC_CYCLE_READ;
/* Start transaction */
SPIBAR16(SPIBAR_HSFC) |= SPIBAR_HSFC_GO;
/* Wait for completion */
for (i = 0; i < SPI_RETRY; i++) {
if (SPIBAR16(SPIBAR_HSFS) & SPIBAR_HSFS_SCIP) {
/* Cycle in progress, wait 1ms */
udelay(SPI_DELAY);
continue;
}
if (SPIBAR16(SPIBAR_HSFS) & SPIBAR_HSFS_AEL) {
printk(BIOS_ERR, "SPI ERROR: Access Error\n");
return -1;
}
if (SPIBAR16(SPIBAR_HSFS) & SPIBAR_HSFS_FCERR) {
printk(BIOS_ERR, "SPI ERROR: Flash Cycle Error\n");
return -1;
}
break;
}
if (i >= SPI_RETRY) {
printk(BIOS_ERR, "SPI ERROR: Timeout\n");
return -1;
}
/* Read the data */
for (i = 0; i < size; i+=sizeof(u32)) {
if (size-i >= 4) {
/* reading >= dword */
*ptr32++ = SPIBAR32(SPIBAR_FDATA(i/sizeof(u32)));
} else {
/* reading < dword */
u8 j, *ptr8 = (u8*)ptr32;
u32 temp = SPIBAR32(SPIBAR_FDATA(i/sizeof(u32)));
for (j = 0; j < (size-i); j++) {
*ptr8++ = temp & 0xff;
temp >>= 8;
}
}
}
return size;
}
int early_spi_read(u32 offset, u32 size, u8 *buffer)
{
u32 current = 0;
while (size > 0) {
u8 count = (size < 64) ? size : 64;
if (early_spi_read_block(offset + current, count,
buffer + current) < 0)
return -1;
size -= count;
current += count;
}
return 0;
}
/*
* Minimal set of commands to read WPSR from SPI.
* Don't use this code outside romstage -- it trashes the opmenu table.
* Returns 0 on success, < 0 on failure.
*/
int early_spi_read_wpsr(u8 *sr)
{
int retry;
/* No address associated with rdsr */
SPIBAR8(SPIBAR_OPTYPE) = 0x0;
/* Setup opcode[0] = read wpsr */
SPIBAR8(SPIBAR_OPMENU_LOWER) = 0x5;
/* Start transaction */
SPIBAR16(SPIBAR_SSFC) = SPIBAR_SSFC_DATA | SPIBAR_SSFC_GO;
/* Wait for error / complete status */
for (retry = SPI_RETRY; retry; retry--) {
u16 status = SPIBAR16(SPIBAR_SSFS);
if (status & SPIBAR_SSFS_ERROR) {
printk(BIOS_ERR, "SPI rdsr failed\n");
return -1;
} else if (status & SPIBAR_SSFS_DONE) {
break;
}
udelay(SPI_DELAY);
}
*sr = SPIBAR32(SPIBAR_FDATA(0)) & 0xff;
return 0;
}

View File

@@ -0,0 +1,124 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <stddef.h>
#include <stdint.h>
#include <arch/cpu.h>
#include <arch/early_variables.h>
#include <console/console.h>
#include <cbmem.h>
#include <cpu/x86/mtrr.h>
#include <soc/romstage.h>
static inline uint32_t *stack_push(u32 *stack, u32 value)
{
stack = &stack[-1];
*stack = value;
return stack;
}
/* Romstage needs quite a bit of stack for decompressing images since the lzma
* lib keeps its state on the stack during romstage. */
static unsigned long choose_top_of_stack(void)
{
unsigned long stack_top;
const unsigned long romstage_ram_stack_size = 0x5000;
/* cbmem_add() does a find() before add(). */
stack_top = (unsigned long)cbmem_add(CBMEM_ID_ROMSTAGE_RAM_STACK,
romstage_ram_stack_size);
stack_top += romstage_ram_stack_size;
return stack_top;
}
/* setup_stack_and_mttrs() determines the stack to use after
* cache-as-ram is torn down as well as the MTRR settings to use. */
void *setup_stack_and_mttrs(void)
{
unsigned long top_of_stack;
int num_mtrrs;
uint32_t *slot;
uint32_t mtrr_mask_upper;
uint32_t top_of_ram;
/* Top of stack needs to be aligned to a 4-byte boundary. */
top_of_stack = choose_top_of_stack() & ~3;
slot = (void *)top_of_stack;
num_mtrrs = 0;
/* The upper bits of the MTRR mask need to set according to the number
* of physical address bits. */
mtrr_mask_upper = (1 << ((cpuid_eax(0x80000008) & 0xff) - 32)) - 1;
/* The order for each MTTR is value then base with upper 32-bits of
* each value coming before the lower 32-bits. The reasoning for
* this ordering is to create a stack layout like the following:
* +0: Number of MTRRs
* +4: MTTR base 0 31:0
* +8: MTTR base 0 63:32
* +12: MTTR mask 0 31:0
* +16: MTTR mask 0 63:32
* +20: MTTR base 1 31:0
* +24: MTTR base 1 63:32
* +28: MTTR mask 1 31:0
* +32: MTTR mask 1 63:32
*/
/* Cache the ROM as WP just below 4GiB. */
slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
slot = stack_push(slot, ~(CONFIG_ROM_SIZE - 1) | MTRRphysMaskValid);
slot = stack_push(slot, 0); /* upper base */
slot = stack_push(slot, ~(CONFIG_ROM_SIZE - 1) | MTRR_TYPE_WRPROT);
num_mtrrs++;
/* Cache RAM as WB from 0 -> CONFIG_RAMTOP. */
slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
slot = stack_push(slot, ~(CONFIG_RAMTOP - 1) | MTRRphysMaskValid);
slot = stack_push(slot, 0); /* upper base */
slot = stack_push(slot, 0 | MTRR_TYPE_WRBACK);
num_mtrrs++;
top_of_ram = (uint32_t)cbmem_top();
/* Cache 8MiB below the top of ram. The top of ram under 4GiB is the
* start of the TSEG region. It is required to be 8MiB aligned. Set
* this area as cacheable so it can be used later for ramstage before
* setting up the entire RAM as cacheable. */
slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
slot = stack_push(slot, ~((8 << 20) - 1) | MTRRphysMaskValid);
slot = stack_push(slot, 0); /* upper base */
slot = stack_push(slot, (top_of_ram - (8 << 20)) | MTRR_TYPE_WRBACK);
num_mtrrs++;
/* Cache 8MiB at the top of ram. Top of ram is where the TSEG
* region resides. However, it is not restricted to SMM mode until
* SMM has been relocated. By setting the region to cacheable it
* provides faster access when relocating the SMM handler as well
* as using the TSEG region for other purposes. */
slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
slot = stack_push(slot, ~((8 << 20) - 1) | MTRRphysMaskValid);
slot = stack_push(slot, 0); /* upper base */
slot = stack_push(slot, top_of_ram | MTRR_TYPE_WRBACK);
num_mtrrs++;
/* Save the number of MTTRs to setup. Return the stack location
* pointing to the number of MTRRs. */
slot = stack_push(slot, num_mtrrs);
return slot;
}

View File

@@ -0,0 +1,55 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2010 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <stdlib.h>
#include <arch/io.h>
#include <device/pci_def.h>
#include <reg_script.h>
#include <soc/iomap.h>
#include <soc/pci_devs.h>
#include <soc/romstage.h>
#include <soc/systemagent.h>
static const struct reg_script systemagent_early_init_script[] = {
REG_PCI_WRITE32(MCHBAR, MCH_BASE_ADDRESS | 1),
REG_PCI_WRITE32(DMIBAR, DMI_BASE_ADDRESS | 1),
REG_PCI_WRITE32(EPBAR, EP_BASE_ADDRESS | 1),
REG_MMIO_WRITE32(MCH_BASE_ADDRESS + EDRAMBAR, EDRAM_BASE_ADDRESS | 1),
REG_MMIO_WRITE32(MCH_BASE_ADDRESS + GDXCBAR, GDXC_BASE_ADDRESS | 1),
/* Set C0000-FFFFF to access RAM on both reads and writes */
REG_PCI_WRITE8(PAM0, 0x30),
REG_PCI_WRITE8(PAM1, 0x33),
REG_PCI_WRITE8(PAM2, 0x33),
REG_PCI_WRITE8(PAM3, 0x33),
REG_PCI_WRITE8(PAM4, 0x33),
REG_PCI_WRITE8(PAM5, 0x33),
REG_PCI_WRITE8(PAM6, 0x33),
/* Device enable: IGD and Mini-HD */
REG_PCI_WRITE32(DEVEN, DEVEN_D0EN | DEVEN_D2EN | DEVEN_D3EN),
REG_SCRIPT_END
};
void systemagent_early_init(void)
{
reg_script_run_on_dev(SA_DEV_ROOT, systemagent_early_init_script);
}

View File

@@ -0,0 +1,85 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/early_variables.h>
#include <arch/io.h>
#include <delay.h>
#include <device/pci_def.h>
#include <reg_script.h>
#include <stdint.h>
#include <uart8250.h>
#include <soc/iobp.h>
#include <soc/serialio.h>
const struct reg_script uart_init[] = {
/* Set MMIO BAR */
REG_PCI_WRITE32(PCI_BASE_ADDRESS_0, CONFIG_TTYS0_BASE),
/* Enable Memory access and Bus Master */
REG_PCI_OR32(PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER),
/* Initialize LTR */
REG_MMIO_RMW32(CONFIG_TTYS0_BASE + SIO_REG_PPR_GEN,
~SIO_REG_PPR_GEN_LTR_MODE_MASK, 0),
REG_MMIO_RMW32(CONFIG_TTYS0_BASE + SIO_REG_PPR_RST,
~(SIO_REG_PPR_RST_ASSERT), 0),
/* Take UART out of reset */
REG_MMIO_OR32(CONFIG_TTYS0_BASE + SIO_REG_PPR_RST,
SIO_REG_PPR_RST_ASSERT),
/* Set M and N divisor inputs and enable clock */
REG_MMIO_WRITE32(CONFIG_TTYS0_BASE + SIO_REG_PPR_CLOCK,
SIO_REG_PPR_CLOCK_EN | SIO_REG_PPR_CLOCK_UPDATE |
(SIO_REG_PPR_CLOCK_N_DIV << 16) |
(SIO_REG_PPR_CLOCK_M_DIV << 1)),
REG_SCRIPT_END
};
void pch_uart_init(void)
{
/* Program IOBP CB000154h[12,9:8,4:0] = 1001100011111b */
u32 gpiodf = 0x131f;
device_t dev;
/* Put UART in byte access mode for 16550 compatibility */
switch (CONFIG_INTEL_PCH_UART_CONSOLE_NUMBER) {
case 0:
dev = PCH_DEV_UART0;
gpiodf |= SIO_IOBP_GPIODF_UART0_BYTE_ACCESS;
break;
case 1:
dev = PCH_DEV_UART1;
gpiodf |= SIO_IOBP_GPIODF_UART1_BYTE_ACCESS;
break;
default:
return;
}
/* Program IOBP GPIODF */
pch_iobp_update(SIO_IOBP_GPIODF, ~gpiodf, gpiodf);
/* Program IOBP CB000180h[5:0] = 111111b (undefined register) */
pch_iobp_update(0xcb000180, ~0x0000003f, 0x0000003f);
/* Initialize chipset uart interface */
reg_script_run_on_dev(dev, uart_init);
/*
* Perform standard UART initialization
* Divisor 1 is 115200 BAUD
*/
uart8250_mem_init(CONFIG_TTYS0_BASE, 1);
}

View File

@@ -0,0 +1,264 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/io.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <delay.h>
#include <soc/iobp.h>
#include <soc/ramstage.h>
#include <soc/rcba.h>
#include <soc/sata.h>
#include <soc/intel/broadwell/chip.h>
static inline u32 sir_read(struct device *dev, int idx)
{
pci_write_config32(dev, SATA_SIRI, idx);
return pci_read_config32(dev, SATA_SIRD);
}
static inline void sir_write(struct device *dev, int idx, u32 value)
{
pci_write_config32(dev, SATA_SIRI, idx);
pci_write_config32(dev, SATA_SIRD, value);
}
static void sata_init(struct device *dev)
{
config_t *config = dev->chip_info;
u32 reg32;
u8 *abar;
u16 reg16;
int port;
printk(BIOS_DEBUG, "SATA: Initializing controller in AHCI mode.\n");
/* Enable BARs */
pci_write_config16(dev, PCI_COMMAND, 0x0007);
/* Set Interrupt Line */
/* Interrupt Pin is set by D31IP.PIP */
pci_write_config8(dev, PCI_INTERRUPT_LINE, 0x0a);
/* Set timings */
pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE);
pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE);
/* for AHCI, Port Enable is managed in memory mapped space */
reg16 = pci_read_config16(dev, 0x92);
reg16 &= ~0xf;
reg16 |= 0x8000 | config->sata_port_map;
pci_write_config16(dev, 0x92, reg16);
udelay(2);
/* Setup register 98h */
reg32 = pci_read_config32(dev, 0x98);
reg32 &= ~((1 << 31) | (1 << 30));
reg32 |= 1 << 23;
reg32 |= 1 << 24; /* Enable MPHY Dynamic Power Gating */
pci_write_config32(dev, 0x98, reg32);
/* Setup register 9Ch */
reg16 = 0; /* Disable alternate ID */
reg16 = 1 << 5; /* BWG step 12 */
pci_write_config16(dev, 0x9c, reg16);
/* SATA Initialization register */
reg32 = 0x183;
reg32 |= (config->sata_port_map ^ 0xf) << 24;
reg32 |= (config->sata_devslp_mux & 1) << 15;
pci_write_config32(dev, 0x94, reg32);
/* Initialize AHCI memory-mapped space */
abar = (u8 *)(pci_read_config32(dev, PCI_BASE_ADDRESS_5));
printk(BIOS_DEBUG, "ABAR: %p\n", abar);
/* CAP (HBA Capabilities) : enable power management */
reg32 = read32(abar + 0x00);
reg32 |= 0x0c006000; /* set PSC+SSC+SALP+SSS */
reg32 &= ~0x00020060; /* clear SXS+EMS+PMS */
reg32 |= (1 << 18); /* SAM: SATA AHCI MODE ONLY */
write32(abar + 0x00, reg32);
/* PI (Ports implemented) */
write32(abar + 0x0c, config->sata_port_map);
(void) read32(abar + 0x0c); /* Read back 1 */
(void) read32(abar + 0x0c); /* Read back 2 */
/* CAP2 (HBA Capabilities Extended)*/
if (config->sata_devslp_disable) {
reg32 = read32(abar + 0x24);
reg32 &= ~(1 << 3);
write32(abar + 0x24, reg32);
} else {
/* Enable DEVSLP */
reg32 = read32(abar + 0x24);
reg32 |= (1 << 5)|(1 << 4)|(1 << 3)|(1 << 2);
write32(abar + 0x24, reg32);
for (port = 0; port < 4; port++) {
if (!(config->sata_port_map & (1 << port)))
continue;
reg32 = read32(abar + 0x144 + (0x80 * port));
reg32 |= (1 << 1); /* DEVSLP DSP */
write32(abar + 0x144 + (0x80 * port), reg32);
}
}
/*
* Static Power Gating for unused ports
*/
reg32 = RCBA32(0x3a84);
/* Port 3 and 2 disabled */
if ((config->sata_port_map & ((1 << 3)|(1 << 2))) == 0)
reg32 |= (1 << 24) | (1 << 26);
/* Port 1 and 0 disabled */
if ((config->sata_port_map & ((1 << 1)|(1 << 0))) == 0)
reg32 |= (1 << 20) | (1 << 18);
RCBA32(0x3a84) = reg32;
/* Set Gen3 Transmitter settings if needed */
if (config->sata_port0_gen3_tx)
pch_iobp_update(SATA_IOBP_SP0_SECRT88,
~(SATA_SECRT88_VADJ_MASK <<
SATA_SECRT88_VADJ_SHIFT),
(config->sata_port0_gen3_tx &
SATA_SECRT88_VADJ_MASK)
<< SATA_SECRT88_VADJ_SHIFT);
if (config->sata_port1_gen3_tx)
pch_iobp_update(SATA_IOBP_SP1_SECRT88,
~(SATA_SECRT88_VADJ_MASK <<
SATA_SECRT88_VADJ_SHIFT),
(config->sata_port1_gen3_tx &
SATA_SECRT88_VADJ_MASK)
<< SATA_SECRT88_VADJ_SHIFT);
/* Set Gen3 DTLE DATA / EDGE registers if needed */
if (config->sata_port0_gen3_dtle) {
pch_iobp_update(SATA_IOBP_SP0DTLE_DATA,
~(SATA_DTLE_MASK << SATA_DTLE_DATA_SHIFT),
(config->sata_port0_gen3_dtle & SATA_DTLE_MASK)
<< SATA_DTLE_DATA_SHIFT);
pch_iobp_update(SATA_IOBP_SP0DTLE_EDGE,
~(SATA_DTLE_MASK << SATA_DTLE_EDGE_SHIFT),
(config->sata_port0_gen3_dtle & SATA_DTLE_MASK)
<< SATA_DTLE_EDGE_SHIFT);
}
if (config->sata_port1_gen3_dtle) {
pch_iobp_update(SATA_IOBP_SP1DTLE_DATA,
~(SATA_DTLE_MASK << SATA_DTLE_DATA_SHIFT),
(config->sata_port1_gen3_dtle & SATA_DTLE_MASK)
<< SATA_DTLE_DATA_SHIFT);
pch_iobp_update(SATA_IOBP_SP1DTLE_EDGE,
~(SATA_DTLE_MASK << SATA_DTLE_EDGE_SHIFT),
(config->sata_port1_gen3_dtle & SATA_DTLE_MASK)
<< SATA_DTLE_EDGE_SHIFT);
}
/*
* Additional Programming Requirements for Power Optimizer
*/
/* Step 1 */
sir_write(dev, 0x64, 0x883c9003);
/* Step 2: SIR 68h[15:0] = 880Ah */
reg32 = sir_read(dev, 0x68);
reg32 &= 0xffff0000;
reg32 |= 0x880a;
sir_write(dev, 0x68, reg32);
/* Step 3: SIR 60h[3] = 1 */
reg32 = sir_read(dev, 0x60);
reg32 |= (1 << 3);
sir_write(dev, 0x60, reg32);
/* Step 4: SIR 60h[0] = 1 */
reg32 = sir_read(dev, 0x60);
reg32 |= (1 << 0);
sir_write(dev, 0x60, reg32);
/* Step 5: SIR 60h[1] = 1 */
reg32 = sir_read(dev, 0x60);
reg32 |= (1 << 1);
sir_write(dev, 0x60, reg32);
/* Clock Gating */
sir_write(dev, 0x70, 0x3f00bf1f);
sir_write(dev, 0x54, 0xcf000f0f);
sir_write(dev, 0x58, 0x00190000);
RCBA32_AND_OR(0x333c, 0xffcfffff, 0x00c00000);
reg32 = pci_read_config32(dev, 0x300);
reg32 |= (1 << 17) | (1 << 16) | (1 << 19);
reg32 |= (1 << 31) | (1 << 30) | (1 << 29);
pci_write_config32(dev, 0x300, reg32);
reg32 = pci_read_config32(dev, 0x98);
reg32 |= 1 << 29;
pci_write_config32(dev, 0x98, reg32);
/* Register Lock */
reg32 = pci_read_config32(dev, 0x9c);
reg32 |= (1 << 31);
pci_write_config32(dev, 0x9c, reg32);
}
/*
* Set SATA controller mode early so the resource allocator can
* properly assign IO/Memory resources for the controller.
*/
static void sata_enable(device_t dev)
{
/* Get the chip configuration */
config_t *config = dev->chip_info;
u16 map = 0x0060;
map |= (config->sata_port_map ^ 0xf) << 8;
pci_write_config16(dev, 0x90, map);
}
static struct device_operations sata_ops = {
.read_resources = &pci_dev_read_resources,
.set_resources = &pci_dev_set_resources,
.enable_resources = &pci_dev_enable_resources,
.init = &sata_init,
.enable = &sata_enable,
.ops_pci = &broadwell_pci_ops,
};
static const unsigned short pci_device_ids[] = {
0x9c03, 0x9c05, 0x9c07, 0x9c0f, /* LynxPoint-LP */
0x9c83, 0x9c85, 0x282a, 0x9c87, 0x282a, 0x9c8f, /* WildcatPoint */
0
};
static const struct pci_driver pch_sata __pci_driver = {
.ops = &sata_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.devices = pci_device_ids,
};

View File

@@ -0,0 +1,318 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/io.h>
#include <cbmem.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pciexp.h>
#include <device/pci_ids.h>
#include <stdlib.h>
#include <soc/iobp.h>
#include <soc/nvs.h>
#include <soc/pci_devs.h>
#include <soc/pch.h>
#include <soc/ramstage.h>
#include <soc/rcba.h>
#include <soc/serialio.h>
#include <soc/intel/broadwell/chip.h>
/* Set D3Hot Power State in ACPI mode */
static void serialio_enable_d3hot(struct resource *res)
{
u32 reg32 = read32(res2mmio(res, PCH_PCS, 0));
reg32 |= PCH_PCS_PS_D3HOT;
write32(res2mmio(res, PCH_PCS, 0), reg32);
}
static int serialio_uart_is_debug(struct device *dev)
{
#if CONFIG_INTEL_PCH_UART_CONSOLE
switch (dev->path.pci.devfn) {
case PCH_DEVFN_UART0: /* UART0 */
return !!(CONFIG_INTEL_PCH_UART_CONSOLE_NUMBER == 0);
case PCH_DEVFN_UART1: /* UART1 */
return !!(CONFIG_INTEL_PCH_UART_CONSOLE_NUMBER == 1);
}
#endif
return 0;
}
/* Enable clock in PCI mode */
static void serialio_enable_clock(struct resource *bar0)
{
u32 reg32 = read32(res2mmio(bar0, SIO_REG_PPR_CLOCK, 0));
reg32 |= SIO_REG_PPR_CLOCK_EN;
write32(res2mmio(bar0, SIO_REG_PPR_CLOCK, 0), reg32);
}
/* Put Serial IO D21:F0-F6 device into desired mode. */
static void serialio_d21_mode(int sio_index, int int_pin, int acpi_mode)
{
u32 portctrl = SIO_IOBP_PORTCTRL_PM_CAP_PRSNT;
/* Snoop select 1. */
portctrl |= SIO_IOBP_PORTCTRL_SNOOP_SELECT(1);
/* Set interrupt pin. */
portctrl |= SIO_IOBP_PORTCTRL_INT_PIN(int_pin);
if (acpi_mode) {
/* Enable ACPI interrupt mode. */
portctrl |= SIO_IOBP_PORTCTRL_ACPI_IRQ_EN;
/* Disable PCI config space. */
portctrl |= SIO_IOBP_PORTCTRL_PCI_CONF_DIS;
}
pch_iobp_update(SIO_IOBP_PORTCTRLX(sio_index), 0, portctrl);
}
/* Put Serial IO D23:F0 device into desired mode. */
static void serialio_d23_mode(int acpi_mode)
{
u32 portctrl = 0;
/* Snoop select 1. */
pch_iobp_update(SIO_IOBP_PORTCTRL1, 0,
SIO_IOBP_PORTCTRL1_SNOOP_SELECT(1));
if (acpi_mode) {
/* Enable ACPI interrupt mode. */
portctrl |= SIO_IOBP_PORTCTRL0_ACPI_IRQ_EN;
/* Disable PCI config space. */
portctrl |= SIO_IOBP_PORTCTRL0_PCI_CONF_DIS;
}
pch_iobp_update(SIO_IOBP_PORTCTRL0, 0, portctrl);
}
/* Enable LTR Auto Mode for D21:F1-F6. */
static void serialio_d21_ltr(struct resource *bar0)
{
u32 reg;
/* 1. Program BAR0 + 808h[2] = 0b */
reg = read32(res2mmio(bar0, SIO_REG_PPR_GEN, 0));
reg &= ~SIO_REG_PPR_GEN_LTR_MODE_MASK;
write32(res2mmio(bar0, SIO_REG_PPR_GEN, 0), reg);
/* 2. Program BAR0 + 804h[1:0] = 00b */
reg = read32(res2mmio(bar0, SIO_REG_PPR_RST, 0));
reg &= ~SIO_REG_PPR_RST_ASSERT;
write32(res2mmio(bar0, SIO_REG_PPR_RST, 0), reg);
/* 3. Program BAR0 + 804h[1:0] = 11b */
reg = read32(res2mmio(bar0, SIO_REG_PPR_RST, 0));
reg |= SIO_REG_PPR_RST_ASSERT;
write32(res2mmio(bar0, SIO_REG_PPR_RST, 0), reg);
/* 4. Program BAR0 + 814h[31:0] = 00000000h */
write32(res2mmio(bar0, SIO_REG_AUTO_LTR, 0), 0);
}
/* Enable LTR Auto Mode for D23:F0. */
static void serialio_d23_ltr(struct resource *bar0)
{
u32 reg;
/* Program BAR0 + 1008h[2] = 1b */
reg = read32(res2mmio(bar0, SIO_REG_SDIO_PPR_GEN, 0));
reg |= SIO_REG_PPR_GEN_LTR_MODE_MASK;
write32(res2mmio(bar0, SIO_REG_SDIO_PPR_GEN, 0), reg);
/* Program BAR0 + 1010h = 0x00000000 */
write32(res2mmio(bar0, SIO_REG_SDIO_PPR_SW_LTR, 0), 0);
/* Program BAR0 + 3Ch[30] = 1b */
reg = read32(res2mmio(bar0, SIO_REG_SDIO_PPR_CMD12, 0));
reg |= SIO_REG_SDIO_PPR_CMD12_B30;
write32(res2mmio(bar0, SIO_REG_SDIO_PPR_CMD12, 0), reg);
}
/* Select I2C voltage of 1.8V or 3.3V. */
static void serialio_i2c_voltage_sel(struct resource *bar0, u8 voltage)
{
u32 reg32 = read32(res2mmio(bar0, SIO_REG_PPR_GEN, 0));
reg32 &= ~SIO_REG_PPR_GEN_VOLTAGE_MASK;
reg32 |= SIO_REG_PPR_GEN_VOLTAGE(voltage);
write32(res2mmio(bar0, SIO_REG_PPR_GEN, 0), reg32);
}
/* Init sequence to be run once, done as part of D21:F0 (SDMA) init. */
static void serialio_init_once(int acpi_mode)
{
if (acpi_mode) {
/* Enable ACPI IRQ for IRQ13, IRQ7, IRQ6, IRQ5 in RCBA. */
RCBA32_OR(ACPIIRQEN, (1 << 13)|(1 << 7)|(1 << 6)|(1 << 5));
}
/* Program IOBP CB000154h[12,9:8,4:0] = 1001100011111b. */
pch_iobp_update(SIO_IOBP_GPIODF, ~0x0000131f, 0x0000131f);
/* Program IOBP CB000180h[5:0] = 111111b (undefined register) */
pch_iobp_update(0xcb000180, ~0x0000003f, 0x0000003f);
}
static void serialio_init(struct device *dev)
{
config_t *config = dev->chip_info;
struct resource *bar0, *bar1;
int sio_index = -1;
u32 reg32;
printk(BIOS_DEBUG, "Initializing Serial IO device\n");
/* Ensure memory and bus master are enabled */
reg32 = pci_read_config32(dev, PCI_COMMAND);
reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
pci_write_config32(dev, PCI_COMMAND, reg32);
/* Find BAR0 and BAR1 */
bar0 = find_resource(dev, PCI_BASE_ADDRESS_0);
if (!bar0)
return;
bar1 = find_resource(dev, PCI_BASE_ADDRESS_1);
if (!bar1)
return;
if (!config->sio_acpi_mode)
serialio_enable_clock(bar0);
switch (dev->path.pci.devfn) {
case PCH_DEVFN_SDMA: /* SDMA */
sio_index = SIO_ID_SDMA;
serialio_init_once(config->sio_acpi_mode);
serialio_d21_mode(sio_index, SIO_PIN_INTB,
config->sio_acpi_mode);
break;
case PCH_DEVFN_I2C0: /* I2C0 */
sio_index = SIO_ID_I2C0;
serialio_d21_ltr(bar0);
serialio_i2c_voltage_sel(bar0, config->sio_i2c0_voltage);
serialio_d21_mode(sio_index, SIO_PIN_INTC,
config->sio_acpi_mode);
break;
case PCH_DEVFN_I2C1: /* I2C1 */
sio_index = SIO_ID_I2C1;
serialio_d21_ltr(bar0);
serialio_i2c_voltage_sel(bar0, config->sio_i2c1_voltage);
serialio_d21_mode(sio_index, SIO_PIN_INTC,
config->sio_acpi_mode);
break;
case PCH_DEVFN_SPI0: /* SPI0 */
sio_index = SIO_ID_SPI0;
serialio_d21_ltr(bar0);
serialio_d21_mode(sio_index, SIO_PIN_INTC,
config->sio_acpi_mode);
break;
case PCH_DEVFN_SPI1: /* SPI1 */
sio_index = SIO_ID_SPI1;
serialio_d21_ltr(bar0);
serialio_d21_mode(sio_index, SIO_PIN_INTC,
config->sio_acpi_mode);
break;
case PCH_DEVFN_UART0: /* UART0 */
sio_index = SIO_ID_UART0;
if (!serialio_uart_is_debug(dev))
serialio_d21_ltr(bar0);
serialio_d21_mode(sio_index, SIO_PIN_INTD,
config->sio_acpi_mode);
break;
case PCH_DEVFN_UART1: /* UART1 */
sio_index = SIO_ID_UART1;
if (!serialio_uart_is_debug(dev))
serialio_d21_ltr(bar0);
serialio_d21_mode(sio_index, SIO_PIN_INTD,
config->sio_acpi_mode);
break;
case PCH_DEVFN_SDIO: /* SDIO */
sio_index = SIO_ID_SDIO;
serialio_d23_ltr(bar0);
serialio_d23_mode(config->sio_acpi_mode);
break;
default:
return;
}
if (config->sio_acpi_mode) {
global_nvs_t *gnvs;
/* Find ACPI NVS to update BARs */
gnvs = (global_nvs_t *)cbmem_find(CBMEM_ID_ACPI_GNVS);
if (!gnvs) {
printk(BIOS_ERR, "Unable to locate Global NVS\n");
return;
}
/* Save BAR0 and BAR1 to ACPI NVS */
gnvs->dev.bar0[sio_index] = (u32)bar0->base;
gnvs->dev.bar1[sio_index] = (u32)bar1->base;
/* Do not enable UART if it is used as debug port */
if (!serialio_uart_is_debug(dev))
gnvs->dev.enable[sio_index] = 1;
/* Put device in D3hot state via BAR1 */
if (dev->path.pci.devfn != PCH_DEVFN_SDMA)
serialio_enable_d3hot(bar1); /* all but SDMA */
}
}
static void serialio_set_resources(struct device *dev)
{
pci_dev_set_resources(dev);
#if CONFIG_INTEL_PCH_UART_CONSOLE
/* Update UART base address if used for debug */
if (serialio_uart_is_debug(dev)) {
struct resource *res = find_resource(dev, PCI_BASE_ADDRESS_0);
if (res)
uartmem_setbaseaddr(res->base);
}
#endif
}
static struct device_operations device_ops = {
.read_resources = &pci_dev_read_resources,
.set_resources = &serialio_set_resources,
.enable_resources = &pci_dev_enable_resources,
.init = &serialio_init,
.ops_pci = &broadwell_pci_ops,
};
static const unsigned short pci_device_ids[] = {
0x9c60, 0x9ce0, /* 0:15.0 - SDMA */
0x9c61, 0x9ce1, /* 0:15.1 - I2C0 */
0x9c62, 0x9ce2, /* 0:15.2 - I2C1 */
0x9c65, 0x9ce5, /* 0:15.3 - SPI0 */
0x9c66, 0x9ce6, /* 0:15.4 - SPI1 */
0x9c63, 0x9ce3, /* 0:15.5 - UART0 */
0x9c64, 0x9ce4, /* 0:15.6 - UART1 */
0x9c35, 0x9cb5, /* 0:17.0 - SDIO */
0
};
static const struct pci_driver pch_pcie __pci_driver = {
.ops = &device_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.devices = pci_device_ids,
};

View File

@@ -0,0 +1,113 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
*
* 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
*/
#include <arch/io.h>
#include <console/console.h>
#include <device/device.h>
#include <device/path.h>
#include <device/smbus.h>
#include <device/smbus_def.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <soc/iomap.h>
#include <soc/ramstage.h>
#include <soc/smbus.h>
static void pch_smbus_init(device_t dev)
{
struct resource *res;
u16 reg16;
/* Enable clock gating */
reg16 = pci_read_config32(dev, 0x80);
reg16 &= ~((1 << 8)|(1 << 10)|(1 << 12)|(1 << 14));
pci_write_config32(dev, 0x80, reg16);
/* Set Receive Slave Address */
res = find_resource(dev, PCI_BASE_ADDRESS_4);
if (res)
outb(SMBUS_SLAVE_ADDR, res->base + SMB_RCV_SLVA);
}
static int lsmbus_read_byte(device_t dev, u8 address)
{
u16 device;
struct resource *res;
struct bus *pbus;
device = dev->path.i2c.device;
pbus = get_pbus_smbus(dev);
res = find_resource(pbus->dev, PCI_BASE_ADDRESS_4);
return do_smbus_read_byte(res->base, device, address);
}
static int lsmbus_write_byte(device_t dev, u8 address, u8 data)
{
u16 device;
struct resource *res;
struct bus *pbus;
device = dev->path.i2c.device;
pbus = get_pbus_smbus(dev);
res = find_resource(pbus->dev, PCI_BASE_ADDRESS_4);
return do_smbus_write_byte(res->base, device, address, data);
}
static struct smbus_bus_operations lops_smbus_bus = {
.read_byte = lsmbus_read_byte,
.write_byte = lsmbus_write_byte,
};
static void smbus_read_resources(device_t dev)
{
struct resource *res = new_resource(dev, PCI_BASE_ADDRESS_4);
res->base = SMBUS_BASE_ADDRESS;
res->size = 32;
res->limit = res->base + res->size - 1;
res->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_RESERVE |
IORESOURCE_STORED | IORESOURCE_ASSIGNED;
/* Also add MMIO resource */
res = pci_get_resource(dev, PCI_BASE_ADDRESS_0);
}
static struct device_operations smbus_ops = {
.read_resources = &smbus_read_resources,
.set_resources = &pci_dev_set_resources,
.enable_resources = &pci_dev_enable_resources,
.scan_bus = &scan_static_bus,
.init = &pch_smbus_init,
.ops_smbus_bus = &lops_smbus_bus,
.ops_pci = &broadwell_pci_ops,
};
static const unsigned short pci_device_ids[] = {
0x9c22, /* LynxPoint */
0x9ca2, /* WildcatPoint */
0
};
static const struct pci_driver pch_smbus __pci_driver = {
.ops = &smbus_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.devices = pci_device_ids,
};

Some files were not shown because too many files have changed in this diff Show More