Leroy P Leahy (leroy.p.leahy@intel.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/10117
-gerrit
commit 0fcf17cc5615e5202857b910cca3ff2051209d59 Author: Lee Leahy leroy.p.leahy@intel.com Date: Tue May 5 15:07:29 2015 -0700
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 --- src/soc/intel/braswell/Kconfig | 245 ++++++++ src/soc/intel/braswell/Makefile.inc | 107 ++++ src/soc/intel/braswell/acpi.c | 511 ++++++++++++++++ src/soc/intel/braswell/acpi/cpu.asl | 77 +++ src/soc/intel/braswell/acpi/device_nvs.asl | 87 +++ src/soc/intel/braswell/acpi/dptf/charger.asl | 59 ++ src/soc/intel/braswell/acpi/dptf/cpu.asl | 144 +++++ src/soc/intel/braswell/acpi/dptf/dptf.asl | 78 +++ src/soc/intel/braswell/acpi/dptf/thermal.asl | 203 ++++++ src/soc/intel/braswell/acpi/globalnvs.asl | 108 ++++ src/soc/intel/braswell/acpi/gpio.asl | 110 ++++ src/soc/intel/braswell/acpi/irq_helper.h | 48 ++ src/soc/intel/braswell/acpi/irqlinks.asl | 492 +++++++++++++++ src/soc/intel/braswell/acpi/irqroute.asl | 37 ++ src/soc/intel/braswell/acpi/lpc.asl | 167 +++++ src/soc/intel/braswell/acpi/lpe.asl | 119 ++++ src/soc/intel/braswell/acpi/lpss.asl | 712 ++++++++++++++++++++++ src/soc/intel/braswell/acpi/pcie.asl | 109 ++++ src/soc/intel/braswell/acpi/platform.asl | 78 +++ src/soc/intel/braswell/acpi/scc.asl | 187 ++++++ src/soc/intel/braswell/acpi/sleepstates.asl | 26 + src/soc/intel/braswell/acpi/southcluster.asl | 274 +++++++++ src/soc/intel/braswell/acpi/xhci.asl | 36 ++ src/soc/intel/braswell/bootblock/Makefile.inc | 1 + src/soc/intel/braswell/bootblock/bootblock.c | 79 +++ src/soc/intel/braswell/bootblock/timestamp.inc | 18 + src/soc/intel/braswell/chip.c | 93 +++ src/soc/intel/braswell/chip.h | 95 +++ src/soc/intel/braswell/cpu.c | 309 ++++++++++ src/soc/intel/braswell/dptf.c | 52 ++ src/soc/intel/braswell/ehci.c | 181 ++++++ src/soc/intel/braswell/elog.c | 122 ++++ src/soc/intel/braswell/emmc.c | 77 +++ src/soc/intel/braswell/gfx.c | 398 ++++++++++++ src/soc/intel/braswell/gpio.c | 245 ++++++++ src/soc/intel/braswell/hda.c | 118 ++++ src/soc/intel/braswell/include/soc/acpi.h | 31 + src/soc/intel/braswell/include/soc/device_nvs.h | 68 +++ src/soc/intel/braswell/include/soc/efi_wrapper.h | 52 ++ src/soc/intel/braswell/include/soc/ehci.h | 44 ++ src/soc/intel/braswell/include/soc/gfx.h | 64 ++ src/soc/intel/braswell/include/soc/gpio.h | 459 ++++++++++++++ src/soc/intel/braswell/include/soc/iomap.h | 90 +++ src/soc/intel/braswell/include/soc/iosf.h | 349 +++++++++++ src/soc/intel/braswell/include/soc/irq.h | 164 +++++ src/soc/intel/braswell/include/soc/lpc.h | 54 ++ src/soc/intel/braswell/include/soc/mrc_wrapper.h | 107 ++++ src/soc/intel/braswell/include/soc/msr.h | 51 ++ src/soc/intel/braswell/include/soc/nvs.h | 78 +++ src/soc/intel/braswell/include/soc/pattrs.h | 64 ++ src/soc/intel/braswell/include/soc/pci_devs.h | 155 +++++ src/soc/intel/braswell/include/soc/pcie.h | 102 ++++ src/soc/intel/braswell/include/soc/pmc.h | 303 +++++++++ src/soc/intel/braswell/include/soc/ramstage.h | 42 ++ src/soc/intel/braswell/include/soc/reset.h | 36 ++ src/soc/intel/braswell/include/soc/romstage.h | 54 ++ src/soc/intel/braswell/include/soc/sata.h | 26 + src/soc/intel/braswell/include/soc/smm.h | 49 ++ src/soc/intel/braswell/include/soc/spi.h | 74 +++ src/soc/intel/braswell/include/soc/xhci.h | 56 ++ src/soc/intel/braswell/iosf.c | 287 +++++++++ src/soc/intel/braswell/lpe.c | 189 ++++++ src/soc/intel/braswell/lpss.c | 206 +++++++ src/soc/intel/braswell/memmap.c | 33 + src/soc/intel/braswell/microcode/Makefile.inc | 1 + src/soc/intel/braswell/microcode/microcode_blob.c | 3 + src/soc/intel/braswell/northcluster.c | 148 +++++ src/soc/intel/braswell/pcie.c | 278 +++++++++ src/soc/intel/braswell/perf_power.c | 292 +++++++++ src/soc/intel/braswell/placeholders.c | 11 + src/soc/intel/braswell/pmutil.c | 364 +++++++++++ src/soc/intel/braswell/ramstage.c | 206 +++++++ src/soc/intel/braswell/refcode.c | 148 +++++ src/soc/intel/braswell/reset.c | 47 ++ src/soc/intel/braswell/romstage/Makefile.inc | 7 + src/soc/intel/braswell/romstage/cache_as_ram.inc | 285 +++++++++ src/soc/intel/braswell/romstage/early_spi.c | 65 ++ src/soc/intel/braswell/romstage/gfx.c | 50 ++ src/soc/intel/braswell/romstage/pmc.c | 81 +++ src/soc/intel/braswell/romstage/raminit.c | 191 ++++++ src/soc/intel/braswell/romstage/romstage.c | 377 ++++++++++++ src/soc/intel/braswell/romstage/uart.c | 38 ++ src/soc/intel/braswell/sata.c | 240 ++++++++ src/soc/intel/braswell/scc.c | 125 ++++ src/soc/intel/braswell/sd.c | 70 +++ src/soc/intel/braswell/smihandler.c | 483 +++++++++++++++ src/soc/intel/braswell/smm.c | 133 ++++ src/soc/intel/braswell/southcluster.c | 572 +++++++++++++++++ src/soc/intel/braswell/spi.c | 647 ++++++++++++++++++++ src/soc/intel/braswell/stage_cache.c | 35 ++ src/soc/intel/braswell/tsc_freq.c | 84 +++ src/soc/intel/braswell/xhci.c | 259 ++++++++ 92 files changed, 14329 insertions(+)
diff --git a/src/soc/intel/braswell/Kconfig b/src/soc/intel/braswell/Kconfig new file mode 100644 index 0000000..0b3e176 --- /dev/null +++ b/src/soc/intel/braswell/Kconfig @@ -0,0 +1,245 @@ +config SOC_INTEL_BAYTRAIL + bool + help + Bay Trail M/D part support. + +if SOC_INTEL_BAYTRAIL + +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 diff --git a/src/soc/intel/braswell/Makefile.inc b/src/soc/intel/braswell/Makefile.inc new file mode 100644 index 0000000..78e2da6 --- /dev/null +++ b/src/soc/intel/braswell/Makefile.inc @@ -0,0 +1,107 @@ +ifeq ($(CONFIG_SOC_INTEL_BAYTRAIL),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 diff --git a/src/soc/intel/braswell/acpi.c b/src/soc/intel/braswell/acpi.c new file mode 100644 index 0000000..74e7336 --- /dev/null +++ b/src/soc/intel/braswell/acpi.c @@ -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; +} diff --git a/src/soc/intel/braswell/acpi/cpu.asl b/src/soc/intel/braswell/acpi/cpu.asl new file mode 100644 index 0000000..f7e404d --- /dev/null +++ b/src/soc/intel/braswell/acpi/cpu.asl @@ -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}) + } +} diff --git a/src/soc/intel/braswell/acpi/device_nvs.asl b/src/soc/intel/braswell/acpi/device_nvs.asl new file mode 100644 index 0000000..fce7b53 --- /dev/null +++ b/src/soc/intel/braswell/acpi/device_nvs.asl @@ -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 diff --git a/src/soc/intel/braswell/acpi/dptf/charger.asl b/src/soc/intel/braswell/acpi/dptf/charger.asl new file mode 100644 index 0000000..7c7f62f --- /dev/null +++ b/src/soc/intel/braswell/acpi/dptf/charger.asl @@ -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 () + } +} diff --git a/src/soc/intel/braswell/acpi/dptf/cpu.asl b/src/soc/intel/braswell/acpi/dptf/cpu.asl new file mode 100644 index 0000000..58c1c7b --- /dev/null +++ b/src/soc/intel/braswell/acpi/dptf/cpu.asl @@ -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 +} diff --git a/src/soc/intel/braswell/acpi/dptf/dptf.asl b/src/soc/intel/braswell/acpi/dptf/dptf.asl new file mode 100644 index 0000000..9ebfb8c --- /dev/null +++ b/src/soc/intel/braswell/acpi/dptf/dptf.asl @@ -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 +} diff --git a/src/soc/intel/braswell/acpi/dptf/thermal.asl b/src/soc/intel/braswell/acpi/dptf/thermal.asl new file mode 100644 index 0000000..7113215 --- /dev/null +++ b/src/soc/intel/braswell/acpi/dptf/thermal.asl @@ -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 diff --git a/src/soc/intel/braswell/acpi/globalnvs.asl b/src/soc/intel/braswell/acpi/globalnvs.asl new file mode 100644 index 0000000..a201c03 --- /dev/null +++ b/src/soc/intel/braswell/acpi/globalnvs.asl @@ -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) +} diff --git a/src/soc/intel/braswell/acpi/gpio.asl b/src/soc/intel/braswell/acpi/gpio.asl new file mode 100644 index 0000000..aa6af71 --- /dev/null +++ b/src/soc/intel/braswell/acpi/gpio.asl @@ -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) + } +} diff --git a/src/soc/intel/braswell/acpi/irq_helper.h b/src/soc/intel/braswell/acpi/irq_helper.h new file mode 100644 index 0000000..b19895b --- /dev/null +++ b/src/soc/intel/braswell/acpi/irq_helper.h @@ -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" diff --git a/src/soc/intel/braswell/acpi/irqlinks.asl b/src/soc/intel/braswell/acpi/irqlinks.asl new file mode 100644 index 0000000..21f1ada --- /dev/null +++ b/src/soc/intel/braswell/acpi/irqlinks.asl @@ -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) + } + } +} diff --git a/src/soc/intel/braswell/acpi/irqroute.asl b/src/soc/intel/braswell/acpi/irqroute.asl new file mode 100644 index 0000000..23987d7 --- /dev/null +++ b/src/soc/intel/braswell/acpi/irqroute.asl @@ -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 + }) + } +} diff --git a/src/soc/intel/braswell/acpi/lpc.asl b/src/soc/intel/braswell/acpi/lpc.asl new file mode 100644 index 0000000..408d2b4 --- /dev/null +++ b/src/soc/intel/braswell/acpi/lpc.asl @@ -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 +} diff --git a/src/soc/intel/braswell/acpi/lpe.asl b/src/soc/intel/braswell/acpi/lpe.asl new file mode 100644 index 0000000..dfa555c --- /dev/null +++ b/src/soc/intel/braswell/acpi/lpe.asl @@ -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) + } + } +} diff --git a/src/soc/intel/braswell/acpi/lpss.asl b/src/soc/intel/braswell/acpi/lpss.asl new file mode 100644 index 0000000..0f8f746 --- /dev/null +++ b/src/soc/intel/braswell/acpi/lpss.asl @@ -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) + } +} diff --git a/src/soc/intel/braswell/acpi/pcie.asl b/src/soc/intel/braswell/acpi/pcie.asl new file mode 100644 index 0000000..5ad4e78 --- /dev/null +++ b/src/soc/intel/braswell/acpi/pcie.asl @@ -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) + }) + } + } +} diff --git a/src/soc/intel/braswell/acpi/platform.asl b/src/soc/intel/braswell/acpi/platform.asl new file mode 100644 index 0000000..e32880e --- /dev/null +++ b/src/soc/intel/braswell/acpi/platform.asl @@ -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) +} diff --git a/src/soc/intel/braswell/acpi/scc.asl b/src/soc/intel/braswell/acpi/scc.asl new file mode 100644 index 0000000..7181fb1 --- /dev/null +++ b/src/soc/intel/braswell/acpi/scc.asl @@ -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) + } +} diff --git a/src/soc/intel/braswell/acpi/sleepstates.asl b/src/soc/intel/braswell/acpi/sleepstates.asl new file mode 100644 index 0000000..8abeb2d --- /dev/null +++ b/src/soc/intel/braswell/acpi/sleepstates.asl @@ -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}) diff --git a/src/soc/intel/braswell/acpi/southcluster.asl b/src/soc/intel/braswell/acpi/southcluster.asl new file mode 100644 index 0000000..9092562 --- /dev/null +++ b/src/soc/intel/braswell/acpi/southcluster.asl @@ -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" +} diff --git a/src/soc/intel/braswell/acpi/xhci.asl b/src/soc/intel/braswell/acpi/xhci.asl new file mode 100644 index 0000000..4d5367a --- /dev/null +++ b/src/soc/intel/braswell/acpi/xhci.asl @@ -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) } + } +} diff --git a/src/soc/intel/braswell/bootblock/Makefile.inc b/src/soc/intel/braswell/bootblock/Makefile.inc new file mode 100644 index 0000000..3a40251 --- /dev/null +++ b/src/soc/intel/braswell/bootblock/Makefile.inc @@ -0,0 +1 @@ +chipset_bootblock_inc += $(src)/soc/intel/baytrail/bootblock/timestamp.inc diff --git a/src/soc/intel/braswell/bootblock/bootblock.c b/src/soc/intel/braswell/bootblock/bootblock.c new file mode 100644 index 0000000..9d7f19c --- /dev/null +++ b/src/soc/intel/braswell/bootblock/bootblock.c @@ -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(); +} diff --git a/src/soc/intel/braswell/bootblock/timestamp.inc b/src/soc/intel/braswell/bootblock/timestamp.inc new file mode 100644 index 0000000..3db5c35 --- /dev/null +++ b/src/soc/intel/braswell/bootblock/timestamp.inc @@ -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 diff --git a/src/soc/intel/braswell/chip.c b/src/soc/intel/braswell/chip.c new file mode 100644 index 0000000..281019a --- /dev/null +++ b/src/soc/intel/braswell/chip.c @@ -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, +}; diff --git a/src/soc/intel/braswell/chip.h b/src/soc/intel/braswell/chip.h new file mode 100644 index 0000000..ecf1ce3 --- /dev/null +++ b/src/soc/intel/braswell/chip.h @@ -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_ */ diff --git a/src/soc/intel/braswell/cpu.c b/src/soc/intel/braswell/cpu.c new file mode 100644 index 0000000..f4d752e --- /dev/null +++ b/src/soc/intel/braswell/cpu.c @@ -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(); +} diff --git a/src/soc/intel/braswell/dptf.c b/src/soc/intel/braswell/dptf.c new file mode 100644 index 0000000..20d3420 --- /dev/null +++ b/src/soc/intel/braswell/dptf.c @@ -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); diff --git a/src/soc/intel/braswell/ehci.c b/src/soc/intel/braswell/ehci.c new file mode 100644 index 0000000..7cf5e2b --- /dev/null +++ b/src/soc/intel/braswell/ehci.c @@ -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 +}; diff --git a/src/soc/intel/braswell/elog.c b/src/soc/intel/braswell/elog.c new file mode 100644 index 0000000..f20dc97 --- /dev/null +++ b/src/soc/intel/braswell/elog.c @@ -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); +} diff --git a/src/soc/intel/braswell/emmc.c b/src/soc/intel/braswell/emmc.c new file mode 100644 index 0000000..1708428 --- /dev/null +++ b/src/soc/intel/braswell/emmc.c @@ -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, +}; diff --git a/src/soc/intel/braswell/gfx.c b/src/soc/intel/braswell/gfx.c new file mode 100644 index 0000000..0601e94 --- /dev/null +++ b/src/soc/intel/braswell/gfx.c @@ -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, +}; diff --git a/src/soc/intel/braswell/gpio.c b/src/soc/intel/braswell/gpio.c new file mode 100644 index 0000000..e4cc59a --- /dev/null +++ b/src/soc/intel/braswell/gpio.c @@ -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; +} diff --git a/src/soc/intel/braswell/hda.c b/src/soc/intel/braswell/hda.c new file mode 100644 index 0000000..dd1ba15 --- /dev/null +++ b/src/soc/intel/braswell/hda.c @@ -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, +}; diff --git a/src/soc/intel/braswell/include/soc/acpi.h b/src/soc/intel/braswell/include/soc/acpi.h new file mode 100644 index 0000000..bdf1cb3 --- /dev/null +++ b/src/soc/intel/braswell/include/soc/acpi.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/device_nvs.h b/src/soc/intel/braswell/include/soc/device_nvs.h new file mode 100644 index 0000000..1ed897f --- /dev/null +++ b/src/soc/intel/braswell/include/soc/device_nvs.h @@ -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 diff --git a/src/soc/intel/braswell/include/soc/efi_wrapper.h b/src/soc/intel/braswell/include/soc/efi_wrapper.h new file mode 100644 index 0000000..3304d03 --- /dev/null +++ b/src/soc/intel/braswell/include/soc/efi_wrapper.h @@ -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 diff --git a/src/soc/intel/braswell/include/soc/ehci.h b/src/soc/intel/braswell/include/soc/ehci.h new file mode 100644 index 0000000..a1edd6d --- /dev/null +++ b/src/soc/intel/braswell/include/soc/ehci.h @@ -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 */ diff --git a/src/soc/intel/braswell/include/soc/gfx.h b/src/soc/intel/braswell/include/soc/gfx.h new file mode 100644 index 0000000..7047dd5 --- /dev/null +++ b/src/soc/intel/braswell/include/soc/gfx.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/gpio.h b/src/soc/intel/braswell/include/soc/gpio.h new file mode 100644 index 0000000..f312cdc --- /dev/null +++ b/src/soc/intel/braswell/include/soc/gpio.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/iomap.h b/src/soc/intel/braswell/include/soc/iomap.h new file mode 100644 index 0000000..867484b --- /dev/null +++ b/src/soc/intel/braswell/include/soc/iomap.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/iosf.h b/src/soc/intel/braswell/include/soc/iosf.h new file mode 100644 index 0000000..6705a73 --- /dev/null +++ b/src/soc/intel/braswell/include/soc/iosf.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/irq.h b/src/soc/intel/braswell/include/soc/irq.h new file mode 100644 index 0000000..34b3f7d --- /dev/null +++ b/src/soc/intel/braswell/include/soc/irq.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/lpc.h b/src/soc/intel/braswell/include/soc/lpc.h new file mode 100644 index 0000000..2f6256c --- /dev/null +++ b/src/soc/intel/braswell/include/soc/lpc.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/mrc_wrapper.h b/src/soc/intel/braswell/include/soc/mrc_wrapper.h new file mode 100644 index 0000000..355dce0 --- /dev/null +++ b/src/soc/intel/braswell/include/soc/mrc_wrapper.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/msr.h b/src/soc/intel/braswell/include/soc/msr.h new file mode 100644 index 0000000..47b9543 --- /dev/null +++ b/src/soc/intel/braswell/include/soc/msr.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/nvs.h b/src/soc/intel/braswell/include/soc/nvs.h new file mode 100644 index 0000000..1ba30d5 --- /dev/null +++ b/src/soc/intel/braswell/include/soc/nvs.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/pattrs.h b/src/soc/intel/braswell/include/soc/pattrs.h new file mode 100644 index 0000000..81df73e --- /dev/null +++ b/src/soc/intel/braswell/include/soc/pattrs.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/pci_devs.h b/src/soc/intel/braswell/include/soc/pci_devs.h new file mode 100644 index 0000000..b3fdce2 --- /dev/null +++ b/src/soc/intel/braswell/include/soc/pci_devs.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/pcie.h b/src/soc/intel/braswell/include/soc/pcie.h new file mode 100644 index 0000000..92ca3c8 --- /dev/null +++ b/src/soc/intel/braswell/include/soc/pcie.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/pmc.h b/src/soc/intel/braswell/include/soc/pmc.h new file mode 100644 index 0000000..1af7ab8 --- /dev/null +++ b/src/soc/intel/braswell/include/soc/pmc.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/ramstage.h b/src/soc/intel/braswell/include/soc/ramstage.h new file mode 100644 index 0000000..0ed83bd --- /dev/null +++ b/src/soc/intel/braswell/include/soc/ramstage.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/reset.h b/src/soc/intel/braswell/include/soc/reset.h new file mode 100644 index 0000000..dbf0fd2 --- /dev/null +++ b/src/soc/intel/braswell/include/soc/reset.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/romstage.h b/src/soc/intel/braswell/include/soc/romstage.h new file mode 100644 index 0000000..f99a8e2 --- /dev/null +++ b/src/soc/intel/braswell/include/soc/romstage.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/sata.h b/src/soc/intel/braswell/include/soc/sata.h new file mode 100644 index 0000000..7704c18 --- /dev/null +++ b/src/soc/intel/braswell/include/soc/sata.h @@ -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 diff --git a/src/soc/intel/braswell/include/soc/smm.h b/src/soc/intel/braswell/include/soc/smm.h new file mode 100644 index 0000000..0d920fb --- /dev/null +++ b/src/soc/intel/braswell/include/soc/smm.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/spi.h b/src/soc/intel/braswell/include/soc/spi.h new file mode 100644 index 0000000..ef71ad5 --- /dev/null +++ b/src/soc/intel/braswell/include/soc/spi.h @@ -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_ */ diff --git a/src/soc/intel/braswell/include/soc/xhci.h b/src/soc/intel/braswell/include/soc/xhci.h new file mode 100644 index 0000000..b317361 --- /dev/null +++ b/src/soc/intel/braswell/include/soc/xhci.h @@ -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 */ diff --git a/src/soc/intel/braswell/iosf.c b/src/soc/intel/braswell/iosf.c new file mode 100644 index 0000000..8dba823 --- /dev/null +++ b/src/soc/intel/braswell/iosf.c @@ -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); +} diff --git a/src/soc/intel/braswell/lpe.c b/src/soc/intel/braswell/lpe.c new file mode 100644 index 0000000..c23fdb2 --- /dev/null +++ b/src/soc/intel/braswell/lpe.c @@ -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, +}; diff --git a/src/soc/intel/braswell/lpss.c b/src/soc/intel/braswell/lpss.c new file mode 100644 index 0000000..caa945c --- /dev/null +++ b/src/soc/intel/braswell/lpss.c @@ -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, +}; diff --git a/src/soc/intel/braswell/memmap.c b/src/soc/intel/braswell/memmap.c new file mode 100644 index 0000000..9a49e35 --- /dev/null +++ b/src/soc/intel/braswell/memmap.c @@ -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(); +} diff --git a/src/soc/intel/braswell/microcode/Makefile.inc b/src/soc/intel/braswell/microcode/Makefile.inc new file mode 100644 index 0000000..09bd454 --- /dev/null +++ b/src/soc/intel/braswell/microcode/Makefile.inc @@ -0,0 +1 @@ +cpu_microcode-$(CONFIG_CPU_MICROCODE_CBFS_GENERATE) += microcode_blob.c diff --git a/src/soc/intel/braswell/microcode/microcode_blob.c b/src/soc/intel/braswell/microcode/microcode_blob.c new file mode 100644 index 0000000..7c7b6f1 --- /dev/null +++ b/src/soc/intel/braswell/microcode/microcode_blob.c @@ -0,0 +1,3 @@ +unsigned microcode[] = { +#include "../../../../../3rdparty/soc/intel/baytrail/microcode_blob.h" +}; diff --git a/src/soc/intel/braswell/northcluster.c b/src/soc/intel/braswell/northcluster.c new file mode 100644 index 0000000..97b3bcc --- /dev/null +++ b/src/soc/intel/braswell/northcluster.c @@ -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, +}; diff --git a/src/soc/intel/braswell/pcie.c b/src/soc/intel/braswell/pcie.c new file mode 100644 index 0000000..e44ebc6 --- /dev/null +++ b/src/soc/intel/braswell/pcie.c @@ -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, +}; diff --git a/src/soc/intel/braswell/perf_power.c b/src/soc/intel/braswell/perf_power.c new file mode 100644 index 0000000..ad5ccfe --- /dev/null +++ b/src/soc/intel/braswell/perf_power.c @@ -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); diff --git a/src/soc/intel/braswell/placeholders.c b/src/soc/intel/braswell/placeholders.c new file mode 100644 index 0000000..3495c30 --- /dev/null +++ b/src/soc/intel/braswell/placeholders.c @@ -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; } diff --git a/src/soc/intel/braswell/pmutil.c b/src/soc/intel/braswell/pmutil.c new file mode 100644 index 0000000..0678fb7 --- /dev/null +++ b/src/soc/intel/braswell/pmutil.c @@ -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); +} diff --git a/src/soc/intel/braswell/ramstage.c b/src/soc/intel/braswell/ramstage.c new file mode 100644 index 0000000..8b6d93c --- /dev/null +++ b/src/soc/intel/braswell/ramstage.c @@ -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(); +} diff --git a/src/soc/intel/braswell/refcode.c b/src/soc/intel/braswell/refcode.c new file mode 100644 index 0000000..558db3c --- /dev/null +++ b/src/soc/intel/braswell/refcode.c @@ -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; + } +} diff --git a/src/soc/intel/braswell/reset.c b/src/soc/intel/braswell/reset.c new file mode 100644 index 0000000..c4cb2ab --- /dev/null +++ b/src/soc/intel/braswell/reset.c @@ -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(); +} diff --git a/src/soc/intel/braswell/romstage/Makefile.inc b/src/soc/intel/braswell/romstage/Makefile.inc new file mode 100644 index 0000000..345037d --- /dev/null +++ b/src/soc/intel/braswell/romstage/Makefile.inc @@ -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 \ No newline at end of file diff --git a/src/soc/intel/braswell/romstage/cache_as_ram.inc b/src/soc/intel/braswell/romstage/cache_as_ram.inc new file mode 100644 index 0000000..b6fcbf2 --- /dev/null +++ b/src/soc/intel/braswell/romstage/cache_as_ram.inc @@ -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: + diff --git a/src/soc/intel/braswell/romstage/early_spi.c b/src/soc/intel/braswell/romstage/early_spi.c new file mode 100644 index 0000000..2c48af1 --- /dev/null +++ b/src/soc/intel/braswell/romstage/early_spi.c @@ -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; +} diff --git a/src/soc/intel/braswell/romstage/gfx.c b/src/soc/intel/braswell/romstage/gfx.c new file mode 100644 index 0000000..f9bb9c9 --- /dev/null +++ b/src/soc/intel/braswell/romstage/gfx.c @@ -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); +} diff --git a/src/soc/intel/braswell/romstage/pmc.c b/src/soc/intel/braswell/romstage/pmc.c new file mode 100644 index 0000000..b41359b --- /dev/null +++ b/src/soc/intel/braswell/romstage/pmc.c @@ -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); +} diff --git a/src/soc/intel/braswell/romstage/raminit.c b/src/soc/intel/braswell/romstage/raminit.c new file mode 100644 index 0000000..61c122c --- /dev/null +++ b/src/soc/intel/braswell/romstage/raminit.c @@ -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); +} diff --git a/src/soc/intel/braswell/romstage/romstage.c b/src/soc/intel/braswell/romstage/romstage.c new file mode 100644 index 0000000..9c8bbc4 --- /dev/null +++ b/src/soc/intel/braswell/romstage/romstage.c @@ -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 diff --git a/src/soc/intel/braswell/romstage/uart.c b/src/soc/intel/braswell/romstage/uart.c new file mode 100644 index 0000000..7705746 --- /dev/null +++ b/src/soc/intel/braswell/romstage/uart.c @@ -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); +} diff --git a/src/soc/intel/braswell/sata.c b/src/soc/intel/braswell/sata.c new file mode 100644 index 0000000..5294207 --- /dev/null +++ b/src/soc/intel/braswell/sata.c @@ -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, +}; diff --git a/src/soc/intel/braswell/scc.c b/src/soc/intel/braswell/scc.c new file mode 100644 index 0000000..6400996 --- /dev/null +++ b/src/soc/intel/braswell/scc.c @@ -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); +} diff --git a/src/soc/intel/braswell/sd.c b/src/soc/intel/braswell/sd.c new file mode 100644 index 0000000..577469d --- /dev/null +++ b/src/soc/intel/braswell/sd.c @@ -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, +}; diff --git a/src/soc/intel/braswell/smihandler.c b/src/soc/intel/braswell/smihandler.c new file mode 100644 index 0000000..3fac525 --- /dev/null +++ b/src/soc/intel/braswell/smihandler.c @@ -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()); +} diff --git a/src/soc/intel/braswell/smm.c b/src/soc/intel/braswell/smm.c new file mode 100644 index 0000000..bfddb68 --- /dev/null +++ b/src/soc/intel/braswell/smm.c @@ -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) + ); +} diff --git a/src/soc/intel/braswell/southcluster.c b/src/soc/intel/braswell/southcluster.c new file mode 100644 index 0000000..8df1f1a --- /dev/null +++ b/src/soc/intel/braswell/southcluster.c @@ -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); diff --git a/src/soc/intel/braswell/spi.c b/src/soc/intel/braswell/spi.c new file mode 100644 index 0000000..2795d37 --- /dev/null +++ b/src/soc/intel/braswell/spi.c @@ -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; +} diff --git a/src/soc/intel/braswell/stage_cache.c b/src/soc/intel/braswell/stage_cache.c new file mode 100644 index 0000000..a4f510d --- /dev/null +++ b/src/soc/intel/braswell/stage_cache.c @@ -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]; +} diff --git a/src/soc/intel/braswell/tsc_freq.c b/src/soc/intel/braswell/tsc_freq.c new file mode 100644 index 0000000..700b098 --- /dev/null +++ b/src/soc/intel/braswell/tsc_freq.c @@ -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__ */ diff --git a/src/soc/intel/braswell/xhci.c b/src/soc/intel/braswell/xhci.c new file mode 100644 index 0000000..776e44c --- /dev/null +++ b/src/soc/intel/braswell/xhci.c @@ -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 +};