Braswell: Use Baytrail as Comparison Base

Add baytrail source for comparison with Braswell.

BRANCH=none
BUG=None
TEST=None

Change-Id: I5170addf41676d95a3daf070a32bcee085f8156d
Signed-off-by: Lee Leahy <leroy.p.leahy@intel.com>
Reviewed-on: http://review.coreboot.org/10117
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Lee Leahy 2015-05-05 15:07:29 -07:00 committed by Leroy P Leahy
parent b5ad827ee5
commit 77ff0b1a01
92 changed files with 14329 additions and 0 deletions

View File

@ -0,0 +1,245 @@
config SOC_INTEL_BRASWELL
bool
help
Bay Trail M/D part support.
if SOC_INTEL_BRASWELL
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 BACKUP_DEFAULT_SMM_REGION
select CACHE_MRC_SETTINGS
select CAR_MIGRATION
select COLLECT_TIMESTAMPS
select CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED
select SUPPORT_CPU_UCODE_IN_CBFS
select HAVE_SMI_HANDLER
select HAVE_HARD_RESET
select MMCONF_SUPPORT
select MMCONF_SUPPORT_DEFAULT
select RELOCATABLE_MODULES
select RELOCATABLE_RAMSTAGE
select PARALLEL_MP
select PCIEXP_ASPM
select PCIEXP_COMMON_CLOCK
select REG_SCRIPT
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_MONOTONIC_TIMER
select TSC_SYNC_MFENCE
select UDELAY_TSC
select SOC_INTEL_COMMON
config BOOTBLOCK_CPU_INIT
string
default "soc/intel/baytrail/bootblock/bootblock.c"
config MMCONF_BASE_ADDRESS
hex
default 0xe0000000
config MAX_CPUS
int
default 4
config CPU_ADDR_BITS
int
default 36
config SMM_TSEG_SIZE
hex
default 0x800000
config SMM_RESERVED_SIZE
hex
default 0x100000
config HAVE_MRC
bool "Add a Memory Reference Code binary"
default y
help
Select this option to add a blob containing
memory reference code.
Note: Without this binary coreboot will not work
if HAVE_MRC
config MRC_FILE
string "Intel memory refeference code path and filename"
default "3rdparty/northbridge/intel/sandybridge/systemagent-r6.bin"
help
The path and filename of the file to use as System Agent
binary. Note that this points to the sandybridge binary file
which is will not work, but it serves its purpose to do builds.
config MRC_BIN_ADDRESS
hex
default 0xfffa0000
config MRC_RMT
bool "Enable MRC RMT training + debug prints"
default n
endif # HAVE_MRC
# Cache As RAM region layout:
#
# +-------------+ DCACHE_RAM_BASE + DCACHE_RAM_SIZE + DCACHE_RAM_MRC_VAR_SIZE
# | MRC usage |
# | |
# +-------------+ DCACHE_RAM_BASE + DCACHE_RAM_SIZE
# | Stack |\
# | | | * DCACHE_RAM_ROMSTAGE_STACK_SIZE
# | v |/
# +-------------+
# | ^ |
# | | |
# | CAR Globals |
# +-------------+ DCACHE_RAM_BASE
#
# Note that the MRC binary is linked to assume the region marked as "MRC usage"
# starts at DCACHE_RAM_BASE + DCACHE_RAM_SIZE. If those values change then
# a new MRC binary needs to be produced with the updated start and size
# information.
config DCACHE_RAM_BASE
hex
default 0xfe000000
config DCACHE_RAM_SIZE
hex
default 0x8000
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 0x8000
help
The amount of cache-as-ram region required by the reference code.
config DCACHE_RAM_ROMSTAGE_STACK_SIZE
hex
default 0x800
help
The amount of anticipated stack usage from the data cache
during pre-RAM ROM stage execution.
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 baytrail 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 CBFS_SIZE
hex "Size of CBFS filesystem in ROM"
default 0x100000
help
On Bay Trail systems the firmware image has to store a lot 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 ENABLE_BUILTIN_COM1
bool "Enable builtin COM1 Serial Port"
default n
help
The PMC has a legacy COM1 serial port. Choose this option to
configure the pads and enable it. This serial port can be used for
the debug console.
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 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/mainboard/$(MAINBOARDDIR)/me.bin"
config HAVE_IFD_BIN
bool
default y
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/mainboard/$(MAINBOARDDIR)/descriptor.bin"
config HAVE_REFCODE_BLOB
depends on ARCH_X86
bool "An external reference code blob should be put into cbfs."
default n
help
The reference code blob will be placed into cbfs.
if HAVE_REFCODE_BLOB
config REFCODE_BLOB_FILE
string "Path and filename to reference code blob."
default "refcode.elf"
help
The path and filename to the file to be added to cbfs.
endif # HAVE_REFCODE_BLOB
endif

View File

@ -0,0 +1,107 @@
ifeq ($(CONFIG_SOC_INTEL_BRASWELL),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 += memmap.c
romstage-y += memmap.c
ramstage-y += tsc_freq.c
romstage-y += tsc_freq.c
smm-y += tsc_freq.c
ramstage-y += spi.c
smm-y += spi.c
ramstage-y += chip.c
ramstage-y += gfx.c
ramstage-y += iosf.c
romstage-y += iosf.c
smm-y += iosf.c
ramstage-y += northcluster.c
ramstage-y += ramstage.c
ramstage-y += gpio.c
romstage-y += reset.c
ramstage-y += reset.c
ramstage-y += cpu.c
ramstage-y += pmutil.c
smm-y += pmutil.c
smm-y += smihandler.c
ramstage-y += smm.c
ramstage-y += ehci.c
ramstage-y += xhci.c
ramstage-y += southcluster.c
ramstage-$(CONFIG_HAVE_REFCODE_BLOB) += refcode.c
ramstage-y += sata.c
ramstage-y += acpi.c
ramstage-y += lpe.c
ramstage-y += scc.c
ramstage-y += emmc.c
ramstage-y += lpss.c
ramstage-y += pcie.c
ramstage-y += sd.c
ramstage-y += dptf.c
ramstage-y += perf_power.c
ramstage-y += stage_cache.c
romstage-y += stage_cache.c
ramstage-$(CONFIG_ELOG) += elog.c
ramstage-y += hda.c
# Remove as ramstage gets fleshed out
ramstage-y += placeholders.c
CPPFLAGS_common += -Isrc/soc/intel/baytrail/include
# Run an intermediate step when producing coreboot.rom
# that adds additional components to the final firmware
# image outside of CBFS
INTERMEDIATE:=baytrail_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
baytrail_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
endif
# 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
PHONY += baytrail_add_me
endif

View File

@ -0,0 +1,511 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2013 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 <soc/acpi.h>
#include <soc/iomap.h>
#include <soc/irq.h>
#include <soc/msr.h>
#include <soc/pattrs.h>
#include <soc/pmc.h>
#include <ec/google/chromeec/ec.h>
#include <vendorcode/google/chromeos/gnvs.h>
#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, \
}
/* C-state map without S0ix */
static acpi_cstate_t cstate_map[] = {
{
/* C1 */
.ctype = 1, /* ACPI C1 */
.latency = 1,
.power = 1000,
.resource = MWAIT_RES(0, 0),
},
{
/* C6NS with no L2 shrink */
/* NOTE: this substate is above CPUID limit */
.ctype = 2, /* ACPI C2 */
.latency = 500,
.power = 10,
.resource = MWAIT_RES(5, 1),
},
{
/* C6FS with full L2 shrink */
.ctype = 3, /* ACPI C3 */
.latency = 1500, /* 1.5ms worst case */
.power = 1,
.resource = MWAIT_RES(5, 2),
}
};
void acpi_init_gnvs(global_nvs_t *gnvs)
{
/* Set unknown wake source */
gnvs->pm1i = -1;
/* CPU core count */
gnvs->pcnt = dev_count_cpu();
/* Top of Low Memory (start of resource allocation) */
gnvs->tolm = nc_read_top_of_low_memory();
#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
#endif
}
static int acpi_sci_irq(void)
{
u32 *actl = (u32 *)(ILB_BASE_ADDRESS + ACTL);
int scis;
static int sci_irq;
if (sci_irq)
return sci_irq;
/* Determine how SCI is routed. */
scis = read32(actl) & SCIS_MASK;
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;
}
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 + PM2A_CNT_BLK;
fadt->pm_tmr_blk = pmbase + PM1_TMR;
fadt->gpe0_blk = pmbase + GPE0_STS;
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 = 2 * (GPE0_EN - GPE0_STS);
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 + PM2A_CNT_BLK;
fadt->x_pm2_cnt_blk.addrh = 0x0;
fadt->x_pm_tmr_blk.space_id = 1;
fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
fadt->x_pm_tmr_blk.bit_offset = 0;
fadt->x_pm_tmr_blk.resv = 0;
fadt->x_pm_tmr_blk.addrl = pmbase + PM1_TMR;
fadt->x_pm_tmr_blk.addrh = 0x0;
fadt->x_gpe0_blk.space_id = 1;
fadt->x_gpe0_blk.bit_width = fadt->gpe0_blk_len * 8;
fadt->x_gpe0_blk.bit_offset = 0;
fadt->x_gpe0_blk.resv = 0;
fadt->x_gpe0_blk.addrl = pmbase + GPE0_STS;
fadt->x_gpe0_blk.addrh = 0x0;
fadt->x_gpe1_blk.space_id = 1;
fadt->x_gpe1_blk.bit_width = 0;
fadt->x_gpe1_blk.bit_offset = 0;
fadt->x_gpe1_blk.resv = 0;
fadt->x_gpe1_blk.addrl = 0x0;
fadt->x_gpe1_blk.addrh = 0x0;
}
static acpi_tstate_t baytrail_tss_table[] = {
{ 100, 1000, 0, 0x00, 0 },
{ 88, 875, 0, 0x1e, 0 },
{ 75, 750, 0, 0x1c, 0 },
{ 63, 625, 0, 0x1a, 0 },
{ 50, 500, 0, 0x18, 0 },
{ 38, 375, 0, 0x16, 0 },
{ 25, 250, 0, 0x14, 0 },
{ 13, 125, 0, 0x12, 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 NVS controlled T-state limit */
len += acpigen_write_TPC("\\TLVL");
/* Write TSS table for MSR access */
len += acpigen_write_TSS_package(
ARRAY_SIZE(baytrail_tss_table), baytrail_tss_table);
return len;
}
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 int generate_P_state_entries(int core, int cores_per_package)
{
int len, len_pss;
int ratio_min, ratio_max, ratio_turbo, ratio_step, ratio_range_2;
int coord_type, power_max, power_unit, num_entries;
int ratio, power, clock, clock_max;
int vid, vid_turbo, vid_min, vid_max, vid_range_2;
u32 control_status;
const struct pattrs *pattrs = pattrs_get();
msr_t msr;
/* Inputs from CPU attributes */
ratio_max = pattrs->iacore_ratios[IACORE_MAX];
ratio_min = pattrs->iacore_ratios[IACORE_LFM];
vid_max = pattrs->iacore_vids[IACORE_MAX];
vid_min = pattrs->iacore_vids[IACORE_LFM];
/* Set P-states coordination type based on MSR disable bit */
coord_type = (pattrs->num_cpus > 2) ? SW_ALL : HW_ALL;
/* Max Non-Turbo Frequency */
clock_max = (ratio_max * pattrs->bclk_khz) / 1000;
/* Calculate CPU TDP in mW */
msr = rdmsr(MSR_PKG_POWER_SKU_UNIT);
power_unit = 1 << (msr.lo & 0xf);
msr = rdmsr(MSR_PKG_POWER_LIMIT);
power_max = ((msr.lo & 0x7fff) / power_unit) * 1000;
/* Write _PCT indicating use of FFixedHW */
len = acpigen_write_empty_PCT();
/* Write _PPC with NVS specified limit on supported P-state */
len += acpigen_write_PPC_NVS();
/* Write PSD indicating configured coordination type */
len += acpigen_write_PSD_package(core, 1, coord_type);
/* Add P-state entries in _PSS table */
len += acpigen_write_name("_PSS");
/* Determine ratio points */
ratio_step = 1;
num_entries = (ratio_max - ratio_min) / ratio_step;
while (num_entries > 15) { /* ACPI max is 15 ratios */
ratio_step <<= 1;
num_entries >>= 1;
}
/* P[T] is Turbo state if enabled */
if (get_turbo_state() == TURBO_ENABLED) {
/* _PSS package count including Turbo */
len_pss = acpigen_write_package(num_entries + 2);
ratio_turbo = pattrs->iacore_ratios[IACORE_TURBO];
vid_turbo = pattrs->iacore_vids[IACORE_TURBO];
control_status = (ratio_turbo << 8) | vid_turbo;
/* Add entry for Turbo ratio */
len_pss += acpigen_write_PSS_package(
clock_max + 1, /*MHz*/
power_max, /*mW*/
10, /*lat1*/
10, /*lat2*/
control_status, /*control*/
control_status); /*status*/
} else {
/* _PSS package count without Turbo */
len_pss = acpigen_write_package(num_entries + 1);
ratio_turbo = ratio_max;
vid_turbo = vid_max;
}
/* First regular entry is max non-turbo ratio */
control_status = (ratio_max << 8) | vid_max;
len_pss += acpigen_write_PSS_package(
clock_max, /*MHz*/
power_max, /*mW*/
10, /*lat1*/
10, /*lat2*/
control_status, /*control */
control_status); /*status*/
/* Set up ratio and vid ranges for VID calculation */
ratio_range_2 = (ratio_turbo - ratio_min) * 2;
vid_range_2 = (vid_turbo - vid_min) * 2;
/* Generate the remaining entries */
for (ratio = ratio_min + ((num_entries - 1) * ratio_step);
ratio >= ratio_min; ratio -= ratio_step) {
/* Calculate VID for this ratio */
vid = ((ratio - ratio_min) * vid_range_2) /
ratio_range_2 + vid_min;
/* Round up if remainder */
if (((ratio - ratio_min) * vid_range_2) % ratio_range_2)
vid++;
/* Calculate power at this ratio */
power = calculate_power(power_max, ratio_max, ratio);
clock = (ratio * pattrs->bclk_khz) / 1000;
control_status = (ratio << 8) | (vid & 0xff);
len_pss += acpigen_write_PSS_package(
clock, /*MHz*/
power, /*mW*/
10, /*lat1*/
10, /*lat2*/
control_status, /*control*/
control_status); /*status*/
}
/* Fix package length */
len_pss--;
acpigen_patch_len(len_pss);
return len + len_pss;
}
void generate_cpu_entries(void)
{
int len_pr, core;
int pcontrol_blk = get_pmbase(), plen = 6;
const struct pattrs *pattrs = pattrs_get();
for (core=0; core<pattrs->num_cpus; core++) {
if (core > 0) {
pcontrol_blk = 0;
plen = 0;
}
/* Generate processor \_PR.CPUx */
len_pr = acpigen_write_processor(
core, pcontrol_blk, plen);
/* Generate P-state tables */
len_pr += generate_P_state_entries(
core, pattrs->num_cpus);
/* Generate C-state tables */
len_pr += acpigen_write_CST_package(
cstate_map, ARRAY_SIZE(cstate_map));
/* Generate T-state tables */
len_pr += generate_T_state_entries(
core, pattrs->num_cpus);
len_pr--;
acpigen_patch_len(len_pr);
}
}
unsigned long acpi_madt_irq_overrides(unsigned long current)
{
int sci_irq = acpi_sci_irq();
acpi_madt_irqoverride_t *irqovr;
uint16_t sci_flags = MP_IRQ_TRIGGER_LEVEL;
/* INT_SRC_OVR */
irqovr = (void *)current;
current += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0);
if (sci_irq >= 20)
sci_flags |= MP_IRQ_POLARITY_LOW;
else
sci_flags |= MP_IRQ_POLARITY_HIGH;
irqovr = (void *)current;
current += acpi_create_madt_irqoverride(irqovr, 0, sci_irq, sci_irq,
sci_flags);
return current;
}

View File

@ -0,0 +1,77 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2011 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)
/* 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
}
}
/* 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
}
}
/* 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
}
}
/* Return a package containing enabled processor entries */
Method (PPKG)
{
If (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,87 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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, // SDMA Enable
S1EN, 8, // I2C1 Enable
S2EN, 8, // I2C2 Enable
S3EN, 8, // I2C3 Enable
S4EN, 8, // I2C4 Enable
S5EN, 8, // I2C5 Enable
S6EN, 8, // I2C6 Enable
S7EN, 8, // I2C7 Enable
S8EN, 8, // SDMA2 Enable
S9EN, 8, // SPI Enable
SAEN, 8, // PWM1 Enable
SBEN, 8, // PWM2 Enable
SCEN, 8, // UART2 Enable
SDEN, 8, // UART2 Enable
C0EN, 8, // MMC Enable
C1EN, 8, // SDIO Enable
C2EN, 8, // SD Card Enable
LPEN, 8, // LPE Enable
/* BAR 0 */
S0B0, 32, // SDMA BAR0
S1B0, 32, // I2C1 BAR0
S2B0, 32, // I2C2 BAR0
S3B0, 32, // I2C3 BAR0
S4B0, 32, // I2C4 BAR0
S5B0, 32, // I2C5 BAR0
S6B0, 32, // I2C6 BAR0
S7B0, 32, // I2C7 BAR0
S8B0, 32, // SDMA2 BAR0
S9B0, 32, // SPI BAR0
SAB0, 32, // PWM1 BAR0
SBB0, 32, // PWM2 BAR0
SCB0, 32, // UART1 BAR0
SDB0, 32, // UART2 BAR0
C0B0, 32, // MMC BAR0
C1B0, 32, // SDIO BAR0
C2B0, 32, // SD Card BAR0
LPB0, 32, // LPE BAR0
/* BAR 1 */
S0B1, 32, // SDMA BAR1
S1B1, 32, // I2C1 BAR1
S2B1, 32, // I2C2 BAR1
S3B1, 32, // I2C3 BAR1
S4B1, 32, // I2C4 BAR1
S5B1, 32, // I2C5 BAR1
S6B1, 32, // I2C6 BAR1
S7B1, 32, // I2C7 BAR1
S8B1, 32, // SDMA2 BAR1
S9B1, 32, // SPI BAR1
SAB1, 32, // PWM1 BAR1
SBB1, 32, // PWM2 BAR1
SCB1, 32, // UART1 BAR1
SDB1, 32, // UART2 BAR1
C0B1, 32, // MMC BAR1
C1B1, 32, // SDIO BAR1
C2B1, 32, // SD Card BAR1
LPB1, 32, // LPE BAR1
/* Extra */
LPFW, 32, // LPE BAR2 Firmware

View File

@ -0,0 +1,59 @@
Device (TCHG)
{
Name (_HID, "INT3403")
Name (_UID, 0)
Name (PTYP, 0x0B)
Name (_STR, Unicode("Battery Charger"))
Method (_STA)
{
If (LEqual (\DPTE, One)) {
Return (0xF)
} Else {
Return (0x0)
}
}
/* Return charger performance states defined by mainboard */
Method (PPSS)
{
Return (\_SB.CHPS)
}
/* Return maximum charger current limit */
Method (PPPC)
{
/* Convert size of PPSS table to index */
Store (SizeOf (\_SB.CHPS), Local0)
Decrement (Local0)
/* Check if charging is disabled (AC removed) */
If (LEqual (\PWRS, Zero)) {
/* Return last power state */
Return (Local0)
} Else {
/* Return highest power state */
Return (0)
}
Return (0)
}
/* Set charger current limit */
Method (SPPC, 1)
{
/* Retrieve Control (index 4) for specified PPSS level */
Store (DeRefOf (Index (DeRefOf (Index
(\_SB.CHPS, ToInteger (Arg0))), 4)), Local0)
/* Pass Control value to EC to limit charging */
\_SB.PCI0.LPCB.EC0.CHGS (Local0)
}
/* Initialize charger participant */
Method (INIT)
{
/* Disable charge limit */
\_SB.PCI0.LPCB.EC0.CHGD ()
}
}

View File

@ -0,0 +1,144 @@
External (\_PR.CP00._TSS, MethodObj)
External (\_PR.CP00._TPC, MethodObj)
External (\_PR.CP00._PTC, PkgObj)
External (\_PR.CP00._TSD, PkgObj)
External (\_PR.CP00._PSS, MethodObj)
Device (TCPU)
{
Name (_HID, EISAID ("INT3401"))
Name (_UID, 0)
Method (_STA)
{
If (LEqual (\DPTE, One)) {
Return (0xF)
} Else {
Return (0x0)
}
}
/*
* Processor Throttling Controls
*/
Method (_TSS)
{
If (CondRefOf (\_PR.CP00._TSS)) {
Return (\_PR.CP00._TSS)
} Else {
Return (Package ()
{
Package () { 0, 0, 0, 0, 0 }
})
}
}
Method (_TPC)
{
If (CondRefOf (\_PR.CP00._TPC)) {
Return (\_PR.CP00._TPC)
} Else {
Return (0)
}
}
Method (_PTC)
{
If (CondRefOf (\_PR.CP00._PTC)) {
Return (\_PR.CP00._PTC)
} Else {
Return (Package ()
{
Buffer () { 0 },
Buffer () { 0 }
})
}
}
Method (_TSD)
{
If (CondRefOf (\_PR.CP00._TSD)) {
Return (\_PR.CP00._TSD)
} Else {
Return (Package ()
{
Package () { 5, 0, 0, 0, 0 }
})
}
}
Method (_TDL)
{
If (CondRefOf (\_PR.CP00._TSS)) {
Store (SizeOf (\_PR.CP00._TSS ()), Local0)
Decrement (Local0)
Return (Local0)
} Else {
Return (0)
}
}
/*
* Processor Performance Control
*/
Method (_PPC)
{
Return (0)
}
Method (SPPC, 1)
{
Store (Arg0, \PPCM)
/* Notify OS to re-read _PPC limit on each CPU */
\PPCN ()
}
Method (_PSS)
{
If (CondRefOf (\_PR.CP00._PSS)) {
Return (\_PR.CP00._PSS)
} Else {
Return (Package ()
{
Package () { 0, 0, 0, 0, 0, 0 }
})
}
}
Method (_PDL)
{
/* Check for mainboard specific _PDL override */
If (CondRefOf (\_SB.MPDL)) {
Return (\_SB.MPDL)
} ElseIf (CondRefOf (\_PR.CP00._PSS)) {
Store (SizeOf (\_PR.CP00._PSS ()), Local0)
Decrement (Local0)
Return (Local0)
} Else {
Return (0)
}
}
/* Return PPCC table defined by mainboard */
Method (PPCC)
{
Return (\_SB.MPPC)
}
#ifdef DPTF_CPU_CRITICAL
Method (_CRT)
{
Return (^^CTOK (DPTF_CPU_CRITICAL))
}
#endif
#ifdef DPTF_CPU_PASSIVE
Method (_PSV)
{
Return (^^CTOK (DPTF_CPU_PASSIVE))
}
#endif
}

View File

@ -0,0 +1,78 @@
Device (DPTF)
{
Name (_HID, EISAID ("INT3400"))
Name (_UID, 0)
Name (IDSP, Package()
{
/* DPPM Passive Policy 1.0 */
ToUUID ("42A441D6-AE6A-462B-A84B-4A8CE79027D3"),
/* DPPM Critical Policy */
ToUUID ("97C68AE7-15FA-499c-B8C9-5DA81D606E0A"),
/* DPPM Cooling Policy */
ToUUID ("16CAF1B7-DD38-40ED-B1C1-1B8A1913D531"),
})
Method (_STA)
{
If (LEqual (\DPTE, One)) {
Return (0xF)
} Else {
Return (0x0)
}
}
/* Arg0: Buffer containing UUID
* Arg1: Integer containing Revision ID of buffer format
* Arg2: Integer containing count of entries in Arg3
* Arg3: Buffer containing list of DWORD capabilities
* Return: Buffer containing list of DWORD capabilities
*/
Method (_OSC, 4, Serialized)
{
/* Check for Passive Policy UUID */
If (LEqual (DeRefOf (Index (IDSP, 0)), Arg0)) {
/* Initialize Thermal Devices */
^TINI ()
#ifdef DPTF_ENABLE_CHARGER
/* Initialize Charger Device */
^TCHG.INIT ()
#endif
}
Return (Arg3)
}
/* Priority based _TRT */
Name (TRTR, 1)
Method (_TRT)
{
Return (\_SB.DTRT)
}
/* Convert from Degrees C to 1/10 Kelvin for ACPI */
Method (CTOK, 1) {
/* 10th of Degrees C */
Multiply (Arg0, 10, Local0)
/* Convert to Kelvin */
Add (Local0, 2732, Local0)
Return (Local0)
}
/* Include CPU Participant */
#include "cpu.asl"
/* Include Thermal Participants */
#include "thermal.asl"
#ifdef DPTF_ENABLE_CHARGER
/* Include Charger Participant */
#include "charger.asl"
#endif
}

View File

@ -0,0 +1,203 @@
/* Thermal Threshold Event Handler */
Method (TEVT, 1, NotSerialized)
{
Store (ToInteger (Arg0), Local0)
#ifdef DPTF_TSR0_SENSOR_ID
If (LEqual (Local0, DPTF_TSR0_SENSOR_ID)) {
Notify (^TSR0, 0x90)
}
#endif
#ifdef DPTF_TSR1_SENSOR_ID
If (LEqual (Local0, DPTF_TSR1_SENSOR_ID)) {
Notify (^TSR1, 0x90)
}
#endif
#ifdef DPTF_TSR2_SENSOR_ID
If (LEqual (Local0, DPTF_TSR2_SENSOR_ID)) {
Notify (^TSR2, 0x90)
}
#endif
}
/* Thermal device initialization - Disable Aux Trip Points */
Method (TINI)
{
#ifdef DPTF_TSR0_SENSOR_ID
^TSR0.PATD ()
#endif
#ifdef DPTF_TSR1_SENSOR_ID
^TSR1.PATD ()
#endif
#ifdef DPTF_TSR2_SENSOR_ID
^TSR2.PATD ()
#endif
}
#ifdef DPTF_TSR0_SENSOR_ID
Device (TSR0)
{
Name (_HID, EISAID ("INT3403"))
Name (_UID, 1)
Name (PTYP, 0x03)
Name (TMPI, DPTF_TSR0_SENSOR_ID)
Name (_STR, Unicode (DPTF_TSR0_SENSOR_NAME))
Name (GTSH, 20) /* 2 degree hysteresis */
Method (_STA)
{
If (LEqual (\DPTE, One)) {
Return (0xF)
} Else {
Return (0x0)
}
}
Method (_TMP, 0, Serialized)
{
Return (\_SB.PCI0.LPCB.EC0.TSRD (TMPI))
}
Method (_PSV)
{
Return (^^CTOK (DPTF_TSR0_PASSIVE))
}
Method (_CRT)
{
Return (^^CTOK (DPTF_TSR0_CRITICAL))
}
Name (PATC, 2)
/* Set Aux Trip Point */
Method (PAT0, 1, Serialized)
{
\_SB.PCI0.LPCB.EC0.PAT0 (TMPI, Arg0)
}
/* Set Aux Trip Point */
Method (PAT1, 1, Serialized)
{
\_SB.PCI0.LPCB.EC0.PAT1 (TMPI, Arg0)
}
/* Disable Aux Trip Point */
Method (PATD, 0, Serialized)
{
\_SB.PCI0.LPCB.EC0.PATD (TMPI)
}
}
#endif
#ifdef DPTF_TSR1_SENSOR_ID
Device (TSR1)
{
Name (_HID, EISAID ("INT3403"))
Name (_UID, 2)
Name (PTYP, 0x03)
Name (TMPI, DPTF_TSR1_SENSOR_ID)
Name (_STR, Unicode (DPTF_TSR1_SENSOR_NAME))
Name (GTSH, 20) /* 2 degree hysteresis */
Method (_STA)
{
If (LEqual (\DPTE, One)) {
Return (0xF)
} Else {
Return (0x0)
}
}
Method (_TMP, 0, Serialized)
{
Return (\_SB.PCI0.LPCB.EC0.TSRD (TMPI))
}
Method (_PSV)
{
Return (^^CTOK (DPTF_TSR1_PASSIVE))
}
Method (_CRT)
{
Return (^^CTOK (DPTF_TSR1_CRITICAL))
}
Name (PATC, 2)
/* Set Aux Trip Point */
Method (PAT0, 1, Serialized)
{
\_SB.PCI0.LPCB.EC0.PAT0 (TMPI, Arg0)
}
/* Set Aux Trip Point */
Method (PAT1, 1, Serialized)
{
\_SB.PCI0.LPCB.EC0.PAT1 (TMPI, Arg0)
}
/* Disable Aux Trip Point */
Method (PATD, 0, Serialized)
{
\_SB.PCI0.LPCB.EC0.PATD (TMPI)
}
}
#endif
#ifdef DPTF_TSR2_SENSOR_ID
Device (TSR2)
{
Name (_HID, EISAID ("INT3403"))
Name (_UID, 3)
Name (PTYP, 0x03)
Name (TMPI, DPTF_TSR2_SENSOR_ID)
Name (_STR, Unicode (DPTF_TSR2_SENSOR_NAME))
Name (GTSH, 20) /* 2 degree hysteresis */
Method (_STA)
{
If (LEqual (\DPTE, One)) {
Return (0xF)
} Else {
Return (0x0)
}
}
Method (_TMP, 0, Serialized)
{
Return (\_SB.PCI0.LPCB.EC0.TSRD (TMPI))
}
Method (_PSV)
{
Return (^^CTOK (DPTF_TSR2_PASSIVE))
}
Method (_CRT)
{
Return (^^CTOK (DPTF_TSR2_CRITICAL))
}
Name (PATC, 2)
/* Set Aux Trip Point */
Method (PAT0, 1, Serialized)
{
\_SB.PCI0.LPCB.EC0.PAT0 (TMPI, Arg0)
}
/* Set Aux Trip Point */
Method (PAT1, 1, Serialized)
{
\_SB.PCI0.LPCB.EC0.PAT1 (TMPI, Arg0)
}
/* Disable Aux Trip Point */
Method (PATD, 0, Serialized)
{
\_SB.PCI0.LPCB.EC0.PATD (TMPI)
}
}
#endif

View File

@ -0,0 +1,108 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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.
*/
OperationRegion (GNVS, SystemMemory, 0xC0DEBABE, 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
P80D, 32, // 0x0b - Debug port (IO 0x80) value
LIDS, 8, // 0x0f - LID state (open = 1)
PWRS, 8, // 0x10 - Power State (AC = 1)
PCNT, 8, // 0x11 - Processor count
TPMP, 8, // 0x12 - TPM Present and Enabled
TLVL, 8, // 0x13 - Throttle Level
PPCM, 8, // 0x14 - Maximum P-state usable by OS
PM1I, 32, // 0x15 - System Wake Source - PM1 Index
/* Device Config */
Offset (0x20),
S5U0, 8, // 0x20 - Enable USB0 in S5
S5U1, 8, // 0x21 - Enable USB1 in S5
S3U0, 8, // 0x22 - Enable USB0 in S3
S3U1, 8, // 0x23 - Enable USB1 in S3
TACT, 8, // 0x24 - Thermal Active trip point
TPSV, 8, // 0x25 - Thermal Passive trip point
TCRT, 8, // 0x26 - Thermal Critical trip point
DPTE, 8, // 0x27 - Enable DPTF
/* Base addresses */
Offset (0x30),
CMEM, 32, // 0x30 - CBMEM TOC
TOLM, 32, // 0x34 - Top of Low Memory
CBMC, 32, // 0x38 - coreboot mem console pointer
/* ChromeOS specific */
Offset (0x100),
#include <vendorcode/google/chromeos/acpi/gnvs.asl>
Offset (0x1000),
#include <soc/intel/baytrail/acpi/device_nvs.asl>
}
/* Set flag to enable USB charging in S3 */
Method (S3UE)
{
Store (One, \S3U0)
Store (One, \S3U1)
}
/* Set flag to disable USB charging in S3 */
Method (S3UD)
{
Store (Zero, \S3U0)
Store (Zero, \S3U1)
}
/* Set flag to enable USB charging in S5 */
Method (S5UE)
{
Store (One, \S5U0)
Store (One, \S5U1)
}
/* Set flag to disable USB charging in S5 */
Method (S5UD)
{
Store (Zero, \S5U0)
Store (Zero, \S5U1)
}

View File

@ -0,0 +1,110 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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>
#include <soc/irq.h>
/* SouthCluster GPIO */
Device (GPSC)
{
Name (_HID, "INT33FC")
Name (_CID, "INT33FC")
Name (_UID, 1)
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, RMEM)
Interrupt (ResourceConsumer, Level, ActiveLow, Shared,,,)
{
GPIO_SC_IRQ
}
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^RMEM._BAS, RBAS)
Add (IO_BASE_ADDRESS, IO_BASE_OFFSET_GPSCORE, RBAS)
Return (^RBUF)
}
Method (_STA)
{
Return (0xF)
}
}
/* NorthCluster GPIO */
Device (GPNC)
{
Name (_HID, "INT33FC")
Name (_CID, "INT33FC")
Name (_UID, 2)
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, RMEM)
Interrupt (ResourceConsumer, Level, ActiveLow, Shared,,,)
{
GPIO_NC_IRQ
}
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^RMEM._BAS, RBAS)
Add (IO_BASE_ADDRESS, IO_BASE_OFFSET_GPNCORE, RBAS)
Return (^RBUF)
}
Method (_STA)
{
Return (0xF)
}
}
/* SUS GPIO */
Device (GPSS)
{
Name (_HID, "INT33FC")
Name (_CID, "INT33FC")
Name (_UID, 3)
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, RMEM)
Interrupt (ResourceConsumer, Level, ActiveLow, Shared,,,)
{
GPIO_SUS_IRQ
}
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^RMEM._BAS, RBAS)
Add (IO_BASE_ADDRESS, IO_BASE_OFFSET_GPSSUS, RBAS)
Return (^RBUF)
}
Method (_STA)
{
Return (0xF)
}
}

View File

@ -0,0 +1,48 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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
*/
#undef PCI_DEV_PIRQ_ROUTES
#undef ACPI_DEV_APIC_IRQ
#undef PCI_DEV_PIRQ_ROUTE
#undef PIRQ_PIC_ROUTES
#undef PIRQ_PIC
#if defined(PIC_MODE)
#define ACPI_DEV_APIC_IRQ(dev_, pin_, pin_name_) \
Package() { ## dev_ ## ffff, pin_, \_SB.PCI0.LPCB.LNK ## pin_name_, 0 }
#else /* defined(PIC_MODE) */
#define ACPI_DEV_APIC_IRQ(dev_, pin_, pin_name_) \
Package() { ## dev_ ## ffff, pin_, 0, PIRQ ## pin_name_ ## _APIC_IRQ }
#endif
#define PCI_DEV_PIRQ_ROUTE(dev_, a_, b_, c_, d_) \
ACPI_DEV_APIC_IRQ(dev_, 0, a_), \
ACPI_DEV_APIC_IRQ(dev_, 1, b_), \
ACPI_DEV_APIC_IRQ(dev_, 2, c_), \
ACPI_DEV_APIC_IRQ(dev_, 3, d_)
/* Empty PIRQ_PIC definition. */
#define PIRQ_PIC(pirq_, pic_irq_)
/* Include the mainboard irq route definition. */
#include "irqroute.h"

View File

@ -0,0 +1,492 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
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,37 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2013 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
*/
// PCI Interrupt Routing
Method(_PRT)
{
If (PICM) {
Return (Package() {
#undef PIC_MODE
#include <soc/intel/baytrail/acpi/irq_helper.h>
PCI_DEV_PIRQ_ROUTES
})
} Else {
Return (Package() {
#define PIC_MODE
#include <soc/intel/baytrail/acpi/irq_helper.h>
PCI_DEV_PIRQ_ROUTES
})
}
}

View File

@ -0,0 +1,167 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2013 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)
#include "irqlinks.asl"
#include "acpi/ec.asl"
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)
Method (_STA, 0) // Device Status
{
Return (0xf) // Enable and show device
}
Name(_CRS, ResourceTemplate()
{
Memory32Fixed(ReadOnly, 0xfed00000, 0x400)
})
}
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(LDRC) // LPC device: Resource consumption
{
Name (_HID, EISAID("PNP0C02"))
Name (_UID, 2)
Name (RBUF, ResourceTemplate()
{
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
})
Method (_CRS, 0, NotSerialized)
{
Return (RBUF)
}
}
Device (RTC) // Real Time Clock
{
Name (_HID, EISAID("PNP0B00"))
Name (_CRS, ResourceTemplate()
{
IO (Decode16, 0x70, 0x70, 1, 8)
// Disable as Windows doesn't like it, and systems don't seem to use it.
// 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 mainboard's superio.asl file.
#include "acpi/superio.asl"
#ifdef ENABLE_TPM
Device (TPM) // Trusted Platform Module
{
Name(_HID, EISAID("IFX0102"))
Name(_CID, 0x310cd041)
Name(_UID, 1)
Method(_STA, 0)
{
If (TPMP) {
Return (0xf)
}
Return (0x0)
}
Name(_CRS, ResourceTemplate() {
IO (Decode16, 0x2e, 0x2e, 0x01, 0x02)
IO (Decode16, 0x6f0, 0x6f0, 0x01, 0x10)
Memory32Fixed (ReadWrite, 0xfed40000, 0x5000)
IRQ (Edge, Activehigh, Exclusive) { 6 }
})
}
#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
*/
Device (LPEA)
{
Name (_HID, "80860F28")
Name (_CID, "80860F28")
Name (_UID, 1)
Name (_DDN, "Low Power Audio Controller")
Name (_PR0, Package () { PLPE })
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x00200000, BAR0)
Memory32Fixed (ReadWrite, 0, 0x00001000, BAR1)
Memory32Fixed (ReadWrite, 0, 0x00100000, BAR2)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
LPE_DMA0_IRQ
}
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
LPE_DMA1_IRQ
}
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
LPE_SSP0_IRQ
}
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
LPE_SSP1_IRQ
}
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
LPE_SSP2_IRQ
}
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
LPE_IPC2HOST_IRQ
}
})
Method (_CRS)
{
/* Update BAR0 from NVS */
CreateDwordField (^RBUF, ^BAR0._BAS, BAS0)
Store (\LPB0, BAS0)
/* Update BAR1 from NVS */
CreateDwordField (^RBUF, ^BAR1._BAS, BAS1)
Store (\LPB1, BAS1)
/* Update LPE FW from NVS */
CreateDwordField (^RBUF, ^BAR2._BAS, BAS2)
Store (\LPFW, BAS2)
/* Append any Mainboard defined GPIOs */
If (CondRefOf (^GBUF, Local0)) {
ConcatenateResTemplate (^RBUF, ^GBUF, Local1)
Return (Local1)
}
Return (^RBUF)
}
Method (_STA)
{
If (LEqual (\LPEN, 1)) {
Return (0xF)
} Else {
Return (0x0)
}
}
OperationRegion (KEYS, SystemMemory, LPB1, 0x100)
Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
{
Offset (0x84),
PSAT, 32,
}
PowerResource (PLPE, 0, 0)
{
Method (_STA)
{
Return (1)
}
Method (_OFF)
{
Or (PSAT, 0x00000003, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
Method (_ON)
{
And (PSAT, 0xfffffffc, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
}
}

View File

@ -0,0 +1,712 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 (SDM1)
{
Name (_HID, "INTL9C60")
Name (_UID, 1)
Name (_DDN, "DMA Controller #1")
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
LPSS_DMA1_IRQ
}
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
Store (\S0B0, RBAS)
Return (^RBUF)
}
Method (_STA)
{
If (LEqual (\S0EN, 1)) {
Return (0xF)
} Else {
Return (0x0)
}
}
}
Device (SDM2)
{
Name (_HID, "INTL9C60")
Name (_UID, 2)
Name (_DDN, "DMA Controller #2")
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
LPSS_DMA2_IRQ
}
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
Store (\S8B0, RBAS)
Return (^RBUF)
}
Method (_STA)
{
If (LEqual (\S8EN, 1)) {
Return (0xF)
} Else {
Return (0x0)
}
}
}
Device (I2C1)
{
Name (_HID, "80860F41")
Name (_UID, 1)
Name (_DDN, "I2C Controller #1")
/* Standard Mode: HCNT, LCNT, SDA Hold Time */
Name (SSCN, Package () { 0x200, 0x200, 0x6 })
/* Fast Mode: HCNT, LCNT, SDA Hold Time */
Name (FMCN, Package () { 0x55, 0x99, 0x6 })
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
LPSS_I2C1_IRQ
}
FixedDMA (0x10, 0x0, Width32Bit, )
FixedDMA (0x11, 0x1, Width32Bit, )
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
Store (\S1B0, RBAS)
Return (^RBUF)
}
Method (_STA)
{
If (LEqual (\S1EN, 1)) {
Return (0xF)
} Else {
Return (0x0)
}
}
OperationRegion (KEYS, SystemMemory, S1B1, 0x100)
Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
{
Offset (0x84),
PSAT, 32,
}
Method (_PS3)
{
Or (PSAT, 0x00000003, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
Method (_PS0)
{
And (PSAT, 0xfffffffc, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
}
Device (I2C2)
{
Name (_HID, "80860F41")
Name (_UID, 2)
Name (_DDN, "I2C Controller #2")
/* Standard Mode: HCNT, LCNT, SDA Hold Time */
Name (SSCN, Package () { 0x200, 0x200, 0x6 })
/* Fast Mode: HCNT, LCNT, SDA Hold Time */
Name (FMCN, Package () { 0x55, 0x99, 0x6 })
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
LPSS_I2C2_IRQ
}
FixedDMA (0x10, 0x0, Width32Bit, )
FixedDMA (0x11, 0x1, Width32Bit, )
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
Store (\S2B0, RBAS)
Return (^RBUF)
}
Method (_STA)
{
If (LEqual (\S2EN, 1)) {
Return (0xF)
} Else {
Return (0x0)
}
}
OperationRegion (KEYS, SystemMemory, S2B1, 0x100)
Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
{
Offset (0x84),
PSAT, 32,
}
Method (_PS3)
{
Or (PSAT, 0x00000003, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
Method (_PS0)
{
And (PSAT, 0xfffffffc, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
}
Device (I2C3)
{
Name (_HID, "80860F41")
Name (_UID, 3)
Name (_DDN, "I2C Controller #3")
/* Standard Mode: HCNT, LCNT, SDA Hold Time */
Name (SSCN, Package () { 0x200, 0x200, 0x6 })
/* Fast Mode: HCNT, LCNT, SDA Hold Time */
Name (FMCN, Package () { 0x55, 0x99, 0x6 })
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
LPSS_I2C3_IRQ
}
FixedDMA (0x10, 0x0, Width32Bit, )
FixedDMA (0x11, 0x1, Width32Bit, )
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
Store (\S3B0, RBAS)
Return (^RBUF)
}
Method (_STA)
{
If (LEqual (\S3EN, 1)) {
Return (0xF)
} Else {
Return (0x0)
}
}
OperationRegion (KEYS, SystemMemory, S3B1, 0x100)
Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
{
Offset (0x84),
PSAT, 32,
}
Method (_PS3)
{
Or (PSAT, 0x00000003, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
Method (_PS0)
{
And (PSAT, 0xfffffffc, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
}
Device (I2C4)
{
Name (_HID, "80860F41")
Name (_UID, 4)
Name (_DDN, "I2C Controller #4")
/* Standard Mode: HCNT, LCNT, SDA Hold Time */
Name (SSCN, Package () { 0x200, 0x200, 0x6 })
/* Fast Mode: HCNT, LCNT, SDA Hold Time */
Name (FMCN, Package () { 0x55, 0x99, 0x6 })
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
LPSS_I2C4_IRQ
}
FixedDMA (0x10, 0x0, Width32Bit, )
FixedDMA (0x11, 0x1, Width32Bit, )
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
Store (\S4B0, RBAS)
Return (^RBUF)
}
Method (_STA)
{
If (LEqual (\S4EN, 1)) {
Return (0xF)
} Else {
Return (0x0)
}
}
OperationRegion (KEYS, SystemMemory, S4B1, 0x100)
Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
{
Offset (0x84),
PSAT, 32,
}
Method (_PS3)
{
Or (PSAT, 0x00000003, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
Method (_PS0)
{
And (PSAT, 0xfffffffc, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
}
Device (I2C5)
{
Name (_HID, "80860F41")
Name (_UID, 5)
Name (_DDN, "I2C Controller #5")
/* Standard Mode: HCNT, LCNT, SDA Hold Time */
Name (SSCN, Package () { 0x200, 0x200, 0x6 })
/* Fast Mode: HCNT, LCNT, SDA Hold Time */
Name (FMCN, Package () { 0x55, 0x99, 0x6 })
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
LPSS_I2C5_IRQ
}
FixedDMA (0x10, 0x0, Width32Bit, )
FixedDMA (0x11, 0x1, Width32Bit, )
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
Store (\S5B0, RBAS)
Return (^RBUF)
}
Method (_STA)
{
If (LEqual (\S5EN, 1)) {
Return (0xF)
} Else {
Return (0x0)
}
}
OperationRegion (KEYS, SystemMemory, S5B1, 0x100)
Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
{
Offset (0x84),
PSAT, 32,
}
Method (_PS3)
{
Or (PSAT, 0x00000003, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
Method (_PS0)
{
And (PSAT, 0xfffffffc, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
}
Device (I2C6)
{
Name (_HID, "80860F41")
Name (_UID, 6)
Name (_DDN, "I2C Controller #6")
/* Standard Mode: HCNT, LCNT, SDA Hold Time */
Name (SSCN, Package () { 0x200, 0x200, 0x6 })
/* Fast Mode: HCNT, LCNT, SDA Hold Time */
Name (FMCN, Package () { 0x55, 0x99, 0x6 })
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
LPSS_I2C6_IRQ
}
FixedDMA (0x10, 0x0, Width32Bit, )
FixedDMA (0x11, 0x1, Width32Bit, )
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
Store (\S6B0, RBAS)
Return (^RBUF)
}
Method (_STA)
{
If (LEqual (\S6EN, 1)) {
Return (0xF)
} Else {
Return (0x0)
}
}
OperationRegion (KEYS, SystemMemory, S6B1, 0x100)
Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
{
Offset (0x84),
PSAT, 32,
}
Method (_PS3)
{
Or (PSAT, 0x00000003, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
Method (_PS0)
{
And (PSAT, 0xfffffffc, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
}
Device (I2C7)
{
Name (_HID, "80860F41")
Name (_UID, 7)
Name (_DDN, "I2C Controller #7")
/* Standard Mode: HCNT, LCNT, SDA Hold Time */
Name (SSCN, Package () { 0x200, 0x200, 0x6 })
/* Fast Mode: HCNT, LCNT, SDA Hold Time */
Name (FMCN, Package () { 0x55, 0x99, 0x6 })
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
LPSS_I2C7_IRQ
}
FixedDMA (0x10, 0x0, Width32Bit, )
FixedDMA (0x11, 0x1, Width32Bit, )
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
Store (\S7B0, RBAS)
Return (^RBUF)
}
Method (_STA)
{
If (LEqual (\S7EN, 1)) {
Return (0xF)
} Else {
Return (0x0)
}
}
OperationRegion (KEYS, SystemMemory, S7B1, 0x100)
Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
{
Offset (0x84),
PSAT, 32,
}
Method (_PS3)
{
Or (PSAT, 0x00000003, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
Method (_PS0)
{
And (PSAT, 0xfffffffc, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
}
Device (SPI1)
{
Name (_HID, "80860F0E")
Name (_UID, 1)
Name (_DDN, "SPI Controller #2")
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
LPSS_SPI_IRQ
}
FixedDMA (0x0, 0x0, Width32Bit, )
FixedDMA (0x1, 0x1, Width32Bit, )
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
Store (\S9B0, RBAS)
Return (^RBUF)
}
Method (_STA)
{
If (LEqual (\S9EN, 1)) {
Return (0xF)
} Else {
Return (0x0)
}
}
OperationRegion (KEYS, SystemMemory, S9B1, 0x100)
Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
{
Offset (0x84),
PSAT, 32,
}
Method (_PS3)
{
Or (PSAT, 0x00000003, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
Method (_PS0)
{
And (PSAT, 0xfffffffc, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
}
Device (PWM1)
{
Name (_HID, "80860F09")
Name (_UID, 1)
Name (_DDN, "PWM Controller #1")
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
Store (\SAB0, RBAS)
Return (^RBUF)
}
Method (_STA)
{
If (LEqual (\SAEN, 1)) {
Return (0xF)
} Else {
Return (0x0)
}
}
}
Device (PWM2)
{
Name (_HID, "80860F09")
Name (_UID, 2)
Name (_DDN, "PWM Controller #2")
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
Store (\SBB0, RBAS)
Return (^RBUF)
}
Method (_STA)
{
If (LEqual (\SBEN, 1)) {
Return (0xF)
} Else {
Return (0x0)
}
}
}
Device (UAR1)
{
Name (_HID, "80860F0A")
Name (_UID, 1)
Name (_DDN, "HS-UART Controller #1")
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
LPSS_HSUART1_IRQ
}
FixedDMA (0x2, 0x2, Width32Bit, )
FixedDMA (0x3, 0x3, Width32Bit, )
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
Store (\SCB0, RBAS)
Return (^RBUF)
}
Method (_STA)
{
If (LEqual (\SCEN, 1)) {
Return (0xF)
} Else {
Return (0x0)
}
}
OperationRegion (KEYS, SystemMemory, SCB1, 0x100)
Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
{
Offset (0x84),
PSAT, 32,
}
Method (_PS3)
{
Or (PSAT, 0x00000003, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
Method (_PS0)
{
And (PSAT, 0xfffffffc, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
}
Device (UAR2)
{
Name (_HID, "80860F0A")
Name (_UID, 2)
Name (_DDN, "HS-UART Controller #2")
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
LPSS_HSUART2_IRQ
}
FixedDMA (0x4, 0x4, Width32Bit, )
FixedDMA (0x5, 0x5, Width32Bit, )
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
Store (\SDB0, RBAS)
Return (^RBUF)
}
Method (_STA)
{
If (LEqual (\SDEN, 1)) {
Return (0xF)
} Else {
Return (0x0)
}
}
OperationRegion (KEYS, SystemMemory, SDB1, 0x100)
Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
{
Offset (0x84),
PSAT, 32,
}
Method (_PS3)
{
Or (PSAT, 0x00000003, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
Method (_PS0)
{
And (PSAT, 0xfffffffc, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
}

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
*/
/* Intel SOC PCIe support */
Device (RP01)
{
Name (_ADR, 0x001c0000)
Method (_PRT)
{
If (PICM) {
Return (Package() {
#undef PIC_MODE
#include <soc/intel/baytrail/acpi/irq_helper.h>
PCI_DEV_PIRQ_ROUTE(0x0, A, B, C, D)
})
} Else {
Return (Package() {
#define PIC_MODE
#include <soc/intel/baytrail/acpi/irq_helper.h>
PCI_DEV_PIRQ_ROUTE(0x0, A, B, C, D)
})
}
}
}
Device (RP02)
{
Name (_ADR, 0x001c0001)
Method (_PRT)
{
If (PICM) {
Return (Package() {
#undef PIC_MODE
#include <soc/intel/baytrail/acpi/irq_helper.h>
PCI_DEV_PIRQ_ROUTE(0x0, B, C, D, A)
})
} Else {
Return (Package() {
#define PIC_MODE
#include <soc/intel/baytrail/acpi/irq_helper.h>
PCI_DEV_PIRQ_ROUTE(0x0, B, C, D, A)
})
}
}
}
Device (RP03)
{
Name (_ADR, 0x001c0002)
Method (_PRT)
{
If (PICM) {
Return (Package() {
#undef PIC_MODE
#include <soc/intel/baytrail/acpi/irq_helper.h>
PCI_DEV_PIRQ_ROUTE(0x0, C, D, A, B)
})
} Else {
Return (Package() {
#define PIC_MODE
#include <soc/intel/baytrail/acpi/irq_helper.h>
PCI_DEV_PIRQ_ROUTE(0x0, C, D, A, B)
})
}
}
}
Device (RP04)
{
Name (_ADR, 0x001c0003)
Method (_PRT)
{
If (PICM) {
Return (Package() {
#undef PIC_MODE
#include <soc/intel/baytrail/acpi/irq_helper.h>
PCI_DEV_PIRQ_ROUTE(0x0, D, A, B, C)
})
} Else {
Return (Package() {
#define PIC_MODE
#include <soc/intel/baytrail/acpi/irq_helper.h>
PCI_DEV_PIRQ_ROUTE(0x0, D, A, B, C)
})
}
}
}

View File

@ -0,0 +1,78 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2012 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})
}
Method (_SWS)
{
/* Index into PM1 for device that caused wake */
Return (\PM1I)
}

View File

@ -0,0 +1,187 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 (EMMC)
{
Name (_HID, "80860F14")
Name (_CID, "PNP0D40")
Name (_UID, 1)
Name (_DDN, "eMMC Controller 4.5")
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
SCC_EMMC_IRQ
}
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
Store (\C0B0, RBAS)
Return (^RBUF)
}
Method (_STA)
{
If (LEqual (\C0EN, 1)) {
Return (0xF)
} Else {
Return (0x0)
}
}
OperationRegion (KEYS, SystemMemory, C0B1, 0x100)
Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
{
Offset (0x84),
PSAT, 32,
}
Method (_PS3)
{
Or (PSAT, 0x00000003, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
Method (_PS0)
{
And (PSAT, 0xfffffffc, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
Device (EM45)
{
/* Slot 0, Function 8 */
Name (_ADR, 0x8)
Method (_RMV, 0, NotSerialized)
{
Return (0)
}
}
}
Device (SDIO)
{
Name (_HID, "INT33BB")
Name (_CID, "PNP0D40")
Name (_UID, 2)
Name (_DDN, "SDIO Controller")
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
SCC_SDIO_IRQ
}
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
Store (\C1B0, RBAS)
Return (^RBUF)
}
Method (_STA)
{
If (LEqual (\C1EN, 1)) {
Return (0xF)
} Else {
Return (0x0)
}
}
OperationRegion (KEYS, SystemMemory, C1B1, 0x100)
Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
{
Offset (0x84),
PSAT, 32,
}
Method (_PS3)
{
Or (PSAT, 0x00000003, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
Method (_PS0)
{
And (PSAT, 0xfffffffc, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
}
Device (SDCD)
{
Name (_HID, "80860F16")
Name (_CID, "PNP0D40")
Name (_UID, 3)
Name (_DDN, "SD Card Controller")
Name (RBUF, ResourceTemplate()
{
Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
{
SCC_SD_IRQ
}
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
Store (\C2B0, RBAS)
Return (^RBUF)
}
Method (_STA)
{
If (LEqual (\C2EN, 1)) {
Return (0xF)
} Else {
Return (0x0)
}
}
OperationRegion (KEYS, SystemMemory, C2B1, 0x100)
Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
{
Offset (0x84),
PSAT, 32,
}
Method (_PS3)
{
Or (PSAT, 0x00000003, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
Method (_PS0)
{
And (PSAT, 0xfffffffc, PSAT)
Or (PSAT, 0x00000000, PSAT)
}
}

View File

@ -0,0 +1,26 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
Name(\_S0, Package(){0x0,0x0,0x0,0x0})
// Name(\_S1, 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,274 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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>
#include <soc/irq.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
}
// Intel Legacy Block
OperationRegion(ILBS, SystemMemory, ILB_BASE_ADDRESS, ILB_BASE_SIZE)
Field (ILBS, AnyAcc, NoLock, Preserve)
{
Offset (0x8),
PRTA, 8,
PRTB, 8,
PRTC, 8,
PRTD, 8,
PRTE, 8,
PRTF, 8,
PRTG, 8,
PRTH, 8,
}
}
Name(_HID,EISAID("PNP0A08")) // PCIe
Name(_CID,EISAID("PNP0A03")) // PCI
Name(_ADR, 0)
Name(_BBN, 0)
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,,, PMEM)
// TPM Area (0xfed40000-0xfed44fff)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0xfed40000, 0xfed44fff, 0x00000000,
0x00005000,,, TPMR)
})
// Update PCI resource area
CreateDwordField(MCRS, PMEM._MIN, PMIN)
CreateDwordField(MCRS, PMEM._MAX, PMAX)
CreateDwordField(MCRS, PMEM._LEN, PLEN)
// TOLM is BMBOUND accessible from IOSF so is saved in NVS
Store (\TOLM, PMIN)
Store (Subtract(CONFIG_MMCONF_BASE_ADDRESS, 1), PMAX)
Add (Subtract (PMAX, PMIN), 1, PLEN)
Return (MCRS)
}
/* Device Resource Consumption */
Device (PDRC)
{
Name (_HID, EISAID("PNP0C02"))
Name (_UID, 1)
Name (PDRS, ResourceTemplate() {
Memory32Fixed(ReadWrite, ABORT_BASE_ADDRESS, ABORT_BASE_SIZE)
Memory32Fixed(ReadWrite, MCFG_BASE_ADDRESS, MCFG_BASE_SIZE)
Memory32Fixed(ReadWrite, PMC_BASE_ADDRESS, PMC_BASE_SIZE)
Memory32Fixed(ReadWrite, ILB_BASE_ADDRESS, ILB_BASE_SIZE)
Memory32Fixed(ReadWrite, SPI_BASE_ADDRESS, SPI_BASE_SIZE)
Memory32Fixed(ReadWrite, MPHY_BASE_ADDRESS, MPHY_BASE_SIZE)
Memory32Fixed(ReadWrite, PUNIT_BASE_ADDRESS, PUNIT_BASE_SIZE)
Memory32Fixed(ReadWrite, RCBA_BASE_ADDRESS, RCBA_BASE_SIZE)
})
// Current Resource Settings
Method (_CRS, 0, Serialized)
{
Return(PDRS)
}
}
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)
}
}
/* IOSF MBI Interface for kernel access */
Device (IOSF)
{
Name (_HID, "INT33BD")
Name (_CID, "INT33BD")
Name (_UID, 1)
Name (RBUF, ResourceTemplate ()
{
/* MCR / MDR / MCRX */
Memory32Fixed (ReadWrite, 0, 12, RBAR)
})
Method (_CRS)
{
CreateDwordField (^RBUF, ^RBAR._BAS, RBAS)
Store (Add (MCFG_BASE_ADDRESS, 0xD0), RBAS)
Return (^RBUF)
}
}
// LPC Bridge 0:1f.0
#include "lpc.asl"
// USB XHCI 0:14.0
#include "xhci.asl"
// IRQ routing for each PCI device
#include "irqroute.asl"
// PCI Express Ports 0:1c.x
#include "pcie.asl"
Scope (\_SB)
{
// GPIO Devices
#include "gpio.asl"
// LPSS Devices
#include "lpss.asl"
// SCC Devices
#include "scc.asl"
// LPE Device
#include "lpe.asl"
}

View File

@ -0,0 +1,36 @@
/*
* 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 (XHCI)
{
Name (_ADR, 0x00140000)
Name (_PRW, Package () { 0x0d, 3 })
Name (_S3D, 3) /* Highest D state in S3 state */
Device (RHUB)
{
Name (_ADR, 0x00000000)
Device (PRT1) { Name (_ADR, 1) }
Device (PRT2) { Name (_ADR, 2) }
Device (PRT3) { Name (_ADR, 3) }
Device (PRT4) { Name (_ADR, 4) }
}
}

View File

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

View File

@ -0,0 +1,79 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 <cpu/x86/cache.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/mtrr.h>
#include <soc/iosf.h>
#include <cpu/intel/microcode/microcode.c>
static void set_var_mtrr(int reg, uint32_t base, uint32_t size, int type)
{
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, 0xffc00000, 4*1024*1024, MTRR_TYPE_WRPROT);
enable_cache();
/* Enable Variable MTRRs */
msr.hi = 0x00000000;
msr.lo = 0x00000800;
wrmsr(MTRRdefType_MSR, msr);
}
static void setup_mmconfig(void)
{
uint32_t reg;
/* Set up the MMCONF range. The register lives in the BUNIT. The
* IO variant of the config access needs to be used initially to
* properly configure as the IOSF access registers live in PCI
* config space. */
reg = 0;
/* Clear the extended register. */
pci_io_write_config32(IOSF_PCI_DEV, MCRX_REG, reg);
reg = CONFIG_MMCONF_BASE_ADDRESS | 1;
pci_io_write_config32(IOSF_PCI_DEV, MDR_REG, reg);
reg = IOSF_OPCODE(IOSF_OP_WRITE_BUNIT) | IOSF_PORT(IOSF_PORT_BUNIT) |
IOSF_REG(BUNIT_MMCONF_REG) | IOSF_BYTE_EN;
pci_io_write_config32(IOSF_PCI_DEV, MCR_REG, reg);
}
static void bootblock_cpu_init(void)
{
/* Allow memory-mapped PCI config access. */
setup_mmconfig();
/* Load microcode before any caching. */
intel_update_microcode_from_cbfs();
enable_rom_caching();
}

View File

@ -0,0 +1,18 @@
/* 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,93 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 <arch/pci_ops.h>
#include <soc/pci_devs.h>
#include <soc/ramstage.h>
#include "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,
.enable_resources = NULL,
.init = NULL,
.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 = baytrail_init_cpus,
.scan_bus = NULL,
};
static void enable_dev(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 south cluster enablement. */
if (PCI_SLOT(dev->path.pci.devfn) > GFX_DEV &&
(dev->ops == NULL || dev->ops->enable == NULL)) {
southcluster_enable_dev(dev);
}
}
}
/* Called at BS_DEV_INIT_CHIPS time -- very early. Just after BS_PRE_DEVICE. */
static void soc_init(void *chip_info)
{
baytrail_init_pre_device(chip_info);
}
struct chip_operations soc_intel_baytrail_ops = {
CHIP_NAME("Intel BayTrail SoC")
.enable_dev = enable_dev,
.init = soc_init,
};
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 & 0xffff) << 16) | (vendor & 0xffff));
}
}
struct pci_operations soc_pci_ops = {
.set_subsystem = &pci_set_subsystem,
};

View File

@ -0,0 +1,95 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 devicetree parser expects chip.h to reside directly in the path
* specified by the devicetree. */
#ifndef _BAYTRAIL_CHIP_H_
#define _BAYTRAIL_CHIP_H_
#include <stdint.h>
struct soc_intel_baytrail_config {
uint8_t enable_xdp_tap;
uint8_t sata_port_map;
uint8_t sata_ahci;
uint8_t ide_legacy_combined;
uint8_t clkreq_enable;
/* VR low power settings -- enable PS2 mode for gfx and core */
int vnn_ps2_enable;
int vcc_ps2_enable;
/* Disable SLP_X stretching after SUS power well loss. */
int disable_slp_x_stretch_sus_fail;
/* USB Port Disable mask */
uint16_t usb2_port_disable_mask;
uint16_t usb3_port_disable_mask;
/* USB routing */
int usb_route_to_xhci;
/* USB PHY settings specific to the board */
uint32_t usb2_per_port_lane0;
uint32_t usb2_per_port_rcomp_hs_pullup0;
uint32_t usb2_per_port_lane1;
uint32_t usb2_per_port_rcomp_hs_pullup1;
uint32_t usb2_per_port_lane2;
uint32_t usb2_per_port_rcomp_hs_pullup2;
uint32_t usb2_per_port_lane3;
uint32_t usb2_per_port_rcomp_hs_pullup3;
uint32_t usb2_comp_bg;
/* LPE Audio Clock configuration. */
int lpe_codec_clk_freq; /* 19 or 25 are valid. */
int lpe_codec_clk_num; /* Platform clock pins. [0:5] are valid. */
/* Native SD Card controller - override controller capabilities. */
uint32_t sdcard_cap_low;
uint32_t sdcard_cap_high;
/* Enable devices in ACPI mode */
int lpss_acpi_mode;
int scc_acpi_mode;
int lpe_acpi_mode;
/* Allow PCIe devices to wake system from suspend. */
int pcie_wake_enable;
int gpu_pipea_port_select; /* Port select: 1=DP_B 2=DP_C */
uint16_t gpu_pipea_power_on_delay;
uint16_t gpu_pipea_light_on_delay;
uint16_t gpu_pipea_power_off_delay;
uint16_t gpu_pipea_light_off_delay;
uint16_t gpu_pipea_power_cycle_delay;
int gpu_pipea_pwm_freq_hz;
int gpu_pipeb_port_select; /* Port select: 1=DP_B 2=DP_C */
uint16_t gpu_pipeb_power_on_delay;
uint16_t gpu_pipeb_light_on_delay;
uint16_t gpu_pipeb_power_off_delay;
uint16_t gpu_pipeb_light_off_delay;
uint16_t gpu_pipeb_power_cycle_delay;
int gpu_pipeb_pwm_freq_hz;
int disable_ddr_2x_refresh_rate;
};
extern struct chip_operations soc_intel_baytrail_ops;
#endif /* _BAYTRAIL_CHIP_H_ */

View File

@ -0,0 +1,309 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 <console/console.h>
#include <cpu/cpu.h>
#include <cpu/intel/microcode.h>
#include <cpu/intel/turbo.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/lapic.h>
#include <cpu/x86/mp.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/mtrr.h>
#include <cpu/x86/smm.h>
#include <reg_script.h>
#include <soc/iosf.h>
#include <soc/msr.h>
#include <soc/pattrs.h>
#include <soc/ramstage.h>
#include <soc/smm.h>
static void smm_relocate(void *unused);
static void enable_smis(void *unused);
static struct mp_flight_record mp_steps[] = {
MP_FR_BLOCK_APS(smm_relocate, NULL, smm_relocate, 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),
};
/* The APIC id space on Bay Trail is sparse. Each id is separated by 2. */
static int adjust_apic_id(int index, int apic_id)
{
return 2 * index;
}
/* Package level MSRs */
const struct reg_script package_msr_script[] = {
/* Set Package TDP to ~7W */
REG_MSR_WRITE(MSR_PKG_POWER_LIMIT, 0x3880fa),
REG_MSR_RMW(MSR_PP1_POWER_LIMIT, ~(0x7f << 17), 0),
REG_MSR_WRITE(MSR_PKG_TURBO_CFG1, 0x702),
REG_MSR_WRITE(MSR_CPU_TURBO_WKLD_CFG1, 0x200b),
REG_MSR_WRITE(MSR_CPU_TURBO_WKLD_CFG2, 0),
REG_MSR_WRITE(MSR_CPU_THERM_CFG1, 0x00000305),
REG_MSR_WRITE(MSR_CPU_THERM_CFG2, 0x0405500d),
REG_MSR_WRITE(MSR_CPU_THERM_SENS_CFG, 0x27),
REG_SCRIPT_END
};
/* Core level MSRs */
const struct reg_script core_msr_script[] = {
/* Dynamic L2 shrink enable and threshold, clear SINGLE_PCTL bit 11 */
REG_MSR_RMW(MSR_PMG_CST_CONFIG_CONTROL, ~0x3f080f, 0xe0008),
REG_MSR_RMW(MSR_POWER_MISC,
~(ENABLE_ULFM_AUTOCM_MASK | ENABLE_INDP_AUTOCM_MASK), 0),
/* Disable C1E */
REG_MSR_RMW(MSR_POWER_CTL, ~0x2, 0),
REG_MSR_OR(MSR_POWER_MISC, 0x44),
REG_SCRIPT_END
};
void baytrail_init_cpus(device_t dev)
{
struct bus *cpu_bus = dev->link_list;
const struct pattrs *pattrs = pattrs_get();
struct mp_params mp_params;
uint32_t bsmrwac;
void *default_smm_area;
/* Set up MTRRs based on physical address size. */
x86_setup_fixed_mtrrs();
x86_setup_var_mtrrs(pattrs->address_bits, 2);
x86_mtrr_check();
mp_params.num_cpus = pattrs->num_cpus,
mp_params.parallel_microcode_load = 1,
mp_params.adjust_apic_id = adjust_apic_id;
mp_params.flight_plan = &mp_steps[0];
mp_params.num_records = ARRAY_SIZE(mp_steps);
mp_params.microcode_pointer = pattrs->microcode_patch;
default_smm_area = backup_default_smm_area();
/*
* Configure the BUNIT to allow dirty cache line evictions in non-SMM
* mode for the lines that were dirtied while in SMM mode. Otherwise
* the writes would be silently dropped.
*/
bsmrwac = iosf_bunit_read(BUNIT_SMRWAC) | SAI_IA_UNTRUSTED;
iosf_bunit_write(BUNIT_SMRWAC, bsmrwac);
/* Set package MSRs */
reg_script_run(package_msr_script);
/* Enable Turbo Mode on BSP and siblings of the BSP's building block. */
enable_turbo();
if (mp_init(cpu_bus, &mp_params)) {
printk(BIOS_ERR, "MP initialization failure.\n");
}
restore_default_smm_area(default_smm_area);
}
static void baytrail_core_init(device_t cpu)
{
printk(BIOS_DEBUG, "Init BayTrail core.\n");
/* On bay trail the turbo disable bit is actually scoped at building
* block level -- not package. For non-bsp cores that are within a
* building block enable turbo. The cores within the BSP's building
* block will just see it already enabled and move on. */
if (lapicid())
enable_turbo();
/* Set core MSRs */
reg_script_run(core_msr_script);
/* Set this core to max frequency ratio */
set_max_freq();
}
static struct device_operations cpu_dev_ops = {
.init = baytrail_core_init,
};
static struct cpu_device_id cpu_table[] = {
{ X86_VENDOR_INTEL, 0x30673 },
{ X86_VENDOR_INTEL, 0x30678 },
{ 0, 0 },
};
static const struct cpu_driver driver __cpu_driver = {
.ops = &cpu_dev_ops,
.id_table = cpu_table,
};
/*
* SMM loading and initialization.
*/
struct smm_relocation_attrs {
uint32_t smbase;
uint32_t smrr_base;
uint32_t smrr_mask;
};
static struct smm_relocation_attrs relo_attrs;
static void adjust_apic_id_map(struct smm_loader_params *smm_params)
{
int i;
struct smm_runtime *runtime = smm_params->runtime;
for (i = 0; i < CONFIG_MAX_CPUS; i++)
runtime->apic_id_to_cpu[i] = mp_get_apic_id(i);
}
static void asmlinkage cpu_smm_do_relocation(void *arg)
{
msr_t smrr;
em64t100_smm_state_save_area_t *smm_state;
const struct smm_module_params *p;
const struct smm_runtime *runtime;
int cpu;
p = arg;
runtime = p->runtime;
cpu = p->cpu;
if (cpu >= CONFIG_MAX_CPUS) {
printk(BIOS_CRIT,
"Invalid CPU number assigned in SMM stub: %d\n", cpu);
return;
}
/* Set up SMRR. */
smrr.lo = relo_attrs.smrr_base;
smrr.hi = 0;
wrmsr(SMRRphysBase_MSR, smrr);
smrr.lo = relo_attrs.smrr_mask;
smrr.hi = 0;
wrmsr(SMRRphysMask_MSR, smrr);
/* The relocated handler runs with all CPUs concurrently. Therefore
* stagger the entry points adjusting SMBASE downwards by save state
* size * CPU num. */
smm_state = (void *)(SMM_EM64T100_SAVE_STATE_OFFSET + runtime->smbase);
smm_state->smbase = relo_attrs.smbase - cpu * runtime->save_state_size;
printk(BIOS_DEBUG, "New SMBASE 0x%08x\n", smm_state->smbase);
}
static int install_relocation_handler(int num_cpus)
{
const int save_state_size = sizeof(em64t100_smm_state_save_area_t);
struct smm_loader_params smm_params = {
.per_cpu_stack_size = save_state_size,
.num_concurrent_stacks = num_cpus,
.per_cpu_save_state_size = save_state_size,
.num_concurrent_save_states = 1,
.handler = (smm_handler_t)&cpu_smm_do_relocation,
};
if (smm_setup_relocation_handler(&smm_params))
return -1;
adjust_apic_id_map(&smm_params);
return 0;
}
static int install_permanent_handler(int num_cpus)
{
/* There are num_cpus concurrent stacks and num_cpus concurrent save
* state areas. Lastly, set the stack size to the save state size. */
int save_state_size = sizeof(em64t100_smm_state_save_area_t);
struct smm_loader_params smm_params = {
.per_cpu_stack_size = save_state_size,
.num_concurrent_stacks = num_cpus,
.per_cpu_save_state_size = save_state_size,
.num_concurrent_save_states = num_cpus,
};
const int tseg_size = smm_region_size() - CONFIG_SMM_RESERVED_SIZE;
printk(BIOS_DEBUG, "Installing SMM handler to 0x%08x\n",
relo_attrs.smbase);
if (smm_load_module((void *)relo_attrs.smbase, tseg_size, &smm_params))
return -1;
adjust_apic_id_map(&smm_params);
return 0;
}
static int smm_load_handlers(void)
{
/* All range registers are aligned to 4KiB */
const uint32_t rmask = ~((1 << 12) - 1);
const struct pattrs *pattrs = pattrs_get();
/* Initialize global tracking state. */
relo_attrs.smbase = (uint32_t)smm_region_start();
relo_attrs.smrr_base = relo_attrs.smbase | MTRR_TYPE_WRBACK;
relo_attrs.smrr_mask = ~(smm_region_size() - 1) & rmask;
relo_attrs.smrr_mask |= MTRRphysMaskValid;
/* Install handlers. */
if (install_relocation_handler(pattrs->num_cpus) < 0) {
printk(BIOS_ERR, "Unable to install SMM relocation handler.\n");
return -1;
}
if (install_permanent_handler(pattrs->num_cpus) < 0) {
printk(BIOS_ERR, "Unable to install SMM permanent handler.\n");
return -1;
}
/* Ensure the SMM handlers hit DRAM before performing first SMI. */
wbinvd();
return 0;
}
static void smm_relocate(void *unused)
{
const struct pattrs *pattrs = pattrs_get();
/* Load relocation and permanent handler. */
if (boot_cpu()) {
if (smm_load_handlers() < 0) {
printk(BIOS_ERR, "Error loading SMM handlers.\n");
return;
}
southcluster_smm_clear_state();
}
/* Relocate SMM space. */
smm_initiate_relocation();
/* Load microcode after SMM relocation. */
intel_microcode_load_unlocked(pattrs->microcode_patch);
}
static void enable_smis(void *unused)
{
southcluster_smm_enable_smi();
}

View File

@ -0,0 +1,52 @@
/*
* 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/io.h>
#include <bootstate.h>
#include <console/console.h>
#include <reg_script.h>
#include <soc/iosf.h>
static const struct reg_script dptf_init_settings[] = {
/* SocThermInit */
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PTMC, 0x00030708),
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_GFXT, 0x0000C000),
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_VEDT, 0x00000004),
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_ISPT, 0x00000004),
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PTPS, 0x00000000),
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_TE_AUX3, 0x00061029),
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_TTE_VRIccMax, 0x00061029),
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_TTE_VRHot, 0x00061029),
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_TTE_XXPROCHOT, 0x00061029),
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_TTE_SLM0, 0x00001029),
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_TTE_SLM1, 0x00001029),
/* ratio 11 = 1466mhz for mid and entry celeron */
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_SOC_POWER_BUDGET, 0x00000B00),
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_SOC_ENERGY_CREDIT, 0x00000002),
REG_SCRIPT_END,
};
static void dptf_init(void *unused)
{
printk(BIOS_DEBUG, "Applying SOC Thermal settings for DPTF.\n");
reg_script_run(dptf_init_settings);
}
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, dptf_init, NULL);

View File

@ -0,0 +1,181 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2013 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 <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <stdint.h>
#include <reg_script.h>
#include <soc/iomap.h>
#include <soc/iosf.h>
#include <soc/pci_devs.h>
#include <soc/pmc.h>
#include <soc/ramstage.h>
#include <soc/ehci.h>
#include "chip.h"
static const struct reg_script ehci_init_script[] = {
/* Enable S0 PLL shutdown
* D29:F0:7A[12,10,7,6,4,3,2,1]=11111111b */
REG_PCI_OR16(0x7a, 0x14de),
/* Enable SB local clock gating
* D29:F0:7C[14,3,2]=111b (14 set in clock gating step) */
REG_PCI_OR32(0x7c, 0x0000000c),
REG_PCI_OR32(0x8c, 0x00000001),
/* Enable dynamic clock gating 0x4001=0xCE */
REG_IOSF_RMW(IOSF_PORT_USBPHY, 0x4001, 0xFFFFFF00, 0xCE),
/* Magic RCBA register set sequence */
/* RCBA + 0x200=0x1 */
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x200, 0x00000001),
/* RCBA + 0x204=0x2 */
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x204, 0x00000002),
/* RCBA + 0x208=0x0 */
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x208, 0x00000000),
/* RCBA + 0x240[4,3,2,1,0]=00000b */
REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x240, ~0x0000001f, 0),
/* RCBA + 0x318[9,8,6,5,4,3,2,1,0]=000000111b */
REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x318, ~0x00000378, 0x00000007),
/* RCBA + 0x31c[3,2,1,0]=0011b */
REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x31c, ~0x0000000c, 0x00000003),
REG_SCRIPT_END
};
static const struct reg_script ehci_clock_gating_script[] = {
/* Enable SB local clock gating */
REG_PCI_OR32(0x7c, 0x00004000),
/* RCBA + 0x284=0xbe (step B0+) */
REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x284, 0x000000be),
REG_SCRIPT_END
};
static const struct reg_script ehci_disable_script[] = {
/* Clear Run/Stop Bit */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, USB2CMD, ~USB2CMD_RS, 0),
/* Wait for HC Halted */
REG_RES_POLL32(PCI_BASE_ADDRESS_0, USB2STS,
USB2STS_HCHALT, USB2STS_HCHALT, 10000),
/* Disable Interrupts */
REG_PCI_OR32(EHCI_CMD_STS, INTRDIS),
/* Disable Asynchronous and Periodic Scheduler */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, USB2CMD,
~(USB2CMD_ASE | USB2CMD_PSE), 0),
/* Disable port wake */
REG_PCI_RMW32(EHCI_SBRN_FLA_PWC, ~(PORTWKIMP | PORTWKCAPMASK), 0),
/* Set Function Disable bit in RCBA */
REG_MMIO_OR32(RCBA_BASE_ADDRESS + RCBA_FUNC_DIS, RCBA_EHCI_DIS),
REG_SCRIPT_END
};
static const struct reg_script ehci_hc_reset[] = {
REG_RES_OR16(PCI_BASE_ADDRESS_0, USB2CMD, USB2CMD_HCRESET),
REG_SCRIPT_END
};
static void usb2_phy_init(device_t dev)
{
struct soc_intel_baytrail_config *config = dev->chip_info;
u32 usb2_comp_bg = (config->usb2_comp_bg == 0 ?
0x4700 : config->usb2_comp_bg);
struct reg_script usb2_phy_script[] = {
/* USB3PHYInit() */
REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_COMPBG,
usb2_comp_bg),
/* Per port phy settings, set in devicetree.cb */
REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_PER_PORT_LANE0,
config->usb2_per_port_lane0),
REG_IOSF_WRITE(IOSF_PORT_USBPHY,
USBPHY_PER_PORT_RCOMP_HS_PULLUP0,
config->usb2_per_port_rcomp_hs_pullup0),
REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_PER_PORT_LANE1,
config->usb2_per_port_lane1),
REG_IOSF_WRITE(IOSF_PORT_USBPHY,
USBPHY_PER_PORT_RCOMP_HS_PULLUP1,
config->usb2_per_port_rcomp_hs_pullup1),
REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_PER_PORT_LANE2,
config->usb2_per_port_lane2),
REG_IOSF_WRITE(IOSF_PORT_USBPHY,
USBPHY_PER_PORT_RCOMP_HS_PULLUP2,
config->usb2_per_port_rcomp_hs_pullup2),
REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_PER_PORT_LANE3,
config->usb2_per_port_lane3),
REG_IOSF_WRITE(IOSF_PORT_USBPHY,
USBPHY_PER_PORT_RCOMP_HS_PULLUP3,
config->usb2_per_port_rcomp_hs_pullup3),
REG_SCRIPT_END
};
reg_script_run(usb2_phy_script);
}
static void ehci_init(device_t dev)
{
struct soc_intel_baytrail_config *config = dev->chip_info;
struct reg_script ehci_hc_init[] = {
/* Controller init */
REG_SCRIPT_NEXT(ehci_init_script),
/* Enable clock gating */
REG_SCRIPT_NEXT(ehci_clock_gating_script),
/*
* Disable ports if requested
*/
/* Open per-port disable control override */
REG_IO_RMW16(ACPI_BASE_ADDRESS + UPRWC, ~0, UPRWC_WR_EN),
REG_PCI_WRITE8(EHCI_USB2PDO, config->usb2_port_disable_mask),
/* Close per-port disable control override */
REG_IO_RMW16(ACPI_BASE_ADDRESS + UPRWC, ~UPRWC_WR_EN, 0),
REG_SCRIPT_END
};
/* Don't reset controller in S3 resume path */
if (!acpi_is_wakeup_s3())
reg_script_run_on_dev(dev, ehci_hc_reset);
/* Disable controller if ports are routed to XHCI */
if (config->usb_route_to_xhci) {
/* Disable controller */
reg_script_run_on_dev(dev, ehci_disable_script);
/* Hide device with southcluster function */
dev->enabled = 0;
southcluster_enable_dev(dev);
} else {
/* Initialize EHCI controller */
reg_script_run_on_dev(dev, ehci_hc_init);
}
/* Setup USB2 PHY based on board config */
usb2_phy_init(dev);
}
static struct device_operations ehci_device_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = ehci_init,
.ops_pci = &soc_pci_ops,
};
static const struct pci_driver baytrail_ehci __pci_driver = {
.ops = &ehci_device_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.device = EHCI_DEVID
};

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
*/
#include <arch/io.h>
#include <arch/acpi.h>
#include <stdint.h>
#include <console/console.h>
#include <cbmem.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ops.h>
#include <elog.h>
#include <soc/iomap.h>
#include <soc/pmc.h>
static void log_power_and_resets(const struct chipset_power_state *ps)
{
if (ps->gen_pmcon1 & PWR_FLR) {
elog_add_event(ELOG_TYPE_POWER_FAIL);
elog_add_event(ELOG_TYPE_PWROK_FAIL);
}
if (ps->gen_pmcon1 & SUS_PWR_FLR) {
elog_add_event(ELOG_TYPE_SUS_POWER_FAIL);
}
if (ps->gen_pmcon1 & RPS) {
elog_add_event(ELOG_TYPE_RTC_RESET);
}
if (ps->tco_sts & SECOND_TO_STS) {
elog_add_event(ELOG_TYPE_TCO_RESET);
}
if (ps->pm1_sts & PRBTNOR_STS) {
elog_add_event(ELOG_TYPE_POWER_BUTTON_OVERRIDE);
}
if (ps->gen_pmcon1 & SRS) {
elog_add_event(ELOG_TYPE_RESET_BUTTON);
}
if (ps->gen_pmcon1 & GEN_RST_STS) {
elog_add_event(ELOG_TYPE_SYSTEM_RESET);
}
}
static void log_wake_events(const struct chipset_power_state *ps)
{
const uint32_t pcie_wake_mask = PCI_EXP_STS | PCIE_WAKE3_STS |
PCIE_WAKE2_STS | PCIE_WAKE1_STS |
PCIE_WAKE0_STS;
uint32_t gpe0_sts;
uint32_t gpio_mask;
int i;
/* Mask off disabled events. */
gpe0_sts = ps->gpe0_sts & ps->gpe0_en;
if (ps->pm1_sts & WAK_STS) {
elog_add_event_byte(ELOG_TYPE_ACPI_WAKE,
acpi_is_wakeup_s3() ? 3 : 5);
}
if (ps->pm1_sts & PWRBTN_STS) {
elog_add_event_wake(ELOG_WAKE_SOURCE_PWRBTN, 0);
}
if (ps->pm1_sts & RTC_STS) {
elog_add_event_wake(ELOG_WAKE_SOURCE_RTC, 0);
}
if (gpe0_sts & PME_B0_EN) {
elog_add_event_wake(ELOG_WAKE_SOURCE_PME_INTERNAL, 0);
}
if (gpe0_sts & pcie_wake_mask) {
elog_add_event_wake(ELOG_WAKE_SOURCE_PCIE, 0);
}
gpio_mask = SUS_GPIO_STS0;
i = 0;
while (gpio_mask) {
if (gpio_mask & gpe0_sts) {
elog_add_event_wake(ELOG_WAKE_SOURCE_GPIO, i);
}
gpio_mask <<= 1;
i++;
}
}
void southcluster_log_state(void)
{
struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE);
if (ps == NULL) {
printk(BIOS_DEBUG, "Not logging power state information. "
"Power state not found in cbmem.\n");
return;
}
log_power_and_resets(ps);
log_wake_events(ps);
}

View File

@ -0,0 +1,77 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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/io.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <reg_script.h>
#include <soc/iosf.h>
#include <soc/nvs.h>
#include <soc/pci_devs.h>
#include <soc/ramstage.h>
#include "chip.h"
static const struct reg_script emmc_ops[] = {
/* Enable 2ms card stable feature. */
REG_PCI_OR32(0xa8, (1 << 24)),
/* Enable HS200 */
REG_PCI_WRITE32(0xa0, 0x446cc801),
REG_PCI_WRITE32(0xa4, 0x80000807),
/* cfio_regs_score_special_bits.sdio1_dummy_loopback_en=1 */
REG_IOSF_OR(IOSF_PORT_SCORE, 0x49c0, (1 << 3)),
/* CLKGATE_EN_1 . cr_scc_mipihsi_clkgate_en = 1 */
REG_IOSF_RMW(IOSF_PORT_CCU, 0x1c, ~(3 << 26), (1 << 26)),
/* Set slew for HS200 */
REG_IOSF_RMW(IOSF_PORT_SCORE, 0x48c0, ~0x3c, 0x3c),
REG_IOSF_RMW(IOSF_PORT_SCORE, 0x48c4, ~0x3c, 0x3c),
/* Max timeout */
REG_RES_WRITE8(PCI_BASE_ADDRESS_0, 0x002e, 0x0e),
REG_SCRIPT_END,
};
static void emmc_init(device_t dev)
{
struct soc_intel_baytrail_config *config = dev->chip_info;
printk(BIOS_DEBUG, "eMMC init\n");
reg_script_run_on_dev(dev, emmc_ops);
if (config->scc_acpi_mode)
scc_enable_acpi_mode(dev, SCC_MMC_CTL, SCC_NVS_MMC);
}
static struct device_operations device_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = emmc_init,
.enable = NULL,
.scan_bus = NULL,
.ops_pci = &soc_pci_ops,
};
static const struct pci_driver southcluster __pci_driver = {
.ops = &device_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.device = MMC_DEVID,
};

View File

@ -0,0 +1,398 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2013 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 <delay.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <reg_script.h>
#include <stdlib.h>
#include <soc/gfx.h>
#include <soc/iosf.h>
#include <soc/pci_devs.h>
#include <soc/ramstage.h>
#include "chip.h"
#define GFX_TIMEOUT 100000 /* 100ms */
/*
* Lock Power Context Base Register to point to a 24KB block
* of memory in GSM. Power context save data is stored here.
*/
static void gfx_lock_pcbase(device_t dev)
{
struct resource *res = find_resource(dev, PCI_BASE_ADDRESS_0);
const u16 gms_size_map[17] = { 0,32,64,96,128,160,192,224,256,
288,320,352,384,416,448,480,512 };
u32 pcsize = 24 << 10; /* 24KB */
u32 wopcmsz = 0x100000; /* PAVP offset */
u32 gms, gmsize, pcbase;
gms = pci_read_config32(dev, GGC) & GGC_GSM_SIZE_MASK;
gms >>= 3;
if (gms > ARRAY_SIZE(gms_size_map))
return;
gmsize = gms_size_map[gms];
/* PcBase = BDSM + GMS Size - WOPCMSZ - PowerContextSize */
pcbase = pci_read_config32(dev, GSM_BASE) & 0xfff00000;
pcbase += (gmsize-1) * wopcmsz - pcsize;
pcbase |= 1; /* Lock */
write32((u32 *)(uintptr_t)(res->base + 0x182120), pcbase);
}
static const struct reg_script gfx_init_script[] = {
/* Allow-Wake render/media wells */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x130090, ~1, 1),
REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x130094, 1, 1, GFX_TIMEOUT),
/* Render Force-Wake */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x1300b0, 0x80008000),
REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x1300b4, 0x8000, 0x8000,
GFX_TIMEOUT),
/* Media Force-Wake */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x1300b8, 0x80008000),
REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x1300bc, 0x8000, 0x8000,
GFX_TIMEOUT),
/* Workaround - X0:261954/A0:261955 */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x182060, ~0xf, 1),
/*
* PowerMeter Weights
*/
/* SET1 */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA800, 0x00000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA804, 0x00000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA808, 0x0000ff0A),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA80C, 0x1D000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA810, 0xAC004900),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA814, 0x000F0000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA818, 0x5A000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA81C, 0x2600001F),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA820, 0x00090000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA824, 0x2000ff00),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA828, 0xff090016),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA82C, 0x00000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA830, 0x00000100),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA834, 0x00A00F51),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA838, 0x000B0000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA83C, 0xcb7D3307),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA840, 0x003C0000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA844, 0xFFFF0000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA848, 0x00220000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA84c, 0x43000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA850, 0x00000800),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA854, 0x00000F00),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA858, 0x00000021),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA85c, 0x00000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA860, 0x00190000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xAA80, 0x00FF00FF),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xAA84, 0x00000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x1300A4, 0x00000000),
/* SET2 */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA900, 0x00000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA904, 0x00000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA908, 0x00000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa90c, 0x1D000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa910, 0xAC005000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa914, 0x000F0000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa918, 0x5A000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa91c, 0x2600001F),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa920, 0x00090000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa924, 0x2000ff00),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa928, 0xff090016),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa92c, 0x00000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa930, 0x00000100),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa934, 0x00A00F51),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa938, 0x000B0000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA93C, 0xcb7D3307),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA940, 0x003C0000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA944, 0xFFFF0000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA948, 0x00220000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA94C, 0x43000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA950, 0x00000800),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA954, 0x00000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA960, 0x00000000),
/* SET3 */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xaa3c, 0x00000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xaa54, 0x00000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xaa60, 0x00000000),
/* Enable PowerMeter Counters */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA248, 0x00000058),
/* Program PUNIT_GPU_EC_VIRUS based on DPTF SDP */
/* SDP Profile 4 == 0x11940, others 0xcf08 */
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_GPU_EC_VIRUS, 0xcf08),
/* GfxPause */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa000, 0x00071388),
/* Dynamic EU Control Settings */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa080, 0x00000004),
/* Lock ECO Bit Settings */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa180, 0x80000000),
/* DOP Clock Gating */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9424, 0x00000001),
/* MBCunit will send the VCR (Fuse) writes as NP-W */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x907c, 0xfffeffff, 0x00010000),
/*
* RC6 Settings
*/
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA090, 0x00000000),
/* RC1e - RC6/6p - RC6pp Wake Rate Limits */
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),
/* RC Sleep / RCx Thresholds */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA0B0, 0x00000000),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA0B8, 0x00000557),
/*
* Turbo Settings
*/
/* Render/Video/Blitter Idle Max Count */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x2054, 0x0000000A),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x12054, 0x0000000A),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x22054, 0x0000000A),
/* RP Down Timeout */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA010, 0x000F4240),
/*
* Turbo Control Settings
*/
/* RP Up/Down Threshold */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA02C, 0x0000E8E8),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA030, 0x0003BD08),
/* RP Up/Down EI */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA068, 0x000101D0),
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA06C, 0x00055730),
/* RP Idle Hysteresis */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa070, 0x0000000a),
/* HW RC6 Control Settings */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa090, 0x11000000),
/* RP Control */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa024, 0x00000592),
/* Enable PM Interrupts */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x44024, 0x03000000),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x4402c, 0x03000076),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa168, 0x0000007e),
/* Aggressive Clock Gating */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9400, 0),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9404, 0),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9408, 0),
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x940c, 0),
/* Enable Gfx Turbo. */
REG_IOSF_RMW(IOSF_PORT_PMC, SB_BIOS_CONFIG,
~SB_BIOS_CONFIG_GFX_TURBO_DIS, 0),
REG_SCRIPT_END
};
static const struct reg_script gpu_pre_vbios_script[] = {
/* Make sure GFX is bus master with MMIO access */
REG_PCI_OR32(PCI_COMMAND, PCI_COMMAND_MASTER|PCI_COMMAND_MEMORY),
/* Display */
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xc0),
REG_IOSF_POLL(IOSF_PORT_PMC, PUNIT_PWRGT_STATUS, 0xc0, 0xc0,
GFX_TIMEOUT),
/* Tx/Rx Lanes */
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xfff0c0),
REG_IOSF_POLL(IOSF_PORT_PMC, PUNIT_PWRGT_STATUS, 0xfff0c0, 0xfff0c0,
GFX_TIMEOUT),
/* Common Lane */
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xfffcc0),
REG_IOSF_POLL(IOSF_PORT_PMC, PUNIT_PWRGT_STATUS, 0xfffcc0, 0xfffcc0,
GFX_TIMEOUT),
/* Ungating Tx only */
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xf00cc0),
REG_IOSF_POLL(IOSF_PORT_PMC, PUNIT_PWRGT_STATUS, 0xfffcc0, 0xf00cc0,
GFX_TIMEOUT),
/* Ungating Common Lane only */
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xf000c0),
REG_IOSF_POLL(IOSF_PORT_PMC, PUNIT_PWRGT_STATUS, 0xffffc0, 0xf000c0,
GFX_TIMEOUT),
/* Ungating Display */
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xf00000),
REG_IOSF_POLL(IOSF_PORT_PMC, PUNIT_PWRGT_STATUS, 0xfffff0, 0xf00000,
GFX_TIMEOUT),
REG_SCRIPT_END
};
static const struct reg_script gfx_post_vbios_script[] = {
/* Deassert Render Force-Wake */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x1300b0, 0x80000000),
REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x1300b4, 0x8000, 0, GFX_TIMEOUT),
/* Deassert Media Force-Wake */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x1300b8, 0x80000000),
REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x1300bc, 0x8000, 0, GFX_TIMEOUT),
/* Set Lock bits */
REG_PCI_RMW32(GGC, 0xffffffff, 1),
REG_PCI_RMW32(GSM_BASE, 0xffffffff, 1),
REG_PCI_RMW32(GTT_BASE, 0xffffffff, 1),
REG_SCRIPT_END
};
static inline void gfx_run_script(device_t dev, const struct reg_script *ops)
{
reg_script_run_on_dev(dev, ops);
}
static void gfx_pre_vbios_init(device_t dev)
{
printk(BIOS_INFO, "GFX: Pre VBIOS Init\n");
gfx_run_script(dev, gpu_pre_vbios_script);
}
static void gfx_pm_init(device_t dev)
{
printk(BIOS_INFO, "GFX: Power Management Init\n");
gfx_run_script(dev, gfx_init_script);
/* Lock power context base */
gfx_lock_pcbase(dev);
}
static void gfx_post_vbios_init(device_t dev)
{
printk(BIOS_INFO, "GFX: Post VBIOS Init\n");
gfx_run_script(dev, gfx_post_vbios_script);
}
static void set_backlight_pwm(device_t dev, uint32_t bklt_reg, int req_hz)
{
int divider;
struct resource *res;
res = find_resource(dev, PCI_BASE_ADDRESS_0);
if (res == NULL)
return;
/* Default to 200 Hz if nothing is set. */
if (req_hz == 0)
req_hz = 200;
/* Base clock is 25MHz */
divider = 25 * 1000 * 1000 / (16 * req_hz);
/* Do not set duty cycle (lower 16 bits). Just set the divider. */
write32((u32 *)(uintptr_t)(res->base + bklt_reg), divider << 16);
}
static void gfx_panel_setup(device_t dev)
{
struct soc_intel_baytrail_config *config = dev->chip_info;
struct reg_script gfx_pipea_init[] = {
/* CONTROL */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, PIPEA_REG(PP_CONTROL),
PP_CONTROL_UNLOCK | PP_CONTROL_EDP_FORCE_VDD),
/* POWER ON */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, PIPEA_REG(PP_ON_DELAYS),
(config->gpu_pipea_port_select << 30 |
config->gpu_pipea_power_on_delay << 16 |
config->gpu_pipea_light_on_delay)),
/* POWER OFF */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, PIPEA_REG(PP_OFF_DELAYS),
(config->gpu_pipea_power_off_delay << 16 |
config->gpu_pipea_light_off_delay)),
/* DIVISOR */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, PIPEA_REG(PP_DIVISOR),
~0x1f, config->gpu_pipea_power_cycle_delay),
REG_SCRIPT_END
};
struct reg_script gfx_pipeb_init[] = {
/* CONTROL */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, PIPEB_REG(PP_CONTROL),
PP_CONTROL_UNLOCK | PP_CONTROL_EDP_FORCE_VDD),
/* POWER ON */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, PIPEB_REG(PP_ON_DELAYS),
(config->gpu_pipeb_port_select << 30 |
config->gpu_pipeb_power_on_delay << 16 |
config->gpu_pipeb_light_on_delay)),
/* POWER OFF */
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, PIPEB_REG(PP_OFF_DELAYS),
(config->gpu_pipeb_power_off_delay << 16 |
config->gpu_pipeb_light_off_delay)),
/* DIVISOR */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, PIPEB_REG(PP_DIVISOR),
~0x1f, config->gpu_pipeb_power_cycle_delay),
REG_SCRIPT_END
};
if (config->gpu_pipea_port_select) {
printk(BIOS_INFO, "GFX: Initialize PIPEA\n");
reg_script_run_on_dev(dev, gfx_pipea_init);
set_backlight_pwm(dev, PIPEA_REG(BACKLIGHT_CTL),
config->gpu_pipea_pwm_freq_hz);
}
if (config->gpu_pipeb_port_select) {
printk(BIOS_INFO, "GFX: Initialize PIPEB\n");
reg_script_run_on_dev(dev, gfx_pipeb_init);
set_backlight_pwm(dev, PIPEB_REG(BACKLIGHT_CTL),
config->gpu_pipeb_pwm_freq_hz);
}
}
static void gfx_init(device_t dev)
{
/* Pre VBIOS Init */
gfx_pre_vbios_init(dev);
/* Power Management Init */
gfx_pm_init(dev);
gfx_panel_setup(dev);
/* Run VBIOS */
pci_dev_init(dev);
/* Post VBIOS Init */
gfx_post_vbios_init(dev);
}
static struct device_operations gfx_device_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = gfx_init,
.ops_pci = &soc_pci_ops,
};
static const struct pci_driver gfx_driver __pci_driver = {
.ops = &gfx_device_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.device = GFX_DEVID,
};

View File

@ -0,0 +1,245 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 <device/pci.h>
#include <console/console.h>
#include <soc/gpio.h>
#include <soc/pmc.h>
#include <soc/smm.h>
/* GPIO-to-Pad LUTs */
static const u8 gpncore_gpio_to_pad[GPNCORE_COUNT] =
{ 19, 18, 17, 20, 21, 22, 24, 25, /* [ 0: 7] */
23, 16, 14, 15, 12, 26, 27, 1, /* [ 8:15] */
4, 8, 11, 0, 3, 6, 10, 13, /* [16:23] */
2, 5, 9 }; /* [24:26] */
static const u8 gpscore_gpio_to_pad[GPSCORE_COUNT] =
{ 85, 89, 93, 96, 99, 102, 98, 101, /* [ 0: 7] */
34, 37, 36, 38, 39, 35, 40, 84, /* [ 8: 15] */
62, 61, 64, 59, 54, 56, 60, 55, /* [16: 23] */
63, 57, 51, 50, 53, 47, 52, 49, /* [24: 31] */
48, 43, 46, 41, 45, 42, 58, 44, /* [32: 39] */
95, 105, 70, 68, 67, 66, 69, 71, /* [40: 47] */
65, 72, 86, 90, 88, 92, 103, 77, /* [48: 55] */
79, 83, 78, 81, 80, 82, 13, 12, /* [56: 63] */
15, 14, 17, 18, 19, 16, 2, 1, /* [64: 71] */
0, 4, 6, 7, 9, 8, 33, 32, /* [72: 79] */
31, 30, 29, 27, 25, 28, 26, 23, /* [80: 87] */
21, 20, 24, 22, 5, 3, 10, 11, /* [88: 95] */
106, 87, 91, 104, 97, 100 }; /* [96:101] */
static const u8 gpssus_gpio_to_pad[GPSSUS_COUNT] =
{ 29, 33, 30, 31, 32, 34, 36, 35, /* [ 0: 7] */
38, 37, 18, 7, 11, 20, 17, 1, /* [ 8:15] */
8, 10, 19, 12, 0, 2, 23, 39, /* [16:23] */
28, 27, 22, 21, 24, 25, 26, 51, /* [24:31] */
56, 54, 49, 55, 48, 57, 50, 58, /* [32:39] */
52, 53, 59, 40 }; /* [40:43] */
/* GPIO bank descriptions */
static const struct gpio_bank gpncore_bank = {
.gpio_count = GPNCORE_COUNT,
.gpio_to_pad = gpncore_gpio_to_pad,
.legacy_base = GP_LEGACY_BASE_NONE,
.pad_base = GPNCORE_PAD_BASE,
.has_wake_en = 0,
.gpio_f1_range_start = GPNCORE_GPIO_F1_RANGE_START,
.gpio_f1_range_end = GPNCORE_GPIO_F1_RANGE_END,
};
static const struct gpio_bank gpscore_bank = {
.gpio_count = GPSCORE_COUNT,
.gpio_to_pad = gpscore_gpio_to_pad,
.legacy_base = GPSCORE_LEGACY_BASE,
.pad_base = GPSCORE_PAD_BASE,
.has_wake_en = 0,
.gpio_f1_range_start = GPSCORE_GPIO_F1_RANGE_START,
.gpio_f1_range_end = GPSCORE_GPIO_F1_RANGE_END,
};
static const struct gpio_bank gpssus_bank = {
.gpio_count = GPSSUS_COUNT,
.gpio_to_pad = gpssus_gpio_to_pad,
.legacy_base = GPSSUS_LEGACY_BASE,
.pad_base = GPSSUS_PAD_BASE,
.has_wake_en = 1,
.gpio_f1_range_start = GPSSUS_GPIO_F1_RANGE_START,
.gpio_f1_range_end = GPSSUS_GPIO_F1_RANGE_END,
};
static void setup_gpios(const struct soc_gpio_map *gpios,
const struct gpio_bank *bank)
{
const struct soc_gpio_map *config;
int gpio = 0;
u32 reg, pad_conf0;
u8 set, bit;
u32 use_sel[4] = {0};
u32 io_sel[4] = {0};
u32 gp_lvl[4] = {0};
u32 tpe[4] = {0};
u32 tne[4] = {0};
u32 wake_en[4] = {0};
if (!gpios)
return;
for (config = gpios; config->pad_conf0 != GPIO_LIST_END;
config++, gpio++) {
if (gpio > bank->gpio_count)
break;
set = gpio >> 5;
bit = gpio % 32;
if (bank->legacy_base != GP_LEGACY_BASE_NONE) {
/* Legacy IO configuration */
use_sel[set] |= config->use_sel << bit;
io_sel[set] |= config->io_sel << bit;
gp_lvl[set] |= config->gp_lvl << bit;
tpe[set] |= config->tpe << bit;
tne[set] |= config->tne << bit;
/* Some banks do not have wake_en ability */
if (bank->has_wake_en)
wake_en[set] |= config->wake_en << bit;
}
/* Pad configuration registers */
reg = bank->pad_base + 16 * bank->gpio_to_pad[gpio];
/* Add correct func to GPIO pad config */
pad_conf0 = config->pad_conf0;
if (config->is_gpio)
{
if (gpio >= bank->gpio_f1_range_start &&
gpio <= bank->gpio_f1_range_end)
pad_conf0 |= PAD_FUNC1;
else
pad_conf0 |= PAD_FUNC0;
}
#ifdef GPIO_DEBUG
printk(BIOS_DEBUG, "Write Pad: Base(%x) - %x %x %x\n",
reg, pad_conf0, config->pad_conf1, config->pad_val);
#endif
write32((u32 *)(reg + PAD_CONF0_REG), pad_conf0);
write32((u32 *)(reg + PAD_CONF1_REG), config->pad_conf1);
write32((u32 *)(reg + PAD_VAL_REG), config->pad_val);
}
if (bank->legacy_base != GP_LEGACY_BASE_NONE)
for (set = 0; set <= (bank->gpio_count - 1) / 32; ++set) {
reg = bank->legacy_base + 0x20 * set;
#ifdef GPIO_DEBUG
printk(BIOS_DEBUG,
"Write GPIO: Reg(%x) - %x %x %x %x %x\n",
reg, use_sel[set], io_sel[set], gp_lvl[set],
tpe[set], tne[set]);
#endif
outl(use_sel[set], reg + LEGACY_USE_SEL_REG);
outl(io_sel[set], reg + LEGACY_IO_SEL_REG);
outl(gp_lvl[set], reg + LEGACY_GP_LVL_REG);
outl(tpe[set], reg + LEGACY_TPE_REG);
outl(tne[set], reg + LEGACY_TNE_REG);
/* TS registers are WOC */
outl(0, reg + LEGACY_TS_REG);
if (bank->has_wake_en)
outl(wake_en[set], reg + LEGACY_WAKE_EN_REG);
}
}
static void setup_gpio_route(const struct soc_gpio_map *sus,
const struct soc_gpio_map *core)
{
uint32_t route_reg = 0;
int i;
for (i = 0; i < 8; i++) {
/* SMI takes precedence and wake_en implies SCI. */
if (sus[i].smi) {
route_reg |= ROUTE_SMI << (2 * i);
} else if (sus[i].sci) {
route_reg |= ROUTE_SCI << (2 * i);
}
if (core[i].smi) {
route_reg |= ROUTE_SMI << (2 * (i + 8));
} else if (core[i].sci) {
route_reg |= ROUTE_SCI << (2 * (i + 8));
}
}
southcluster_smm_save_param(SMM_SAVE_PARAM_GPIO_ROUTE, route_reg);
}
static void setup_dirqs(const u8 dirq[GPIO_MAX_DIRQS],
const struct gpio_bank *bank)
{
u32 *reg = (u32 *)(bank->pad_base + PAD_BASE_DIRQ_OFFSET);
u32 val;
int i;
/* Write all four DIRQ registers */
for (i=0; i<4; ++i) {
val = dirq[i * 4 + 3] << 24 | dirq[i * 4 + 2] << 16 |
dirq[i * 4 + 1] << 8 | dirq[i * 4];
write32(reg + i, val);
#ifdef GPIO_DEBUG
printk(BIOS_DEBUG, "Write DIRQ reg(%x) - %x\n",
reg + i, val);
#endif
}
}
void setup_soc_gpios(struct soc_gpio_config *config, u8 enable_xdp_tap)
{
if (config) {
setup_gpios(config->ncore, &gpncore_bank);
setup_gpios(config->score, &gpscore_bank);
setup_gpios(config->ssus, &gpssus_bank);
setup_gpio_route(config->ssus, config->score);
if (config->core_dirq)
setup_dirqs(*config->core_dirq, &gpscore_bank);
if (config->sus_dirq)
setup_dirqs(*config->sus_dirq, &gpssus_bank);
}
/* Set on die termination feature with pull up value and
* drive the pad high for TAP_TDO and TAP_TMS
*/
if (!enable_xdp_tap) {
printk(BIOS_DEBUG, "Tri-state TDO and TMS\n");
write32((u32 *)(GPSSUS_PAD_BASE + 0x2fc), 0xc);
write32((u32 *)(GPSSUS_PAD_BASE + 0x2cc), 0xc);
}
}
struct soc_gpio_config* __attribute__((weak)) mainboard_get_gpios(void)
{
printk(BIOS_DEBUG, "Default/empty GPIO config\n");
return NULL;
}

View File

@ -0,0 +1,118 @@
/*
* 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.h>
#include <device/pci_def.h>
#include <device/pci_ids.h>
#include <reg_script.h>
#include <soc/intel/common/hda_verb.h>
#include <soc/iomap.h>
#include <soc/iosf.h>
#include <soc/pci_devs.h>
#include <soc/ramstage.h>
static const struct reg_script init_ops[] = {
/* Enable no snoop traffic. */
REG_PCI_OR16(0x78, 1 << 11),
/* Configure HDMI codec connection. */
REG_PCI_OR32(0xc4, 1 << 1),
REG_PCI_OR8(0x43, (1 << 3) | (1 << 6)),
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xc0),
REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0x00),
/* Configure internal settings. */
REG_PCI_OR32(0xc0, 0x7 << 21),
REG_PCI_OR32(0xc4, (0x3 << 26) | (1 << 13) | (1 << 10)),
REG_PCI_WRITE32(0xc8, 0x82a30000),
REG_PCI_RMW32(0xd0, ~(1 << 31), 0x0),
/* Disable docking. */
REG_PCI_RMW8(0x4d, ~(1 << 7), 0),
REG_SCRIPT_END,
};
static const uint32_t hdmi_codec_verb_table[] = {
/* coreboot specific header */
0x80862882, /* vid did for hdmi codec */
0x00000000, /* subsystem id */
0x00000003, /* number of jacks */
/* pin widget 5 - port B */
0x20471c10,
0x20471d00,
0x20471e56,
0x20471f18,
/* pin widget 6 - port C */
0x20571c20,
0x20571d00,
0x20571e56,
0x20571f18,
/* pin widget 7 - port D */
0x20671c30,
0x20671d00,
0x20671e56,
0x20671f58,
};
static void hda_init(device_t dev)
{
struct resource *res;
int codec_mask;
int i;
u8 *base;
reg_script_run_on_dev(dev, init_ops);
res = find_resource(dev, PCI_BASE_ADDRESS_0);
if (res == NULL)
return;
base = res2mmio(res, 0, 0);
codec_mask = hda_codec_detect(base);
printk(BIOS_DEBUG, "codec mask = %x\n", codec_mask);
if (!codec_mask)
return;
for (i = 3; i >= 0; i--) {
if (!((1 << i) & codec_mask))
continue;
hda_codec_init(base, i, sizeof(hdmi_codec_verb_table),
hdmi_codec_verb_table);
}
}
static const struct device_operations device_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = hda_init,
.enable = NULL,
.scan_bus = NULL,
.ops_pci = &soc_pci_ops,
};
static const struct pci_driver southcluster __pci_driver = {
.ops = &device_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.device = HDA_DEVID,
};

View File

@ -0,0 +1,31 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 _BAYTRAIL_ACPI_H_
#define _BAYTRAIL_ACPI_H_
#include <arch/acpi.h>
#include <soc/nvs.h>
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 /* _BAYTRAIL_ACPI_H_ */

View File

@ -0,0 +1,68 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 _BAYTRAIL_DEVICE_NVS_H_
#define _BAYTRAIL_DEVICE_NVS_H_
#include <stdint.h>
/* Offset in Global NVS where this structure lives */
#define DEVICE_NVS_OFFSET 0x1000
#define LPSS_NVS_SIO_DMA1 0
#define LPSS_NVS_I2C1 1
#define LPSS_NVS_I2C2 2
#define LPSS_NVS_I2C3 3
#define LPSS_NVS_I2C4 4
#define LPSS_NVS_I2C5 5
#define LPSS_NVS_I2C6 6
#define LPSS_NVS_I2C7 7
#define LPSS_NVS_SIO_DMA2 8
#define LPSS_NVS_SPI 9
#define LPSS_NVS_PWM1 10
#define LPSS_NVS_PWM2 11
#define LPSS_NVS_HSUART1 12
#define LPSS_NVS_HSUART2 13
#define SCC_NVS_MMC 0
#define SCC_NVS_SDIO 1
#define SCC_NVS_SD 2
typedef struct {
/* Device Enabled in ACPI Mode */
u8 lpss_en[14];
u8 scc_en[3];
u8 lpe_en;
/* BAR 0 */
u32 lpss_bar0[14];
u32 scc_bar0[3];
u32 lpe_bar0;
/* BAR 0 */
u32 lpss_bar1[14];
u32 scc_bar1[3];
u32 lpe_bar1;
/* Extra */
u32 lpe_fw; /* LPE Firmware */
u8 rsvd1[3930]; /* Add padding so sizeof(device_nvs_t) == 0x1000 */
} __attribute__((packed)) device_nvs_t;
#endif

View File

@ -0,0 +1,52 @@
/*
* PEI EFI entry point
*
* Copyright 2013 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 __EFI_WRAPPER_H__
#define __EFI_WRAPPER_H__
#define EFI_WRAPPER_VER 2
/* Provide generic x86 calling conventions. */
#define ABI_X86 __attribute((regparm(0)))
/* Errors returned by the EFI wrapper. */
enum efi_wrapper_error {
INVALID_VER = -1,
};
struct efi_wrapper_params {
/* Mainboard Inputs */
int version;
void ABI_X86 (*console_out)(unsigned char byte);
unsigned int tsc_ticks_per_microsecond;
} __attribute__((packed));
typedef int ABI_X86 (*efi_wrapper_entry_t)(struct efi_wrapper_params *);
#endif

View File

@ -0,0 +1,44 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 BAYTRAIL_EHCI_H
#define BAYTRAIL_EHCI_H
/* EHCI PCI Registers */
#define EHCI_CMD_STS 0x04
# define INTRDIS (1 << 10)
#define EHCI_SBRN_FLA_PWC 0x60
# define PORTWKIMP (1 << 16)
# define PORTWKCAPMASK (0x3ff << 17)
#define EHCI_USB2PDO 0x64
/* EHCI Memory Registers */
#define USB2CMD 0x20
# define USB2CMD_ASE (1 << 5)
# define USB2CMD_PSE (1 << 4)
# define USB2CMD_HCRESET (1 << 1)
# define USB2CMD_RS (1 << 0)
#define USB2STS 0x24
# define USB2STS_HCHALT (1 << 12)
/* RCBA EHCI Registers */
#define RCBA_FUNC_DIS 0x220
# define RCBA_EHCI_DIS (1 << 0)
#endif /* BAYTRAIL_EHCI_H */

View File

@ -0,0 +1,64 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 _BAYTRAIL_GFX_H_
#define _BAYTRAIL_GFX_H_
/*
* PCI config registers.
*/
#define GGC 0x50
# define GGC_VGA_DISABLE (1 << 1)
# define GGC_GTT_SIZE_MASK (3 << 8)
# define GGC_GTT_SIZE_0MB (0 << 8)
# define GGC_GTT_SIZE_1MB (1 << 8)
# define GGC_GTT_SIZE_2MB (2 << 8)
# define GGC_GSM_SIZE_MASK (0x1f << 3)
# define GGC_GSM_SIZE_0MB (0 << 3)
# define GGC_GSM_SIZE_32MB (1 << 3)
# define GGC_GSM_SIZE_64MB (2 << 3)
# define GGC_GSM_SIZE_128MB (4 << 3)
#define GSM_BASE 0x5c
#define GTT_BASE 0x70
#define MSAC 0x62
#define APERTURE_SIZE_MASK (3 << 1)
#define APERTURE_SIZE_128MB (0 << 1)
#define APERTURE_SIZE_256MB (1 << 1)
#define APERTURE_SIZE_512MB (3 << 1)
#define VLV_DISPLAY_BASE 0x180000
#define PIPEA_REG(reg) (VLV_DISPLAY_BASE + (reg))
#define PIPEB_REG(reg) (VLV_DISPLAY_BASE + 0x100 + (reg))
/* Panel control registers */
#define HOTPLUG_CTRL 0x61110
#define PP_CONTROL 0x61204
#define PP_CONTROL_UNLOCK 0xabcd0000
#define PP_CONTROL_EDP_FORCE_VDD (1 << 3)
#define PP_ON_DELAYS 0x61208
#define PP_OFF_DELAYS 0x6120c
#define PP_DIVISOR 0x61210
#define BACKLIGHT_CTL2 0x61250
#define BACKLIGHT_ENABLE (1 << 31)
#define BACKLIGHT_CTL 0x61254
#endif /* _BAYTRAIL_GFX_H_ */

View File

@ -0,0 +1,459 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 _BAYTRAIL_GPIO_H_
#define _BAYTRAIL_GPIO_H_
#include <stdint.h>
#include <arch/io.h>
#include <soc/iomap.h>
/* #define GPIO_DEBUG */
/* Pad base, ex. PAD_CONF0[n]= PAD_BASE+16*n */
#define GPSCORE_PAD_BASE (IO_BASE_ADDRESS + IO_BASE_OFFSET_GPSCORE)
#define GPNCORE_PAD_BASE (IO_BASE_ADDRESS + IO_BASE_OFFSET_GPNCORE)
#define GPSSUS_PAD_BASE (IO_BASE_ADDRESS + IO_BASE_OFFSET_GPSSUS)
/* DIRQ registers start at pad base + 0x980 */
#define PAD_BASE_DIRQ_OFFSET 0x980
/* Pad register offset */
#define PAD_CONF0_REG 0x0
#define PAD_CONF1_REG 0x4
#define PAD_VAL_REG 0x8
/* Legacy IO register base */
#define GPSCORE_LEGACY_BASE (GPIO_BASE_ADDRESS + 0x00)
#define GPSSUS_LEGACY_BASE (GPIO_BASE_ADDRESS + 0x80)
/* Some banks have no legacy GPIO interface */
#define GP_LEGACY_BASE_NONE 0xFFFF
#define LEGACY_USE_SEL_REG 0x00
#define LEGACY_IO_SEL_REG 0x04
#define LEGACY_GP_LVL_REG 0x08
#define LEGACY_TPE_REG 0x0C
#define LEGACY_TNE_REG 0x10
#define LEGACY_TS_REG 0x14
#define LEGACY_WAKE_EN_REG 0x18
/* Number of GPIOs in each bank */
#define GPNCORE_COUNT 27
#define GPSCORE_COUNT 102
#define GPSSUS_COUNT 44
/* GPIO legacy IO register settings */
#define GPIO_USE_MMIO 0
#define GPIO_USE_LEGACY 1
#define GPIO_DIR_OUTPUT 0
#define GPIO_DIR_INPUT 1
#define GPIO_LEVEL_LOW 0
#define GPIO_LEVEL_HIGH 1
#define GPIO_PEDGE_DISABLE 0
#define GPIO_PEDGE_ENABLE 1
#define GPIO_NEDGE_DISABLE 0
#define GPIO_NEDGE_ENABLE 1
/* config0[29] - Disable second mask */
#define PAD_MASK2_DISABLE (1 << 29)
/* config0[27] - Direct Irq En */
#define PAD_IRQ_EN (1 << 27)
/* config0[26] - gd_tne */
#define PAD_TNE_IRQ (1 << 26)
/* config0[25] - gd_tpe */
#define PAD_TPE_IRQ (1 << 25)
/* config0[24] - Gd Level */
#define PAD_LEVEL_IRQ (1 << 24)
#define PAD_EDGE_IRQ (0 << 24)
/* config0[17] - Slow clkgate / glitch filter */
#define PAD_SLOWGF_ENABLE (1 << 17)
/* config0[16] - Fast clkgate / glitch filter */
#define PAD_FASTGF_ENABLE (1 << 16)
/* config0[15] - Hysteresis enable (inverted) */
#define PAD_HYST_DISABLE (1 << 15)
#define PAD_HYST_ENABLE (0 << 15)
/* config0[14:13] - Hysteresis control */
#define PAD_HYST_CTRL_DEFAULT (2 << 13)
/* config0[11] - Bypass Flop */
#define PAD_FLOP_BYPASS (1 << 11)
#define PAD_FLOP_ENABLE (0 << 11)
/* config0[10:9] - Pull str */
#define PAD_PU_2K (0 << 9)
#define PAD_PU_10K (1 << 9)
#define PAD_PU_20K (2 << 9)
#define PAD_PU_40K (3 << 9)
/* config0[8:7] - Pull assign */
#define PAD_PULL_DISABLE (0 << 7)
#define PAD_PULL_UP (1 << 7)
#define PAD_PULL_DOWN (2 << 7)
/* config0[2:0] - Func. pin mux */
#define PAD_FUNC0 0x0
#define PAD_FUNC1 0x1
#define PAD_FUNC2 0x2
#define PAD_FUNC3 0x3
#define PAD_FUNC4 0x4
#define PAD_FUNC5 0x5
#define PAD_FUNC6 0x6
/* pad config0 power-on values - We will not often want to change these */
#define PAD_CONFIG0_DEFAULT (PAD_MASK2_DISABLE | PAD_SLOWGF_ENABLE | \
PAD_FASTGF_ENABLE | PAD_HYST_DISABLE | \
PAD_HYST_CTRL_DEFAULT | PAD_FLOP_BYPASS)
/* pad config1 reg power-on values - Shouldn't need to change this */
#define PAD_CONFIG1_DEFAULT 0x8000
/* pad_val[2] - Iinenb - active low */
#define PAD_VAL_INPUT_DISABLE (1 << 2)
#define PAD_VAL_INPUT_ENABLE (0 << 2)
/* pad_val[1] - Ioutenb - active low */
#define PAD_VAL_OUTPUT_DISABLE (1 << 1)
#define PAD_VAL_OUTPUT_ENABLE (0 << 1)
/* Input / Output state should usually be mutually exclusive */
#define PAD_VAL_INPUT (PAD_VAL_INPUT_ENABLE | PAD_VAL_OUTPUT_DISABLE)
#define PAD_VAL_OUTPUT (PAD_VAL_OUTPUT_ENABLE | PAD_VAL_INPUT_DISABLE)
/* pad_val[0] - Value */
#define PAD_VAL_HIGH (1 << 0)
#define PAD_VAL_LOW (0 << 0)
/* pad_val reg power-on default varies by pad, and apparently can cause issues
* if not set correctly, even if the pin isn't configured as GPIO. */
#define PAD_VAL_DEFAULT PAD_VAL_INPUT
/* Configure GPIOs as MMIO by default */
#define GPIO_INPUT_PU_10K \
{ .pad_conf0 = PAD_PU_10K | PAD_PULL_UP | PAD_CONFIG0_DEFAULT, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_INPUT, \
.use_sel = GPIO_USE_MMIO, \
.is_gpio = 1 }
#define GPIO_INPUT_PU_20K \
{ .pad_conf0 = PAD_PU_20K | PAD_PULL_UP | PAD_CONFIG0_DEFAULT, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_INPUT, \
.use_sel = GPIO_USE_MMIO, \
.is_gpio = 1 }
#define GPIO_INPUT_PD_10K \
{ .pad_conf0 = PAD_PU_10K | PAD_PULL_DOWN | PAD_CONFIG0_DEFAULT, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_INPUT, \
.use_sel = GPIO_USE_MMIO, \
.is_gpio = 1 }
#define GPIO_INPUT_PD_20K \
{ .pad_conf0 = PAD_PU_20K | PAD_PULL_DOWN | PAD_CONFIG0_DEFAULT, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_INPUT, \
.use_sel = GPIO_USE_MMIO, \
.is_gpio = 1 }
#define GPIO_INPUT_NOPU \
{ .pad_conf0 = PAD_PU_20K | PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_INPUT, \
.use_sel = GPIO_USE_MMIO, \
.is_gpio = 1 }
#define GPIO_INPUT_LEGACY_NOPU \
{ .pad_conf0 = PAD_PU_20K | PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_INPUT, \
.use_sel = GPIO_USE_LEGACY, \
.io_sel = GPIO_DIR_INPUT, \
.is_gpio = 1 }
/* Direct / dedicated IRQ input - pass signal directly to apic */
#define GPIO_DIRQ \
{ .pad_conf0 = PAD_PU_20K | PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT \
| PAD_FUNC0 | PAD_IRQ_EN | PAD_TPE_IRQ | PAD_LEVEL_IRQ, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_INPUT, }
/* Direct / dedicated IRQ input - pass signal directly to apic */
#define GPIO_DIRQ_LEVELHIGH_NO_PULL \
{ .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT \
| PAD_FUNC0 | PAD_IRQ_EN | PAD_TPE_IRQ | PAD_LEVEL_IRQ, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_INPUT, }
/* Direct / dedicated IRQ input - pass signal directly to apic */
#define GPIO_DIRQ_LEVELLOW_PU_20K \
{ .pad_conf0 = PAD_PU_20K | PAD_PULL_UP | PAD_CONFIG0_DEFAULT \
| PAD_FUNC0 | PAD_IRQ_EN | PAD_TNE_IRQ | PAD_LEVEL_IRQ, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_INPUT, }
/* Direct / dedicated IRQ input - pass signal directly to apic */
#define GPIO_DIRQ_EDGELOW_PU_20K \
{ .pad_conf0 = PAD_PU_20K | PAD_PULL_UP | PAD_CONFIG0_DEFAULT \
| PAD_FUNC0 | PAD_IRQ_EN | PAD_TNE_IRQ | PAD_EDGE_IRQ, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_INPUT, }
/* Direct / dedicated IRQ input - pass signal directly to apic */
#define GPIO_DIRQ_EDGEHIGH_PD_20K \
{ .pad_conf0 = PAD_PU_20K | PAD_PULL_DOWN | PAD_CONFIG0_DEFAULT \
| PAD_FUNC0 | PAD_IRQ_EN | PAD_TPE_IRQ | PAD_EDGE_IRQ, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_INPUT, }
/* Direct / dedicated IRQ input - pass signal directly to apic */
#define GPIO_DIRQ_EDGELOW_PD_20K \
{ .pad_conf0 = PAD_PU_20K | PAD_PULL_DOWN | PAD_CONFIG0_DEFAULT \
| PAD_FUNC0 | PAD_IRQ_EN | PAD_TNE_IRQ | PAD_EDGE_IRQ, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_INPUT, }
/* Direct / dedicated IRQ input - pass signal directly to apic */
#define GPIO_DIRQ_EDGEBOTH_PU_20K \
{ .pad_conf0 = PAD_PU_20K | PAD_PULL_UP | PAD_CONFIG0_DEFAULT \
| PAD_FUNC0 | PAD_IRQ_EN | PAD_TPE_IRQ| PAD_TNE_IRQ | PAD_EDGE_IRQ, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_INPUT, }
#define GPIO_OUT_LOW \
{ .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_OUTPUT | PAD_VAL_LOW, \
.use_sel = GPIO_USE_LEGACY, \
.io_sel = GPIO_DIR_OUTPUT, \
.gp_lvl = GPIO_LEVEL_LOW, \
.is_gpio = 1 }
#define GPIO_OUT_HIGH \
{ .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_OUTPUT | PAD_VAL_HIGH, \
.use_sel = GPIO_USE_LEGACY, \
.io_sel = GPIO_DIR_OUTPUT, \
.gp_lvl = GPIO_LEVEL_HIGH, \
.is_gpio = 1 }
/* Define no-pull / PU / PD configs for each functional config option */
#define GPIO_FUNC(_func, _pudir, _str) \
{ .use_sel = GPIO_USE_MMIO, \
.pad_conf0 = PAD_FUNC##_func | PAD_##_pudir | PAD_PU_##_str | \
PAD_CONFIG0_DEFAULT, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_DEFAULT }
/* Default functional configs -- no PU */
#define GPIO_FUNC0 GPIO_FUNC(0, PULL_DISABLE, 20K)
#define GPIO_FUNC1 GPIO_FUNC(1, PULL_DISABLE, 20K)
#define GPIO_FUNC2 GPIO_FUNC(2, PULL_DISABLE, 20K)
#define GPIO_FUNC3 GPIO_FUNC(3, PULL_DISABLE, 20K)
#define GPIO_FUNC4 GPIO_FUNC(4, PULL_DISABLE, 20K)
#define GPIO_FUNC5 GPIO_FUNC(5, PULL_DISABLE, 20K)
#define GPIO_FUNC6 GPIO_FUNC(6, PULL_DISABLE, 20K)
/* ACPI GPIO routing. Assume everything is externally pulled and negative edge
* triggered. SCI implies WAKE, but WAKE doesn't imply SCI. */
#define GPIO_ACPI_SCI \
{ .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT | PAD_FUNC0, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_INPUT, \
.use_sel = GPIO_USE_LEGACY, \
.io_sel = GPIO_DIR_INPUT, \
.tne = 1, \
.sci = 1, \
.wake_en = 1, }
#define GPIO_ACPI_WAKE \
{ .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT | PAD_FUNC0, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_INPUT, \
.use_sel = GPIO_USE_LEGACY, \
.io_sel = GPIO_DIR_INPUT, \
.tne = 1, \
.wake_en = 1, }
#define GPIO_ACPI_SMI \
{ .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT | PAD_FUNC0, \
.pad_conf1 = PAD_CONFIG1_DEFAULT, \
.pad_val = PAD_VAL_INPUT, \
.use_sel = GPIO_USE_LEGACY, \
.io_sel = GPIO_DIR_INPUT, \
.tne = 1, \
.smi = 1}
/* End marker */
#define GPIO_LIST_END 0xffffffff
#define GPIO_END \
{ .pad_conf0 = GPIO_LIST_END }
/* Common default GPIO settings */
#define GPIO_INPUT GPIO_INPUT_NOPU
#define GPIO_INPUT_LEGACY GPIO_INPUT_LEGACY_NOPU
#define GPIO_INPUT_PU GPIO_INPUT_PU_20K
#define GPIO_INPUT_PD GPIO_INPUT_PD_20K
#define GPIO_NC GPIO_OUT_HIGH
#define GPIO_DEFAULT GPIO_FUNC0
/* 16 DirectIRQs per supported bank */
#define GPIO_MAX_DIRQS 16
/* Most pins are GPIO function 0. Some banks have a range of pins with GPIO
* function 1. Indicate first / last GPIOs with function 1. */
#define GPIO_NONE 255
/* All NCORE GPIOs are function 0 */
#define GPNCORE_GPIO_F1_RANGE_START GPIO_NONE
#define GPNCORE_GPIO_F1_RANGE_END GPIO_NONE
/* SCORE GPIO [92:93] are function 1 */
#define GPSCORE_GPIO_F1_RANGE_START 92
#define GPSCORE_GPIO_F1_RANGE_END 93
/* SSUS GPIO [11:21] are function 1 */
#define GPSSUS_GPIO_F1_RANGE_START 11
#define GPSSUS_GPIO_F1_RANGE_END 21
struct soc_gpio_map {
u32 pad_conf0;
u32 pad_conf1;
u32 pad_val;
u32 use_sel : 1;
u32 io_sel : 1;
u32 gp_lvl : 1;
u32 tpe : 1;
u32 tne : 1;
u32 wake_en : 1;
u32 smi : 1;
u32 is_gpio : 1;
u32 sci : 1;
} __attribute__ ((packed));
struct soc_gpio_config {
const struct soc_gpio_map *ncore;
const struct soc_gpio_map *score;
const struct soc_gpio_map *ssus;
const u8 (*core_dirq)[GPIO_MAX_DIRQS];
const u8 (*sus_dirq)[GPIO_MAX_DIRQS];
};
/* Description of GPIO 'bank' ex. {ncore, score. ssus} */
struct gpio_bank {
const int gpio_count;
const u8* gpio_to_pad;
const int legacy_base;
const unsigned long pad_base;
const u8 has_wake_en :1;
const u8 gpio_f1_range_start;
const u8 gpio_f1_range_end;
};
void setup_soc_gpios(struct soc_gpio_config *config, u8 enable_xdp_tap);
/* This function is weak and can be overridden by a mainboard function. */
struct soc_gpio_config* mainboard_get_gpios(void);
/* Functions / defines for changing GPIOs in romstage */
/* SCORE Pad definitions. */
#define UART_RXD_PAD 82
#define UART_TXD_PAD 83
#define PCU_SMB_CLK_PAD 88
#define PCU_SMB_DATA_PAD 90
#define SOC_DDI1_VDDEN_PAD 16
static inline u32 *ncore_pconf0(int pad_num)
{
return (u32 *)(GPNCORE_PAD_BASE + pad_num * 16);
}
static inline void ncore_select_func(int pad, int func)
{
uint32_t reg;
u32 *pconf0_addr = ncore_pconf0(pad);
reg = read32(pconf0_addr);
reg &= ~0x7;
reg |= func & 0x7;
write32(pconf0_addr, reg);
}
static inline u32 *score_pconf0(int pad_num)
{
return (u32 *)(GPSCORE_PAD_BASE + pad_num * 16);
}
static inline u32 *ssus_pconf0(int pad_num)
{
return (u32 *)(GPSSUS_PAD_BASE + pad_num * 16);
}
static inline void score_select_func(int pad, int func)
{
uint32_t reg;
uint32_t *pconf0_addr = score_pconf0(pad);
reg = read32(pconf0_addr);
reg &= ~0x7;
reg |= func & 0x7;
write32(pconf0_addr, reg);
}
static inline void ssus_select_func(int pad, int func)
{
uint32_t reg;
uint32_t *pconf0_addr = ssus_pconf0(pad);
reg = read32(pconf0_addr);
reg &= ~0x7;
reg |= func & 0x7;
write32(pconf0_addr, reg);
}
/* These functions require that the input pad be configured as an input GPIO */
static inline int score_get_gpio(int pad)
{
uint32_t *val_addr = score_pconf0(pad) + (PAD_VAL_REG/sizeof(uint32_t));
return read32(val_addr) & PAD_VAL_HIGH;
}
static inline int ssus_get_gpio(int pad)
{
uint32_t *val_addr = ssus_pconf0(pad) + (PAD_VAL_REG/sizeof(uint32_t));
return read32(val_addr) & PAD_VAL_HIGH;
}
static inline void ssus_disable_internal_pull(int pad)
{
const uint32_t pull_mask = ~(0xf << 7);
write32(ssus_pconf0(pad), read32(ssus_pconf0(pad)) & pull_mask);
}
#endif /* _BAYTRAIL_GPIO_H_ */

View File

@ -0,0 +1,90 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 _BAYTRAIL_IOMAP_H_
#define _BAYTRAIL_IOMAP_H_
/*
* Memory Mapped IO bases.
*/
/* PCI Configuration Space */
#define MCFG_BASE_ADDRESS CONFIG_MMCONF_BASE_ADDRESS
#define MCFG_BASE_SIZE 0x10000000
/* Transactions in this range will abort */
#define ABORT_BASE_ADDRESS 0xfeb00000
#define ABORT_BASE_SIZE 0x00100000
/* Power Management Controller */
#define PMC_BASE_ADDRESS 0xfed03000
#define PMC_BASE_SIZE 0x400
/* IO Memory */
#define IO_BASE_ADDRESS 0xfed0c000
#define IO_BASE_OFFSET_GPSCORE 0x0000
#define IO_BASE_OFFSET_GPNCORE 0x1000
#define IO_BASE_OFFSET_GPSSUS 0x2000
#define IO_BASE_SIZE 0x4000
/* Intel Legacy Block */
#define ILB_BASE_ADDRESS 0xfed08000
#define ILB_BASE_SIZE 0x400
/* SPI Bus */
#define SPI_BASE_ADDRESS 0xfed01000
#define SPI_BASE_SIZE 0x400
/* MODPHY */
#define MPHY_BASE_ADDRESS 0xfef00000
#define MPHY_BASE_SIZE 0x100000
/* Power Management Unit */
#define PUNIT_BASE_ADDRESS 0xfed05000
#define PUNIT_BASE_SIZE 0x800
/* Root Complex Base Address */
#define RCBA_BASE_ADDRESS 0xfed1c000
#define RCBA_BASE_SIZE 0x400
/* High Performance Event Timer */
#define HPET_BASE_ADDRESS 0xfed00000
#define HPET_BASE_SIZE 0x400
/* Temporary Base Address */
#define TEMP_BASE_ADDRESS 0xfd000000
/*
* IO Port bases.
*/
#define ACPI_BASE_ADDRESS 0x0400
#define ACPI_BASE_SIZE 0x80
#define GPIO_BASE_ADDRESS 0x0500
#define GPIO_BASE_SIZE 0x100
#define SMBUS_BASE_ADDRESS 0xefa0
#ifndef __ACPI__
/* Read Top of Low Memory (BMBOUND) */
uint32_t nc_read_top_of_low_memory(void);
#endif
#endif /* _BAYTRAIL_IOMAP_H_ */

View File

@ -0,0 +1,349 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 _BAYTRAIL_IOSF_H_
#define _BAYTRAIL_IOSF_H_
#include <stdint.h>
#include <soc/pci_devs.h>
/*
* The Bay Trail SoC has a message network called IOSF Sideband. The access
* routines are through 3 registers in PCI config space of 00:00.0:
* MCR - control register
* MDR - data register
* MCRX - control register extension
* The extension regist is only used for addresses that don't fit into the
* 8 bit register address.
*/
#ifndef PCI_DEV
#define PCI_DEV(SEGBUS, DEV, FN) ( \
(((SEGBUS) & 0xFFF) << 20) | \
(((DEV) & 0x1F) << 15) | \
(((FN) & 0x07) << 12))
#endif
#define IOSF_PCI_DEV PCI_DEV(0,SOC_DEV,SOC_FUNC)
#define MCR_REG 0xd0
#define IOSF_OPCODE(x) ((x) << 24)
#define IOSF_PORT(x) ((0xff & (x)) << 16)
#define IOSF_REG(x) ((0xff & (x)) << 8)
#define IOSF_REG_UPPER(x) (((~0xff) & (x)))
#define IOSF_BYTE_EN_0 0x10
#define IOSF_BYTE_EN_1 0x20
#define IOSF_BYTE_EN_2 0x40
#define IOSF_BYTE_EN_3 0x80
#define IOSF_BYTE_EN \
(IOSF_BYTE_EN_0 | IOSF_BYTE_EN_1 | IOSF_BYTE_EN_2 | IOSF_BYTE_EN_3)
#define MDR_REG 0xd4
#define MCRX_REG 0xd8
uint32_t iosf_aunit_read(int reg);
void iosf_aunit_write(int reg, uint32_t val);
uint32_t iosf_cpu_bus_read(int reg);
void iosf_cpu_bus_write(int reg, uint32_t val);
uint32_t iosf_bunit_read(int reg);
void iosf_bunit_write(int reg, uint32_t val);
uint32_t iosf_dunit_read(int reg);
void iosf_dunit_write(int reg, uint32_t val);
/* Some registers are per channel while the globals live in dunit 0 */
uint32_t iosf_dunit_ch0_read(int reg);
uint32_t iosf_dunit_ch1_read(int reg);
uint32_t iosf_punit_read(int reg);
void iosf_punit_write(int reg, uint32_t val);
uint32_t iosf_usbphy_read(int reg);
void iosf_usbphy_write(int reg, uint32_t val);
uint32_t iosf_ushphy_read(int reg);
void iosf_ushphy_write(int reg, uint32_t val);
uint32_t iosf_sec_read(int reg);
void iosf_sec_write(int reg, uint32_t val);
uint32_t iosf_port45_read(int reg);
void iosf_port45_write(int reg, uint32_t val);
uint32_t iosf_port46_read(int reg);
void iosf_port46_write(int reg, uint32_t val);
uint32_t iosf_port47_read(int reg);
void iosf_port47_write(int reg, uint32_t val);
uint32_t iosf_port55_read(int reg);
void iosf_port55_write(int reg, uint32_t val);
uint32_t iosf_port58_read(int reg);
void iosf_port58_write(int reg, uint32_t val);
uint32_t iosf_port59_read(int reg);
void iosf_port59_write(int reg, uint32_t val);
uint32_t iosf_port5a_read(int reg);
void iosf_port5a_write(int reg, uint32_t val);
uint32_t iosf_lpss_read(int reg);
void iosf_lpss_write(int reg, uint32_t val);
uint32_t iosf_ccu_read(int reg);
void iosf_ccu_write(int reg, uint32_t val);
uint32_t iosf_score_read(int reg);
void iosf_score_write(int reg, uint32_t val);
uint32_t iosf_scc_read(int reg);
void iosf_scc_write(int reg, uint32_t val);
uint32_t iosf_porta2_read(int reg);
void iosf_porta2_write(int reg, uint32_t val);
uint32_t iosf_ssus_read(int reg);
void iosf_ssus_write(int reg, uint32_t val);
/* IOSF ports. */
#define IOSF_PORT_AUNIT 0x00 /* IO Arbiter unit */
#define IOSF_PORT_SYSMEMC 0x01 /* System Memory Controller */
#define IOSF_PORT_DUNIT_CH0 0x07 /* DUNIT Channel 0 */
#define IOSF_PORT_CPU_BUS 0x02 /* CPU Bus Interface Controller */
#define IOSF_PORT_BUNIT 0x03 /* System Memory Arbiter/Bunit */
#define IOSF_PORT_PMC 0x04 /* Power Management Controller */
#define IOSF_PORT_GFX 0x06 /* Graphics Adapter */
#define IOSF_PORT_DUNIT_CH1 0x07 /* DUNIT Channel 1 */
#define IOSF_PORT_SYSMEMIO 0x0c /* System Memory IO */
#define IOSF_PORT_USBPHY 0x43 /* USB PHY */
#define IOSF_PORT_SEC 0x44 /* SEC */
#define IOSF_PORT_0x45 0x45
#define IOSF_PORT_0x46 0x46
#define IOSF_PORT_0x47 0x47
#define IOSF_PORT_SCORE 0x48 /* SCORE */
#define IOSF_PORT_0x55 0x55
#define IOSF_PORT_0x58 0x58
#define IOSF_PORT_0x59 0x59
#define IOSF_PORT_0x5a 0x5a
#define IOSF_PORT_USHPHY 0x61 /* USB XHCI PHY */
#define IOSF_PORT_SCC 0x63 /* Storage Control Cluster */
#define IOSF_PORT_LPSS 0xa0 /* LPSS - Low Power Subsystem */
#define IOSF_PORT_0xa2 0xa2
#define IOSF_PORT_SATAPHY 0xa3 /* SATA PHY */
#define IOSF_PORT_PCIEPHY 0xa3 /* PCIE PHY */
#define IOSF_PORT_SSUS 0xa8 /* SUS */
#define IOSF_PORT_CCU 0xa9 /* Clock control unit. */
/* Read and write opcodes differ per port. */
#define IOSF_OP_READ_AUNIT 0x10
#define IOSF_OP_WRITE_AUNIT (IOSF_OP_READ_AUNIT | 1)
#define IOSF_OP_READ_SYSMEMC 0x10
#define IOSF_OP_WRITE_SYSMEMC (IOSF_OP_READ_SYSMEMC | 1)
#define IOSF_OP_READ_CPU_BUS 0x10
#define IOSF_OP_WRITE_CPU_BUS (IOSF_OP_READ_CPU_BUS | 1)
#define IOSF_OP_READ_BUNIT 0x10
#define IOSF_OP_WRITE_BUNIT (IOSF_OP_READ_BUNIT | 1)
#define IOSF_OP_READ_PMC 0x06
#define IOSF_OP_WRITE_PMC (IOSF_OP_READ_PMC | 1)
#define IOSF_OP_READ_GFX 0x00
#define IOSF_OP_WRITE_GFX (IOSF_OP_READ_GFX | 1)
#define IOSF_OP_READ_SYSMEMIO 0x06
#define IOSF_OP_WRITE_SYSMEMIO (IOSF_OP_READ_SYSMEMIO | 1)
#define IOSF_OP_READ_USBPHY 0x06
#define IOSF_OP_WRITE_USBPHY (IOSF_OP_READ_USBPHY | 1)
#define IOSF_OP_READ_SEC 0x04
#define IOSF_OP_WRITE_SEC (IOSF_OP_READ_SEC | 1)
#define IOSF_OP_READ_0x45 0x06
#define IOSF_OP_WRITE_0x45 (IOSF_OP_READ_0x45 | 1)
#define IOSF_OP_READ_0x46 0x06
#define IOSF_OP_WRITE_0x46 (IOSF_OP_READ_0x46 | 1)
#define IOSF_OP_READ_0x47 0x06
#define IOSF_OP_WRITE_0x47 (IOSF_OP_READ_0x47 | 1)
#define IOSF_OP_READ_SCORE 0x06
#define IOSF_OP_WRITE_SCORE (IOSF_OP_READ_SCORE | 1)
#define IOSF_OP_READ_0x55 0x04
#define IOSF_OP_WRITE_0x55 (IOSF_OP_READ_0x55 | 1)
#define IOSF_OP_READ_0x58 0x06
#define IOSF_OP_WRITE_0x58 (IOSF_OP_READ_0x58 | 1)
#define IOSF_OP_READ_0x59 0x06
#define IOSF_OP_WRITE_0x59 (IOSF_OP_READ_0x59 | 1)
#define IOSF_OP_READ_0x5a 0x04
#define IOSF_OP_WRITE_0x5a (IOSF_OP_READ_0x5a | 1)
#define IOSF_OP_READ_USHPHY 0x06
#define IOSF_OP_WRITE_USHPHY (IOSF_OP_READ_USHPHY | 1)
#define IOSF_OP_READ_SCC 0x06
#define IOSF_OP_WRITE_SCC (IOSF_OP_READ_SCC | 1)
#define IOSF_OP_READ_LPSS 0x06
#define IOSF_OP_WRITE_LPSS (IOSF_OP_READ_LPSS | 1)
#define IOSF_OP_READ_0xa2 0x06
#define IOSF_OP_WRITE_0xa2 (IOSF_OP_READ_0xa2 | 1)
#define IOSF_OP_READ_SATAPHY 0x00
#define IOSF_OP_WRITE_SATAPHY (IOSF_OP_READ_SATAPHY | 1)
#define IOSF_OP_READ_PCIEPHY 0x00
#define IOSF_OP_WRITE_PCIEPHY (IOSF_OP_READ_PCIEPHY | 1)
#define IOSF_OP_READ_SSUS 0x10
#define IOSF_OP_WRITE_SSUS (IOSF_OP_READ_SSUS | 1)
#define IOSF_OP_READ_CCU 0x06
#define IOSF_OP_WRITE_CCU (IOSF_OP_READ_CCU | 1)
/*
* BUNIT Registers.
*/
#define BNOCACHE 0x23
/* BMBOUND has a 128MiB granularity. Highest address is 0xf8000000. */
#define BUNIT_BMBOUND 0x25
/* BMBOUND_HI describes the available ram above 4GiB. It has a
* 256MiB granularity. Physical address bits 35:28 are compared with 31:24
* bits in the BMBOUND_HI register. Also note that since BMBOUND has 128MiB
* granularity care needs to be taken with the e820 map to account for a hole
* in the ram. */
#define BUNIT_BMBOUND_HI 0x26
#define BUNIT_MMCONF_REG 0x27
/* The SMMRR registers define the SMM region in MiB granularity. */
#define BUNIT_SMRCP 0x2b
#define BUNIT_SMRRAC 0x2c
#define BUNIT_SMRWAC 0x2d
#define BUNIT_SMRRL 0x2e
#define BUNIT_SMRRH 0x2f
# define BUNIT_SMRR_ENABLE (1 << 31)
/* SA ID bits. */
#define SAI_IA_UNTRUSTED (1 << 0)
#define SAI_IA_SMM (1 << 2)
#define SAI_IA_BOOT (1 << 4)
/*
* DUNIT Registers.
*/
#define DRP 0x00
# define DRP_DIMM0_RANK0_EN (0x01 << 0)
# define DRP_DIMM0_RANK1_EN (0x01 << 1)
# define DRP_DIMM1_RANK0_EN (0x01 << 2)
# define DRP_DIMM1_RANK1_EN (0x01 << 3)
# define DRP_RANK_MASK (DRP_DIMM0_RANK0_EN | DRP_DIMM0_RANK1_EN | \
DRP_DIMM1_RANK0_EN | DRP_DIMM1_RANK1_EN)
#define DTR0 0x01
# define DTR0_SPEED_MASK 0x03
# define DTR0_SPEED_800 0x00
# define DTR0_SPEED_1066 0x01
# define DTR0_SPEED_1333 0x02
# define DTR0_SPEED_1600 0x03
/*
* PUNIT Registers
*/
#define SB_BIOS_CONFIG 0x06
# define SB_BIOS_CONFIG_ECC_EN (1 << 31)
# define SB_BIOS_CONFIG_DUAL_CH_DIS (1 << 30)
# define SB_BIOS_CONFIG_EFF_ECC (1 << 29)
# define SB_BIOS_CONFIG_EFF_DUAL_CH_DIS (1 << 28)
# define SB_BIOS_CONFIG_PERF_MODE (1 << 17)
# define SB_BIOS_CONFIG_PDM_MODE (1 << 16)
# define SB_BIOS_CONFIG_DDRIO_PWRGATE (1 << 8)
# define SB_BIOS_CONFIG_GFX_TURBO_DIS (1 << 7)
# define SB_BIOS_CONFIG_PS2_EN_VNN (1 << 3)
# define SB_BIOS_CONFIG_PS2_EN_VCC (1 << 2)
# define SB_BIOS_CONFIG_PCIE_PLLOFFOK (1 << 1)
# define SB_BIOS_CONFIG_USB_CACHING_EN (1 << 0)
#define BIOS_RESET_CPL 0x05
# define BIOS_RESET_CPL_ALL_DONE (1 << 1)
# define BIOS_RESET_CPL_RESET_DONE (1 << 0)
#define PUNIT_PWRGT_CONTROL 0x60
#define PUNIT_PWRGT_STATUS 0x61
#define PUNIT_GPU_EC_VIRUS 0xd2
#define PUNIT_SOC_POWER_BUDGET 0x02
#define PUNIT_SOC_ENERGY_CREDIT 0x03
#define PUNIT_PTMC 0x80
#define PUNIT_GFXT 0x88
#define PUNIT_VEDT 0x89
#define PUNIT_ISPT 0x8c
#define PUNIT_PTPS 0xb2
#define PUNIT_TE_AUX0 0xb5
#define PUNIT_TE_AUX1 0xb6
#define PUNIT_TE_AUX2 0xb7
#define PUNIT_TE_AUX3 0xb8
#define PUNIT_TTE_VRIccMax 0xb9
#define PUNIT_TTE_VRHot 0xba
#define PUNIT_TTE_XXPROCHOT 0xbb
#define PUNIT_TTE_SLM0 0xbc
#define PUNIT_TTE_SLM1 0xbd
#define PUNIT_TTE_SWT 0xbf
/*
* LPSS Registers
*/
#define LPSS_SIO_DMA1_CTL 0x280
#define LPSS_I2C1_CTL 0x288
#define LPSS_I2C2_CTL 0x290
#define LPSS_I2C3_CTL 0x298
#define LPSS_I2C4_CTL 0x2a0
#define LPSS_I2C5_CTL 0x2a8
#define LPSS_I2C6_CTL 0x2b0
#define LPSS_I2C7_CTL 0x2b8
#define LPSS_SIO_DMA2_CTL 0x240
#define LPSS_PWM1_CTL 0x248
#define LPSS_PWM2_CTL 0x250
#define LPSS_HSUART1_CTL 0x258
#define LPSS_HSUART2_CTL 0x260
#define LPSS_SPI_CTL 0x268
# define LPSS_CTL_ACPI_INT_EN (1 << 21)
# define LPSS_CTL_PCI_CFG_DIS (1 << 20)
# define LPSS_CTL_SNOOP (1 << 18)
# define LPSS_CTL_NOSNOOP (1 << 19)
# define LPSS_CTL_PM_CAP_PRSNT (1 << 1)
/*
* SCC Registers
*/
#define SCC_SD_CTL 0x504
#define SCC_SDIO_CTL 0x508
#define SCC_MMC_CTL 0x50c
# define SCC_CTL_PCI_CFG_DIS (1 << 0)
# define SCC_CTL_ACPI_INT_EN (1 << 1)
/*
* CCU Registers
*/
#define PLT_CLK_CTRL_0 0x3c
#define PLT_CLK_CTRL_1 0x40
#define PLT_CLK_CTRL_2 0x44
#define PLT_CLK_CTRL_3 0x48
#define PLT_CLK_CTRL_4 0x4c
#define PLT_CLK_CTRL_5 0x50
# define PLT_CLK_CTRL_19P2MHZ_FREQ (0 << 1)
# define PLT_CLK_CTRL_25MHZ_FREQ (1 << 1)
# define PLT_CLK_CTRL_SELECT_FREQ (1 << 0)
/*
* USBPHY Registers
*/
#define USBPHY_COMPBG 0x7f04
#define USBPHY_PER_PORT_LANE0 0x4100
#define USBPHY_PER_PORT_RCOMP_HS_PULLUP0 0x4122
#define USBPHY_PER_PORT_LANE1 0x4200
#define USBPHY_PER_PORT_RCOMP_HS_PULLUP1 0x4222
#define USBPHY_PER_PORT_LANE2 0x4300
#define USBPHY_PER_PORT_RCOMP_HS_PULLUP2 0x4322
#define USBPHY_PER_PORT_LANE3 0x4400
#define USBPHY_PER_PORT_RCOMP_HS_PULLUP3 0x4422
/*
* USHPHY Registers
*/
#define USHPHY_CDN_PLL_CONTROL 0x03c0
#define USHPHY_CDN_VCO_START_CAL_POINT 0x0054
#define USHPHY_CCDRLF 0x8040
#define USHPHY_PEAKING_AMP_CONFIG_DIAG 0x80a8
#define USHPHY_OFFSET_COR_CONFIG_DIAG 0x80b0
#define USHPHY_VGA_GAIN_CONFIG_DIAG 0x8080
#define USHPHY_REE_DAC_CONTROL 0x80b8
#define USHPHY_CDN_U1_POWER_STATE_DEF 0x0000
/*
* LPE Registers
*/
#define LPE_PCICFGCTR1 0x0500
# define LPE_PCICFGCTR1_PCI_CFG_DIS (1 << 0)
# define LPE_PCICFGCTR1_ACPI_INT_EN (1 << 1)
#endif /* _BAYTRAIL_IOSF_H_ */

View File

@ -0,0 +1,164 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 _BAYTRAIL_IRQ_H_
#define _BAYTRAIL_IRQ_H_
#define PIRQA_APIC_IRQ 16
#define PIRQB_APIC_IRQ 17
#define PIRQC_APIC_IRQ 18
#define PIRQD_APIC_IRQ 19
#define PIRQE_APIC_IRQ 20
#define PIRQF_APIC_IRQ 21
#define PIRQG_APIC_IRQ 22
#define PIRQH_APIC_IRQ 23
/* The below IRQs are for when devices are in ACPI mode. Active low. */
#define LPE_DMA0_IRQ 24
#define LPE_DMA1_IRQ 25
#define LPE_SSP0_IRQ 26
#define LPE_SSP1_IRQ 27
#define LPE_SSP2_IRQ 28
#define LPE_IPC2HOST_IRQ 29
#define LPSS_I2C1_IRQ 32
#define LPSS_I2C2_IRQ 33
#define LPSS_I2C3_IRQ 34
#define LPSS_I2C4_IRQ 35
#define LPSS_I2C5_IRQ 36
#define LPSS_I2C6_IRQ 37
#define LPSS_I2C7_IRQ 38
#define LPSS_HSUART1_IRQ 39
#define LPSS_HSUART2_IRQ 40
#define LPSS_SPI_IRQ 41
#define LPSS_DMA1_IRQ 42
#define LPSS_DMA2_IRQ 43
#define SCC_EMMC_IRQ 44
#define SCC_SDIO_IRQ 46
#define SCC_SD_IRQ 47
#define GPIO_NC_IRQ 48
#define GPIO_SC_IRQ 49
#define GPIO_SUS_IRQ 50
/* GPIO direct / dedicated IRQs. */
#define GPIO_S0_DED_IRQ_0 51
#define GPIO_S0_DED_IRQ_1 52
#define GPIO_S0_DED_IRQ_2 53
#define GPIO_S0_DED_IRQ_3 54
#define GPIO_S0_DED_IRQ_4 55
#define GPIO_S0_DED_IRQ_5 56
#define GPIO_S0_DED_IRQ_6 57
#define GPIO_S0_DED_IRQ_7 58
#define GPIO_S0_DED_IRQ_8 59
#define GPIO_S0_DED_IRQ_9 60
#define GPIO_S0_DED_IRQ_10 61
#define GPIO_S0_DED_IRQ_11 62
#define GPIO_S0_DED_IRQ_12 63
#define GPIO_S0_DED_IRQ_13 64
#define GPIO_S0_DED_IRQ_14 65
#define GPIO_S0_DED_IRQ_15 66
#define GPIO_S5_DED_IRQ_0 67
#define GPIO_S5_DED_IRQ_1 68
#define GPIO_S5_DED_IRQ_2 69
#define GPIO_S5_DED_IRQ_3 70
#define GPIO_S5_DED_IRQ_4 71
#define GPIO_S5_DED_IRQ_5 72
#define GPIO_S5_DED_IRQ_6 73
#define GPIO_S5_DED_IRQ_7 74
#define GPIO_S5_DED_IRQ_8 75
#define GPIO_S5_DED_IRQ_9 76
#define GPIO_S5_DED_IRQ_10 77
#define GPIO_S5_DED_IRQ_11 78
#define GPIO_S5_DED_IRQ_12 79
#define GPIO_S5_DED_IRQ_13 80
#define GPIO_S5_DED_IRQ_14 81
#define GPIO_S5_DED_IRQ_15 82
/* DIRQs - Two levels of expansion to evaluate to numeric constants for ASL. */
#define _GPIO_S0_DED_IRQ(slot) GPIO_S0_DED_IRQ_##slot
#define _GPIO_S5_DED_IRQ(slot) GPIO_S5_DED_IRQ_##slot
#define GPIO_S0_DED_IRQ(slot) _GPIO_S0_DED_IRQ(slot)
#define GPIO_S5_DED_IRQ(slot) _GPIO_S5_DED_IRQ(slot)
/* PIC IRQ settings. */
#define PIRQ_PIC_IRQDISABLE 0x0
#define PIRQ_PIC_IRQ3 0x3
#define PIRQ_PIC_IRQ4 0x4
#define PIRQ_PIC_IRQ5 0x5
#define PIRQ_PIC_IRQ6 0x6
#define PIRQ_PIC_IRQ7 0x7
#define PIRQ_PIC_IRQ9 0x9
#define PIRQ_PIC_IRQ10 0xa
#define PIRQ_PIC_IRQ11 0xb
#define PIRQ_PIC_IRQ12 0xc
#define PIRQ_PIC_IRQ14 0xe
#define PIRQ_PIC_IRQ15 0xf
/* Overloaded term, but these values determine the per device route. */
#define PIRQA 0
#define PIRQB 1
#define PIRQC 2
#define PIRQD 3
#define PIRQE 4
#define PIRQF 5
#define PIRQG 6
#define PIRQH 7
/* These registers live behind the ILB_BASE_ADDRESS */
#define ACTL 0x00
# define SCIS_MASK 0x07
# define SCIS_IRQ9 0x00
# define SCIS_IRQ10 0x01
# define SCIS_IRQ11 0x02
# define SCIS_IRQ20 0x04
# define SCIS_IRQ21 0x05
# define SCIS_IRQ22 0x06
# define SCIS_IRQ23 0x07
/* In each mainboard directory there should exist a header file irqroute.h that
* defines the PCI_DEV_PIRQ_ROUTES and PIRQ_PIC_ROUTES macros which
* consist of PCI_DEV_PIRQ_ROUTE and PIRQ_PIC entries. */
#if !defined(__ASSEMBLER__) && !defined(__ACPI__)
#include <stdint.h>
#define NUM_IR_DEVS 32
#define NUM_PIRQS 8
struct baytrail_irq_route {
/* Per device configuration. */
uint16_t pcidev[NUM_IR_DEVS];
/* Route path for each internal PIRQx in PIC mode. */
uint8_t pic[NUM_PIRQS];
};
extern const struct baytrail_irq_route global_baytrail_irq_route;
#define DEFINE_IRQ_ROUTES \
const struct baytrail_irq_route global_baytrail_irq_route = { \
.pcidev = { PCI_DEV_PIRQ_ROUTES, }, \
.pic = { PIRQ_PIC_ROUTES, }, \
}
#define PCI_DEV_PIRQ_ROUTE(dev_, a_, b_, c_, d_) \
[dev_] = ((PIRQ ## d_) << 12) | ((PIRQ ## c_) << 8) | \
((PIRQ ## b_) << 4) | ((PIRQ ## a_) << 0)
#define PIRQ_PIC(pirq_, pic_irq_) \
[PIRQ ## pirq_] = PIRQ_PIC_IRQ ## pic_irq_
#endif /* !defined(__ASSEMBLER__) && !defined(__ACPI__) */
#endif /* _BAYTRAIL_IRQ_H_ */

View File

@ -0,0 +1,54 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 _BAYTRAIL_LPC_H_
#define _BAYTRAIL_LPC_H_
/* PCI config registers in LPC bridge. */
#define REVID 0x08
#define ABASE 0x40
#define PBASE 0x44
#define GBASE 0x48
#define IOBASE 0x4c
#define IBASE 0x50
#define SBASE 0x54
#define MPBASE 0x58
#define PUBASE 0x5c
#define UART_CONT 0x80
#define RCBA 0xf0
#define RID_A_STEPPING_START 1
#define RID_B_STEPPING_START 5
#define RID_C_STEPPING_START 0xe
enum baytrail_stepping {
STEP_A0,
STEP_A1,
STEP_B0,
STEP_B1,
STEP_B2,
STEP_B3,
STEP_C0,
};
/* Registers behind the RCBA_BASE_ADDRESS bar. */
#define GCS 0x00
# define BILD (1 << 0)
#endif /* _BAYTRAIL_LPC_H_ */

View File

@ -0,0 +1,107 @@
/*
* MRC wrapper definitions
*
* Copyright 2013 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 _MRC_WRAPPER_H_
#define _MRC_WRAPPER_H_
#define MRC_PARAMS_VER 5
#define NUM_CHANNELS 2
/* Provide generic x86 calling conventions. */
#define ABI_X86 __attribute((regparm(0)))
enum {
DRAM_INFO_SPD_SMBUS, /* Use the typical SPD smbus access. */
DRAM_INFO_SPD_MEM, /* SPD info in memory. */
DRAM_INFO_DETAILED, /* Timing info not in SPD format. */
};
enum dram_type {
DRAM_DDR3,
DRAM_DDR3L,
DRAM_LPDDR3,
};
/* Errors returned by the MRC wrapper. */
enum mrc_wrapper_error {
INVALID_VER = -1,
INVALID_DRAM_TYPE = -2,
INVALID_SLEEP_MODE = -3,
PLATFORM_SETTINGS_FAIL = -4,
DIMM_DETECTION_FAILURE = -5,
MEMORY_CONFIG_FAILURE = -6,
INVALID_CPU_ODT_SETTING = -7,
INVALID_DRAM_ODT_SETTING = -8,
};
struct mrc_mainboard_params {
int dram_type;
int dram_info_location; /* DRAM_INFO_* */
int dram_is_slotted; /* mobo has DRAM slots. */
/*
* The below ODT settings are only honored when !dram_is_slotted.
* Additionally, weaker_odt_settings being non-zero causes
* cpu_odt_value to not be honored as weaker_odt_settings have a
* special training path.
*/
int weaker_odt_settings;
/* Allowed settings: 60, 80, 100, 120, and 150. */
int cpu_odt_value;
/* Allowed settings: 60 and 120. */
int dram_odt_value;
int spd_addrs[NUM_CHANNELS];
void *dram_data[NUM_CHANNELS]; /* SPD or Timing specific data. */
} __attribute__((packed));
struct mrc_params {
/* Mainboard Inputs */
int version;
struct mrc_mainboard_params mainboard;
void ABI_X86 (*console_out)(unsigned char byte);
int prev_sleep_state;
int saved_data_size;
const void *saved_data;
int txe_size_mb; /* TXE memory size in megabytes. */
int rmt_enabled; /* Enable RMT training + prints. */
int io_hole_mb; /* Size of IO hole in MiB. */
/* Outputs */
void *txe_base_address;
int data_to_save_size;
void *data_to_save;
} __attribute__((packed));
/* Call into wrapper. */
typedef int ABI_X86 (*mrc_wrapper_entry_t)(struct mrc_params *);
#endif /* _MRC_WRAPPER_H_ */

View File

@ -0,0 +1,51 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 _BAYTRAIL_MSR_H_
#define _BAYTRAIL_MSR_H_
#define MSR_IA32_PLATFORM_ID 0x17
#define MSR_BSEL_CR_OVERCLOCK_CONTROL 0xcd
#define MSR_PLATFORM_INFO 0xce
#define MSR_PMG_CST_CONFIG_CONTROL 0xe2
#define SINGLE_PCTL (1 << 11)
#define MSR_POWER_MISC 0x120
#define ENABLE_ULFM_AUTOCM_MASK (1 << 2)
#define ENABLE_INDP_AUTOCM_MASK (1 << 3)
#define MSR_IA32_PERF_CTL 0x199
#define MSR_IA32_MISC_ENABLES 0x1a0
#define MSR_POWER_CTL 0x1fc
#define MSR_PKG_POWER_SKU_UNIT 0x606
#define MSR_PKG_POWER_LIMIT 0x610
#define MSR_PP1_POWER_LIMIT 0x638
#define MSR_IACORE_RATIOS 0x66a
#define MSR_IACORE_TURBO_RATIOS 0x66c
#define MSR_IACORE_VIDS 0x66b
#define MSR_IACORE_TURBO_VIDS 0x66d
#define MSR_PKG_TURBO_CFG1 0x670
#define MSR_CPU_TURBO_WKLD_CFG1 0x671
#define MSR_CPU_TURBO_WKLD_CFG2 0x672
#define MSR_CPU_THERM_CFG1 0x673
#define MSR_CPU_THERM_CFG2 0x674
#define MSR_CPU_THERM_SENS_CFG 0x675
/* Read BCLK from MSR */
unsigned bus_freq_khz(void);
#endif /* _BAYTRAIL_MSR_H_ */

View File

@ -0,0 +1,78 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008-2009 coresystems GmbH
* Copyright (C) 2011 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 _BAYTRAIL_NVS_H_
#define _BAYTRAIL_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 */
u32 p80d; /* 0x0b - Debug port (IO 0x80) value */
u8 lids; /* 0x0f - LID state (open = 1) */
u8 pwrs; /* 0x10 - Power state (AC = 1) */
u8 pcnt; /* 0x11 - Processor Count */
u8 tpmp; /* 0x12 - TPM Present and Enabled */
u8 tlvl; /* 0x13 - Throttle Level */
u8 ppcm; /* 0x14 - Maximum P-state usable by OS */
u32 pm1i; /* 0x15 - System Wake Source - PM1 Index */
u8 rsvd1[7];
/* Device Config */
u8 s5u0; /* 0x20 - Enable USB0 in S5 */
u8 s5u1; /* 0x21 - Enable USB1 in S5 */
u8 s3u0; /* 0x22 - Enable USB0 in S3 */
u8 s3u1; /* 0x23 - Enable USB1 in S3 */
u8 tact; /* 0x24 - Thermal Active trip point */
u8 tpsv; /* 0x25 - Thermal Passive trip point */
u8 tcrt; /* 0x26 - Thermal Critical trip point */
u8 dpte; /* 0x27 - Enable DPTF */
u8 rsvd2[8];
/* Base Addresses */
u32 obsolete_cmem; /* 0x30 - CBMEM TOC */
u32 tolm; /* 0x34 - Top of Low Memory */
u32 cbmc; /* 0x38 - coreboot memconsole */
u8 rsvd3[196];
/* ChromeOS specific (0x100-0xfff)*/
chromeos_acpi_t chromeos;
/* Baytrail LPSS (0x1000) */
device_nvs_t dev;
} __attribute__((packed)) global_nvs_t;
#ifdef __SMM__
/* Used in SMM to find the ACPI GNVS address */
global_nvs_t *smm_get_gnvs(void);
#endif
#endif /* _BAYTRAIL_NVS_H_ */

View File

@ -0,0 +1,64 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 _PATTRS_H_
#define _PATTRS_H_
#include <stdint.h>
#include <cpu/x86/msr.h>
enum {
IACORE_MIN,
IACORE_LFM,
IACORE_MAX,
IACORE_TURBO,
IACORE_END
};
/* The pattrs structure is a common place to stash pertinent information
* about the processor or platform. Instead of going to the source (msrs, cpuid)
* every time an attribute is needed use the pattrs structure.
*/
struct pattrs {
msr_t platform_id;
msr_t platform_info;
int iacore_ratios[IACORE_END];
int iacore_vids[IACORE_END];
uint32_t cpuid;
int revid;
int stepping;
const void *microcode_patch;
int address_bits;
int num_cpus;
unsigned bclk_khz;
};
/* This is just to hide the abstraction w/o relying on how the underlying
* storage is allocated. */
#define PATTRS_GLOB_NAME __global_pattrs
#define DEFINE_PATTRS struct pattrs PATTRS_GLOB_NAME
extern DEFINE_PATTRS;
static inline const struct pattrs *pattrs_get(void)
{
return &PATTRS_GLOB_NAME;
}
#endif /* _PATTRS_H_ */

View File

@ -0,0 +1,155 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 _BAYTRAIL_PCI_DEVS_H_
#define _BAYTRAIL_PCI_DEVS_H_
/* All these devices live on bus 0 with the associated device and function */
/* SoC transaction router */
#define SOC_DEV 0x0
#define SOC_FUNC 0
# define SOC_DEVID 0x0f00
/* Graphics and Display */
#define GFX_DEV 0x2
#define GFX_FUNC 0
# define GFX_DEVID 0x0f31
/* SDIO Port */
#define SDIO_DEV 0x11
#define SDIO_FUNC 0
# define SDIO_DEVID 0x0f15
/* SD Port */
#define SD_DEV 0x12
#define SD_FUNC 0
# define SD_DEVID 0x0f16
/* SATA */
#define SATA_DEV 0x13
#define SATA_FUNC 0
#define IDE1_DEVID 0x0f20
#define IDE2_DEVID 0x0f21
#define AHCI1_DEVID 0x0f22
#define AHCI2_DEVID 0x0f23
/* xHCI */
#define XHCI_DEV 0x14
#define XHCI_FUNC 0
# define XHCI_DEVID 0x0f35
/* LPE Audio */
#define LPE_DEV 0x15
#define LPE_FUNC 0
# define LPE_DEVID 0x0f28
/* MMC Port */
#define MMC_DEV 0x17
#define MMC_FUNC 0
# define MMC_DEVID 0x0f50
/* Serial IO 1 */
#define SIO1_DEV 0x18
# define SIO_DMA1_DEV SIO1_DEV
# define SIO_DMA1_FUNC 0
# define SIO_DMA1_DEVID 0x0f40
# define I2C1_DEV SIO1_DEV
# define I2C1_FUNC 1
# define I2C1_DEVID 0x0f41
# define I2C2_DEV SIO1_DEV
# define I2C2_FUNC 2
# define I2C2_DEVID 0x0f42
# define I2C3_DEV SIO1_DEV
# define I2C3_FUNC 3
# define I2C3_DEVID 0x0f43
# define I2C4_DEV SIO1_DEV
# define I2C4_FUNC 4
# define I2C4_DEVID 0x0f44
# define I2C5_DEV SIO1_DEV
# define I2C5_FUNC 5
# define I2C5_DEVID 0x0f45
# define I2C6_DEV SIO1_DEV
# define I2C6_FUNC 6
# define I2C6_DEVID 0x0f46
# define I2C7_DEV SIO1_DEV
# define I2C7_FUNC 7
# define I2C7_DEVID 0x0f47
/* Trusted Execution Engine */
#define TXE_DEV 0x1a
#define TXE_FUNC 0
# define TXE_DEVID 0x0f18
/* HD Audio */
#define HDA_DEV 0x1b
#define HDA_FUNC 0
# define HDA_DEVID 0x0f04
/* PCIe Ports */
#define PCIE_DEV 0x1c
# define PCIE_PORT1_DEV PCIE_DEV
# define PCIE_PORT1_FUNC 0
# define PCIE_PORT1_DEVID 0x0f48
# define PCIE_PORT2_DEV PCIE_DEV
# define PCIE_PORT2_FUNC 1
# define PCIE_PORT2_DEVID 0x0f4a
# define PCIE_PORT3_DEV PCIE_DEV
# define PCIE_PORT3_FUNC 2
# define PCIE_PORT3_DEVID 0x0f4c
# define PCIE_PORT4_DEV PCIE_DEV
# define PCIE_PORT4_FUNC 3
# define PCIE_PORT4_DEVID 0x0f4e
/* EHCI */
#define EHCI_DEV 0x1d
#define EHCI_FUNC 0
# define EHCI_DEVID 0x0f34
/* Serial IO 2 */
#define SIO2_DEV 0x1e
# define SIO_DMA2_DEV SIO2_DEV
# define SIO_DMA2_FUNC 0
# define SIO_DMA2_DEVID 0x0f06
# define PWM1_DEV SIO2_DEV
# define PWM1_FUNC 1
# define PWM1_DEVID 0x0f08
# define PWM2_DEV SIO2_DEV
# define PWM2_FUNC 2
# define PWM2_DEVID 0x0f09
# define HSUART1_DEV SIO2_DEV
# define HSUART1_FUNC 3
# define HSUART1_DEVID 0x0f0a
# define HSUART2_DEV SIO2_DEV
# define HSUART2_FUNC 4
# define HSUART2_DEVID 0x0f0c
# define SPI_DEV SIO2_DEV
# define SPI_FUNC 5
# define SPI_DEVID 0xf0e
/* Platform Controller Unit */
#define PCU_DEV 0x1f
# define LPC_DEV PCU_DEV
# define LPC_FUNC 0
# define LPC_DEVID 0x0f1c
# define SMBUS_DEV PCU_DEV
# define SMBUS_FUNC 3
# define SMBUS_DEVID 0x0f12
#endif /* _BAYTRAIL_PCI_DEVS_H_ */

View File

@ -0,0 +1,102 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 _BAYTRAIL_PCIE_H_
#define _BAYTRAIL_PCIE_H_
/* PCIe root port config space registers. */
#define XCAP 0x40
# define SI (1 << 24)
#define DCAP 0x44
# define MPS_MASK 0x7
#define DCTL_DSTS 0x48
# define URE (1 << 3)
# define FEE (1 << 2)
# define NFE (1 << 1)
# define CEE (1 << 0)
#define LCAP 0x4c
# define L1EXIT_SHIFT 15
# define L1EXIT_MASK (0x7 << L1EXIT_SHIFT)
#define LCTL 0x50
# define CCC (1 << 6)
# define RL (1 << 5)
# define LD (1 << 4)
#define LSTS 0x52
#define SLCAP 0x54
# define SLN_SHIFT 19
# define SLS_SHIFT 15
# define SLV_SHIFT 7
# define HPC (1 << 6)
# define HPS (1 << 5)
#define SLCTL_SLSTS 0x58
# define PDS (1 << 22)
#define DCAP2 0x64
# define OBFFS (0x3 << 18)
# define LTRMS (1 << 11)
#define DSTS2 0x68
# define OBFFEN (3 << 13)
# define LTRME (1 << 10)
# define CTD (1 << 4)
#define CHCFG 0xd0
# define UPSD (1 << 24)
# define UNRS (1 << 15)
# define UPRS (1 << 14)
#define MPC2 0xd4
# define IPF (1 << 11)
# define LSTP (1 << 6)
# define EOIFD (1 << 1)
#define MPC 0xd8
# define CCEL_SHIFT 15
# define CCEL_MASK (0x7 << CCEL_SHIFT)
#define RPPGEN 0xe0
# define RPSCGEN (1 << 15)
# define LCLKREQEN (1 << 13)
# define BBCLKREQEN (1 << 12)
# define SRDLCGEN (1 << 11)
# define SRDBCGEN (1 << 10)
# define RPDLCGEN (1 << 9)
# define RPDBCGEN (1 << 8)
#define PWRCTL 0xe8
# define RPL1SQPOL (1 << 1)
# define RPDTSQPOL (1 << 0)
#define PHYCTL2_IOSFBCTL 0xf4
# define PLL_OFF_EN (1 << 8)
# define TDFT (3 << 14)
# define TXCFGCHWAIT (3 << 12)
# define SIID (3 << 26)
#define STRPFUSECFG 0xfc
# define LANECFG_SHIFT 14
# define LANECFG_MASK (0x3 << LANECFG_SHIFT)
#define AERCH 0x100
#define NFTS 0x314
#define L0SC 0x318
#define CFG2 0x320
# define CSREN (1 << 22)
# define LATGC_SHIFT 6
# define LATGC_MASK (0x7 << LATGC_SHIFT)
#define PCIEDBG 0x324
# define SPCE (1 << 5)
#define PCIESTS1 0x328
#define PCIEALC 0x338
#define RTP 0x33c
#define PHYCTL4 0x408
# define SQDIS (1 << 27)
#define PCIE_ROOT_PORT_COUNT 4
#endif /* _BAYTRAIL_PCIE_H_ */

View File

@ -0,0 +1,303 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 _BAYTRAIL_PMC_H_
#define _BAYTRAIL_PMC_H_
#define IOCOM1 0x3f8
/* Memory mapped IO registers behind PMC_BASE_ADDRESS */
#define PRSTS 0x00
# define PMC_WDT_STS (1 << 15)
# define SEC_GBLRST_STS (1 << 7)
# define SEC_WDT_STS (1 << 6)
# define WOL_OVR_WK_STS (1 << 5)
# define PMC_WAKE_STS (1 << 4)
#define PMC_CFG 0x08
# define SPS (1 << 5)
# define NO_REBOOT (1 << 4)
# define SX_ENT_TO_EN (1 << 3)
# define TIMING_T581_SHIFT (0)
# define TIMING_T581_MASK (3 << TIMING_T581_SHIFT)
# define TIMING_T581_10uS (0 << TIMING_T581_SHIFT)
# define TIMING_T581_100uS (1 << TIMING_T581_SHIFT)
# define TIMING_T581_1mS (2 << TIMING_T581_SHIFT)
# define TIMING_T581_10mS (3 << TIMING_T581_SHIFT)
#define VLV_PM_STS 0x0c
# define PMC_MSG_FULL_STS (1 << 24)
# define PMC_MSG_4_FULL_STS (1 << 23)
# define PMC_MSG_3_FULL_STS (1 << 22)
# define PMC_MSG_2_FULL_STS (1 << 21)
# define PMC_MSG_1_FULL_STS (1 << 20)
# define CODE_REQ (1 << 8)
# define HPR_ENT_TO (1 << 2)
# define SX_ENT_TO (1 << 1)
#define GEN_PMCON1 0x20
# define UART_EN (1 << 24)
# define DISB (1 << 23)
# define MEM_SR (1 << 21)
# define SRS (1 << 20)
# define CTS (1 << 19)
# define MS4V (1 << 18)
# define PWR_FLR (1 << 16)
# define PME_B0_S5_DIS (1 << 15)
# define SUS_PWR_FLR (1 << 14)
# define WOL_EN_OVRD (1 << 13)
# define DIS_SLP_X_STRCH_SUS_UP (1 << 12)
# define GEN_RST_STS (1 << 9)
# define RPS (1 << 2)
# define AFTERG3_EN (1 << 0)
#define GEN_PMCON2 0x24
# define SLPSX_STR_POL_LOCK (1 << 18)
# define BIOS_PCI_EXP_EN (1 << 10)
# define PWRBTN_LVL (1 << 9)
# define SMI_LOCK (1 << 4)
#define ETR 0x48
# define CF9LOCK (1 << 31)
# define LTR_DEF (1 << 22)
# define IGNORE_HPET (1 << 21)
# define CF9GR (1 << 20)
# define CWORWRE (1 << 18)
#define FUNC_DIS 0x34
# define SIO_DMA2_DIS (1 << 0)
# define PWM1_DIS (1 << 1)
# define PWM2_DIS (1 << 2)
# define HSUART1_DIS (1 << 3)
# define HSUART2_DIS (1 << 4)
# define SPI_DIS (1 << 5)
# define SDIO_DIS (1 << 9)
# define SD_DIS (1 << 10)
# define MMC_DIS (1 << 11)
# define HDA_DIS (1 << 12)
# define LPE_DIS (1 << 13)
# define OTG_DIS (1 << 14)
# define XHCI_DIS (1 << 15)
# define SATA_DIS (1 << 17)
# define EHCI_DIS (1 << 18)
# define TXE_DIS (1 << 19)
# define PCIE_PORT1_DIS (1 << 20)
# define PCIE_PORT2_DIS (1 << 21)
# define PCIE_PORT3_DIS (1 << 22)
# define PCIE_PORT4_DIS (1 << 23)
# define SIO_DMA1_DIS (1 << 24)
# define I2C1_DIS (1 << 25)
# define I2C2_DIS (1 << 26)
# define I2C3_DIS (1 << 27)
# define I2C4_DIS (1 << 28)
# define I2C5_DIS (1 << 29)
# define I2C6_DIS (1 << 30)
# define I2C7_DIS (1 << 31)
#define FUNC_DIS2 0x38
# define USH_SS_PHY_DIS (1 << 2)
# define OTG_SS_PHY_DIS (1 << 1)
# define SMBUS_DIS (1 << 0)
#define GPIO_ROUT 0x58
# define ROUTE_MASK 3
# define ROUTE_NONE 0
# define ROUTE_SMI 1
# define ROUTE_SCI 2
#define PLT_CLK_CTL_0 0x60
#define PLT_CLK_CTL_1 0x64
#define PLT_CLK_CTL_2 0x68
#define PLT_CLK_CTL_3 0x6c
#define PLT_CLK_CTL_4 0x70
#define PLT_CLK_CTL_5 0x74
# define CLK_FREQ_25MHZ (0x0 << 2)
# define CLK_FREQ_19P2MHZ (0x1 << 2)
# define CLK_CTL_D3_LPE (0x0 << 0)
# define CLK_CTL_ON (0x1 << 0)
# define CLK_CTL_OFF (0x2 << 0)
#define PME_STS 0xc0
#define GPE_LEVEL_EDGE 0xc4
# define GPE_EDGE 0
# define GPE_LEVEL 1
#define GPE_POLARITY 0xc8
# define GPE_ACTIVE_HIGH 1
# define GPE_ACTIVE_LOW 0
#define LOCK 0xcc
/* IO Mapped registers behind ACPI_BASE_ADDRESS */
#define PM1_STS 0x00
#define WAK_STS (1 << 15)
#define PCIEXPWAK_STS (1 << 14)
#define USB_STS (1 << 13)
#define PRBTNOR_STS (1 << 11)
#define RTC_STS (1 << 10)
#define PWRBTN_STS (1 << 8)
#define GBL_STS (1 << 5)
#define TMROF_STS (1 << 0)
#define PM1_EN 0x02
#define PCIEXPWAK_DIS (1 << 14)
#define USB_WAKE_EN (1 << 13)
#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_SHIFT 10
#define SLP_TYP (7 << SLP_TYP_SHIFT)
#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 GPE0_STS 0x20
#define CORE_GPIO_STS7 (1 << 31)
#define CORE_GPIO_STS6 (1 << 30)
#define CORE_GPIO_STS5 (1 << 29)
#define CORE_GPIO_STS4 (1 << 28)
#define CORE_GPIO_STS3 (1 << 27)
#define CORE_GPIO_STS2 (1 << 26)
#define CORE_GPIO_STS1 (1 << 25)
#define CORE_GPIO_STS0 (1 << 24)
#define SUS_GPIO_STS7 (1 << 23)
#define SUS_GPIO_STS6 (1 << 22)
#define SUS_GPIO_STS5 (1 << 21)
#define SUS_GPIO_STS4 (1 << 20)
#define SUS_GPIO_STS3 (1 << 19)
#define SUS_GPIO_STS2 (1 << 18)
#define SUS_GPIO_STS1 (1 << 17)
#define SUS_GPIO_STS0 (1 << 16)
#define PME_B0_STS (1 << 13)
#define BATLOW_STS (1 << 10)
#define PCI_EXP_STS (1 << 9)
#define PCIE_WAKE3_STS (1 << 8)
#define PCIE_WAKE2_STS (1 << 7)
#define PCIE_WAKE1_STS (1 << 6)
#define GUNIT_SCI_STS (1 << 5)
#define PUNIT_SCI_STS (1 << 4)
#define PCIE_WAKE0_STS (1 << 3)
#define SWGPE_STS (1 << 2)
#define HOT_PLUG_STS (1 << 1)
#define GPE0_EN 0x28
#define CORE_GPIO_EN7 (1 << 31)
#define CORE_GPIO_EN6 (1 << 30)
#define CORE_GPIO_EN5 (1 << 29)
#define CORE_GPIO_EN4 (1 << 28)
#define CORE_GPIO_EN3 (1 << 27)
#define CORE_GPIO_EN2 (1 << 26)
#define CORE_GPIO_EN1 (1 << 25)
#define CORE_GPIO_EN0 (1 << 24)
#define SUS_GPIO_EN7_BIT 23
#define SUS_GPIO_EN7 (1 << SUS_GPIO_EN7_BIT)
#define SUS_GPIO_EN6_BIT 22
#define SUS_GPIO_EN6 (1 << SUS_GPIO_EN6_BIT)
#define SUS_GPIO_EN5_BIT 21
#define SUS_GPIO_EN5 (1 << SUS_GPIO_EN5_BIT)
#define SUS_GPIO_EN4_BIT 20
#define SUS_GPIO_EN4 (1 << SUS_GPIO_EN4_BIT)
#define SUS_GPIO_EN3_BIT 19
#define SUS_GPIO_EN3 (1 << SUS_GPIO_EN3_BIT)
#define SUS_GPIO_EN2_BIT 18
#define SUS_GPIO_EN2 (1 << SUS_GPIO_EN2_BIT)
#define SUS_GPIO_EN1_BIT 17
#define SUS_GPIO_EN1 (1 << SUS_GPIO_EN1_BIT)
#define SUS_GPIO_EN0_BIT 16
#define SUS_GPIO_EN0 (1 << SUS_GPIO_EN0_BIT)
#define PME_B0_EN (1 << 13)
#define BATLOW_EN (1 << 10)
#define PCI_EXP_EN (1 << 9)
#define PCIE_WAKE3_EN (1 << 8)
#define PCIE_WAKE2_EN (1 << 7)
#define PCIE_WAKE1_EN (1 << 6)
#define PCIE_WAKE0_EN (1 << 3)
#define SWGPE_EN (1 << 2)
#define HOT_PLUG_EN (1 << 1)
#define _ACPI_ENABLE_WAKE_SUS_GPIO(x) SUS_GPIO_EN##x##_BIT
#define ACPI_ENABLE_WAKE_SUS_GPIO(x) _ACPI_ENABLE_WAKE_SUS_GPIO(x)
#define SMI_EN 0x30
#define INTEL_USB2_EN (1 << 18) // Intel-Specific USB2 SMI logic
#define USB_EN (1 << 17) // Legacy USB2 SMI logic
#define PERIODIC_EN (1 << 14) // SMI on PERIODIC_STS in SMI_STS
#define TCO_EN (1 << 13) // Enable TCO Logic (BIOSWE et al)
#define BIOS_RLS (1 << 7) // asserts SCI on bit set
#define SWSMI_TMR_EN (1 << 6) // start software smi timer on bit set
#define APMC_EN (1 << 5) // Writes to APM_CNT cause SMI#
#define SLP_SMI_EN (1 << 4) // Write to SLP_EN in PM1_CNT asserts SMI#
#define BIOS_EN (1 << 2) // Assert SMI# on setting GBL_RLS bit
#define EOS (1 << 1) // End of SMI (deassert SMI#)
#define GBL_SMI_EN (1 << 0) // SMI# generation at all?
#define SMI_STS 0x34
#define ALT_GPIO_SMI 0x38
#define UPRWC 0x3c
# define UPRWC_WR_EN (1 << 1) // USB Per-Port Registers Write Enable
#define GPE_CTRL 0x40
#define PM2A_CNT_BLK 0x50
#define TCO_RLD 0x60
#define TCO_STS 0x64
# define SECOND_TO_STS (1 << 17)
# define TCO_TIMEOUT (1 << 3)
#define TCO1_CNT 0x68
# define TCO_LOCK (1 << 12)
# define TCO_TMR_HALT (1 << 11)
#define TCO_TMR 0x70
/* I/O ports */
#define RST_CNT 0xcf9
# define FULL_RST (1 << 3)
# define RST_CPU (1 << 2)
# define SYS_RST (1 << 1)
#if !defined(__ASSEMBLER__) && !defined(__ACPI__)
/* Track power state from reset to log events. */
struct chipset_power_state {
uint16_t pm1_sts;
uint16_t pm1_en;
uint32_t pm1_cnt;
uint32_t gpe0_sts;
uint32_t gpe0_en;
uint32_t tco_sts;
uint32_t prsts;
uint32_t gen_pmcon1;
uint32_t gen_pmcon2;
} __attribute__((packed));
/* Power Management Utility Functions. */
uint16_t get_pmbase(void);
uint32_t clear_smi_status(void);
uint16_t clear_pm1_status(void);
uint32_t clear_tco_status(void);
uint32_t clear_gpe_status(void);
uint32_t clear_alt_status(void);
void clear_pmc_status(void);
void enable_smi(uint32_t mask);
void disable_smi(uint32_t mask);
void enable_pm1(uint16_t events);
void enable_pm1_control(uint32_t mask);
void disable_pm1_control(uint32_t mask);
void enable_gpe(uint32_t mask);
void disable_gpe(uint32_t mask);
void disable_all_gpe(void);
#if CONFIG_ELOG
void southcluster_log_state(void);
#else
static inline void southcluster_log_state(void) {}
#endif
#endif /* !defined(__ASSEMBLER__) && !defined(__ACPI__) */
#endif /* _BAYTRAIL_PMC_H_ */

View File

@ -0,0 +1,42 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 _BAYTRAIL_RAMSTAGE_H_
#define _BAYTRAIL_RAMSTAGE_H_
#include <device/device.h>
#include <soc/intel/baytrail/chip.h>
/* The baytrail_init_pre_device() function is called prior to device
* initialization, but it's after console and cbmem has been reinitialized. */
void baytrail_init_pre_device(struct soc_intel_baytrail_config *config);
void baytrail_init_cpus(device_t dev);
void set_max_freq(void);
void southcluster_enable_dev(device_t dev);
#if CONFIG_HAVE_REFCODE_BLOB
void baytrail_run_reference_code(void);
#else
static inline void baytrail_run_reference_code(void) {}
#endif
void baytrail_init_scc(void);
void scc_enable_acpi_mode(device_t dev, int iosf_reg, int nvs_index);
extern struct pci_operations soc_pci_ops;
#endif /* _BAYTRAIL_RAMSTAGE_H_ */

View File

@ -0,0 +1,36 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 _BAYTRAIL_RESET_H_
#define _BAYTRAIL_RESET_H_
#include <reset.h>
/* Bay Trail has the following types of resets:
* - 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 (PMC_PLTRST# assertion) - write 0x6 to I/O 0xcf9
* - Global reset (S0->S5->S0 with TXE reset) - write 0x6 or 0xe to 0xcf9 but
* with ETR[20] set.
*/
void cold_reset(void);
void warm_reset(void);
#endif /* _BAYTRAIL_RESET_H_ */

View File

@ -0,0 +1,54 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 _BAYTRAIL_ROMSTAGE_H_
#define _BAYTRAIL_ROMSTAGE_H_
#if !defined(__PRE_RAM__)
#error "Don't include romstage.h from a ramstage compilation unit!"
#endif
#include <stdint.h>
#include <arch/cpu.h>
#include <soc/mrc_wrapper.h>
struct romstage_params {
unsigned long bist;
struct mrc_params *mrc_params;
};
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 mrc_params *mp, int prev_sleep_state);
void gfx_init(void);
void tco_disable(void);
void punit_init(void);
void set_max_freq(void);
int early_spi_read_wpsr(u8 *sr);
#if CONFIG_ENABLE_BUILTIN_COM1
void byt_config_com1_and_enable(void);
#else
static inline void byt_config_com1_and_enable(void) { }
#endif
#endif /* _BAYTRAIL_ROMSTAGE_H_ */

View File

@ -0,0 +1,26 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 BAYTRAIL_SATA_H
#define BAYTRAIL_SATA_H
#define SATA_SIRI 0xa0
#define SATA_SIRD 0xa4
#endif

View File

@ -0,0 +1,49 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 _BAYTRAIL_SMM_H_
#define _BAYTRAIL_SMM_H_
/* 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;
}
uintptr_t smm_region_start(void);
#if !defined(__PRE_RAM__) && !defined(__SMM___)
#include <stdint.h>
void southcluster_smm_clear_state(void);
void southcluster_smm_enable_smi(void);
void southcluster_smm_save_param(int param, uint32_t data);
#endif
enum {
SMM_SAVE_PARAM_GPIO_ROUTE = 0,
SMM_SAVE_PARAM_PCIE_WAKE_ENABLE,
SMM_SAVE_PARAM_COUNT
};
#endif /* _BAYTRAIL_SMM_H_ */

View File

@ -0,0 +1,74 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 _BAYTRAIL_SPI_H_
#define _BAYTRAIL_SPI_H_
#include <stdint.h>
/* These registers live behind SPI_BASE_ADDRESS. */
#define HSFSTS 0x04
#define FDATA0 0x10
# define FLOCKDN (0x1 << 15)
#define SSFS 0x90
# define CYCLE_DONE_STATUS (0x1 << 2)
# define FLASH_CYCLE_ERROR (0x1 << 3)
#define SSFC 0x91
# define SPI_CYCLE_GO (0x1 << 1)
# define DATA_CYCLE (0x1 << 14)
#define PREOP 0x94
#define OPTYPE 0x96
#define OPMENU0 0x98
#define OPMENU1 0x9c
#define LVSCC 0xc4
# define VCL (0x1 << 23)
# define EO(x) (((x) & 0xff) << 8)
# define WG_1_BYTE (0x0 << 2)
# define WG_64_BYTE (0x1 << 2)
# define BES_256_BYTE (0x0 << 0)
# define BES_4_KB (0x1 << 0)
# define BES_8_KB (0x2 << 0)
# define BES_64_KB (0x3 << 0)
#define UVSCC 0xc8
#define SCS 0xf8
# define SMIWPEN (0x1 << 7)
#define BCR 0xfc
# define EISS (0x1 << 5)
# define SRC_MASK (0x3 << 2)
# define SRC_CACHE_NO_PREFETCH (0x0 << 2)
# define SRC_NO_CACHE_NO_PREFETCH (0x1 << 2)
# define SRC_CACHE_PREFETCH (0x2 << 2)
# define BCR_LE (0x1 << 1)
# define BCR_WPD (0x1 << 0)
/*
* SPI lockdown configuration.
*/
struct spi_config {
uint16_t preop;
uint16_t optype;
uint32_t opmenu[2];
uint32_t lvscc;
uint32_t uvscc;
};
/* Return 0 on success < 0 on failure. */
int mainboard_get_spi_config(struct spi_config *cfg);
#endif /* _BAYTRAIL_SPI_H_ */

View File

@ -0,0 +1,56 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 BAYTRAIL_XHCI_H
#define BAYTRAIL_XHCI_H
/* XHCI PCI Registers */
#define XHCI_PWR_CTL_STS 0x74
#define XHCI_USB2PR 0xd0
#define XHCI_USB2PRM 0xd4
#define XHCI_USB3PR 0xd8
#define XHCI_USB3PRM 0xdc
#define XHCI_USB2PDO 0xe4
#define XHCI_USB3PDO 0xe8
/* XHCI Memory Registers */
#define XHCI_USB3_PORTSC(port) (0x4e0 + (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) /* Enable port */
/* The Fuse register is incorrect for Baytrail-M so use hardcoded values */
#define BYTM_USB2_PORT_COUNT 4
#define BYTM_USB2_PORT_MAP 0xf
#define BYTM_USB3_PORT_COUNT 1
#define BYTM_USB3_PORT_MAP 0x1
#define XHCI_RESET_TIMEOUT 100000 /* 100ms */
#endif /* BAYTRAIL_XHCI_H */

View File

@ -0,0 +1,287 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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/iosf.h>
#if !defined(__PRE_RAM__)
#define IOSF_PCI_BASE (CONFIG_MMCONF_BASE_ADDRESS + (IOSF_PCI_DEV << 12))
static inline void write_iosf_reg(int reg, uint32_t value)
{
write32((u32 *)(IOSF_PCI_BASE + reg), value);
}
static inline uint32_t read_iosf_reg(int reg)
{
return read32((u32 *)(IOSF_PCI_BASE + reg));
}
#else
static inline void write_iosf_reg(int reg, uint32_t value)
{
pci_write_config32(IOSF_PCI_DEV, reg, value);
}
static inline uint32_t read_iosf_reg(int reg)
{
return pci_read_config32(IOSF_PCI_DEV, reg);
}
#endif
/* Common sequences for all the port accesses. */
static uint32_t iosf_read_port(uint32_t cr, int reg)
{
cr |= IOSF_REG(reg) | IOSF_BYTE_EN;
write_iosf_reg(MCRX_REG, IOSF_REG_UPPER(reg));
write_iosf_reg(MCR_REG, cr);
return read_iosf_reg(MDR_REG);
}
static void iosf_write_port(uint32_t cr, int reg, uint32_t val)
{
cr |= IOSF_REG(reg) | IOSF_BYTE_EN;
write_iosf_reg(MDR_REG, val);
write_iosf_reg(MCRX_REG, IOSF_REG_UPPER(reg));
write_iosf_reg(MCR_REG, cr);
}
#define IOSF_READ(port) \
IOSF_OPCODE(IOSF_OP_READ_##port) | IOSF_PORT(IOSF_PORT_##port)
#define IOSF_WRITE(port) \
IOSF_OPCODE(IOSF_OP_WRITE_##port) | IOSF_PORT(IOSF_PORT_##port)
uint32_t iosf_bunit_read(int reg)
{
return iosf_read_port(IOSF_READ(BUNIT), reg);
}
void iosf_bunit_write(int reg, uint32_t val)
{
iosf_write_port(IOSF_WRITE(BUNIT), reg, val);
}
uint32_t iosf_dunit_read(int reg)
{
return iosf_read_port(IOSF_READ(SYSMEMC), reg);
}
uint32_t iosf_dunit_ch0_read(int reg)
{
return iosf_dunit_read(reg);
}
uint32_t iosf_dunit_ch1_read(int reg)
{
uint32_t cr = IOSF_OPCODE(IOSF_OP_READ_SYSMEMC) |
IOSF_PORT(IOSF_PORT_DUNIT_CH1);
return iosf_read_port(cr, reg);
}
void iosf_dunit_write(int reg, uint32_t val)
{
iosf_write_port(IOSF_WRITE(SYSMEMC), reg, val);
}
uint32_t iosf_punit_read(int reg)
{
return iosf_read_port(IOSF_READ(PMC), reg);
}
void iosf_punit_write(int reg, uint32_t val)
{
iosf_write_port(IOSF_WRITE(PMC), reg, val);
}
uint32_t iosf_usbphy_read(int reg)
{
return iosf_read_port(IOSF_READ(USBPHY), reg);
}
void iosf_usbphy_write(int reg, uint32_t val)
{
return iosf_write_port(IOSF_WRITE(USBPHY), reg, val);
}
uint32_t iosf_ushphy_read(int reg)
{
return iosf_read_port(IOSF_READ(USHPHY), reg);
}
void iosf_ushphy_write(int reg, uint32_t val)
{
return iosf_write_port(IOSF_WRITE(USHPHY), reg, val);
}
uint32_t iosf_lpss_read(int reg)
{
return iosf_read_port(IOSF_READ(LPSS), reg);
}
void iosf_lpss_write(int reg, uint32_t val)
{
return iosf_write_port(IOSF_WRITE(LPSS), reg, val);
}
uint32_t iosf_ccu_read(int reg)
{
return iosf_read_port(IOSF_READ(CCU), reg);
}
void iosf_ccu_write(int reg, uint32_t val)
{
return iosf_write_port(IOSF_WRITE(CCU), reg, val);
}
uint32_t iosf_score_read(int reg)
{
return iosf_read_port(IOSF_READ(SCORE), reg);
}
void iosf_score_write(int reg, uint32_t val)
{
return iosf_write_port(IOSF_WRITE(SCORE), reg, val);
}
uint32_t iosf_scc_read(int reg)
{
return iosf_read_port(IOSF_READ(SCC), reg);
}
void iosf_scc_write(int reg, uint32_t val)
{
return iosf_write_port(IOSF_WRITE(SCC), reg, val);
}
uint32_t iosf_aunit_read(int reg)
{
return iosf_read_port(IOSF_READ(AUNIT), reg);
}
void iosf_aunit_write(int reg, uint32_t val)
{
return iosf_write_port(IOSF_WRITE(AUNIT), reg, val);
}
uint32_t iosf_cpu_bus_read(int reg)
{
return iosf_read_port(IOSF_READ(CPU_BUS), reg);
}
void iosf_cpu_bus_write(int reg, uint32_t val)
{
return iosf_write_port(IOSF_WRITE(CPU_BUS), reg, val);
}
uint32_t iosf_sec_read(int reg)
{
return iosf_read_port(IOSF_READ(SEC), reg);
}
void iosf_sec_write(int reg, uint32_t val)
{
return iosf_write_port(IOSF_WRITE(SEC), reg, val);
}
uint32_t iosf_port45_read(int reg)
{
return iosf_read_port(IOSF_READ(0x45), reg);
}
void iosf_port45_write(int reg, uint32_t val)
{
return iosf_write_port(IOSF_WRITE(0x45), reg, val);
}
uint32_t iosf_port46_read(int reg)
{
return iosf_read_port(IOSF_READ(0x46), reg);
}
void iosf_port46_write(int reg, uint32_t val)
{
return iosf_write_port(IOSF_WRITE(0x46), reg, val);
}
uint32_t iosf_port47_read(int reg)
{
return iosf_read_port(IOSF_READ(0x47), reg);
}
void iosf_port47_write(int reg, uint32_t val)
{
return iosf_write_port(IOSF_WRITE(0x47), reg, val);
}
uint32_t iosf_port55_read(int reg)
{
return iosf_read_port(IOSF_READ(0x55), reg);
}
void iosf_port55_write(int reg, uint32_t val)
{
return iosf_write_port(IOSF_WRITE(0x55), reg, val);
}
uint32_t iosf_port58_read(int reg)
{
return iosf_read_port(IOSF_READ(0x58), reg);
}
void iosf_port58_write(int reg, uint32_t val)
{
return iosf_write_port(IOSF_WRITE(0x58), reg, val);
}
uint32_t iosf_port59_read(int reg)
{
return iosf_read_port(IOSF_READ(0x59), reg);
}
void iosf_port59_write(int reg, uint32_t val)
{
return iosf_write_port(IOSF_WRITE(0x59), reg, val);
}
uint32_t iosf_port5a_read(int reg)
{
return iosf_read_port(IOSF_READ(0x5a), reg);
}
void iosf_port5a_write(int reg, uint32_t val)
{
return iosf_write_port(IOSF_WRITE(0x5a), reg, val);
}
uint32_t iosf_porta2_read(int reg)
{
return iosf_read_port(IOSF_READ(0xa2), reg);
}
void iosf_porta2_write(int reg, uint32_t val)
{
return iosf_write_port(IOSF_WRITE(0xa2), reg, val);
}
uint32_t iosf_ssus_read(int reg)
{
return iosf_read_port(IOSF_READ(SSUS), reg);
}
void iosf_ssus_write(int reg, uint32_t val)
{
return iosf_write_port(IOSF_WRITE(SSUS), reg, val);
}

View File

@ -0,0 +1,189 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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/pci_ids.h>
#include <reg_script.h>
#include <soc/iomap.h>
#include <soc/iosf.h>
#include <soc/lpc.h>
#include <soc/nvs.h>
#include <soc/pattrs.h>
#include <soc/pci_devs.h>
#include <soc/pmc.h>
#include <soc/ramstage.h>
#include "chip.h"
/* The LPE audio devices needs 1MiB of memory reserved aligned to a 512MiB
* address. Just take 1MiB @ 512MiB. */
#define FIRMWARE_PHYS_BASE (512 << 20)
#define FIRMWARE_PHYS_LENGTH (1 << 20)
#define FIRMWARE_PCI_REG_BASE 0xa8
#define FIRMWARE_PCI_REG_LENGTH 0xac
#define FIRMWARE_REG_BASE_C0 0x144000
#define FIRMWARE_REG_LENGTH_C0 (FIRMWARE_REG_BASE_C0 + 4)
static void assign_device_nvs(device_t dev, u32 *field, unsigned index)
{
struct resource *res;
res = find_resource(dev, index);
if (res)
*field = res->base;
}
static void lpe_enable_acpi_mode(device_t dev)
{
static const struct reg_script ops[] = {
/* Disable PCI interrupt, enable Memory and Bus Master */
REG_PCI_OR32(PCI_COMMAND,
PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | (1<<10)),
/* Enable ACPI mode */
REG_IOSF_OR(IOSF_PORT_0x58, LPE_PCICFGCTR1,
LPE_PCICFGCTR1_PCI_CFG_DIS |
LPE_PCICFGCTR1_ACPI_INT_EN),
REG_SCRIPT_END
};
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, BAR1, and firmware base to ACPI NVS */
assign_device_nvs(dev, &gnvs->dev.lpe_bar0, PCI_BASE_ADDRESS_0);
assign_device_nvs(dev, &gnvs->dev.lpe_bar1, PCI_BASE_ADDRESS_1);
assign_device_nvs(dev, &gnvs->dev.lpe_fw, FIRMWARE_PCI_REG_BASE);
/* Device is enabled in ACPI mode */
gnvs->dev.lpe_en = 1;
/* Put device in ACPI mode */
reg_script_run_on_dev(dev, ops);
}
static void setup_codec_clock(device_t dev)
{
uint32_t reg;
u32 *clk_reg;
struct soc_intel_baytrail_config *config;
const char *freq_str;
config = dev->chip_info;
switch (config->lpe_codec_clk_freq) {
case 19:
freq_str = "19.2";
reg = CLK_FREQ_19P2MHZ;
break;
case 25:
freq_str = "25";
reg = CLK_FREQ_25MHZ;
break;
default:
printk(BIOS_DEBUG, "LPE codec clock not required.\n");
return;
}
/* Default to always running. */
reg |= CLK_CTL_ON;
if (config->lpe_codec_clk_num < 0 || config->lpe_codec_clk_num > 5) {
printk(BIOS_DEBUG, "Invalid LPE codec clock number.\n");
return;
}
printk(BIOS_DEBUG, "LPE Audio codec clock set to %sMHz.\n", freq_str);
clk_reg = (u32 *)(PMC_BASE_ADDRESS + PLT_CLK_CTL_0);
clk_reg += config->lpe_codec_clk_num;
write32(clk_reg, (read32(clk_reg) & ~0x7) | reg);
}
static void lpe_stash_firmware_info(device_t dev)
{
struct resource *res;
struct resource *mmio;
const struct pattrs *pattrs = pattrs_get();
res = find_resource(dev, FIRMWARE_PCI_REG_BASE);
if (res == NULL) {
printk(BIOS_DEBUG, "LPE Firmware memory not found.\n");
return;
}
/* Continue using old way of informing firmware address / size. */
pci_write_config32(dev, FIRMWARE_PCI_REG_BASE, res->base);
pci_write_config32(dev, FIRMWARE_PCI_REG_LENGTH, res->size);
/* C0 and later steppings use an offset in the MMIO space. */
if (pattrs->stepping >= STEP_C0) {
mmio = find_resource(dev, PCI_BASE_ADDRESS_0);
write32((u32 *)(uintptr_t)(mmio->base + FIRMWARE_REG_BASE_C0),
res->base);
write32((u32 *)(uintptr_t)(mmio->base + FIRMWARE_REG_LENGTH_C0),
res->size);
}
}
static void lpe_init(device_t dev)
{
struct soc_intel_baytrail_config *config = dev->chip_info;
lpe_stash_firmware_info(dev);
setup_codec_clock(dev);
if (config->lpe_acpi_mode)
lpe_enable_acpi_mode(dev);
}
static void lpe_read_resources(device_t dev)
{
pci_dev_read_resources(dev);
reserved_ram_resource(dev, FIRMWARE_PCI_REG_BASE,
FIRMWARE_PHYS_BASE >> 10,
FIRMWARE_PHYS_LENGTH >> 10);
}
static const struct device_operations device_ops = {
.read_resources = lpe_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = lpe_init,
.enable = NULL,
.scan_bus = NULL,
.ops_pci = &soc_pci_ops,
};
static const struct pci_driver southcluster __pci_driver = {
.ops = &device_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.device = LPE_DEVID,
};

View File

@ -0,0 +1,206 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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/io.h>
#include <cbmem.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <reg_script.h>
#include <soc/iosf.h>
#include <soc/nvs.h>
#include <soc/pci_devs.h>
#include <soc/ramstage.h>
#include "chip.h"
static void dev_enable_acpi_mode(device_t dev, int iosf_reg, int nvs_index)
{
struct reg_script ops[] = {
/* Disable PCI interrupt, enable Memory and Bus Master */
REG_PCI_OR32(PCI_COMMAND,
PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | (1<<10)),
/* Enable ACPI mode */
REG_IOSF_OR(IOSF_PORT_LPSS, iosf_reg,
LPSS_CTL_PCI_CFG_DIS | LPSS_CTL_ACPI_INT_EN),
REG_SCRIPT_END
};
struct resource *bar;
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 */
bar = find_resource(dev, PCI_BASE_ADDRESS_0);
if (bar)
gnvs->dev.lpss_bar0[nvs_index] = (u32)bar->base;
bar = find_resource(dev, PCI_BASE_ADDRESS_1);
if (bar)
gnvs->dev.lpss_bar1[nvs_index] = (u32)bar->base;
/* Device is enabled in ACPI mode */
gnvs->dev.lpss_en[nvs_index] = 1;
/* Put device in ACPI mode */
reg_script_run_on_dev(dev, ops);
}
static void dev_enable_snoop_and_pm(device_t dev, int iosf_reg)
{
struct reg_script ops[] = {
REG_IOSF_RMW(IOSF_PORT_LPSS, iosf_reg,
~(LPSS_CTL_SNOOP | LPSS_CTL_NOSNOOP),
LPSS_CTL_SNOOP | LPSS_CTL_PM_CAP_PRSNT),
REG_SCRIPT_END,
};
reg_script_run_on_dev(dev, ops);
}
static void dev_ctl_reg(device_t dev, int *iosf_reg, int *nvs_index)
{
*iosf_reg = -1;
*nvs_index = -1;
#define SET_IOSF_REG(name_) \
case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC): \
*iosf_reg = LPSS_ ## name_ ## _CTL; \
*nvs_index = LPSS_NVS_ ## name_
switch (dev->path.pci.devfn) {
SET_IOSF_REG(SIO_DMA1);
break;
SET_IOSF_REG(I2C1);
break;
SET_IOSF_REG(I2C2);
break;
SET_IOSF_REG(I2C3);
break;
SET_IOSF_REG(I2C4);
break;
SET_IOSF_REG(I2C5);
break;
SET_IOSF_REG(I2C6);
break;
SET_IOSF_REG(I2C7);
break;
SET_IOSF_REG(SIO_DMA2);
break;
SET_IOSF_REG(PWM1);
break;
SET_IOSF_REG(PWM2);
break;
SET_IOSF_REG(HSUART1);
break;
SET_IOSF_REG(HSUART2);
break;
SET_IOSF_REG(SPI);
break;
}
}
static void i2c_disable_resets(device_t dev)
{
/* Release the I2C devices from reset. */
static const struct reg_script ops[] = {
REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x804, 0x3),
REG_SCRIPT_END,
};
#define CASE_I2C(name_) \
case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC)
switch (dev->path.pci.devfn) {
CASE_I2C(I2C1):
CASE_I2C(I2C2):
CASE_I2C(I2C3):
CASE_I2C(I2C4):
CASE_I2C(I2C5):
CASE_I2C(I2C6):
CASE_I2C(I2C7):
printk(BIOS_DEBUG, "Releasing I2C device from reset.\n");
reg_script_run_on_dev(dev, ops);
break;
default:
return;
}
}
static void lpss_init(device_t dev)
{
struct soc_intel_baytrail_config *config = dev->chip_info;
int iosf_reg, nvs_index;
dev_ctl_reg(dev, &iosf_reg, &nvs_index);
if (iosf_reg < 0) {
int slot = PCI_SLOT(dev->path.pci.devfn);
int func = PCI_FUNC(dev->path.pci.devfn);
printk(BIOS_DEBUG, "Could not find iosf_reg for %02x.%01x\n",
slot, func);
return;
}
dev_enable_snoop_and_pm(dev, iosf_reg);
i2c_disable_resets(dev);
if (config->lpss_acpi_mode)
dev_enable_acpi_mode(dev, iosf_reg, nvs_index);
}
static struct device_operations device_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = lpss_init,
.enable = NULL,
.scan_bus = NULL,
.ops_pci = &soc_pci_ops,
};
static const unsigned short pci_device_ids[] = {
SIO_DMA1_DEVID,
I2C1_DEVID,
I2C2_DEVID,
I2C3_DEVID,
I2C4_DEVID,
I2C5_DEVID,
I2C6_DEVID,
I2C7_DEVID,
SIO_DMA2_DEVID,
PWM1_DEVID,
PWM2_DEVID,
HSUART1_DEVID,
HSUART2_DEVID,
SPI_DEVID,
0,
};
static const struct pci_driver southcluster __pci_driver = {
.ops = &device_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.devices = pci_device_ids,
};

View File

@ -0,0 +1,33 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 <soc/iosf.h>
#include <soc/smm.h>
uintptr_t smm_region_start(void)
{
return (iosf_bunit_read(BUNIT_SMRRL) << 20);
}
void *cbmem_top(void)
{
return (void *) smm_region_start();
}

View File

@ -0,0 +1 @@
cpu_microcode-$(CONFIG_CPU_MICROCODE_CBFS_GENERATE) += microcode_blob.c

View File

@ -0,0 +1,3 @@
unsigned microcode[] = {
#include "../../../../../3rdparty/soc/intel/baytrail/microcode_blob.h"
};

View File

@ -0,0 +1,148 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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/x86/smm.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <vendorcode/google/chromeos/chromeos.h>
#include <soc/iomap.h>
#include <soc/iosf.h>
#include <soc/pci_devs.h>
#include <soc/ramstage.h>
/* Host Memory Map:
*
* +--------------------------+ BMBOUND_HI
* | Usable DRAM |
* +--------------------------+ 4GiB
* | PCI Address Space |
* +--------------------------+ BMBOUND
* | TPM |
* +--------------------------+ IMR2
* | TXE |
* +--------------------------+ IMR1
* | iGD |
* +--------------------------+
* | GTT |
* +--------------------------+ SMMRRH, IRM0
* | TSEG |
* +--------------------------+ SMMRRL
* | Usable DRAM |
* +--------------------------+ 0
*
* Note that there are really only a few regions that need to enumerated w.r.t.
* coreboot's resource model:
*
* +--------------------------+ BMBOUND_HI
* | Cacheable/Usable |
* +--------------------------+ 4GiB
*
* +--------------------------+ BMBOUND
* | Uncacheable/Reserved |
* +--------------------------+ SMMRRH
* | Cacheable/Reserved |
* +--------------------------+ SMMRRL
* | Cacheable/Usable |
* +--------------------------+ 0
*/
#define RES_IN_KiB(r) ((r) >> 10)
uint32_t nc_read_top_of_low_memory(void)
{
return iosf_bunit_read(BUNIT_BMBOUND) & ~((1 << 27) - 1);
}
static void nc_read_resources(device_t dev)
{
unsigned long mmconf;
unsigned long bmbound;
unsigned long bmbound_hi;
unsigned long smmrrh;
unsigned long smmrrl;
unsigned long base_k, size_k;
const unsigned long four_gig_kib = (4 << (30 - 10));
int index = 0;
/* Read standard PCI resources. */
pci_dev_read_resources(dev);
/* PCIe memory-mapped config space access - 256 MiB. */
mmconf = iosf_bunit_read(BUNIT_MMCONF_REG) & ~((1 << 28) - 1);
mmio_resource(dev, BUNIT_MMCONF_REG, RES_IN_KiB(mmconf), 256 * 1024);
/* 0 -> 0xa0000 */
base_k = RES_IN_KiB(0);
size_k = RES_IN_KiB(0xa0000) - base_k;
ram_resource(dev, index++, base_k, size_k);
/* The SMMRR registers are 1MiB granularity with smmrrh being
* inclusive of the SMM region. */
smmrrl = (iosf_bunit_read(BUNIT_SMRRL) & 0xffff) << 10;
smmrrh = ((iosf_bunit_read(BUNIT_SMRRH) & 0xffff) + 1) << 10;
/* 0xc0000 -> smrrl - cacheable and usable */
base_k = RES_IN_KiB(0xc0000);
size_k = smmrrl - base_k;
ram_resource(dev, index++, base_k, size_k);
if (smmrrh > smmrrl)
reserved_ram_resource(dev, index++, smmrrl, smmrrh - smmrrl);
/* All address space between bmbound and smmrrh is unusable. */
bmbound = RES_IN_KiB(nc_read_top_of_low_memory());
mmio_resource(dev, index++, smmrrh, bmbound - smmrrh);
/* The BMBOUND_HI register matches register bits of 31:24 with address
* bits of 35:28. Therefore, shift register to align properly. */
bmbound_hi = iosf_bunit_read(BUNIT_BMBOUND_HI) & ~((1 << 24) - 1);
bmbound_hi = RES_IN_KiB(bmbound_hi) << 4;
if (bmbound_hi > four_gig_kib)
ram_resource(dev, index++, four_gig_kib,
bmbound_hi - four_gig_kib);
/* Reserve everything between A segment and 1MB:
*
* 0xa0000 - 0xbffff: legacy VGA
* 0xc0000 - 0xfffff: RAM
*/
mmio_resource(dev, index++, (0xa0000 >> 10), (0xc0000 - 0xa0000) >> 10);
reserved_ram_resource(dev, index++, (0xc0000 >> 10),
(0x100000 - 0xc0000) >> 10);
chromeos_reserve_ram_oops(dev, index++);
}
static struct device_operations nc_ops = {
.read_resources = nc_read_resources,
.set_resources = NULL,
.enable_resources = NULL,
.init = NULL,
.enable = NULL,
.scan_bus = NULL,
.ops_pci = &soc_pci_ops,
};
static const struct pci_driver nc_driver __pci_driver = {
.ops = &nc_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.device = SOC_DEVID,
};

View File

@ -0,0 +1,278 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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_ids.h>
#include <reg_script.h>
#include <soc/pci_devs.h>
#include <soc/pcie.h>
#include <soc/ramstage.h>
#include <soc/smm.h>
#include "chip.h"
static int pll_en_off;
static uint32_t strpfusecfg;
static inline int root_port_offset(device_t dev)
{
return PCI_FUNC(dev->path.pci.devfn);
}
static inline int is_first_port(device_t dev)
{
return root_port_offset(dev) == PCIE_PORT1_FUNC;
}
static const struct reg_script init_static_before_exit_latency[] = {
/* Disable optimized buffer flush fill and latency tolerant reporting */
REG_PCI_RMW32(DCAP2, ~(OBFFS | LTRMS), 0),
REG_PCI_RMW32(DSTS2, ~(OBFFEN| LTRME), 0),
/* Set maximum payload size. */
REG_PCI_RMW32(DCAP, ~MPS_MASK, 0),
/* Disable transmit datapath flush timer, clear transmit config change
* wait time, clear sideband interface idle counter. */
REG_PCI_RMW32(PHYCTL2_IOSFBCTL, ~(TDFT | TXCFGCHWAIT | SIID), 0),
REG_SCRIPT_END,
};
static const struct reg_script init_static_after_exit_latency[] = {
/* Set common clock configuration. */
REG_PCI_OR16(LCTL, CCC),
/* Set NFTS to 0x743a361b */
REG_PCI_WRITE32(NFTS, 0x743a361b),
/* Set common clock latency to 0x3 */
REG_PCI_RMW32(MPC, ~CCEL_MASK, (0x3 << CCEL_SHIFT)),
/* Set relay timer policy. */
REG_PCI_RMW32(RTP, 0xff000000, 0x854c74),
/* Set IOSF packet fast transmit mode and link speed training policy. */
REG_PCI_OR16(MPC2, IPF | LSTP),
/* Channel configuration - enable upstream posted split, set non-posted
* and posted request size */
REG_PCI_RMW32(CHCFG, ~UPSD, UNRS | UPRS),
/* Completion status replay enable and set TLP grant count */
REG_PCI_RMW32(CFG2, ~(LATGC_MASK), CSREN | (3 << LATGC_SHIFT)),
/* Assume no IOAPIC behind root port -- disable EOI forwarding. */
REG_PCI_OR16(MPC2, EOIFD),
/* Expose AER */
REG_PCI_RMW32(AERCH, ~0, (1 << 16) | (1 << 0)),
/* set completion timeout to 160ms to 170ms */
REG_PCI_RMW16(DSTS2, ~CTD, 0x6),
/* Enable AER */
REG_PCI_OR16(DCTL_DSTS, URE | FEE | NFE | CEE),
/* Read and write back capability registers. */
REG_PCI_OR32(0x34, 0),
REG_PCI_OR32(0x80, 0),
/* Retrain the link. */
REG_PCI_OR16(LCTL, RL),
REG_SCRIPT_END,
};
static void byt_pcie_init(device_t dev)
{
struct reg_script init_script[] = {
REG_SCRIPT_NEXT(init_static_before_exit_latency),
/* Exit latency configuration based on
* PHYCTL2_IOSFBCTL[PLL_OFF_EN] set in root port 1*/
REG_PCI_RMW32(LCAP, ~L1EXIT_MASK,
2 << (L1EXIT_SHIFT + pll_en_off)),
REG_SCRIPT_NEXT(init_static_after_exit_latency),
/* Disable hot plug, set power to 10W, set slot number. */
REG_PCI_RMW32(SLCAP, ~(HPC | HPS),
(1 << SLS_SHIFT) | (100 << SLV_SHIFT) |
(root_port_offset(dev) << SLN_SHIFT)),
/* Dynamic clock gating. */
REG_PCI_OR32(RPPGEN, RPDLCGEN | RPDBCGEN | RPSCGEN),
REG_PCI_OR32(PWRCTL, RPL1SQPOL | RPDTSQPOL),
REG_PCI_OR32(PCIEDBG, SPCE),
REG_SCRIPT_END,
};
reg_script_run_on_dev(dev, init_script);
if (is_first_port(dev)) {
struct soc_intel_baytrail_config *config = dev->chip_info;
uint32_t reg = pci_read_config32(dev, RPPGEN);
reg |= SRDLCGEN | SRDBCGEN;
if (config && config->clkreq_enable)
reg |= LCLKREQEN | BBCLKREQEN;
pci_write_config32(dev, RPPGEN, reg);
}
}
static const struct reg_script no_dev_behind_port[] = {
REG_PCI_OR32(PCIEALC, (1 << 26)),
REG_PCI_POLL32(PCIESTS1, 0x1f000000, (1 << 24), 50000),
REG_PCI_OR32(PHYCTL4, SQDIS),
REG_SCRIPT_END,
};
static void check_port_enabled(device_t dev)
{
int rp_config = (strpfusecfg & LANECFG_MASK) >> LANECFG_SHIFT;
switch (root_port_offset(dev)) {
case PCIE_PORT1_FUNC:
/* Port 1 cannot be disabled from strapping config. */
break;
case PCIE_PORT2_FUNC:
/* Port 2 disabled in all configs but 4x1. */
if (rp_config != 0x0)
dev->enabled = 0;
break;
case PCIE_PORT3_FUNC:
/* Port 3 disabled only in 1x4 config. */
if (rp_config == 0x3)
dev->enabled = 0;
break;
case PCIE_PORT4_FUNC:
/* Port 4 disabled in 1x4 and 2x2 config. */
if (rp_config >= 0x2)
dev->enabled = 0;
break;
}
}
static u8 all_ports_no_dev_present(device_t dev)
{
u8 func;
u8 temp = dev->path.pci.devfn;
u8 device_not_present = 1;
u8 data;
for (func = 1; func < PCIE_ROOT_PORT_COUNT; func++) {
dev->path.pci.devfn &= ~0x7;
dev->path.pci.devfn |= func;
/* is pcie device there */
if (pci_read_config32(dev, 0) == 0xFFFFFFFF)
continue;
data = pci_read_config8(dev, XCAP + 3) | (SI >> 24);
pci_write_config8(dev, XCAP + 3, data);
/* is any device present */
if ((pci_read_config32(dev, SLCTL_SLSTS) & PDS)) {
device_not_present = 0;
break;
}
}
dev->path.pci.devfn = temp;
return device_not_present;
}
static void check_device_present(device_t dev)
{
/* Set slot implemented. */
pci_write_config32(dev, XCAP, pci_read_config32(dev, XCAP) | SI);
/* No device present. */
if (!(pci_read_config32(dev, SLCTL_SLSTS) & PDS)) {
printk(BIOS_DEBUG, "No PCIe device present.\n");
if (is_first_port(dev)) {
if (all_ports_no_dev_present(dev)) {
reg_script_run_on_dev(dev, no_dev_behind_port);
dev->enabled = 0;
}
} else {
reg_script_run_on_dev(dev, no_dev_behind_port);
dev->enabled = 0;
}
} else if(!dev->enabled) {
/* Port is disabled, but device present. Disable link. */
pci_write_config32(dev, LCTL,
pci_read_config32(dev, LCTL) | LD);
}
}
static void byt_pcie_enable(device_t dev)
{
if (is_first_port(dev)) {
struct soc_intel_baytrail_config *config = dev->chip_info;
uint32_t reg = pci_read_config32(dev, PHYCTL2_IOSFBCTL);
pll_en_off = !!(reg & PLL_OFF_EN);
strpfusecfg = pci_read_config32(dev, STRPFUSECFG);
if (config && config->pcie_wake_enable)
southcluster_smm_save_param(
SMM_SAVE_PARAM_PCIE_WAKE_ENABLE, 1);
}
/* Check if device is enabled in strapping. */
check_port_enabled(dev);
/* Determine if device is behind port. */
check_device_present(dev);
southcluster_enable_dev(dev);
}
static unsigned int byt_pciexp_scan_bridge(device_t dev, unsigned int max)
{
static const struct reg_script wait_for_link_active[] = {
REG_PCI_POLL32(LCTL, (1 << 29) , (1 << 29), 50000),
REG_SCRIPT_END,
};
/* wait for Link Active with 50ms timeout */
reg_script_run_on_dev(dev, wait_for_link_active);
return do_pci_scan_bridge(dev, max, pciexp_scan_bus);
}
static void pcie_root_set_subsystem(device_t dev, unsigned vid, unsigned did)
{
uint32_t didvid = ((did & 0xffff) << 16) | (vid & 0xffff);
if (!didvid)
didvid = pci_read_config32(dev, PCI_VENDOR_ID);
pci_write_config32(dev, 0x94, didvid);
}
static struct pci_operations pcie_root_ops = {
.set_subsystem = &pcie_root_set_subsystem,
};
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 = byt_pcie_init,
.scan_bus = byt_pciexp_scan_bridge,
.enable = byt_pcie_enable,
.ops_pci = &pcie_root_ops,
};
static const unsigned short pci_device_ids[] = {
PCIE_PORT1_DEVID, PCIE_PORT2_DEVID, PCIE_PORT3_DEVID, PCIE_PORT4_DEVID,
0
};
static const struct pci_driver pcie_root_ports __pci_driver = {
.ops = &device_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.devices = pci_device_ids,
};

View File

@ -0,0 +1,292 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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/io.h>
#include <bootstate.h>
#include <console/console.h>
#include <reg_script.h>
#include <soc/iosf.h>
#define MAKE_MASK_INCLUSIVE(msb) \
((1ULL << (1 + (msb))) - 1)
#define MAKE_MASK(msb) \
((1ULL << (msb)) - 1)
#define MASK_VAL(msb, lsb, val) \
~(MAKE_MASK_INCLUSIVE(msb) & ~MAKE_MASK(lsb)), (val) << (lsb)
#define E(arg1, arg2, args) \
REG_IOSF_RMW(IOSF_PORT_##arg1, arg2, args)
static const struct reg_script perf_power_settings[] = {
E(AUNIT, 0x18, MASK_VAL(22, 22, 0x1)), // ACKGATE.AMESSAGE_MSGIF
E(AUNIT, 0x18, MASK_VAL(21, 21, 0x1)), // ACKGATE.AREQDOWN_SCL0_ARB
E(AUNIT, 0x18, MASK_VAL(20, 20, 0x1)), // ACKGATE.AREQUP_MIRROR
E(AUNIT, 0x18, MASK_VAL(19, 19, 0x1)), // ACKGATE.AREQTAHACK
E(AUNIT, 0x18, MASK_VAL(18, 18, 0x1)), // ACKGATE.AREQDOWN_TAREQQ
E(AUNIT, 0x18, MASK_VAL(17, 17, 0x1)), // ACKGATE.AREQDOWN_CREDIT
E(AUNIT, 0x18, MASK_VAL(16, 16, 0x1)), // ACKGATE.ASCLUP_FAIR_ARBITER
E(AUNIT, 0x18, MASK_VAL(15, 15, 0x1)), // ACKGATE.AIOSFDOWN_DATA
E(AUNIT, 0x18, MASK_VAL(14, 14, 0x1)), // ACKGATE.ASCLUP_IOSF_ADAPTER
E(AUNIT, 0x18, MASK_VAL(12, 12, 0x1)), // ACKGATE.ASCLUP_CMD_QUEUE
E(AUNIT, 0x18, MASK_VAL(11, 11, 0x1)), // ACKGATE.ASCLUP_DATA_QUEUE
E(AUNIT, 0x18, MASK_VAL(10, 10, 0x1)), // ACKGATE.AREQUP_CMD_QUEUE
E(AUNIT, 0x18, MASK_VAL(9, 9, 0x1)), // ACKGATE.AREQUP_DATA_QUEUE
E(AUNIT, 0x18, MASK_VAL(8, 8, 0x1)), // ACKGATE.AREQDOWN_RSP_QUEUE
E(AUNIT, 0x18, MASK_VAL(7, 7, 0x1)), // ACKGATE.AREQDOWN_DATA_QUEUE
E(AUNIT, 0x18, MASK_VAL(6, 6, 0x1)), // ACKGATE.AIOSFDOWN_CMD_DRVR
E(AUNIT, 0x18, MASK_VAL(5, 5, 0x1)), // ACKGATE.AIOSFDOWN_CMD_DATA_BUFF
E(AUNIT, 0x18, MASK_VAL(4, 4, 0x1)), // ACKGATE.AT_REQ_QUEUE
E(AUNIT, 0x18, MASK_VAL(3, 3, 0x1)), // ACKGATE.AT_DATA_QUEUE
E(AUNIT, 0x18, MASK_VAL(2, 2, 0x1)), // ACKGATE.TA_REQ_QUEUE
E(AUNIT, 0x18, MASK_VAL(1, 1, 0x1)), // ACKGATE.TA_DATA_QUEUE
E(AUNIT, 0x18, MASK_VAL(0, 0, 0x1)), // ACKGATE.CONFIG_REGS
E(AUNIT, 0x20, MASK_VAL(26, 24, 0x2)), // AISOCHCTL.CHANNEL_AB_DEADLINE_EN
E(AUNIT, 0x20, MASK_VAL(8, 0, 0x1)), // AISOCHCTL.VC1_ISOC_CH_DEFAULT_DDLINE_DLY
E(AUNIT, 0x21, MASK_VAL(31, 31, 0x1)), // AVCCTL.EFFICIENT_PERF_UP_EN
E(AUNIT, 0x21, MASK_VAL(8, 8, 0x0)), // AVCCTL.VC_EN_PRIORITY_DNARB
E(AUNIT, 0x0C0, MASK_VAL(11, 8, 0x4)), // AARBCTL0.IOSF0VC2_WGT
E(AUNIT, 0x0C0, MASK_VAL(7, 4, 0x4)), // AARBCTL0.IOSF0VC1_WGT
E(AUNIT, 0x0C0, MASK_VAL(3, 0, 0x4)), // AARBCTL0.IOSF0VC0_WGT
E(BUNIT, 0x3, MASK_VAL(29, 24, 0x4)), // BARBCTRL0.AGENT3_WEIGHT
E(BUNIT, 0x3, MASK_VAL(21, 16, 0x4)), // BARBCTRL0.AGENT2_WEIGHT
E(BUNIT, 0x3, MASK_VAL(13, 8, 0x4)), // BARBCTRL0.AGENT1_WEIGHT
E(BUNIT, 0x3, MASK_VAL(5, 0, 0x4)), // BARBCTRL0.AGENT0_WEIGHT
E(BUNIT, 0x4, MASK_VAL(29, 24, 0x4)), // BARBCTRL1.AGENT7_WEIGHT
E(BUNIT, 0x4, MASK_VAL(21, 16, 0x4)), // BARBCTRL1.AGENT6_WEIGHT
E(BUNIT, 0x4, MASK_VAL(13, 8, 0x4)), // BARBCTRL1.AGENT5_WEIGHT
E(BUNIT, 0x4, MASK_VAL(5, 0, 0x4)), // BARBCTRL1.AGENT4_WEIGHT
E(BUNIT, 0x5, MASK_VAL(21, 16, 0x4)), // BARBCTRL2.AGENT10_WEIGHT
E(BUNIT, 0x5, MASK_VAL(13, 8, 0x4)), // BARBCTRL2.AGENT9_WEIGHT
E(BUNIT, 0x5, MASK_VAL(5, 0, 0x8)), // BARBCTRL2.AGENT8_WEIGHT
E(BUNIT, 0x7, MASK_VAL(31, 24, 0x20)), // BWFLUSH.FLUSH_THRSHOLD
E(BUNIT, 0x7, MASK_VAL(15, 8, 0x0A)), // BWFLUSH.DIRTY_LWM
E(BUNIT, 0x7, MASK_VAL(7, 0, 0x10)), // BWFLUSH.DIRTY_HWM
E(BUNIT, 0x8, MASK_VAL(23, 0, 0x0)), // BBANKMASK.BANK_MASK
E(BUNIT, 0x9, MASK_VAL(23, 0, 0x3FFFFC)), // BROWMASK.ROW_MASK
E(BUNIT, 0x0A, MASK_VAL(9, 0, 0x080)), // BRANKMASK.RANK_MASK
E(BUNIT, 0x0B, MASK_VAL(29, 24, 0x1F)), // BALIMIT0.AGENT3_LIMIT
E(BUNIT, 0x0B, MASK_VAL(21, 16, 0x2F)), // BALIMIT0.AGENT2_LIMIT
E(BUNIT, 0x0B, MASK_VAL(13, 8, 0x2F)), // BALIMIT0.AGENT1_LIMIT
E(BUNIT, 0x0B, MASK_VAL(5, 0, 0x2F)), // BALIMIT0.AGENT0_LIMIT
E(BUNIT, 0x0C, MASK_VAL(29, 24, 0x2F)), // BALIMIT1.AGENT7_LIMIT
E(BUNIT, 0x0C, MASK_VAL(21, 16, 0x2F)), // BALIMIT1.AGENT6_LIMIT
E(BUNIT, 0x0C, MASK_VAL(13, 8, 0x2F)), // BALIMIT1.AGENT5_LIMIT
E(BUNIT, 0x0C, MASK_VAL(5, 0, 0x2B)), // BALIMIT1.AGENT4_LIMIT
E(BUNIT, 0x0D, MASK_VAL(21, 16, 0x2F)), // BALIMIT2.AGENT10_LIMIT
E(BUNIT, 0x0D, MASK_VAL(13, 8, 0x2F)), // BALIMIT2.AGENT9_LIMIT
E(BUNIT, 0x0D, MASK_VAL(5, 0, 0x2F)), // BALIMIT2.AGENT8_LIMIT
E(BUNIT, 0x0F, MASK_VAL(29, 28, 0x0)), // BARES0.AGENT7_RSVD
E(BUNIT, 0x0F, MASK_VAL(25, 24, 0x0)), // BARES0.AGENT6_RSVD
E(BUNIT, 0x0F, MASK_VAL(21, 20, 0x0)), // BARES0.AGENT5_RSVD
E(BUNIT, 0x0F, MASK_VAL(17, 16, 0x0)), // BARES0.AGENT4_RSVD
E(BUNIT, 0x0F, MASK_VAL(13, 12, 0x0)), // BARES0.AGENT3_RSVD
E(BUNIT, 0x0F, MASK_VAL(9, 8, 0x0)), // BARES0.AGENT2_RSVD
E(BUNIT, 0x0F, MASK_VAL(5, 4, 0x0)), // BARES0.AGENT1_RSVD
E(BUNIT, 0x0F, MASK_VAL(1, 0, 0x0)), // BARES0.AGENT0_RSVD
E(BUNIT, 0x10, MASK_VAL(9, 8, 0x0)), // BARES1.AGENT10_RSVD
E(BUNIT, 0x10, MASK_VAL(5, 4, 0x0)), // BARES1.AGENT9_RSVD
E(BUNIT, 0x10, MASK_VAL(1, 0, 0x0)), // BARES1.AGENT8_RSVD
E(BUNIT, 0x11, MASK_VAL(31, 22, 0x20)), // BISOC.ENTER_SELF_REFRESH_THRSH
E(BUNIT, 0x11, MASK_VAL(18, 18, 0x1)), // BISOC.SR_EXIT_SYNC_EN
E(BUNIT, 0x11, MASK_VAL(17, 12, 0x4)), // BISOC.ENTER_SELF_REFRESH_DLY
E(BUNIT, 0x11, MASK_VAL(11, 8, 0x8)), // BISOC.SCHEDULER_LATENCY
E(BUNIT, 0x12, MASK_VAL(31, 30, 0x0)), // BCOSCAT.COS_CAT_AGENT15 and BCOSCAT.BUS_LOCK_THROTTLE_ENABLE
E(BUNIT, 0x12, MASK_VAL(29, 28, 0x0)), // BCOSCAT.COS_CAT_AGENT14
E(BUNIT, 0x12, MASK_VAL(27, 26, 0x0)), // BCOSCAT.COS_CAT_AGENT13
E(BUNIT, 0x12, MASK_VAL(25, 24, 0x0)), // BCOSCAT.COS_CAT_AGENT12
E(BUNIT, 0x12, MASK_VAL(23, 22, 0x0)), // BCOSCAT.COS_CAT_AGENT11
E(BUNIT, 0x12, MASK_VAL(21, 20, 0x0)), // BCOSCAT.COS_CAT_AGENT10
E(BUNIT, 0x12, MASK_VAL(19, 18, 0x0)), // BCOSCAT.COS_CAT_AGENT9
E(BUNIT, 0x12, MASK_VAL(17, 16, 0x1)), // BCOSCAT.COS_CAT_AGENT8
E(BUNIT, 0x12, MASK_VAL(15, 14, 0x0)), // BCOSCAT.COS_CAT_AGENT7
E(BUNIT, 0x12, MASK_VAL(13, 12, 0x0)), // BCOSCAT.COS_CAT_AGENT6
E(BUNIT, 0x12, MASK_VAL(11, 10, 0x1)), // BCOSCAT.COS_CAT_AGENT5
E(BUNIT, 0x12, MASK_VAL(9, 8, 0x1)), // BCOSCAT.COS_CAT_AGENT4
E(BUNIT, 0x12, MASK_VAL(7, 6, 0x0)), // BCOSCAT.COS_CAT_AGENT3
E(BUNIT, 0x12, MASK_VAL(5, 4, 0x0)), // BCOSCAT.COS_CAT_AGENT2
E(BUNIT, 0x12, MASK_VAL(3, 2, 0x0)), // BCOSCAT.COS_CAT_AGENT1
E(BUNIT, 0x12, MASK_VAL(1, 0, 0x0)), // BCOSCAT.COS_CAT_AGENT0
E(BUNIT, 0x14, MASK_VAL(31, 31, 0x0)), // BFLWT.DISABLE_FLUSH_WEIGHTS
E(BUNIT, 0x14, MASK_VAL(30, 30, 0x0)), // BFLWT.ENABLE_READ_INVALIDATE_TIMER
E(BUNIT, 0x14, MASK_VAL(13, 8, 0x8)), // BFLWT.WRITE_WEIGHTS
E(BUNIT, 0x14, MASK_VAL(5, 0, 0x10)), // BFLWT.READ_WEIGHTS
E(BUNIT, 0x16, MASK_VAL(31, 31, 0x0)), // BISOCWT.ENABLE_ISOC_WEIGHTS
E(BUNIT, 0x16, MASK_VAL(13, 8, 0x3F)), // BISOCWT.ISOC_REQUEST_WEIGHTS
E(BUNIT, 0x16, MASK_VAL(5, 0, 0x8)), // BISOCWT.NON_ISOC_REQUEST_WEIGHTS
E(BUNIT, 0x18, MASK_VAL(31, 24, 0x20)), // BSCHCTRL0.BEST_EFFORT_MAX_LATENCY
E(BUNIT, 0x18, MASK_VAL(23, 21, 0x6)), // BSCHCTRL0.PAGE_HIT_DELAY
E(BUNIT, 0x18, MASK_VAL(13, 7, 0x0)), // BSCHCTRL0.ISOC_BANK_PREFETCH
E(BUNIT, 0x18, MASK_VAL(6, 0, 0x20)), // BSCHCTRL0.BEST_EFFORT_BANK_PREFETCH
E(BUNIT, 0x3B, MASK_VAL(23, 16, 0x4)), // BDEBUG0.CASUAL_TIMER
E(BUNIT, 0x3B, MASK_VAL(9, 9, 0x0)), // BDEBUG0.DISABLE_BADMIT_URGENT_ISOC
E(BUNIT, 0x3B, MASK_VAL(7, 0, 0x0A)), // BDEBUG0.CASUAL_WATER_MARK
E(BUNIT, 0x3C, MASK_VAL(31, 16, 0x0FFFF)), // BDEBUG1.AGENT_WEIGHT_ENABLE
E(BUNIT, 0x3C, MASK_VAL(2, 2, 0x0)), // BDEBUG1.EXIT_SR_FOR_CASUAL_FLUSH
E(BUNIT, 0x3C, MASK_VAL(1, 1, 0x0)), // BDEBUG1.ENABLE_DRAM_SELF_RFRSH
E(BUNIT, 0x3D, MASK_VAL(14, 14, 0x1)), // BCTRL.BANK_STATUS_ENABLE
E(BUNIT, 0x3D, MASK_VAL(13, 13, 0x0)), // BCTRL.DISABLE_OWNED
E(BUNIT, 0x3D, MASK_VAL(12, 12, 0x0)), // BCTRL.INORDER_READ_ENABLE
E(BUNIT, 0x3D, MASK_VAL(11, 11, 0x0)), // BCTRL.INORDER_FLUSH_ENABLE
E(BUNIT, 0x3D, MASK_VAL(8, 8, 0x0)), // BCTRL.MISS_VALID_ENTRIES
E(BUNIT, 0x3D, MASK_VAL(7, 7, 0x0)), // BCTRL.DIRTY_STALL
E(BUNIT, 0x3D, MASK_VAL(6, 6, 0x0)), // BCTRL.SINGLE_TAG_ACCESS
E(BUNIT, 0x3D, MASK_VAL(5, 5, 0x0)), // BCTRL.SINGLE_CHUNK_ACCESS
E(BUNIT, 0x3D, MASK_VAL(2, 2, 0x1)), // BCTRL.BECLK_GATE_EN
E(BUNIT, 0x3D, MASK_VAL(1, 1, 0x1)), // BCTRL.MASTERCLK_GATE_EN
E(BUNIT, 0x3D, MASK_VAL(0, 0, 0x1)), // BCTRL.REQUESTCLK_GATE_EN
E(BUNIT, 0x3E, MASK_VAL(31, 16, 0x0)), // BTHCTRL.AGENT_THROTTLING_ENABLE
E(BUNIT, 0x3E, MASK_VAL(7, 0, 0x0)), // BTHCTRL.RANK_SELECTION_MASK
E(BUNIT, 0x3F, MASK_VAL(31, 24, 0x0FF)), // BTHMASK.ORWRITE_MASK
E(BUNIT, 0x3F, MASK_VAL(23, 16, 0x0FF)), // BTHMASK.ORREAD_MASK
E(BUNIT, 0x3F, MASK_VAL(15, 8, 0x0FF)), // BTHMASK.ERWRITE_MASK
E(BUNIT, 0x3F, MASK_VAL(7, 0, 0x0FF)), // BTHMASK.ERREAD_MASK
//0x02, 0x0, 2, 0, 0x1, //T_INTR_REDIR_CTL.REDIR_MODE_SEL
E(CPU_BUS, 0x3, MASK_VAL(20, 20, 0x1)), // T_CTL.SPLIT_GOIWP_MODE
E(CPU_BUS, 0x3, MASK_VAL(19, 19, 0x0)), // T_CTL.DISABLE_TRDY_RDGO
E(CPU_BUS, 0x3, MASK_VAL(18, 18, 0x0)), // T_CTL.DISABLE_ISOC_HIGHPRI_RDDATA_RETURN
E(CPU_BUS, 0x3, MASK_VAL(17, 17, 0x0)), // T_CTL.ENABLE_NPC_COLLECTOR
E(CPU_BUS, 0x3, MASK_VAL(16, 16, 0x1)), // T_CTL.ENABLE_IN_ORDER_APIC
E(CPU_BUS, 0x3, MASK_VAL(15, 15, 0x0)), // T_CTL.TG_HIGHPRI_WRITE_PULLS
//0x02, 0x3, 12, 12, 0x1, // T_CTL.TG_NDRAMSNP
E(CPU_BUS, 0x3, MASK_VAL(10, 10, 0x1)), // T_CTL.TG_DW_POST_PUSH_LOG
E(CPU_BUS, 0x3, MASK_VAL(3, 3, 0x0)), // T_CTL.ALWAYS_SNP_IDI
E(CPU_BUS, 0x3, MASK_VAL(2, 2, 0x0)), // T_CTL.DIS_LIVE_BRAM_BYP_IDI
E(CPU_BUS, 0x4, MASK_VAL(18, 18, 0x1)), // T_MISC_CTL.DISABLE_IOSF_OUTBOUND_THROTTLE
E(CPU_BUS, 0x4, MASK_VAL(4, 1, 0x8)), // T_MISC_CTL.DPTE_CNT
E(CPU_BUS, 0x4, MASK_VAL(0, 0, 0x0)), // T_MISC_CTL.DPTE_EN
E(CPU_BUS, 0x5, MASK_VAL(27, 27, 0x1)), // T_CLKGATE_CTL.XUNIT_4_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(26, 26, 0x1)), // T_CLKGATE_CTL.XUNIT_3_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(25, 25, 0x1)), // T_CLKGATE_CTL.XUNIT_2_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(24, 24, 0x1)), // T_CLKGATE_CTL.XUNIT_1_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(23, 23, 0x1)), // T_CLKGATE_CTL.MON_LOG_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(22, 22, 0x1)), // T_CLKGATE_CTL.A2T_Q_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(21, 21, 0x1)), // T_CLKGATE_CTL.T2A_Q_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(20, 20, 0x1)), // T_CLKGATE_CTL.A2TAPIC_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(19, 19, 0x1)), // T_CLKGATE_CTL.B2X_DATSEL_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(18, 18, 0x1)), // T_CLKGATE_CTL.X2B_DATSEL_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(17, 17, 0x1)), // T_CLKGATE_CTL.S2C_RESP_SEL_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(16, 16, 0x1)), // T_CLKGATE_CTL.T2A_REQ_SEL_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(15, 15, 0x1)), // T_CLKGATE_CTL.C2APIC_FIFO_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(14, 14, 0x1)), // T_CLKGATE_CTL.S2C_REQ_FIFO_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(13, 13, 0x1)), // T_CLKGATE_CTL.S2C_REQ_SEL_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(12, 12, 0x1)), // T_CLKGATE_CTL.TRKR_SB_LLST_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(11, 11, 0x1)), // T_CLKGATE_CTL.TRKR_SB_OLDST_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(10, 10, 0x1)), // T_CLKGATE_CTL.TRKR_SB_S2C_RESP_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(9, 9, 0x1)), // T_CLKGATE_CTL.TRKR_SB_T2A_REQSTAT_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(8, 8, 0x1)), // T_CLKGATE_CTL.TRKR_SB_B2X_DATSTAT_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(7, 7, 0x1)), // T_CLKGATE_CTL.TRKR_SB_WRSTAT_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(6, 6, 0x1)), // T_CLKGATE_CTL.TRKR_SB_SNP_STAT_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(5, 5, 0x1)), // T_CLKGATE_CTL.TRKR_SB_REQ_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(4, 4, 0x1)), // T_CLKGATE_CTL.TRKR_SB_VIOL_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(3, 3, 0x1)), // T_CLKGATE_CTL.TRKR_SB_VALID_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(2, 2, 0x1)), // T_CLKGATE_CTL.TRKR_SB_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(1, 1, 0x1)), // T_CLKGATE_CTL.IOSF_SB_CFG_REG_CLK_GATE_EN
E(CPU_BUS, 0x5, MASK_VAL(0, 0, 0x1)), // T_CLKGATE_CTL.IOSF_SB_MSG_CLK_GATE_EN
E(0x58, 0x40, MASK_VAL(4, 4, 0x0)), // SSCR2.ACG_EN
E(0x58, 0x40, MASK_VAL(4, 4, 0x0)), // SSCR2.ACG_EN
E(0x58, 0x40, MASK_VAL(4, 4, 0x0)), // SSCR2.ACG_EN
E(0x55, 0x54, MASK_VAL(1, 0, 0x0)), // SMB_Config_PMCSR.PS
E(0x55, 0x0FC, MASK_VAL(17, 17, 0x0)), // SMB_Config_CGC.FUNC_CLK_CGD
E(0x55, 0x0FC, MASK_VAL(9, 9, 0x0)), // SMB_Config_CGC.SB_LOCAL_CGD
E(0xa2, 0x0C000, MASK_VAL(0, 0, 0x0)), // power_options.clkgate_disable
E(0x47, 0x0C000, MASK_VAL(0, 0, 0x0)), // power_options.clkgate_disable
E(0x45, 0x0C000, MASK_VAL(0, 0, 0x0)), // power_options.clkgate_disable
E(0x46, 0x0C000, MASK_VAL(0, 0, 0x0)), // power_options.clkgate_disable
E(PMC, 0x0, MASK_VAL(11, 11, 0x1)), // PUNIT_CONTROL.MODE_DEMOTE_EN
E(PMC, 0x0, MASK_VAL(10, 10, 0x1)), // PUNIT_CONTROL.CORE_DEMOTE_EN
//
//s0ix_PnP_Settings
//
E(0x58, 0x1e0, MASK_VAL(4, 4, 0x1)), //vlv.audio.lpe.bridge.pmctl.iosfprim_trunk_gate_en
E(0x58, 0x1e0, MASK_VAL(0, 0, 0x0)), //vlv.audio.lpe.bridge.pmctl.iosfprimclk_gate_en
E(0x58, 0x1e0, MASK_VAL(5, 5, 0x1)), //vlv.audio.lpe.bridge.pmctl.iosfsb_trunk_gate_en
E(0x58, 0x1e0, MASK_VAL(3, 3, 0x1)), //vlv.audio.lpe.bridge.pmctl.pmctl.iosfsbclk_gate_en
E(0x58, 0x1e0, MASK_VAL(1, 1, 0x1)), //vlv.audio.lpe.bridge.pmctl.ocpclk_gate_en
E(0x58, 0x1e0, MASK_VAL(2, 2, 0x1)), //vlv.audio.lpe.bridge.pmctl.ocpclk_trunk_gate_en
E(CCU, 0x28, MASK_VAL(31, 0, 0x0)), //vlv.ccu.ccu_trunk_clkgate
E(CCU, 0x38, MASK_VAL(31, 0, 0x0)), //vlv.ccu.ccu_trunk_clkgate_2
E(CCU, 0x1c, MASK_VAL(29, 28, 0x0)), //vlv.ccu.clkgate_en_1.cr_lpe_pri_clkgate_en
E(CCU, 0x1c, MASK_VAL(25, 24, 0x0)), //vlv.ccu.clkgate_en_1.cr_lpe_sb_clkgate_en
E(CCU, 0x1c, MASK_VAL( 1, 0, 0x0)), //vlv.ccu.clkgate_en_1.lps_free_clkgate_en
E(CCU, 0x54, MASK_VAL(17, 16, 0x0)), //vlv.ccu.clkgate_en_3.cr_lpe_func_ip_clkgate_en
E(CCU, 0x54, MASK_VAL(13, 12, 0x0)), //vlv.ccu.clkgate_en_3.cr_lpe_osc_ip_clk_en
E(CCU, 0x54, MASK_VAL(15, 14, 0x0)), //vlv.ccu.clkgate_en_3.cr_lpe_xtal_ip_clkgate_en
E(CCU, 0x54, MASK_VAL(26, 24, 0x0)), //vlv.ccu.clkgate_en_3.psf_pri_clkgate_en
E(CCU, 0x24, MASK_VAL(24, 20, 0x0)), //vlv.ccu.iclk_clkgate_ctrl.iopcibuffen_force_on
E(0x59, 0x1e0, MASK_VAL(4, 4, 0x1)), //vlv.usb.xdci_otg.controller.pmctl.iosfprim_trunk_gate_en
E(0x59, 0x1e0, MASK_VAL(0, 0, 0x1)), //vlv.usb.xdci_otg.controller.pmctl.iosfprimclk_gate_en
E(0x59, 0x1e0, MASK_VAL(5, 5, 0x1)), //vlv.usb.xdci_otg.controller.pmctl.iosfsb_trunk_gate_en
E(0x59, 0x1e0, MASK_VAL(3, 3, 0x1)), //vlv.usb.xdci_otg.controller.pmctl.iosfsbclk_gate_en
E(0x59, 0x1e0, MASK_VAL(1, 1, 0x1)), //vlv.usb.xdci_otg.controller.pmctl.ocpclk_gate_en
E(0x59, 0x1e0, MASK_VAL(2, 2, 0x1)), //vlv.usb.xdci_otg.controller.pmctl.ocpclk_trunk_gate_en
E(0x5a, 0xd0, MASK_VAL(8, 0, 0x3f)), //vlv.usb.xhci.controller.usb2pr.usb2hcsel
E(0x5a, 0x40, MASK_VAL(21, 19, 0x6)), //vlv.usb.xhci.controller.xhcc1.iil1e
E(0x5a, 0x40, MASK_VAL(10, 8, 0x1)), //vlv.usb.xhci.controller.xhcc1.l23hrawc
E(0x5a, 0x40, MASK_VAL(18, 18, 0x1)), //vlv.usb.xhci.controller.xhcc1.xhcil1e
E(0x5a, 0x50, MASK_VAL(3, 3, 0x1)), //vlv.usb.xhci.controller.xhclkgten.hsltcge
E(0x5a, 0x50, MASK_VAL(0, 0, 0x1)), //vlv.usb.xhci.controller.xhclkgten.iosfblcge
E(0x5a, 0x50, MASK_VAL(1, 1, 0x1)), //vlv.usb.xhci.controller.xhclkgten.iosfbtcge
E(0x5a, 0x50, MASK_VAL(2, 2, 0x1)), //vlv.usb.xhci.controller.xhclkgten.ssltcge
E(0x5a, 0x50, MASK_VAL(7, 5, 0x2)), //vlv.usb.xhci.controller.xhclkgten.sspllsue
E(0x5a, 0x50, MASK_VAL(13, 13, 0x1)), //vlv.usb.xhci.controller.xhclkgten.xhcbbtcgipiso
E(0x5a, 0x50, MASK_VAL(4, 4, 0x1)), //vlv.usb.xhci.controller.xhclkgten.xhcblcge
E(0x5a, 0x50, MASK_VAL(14, 14, 0x1)), //vlv.usb.xhci.controller.xhclkgten.xhcftclkse
E(0x5a, 0x50, MASK_VAL(12, 12, 0x0)), //vlv.usb.xhci.controller.xhclkgten.xhchstcgu2nrwe
E(0x5a, 0x50, MASK_VAL(11, 10, 0x3)), //vlv.usb.xhci.controller.xhclkgten.xhcusb2pllsdle
E(SCORE, 0x4900, MASK_VAL(16, 16, 0x1)), //vlv.gpio.gpscore.cfio_regs_com_cfg_score_pb_config.sb_clkgaten
E(SSUS, 0x4900, MASK_VAL(16, 16, 0x1)), //vlv.gpio.gpssus.cfio_regs_com_cfg_ssus_pb_config.sb_clkgaten
E(LPSS, 0x180, MASK_VAL(1, 1, 0x1)), //vlv.lpss.iosf2ahb.pmctl.ahb_clk_gate_en
E(LPSS, 0x180, MASK_VAL(4, 4, 0x1)), //vlv.lpss.iosf2ahb.pmctl.ahb_trunk_gate_enable
E(LPSS, 0x180, MASK_VAL(0, 0, 0x1)), //vlv.lpss.iosf2ahb.pmctl.iosf_clk_gate_enable
E(LPSS, 0x180, MASK_VAL(3, 3, 0x1)), //vlv.lpss.iosf2ahb.pmctl.iosfprim_trunk_gate_enable
E(LPSS, 0x180, MASK_VAL(5, 5, 0x1)), //vlv.lpss.iosf2ahb.pmctl.iosfsb_trunk_gate_enable
E(LPSS, 0x180, MASK_VAL(2, 2, 0x1)), //vlv.lpss.iosf2ahb.pmctl.side_clk_gate_enable
//0x54, 0xfc, 31, 0, 0x0, //vlv.pcu.iosfahbep.clock_gating_control
//0x55, 0xfc, 1, 1, 0x0, //vlv.pcu.smbus.smb_config_cgc.pri_local_cgd
//0x55, 0xfc, 0, 0, 0x0, //vlv.pcu.smbus.smb_config_cgc.pri_trunk_cgd
//0x55, 0xfc, 8, 8, 0x0, //vlv.pcu.smbus.smb_config_cgc.sb_trunk_cgd
E(SCC, 0x600, MASK_VAL(31, 15, 0x5)), //vlv.scc.iosf2ocp.gen_regrw1.gen_reg_rw1
E(SCC, 0x1e0, MASK_VAL(4, 4, 0x1)), //vlv.scc.iosf2ocp.pmctl.iosfprim_trunk_gate_en
E(SCC, 0x1e0, MASK_VAL(0, 0, 0x1)), //vlv.scc.iosf2ocp.pmctl.iosfprimclk_gate_en
E(SCC, 0x1e0, MASK_VAL(5, 5, 0x1)), //vlv.scc.iosf2ocp.pmctl.iosfsb_trunk_gate_en
E(SCC, 0x1e0, MASK_VAL(3, 3, 0x1)), //vlv.scc.iosf2ocp.pmctl.iosfsbclk_gate_en
E(SCC, 0x1e0, MASK_VAL(1, 1, 0x1)), //vlv.scc.iosf2ocp.pmctl.ocpclk_gate_en
E(SCC, 0x1e0, MASK_VAL(2, 2, 0x1)), //vlv.scc.iosf2ocp.pmctl.ocpclk_trunk_gate_en
E(SEC, 0x88, MASK_VAL(7, 7, 0x0)), //vlv.sec.clk_gate_dis.nfc_cg_dis
E(SEC, 0x88, MASK_VAL(1, 1, 0x0)), //vlv.sec.clk_gate_dis.prim_cg_dis
E(SEC, 0x88, MASK_VAL(2, 2, 0x0)), //vlv.sec.clk_gate_dis.prim_clkreq_dis
E(SEC, 0x88, MASK_VAL(3, 3, 0x0)), //vlv.sec.clk_gate_dis.prim_xsm_clkreq_dis
E(SEC, 0x88, MASK_VAL(4, 4, 0x0)), //vlv.sec.clk_gate_dis.sap_cg_dis
E(SEC, 0x88, MASK_VAL(6, 6, 0x0)), //vlv.sec.clk_gate_dis.sap_clkidle_dis
E(SEC, 0x88, MASK_VAL(5, 5, 0x0)), //vlv.sec.clk_gate_dis.sap_ip_cg_dis
E(SEC, 0x88, MASK_VAL(0, 0, 0x0)), //vlv.sec.clk_gate_dis.sb_cg_dis
REG_SCRIPT_END,
};
static void perf_power(void *unused)
{
printk(BIOS_DEBUG, "Applying perf/power settings.\n");
reg_script_run(perf_power_settings);
}
BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, perf_power, NULL);
BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, perf_power, NULL);

View File

@ -0,0 +1,11 @@
#include <arch/acpi.h>
#include <cpu/cpu.h>
#include <device/pci_rom.h>
#include <soc/acpi.h>
void smm_init(void) {}
/* Rmodules don't like weak symbols. */
u32 map_oprom_vendev(u32 vendev) { return vendev; }

View File

@ -0,0 +1,364 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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/io.h>
#include <console/console.h>
#include <soc/iomap.h>
#include <soc/lpc.h>
#include <soc/pci_devs.h>
#include <soc/pmc.h>
#if defined(__SMM__)
static const device_t pcu_dev = PCI_DEV(0, PCU_DEV, 0);
static inline device_t get_pcu_dev(void)
{
return pcu_dev;
}
#else /* !__SMM__ */
#include <device/device.h>
#include <device/pci.h>
static device_t pcu_dev;
static device_t get_pcu_dev(void)
{
if (pcu_dev == NULL)
pcu_dev = dev_find_slot(0, PCI_DEVFN(PCU_DEV, 0));
return pcu_dev;
}
#endif
uint16_t get_pmbase(void)
{
return pci_read_config16(get_pcu_dev(), ABASE) & 0xfff8;
}
static void print_num_status_bits(int num_bits, uint32_t status,
const char *bit_names[])
{
int i;
if (!status)
return;
for (i = num_bits - 1; 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);
}
}
}
static void print_status_bits(uint32_t status, const char *bit_names[])
{
print_num_status_bits(32, status, bit_names);
}
static uint32_t print_smi_status(uint32_t smi_sts)
{
static const char *smi_sts_bits[] = {
[2] = "BIOS",
[4] = "SLP_SMI",
[5] = "APM",
[6] = "SWSMI_TMR",
[8] = "PM1",
[9] = "GPE0",
[12] = "DEVMON",
[13] = "TCO",
[14] = "PERIODIC",
[15] = "ILB",
[16] = "SMBUS_SMI",
[17] = "LEGACY_USB2",
[18] = "INTEL_USB2",
[20] = "PCI_EXP_SMI",
[26] = "SPI",
[28] = "PUNIT",
[29] = "GUNIT",
};
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;
}
static uint32_t reset_smi_status(void)
{
uint16_t pmbase = get_pmbase();
uint32_t smi_sts = inl(pmbase + SMI_STS);
outl(smi_sts, pmbase + SMI_STS);
return smi_sts;
}
uint32_t clear_smi_status(void)
{
return print_smi_status(reset_smi_status());
}
void enable_smi(uint32_t mask)
{
uint16_t pmbase = get_pmbase();
uint32_t smi_en = inl(pmbase + SMI_EN);
smi_en |= mask;
outl(smi_en, pmbase + SMI_EN);
}
void disable_smi(uint32_t mask)
{
uint16_t pmbase = get_pmbase();
uint32_t smi_en = inl(pmbase + SMI_EN);
smi_en &= ~mask;
outl(smi_en, pmbase + SMI_EN);
}
void enable_pm1_control(uint32_t mask)
{
uint16_t pmbase = get_pmbase();
uint32_t pm1_cnt = inl(pmbase + PM1_CNT);
pm1_cnt |= mask;
outl(pm1_cnt, pmbase + PM1_CNT);
}
void disable_pm1_control(uint32_t mask)
{
uint16_t pmbase = get_pmbase();
uint32_t pm1_cnt = inl(pmbase + PM1_CNT);
pm1_cnt &= ~mask;
outl(pm1_cnt, pmbase + PM1_CNT);
}
static uint16_t reset_pm1_status(void)
{
uint16_t pmbase = get_pmbase();
uint16_t pm1_sts = inw(pmbase + PM1_STS);
outw(pm1_sts, pmbase + PM1_STS);
return pm1_sts;
}
static uint16_t print_pm1_status(uint16_t pm1_sts)
{
static const char *pm1_sts_bits[] = {
[0] = "TMROF",
[5] = "GBL",
[8] = "PWRBTN",
[10] = "RTC",
[11] = "PRBTNOR",
[13] = "USB",
[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;
}
uint16_t clear_pm1_status(void)
{
return print_pm1_status(reset_pm1_status());
}
void enable_pm1(uint16_t events)
{
outw(events, get_pmbase() + PM1_EN);
}
static uint32_t print_tco_status(uint32_t tco_sts)
{
static const char *tco_sts_bits[] = {
[3] = "TIMEOUT",
[17] = "SECOND_TO",
};
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;
}
static uint32_t reset_tco_status(void)
{
uint16_t pmbase = get_pmbase();
uint32_t tco_sts = inl(pmbase + TCO_STS);
uint32_t tco_en = inl(pmbase + TCO1_CNT);
outl(tco_sts, pmbase + TCO_STS);
return tco_sts & tco_en;
}
uint32_t clear_tco_status(void)
{
return print_tco_status(reset_tco_status());
}
void enable_gpe(uint32_t mask)
{
uint16_t pmbase = get_pmbase();
uint32_t gpe0_en = inl(pmbase + GPE0_EN);
gpe0_en |= mask;
outl(gpe0_en, pmbase + GPE0_EN);
}
void disable_gpe(uint32_t mask)
{
uint16_t pmbase = get_pmbase();
uint32_t gpe0_en = inl(pmbase + GPE0_EN);
gpe0_en &= ~mask;
outl(gpe0_en, pmbase + GPE0_EN);
}
void disable_all_gpe(void)
{
disable_gpe(~0);
}
static uint32_t reset_gpe_status(void)
{
uint16_t pmbase = get_pmbase();
uint32_t gpe_sts = inl(pmbase + GPE0_STS);
outl(gpe_sts, pmbase + GPE0_STS);
return gpe_sts;
}
static uint32_t print_gpe_sts(uint32_t gpe_sts)
{
static const char *gpe_sts_bits[] = {
[1] = "HOTPLUG",
[2] = "SWGPE",
[3] = "PCIE_WAKE0",
[4] = "PUNIT",
[5] = "GUNIT",
[6] = "PCIE_WAKE1",
[7] = "PCIE_WAKE2",
[8] = "PCIE_WAKE3",
[9] = "PCI_EXP",
[10] = "BATLOW",
[13] = "PME_B0",
[16] = "SUS_GPIO_0",
[17] = "SUS_GPIO_1",
[18] = "SUS_GPIO_2",
[19] = "SUS_GPIO_3",
[20] = "SUS_GPIO_4",
[21] = "SUS_GPIO_5",
[22] = "SUS_GPIO_6",
[23] = "SUS_GPIO_7",
[24] = "CORE_GPIO_0",
[25] = "CORE_GPIO_1",
[26] = "CORE_GPIO_2",
[27] = "CORE_GPIO_3",
[28] = "CORE_GPIO_4",
[29] = "CORE_GPIO_5",
[30] = "CORE_GPIO_6",
[31] = "CORE_GPIO_7",
};
if (!gpe_sts)
return gpe_sts;
printk(BIOS_DEBUG, "GPE0a_STS: ");
print_status_bits(gpe_sts, gpe_sts_bits);
printk(BIOS_DEBUG, "\n");
return gpe_sts;
}
uint32_t clear_gpe_status(void)
{
return print_gpe_sts(reset_gpe_status());
}
static uint32_t reset_alt_status(void)
{
uint16_t pmbase = get_pmbase();
uint32_t alt_gpio_smi = inl(pmbase + ALT_GPIO_SMI);
outl(alt_gpio_smi, pmbase + ALT_GPIO_SMI);
return alt_gpio_smi;
}
static uint32_t print_alt_sts(uint32_t alt_gpio_smi)
{
uint32_t alt_gpio_sts;
static const char *alt_gpio_smi_sts_bits[] = {
[0] = "SUS_GPIO_0",
[1] = "SUS_GPIO_1",
[2] = "SUS_GPIO_2",
[3] = "SUS_GPIO_3",
[4] = "SUS_GPIO_4",
[5] = "SUS_GPIO_5",
[6] = "SUS_GPIO_6",
[7] = "SUS_GPIO_7",
[8] = "CORE_GPIO_0",
[9] = "CORE_GPIO_1",
[10] = "CORE_GPIO_2",
[11] = "CORE_GPIO_3",
[12] = "CORE_GPIO_4",
[13] = "CORE_GPIO_5",
[14] = "CORE_GPIO_6",
[15] = "CORE_GPIO_7",
};
/* Status bits are in the upper 16 bits. */
alt_gpio_sts = alt_gpio_smi >> 16;
if (!alt_gpio_sts)
return alt_gpio_smi;
printk(BIOS_DEBUG, "ALT_GPIO_SMI: ");
print_num_status_bits(16, alt_gpio_sts, alt_gpio_smi_sts_bits);
printk(BIOS_DEBUG, "\n");
return alt_gpio_smi;
}
uint32_t clear_alt_status(void)
{
return print_alt_sts(reset_alt_status());
}
void clear_pmc_status(void)
{
uint32_t prsts;
uint32_t gen_pmcon1;
prsts = read32((u32 *)(PMC_BASE_ADDRESS + PRSTS));
gen_pmcon1 = read32((u32 *)(PMC_BASE_ADDRESS + GEN_PMCON1));
/* Clear the status bits. The RPS field is cleared on a 0 write. */
write32((u32 *)(PMC_BASE_ADDRESS + GEN_PMCON1), gen_pmcon1 & ~RPS);
write32((u32 *)(PMC_BASE_ADDRESS + PRSTS), prsts);
}

View File

@ -0,0 +1,206 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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/acpi.h>
#include <cbmem.h>
#include <console/console.h>
#include <cpu/intel/microcode.h>
#include <cpu/x86/cr.h>
#include <cpu/x86/msr.h>
#include <device/device.h>
#include <device/pci_def.h>
#include <device/pci_ops.h>
#include <stdlib.h>
#include <string.h>
#include <soc/gpio.h>
#include <soc/lpc.h>
#include <soc/msr.h>
#include <soc/nvs.h>
#include <soc/pattrs.h>
#include <soc/pci_devs.h>
#include <soc/pmc.h>
#include <soc/ramstage.h>
#include <soc/iosf.h>
/* Global PATTRS */
DEFINE_PATTRS;
#define SHOW_PATTRS 1
static void detect_num_cpus(struct pattrs *attrs)
{
int ecx = 0;
while (1) {
struct cpuid_result leaf_b;
leaf_b = cpuid_ext(0xb, ecx);
/* Bay Trail doesn't have hyperthreading so just determine the
* number of cores by from level type (ecx[15:8] == * 2). */
if ((leaf_b.ecx & 0xff00) == 0x0200) {
attrs->num_cpus = leaf_b.ebx & 0xffff;
break;
}
ecx++;
}
}
static inline void fill_in_msr(msr_t *msr, int idx)
{
*msr = rdmsr(idx);
if (SHOW_PATTRS) {
printk(BIOS_DEBUG, "msr(%x) = %08x%08x\n",
idx, msr->hi, msr->lo);
}
}
static const char *stepping_str[] = {
"A0", "A1", "B0", "B1", "B2", "B3", "C0"
};
static void fill_in_pattrs(void)
{
device_t dev;
msr_t msr;
struct pattrs *attrs = (struct pattrs *)pattrs_get();
attrs->cpuid = cpuid_eax(1);
dev = dev_find_slot(0, PCI_DEVFN(LPC_DEV, LPC_FUNC));
attrs->revid = pci_read_config8(dev, REVID);
/* The revision to stepping IDs have two values per metal stepping. */
if (attrs->revid >= RID_C_STEPPING_START) {
attrs->stepping = (attrs->revid - RID_C_STEPPING_START) / 2;
attrs->stepping += STEP_C0;
} else if (attrs->revid >= RID_B_STEPPING_START) {
attrs->stepping = (attrs->revid - RID_B_STEPPING_START) / 2;
attrs->stepping += STEP_B0;
} else {
attrs->stepping = (attrs->revid - RID_A_STEPPING_START) / 2;
attrs->stepping += STEP_A0;
}
attrs->microcode_patch = intel_microcode_find();
attrs->address_bits = cpuid_eax(0x80000008) & 0xff;
detect_num_cpus(attrs);
if (SHOW_PATTRS) {
printk(BIOS_DEBUG, "BYT: cpuid %08x cpus %d rid %02x step %s\n",
attrs->cpuid, attrs->num_cpus, attrs->revid,
(attrs->stepping >= ARRAY_SIZE(stepping_str)) ? "??" :
stepping_str[attrs->stepping]);
}
fill_in_msr(&attrs->platform_id, MSR_IA32_PLATFORM_ID);
fill_in_msr(&attrs->platform_info, MSR_PLATFORM_INFO);
/* Set IA core speed ratio and voltages */
msr = rdmsr(MSR_IACORE_RATIOS);
attrs->iacore_ratios[IACORE_MIN] = msr.lo & 0x7f;
attrs->iacore_ratios[IACORE_LFM] = (msr.lo >> 8) & 0x7f;
attrs->iacore_ratios[IACORE_MAX] = (msr.lo >> 16) & 0x7f;
msr = rdmsr(MSR_IACORE_TURBO_RATIOS);
attrs->iacore_ratios[IACORE_TURBO] = (msr.lo & 0xff); /* 1 core max */
msr = rdmsr(MSR_IACORE_VIDS);
attrs->iacore_vids[IACORE_MIN] = msr.lo & 0x7f;
attrs->iacore_vids[IACORE_LFM] = (msr.lo >> 8) & 0x7f;
attrs->iacore_vids[IACORE_MAX] = (msr.lo >> 16) & 0x7f;
msr = rdmsr(MSR_IACORE_TURBO_VIDS);
attrs->iacore_vids[IACORE_TURBO] = (msr.lo & 0xff); /* 1 core max */
/* Set bus clock speed */
attrs->bclk_khz = bus_freq_khz();
}
/* Save bit index for first enabled event in PM1_STS for \_SB._SWS */
static void s3_save_acpi_wake_source(global_nvs_t *gnvs)
{
struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE);
uint16_t pm1;
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;
printk(BIOS_DEBUG, "ACPI System Wake Source is PM1 Index %d\n",
gnvs->pm1i);
}
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
s3_save_acpi_wake_source(gnvs);
}
static void baytrail_enable_2x_refresh_rate(void)
{
u32 reg;
reg = iosf_dunit_read(0x8);
reg = reg & ~0x7000;
reg = reg | 0x2000;
iosf_dunit_write(0x8, reg);
}
void baytrail_init_pre_device(struct soc_intel_baytrail_config *config)
{
struct soc_gpio_config *gpio_config;
fill_in_pattrs();
if (!config->disable_ddr_2x_refresh_rate)
baytrail_enable_2x_refresh_rate();
/* Allow for SSE instructions to be executed. */
write_cr4(read_cr4() | CR4_OSFXSR | CR4_OSXMMEXCPT);
/* Indicate S3 resume to rest of ramstage. */
s3_resume_prepare();
/* Run reference code. */
baytrail_run_reference_code();
/* Get GPIO initial states from mainboard */
gpio_config = mainboard_get_gpios();
setup_soc_gpios(gpio_config, config->enable_xdp_tap);
baytrail_init_scc();
}

View File

@ -0,0 +1,148 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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>
#if IS_ENABLED(CONFIG_CHROMEOS)
#include <vendorcode/google/chromeos/vboot_handoff.h>
#endif
#include <soc/ramstage.h>
#include <soc/efi_wrapper.h>
static void ABI_X86 send_to_console(unsigned char b)
{
console_tx_byte(b);
}
static efi_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 (efi_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 efi_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 baytrail_run_reference_code(void)
{
int ret;
efi_wrapper_entry_t entry;
struct efi_wrapper_params wrp = {
.version = EFI_WRAPPER_VER,
.console_out = send_to_console,
};
entry = load_reference_code();
if (entry == NULL)
return;
wrp.tsc_ticks_per_microsecond = tsc_freq_mhz();
/* Call into reference code. */
ret = entry(&wrp);
if (ret != 0) {
printk(BIOS_DEBUG, "Reference code returned %d\n", ret);
return;
}
}

View File

@ -0,0 +1,47 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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/pmc.h>
#include <soc/reset.h>
void cold_reset(void)
{
/* S0->S5->S0 trip. */
outb(RST_CPU | SYS_RST | FULL_RST, RST_CNT);
}
void warm_reset(void)
{
/* PMC_PLTRST# asserted. */
outb(RST_CPU | SYS_RST, RST_CNT);
}
void soft_reset(void)
{
/* Sends INIT# to CPU */
outb(RST_CPU, RST_CNT);
}
void hard_reset(void)
{
/* Don't power cycle on hard_reset(). It's not really clear what the
* semantics should be for the meaning of hard_reset(). */
warm_reset();
}

View File

@ -0,0 +1,7 @@
cpu_incs += $(src)/soc/intel/baytrail/romstage/cache_as_ram.inc
romstage-y += romstage.c
romstage-y += raminit.c
romstage-$(CONFIG_ENABLE_BUILTIN_COM1) += uart.c
romstage-y += gfx.c
romstage-y += pmc.c
romstage-y += early_spi.c

View File

@ -0,0 +1,285 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com>
* Copyright (C) 2007-2008 coresystems GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#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
/* Cache all of CBFS just below 4GiB as Write-Protect type. */
#define CODE_CACHE_SIZE (CONFIG_CBFS_SIZE)
#define CODE_CACHE_BASE (-CODE_CACHE_SIZE)
#define CODE_CACHE_MASK (~(CODE_CACHE_SIZE - 1))
#define CPU_PHYSMASK_HI ((1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1)
#define NoEvictMod_MSR 0x2e0
#define BBL_CR_CTL3_MSR 0x11e
#define MCG_CAP_MSR 0x179
/* 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)
/* Configure the default memory type to uncacheable as well as disable
* fixed and variable range mtrrs. */
movl $MTRRdefType_MSR, %ecx
rdmsr
andl $(~0x00000cff), %eax
wrmsr
post_code(0x22)
/* Zero the variable MTRRs. */
movl $MCG_CAP_MSR, %ecx
rdmsr
movzx %al, %ebx
/* First variable MTRR. */
movl $0x200, %ecx
xorl %eax, %eax
xorl %edx, %edx
1:
wrmsr
inc %ecx
dec %ebx
jnz 1b
/* Zero out all fixed range and variable range MTRRs. */
movl $fixed_mtrr_table, %esi
movl $((fixed_mtrr_table_end - fixed_mtrr_table) / 2), %edi
xorl %eax, %eax
xorl %edx, %edx
1:
movw (%esi), %bx
movzx %bx, %ecx
wrmsr
add $2, %esi
dec %edi
jnz 1b
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)
/* Set code caching up for romstage. */
movl $(MTRRphysBase_MSR(1)), %ecx
movl $(CODE_CACHE_BASE | MTRR_TYPE_WRPROT), %eax
xorl %edx, %edx
wrmsr
movl $(MTRRphysMask_MSR(1)), %ecx
movl $(CODE_CACHE_MASK | MTRRphysMaskValid), %eax
movl $CPU_PHYSMASK_HI, %edx
wrmsr
/* Enable MTRR. */
movl $MTRRdefType_MSR, %ecx
rdmsr
orl $MTRRdefTypeEn, %eax
wrmsr
post_code(0x26)
/* Enable the L2 cache. */
movl $BBL_CR_CTL3_MSR, %ecx
rdmsr
orl $0x100, %eax
wrmsr
post_code(0x27)
/* 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
wrmsr
post_code(0x28)
/* 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 no evict mode */
movl $NoEvictMod_MSR, %ecx
rdmsr
orl $2, %eax
wrmsr
post_code(0x29)
/* Setup the stack. */
movl $(CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE), %eax
movl %eax, %esp
/* Push the initial TSC value from boot block. The low 32 bits are
* in mm0, and the high 32 bits are in mm1. */
movd %mm1, %eax
pushl %eax
movd %mm0, %eax
pushl %eax
/* Restore the BIST result. */
movl %ebp, %eax
movl %esp, %ebp
pushl %eax
before_romstage:
post_code(0x2a)
/* 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(0x2b)
/* Disable cache. */
movl %cr0, %eax
orl $CR0_CacheDisable, %eax
movl %eax, %cr0
post_code(0x2c)
/* Disable MTRR. */
movl $MTRRdefType_MSR, %ecx
rdmsr
andl $(~MTRRdefTypeEn), %eax
wrmsr
invd
post_code(0x2d)
/* Disable the no eviction run state */
movl $NoEvictMod_MSR, %ecx
rdmsr
andl $~2, %eax
wrmsr
/* Disable the no eviction mode */
rdmsr
andl $~1, %eax
wrmsr
post_code(0x2e)
/* 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(0x2f)
/* And enable cache again after setting MTRRs. */
movl %cr0, %eax
andl $~(CR0_CacheDisable | CR0_NoWriteThrough), %eax
movl %eax, %cr0
post_code(0x30)
/* Enable MTRR. */
movl $MTRRdefType_MSR, %ecx
rdmsr
orl $MTRRdefTypeEn, %eax
wrmsr
post_code(0x31)
__main:
post_code(POST_PREPARE_RAMSTAGE)
cld /* Clear direction flag. */
call romstage_after_car
.Lhlt:
post_code(POST_DEAD_CODE)
hlt
jmp .Lhlt
/* Fixed MTRRs */
fixed_mtrr_table:
.word 0x250, 0x258, 0x259
.word 0x268, 0x269, 0x26A
.word 0x26B, 0x26C, 0x26D
.word 0x26E, 0x26F
fixed_mtrr_table_end:

View File

@ -0,0 +1,65 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc. All rights reserved.
*
* 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 <delay.h>
#include <console/console.h>
#include <soc/iomap.h>
#include <soc/romstage.h>
#include <soc/spi.h>
#define SPI_CYCLE_DELAY 10 /* 10us */
#define SPI_CYCLE_TIMEOUT 400000 / SPI_CYCLE_DELAY /* 400ms */
#define SPI8(x) *((volatile u8 *)(SPI_BASE_ADDRESS + x))
#define SPI16(x) *((volatile u16 *)(SPI_BASE_ADDRESS + x))
#define SPI32(x) *((volatile u32 *)(SPI_BASE_ADDRESS + x))
/* 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 timeout = SPI_CYCLE_TIMEOUT;
/* No address associated with rdsr */
SPI8(OPTYPE) = 0x0;
/* Setup opcode[0] = read wpsr */
SPI8(OPMENU0) = 0x5;
/* Start transaction */
SPI16(SSFC) = DATA_CYCLE | SPI_CYCLE_GO;
/* Wait for error / complete status */
while(timeout--) {
u16 status = SPI16(SSFS);
if (status & FLASH_CYCLE_ERROR) {
printk(BIOS_ERR, "SPI rdsr failed\n");
return -1;
} else if (status & CYCLE_DONE_STATUS)
break;
udelay(SPI_CYCLE_DELAY);
}
*sr = SPI32(FDATA0) & 0xff;
return 0;
}

View File

@ -0,0 +1,50 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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/gfx.h>
#include <soc/pci_devs.h>
#include <soc/romstage.h>
void gfx_init(void)
{
uint32_t ggc;
uint8_t msac;
const unsigned int gfx_dev = PCI_DEV(0, GFX_DEV, GFX_FUNC);
/* The GFX device needs to set the aperture, gtt stolen size, and
* graphics stolen memory stolen size before running MRC. For now
* just hard code the defaults. Options can be added to the device
* tree if needed. */
ggc = pci_read_config32(gfx_dev, GGC);
msac = pci_read_config8(gfx_dev, MSAC);
ggc &= ~(GGC_GTT_SIZE_MASK | GGC_GSM_SIZE_MASK);
/* 32MB GSM is not supported with <C0 stepping. */
ggc |= GGC_GTT_SIZE_2MB | GGC_GSM_SIZE_64MB;
/* Enable VGA decoding as well. */
ggc &= ~(GGC_VGA_DISABLE);
msac &= ~(APERTURE_SIZE_MASK);
msac |= APERTURE_SIZE_256MB;
pci_write_config32(gfx_dev, GGC, ggc);
pci_write_config8(gfx_dev, MSAC, msac);
}

View File

@ -0,0 +1,81 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 <arch/io.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci_def.h>
#include <soc/iomap.h>
#include <soc/iosf.h>
#include <soc/lpc.h>
#include <soc/pci_devs.h>
#include <soc/pmc.h>
#include <soc/romstage.h>
#include "../chip.h"
void tco_disable(void)
{
uint32_t reg;
reg = inl(ACPI_BASE_ADDRESS + TCO1_CNT);
reg |= TCO_TMR_HALT;
outl(reg, ACPI_BASE_ADDRESS + TCO1_CNT);
}
/* This sequence signals the PUNIT to start running. */
void punit_init(void)
{
uint32_t reg;
uint8_t rid;
const struct device *dev;
const struct soc_intel_baytrail_config *cfg = NULL;
rid = pci_read_config8(IOSF_PCI_DEV, REVID);
dev = dev_find_slot(0, PCI_DEVFN(SOC_DEV, SOC_FUNC));
if (dev)
cfg = dev->chip_info;
reg = iosf_punit_read(SB_BIOS_CONFIG);
/* Write bits 17:16 of SB_BIOS_CONFIG in the PUNIT. */
reg |= SB_BIOS_CONFIG_PERF_MODE | SB_BIOS_CONFIG_PDM_MODE;
/* Configure VR low power mode for C0 and above. */
if (rid >= RID_C_STEPPING_START && cfg != NULL &&
(cfg->vnn_ps2_enable || cfg->vcc_ps2_enable)) {
printk(BIOS_DEBUG, "Enabling VR PS2 mode: ");
if (cfg->vnn_ps2_enable) {
reg |= SB_BIOS_CONFIG_PS2_EN_VNN;
printk(BIOS_DEBUG, "VNN ");
}
if (cfg->vcc_ps2_enable) {
reg |= SB_BIOS_CONFIG_PS2_EN_VCC;
printk(BIOS_DEBUG, "VCC ");
}
printk(BIOS_DEBUG, "\n");
}
iosf_punit_write(SB_BIOS_CONFIG, reg);
/* Write bits 1:0 of BIOS_RESET_CPL in the PUNIT. */
reg = BIOS_RESET_CPL_ALL_DONE | BIOS_RESET_CPL_RESET_DONE;
pci_write_config32(IOSF_PCI_DEV, MDR_REG, reg);
reg = IOSF_OPCODE(IOSF_OP_WRITE_PMC) | IOSF_PORT(IOSF_PORT_PMC) |
IOSF_REG(BIOS_RESET_CPL) | IOSF_BYTE_EN_0;
pci_write_config32(IOSF_PCI_DEV, MCR_REG, reg);
}

View File

@ -0,0 +1,191 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 <arch/io.h>
#include <bootmode.h>
#include <cbfs.h>
#include <cbmem.h>
#include <console/console.h>
#include <device/pci_def.h>
#include <halt.h>
#include <stage_cache.h>
#include <soc/gpio.h>
#include <soc/intel/common/mrc_cache.h>
#include <soc/iomap.h>
#include <soc/iosf.h>
#include <soc/pci_devs.h>
#include <soc/reset.h>
#include <soc/romstage.h>
#include <ec/google/chromeec/ec.h>
#include <ec/google/chromeec/ec_commands.h>
static void reset_system(void)
{
warm_reset();
halt();
}
static void enable_smbus(void)
{
uint32_t reg;
const uint32_t smbus_dev = PCI_DEV(0, SMBUS_DEV, SMBUS_FUNC);
/* SMBus I/O BAR */
reg = SMBUS_BASE_ADDRESS | 2;
pci_write_config32(smbus_dev, PCI_BASE_ADDRESS_4, reg);
/* Enable decode of I/O space. */
reg = pci_read_config16(smbus_dev, PCI_COMMAND);
reg |= 0x1;
pci_write_config16(smbus_dev, PCI_COMMAND, reg);
/* Enable Host Controller */
reg = pci_read_config8(smbus_dev, 0x40);
reg |= 1;
pci_write_config8(smbus_dev, 0x40, reg);
/* Configure pads to be used for SMBus */
score_select_func(PCU_SMB_CLK_PAD, 1);
score_select_func(PCU_SMB_DATA_PAD, 1);
}
static void ABI_X86 send_to_console(unsigned char b)
{
do_putchar(b);
}
static void print_dram_info(void)
{
const int mrc_ver_reg = 0xf0;
const uint32_t soc_dev = PCI_DEV(0, SOC_DEV, SOC_FUNC);
uint32_t reg;
int num_channels;
int speed;
uint32_t ch0;
uint32_t ch1;
reg = pci_read_config32(soc_dev, mrc_ver_reg);
printk(BIOS_INFO, "MRC v%d.%02d\n", (reg >> 8) & 0xff, reg & 0xff);
/* Number of channels enabled and DDR3 type. Determine number of
* channels by keying of the rank enable bits [3:0]. * */
ch0 = iosf_dunit_ch0_read(DRP);
ch1 = iosf_dunit_ch1_read(DRP);
num_channels = 0;
if (ch0 & DRP_RANK_MASK)
num_channels++;
if (ch1 & DRP_RANK_MASK)
num_channels++;
printk(BIOS_INFO, "%d channels of %sDDR3 @ ", num_channels,
(reg & (1 << 22)) ? "LP" : "");
/* DRAM frequency -- all channels run at same frequency. */
reg = iosf_dunit_read(DTR0);
switch (reg & 0x3) {
case 0:
speed = 800; break;
case 1:
speed = 1066; break;
case 2:
speed = 1333; break;
case 3:
speed = 1600; break;
}
printk(BIOS_INFO, "%dMHz\n", speed);
}
void raminit(struct mrc_params *mp, int prev_sleep_state)
{
int ret;
mrc_wrapper_entry_t mrc_entry;
const struct mrc_saved_data *cache;
/* Fill in default entries. */
mp->version = MRC_PARAMS_VER;
mp->console_out = &send_to_console;
mp->prev_sleep_state = prev_sleep_state;
mp->rmt_enabled = IS_ENABLED(CONFIG_MRC_RMT);
/* Default to 2GiB IO hole. */
if (!mp->io_hole_mb)
mp->io_hole_mb = 2048;
if (recovery_mode_enabled()) {
printk(BIOS_DEBUG, "Recovery mode: not using MRC cache.\n");
} else if (!mrc_cache_get_current(&cache)) {
mp->saved_data_size = cache->size;
mp->saved_data = &cache->data[0];
} else if (prev_sleep_state == 3) {
/* If waking from S3 and no cache then. */
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 (prev_sleep_state == 0) {
/* Ensure EC is running RO firmware. */
google_chromeec_check_ec_image(EC_IMAGE_RO);
}
#endif
}
/* Determine if mrc.bin is in the cbfs. */
if (cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "mrc.bin", CBFS_TYPE_MRC,
NULL) == NULL) {
printk(BIOS_DEBUG, "Couldn't find mrc.bin\n");
return;
}
/*
* The entry point is currently the first instruction. Handle the
* case of an ELF file being put in the cbfs by setting the entry
* to the CONFIG_MRC_BIN_ADDRESS.
*/
mrc_entry = (void *)(uintptr_t)CONFIG_MRC_BIN_ADDRESS;
if (mp->mainboard.dram_info_location == DRAM_INFO_SPD_SMBUS)
enable_smbus();
ret = mrc_entry(mp);
print_dram_info();
if (prev_sleep_state != 3) {
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 Wrapper returned %d\n", ret);
printk(BIOS_DEBUG, "MRC data at %p %d bytes\n", mp->data_to_save,
mp->data_to_save_size);
if (mp->data_to_save != NULL && mp->data_to_save_size > 0)
mrc_cache_stash_data(mp->data_to_save, mp->data_to_save_size);
}

View File

@ -0,0 +1,377 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 <arch/cpu.h>
#include <arch/io.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>
#if CONFIG_EC_GOOGLE_CHROMEEC
#include <ec/google/chromeec/ec.h>
#endif
#include <elog.h>
#include <romstage_handoff.h>
#include <stage_cache.h>
#include <timestamp.h>
#include <vendorcode/google/chromeos/chromeos.h>
#include <soc/gpio.h>
#include <soc/iomap.h>
#include <soc/lpc.h>
#include <soc/pci_devs.h>
#include <soc/pmc.h>
#include <soc/reset.h>
#include <soc/romstage.h>
#include <soc/smm.h>
#include <soc/spi.h>
/* The cache-as-ram assembly file calls romstage_main() after setting up
* cache-as-ram. romstage_main() will then call the mainboards's
* mainboard_romstage_entry() function. That function then calls
* romstage_common() below. The reason for the back and forth is to provide
* common entry point from cache-as-ram while still allowing for code sharing.
* Because we can't use global variables the stack is used for allocations --
* thus the need to call back and forth. */
static void *setup_stack_and_mttrs(void);
static void program_base_addresses(void)
{
uint32_t reg;
const uint32_t lpc_dev = PCI_DEV(0, LPC_DEV, LPC_FUNC);
/* Memory Mapped IO registers. */
reg = PMC_BASE_ADDRESS | 2;
pci_write_config32(lpc_dev, PBASE, reg);
reg = IO_BASE_ADDRESS | 2;
pci_write_config32(lpc_dev, IOBASE, reg);
reg = ILB_BASE_ADDRESS | 2;
pci_write_config32(lpc_dev, IBASE, reg);
reg = SPI_BASE_ADDRESS | 2;
pci_write_config32(lpc_dev, SBASE, reg);
reg = MPHY_BASE_ADDRESS | 2;
pci_write_config32(lpc_dev, MPBASE, reg);
reg = PUNIT_BASE_ADDRESS | 2;
pci_write_config32(lpc_dev, PUBASE, reg);
reg = RCBA_BASE_ADDRESS | 1;
pci_write_config32(lpc_dev, RCBA, reg);
/* IO Port Registers. */
reg = ACPI_BASE_ADDRESS | 2;
pci_write_config32(lpc_dev, ABASE, reg);
reg = GPIO_BASE_ADDRESS | 2;
pci_write_config32(lpc_dev, GBASE, reg);
}
static void spi_init(void)
{
u32 *scs = (u32 *)(SPI_BASE_ADDRESS + SCS);
u32 *bcr = (u32 *)(SPI_BASE_ADDRESS + BCR);
uint32_t reg;
/* Disable generating SMI when setting WPD bit. */
write32(scs, read32(scs) & ~SMIWPEN);
/*
* Enable caching and prefetching in the SPI controller. Disable
* the SMM-only BIOS write and set WPD bit.
*/
reg = (read32(bcr) & ~SRC_MASK) | SRC_CACHE_PREFETCH | BCR_WPD;
reg &= ~EISS;
write32(bcr, reg);
}
/* 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,
.mrc_params = NULL,
};
/* 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);
program_base_addresses();
tco_disable();
byt_config_com1_and_enable();
console_init();
spi_init();
set_max_freq();
punit_init();
gfx_init();
#if CONFIG_EC_GOOGLE_CHROMEEC
/* Ensure the EC is in the right mode for recovery */
google_chromeec_early_init();
#endif
/* Call into mainboard. */
mainboard_romstage_entry(&rp);
return setup_stack_and_mttrs();
}
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);
static 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->gpe0_sts = inl(ACPI_BASE_ADDRESS + GPE0_STS);
ps->gpe0_en = inl(ACPI_BASE_ADDRESS + GPE0_EN);
ps->tco_sts = inl(ACPI_BASE_ADDRESS + TCO_STS);
ps->prsts = read32((u32 *)(PMC_BASE_ADDRESS + PRSTS));
ps->gen_pmcon1 = read32((u32 *)(PMC_BASE_ADDRESS + GEN_PMCON1));
ps->gen_pmcon2 = read32((u32 *)(PMC_BASE_ADDRESS + GEN_PMCON2));
printk(BIOS_DEBUG, "pm1_sts: %04x pm1_en: %04x pm1_cnt: %08x\n",
ps->pm1_sts, ps->pm1_en, ps->pm1_cnt);
printk(BIOS_DEBUG, "gpe0_sts: %08x gpe0_en: %08x tco_sts: %08x\n",
ps->gpe0_sts, ps->gpe0_en, ps->tco_sts);
printk(BIOS_DEBUG, "prsts: %08x gen_pmcon1: %08x gen_pmcon2: %08x\n",
ps->prsts, ps->gen_pmcon1, ps->gen_pmcon2);
return ps;
}
/* Return 0, 3, or 5 to indicate the previous sleep state. */
static int chipset_prev_sleep_state(struct chipset_power_state *ps)
{
/* Default to S0. */
int prev_sleep_state = 0;
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 = 3;
break;
#endif
case SLP_TYP_S5:
prev_sleep_state = 5;
break;
}
/* Clear SLP_TYP. */
outl(ps->pm1_cnt & ~(SLP_TYP), ACPI_BASE_ADDRESS + PM1_CNT);
}
if (ps->gen_pmcon1 & (PWR_FLR | SUS_PWR_FLR)) {
prev_sleep_state = 5;
}
return prev_sleep_state;
}
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 == 3 ? 2 : 0);
#endif
}
/* Entry from the mainboard. */
void romstage_common(struct romstage_params *params)
{
struct romstage_handoff *handoff;
struct chipset_power_state *ps;
int prev_sleep_state;
timestamp_add_now(TS_BEFORE_INITRAM);
ps = fill_power_state();
prev_sleep_state = chipset_prev_sleep_state(ps);
printk(BIOS_DEBUG, "prev_sleep_state = S%d\n", prev_sleep_state);
#if CONFIG_ELOG_BOOT_COUNT
if (prev_sleep_state != 3)
boot_count_increment();
#endif
/* Initialize RAM */
raminit(params->mrc_params, prev_sleep_state);
timestamp_add_now(TS_AFTER_INITRAM);
handoff = romstage_handoff_find_or_add();
if (handoff != NULL)
handoff->s3_resume = (prev_sleep_state == 3);
else
printk(BIOS_DEBUG, "Romstage handoff structure not added!\n");
chromeos_init(prev_sleep_state);
}
void asmlinkage romstage_after_car(void)
{
timestamp_add_now(TS_END_ROMSTAGE);
/* Load the ramstage. */
copy_and_run();
while (1);
}
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. */
static 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 MTRR 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: MTRR base 0 31:0
* +8: MTRR base 0 63:32
* +12: MTRR mask 0 31:0
* +16: MTRR mask 0 63:32
* +20: MTRR base 1 31:0
* +24: MTRR base 1 63:32
* +28: MTRR mask 1 31:0
* +32: MTRR 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 MTRRs to setup. Return the stack location
* pointing to the number of MTRRs. */
slot = stack_push(slot, num_mtrrs);
return slot;
}
void ramstage_cache_invalid(void)
{
#if CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE
/* Perform cold reset on invalid ramstage cache. */
cold_reset();
#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

View File

@ -0,0 +1,38 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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/gpio.h>
#include <soc/iomap.h>
#include <soc/lpc.h>
#include <soc/pci_devs.h>
#include <soc/romstage.h>
void byt_config_com1_and_enable(void)
{
uint32_t reg;
/* Enable the UART hardware for COM1. */
reg = 1;
pci_write_config32(PCI_DEV(0, LPC_DEV, 0), UART_CONT, reg);
/* Set up the pads to select the UART function */
score_select_func(UART_RXD_PAD, 1);
score_select_func(UART_TXD_PAD, 1);
}

View File

@ -0,0 +1,240 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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/ramstage.h>
#include <soc/sata.h>
#include <console/console.h>
#include <delay.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include "chip.h"
typedef struct soc_intel_baytrail_config config_t;
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;
u16 reg16;
u8 reg8;
printk(BIOS_DEBUG, "SATA: Initializing...\n");
if (config == NULL) {
printk(BIOS_ERR, "SATA: ERROR: Device not in devicetree.cb!\n");
return;
}
if (!config->sata_ahci) {
/* Set legacy or native decoding mode */
if (config->ide_legacy_combined) {
reg8 = pci_read_config8(dev, 0x09);
reg8 &= ~0x5;
pci_write_config8(dev, 0x09, reg8);
} else {
reg8 = pci_read_config8(dev, 0x09);
reg8 |= 0x5;
pci_write_config8(dev, 0x09, reg8);
}
/* Set capabilities pointer */
pci_write_config8(dev, 0x34, 0x70);
reg16 = pci_read_config16(dev, 0x70);
reg16 &= ~0xFF00;
pci_write_config16(dev, 0x70, reg16);
}
/* Primary timing - decode enable */
reg16 = pci_read_config16(dev, 0x40);
reg16 |= 1 << 15;
pci_write_config16(dev, 0x40, reg16);
/* Secondary timing - decode enable */
reg16 = pci_read_config16(dev, 0x42);
reg16 |= 1 << 15;
pci_write_config16(dev, 0x42, reg16);
/* Port mapping enables */
reg16 = pci_read_config16(dev, 0x90);
reg16 |= (config->sata_port_map ^ 0x3) << 8;
pci_write_config16(dev, 0x90, reg16);
/* Port control enables */
reg16 = pci_read_config16(dev, 0x92);
reg16 &= ~0x003f;
reg16 |= config->sata_port_map;
pci_write_config16(dev, 0x92, reg16);
if (config->sata_ahci) {
u8 *abar = (u8 *)pci_read_config32(dev, PCI_BASE_ADDRESS_5);
/* Enable CR memory space decoding */
reg16 = pci_read_config16(dev, 0x04);
reg16 |= 0x2;
pci_write_config16(dev, 0x04, reg16);
/* Set capability register */
reg32 = read32(abar + 0x00);
reg32 |= 0x0c046000; // set PSC+SSC+SALP+SSS+SAM
reg32 &= ~0x00f20060; // clear SXS+EMS+PMS+gen bits
reg32 |= (0x3 << 20); // Gen3 SATA
write32(abar + 0x00, reg32);
/* Ports enabled */
reg32 = read32(abar + 0x0c);
reg32 &= (u32)(~0x3f);
reg32 |= config->sata_port_map;
write32(abar + 0xc, reg32);
/* Two extra reads to latch */
read32(abar + 0x0c);
read32(abar + 0x0c);
/* Set cap2 - Support devslp */
reg32 = (1 << 5) | (1 << 4) | (1 << 3);
write32(abar + 0x24, reg32);
/* Set PxCMD registers */
reg32 = read32(abar + 0x118);
reg32 &= ~((1 << 27) | (1 << 26) | (1 << 22) | (1 << 21) |
(1 << 19) | (1 << 18) | (1 << 1));
reg32 |= 2;
write32(abar + 0x118, reg32);
reg32 = read32(abar + 0x198);
reg32 &= ~((1 << 27) | (1 << 26) | (1 << 22) | (1 << 21) |
(1 << 19) | (1 << 18) | (1 << 1));
reg32 |= 2;
write32(abar + 0x198, reg32);
/* Clear reset features */
write32(abar + 0xc8, 0);
/* Enable interrupts */
reg8 = read8(abar + 0x04);
reg8 |= 0x02;
write8(abar + 0x04, reg8);
} else {
/* TODO(shawnn): Configure IDE SATA speed regs */
}
/* 1.4 us delay after configuring port / enable bits */
udelay(2);
/* Enable clock for ports */
reg32 = pci_read_config32(dev, 0x94);
reg32 |= 0x3f << 24;
pci_write_config32(dev, 0x94, reg32);
reg32 &= (config->sata_port_map ^ 0x3) << 24;
pci_write_config32(dev, 0x94, reg32);
/* Lock SataGc register */
reg32 = (0x1 << 31) | (0x7 << 12);
pci_write_config32(dev, 0x98, reg32);
}
static void sata_enable(device_t dev)
{
config_t *config = dev->chip_info;
u8 reg8;
u16 reg16;
u32 reg32;
southcluster_enable_dev(dev);
if (!config)
return;
/* Port mapping -- mask off SPD + SMS + SC bits, then re-set */
reg16 = pci_read_config16(dev, 0x90);
reg16 &= ~0x03e0;
reg16 |= (config->sata_port_map ^ 0x3) << 8;
if(config->sata_ahci)
reg16 |= 0x60;
pci_write_config16(dev, 0x90, reg16);
/* Set reg 0x94 before starting configuration */
reg32 = pci_read_config32(dev, 0x94);
reg32 &= (u32)(~0x1ff);
reg32 |= 0x183;
pci_write_config32(dev, 0x94, reg32);
/* Set ORM bit */
reg16 = pci_read_config16(dev, 0x92);
reg16 |= (1 << 15);
pci_write_config16(dev, 0x92, reg16);
/* R_PCH_SATA_TM2 - Undocumented in EDS, set according to ref. code */
reg32 = pci_read_config32(dev, 0x98);
reg32 &= (u32)~(0x1f80 | (1 << 6) | (1 << 5));
reg32 |= (1 << 29) | (1 << 25) | (1 << 23) | (1 << 22) |
(1 << 20) | (1 << 19) | (1 << 18) | (1 << 9) | (1 << 5);
pci_write_config32(dev, 0x98, reg32);
/* CMD reg - set bus master enable (BME) */
reg8 = pci_read_config8(dev, 0x04);
reg8 |= (1 << 2);
pci_write_config8(dev, 0x04, reg8);
/* "Test mode registers" */
sir_write(dev, 0x70, 0x00288301);
sir_write(dev, 0x54, 0x00000300);
sir_write(dev, 0x58, 0x50000000);
/* "OOB Detection Margin */
sir_write(dev, 0x6c, 0x130C0603);
/* "Gasket Control" */
sir_write(dev, 0xf4, 0);
/* PCS - Enable requested SATA ports */
reg8 = pci_read_config8(dev, 0x92);
reg8 &= ~0x03;
reg8 |= config->sata_port_map;
pci_write_config8(dev, 0x92, reg8);
}
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,
.scan_bus = NULL,
.ops_pci = &soc_pci_ops,
};
static const unsigned short pci_device_ids[] = {
IDE1_DEVID, IDE2_DEVID, /* IDE */
AHCI1_DEVID, AHCI2_DEVID, /* AHCI */
0,
};
static const struct pci_driver baytrail_sata __pci_driver = {
.ops = &sata_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.devices = pci_device_ids,
};

View File

@ -0,0 +1,125 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 <reg_script.h>
#include <soc/iosf.h>
#include <soc/nvs.h>
#include <soc/ramstage.h>
static const struct reg_script scc_start_dll[] = {
/* Configure master DLL. */
REG_IOSF_WRITE(IOSF_PORT_SCORE, 0x4964, 0x00078000),
/* Configure Swing,FSM for Master DLL */
REG_IOSF_WRITE(IOSF_PORT_SCORE, 0x4970, 0x00000133),
/* Run+Local Reset on Master DLL */
REG_IOSF_WRITE(IOSF_PORT_SCORE, 0x4970, 0x00001933),
REG_SCRIPT_END,
};
static const struct reg_script scc_after_dll[] = {
/* Configure Write Path */
REG_IOSF_RMW(IOSF_PORT_SCORE, 0x4954, ~0x7fff, 0x35ad),
REG_IOSF_RMW(IOSF_PORT_SCORE, 0x4958, ~0x7fff, 0x35ad),
REG_IOSF_RMW(IOSF_PORT_SCORE, 0x495c, ~0x7fff, 0x35ad),
/* Configure Read Path */
REG_IOSF_RMW(IOSF_PORT_SCORE, 0x43e4, ~0x7fff, 0x35ad),
REG_IOSF_RMW(IOSF_PORT_SCORE, 0x4324, ~0x7fff, 0x35ad),
REG_IOSF_RMW(IOSF_PORT_SCORE, 0x42b4, ~0x7fff, 0x35ad),
/* eMMC 4.5 TX and RX DLL */
REG_IOSF_RMW(IOSF_PORT_SCORE, 0x49a4, ~0x1f001f, 0xa000d),
REG_IOSF_RMW(IOSF_PORT_SCORE, 0x49a8, ~0x1f001f, 0xd000d),
REG_IOSF_RMW(IOSF_PORT_SCORE, 0x49ac, ~0x1f001f, 0xd000d),
REG_IOSF_RMW(IOSF_PORT_SCORE, 0x49b0, ~0x1f001f, 0xd000d),
REG_IOSF_RMW(IOSF_PORT_SCORE, 0x49b4, ~0x1f001f, 0xd000d),
REG_IOSF_RMW(IOSF_PORT_SCORE, 0x49b8, ~0x1, 0x0),
/* cfio_regs_mmc1_ELECTRICAL.nslew/pslew */
REG_IOSF_RMW(IOSF_PORT_SCORE, 0x48c0, ~0x3c, 0x0),
REG_IOSF_RMW(IOSF_PORT_SCORE, 0x48c4, ~0x3c, 0x0),
/*
* iosf2ocp_private.GENREGRW1.cr_clock_enable_clk_ocp = 01
* iosf2ocp_private.GENREGRW1.cr_clock_enable_clk_xin = 01
*/
REG_IOSF_RMW(IOSF_PORT_SCC, 0x600, ~0xf, 0x5),
/* Enable IOSF Snoop */
REG_IOSF_OR(IOSF_PORT_SCC, 0x00, (1 << 7)),
/* SDIO 3V Support. */
REG_IOSF_RMW(IOSF_PORT_SCC, 0x600, ~0x30, 0x30),
REG_SCRIPT_END,
};
void baytrail_init_scc(void)
{
uint32_t dll_values;
printk(BIOS_DEBUG, "Initializing sideband SCC registers.\n");
/* Common Sideband Initialization for SCC */
reg_script_run(scc_start_dll);
/* Override Slave Path - populate DLL settings. */
dll_values = iosf_score_read(0x496c) & 0x7ffff;
dll_values |= iosf_score_read(0x4950) & ~0xfffff;
iosf_score_write(0x4950, dll_values | (1 << 19));
reg_script_run(scc_after_dll);
}
void scc_enable_acpi_mode(device_t dev, int iosf_reg, int nvs_index)
{
struct reg_script ops[] = {
/* Disable PCI interrupt, enable Memory and Bus Master */
REG_PCI_OR32(PCI_COMMAND,
PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | (1<<10)),
/* Enable ACPI mode */
REG_IOSF_OR(IOSF_PORT_SCC, iosf_reg,
SCC_CTL_PCI_CFG_DIS | SCC_CTL_ACPI_INT_EN),
REG_SCRIPT_END
};
struct resource *bar;
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 */
bar = find_resource(dev, PCI_BASE_ADDRESS_0);
if (bar)
gnvs->dev.scc_bar0[nvs_index] = (u32)bar->base;
bar = find_resource(dev, PCI_BASE_ADDRESS_1);
if (bar)
gnvs->dev.scc_bar1[nvs_index] = (u32)bar->base;
/* Device is enabled in ACPI mode */
gnvs->dev.scc_en[nvs_index] = 1;
/* Put device in ACPI mode */
reg_script_run_on_dev(dev, ops);
}

View File

@ -0,0 +1,70 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 <reg_script.h>
#include <soc/iosf.h>
#include <soc/nvs.h>
#include <soc/pci_devs.h>
#include <soc/ramstage.h>
#include "chip.h"
#define CAP_OVERRIDE_LOW 0xa0
#define CAP_OVERRIDE_HIGH 0xa4
# define USE_CAP_OVERRIDES (1 << 31)
static void sd_init(device_t dev)
{
struct soc_intel_baytrail_config *config = dev->chip_info;
if (config == NULL)
return;
if (config->sdcard_cap_low != 0 || config->sdcard_cap_high != 0) {
printk(BIOS_DEBUG, "Overriding SD Card controller caps.\n");
pci_write_config32(dev, CAP_OVERRIDE_LOW,
config->sdcard_cap_low);
pci_write_config32(dev, CAP_OVERRIDE_HIGH,
config->sdcard_cap_high | USE_CAP_OVERRIDES);
}
if (config->scc_acpi_mode)
scc_enable_acpi_mode(dev, SCC_SD_CTL, SCC_NVS_SD);
}
static const struct device_operations device_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = sd_init,
.enable = NULL,
.scan_bus = NULL,
.ops_pci = &soc_pci_ops,
};
static const struct pci_driver southcluster __pci_driver = {
.ops = &device_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.device = SD_DEVID,
};

View File

@ -0,0 +1,483 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 <stdlib.h>
#include <arch/io.h>
#include <console/console.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/smm.h>
#include <device/pci_def.h>
#include <elog.h>
#include <halt.h>
#include <spi-generic.h>
#include <soc/iosf.h>
#include <soc/pci_devs.h>
#include <soc/pmc.h>
#include <soc/nvs.h>
/* GNVS needs to be set by coreboot initiating a software SMI. */
static global_nvs_t *gnvs;
static int smm_initialized;
int southbridge_io_trap_handler(int smif)
{
switch (smif) {
case 0x32:
printk(BIOS_DEBUG, "OS Init\n");
/* gnvs->smif:
* On success, the IO Trap Handler returns 0
* On failure, the IO Trap Handler returns a value != 0
*/
gnvs->smif = 0;
return 1; /* IO trap handled */
}
/* Not handled */
return 0;
}
void southbridge_smi_set_eos(void)
{
enable_smi(EOS);
}
global_nvs_t *smm_get_gnvs(void)
{
return gnvs;
}
static void busmaster_disable_on_bus(int bus)
{
int slot, func;
unsigned int val;
unsigned char hdr;
for (slot = 0; slot < 0x20; slot++) {
for (func = 0; func < 8; func++) {
u32 reg32;
device_t dev = PCI_DEV(bus, slot, func);
val = pci_read_config32(dev, PCI_VENDOR_ID);
if (val == 0xffffffff || val == 0x00000000 ||
val == 0x0000ffff || val == 0xffff0000)
continue;
/* Disable Bus Mastering for this one device */
reg32 = pci_read_config32(dev, PCI_COMMAND);
reg32 &= ~PCI_COMMAND_MASTER;
pci_write_config32(dev, PCI_COMMAND, reg32);
/* If this is a bridge, then follow it. */
hdr = pci_read_config8(dev, PCI_HEADER_TYPE);
hdr &= 0x7f;
if (hdr == PCI_HEADER_TYPE_BRIDGE ||
hdr == PCI_HEADER_TYPE_CARDBUS) {
unsigned int buses;
buses = pci_read_config32(dev, PCI_PRIMARY_BUS);
busmaster_disable_on_bus((buses >> 8) & 0xff);
}
}
}
}
static void southbridge_smi_sleep(void)
{
uint32_t reg32;
uint8_t slp_typ;
uint16_t pmbase = get_pmbase();
/* First, disable further SMIs */
disable_smi(SLP_SMI_EN);
/* Figure out SLP_TYP */
reg32 = inl(pmbase + PM1_CNT);
printk(BIOS_SPEW, "SMI#: SLP = 0x%08x\n", reg32);
slp_typ = (reg32 >> 10) & 7;
/* Do any mainboard sleep handling */
mainboard_smi_sleep(slp_typ-2);
#if CONFIG_ELOG_GSMI
/* Log S3, S4, and S5 entry */
if (slp_typ >= 5)
elog_add_event_byte(ELOG_TYPE_ACPI_ENTER, slp_typ-2);
#endif
/* Next, do the deed.
*/
switch (slp_typ) {
case SLP_TYP_S0:
printk(BIOS_DEBUG, "SMI#: Entering S0 (On)\n");
break;
case SLP_TYP_S1:
printk(BIOS_DEBUG, "SMI#: Entering S1 (Assert STPCLK#)\n");
break;
case SLP_TYP_S3:
printk(BIOS_DEBUG, "SMI#: Entering S3 (Suspend-To-RAM)\n");
/* Invalidate the cache before going to S3 */
wbinvd();
break;
case SLP_TYP_S4:
printk(BIOS_DEBUG, "SMI#: Entering S4 (Suspend-To-Disk)\n");
break;
case SLP_TYP_S5:
printk(BIOS_DEBUG, "SMI#: Entering S5 (Soft Power off)\n");
/* Disable all GPE */
disable_all_gpe();
/* also iterates over all bridges on bus 0 */
busmaster_disable_on_bus(0);
break;
default:
printk(BIOS_DEBUG, "SMI#: ERROR: SLP_TYP reserved\n");
break;
}
/* Write back to the SLP register to cause the originally intended
* event again. We need to set BIT13 (SLP_EN) though to make the
* sleep happen.
*/
enable_pm1_control(SLP_EN);
/* Make sure to stop executing code here for S3/S4/S5 */
if (slp_typ > 1)
halt();
/* In most sleep states, the code flow of this function ends at
* the line above. However, if we entered sleep state S1 and wake
* up again, we will continue to execute code in this function.
*/
reg32 = inl(pmbase + PM1_CNT);
if (reg32 & SCI_EN) {
/* The OS is not an ACPI OS, so we set the state to S0 */
disable_pm1_control(SLP_EN | SLP_TYP);
}
}
/*
* Look for Synchronous IO SMI and use save state from that
* core in case we are not running on the same core that
* initiated the IO transaction.
*/
static em64t100_smm_state_save_area_t *smi_apmc_find_state_save(uint8_t cmd)
{
em64t100_smm_state_save_area_t *state;
int node;
/* Check all nodes looking for the one that issued the IO */
for (node = 0; node < CONFIG_MAX_CPUS; node++) {
state = smm_get_save_state(node);
/* Check for Synchronous IO (bit0==1) */
if (!(state->io_misc_info & (1 << 0)))
continue;
/* Make sure it was a write (bit4==0) */
if (state->io_misc_info & (1 << 4))
continue;
/* Check for APMC IO port */
if (((state->io_misc_info >> 16) & 0xff) != APM_CNT)
continue;
/* Check AX against the requested command */
if ((state->rax & 0xff) != cmd)
continue;
return state;
}
return NULL;
}
#if CONFIG_ELOG_GSMI
static void southbridge_smi_gsmi(void)
{
u32 *ret, *param;
uint8_t sub_command;
em64t100_smm_state_save_area_t *io_smi =
smi_apmc_find_state_save(ELOG_GSMI_APM_CNT);
if (!io_smi)
return;
/* Command and return value in EAX */
ret = (u32*)&io_smi->rax;
sub_command = (uint8_t)(*ret >> 8);
/* Parameter buffer in EBX */
param = (u32*)&io_smi->rbx;
/* drivers/elog/gsmi.c */
*ret = gsmi_exec(sub_command, param);
}
#endif
static void finalize(void)
{
static int finalize_done;
if (finalize_done) {
printk(BIOS_DEBUG, "SMM already finalized.\n");
return;
}
finalize_done = 1;
#if CONFIG_SPI_FLASH_SMM
/* Re-init SPI driver to handle locked BAR */
spi_init();
#endif
}
/*
* soc_legacy: A payload (Depthcharge) has indicated that the
* legacy payload (SeaBIOS) is being loaded. Switch devices that are
* in ACPI mode to PCI mode so that non-ACPI drivers may work.
*
*/
static void soc_legacy(void)
{
u32 reg32;
/* LPE Device */
if (gnvs->dev.lpe_en) {
reg32 = iosf_port58_read(LPE_PCICFGCTR1);
reg32 &=
~(LPE_PCICFGCTR1_PCI_CFG_DIS | LPE_PCICFGCTR1_ACPI_INT_EN);
iosf_port58_write(LPE_PCICFGCTR1, reg32);
}
/* SCC Devices */
#define SCC_ACPI_MODE_DISABLE(name_) \
do { if (gnvs->dev.scc_en[SCC_NVS_ ## name_]) { \
reg32 = iosf_scc_read(SCC_ ## name_ ## _CTL); \
reg32 &= ~(SCC_CTL_PCI_CFG_DIS | SCC_CTL_ACPI_INT_EN); \
iosf_scc_write(SCC_ ## name_ ## _CTL, reg32); \
} } while (0)
SCC_ACPI_MODE_DISABLE(MMC);
SCC_ACPI_MODE_DISABLE(SD);
SCC_ACPI_MODE_DISABLE(SDIO);
/* LPSS Devices */
#define LPSS_ACPI_MODE_DISABLE(name_) \
do { if (gnvs->dev.lpss_en[LPSS_NVS_ ## name_]) { \
reg32 = iosf_lpss_read(LPSS_ ## name_ ## _CTL); \
reg32 &= ~LPSS_CTL_PCI_CFG_DIS | ~LPSS_CTL_ACPI_INT_EN; \
iosf_lpss_write(LPSS_ ## name_ ## _CTL, reg32); \
} } while (0)
LPSS_ACPI_MODE_DISABLE(SIO_DMA1);
LPSS_ACPI_MODE_DISABLE(I2C1);
LPSS_ACPI_MODE_DISABLE(I2C2);
LPSS_ACPI_MODE_DISABLE(I2C3);
LPSS_ACPI_MODE_DISABLE(I2C4);
LPSS_ACPI_MODE_DISABLE(I2C5);
LPSS_ACPI_MODE_DISABLE(I2C6);
LPSS_ACPI_MODE_DISABLE(I2C7);
LPSS_ACPI_MODE_DISABLE(SIO_DMA2);
LPSS_ACPI_MODE_DISABLE(PWM1);
LPSS_ACPI_MODE_DISABLE(PWM2);
LPSS_ACPI_MODE_DISABLE(HSUART1);
LPSS_ACPI_MODE_DISABLE(HSUART2);
LPSS_ACPI_MODE_DISABLE(SPI);
}
static void southbridge_smi_apmc(void)
{
uint8_t reg8;
em64t100_smm_state_save_area_t *state;
/* Emulate B2 register as the FADT / Linux expects it */
reg8 = inb(APM_CNT);
switch (reg8) {
case APM_CNT_CST_CONTROL:
/* Calling this function seems to cause
* some kind of race condition in Linux
* and causes a kernel oops
*/
printk(BIOS_DEBUG, "C-state control\n");
break;
case APM_CNT_PST_CONTROL:
/* Calling this function seems to cause
* some kind of race condition in Linux
* and causes a kernel oops
*/
printk(BIOS_DEBUG, "P-state control\n");
break;
case APM_CNT_ACPI_DISABLE:
disable_pm1_control(SCI_EN);
printk(BIOS_DEBUG, "SMI#: ACPI disabled.\n");
break;
case APM_CNT_ACPI_ENABLE:
enable_pm1_control(SCI_EN);
printk(BIOS_DEBUG, "SMI#: ACPI enabled.\n");
break;
case APM_CNT_GNVS_UPDATE:
if (smm_initialized) {
printk(BIOS_DEBUG,
"SMI#: SMM structures already initialized!\n");
return;
}
state = smi_apmc_find_state_save(reg8);
if (state) {
/* EBX in the state save contains the GNVS pointer */
gnvs = (global_nvs_t *)((uint32_t)state->rbx);
smm_initialized = 1;
printk(BIOS_DEBUG, "SMI#: Setting GNVS to %p\n", gnvs);
}
break;
#if CONFIG_ELOG_GSMI
case ELOG_GSMI_APM_CNT:
southbridge_smi_gsmi();
break;
#endif
case APM_CNT_FINALIZE:
finalize();
break;
case APM_CNT_LEGACY:
soc_legacy();
break;
}
mainboard_smi_apmc(reg8);
}
static void southbridge_smi_pm1(void)
{
uint16_t pm1_sts = clear_pm1_status();
/* While OSPM is not active, poweroff immediately
* on a power button event.
*/
if (pm1_sts & PWRBTN_STS) {
// power button pressed
#if CONFIG_ELOG_GSMI
elog_add_event(ELOG_TYPE_POWER_BUTTON);
#endif
disable_pm1_control(-1UL);
enable_pm1_control(SLP_EN | (SLP_TYP_S5 << SLP_TYP_SHIFT));
}
}
static void southbridge_smi_gpe0(void)
{
clear_gpe_status();
}
static void southbridge_smi_tco(void)
{
uint32_t tco_sts = clear_tco_status();
/* Any TCO event? */
if (!tco_sts)
return;
if (tco_sts & TCO_TIMEOUT) { /* TIMEOUT */
/* Handle TCO timeout */
printk(BIOS_DEBUG, "TCO Timeout.\n");
}
}
static void southbridge_smi_periodic(void)
{
uint32_t reg32;
reg32 = inl(get_pmbase() + SMI_EN);
/* Are periodic SMIs enabled? */
if ((reg32 & PERIODIC_EN) == 0)
return;
printk(BIOS_DEBUG, "Periodic SMI.\n");
}
typedef void (*smi_handler_t)(void);
static const smi_handler_t southbridge_smi[32] = {
NULL, // [0] reserved
NULL, // [1] reserved
NULL, // [2] BIOS_STS
NULL, // [3] LEGACY_USB_STS
southbridge_smi_sleep, // [4] SLP_SMI_STS
southbridge_smi_apmc, // [5] APM_STS
NULL, // [6] SWSMI_TMR_STS
NULL, // [7] reserved
southbridge_smi_pm1, // [8] PM1_STS
southbridge_smi_gpe0, // [9] GPE0_STS
NULL, // [10] reserved
NULL, // [11] reserved
NULL, // [12] reserved
southbridge_smi_tco, // [13] TCO_STS
southbridge_smi_periodic, // [14] PERIODIC_STS
NULL, // [15] SERIRQ_SMI_STS
NULL, // [16] SMBUS_SMI_STS
NULL, // [17] LEGACY_USB2_STS
NULL, // [18] INTEL_USB2_STS
NULL, // [19] reserved
NULL, // [20] PCI_EXP_SMI_STS
NULL, // [21] reserved
NULL, // [22] reserved
NULL, // [23] reserved
NULL, // [24] reserved
NULL, // [25] reserved
NULL, // [26] SPI_STS
NULL, // [27] reserved
NULL, // [28] PUNIT
NULL, // [29] GUNIT
NULL, // [30] reserved
NULL // [31] reserved
};
void southbridge_smi_handler(void)
{
int i;
uint32_t smi_sts;
/* We need to clear the SMI status registers, or we won't see what's
* happening in the following calls.
*/
smi_sts = clear_smi_status();
/* Call SMI sub handler for each of the status bits */
for (i = 0; i < ARRAY_SIZE(southbridge_smi); i++) {
if (!(smi_sts & (1 << i)))
continue;
if (southbridge_smi[i] != NULL) {
southbridge_smi[i]();
} else {
printk(BIOS_DEBUG,
"SMI_STS[%d] occurred, but no "
"handler available.\n", i);
}
}
/* The GPIO SMI events do not have a status bit in SMI_STS. Therefore,
* these events need to be cleared and checked unconditionally. */
mainboard_smi_gpi(clear_alt_status());
}

View File

@ -0,0 +1,133 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 <device/device.h>
#include <device/pci.h>
#include <console/console.h>
#include <arch/io.h>
#include <cpu/cpu.h>
#include <cpu/x86/smm.h>
#include <string.h>
#include <soc/iomap.h>
#include <soc/pmc.h>
#include <soc/smm.h>
/* Save settings which will be committed in SMI functions. */
static uint32_t smm_save_params[SMM_SAVE_PARAM_COUNT];
void southcluster_smm_save_param(int param, uint32_t data)
{
smm_save_params[param] = data;
}
void southcluster_smm_clear_state(void)
{
uint32_t smi_en;
/* Log events from chipset before clearing */
southcluster_log_state();
printk(BIOS_DEBUG, "Initializing Southbridge SMI...");
printk(BIOS_SPEW, " pmbase = 0x%04x\n", get_pmbase());
smi_en = inl(get_pmbase() + SMI_EN);
if (smi_en & APMC_EN) {
printk(BIOS_INFO, "SMI# handler already enabled?\n");
return;
}
/* Dump and clear status registers */
clear_smi_status();
clear_pm1_status();
clear_tco_status();
clear_gpe_status();
clear_alt_status();
clear_pmc_status();
}
static void southcluster_smm_route_gpios(void)
{
u32 *gpio_rout = (u32 *)(PMC_BASE_ADDRESS + GPIO_ROUT);
const unsigned short alt_gpio_smi = ACPI_BASE_ADDRESS + ALT_GPIO_SMI;
uint32_t alt_gpio_reg = 0;
uint32_t route_reg = smm_save_params[SMM_SAVE_PARAM_GPIO_ROUTE];
int i;
printk(BIOS_DEBUG, "GPIO_ROUT = %08x\n", route_reg);
/* Start the routing for the specific gpios. */
write32(gpio_rout, route_reg);
/* Enable SMIs for the gpios that are set to trigger the SMI. */
for (i = 0; i < 16; i++) {
if ((route_reg & ROUTE_MASK) == ROUTE_SMI) {
alt_gpio_reg |= (1 << i);
}
route_reg >>= 2;
}
printk(BIOS_DEBUG, "ALT_GPIO_SMI = %08x\n", alt_gpio_reg);
outl(alt_gpio_reg, alt_gpio_smi);
}
void southcluster_smm_enable_smi(void)
{
uint16_t pm1_events = PWRBTN_EN | GBL_EN;
printk(BIOS_DEBUG, "Enabling SMIs.\n");
if (!smm_save_params[SMM_SAVE_PARAM_PCIE_WAKE_ENABLE])
pm1_events |= PCIEXPWAK_DIS;
enable_pm1(pm1_events);
disable_gpe(PME_B0_EN);
/* Set up the GPIO route. */
southcluster_smm_route_gpios();
/* Enable SMI generation:
* - on APMC writes (io 0xb2)
* - on writes to SLP_EN (sleep states)
* - on writes to GBL_RLS (bios commands)
* No SMIs:
* - on TCO events
* - on microcontroller writes (io 0x62/0x66)
*/
enable_smi(APMC_EN | SLP_SMI_EN | GBL_SMI_EN | EOS);
}
void smm_setup_structures(void *gnvs, void *tcg, void *smi1)
{
/*
* Issue SMI to set the gnvs pointer in SMM.
* tcg and smi1 are unused.
*
* EAX = APM_CNT_GNVS_UPDATE
* EBX = gnvs pointer
* EDX = APM_CNT
*/
asm volatile (
"outb %%al, %%dx\n\t"
: /* ignore result */
: "a" (APM_CNT_GNVS_UPDATE),
"b" ((uint32_t)gnvs),
"d" (APM_CNT)
);
}

View File

@ -0,0 +1,572 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008-2009 coresystems GmbH
* Copyright (C) 2013 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/io.h>
#include <arch/acpi.h>
#include <bootstate.h>
#include <cbmem.h>
#include <console/console.h>
#include <cpu/x86/smm.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <pc80/mc146818rtc.h>
#include <drivers/uart/uart8250reg.h>
#include <soc/iomap.h>
#include <soc/irq.h>
#include <soc/lpc.h>
#include <soc/nvs.h>
#include <soc/pci_devs.h>
#include <soc/pmc.h>
#include <soc/ramstage.h>
#include <soc/spi.h>
#include "chip.h"
static inline void
add_mmio_resource(device_t dev, int i, unsigned long addr, unsigned long size)
{
mmio_resource(dev, i, addr >> 10, size >> 10);
}
static void sc_add_mmio_resources(device_t dev)
{
add_mmio_resource(dev, 0xfeb, ABORT_BASE_ADDRESS, ABORT_BASE_SIZE);
add_mmio_resource(dev, PBASE, PMC_BASE_ADDRESS, PMC_BASE_SIZE);
add_mmio_resource(dev, IOBASE, IO_BASE_ADDRESS, IO_BASE_SIZE);
add_mmio_resource(dev, IBASE, ILB_BASE_ADDRESS, ILB_BASE_SIZE);
add_mmio_resource(dev, SBASE, SPI_BASE_ADDRESS, SPI_BASE_SIZE);
add_mmio_resource(dev, MPBASE, MPHY_BASE_ADDRESS, MPHY_BASE_SIZE);
add_mmio_resource(dev, PUBASE, PUNIT_BASE_ADDRESS, PUNIT_BASE_SIZE);
add_mmio_resource(dev, RCBA, RCBA_BASE_ADDRESS, RCBA_BASE_SIZE);
}
/* 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 io_range_in_default(int base, int 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 sc_add_io_resource(device_t dev, int base, int size, int index)
{
struct resource *res;
if (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 sc_add_io_resources(device_t dev)
{
struct resource *res;
/* 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;
/* GPIO */
sc_add_io_resource(dev, GPIO_BASE_ADDRESS, 256, GBASE);
/* ACPI */
sc_add_io_resource(dev, ACPI_BASE_ADDRESS, 128, ABASE);
}
static void sc_read_resources(device_t dev)
{
/* Get the normal PCI resources of this device. */
pci_dev_read_resources(dev);
/* Add non-standard MMIO resources. */
sc_add_mmio_resources(dev);
/* Add IO resources. */
sc_add_io_resources(dev);
}
static void sc_rtc_init(void)
{
uint32_t gen_pmcon1;
int rtc_fail;
struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE);
if (ps != NULL) {
gen_pmcon1 = ps->gen_pmcon1;
} else {
gen_pmcon1 = read32((u32 *)(PMC_BASE_ADDRESS + GEN_PMCON1));
}
rtc_fail = !!(gen_pmcon1 & RPS);
if (rtc_fail) {
printk(BIOS_DEBUG, "RTC failure.\n");
}
cmos_init(rtc_fail);
}
/*
* The UART hardware loses power while in suspend. Because of this the kernel
* can hang because it doesn't re-initialize serial ports it is using for
* consoles at resume time. The following function configures the UART
* if the hardware is enabled though it may not be the correct baud rate
* or configuration. This is definitely a hack, but it helps the kernel
* along.
*/
static void com1_configure_resume(device_t dev)
{
const uint16_t port = 0x3f8;
/* Is the UART I/O port enabled? */
if (!(pci_read_config32(dev, UART_CONT) & 1))
return;
/* Disable interrupts */
outb(0x0, port + UART8250_IER);
/* Enable FIFOs */
outb(UART8250_FCR_FIFO_EN, port + UART8250_FCR);
/* assert DTR and RTS so the other end is happy */
outb(UART8250_MCR_DTR | UART8250_MCR_RTS, port + UART8250_MCR);
/* DLAB on */
outb(UART8250_LCR_DLAB | 3, port + UART8250_LCR);
/* Set Baud Rate Divisor. 1 ==> 115200 Baud */
outb(1, port + UART8250_DLL);
outb(0, port + UART8250_DLM);
/* Set to 3 for 8N1 */
outb(3, port + UART8250_LCR);
}
static void sc_init(device_t dev)
{
int i;
u8 *pr_base = (u8 *)(ILB_BASE_ADDRESS + 0x08);
u16 *ir_base = (u16 *)ILB_BASE_ADDRESS + 0x20;
u32 *gen_pmcon1 = (u32 *)(PMC_BASE_ADDRESS + GEN_PMCON1);
u32 *actl = (u32 *)(ILB_BASE_ADDRESS + ACTL);
const struct baytrail_irq_route *ir = &global_baytrail_irq_route;
struct soc_intel_baytrail_config *config = dev->chip_info;
/* Set up the PIRQ PIC routing based on static config. */
for (i = 0; i < NUM_PIRQS; i++) {
write8(pr_base + i, ir->pic[i]);
}
/* Set up the per device PIRQ routing base on static config. */
for (i = 0; i < NUM_IR_DEVS; i++) {
write16(ir_base + i, ir->pcidev[i]);
}
/* Route SCI to IRQ9 */
write32(actl, (read32(actl) & ~SCIS_MASK) | SCIS_IRQ9);
sc_rtc_init();
if (config->disable_slp_x_stretch_sus_fail) {
printk(BIOS_DEBUG, "Disabling slp_x stretching.\n");
write32(gen_pmcon1,
read32(gen_pmcon1) | DIS_SLP_X_STRCH_SUS_UP);
} else {
write32(gen_pmcon1,
read32(gen_pmcon1) & ~DIS_SLP_X_STRCH_SUS_UP);
}
if (acpi_is_wakeup_s3())
com1_configure_resume(dev);
}
/*
* Common code for the south cluster devices.
*/
/* Set bit in function disable register to hide this device. */
static void sc_disable_devfn(device_t dev)
{
u32 *func_dis = (u32 *)(PMC_BASE_ADDRESS + FUNC_DIS);
u32 *func_dis2 = (u32 *)(PMC_BASE_ADDRESS + FUNC_DIS2);
uint32_t mask = 0;
uint32_t mask2 = 0;
switch (dev->path.pci.devfn) {
case PCI_DEVFN(SDIO_DEV, SDIO_FUNC):
mask |= SDIO_DIS;
break;
case PCI_DEVFN(SD_DEV, SD_FUNC):
mask |= SD_DIS;
break;
case PCI_DEVFN(SATA_DEV, SATA_FUNC):
mask |= SATA_DIS;
break;
case PCI_DEVFN(XHCI_DEV, XHCI_FUNC):
mask |= XHCI_DIS;
/* Disable super speed PHY when XHCI is not available. */
mask2 |= USH_SS_PHY_DIS;
break;
case PCI_DEVFN(LPE_DEV, LPE_FUNC):
mask |= LPE_DIS;
break;
case PCI_DEVFN(MMC_DEV, MMC_FUNC):
mask |= MMC_DIS;
break;
case PCI_DEVFN(SIO_DMA1_DEV, SIO_DMA1_FUNC):
mask |= SIO_DMA1_DIS;
break;
case PCI_DEVFN(I2C1_DEV, I2C1_FUNC):
mask |= I2C1_DIS;
break;
case PCI_DEVFN(I2C2_DEV, I2C2_FUNC):
mask |= I2C1_DIS;
break;
case PCI_DEVFN(I2C3_DEV, I2C3_FUNC):
mask |= I2C3_DIS;
break;
case PCI_DEVFN(I2C4_DEV, I2C4_FUNC):
mask |= I2C4_DIS;
break;
case PCI_DEVFN(I2C5_DEV, I2C5_FUNC):
mask |= I2C5_DIS;
break;
case PCI_DEVFN(I2C6_DEV, I2C6_FUNC):
mask |= I2C6_DIS;
break;
case PCI_DEVFN(I2C7_DEV, I2C7_FUNC):
mask |= I2C7_DIS;
break;
case PCI_DEVFN(TXE_DEV, TXE_FUNC):
mask |= TXE_DIS;
break;
case PCI_DEVFN(HDA_DEV, HDA_FUNC):
mask |= HDA_DIS;
break;
case PCI_DEVFN(PCIE_PORT1_DEV, PCIE_PORT1_FUNC):
mask |= PCIE_PORT1_DIS;
break;
case PCI_DEVFN(PCIE_PORT2_DEV, PCIE_PORT2_FUNC):
mask |= PCIE_PORT2_DIS;
break;
case PCI_DEVFN(PCIE_PORT3_DEV, PCIE_PORT3_FUNC):
mask |= PCIE_PORT3_DIS;
break;
case PCI_DEVFN(PCIE_PORT4_DEV, PCIE_PORT4_FUNC):
mask |= PCIE_PORT4_DIS;
break;
case PCI_DEVFN(EHCI_DEV, EHCI_FUNC):
mask |= EHCI_DIS;
break;
case PCI_DEVFN(SIO_DMA2_DEV, SIO_DMA2_FUNC):
mask |= SIO_DMA2_DIS;
break;
case PCI_DEVFN(PWM1_DEV, PWM1_FUNC):
mask |= PWM1_DIS;
break;
case PCI_DEVFN(PWM2_DEV, PWM2_FUNC):
mask |= PWM2_DIS;
break;
case PCI_DEVFN(HSUART1_DEV, HSUART1_FUNC):
mask |= HSUART1_DIS;
break;
case PCI_DEVFN(HSUART2_DEV, HSUART2_FUNC):
mask |= HSUART2_DIS;
break;
case PCI_DEVFN(SPI_DEV, SPI_FUNC):
mask |= SPI_DIS;
break;
case PCI_DEVFN(SMBUS_DEV, SMBUS_FUNC):
mask2 |= SMBUS_DIS;
break;
}
if (mask != 0) {
write32(func_dis, read32(func_dis) | mask);
/* Ensure posted write hits. */
read32(func_dis);
}
if (mask2 != 0) {
write32(func_dis2, read32(func_dis2) | mask2);
/* Ensure posted write hits. */
read32(func_dis2);
}
}
static inline void set_d3hot_bits(device_t dev, int offset)
{
uint32_t reg8;
printk(BIOS_DEBUG, "Power management CAP offset 0x%x.\n", offset);
reg8 = pci_read_config8(dev, offset + 4);
reg8 |= 0x3;
pci_write_config8(dev, offset + 4, reg8);
}
/* Parts of the audio subsystem are powered by the HDA device. Therefore, one
* cannot put HDA into D3Hot. Instead perform this workaround to make some of
* the audio paths work for LPE audio. */
static void hda_work_around(device_t dev)
{
u32 *gctl = (u32 *)(TEMP_BASE_ADDRESS + 0x8);
/* Need to set magic register 0x43 to 0xd7 in config space. */
pci_write_config8(dev, 0x43, 0xd7);
/* Need to set bit 0 of GCTL to take the device out of reset. However,
* that requires setting up the 64-bit BAR. */
pci_write_config32(dev, PCI_BASE_ADDRESS_0, TEMP_BASE_ADDRESS);
pci_write_config32(dev, PCI_BASE_ADDRESS_1, 0);
pci_write_config8(dev, PCI_COMMAND, PCI_COMMAND_MEMORY);
write32(gctl, read32(gctl) | 0x1);
pci_write_config8(dev, PCI_COMMAND, 0);
pci_write_config32(dev, PCI_BASE_ADDRESS_0, 0);
}
static int place_device_in_d3hot(device_t dev)
{
unsigned offset;
/* Parts of the HDA block are used for LPE audio as well.
* Therefore assume the HDA will never be put into D3Hot. */
if (dev->path.pci.devfn == PCI_DEVFN(HDA_DEV, HDA_FUNC)) {
hda_work_around(dev);
return 0;
}
offset = pci_find_capability(dev, PCI_CAP_ID_PM);
if (offset != 0) {
set_d3hot_bits(dev, offset);
return 0;
}
/* For some reason some of the devices don't have the capability
* pointer set correctly. Work around this by hard coding the offset. */
switch (dev->path.pci.devfn) {
case PCI_DEVFN(SDIO_DEV, SDIO_FUNC):
offset = 0x80;
break;
case PCI_DEVFN(SD_DEV, SD_FUNC):
offset = 0x80;
break;
case PCI_DEVFN(MMC_DEV, MMC_FUNC):
offset = 0x80;
break;
case PCI_DEVFN(LPE_DEV, LPE_FUNC):
offset = 0x80;
break;
case PCI_DEVFN(SIO_DMA1_DEV, SIO_DMA1_FUNC):
offset = 0x80;
break;
case PCI_DEVFN(I2C1_DEV, I2C1_FUNC):
offset = 0x80;
break;
case PCI_DEVFN(I2C2_DEV, I2C2_FUNC):
offset = 0x80;
break;
case PCI_DEVFN(I2C3_DEV, I2C3_FUNC):
offset = 0x80;
break;
case PCI_DEVFN(I2C4_DEV, I2C4_FUNC):
offset = 0x80;
break;
case PCI_DEVFN(I2C5_DEV, I2C5_FUNC):
offset = 0x80;
break;
case PCI_DEVFN(I2C6_DEV, I2C6_FUNC):
offset = 0x80;
break;
case PCI_DEVFN(I2C7_DEV, I2C7_FUNC):
offset = 0x80;
break;
case PCI_DEVFN(SIO_DMA2_DEV, SIO_DMA2_FUNC):
offset = 0x80;
break;
case PCI_DEVFN(PWM1_DEV, PWM1_FUNC):
offset = 0x80;
break;
case PCI_DEVFN(PWM2_DEV, PWM2_FUNC):
offset = 0x80;
break;
case PCI_DEVFN(HSUART1_DEV, HSUART1_FUNC):
offset = 0x80;
break;
case PCI_DEVFN(HSUART2_DEV, HSUART2_FUNC):
offset = 0x80;
break;
case PCI_DEVFN(SPI_DEV, SPI_FUNC):
offset = 0x80;
break;
case PCI_DEVFN(SATA_DEV, SATA_FUNC):
offset = 0x70;
break;
case PCI_DEVFN(XHCI_DEV, XHCI_FUNC):
offset = 0x70;
break;
case PCI_DEVFN(EHCI_DEV, EHCI_FUNC):
offset = 0x70;
break;
case PCI_DEVFN(HDA_DEV, HDA_FUNC):
offset = 0x50;
break;
case PCI_DEVFN(SMBUS_DEV, SMBUS_FUNC):
offset = 0x50;
break;
case PCI_DEVFN(TXE_DEV, TXE_FUNC):
/* TXE cannot be placed in D3Hot. */
return 0;
case PCI_DEVFN(PCIE_PORT1_DEV, PCIE_PORT1_FUNC):
offset = 0xa0;
break;
case PCI_DEVFN(PCIE_PORT2_DEV, PCIE_PORT2_FUNC):
offset = 0xa0;
break;
case PCI_DEVFN(PCIE_PORT3_DEV, PCIE_PORT3_FUNC):
offset = 0xa0;
break;
case PCI_DEVFN(PCIE_PORT4_DEV, PCIE_PORT4_FUNC):
offset = 0xa0;
break;
}
if (offset != 0) {
set_d3hot_bits(dev, offset);
return 0;
}
return -1;
}
/* Common PCI device function disable. */
void southcluster_enable_dev(device_t dev)
{
uint32_t reg32;
if (!dev->enabled) {
int slot = PCI_SLOT(dev->path.pci.devfn);
int func = PCI_FUNC(dev->path.pci.devfn);
printk(BIOS_DEBUG, "%s: Disabling device: %02x.%01x\n",
dev_path(dev), slot, func);
/* 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);
/* Place device in D3Hot */
if (place_device_in_d3hot(dev) < 0) {
printk(BIOS_WARNING,
"Could not place %02x.%01x into D3Hot. "
"Keeping device visible.\n", slot, func);
return;
}
/* Disable this device if possible */
sc_disable_devfn(dev);
} else {
/* Enable SERR */
reg32 = pci_read_config32(dev, PCI_COMMAND);
reg32 |= PCI_COMMAND_SERR;
pci_write_config32(dev, PCI_COMMAND, reg32);
}
}
static struct device_operations device_ops = {
.read_resources = sc_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = NULL,
.init = sc_init,
.enable = southcluster_enable_dev,
.scan_bus = scan_static_bus,
.ops_pci = &soc_pci_ops,
};
static const struct pci_driver southcluster __pci_driver = {
.ops = &device_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.device = LPC_DEVID,
};
int __attribute__((weak)) mainboard_get_spi_config(struct spi_config *cfg)
{
return -1;
}
static void finalize_chipset(void *unused)
{
u32 *bcr = (u32 *)(SPI_BASE_ADDRESS + BCR);
u32 *gcs = (u32 *)(RCBA_BASE_ADDRESS + GCS);
u32 *gen_pmcon2 = (u32 *)(PMC_BASE_ADDRESS + GEN_PMCON2);
u32 *etr = (u32 *)(PMC_BASE_ADDRESS + ETR);
u8 *spi = (u8 *)SPI_BASE_ADDRESS;
struct spi_config cfg;
/* Set the lock enable on the BIOS control register. */
write32(bcr, read32(bcr) | BCR_LE);
/* Set BIOS lock down bit controlling boot block size and swapping. */
write32(gcs, read32(gcs) | BILD);
/* Lock sleep stretching policy and set SMI lock. */
write32(gen_pmcon2, read32(gen_pmcon2) | SLPSX_STR_POL_LOCK | SMI_LOCK);
/* Set the CF9 lock. */
write32(etr, read32(etr) | CF9LOCK);
if (mainboard_get_spi_config(&cfg) < 0) {
printk(BIOS_DEBUG, "No SPI lockdown configuration.\n");
} else {
write16(spi + PREOP, cfg.preop);
write16(spi + OPTYPE, cfg.optype);
write32(spi + OPMENU0, cfg.opmenu[0]);
write32(spi + OPMENU1, cfg.opmenu[1]);
write16(spi + HSFSTS, read16(spi + HSFSTS) | FLOCKDN);
write32(spi + UVSCC, cfg.uvscc);
write32(spi + LVSCC, cfg.lvscc | VCL);
}
printk(BIOS_DEBUG, "Finalizing SMM.\n");
outb(APM_CNT_FINALIZE, APM_CNT);
}
BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, finalize_chipset, NULL);
BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, finalize_chipset, NULL);

View File

@ -0,0 +1,647 @@
/*
* Copyright (c) 2013 Google Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/* This file is derived from the flashrom project. */
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <bootstate.h>
#include <delay.h>
#include <arch/io.h>
#include <console/console.h>
#include <device/pci_ids.h>
#include <spi_flash.h>
#include <soc/lpc.h>
#include <soc/pci_devs.h>
#ifdef __SMM__
#define pci_read_config_byte(dev, reg, targ)\
*(targ) = pci_read_config8(dev, reg)
#define pci_read_config_word(dev, reg, targ)\
*(targ) = pci_read_config16(dev, reg)
#define pci_read_config_dword(dev, reg, targ)\
*(targ) = pci_read_config32(dev, reg)
#define pci_write_config_byte(dev, reg, val)\
pci_write_config8(dev, reg, val)
#define pci_write_config_word(dev, reg, val)\
pci_write_config16(dev, reg, val)
#define pci_write_config_dword(dev, reg, val)\
pci_write_config32(dev, reg, val)
#else /* !__SMM__ */
#include <device/device.h>
#include <device/pci.h>
#define pci_read_config_byte(dev, reg, targ)\
*(targ) = pci_read_config8(dev, reg)
#define pci_read_config_word(dev, reg, targ)\
*(targ) = pci_read_config16(dev, reg)
#define pci_read_config_dword(dev, reg, targ)\
*(targ) = pci_read_config32(dev, reg)
#define pci_write_config_byte(dev, reg, val)\
pci_write_config8(dev, reg, val)
#define pci_write_config_word(dev, reg, val)\
pci_write_config16(dev, reg, val)
#define pci_write_config_dword(dev, reg, val)\
pci_write_config32(dev, reg, val)
#endif /* !__SMM__ */
typedef struct spi_slave ich_spi_slave;
static int ichspi_lock = 0;
typedef struct ich9_spi_regs {
uint32_t bfpr;
uint16_t hsfs;
uint16_t hsfc;
uint32_t faddr;
uint32_t _reserved0;
uint32_t fdata[16];
uint32_t frap;
uint32_t freg[5];
uint32_t _reserved1[3];
uint32_t pr[5];
uint32_t _reserved2[2];
uint8_t ssfs;
uint8_t ssfc[3];
uint16_t preop;
uint16_t optype;
uint8_t opmenu[8];
uint32_t bbar;
uint8_t _reserved3[12];
uint32_t fdoc;
uint32_t fdod;
uint8_t _reserved4[8];
uint32_t afc;
uint32_t lvscc;
uint32_t uvscc;
uint8_t _reserved5[4];
uint32_t fpb;
uint8_t _reserved6[28];
uint32_t srdl;
uint32_t srdc;
uint32_t srd;
} __attribute__((packed)) ich9_spi_regs;
typedef struct ich_spi_controller {
int locked;
uint8_t *opmenu;
int menubytes;
uint16_t *preop;
uint16_t *optype;
uint32_t *addr;
uint8_t *data;
unsigned databytes;
uint8_t *status;
uint16_t *control;
uint32_t *bbar;
} ich_spi_controller;
static ich_spi_controller cntlr;
enum {
SPIS_SCIP = 0x0001,
SPIS_GRANT = 0x0002,
SPIS_CDS = 0x0004,
SPIS_FCERR = 0x0008,
SSFS_AEL = 0x0010,
SPIS_LOCK = 0x8000,
SPIS_RESERVED_MASK = 0x7ff0,
SSFS_RESERVED_MASK = 0x7fe2
};
enum {
SPIC_SCGO = 0x000002,
SPIC_ACS = 0x000004,
SPIC_SPOP = 0x000008,
SPIC_DBC = 0x003f00,
SPIC_DS = 0x004000,
SPIC_SME = 0x008000,
SSFC_SCF_MASK = 0x070000,
SSFC_RESERVED = 0xf80000
};
enum {
HSFS_FDONE = 0x0001,
HSFS_FCERR = 0x0002,
HSFS_AEL = 0x0004,
HSFS_BERASE_MASK = 0x0018,
HSFS_BERASE_SHIFT = 3,
HSFS_SCIP = 0x0020,
HSFS_FDOPSS = 0x2000,
HSFS_FDV = 0x4000,
HSFS_FLOCKDN = 0x8000
};
enum {
HSFC_FGO = 0x0001,
HSFC_FCYCLE_MASK = 0x0006,
HSFC_FCYCLE_SHIFT = 1,
HSFC_FDBC_MASK = 0x3f00,
HSFC_FDBC_SHIFT = 8,
HSFC_FSMIE = 0x8000
};
enum {
SPI_OPCODE_TYPE_READ_NO_ADDRESS = 0,
SPI_OPCODE_TYPE_WRITE_NO_ADDRESS = 1,
SPI_OPCODE_TYPE_READ_WITH_ADDRESS = 2,
SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS = 3
};
#if CONFIG_DEBUG_SPI_FLASH
static u8 readb_(const void *addr)
{
u8 v = read8((unsigned long)addr);
printk(BIOS_DEBUG, "read %2.2x from %4.4x\n",
v, ((unsigned) addr & 0xffff) - 0xf020);
return v;
}
static u16 readw_(const void *addr)
{
u16 v = read16((unsigned long)addr);
printk(BIOS_DEBUG, "read %4.4x from %4.4x\n",
v, ((unsigned) addr & 0xffff) - 0xf020);
return v;
}
static u32 readl_(const void *addr)
{
u32 v = read32((unsigned long)addr);
printk(BIOS_DEBUG, "read %8.8x from %4.4x\n",
v, ((unsigned) addr & 0xffff) - 0xf020);
return v;
}
static void writeb_(u8 b, const void *addr)
{
write8(addr, b);
printk(BIOS_DEBUG, "wrote %2.2x to %4.4x\n",
b, ((unsigned) addr & 0xffff) - 0xf020);
}
static void writew_(u16 b, const void *addr)
{
write16(addr, b);
printk(BIOS_DEBUG, "wrote %4.4x to %4.4x\n",
b, ((unsigned) addr & 0xffff) - 0xf020);
}
static void writel_(u32 b, const void *addr)
{
write32(addr, b);
printk(BIOS_DEBUG, "wrote %8.8x to %4.4x\n",
b, ((unsigned) addr & 0xffff) - 0xf020);
}
#else /* CONFIG_DEBUG_SPI_FLASH ^^^ enabled vvv NOT enabled */
#define readb_(a) read8(a)
#define readw_(a) read16(a)
#define readl_(a) read32(a)
#define writeb_(val, addr) write8(addr, val)
#define writew_(val, addr) write16(addr, val)
#define writel_(val, addr) write32(addr, val)
#endif /* CONFIG_DEBUG_SPI_FLASH ^^^ NOT enabled */
static void write_reg(const void *value, void *dest, uint32_t size)
{
const uint8_t *bvalue = value;
uint8_t *bdest = dest;
while (size >= 4) {
writel_(*(const uint32_t *)bvalue, bdest);
bdest += 4; bvalue += 4; size -= 4;
}
while (size) {
writeb_(*bvalue, bdest);
bdest++; bvalue++; size--;
}
}
static void read_reg(const void *src, void *value, uint32_t size)
{
const uint8_t *bsrc = src;
uint8_t *bvalue = value;
while (size >= 4) {
*(uint32_t *)bvalue = readl_(bsrc);
bsrc += 4; bvalue += 4; size -= 4;
}
while (size) {
*bvalue = readb_(bsrc);
bsrc++; bvalue++; size--;
}
}
static void ich_set_bbar(uint32_t minaddr)
{
const uint32_t bbar_mask = 0x00ffff00;
uint32_t ichspi_bbar;
minaddr &= bbar_mask;
ichspi_bbar = readl_(cntlr.bbar) & ~bbar_mask;
ichspi_bbar |= minaddr;
writel_(ichspi_bbar, cntlr.bbar);
}
struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
{
ich_spi_slave *slave = malloc(sizeof(*slave));
if (!slave) {
printk(BIOS_DEBUG, "ICH SPI: Bad allocation\n");
return NULL;
}
memset(slave, 0, sizeof(*slave));
slave->bus = bus;
slave->cs = cs;
return slave;
}
static ich9_spi_regs *spi_regs(void)
{
device_t dev;
uint32_t sbase;
#ifdef __SMM__
dev = PCI_DEV(0, LPC_DEV, LPC_FUNC);
#else
dev = dev_find_slot(0, PCI_DEVFN(LPC_DEV, LPC_FUNC));
#endif
pci_read_config_dword(dev, SBASE, &sbase);
sbase &= ~0x1ff;
return (void *)sbase;
}
void spi_init(void)
{
ich9_spi_regs *ich9_spi = spi_regs();
ichspi_lock = readw_(&ich9_spi->hsfs) & HSFS_FLOCKDN;
cntlr.opmenu = ich9_spi->opmenu;
cntlr.menubytes = sizeof(ich9_spi->opmenu);
cntlr.optype = &ich9_spi->optype;
cntlr.addr = &ich9_spi->faddr;
cntlr.data = (uint8_t *)ich9_spi->fdata;
cntlr.databytes = sizeof(ich9_spi->fdata);
cntlr.status = &ich9_spi->ssfs;
cntlr.control = (uint16_t *)ich9_spi->ssfc;
cntlr.bbar = &ich9_spi->bbar;
cntlr.preop = &ich9_spi->preop;
ich_set_bbar(0);
}
#ifndef __SMM__
static void spi_init_cb(void *unused)
{
spi_init();
}
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, spi_init_cb, NULL);
#endif
int spi_claim_bus(struct spi_slave *slave)
{
/* Handled by ICH automatically. */
return 0;
}
void spi_release_bus(struct spi_slave *slave)
{
/* Handled by ICH automatically. */
}
typedef struct spi_transaction {
const uint8_t *out;
uint32_t bytesout;
uint8_t *in;
uint32_t bytesin;
uint8_t type;
uint8_t opcode;
uint32_t offset;
} spi_transaction;
static inline void spi_use_out(spi_transaction *trans, unsigned bytes)
{
trans->out += bytes;
trans->bytesout -= bytes;
}
static inline void spi_use_in(spi_transaction *trans, unsigned bytes)
{
trans->in += bytes;
trans->bytesin -= bytes;
}
static void spi_setup_type(spi_transaction *trans)
{
trans->type = 0xFF;
/* Try to guess spi type from read/write sizes. */
if (trans->bytesin == 0) {
if (trans->bytesout > 4)
/*
* If bytesin = 0 and bytesout > 4, we presume this is
* a write data operation, which is accompanied by an
* address.
*/
trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS;
else
trans->type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS;
return;
}
if (trans->bytesout == 1) { /* and bytesin is > 0 */
trans->type = SPI_OPCODE_TYPE_READ_NO_ADDRESS;
return;
}
if (trans->bytesout == 4) { /* and bytesin is > 0 */
trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
}
/* Fast read command is called with 5 bytes instead of 4 */
if (trans->out[0] == SPI_OPCODE_FAST_READ && trans->bytesout == 5) {
trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
--trans->bytesout;
}
}
static int spi_setup_opcode(spi_transaction *trans)
{
uint16_t optypes;
uint8_t opmenu[cntlr.menubytes];
trans->opcode = trans->out[0];
spi_use_out(trans, 1);
if (!ichspi_lock) {
/* The lock is off, so just use index 0. */
writeb_(trans->opcode, cntlr.opmenu);
optypes = readw_(cntlr.optype);
optypes = (optypes & 0xfffc) | (trans->type & 0x3);
writew_(optypes, cntlr.optype);
return 0;
} else {
/* The lock is on. See if what we need is on the menu. */
uint8_t optype;
uint16_t opcode_index;
/* Write Enable is handled as atomic prefix */
if (trans->opcode == SPI_OPCODE_WREN)
return 0;
read_reg(cntlr.opmenu, opmenu, sizeof(opmenu));
for (opcode_index = 0; opcode_index < cntlr.menubytes;
opcode_index++) {
if (opmenu[opcode_index] == trans->opcode)
break;
}
if (opcode_index == cntlr.menubytes) {
printk(BIOS_DEBUG, "ICH SPI: Opcode %x not found\n",
trans->opcode);
return -1;
}
optypes = readw_(cntlr.optype);
optype = (optypes >> (opcode_index * 2)) & 0x3;
if (trans->type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS &&
optype == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS &&
trans->bytesout >= 3) {
/* We guessed wrong earlier. Fix it up. */
trans->type = optype;
}
if (optype != trans->type) {
printk(BIOS_DEBUG, "ICH SPI: Transaction doesn't fit type %d\n",
optype);
return -1;
}
return opcode_index;
}
}
static int spi_setup_offset(spi_transaction *trans)
{
/* Separate the SPI address and data. */
switch (trans->type) {
case SPI_OPCODE_TYPE_READ_NO_ADDRESS:
case SPI_OPCODE_TYPE_WRITE_NO_ADDRESS:
return 0;
case SPI_OPCODE_TYPE_READ_WITH_ADDRESS:
case SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS:
trans->offset = ((uint32_t)trans->out[0] << 16) |
((uint32_t)trans->out[1] << 8) |
((uint32_t)trans->out[2] << 0);
spi_use_out(trans, 3);
return 1;
default:
printk(BIOS_DEBUG, "Unrecognized SPI transaction type %#x\n", trans->type);
return -1;
}
}
/*
* Wait for up to 60ms til status register bit(s) turn 1 (in case wait_til_set
* below is True) or 0. In case the wait was for the bit(s) to set - write
* those bits back, which would cause resetting them.
*
* Return the last read status value on success or -1 on failure.
*/
static int ich_status_poll(u16 bitmask, int wait_til_set)
{
int timeout = 40000; /* This will result in 400 ms */
u16 status = 0;
while (timeout--) {
status = readw_(cntlr.status);
if (wait_til_set ^ ((status & bitmask) == 0)) {
if (wait_til_set)
writew_((status & bitmask), cntlr.status);
return status;
}
udelay(10);
}
printk(BIOS_DEBUG, "ICH SPI: SCIP timeout, read %x, expected %x\n",
status, bitmask);
return -1;
}
unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
{
return min(cntlr.databytes, buf_len);
}
int spi_xfer(struct spi_slave *slave, const void *dout,
unsigned int bytesout, void *din, unsigned int bytesin)
{
uint16_t control;
int16_t opcode_index;
int with_address;
int status;
spi_transaction trans = {
dout, bytesout,
din, bytesin,
0xff, 0xff, 0
};
/* There has to always at least be an opcode. */
if (!bytesout || !dout) {
printk(BIOS_DEBUG, "ICH SPI: No opcode for transfer\n");
return -1;
}
/* Make sure if we read something we have a place to put it. */
if (bytesin != 0 && !din) {
printk(BIOS_DEBUG, "ICH SPI: Read but no target buffer\n");
return -1;
}
if (ich_status_poll(SPIS_SCIP, 0) == -1)
return -1;
writew_(SPIS_CDS | SPIS_FCERR, cntlr.status);
spi_setup_type(&trans);
if ((opcode_index = spi_setup_opcode(&trans)) < 0)
return -1;
if ((with_address = spi_setup_offset(&trans)) < 0)
return -1;
if (trans.opcode == SPI_OPCODE_WREN) {
/*
* Treat Write Enable as Atomic Pre-Op if possible
* in order to prevent the Management Engine from
* issuing a transaction between WREN and DATA.
*/
if (!ichspi_lock)
writew_(trans.opcode, cntlr.preop);
return 0;
}
/* Preset control fields */
control = SPIC_SCGO | ((opcode_index & 0x07) << 4);
/* Issue atomic preop cycle if needed */
if (readw_(cntlr.preop))
control |= SPIC_ACS;
if (!trans.bytesout && !trans.bytesin) {
/* SPI addresses are 24 bit only */
if (with_address)
writel_(trans.offset & 0x00FFFFFF, cntlr.addr);
/*
* This is a 'no data' command (like Write Enable), its
* bytesout size was 1, decremented to zero while executing
* spi_setup_opcode() above. Tell the chip to send the
* command.
*/
writew_(control, cntlr.control);
/* wait for the result */
status = ich_status_poll(SPIS_CDS | SPIS_FCERR, 1);
if (status == -1)
return -1;
if (status & SPIS_FCERR) {
printk(BIOS_DEBUG, "ICH SPI: Command transaction error\n");
return -1;
}
return 0;
}
/*
* Check if this is a write command attempting to transfer more bytes
* than the controller can handle. Iterations for writes are not
* supported here because each SPI write command needs to be preceded
* and followed by other SPI commands, and this sequence is controlled
* by the SPI chip driver.
*/
if (trans.bytesout > cntlr.databytes) {
printk(BIOS_DEBUG, "ICH SPI: Too much to write. Does your SPI chip driver use"
" spi_crop_chunk()?\n");
return -1;
}
/*
* Read or write up to databytes bytes at a time until everything has
* been sent.
*/
while (trans.bytesout || trans.bytesin) {
uint32_t data_length;
/* SPI addresses are 24 bit only */
writel_(trans.offset & 0x00FFFFFF, cntlr.addr);
if (trans.bytesout)
data_length = min(trans.bytesout, cntlr.databytes);
else
data_length = min(trans.bytesin, cntlr.databytes);
/* Program data into FDATA0 to N */
if (trans.bytesout) {
write_reg(trans.out, cntlr.data, data_length);
spi_use_out(&trans, data_length);
if (with_address)
trans.offset += data_length;
}
/* Add proper control fields' values */
control &= ~((cntlr.databytes - 1) << 8);
control |= SPIC_DS;
control |= (data_length - 1) << 8;
/* write it */
writew_(control, cntlr.control);
/* Wait for Cycle Done Status or Flash Cycle Error. */
status = ich_status_poll(SPIS_CDS | SPIS_FCERR, 1);
if (status == -1)
return -1;
if (status & SPIS_FCERR) {
printk(BIOS_DEBUG, "ICH SPI: Data transaction error\n");
return -1;
}
if (trans.bytesin) {
read_reg(cntlr.data, trans.in, data_length);
spi_use_in(&trans, data_length);
if (with_address)
trans.offset += data_length;
}
}
/* Clear atomic preop now that xfer is done */
writew_(0, cntlr.preop);
return 0;
}

View File

@ -0,0 +1,35 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 <stage_cache.h>
#include <soc/smm.h>
void stage_cache_external_region(void **base, size_t *size)
{
char *smm_base;
/* 1MiB cache size */
const long cache_size = CONFIG_SMM_RESERVED_SIZE;
/* Ramstage cache lives in TSEG region which is the definition of
* cbmem_top(). */
smm_base = cbmem_top();
*size = cache_size;
*base = &smm_base[smm_region_size() - cache_size];
}

View File

@ -0,0 +1,84 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 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 <cpu/x86/tsc.h>
#include <soc/msr.h>
unsigned bus_freq_khz(void)
{
msr_t clk_info = rdmsr(MSR_BSEL_CR_OVERCLOCK_CONTROL);
switch (clk_info.lo & 0x3) {
case 0:
return 83333;
case 1:
return 100000;
case 2:
return 133333;
case 3:
return 116666;
default:
return 0;
}
}
unsigned long tsc_freq_mhz(void)
{
msr_t platform_info;
unsigned bclk_khz = bus_freq_khz();
if (!bclk_khz)
return 0;
platform_info = rdmsr(MSR_PLATFORM_INFO);
return (bclk_khz * ((platform_info.lo >> 8) & 0xff)) / 1000;
}
#if !defined(__SMM__)
#if !defined(__PRE_RAM__)
#include <soc/ramstage.h>
#else
#include <soc/romstage.h>
#endif
void set_max_freq(void)
{
msr_t perf_ctl;
msr_t msr;
/* Enable speed step. */
msr = rdmsr(MSR_IA32_MISC_ENABLES);
msr.lo |= (1 << 16);
wrmsr(MSR_IA32_MISC_ENABLES, msr);
/* Set guaranteed ratio [21:16] from IACORE_RATIOS to bits [15:8] of
* the PERF_CTL. */
msr = rdmsr(MSR_IACORE_RATIOS);
perf_ctl.lo = (msr.lo & 0x3f0000) >> 8;
/* Set guaranteed vid [21:16] from IACORE_VIDS to bits [7:0] of
* the PERF_CTL. */
msr = rdmsr(MSR_IACORE_VIDS);
perf_ctl.lo |= (msr.lo & 0x7f0000) >> 16;
perf_ctl.hi = 0;
wrmsr(MSR_IA32_PERF_CTL, perf_ctl);
}
#endif /* __SMM__ */

View File

@ -0,0 +1,259 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2013 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 <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <stdint.h>
#include <reg_script.h>
#include <soc/iomap.h>
#include <soc/iosf.h>
#include <soc/lpc.h>
#include <soc/pattrs.h>
#include <soc/pci_devs.h>
#include <soc/pmc.h>
#include <soc/ramstage.h>
#include <soc/xhci.h>
#include "chip.h"
struct reg_script usb3_phy_script[] = {
/* USB3PHYInit() */
REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CDN_PLL_CONTROL,
~0x00700000, 0x00500000),
REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CDN_VCO_START_CAL_POINT,
~0x001f0000, 0x000A0000),
REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CCDRLF,
~0x0000000f, 0x0000000b),
REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_PEAKING_AMP_CONFIG_DIAG,
~0x000000f0, 0x000000f0),
REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_OFFSET_COR_CONFIG_DIAG,
~0x000001c0, 0x00000000),
REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_VGA_GAIN_CONFIG_DIAG,
~0x00000070, 0x00000020),
REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_REE_DAC_CONTROL,
~0x00000002, 0x00000002),
REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CDN_U1_POWER_STATE_DEF,
~0x00000000, 0x00040000),
REG_SCRIPT_END
};
const struct reg_script xhci_init_script[] = {
/* CommonXhciHcInit() */
/* BAR + 0x0c[31:16] = 0x0200 */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x000c, 0x0000ffff, 0x02000000),
/* BAR + 0x0c[7:0] = 0x0a */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x000c, 0xffffff00, 0x0000000a),
/* BAR + 0x8094[23,21,14]=111b */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8094, 0x00a04000),
/* BAR + 0x8110[20,11,8,2]=1100b */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8110, ~0x00000104, 0x00100800),
/* BAR + 0x8144[8,7,6]=111b */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8144, 0x000001c0),
/* BAR + 0x8154[21,13,3]=010b */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8154, ~0x00200008, 0x80002000),
/* BAR + 0x816c[19:0]=1110x100000000111100b */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x816c, 0xfff08000, 0x000e0030),
/* BAR + 0x8188[26,24]=11b */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8188, 0x05000000),
/* BAR + 0x8174=0x1000c0a*/
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8174, 0xfe000000, 0x01000c0a),
/* BAR + 0x854c[29]=0b */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x854c, ~0x20000000, 0),
/* BAR + 0x8178[12:0]=0b */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8178, ~0xffffe000, 0),
/* BAR + 0x8164[7:0]=0xff */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8164, 0x000000ff),
/* BAR + 0x0010[10,9,5]=110b */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x0010, ~0x00000020, 0x00000600),
/* BAR + 0x8058[20,16,8]=110b */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8058, ~0x00000100, 0x00110000),
/* BAR + 0x8060[25]=1b */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8060, 0x02000000),
/* BAR + 0x80f0[20]=0b */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80f0, ~0x00100000, 0),
/* BAR + 0x8008[19]=1b (to enable LPM) */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8008, 0x00080000),
/* BAR + 0x80fc[25]=1b */
REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x80fc, 0x02000000),
/* 0x40/0x44 are written as bytes to avoid touching bit31 */
/* D20:F0:40[21,20,18,10,9,8]=111001b (don't write byte3) */
REG_PCI_RMW8(0x41, ~0x06, 0x01),
/* Except [21,20,19,18]=0001b USB wake W/A is disable IIL1E */
REG_PCI_RMW8(0x42, 0x3c, 0x04),
/* D20:F0:44[19:14,10,9,7,3:0]=1 (don't write byte3) */
REG_PCI_RMW8(0x44, 0x00, 0x8f),
REG_PCI_RMW8(0x45, ~0xcf, 0xc6),
REG_PCI_RMW8(0x46, ~0x0f, 0x0f),
/* BAR + 0x8140 = 0xff00f03c */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8140, 0, 0xff00f03c),
REG_SCRIPT_END
};
const struct reg_script xhci_init_boot_script[] = {
/* Setup USB3 phy */
REG_SCRIPT_NEXT(usb3_phy_script),
/* Initialize host controller */
REG_SCRIPT_NEXT(xhci_init_script),
/* BAR + 0x80e0[16,9,6]=001b, toggle bit 24=1 */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80e0, ~0x00010200, 0x01000040),
/* BAR + 0x80e0 toggle bit 24=0 */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80e0, ~0x01000000, 0),
REG_SCRIPT_END
};
const struct reg_script xhci_init_resume_script[] = {
/* Setup USB3 phy */
REG_SCRIPT_NEXT(usb3_phy_script),
/* Initialize host controller */
REG_SCRIPT_NEXT(xhci_init_script),
/* BAR + 0x80e0[16,9,6]=001b, leave bit 24=0 to prevent HC reset */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80e0, ~0x01010200, 0x00000040),
REG_SCRIPT_END
};
const struct reg_script xhci_clock_gating_script[] = {
/* ConfigureXhciClockGating() */
/* D20:F0:40[21:19,18,10:8]=000,1,001 (don't write byte 3) */
REG_PCI_RMW16(0x40, ~0x0600, 0x0100),
REG_PCI_RMW8(0x42, ~0x38, 0x04),
/* D20:F0:44[5:3]=001b */
REG_PCI_RMW16(0x44, ~0x0030, 0x0008),
/* D20:F0:A0[19:18]=01b */
REG_PCI_RMW32(0xa0, ~0x00080000, 0x00040000),
/* D20:F0:A4[15:0]=0x00 */
REG_PCI_WRITE16(0xa4, 0x0000),
/* D20:F0:B0[21:17,14:13]=0000000b */
REG_PCI_RMW32(0xb0, ~0x00376000, 0x00000000),
/* D20:F0:50[31:0]=0x0bce6e5f */
REG_PCI_WRITE32(0x50, 0x0bce6e5f),
REG_SCRIPT_END
};
/* Warm Reset a USB3 port */
static void xhci_reset_port_usb3(device_t dev, int port)
{
struct reg_script reset_port_usb3_script[] = {
/* Issue Warm Port Rest to the port */
REG_RES_OR32(PCI_BASE_ADDRESS_0, XHCI_USB3_PORTSC(port),
XHCI_USB3_PORTSC_WPR),
/* Wait up to 100ms for it to complete */
REG_RES_POLL32(PCI_BASE_ADDRESS_0, XHCI_USB3_PORTSC(port),
XHCI_USB3_PORTSC_WRC, XHCI_USB3_PORTSC_WRC,
XHCI_RESET_TIMEOUT),
/* Clear change status bits, do not set PED */
REG_RES_RMW32(PCI_BASE_ADDRESS_0, XHCI_USB3_PORTSC(port),
~XHCI_USB3_PORTSC_PED, XHCI_USB3_PORTSC_CHST),
REG_SCRIPT_END
};
reg_script_run_on_dev(dev, reset_port_usb3_script);
}
/* Prepare ports to be routed to EHCI or XHCI */
static void xhci_route_all(device_t dev)
{
static const struct reg_script xhci_route_all_script[] = {
/* USB3 SuperSpeed Enable */
REG_PCI_WRITE32(XHCI_USB3PR, BYTM_USB3_PORT_MAP),
/* USB2 Port Route to XHCI */
REG_PCI_WRITE32(XHCI_USB2PR, BYTM_USB2_PORT_MAP),
REG_SCRIPT_END
};
u32 port_disabled;
int port;
printk(BIOS_INFO, "USB: Route ports to XHCI controller\n");
/* Route ports to XHCI controller */
reg_script_run_on_dev(dev, xhci_route_all_script);
if (acpi_is_wakeup_s3())
return;
/* Reset enabled USB3 ports */
port_disabled = pci_read_config32(dev, XHCI_USB3PDO);
for (port = 0; port < BYTM_USB3_PORT_COUNT; port++) {
if (port_disabled & (1 << port))
continue;
xhci_reset_port_usb3(dev, port);
}
}
static void xhci_init(device_t dev)
{
struct soc_intel_baytrail_config *config = dev->chip_info;
struct reg_script xhci_hc_init[] = {
/* Initialize clock gating */
REG_SCRIPT_NEXT(xhci_clock_gating_script),
/* Finalize XHCC1 and XHCC2 */
REG_PCI_RMW32(0x44, ~0x00000000, 0x83c00000),
REG_PCI_RMW32(0x40, ~0x00800000, 0x80000000),
/* Set USB2 Port Routing Mask */
REG_PCI_WRITE32(XHCI_USB2PRM, BYTM_USB2_PORT_MAP),
/* Set USB3 Port Routing Mask */
REG_PCI_WRITE32(XHCI_USB3PRM, BYTM_USB3_PORT_MAP),
/*
* Disable ports if requested
*/
/* Open per-port disable control override */
REG_IO_RMW16(ACPI_BASE_ADDRESS + UPRWC, ~0, UPRWC_WR_EN),
REG_PCI_WRITE32(XHCI_USB2PDO, config->usb2_port_disable_mask),
REG_PCI_WRITE32(XHCI_USB3PDO, config->usb3_port_disable_mask),
/* Close per-port disable control override */
REG_IO_RMW16(ACPI_BASE_ADDRESS + UPRWC, ~UPRWC_WR_EN, 0),
REG_SCRIPT_END
};
/* Initialize XHCI controller for boot or resume path */
if (acpi_is_wakeup_s3())
reg_script_run_on_dev(dev, xhci_init_resume_script);
else
reg_script_run_on_dev(dev, xhci_init_boot_script);
/* C0 steppings change iCLK/USB PLL VCO settings from 5 to 7 */
if (pattrs_get()->stepping == STEP_C0) {
uint32_t reg = iosf_ushphy_read(USHPHY_CDN_PLL_CONTROL);
reg |= 0x00700000;
iosf_ushphy_write(USHPHY_CDN_PLL_CONTROL, reg);
}
/* Finalize Initialization */
reg_script_run_on_dev(dev, xhci_hc_init);
/* Route all ports to XHCI if requested */
if (config->usb_route_to_xhci)
xhci_route_all(dev);
}
static struct device_operations xhci_device_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = xhci_init,
.ops_pci = &soc_pci_ops,
};
static const struct pci_driver baytrail_xhci __pci_driver = {
.ops = &xhci_device_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.device = XHCI_DEVID
};