From 58562405c8c416a415652516b8af31b204b4ff0d Mon Sep 17 00:00:00 2001 From: Martin Roth Date: Sun, 11 Oct 2015 10:36:26 +0200 Subject: Revert "Remove FSP Rangeley SOC and mohonpeak board support" This chip is still being used and should not have been deleted. It's a current intel chip, and doesn't even require an ME binary. This reverts commit 959478a763c16688d43752adbae2c76e7764da45. Change-Id: I78594871f87af6e882a245077b59727e15f8021a Signed-off-by: Martin Roth Reviewed-on: http://review.coreboot.org/11860 Tested-by: build bot (Jenkins) Reviewed-by: Marc Jones Reviewed-by: Stefan Reinauer --- src/cpu/intel/Kconfig | 1 + src/cpu/intel/Makefile.inc | 1 + src/cpu/intel/fsp_model_406dx/Kconfig | 65 ++ src/cpu/intel/fsp_model_406dx/Makefile.inc | 28 + src/cpu/intel/fsp_model_406dx/acpi.c | 306 +++++++++ src/cpu/intel/fsp_model_406dx/acpi/cpu.asl | 101 +++ src/cpu/intel/fsp_model_406dx/bootblock.c | 95 +++ src/cpu/intel/fsp_model_406dx/chip.h | 36 + src/cpu/intel/fsp_model_406dx/model_406dx.h | 112 +++ src/cpu/intel/fsp_model_406dx/model_406dx_init.c | 210 ++++++ src/mainboard/intel/mohonpeak/Kconfig | 86 +++ src/mainboard/intel/mohonpeak/Kconfig.name | 2 + src/mainboard/intel/mohonpeak/Makefile.inc | 20 + src/mainboard/intel/mohonpeak/acpi/ec.asl | 0 src/mainboard/intel/mohonpeak/acpi/mainboard.asl | 27 + src/mainboard/intel/mohonpeak/acpi/platform.asl | 64 ++ src/mainboard/intel/mohonpeak/acpi/superio.asl | 0 src/mainboard/intel/mohonpeak/acpi/thermal.asl | 0 src/mainboard/intel/mohonpeak/acpi_tables.c | 83 +++ src/mainboard/intel/mohonpeak/board_info.txt | 4 + src/mainboard/intel/mohonpeak/cmos.layout | 117 ++++ src/mainboard/intel/mohonpeak/devicetree.cb | 68 ++ src/mainboard/intel/mohonpeak/dsdt.asl | 53 ++ src/mainboard/intel/mohonpeak/fadt.c | 42 ++ src/mainboard/intel/mohonpeak/gpio.h | 178 +++++ src/mainboard/intel/mohonpeak/irq_tables.c | 67 ++ src/mainboard/intel/mohonpeak/irqroute.c | 23 + src/mainboard/intel/mohonpeak/irqroute.h | 73 ++ src/mainboard/intel/mohonpeak/mainboard.c | 34 + src/mainboard/intel/mohonpeak/romstage.c | 86 +++ src/mainboard/intel/mohonpeak/thermal.h | 33 + src/northbridge/intel/fsp_rangeley/Kconfig | 92 +++ src/northbridge/intel/fsp_rangeley/Makefile.inc | 41 ++ src/northbridge/intel/fsp_rangeley/acpi.c | 78 +++ .../intel/fsp_rangeley/acpi/hostbridge.asl | 139 ++++ .../intel/fsp_rangeley/acpi/rangeley.asl | 40 ++ src/northbridge/intel/fsp_rangeley/chip.h | 73 ++ src/northbridge/intel/fsp_rangeley/fsp/Kconfig | 49 ++ .../intel/fsp_rangeley/fsp/Makefile.inc | 21 + .../intel/fsp_rangeley/fsp/chipset_fsp_util.c | 185 +++++ .../intel/fsp_rangeley/fsp/chipset_fsp_util.h | 52 ++ src/northbridge/intel/fsp_rangeley/northbridge.c | 276 ++++++++ src/northbridge/intel/fsp_rangeley/northbridge.h | 85 +++ src/northbridge/intel/fsp_rangeley/port_access.c | 72 ++ src/northbridge/intel/fsp_rangeley/raminit.c | 48 ++ src/northbridge/intel/fsp_rangeley/udelay.c | 68 ++ src/southbridge/intel/fsp_rangeley/Kconfig | 63 ++ src/southbridge/intel/fsp_rangeley/Makefile.inc | 38 ++ src/southbridge/intel/fsp_rangeley/acpi.c | 201 ++++++ .../intel/fsp_rangeley/acpi/globalnvs.asl | 185 +++++ .../intel/fsp_rangeley/acpi/irq_helper.h | 61 ++ .../intel/fsp_rangeley/acpi/irqlinks.asl | 491 ++++++++++++++ .../intel/fsp_rangeley/acpi/irqroute.asl | 43 ++ src/southbridge/intel/fsp_rangeley/acpi/lpc.asl | 230 +++++++ src/southbridge/intel/fsp_rangeley/acpi/pcie.asl | 169 +++++ .../intel/fsp_rangeley/acpi/pcie_port.asl | 29 + src/southbridge/intel/fsp_rangeley/acpi/sata.asl | 81 +++ .../intel/fsp_rangeley/acpi/sleepstates.asl | 30 + src/southbridge/intel/fsp_rangeley/acpi/smbus.asl | 240 +++++++ src/southbridge/intel/fsp_rangeley/acpi/soc.asl | 276 ++++++++ src/southbridge/intel/fsp_rangeley/acpi/usb.asl | 52 ++ src/southbridge/intel/fsp_rangeley/chip.h | 88 +++ src/southbridge/intel/fsp_rangeley/early_init.c | 79 +++ src/southbridge/intel/fsp_rangeley/early_smbus.c | 61 ++ src/southbridge/intel/fsp_rangeley/early_spi.c | 114 ++++ src/southbridge/intel/fsp_rangeley/early_usb.c | 47 ++ src/southbridge/intel/fsp_rangeley/gpio.c | 108 +++ src/southbridge/intel/fsp_rangeley/gpio.h | 128 ++++ src/southbridge/intel/fsp_rangeley/irq.h | 166 +++++ src/southbridge/intel/fsp_rangeley/lpc.c | 478 +++++++++++++ src/southbridge/intel/fsp_rangeley/nvs.h | 156 +++++ src/southbridge/intel/fsp_rangeley/pci_devs.h | 137 ++++ src/southbridge/intel/fsp_rangeley/reset.c | 34 + src/southbridge/intel/fsp_rangeley/romstage.c | 143 ++++ src/southbridge/intel/fsp_rangeley/romstage.h | 39 ++ src/southbridge/intel/fsp_rangeley/sata.c | 135 ++++ src/southbridge/intel/fsp_rangeley/smbus.c | 99 +++ src/southbridge/intel/fsp_rangeley/smbus.h | 99 +++ src/southbridge/intel/fsp_rangeley/soc.c | 99 +++ src/southbridge/intel/fsp_rangeley/soc.h | 452 +++++++++++++ src/southbridge/intel/fsp_rangeley/spi.c | 753 +++++++++++++++++++++ src/southbridge/intel/fsp_rangeley/watchdog.c | 56 ++ src/vendorcode/intel/Kconfig | 1 + 83 files changed, 8995 insertions(+) create mode 100644 src/cpu/intel/fsp_model_406dx/Kconfig create mode 100644 src/cpu/intel/fsp_model_406dx/Makefile.inc create mode 100644 src/cpu/intel/fsp_model_406dx/acpi.c create mode 100644 src/cpu/intel/fsp_model_406dx/acpi/cpu.asl create mode 100644 src/cpu/intel/fsp_model_406dx/bootblock.c create mode 100644 src/cpu/intel/fsp_model_406dx/chip.h create mode 100644 src/cpu/intel/fsp_model_406dx/model_406dx.h create mode 100644 src/cpu/intel/fsp_model_406dx/model_406dx_init.c create mode 100644 src/mainboard/intel/mohonpeak/Kconfig create mode 100644 src/mainboard/intel/mohonpeak/Kconfig.name create mode 100644 src/mainboard/intel/mohonpeak/Makefile.inc create mode 100644 src/mainboard/intel/mohonpeak/acpi/ec.asl create mode 100644 src/mainboard/intel/mohonpeak/acpi/mainboard.asl create mode 100644 src/mainboard/intel/mohonpeak/acpi/platform.asl create mode 100644 src/mainboard/intel/mohonpeak/acpi/superio.asl create mode 100644 src/mainboard/intel/mohonpeak/acpi/thermal.asl create mode 100644 src/mainboard/intel/mohonpeak/acpi_tables.c create mode 100644 src/mainboard/intel/mohonpeak/board_info.txt create mode 100644 src/mainboard/intel/mohonpeak/cmos.layout create mode 100644 src/mainboard/intel/mohonpeak/devicetree.cb create mode 100644 src/mainboard/intel/mohonpeak/dsdt.asl create mode 100644 src/mainboard/intel/mohonpeak/fadt.c create mode 100644 src/mainboard/intel/mohonpeak/gpio.h create mode 100644 src/mainboard/intel/mohonpeak/irq_tables.c create mode 100644 src/mainboard/intel/mohonpeak/irqroute.c create mode 100644 src/mainboard/intel/mohonpeak/irqroute.h create mode 100644 src/mainboard/intel/mohonpeak/mainboard.c create mode 100644 src/mainboard/intel/mohonpeak/romstage.c create mode 100644 src/mainboard/intel/mohonpeak/thermal.h create mode 100644 src/northbridge/intel/fsp_rangeley/Kconfig create mode 100644 src/northbridge/intel/fsp_rangeley/Makefile.inc create mode 100644 src/northbridge/intel/fsp_rangeley/acpi.c create mode 100644 src/northbridge/intel/fsp_rangeley/acpi/hostbridge.asl create mode 100644 src/northbridge/intel/fsp_rangeley/acpi/rangeley.asl create mode 100644 src/northbridge/intel/fsp_rangeley/chip.h create mode 100644 src/northbridge/intel/fsp_rangeley/fsp/Kconfig create mode 100644 src/northbridge/intel/fsp_rangeley/fsp/Makefile.inc create mode 100644 src/northbridge/intel/fsp_rangeley/fsp/chipset_fsp_util.c create mode 100644 src/northbridge/intel/fsp_rangeley/fsp/chipset_fsp_util.h create mode 100644 src/northbridge/intel/fsp_rangeley/northbridge.c create mode 100644 src/northbridge/intel/fsp_rangeley/northbridge.h create mode 100644 src/northbridge/intel/fsp_rangeley/port_access.c create mode 100644 src/northbridge/intel/fsp_rangeley/raminit.c create mode 100644 src/northbridge/intel/fsp_rangeley/udelay.c create mode 100644 src/southbridge/intel/fsp_rangeley/Kconfig create mode 100644 src/southbridge/intel/fsp_rangeley/Makefile.inc create mode 100644 src/southbridge/intel/fsp_rangeley/acpi.c create mode 100644 src/southbridge/intel/fsp_rangeley/acpi/globalnvs.asl create mode 100644 src/southbridge/intel/fsp_rangeley/acpi/irq_helper.h create mode 100644 src/southbridge/intel/fsp_rangeley/acpi/irqlinks.asl create mode 100644 src/southbridge/intel/fsp_rangeley/acpi/irqroute.asl create mode 100644 src/southbridge/intel/fsp_rangeley/acpi/lpc.asl create mode 100644 src/southbridge/intel/fsp_rangeley/acpi/pcie.asl create mode 100644 src/southbridge/intel/fsp_rangeley/acpi/pcie_port.asl create mode 100644 src/southbridge/intel/fsp_rangeley/acpi/sata.asl create mode 100644 src/southbridge/intel/fsp_rangeley/acpi/sleepstates.asl create mode 100644 src/southbridge/intel/fsp_rangeley/acpi/smbus.asl create mode 100644 src/southbridge/intel/fsp_rangeley/acpi/soc.asl create mode 100644 src/southbridge/intel/fsp_rangeley/acpi/usb.asl create mode 100644 src/southbridge/intel/fsp_rangeley/chip.h create mode 100644 src/southbridge/intel/fsp_rangeley/early_init.c create mode 100644 src/southbridge/intel/fsp_rangeley/early_smbus.c create mode 100644 src/southbridge/intel/fsp_rangeley/early_spi.c create mode 100644 src/southbridge/intel/fsp_rangeley/early_usb.c create mode 100644 src/southbridge/intel/fsp_rangeley/gpio.c create mode 100644 src/southbridge/intel/fsp_rangeley/gpio.h create mode 100644 src/southbridge/intel/fsp_rangeley/irq.h create mode 100644 src/southbridge/intel/fsp_rangeley/lpc.c create mode 100644 src/southbridge/intel/fsp_rangeley/nvs.h create mode 100644 src/southbridge/intel/fsp_rangeley/pci_devs.h create mode 100644 src/southbridge/intel/fsp_rangeley/reset.c create mode 100644 src/southbridge/intel/fsp_rangeley/romstage.c create mode 100644 src/southbridge/intel/fsp_rangeley/romstage.h create mode 100644 src/southbridge/intel/fsp_rangeley/sata.c create mode 100644 src/southbridge/intel/fsp_rangeley/smbus.c create mode 100644 src/southbridge/intel/fsp_rangeley/smbus.h create mode 100644 src/southbridge/intel/fsp_rangeley/soc.c create mode 100644 src/southbridge/intel/fsp_rangeley/soc.h create mode 100644 src/southbridge/intel/fsp_rangeley/spi.c create mode 100644 src/southbridge/intel/fsp_rangeley/watchdog.c (limited to 'src') diff --git a/src/cpu/intel/Kconfig b/src/cpu/intel/Kconfig index 17c1229af5..ab63682414 100644 --- a/src/cpu/intel/Kconfig +++ b/src/cpu/intel/Kconfig @@ -11,6 +11,7 @@ source src/cpu/intel/model_6fx/Kconfig source src/cpu/intel/model_1067x/Kconfig source src/cpu/intel/model_106cx/Kconfig source src/cpu/intel/model_206ax/Kconfig +source src/cpu/intel/fsp_model_406dx/Kconfig source src/cpu/intel/model_2065x/Kconfig source src/cpu/intel/model_f0x/Kconfig source src/cpu/intel/model_f1x/Kconfig diff --git a/src/cpu/intel/Makefile.inc b/src/cpu/intel/Makefile.inc index 904aa5d7b5..14a8a62a29 100644 --- a/src/cpu/intel/Makefile.inc +++ b/src/cpu/intel/Makefile.inc @@ -23,6 +23,7 @@ subdirs-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += model_206ax subdirs-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE_MRC) += model_206ax subdirs-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += model_206ax subdirs-$(CONFIG_NORTHBRIDGE_INTEL_HASWELL) += haswell +subdirs-$(CONFIG_NORTHBRIDGE_INTEL_FSP_RANGELEY) += fsp_model_406dx subdirs-$(CONFIG_CPU_INTEL_SLOT_2) += slot_2 subdirs-$(CONFIG_CPU_INTEL_SLOT_1) += slot_1 subdirs-$(CONFIG_CPU_INTEL_SOCKET_LGA1155) += socket_LGA1155 diff --git a/src/cpu/intel/fsp_model_406dx/Kconfig b/src/cpu/intel/fsp_model_406dx/Kconfig new file mode 100644 index 0000000000..163040970f --- /dev/null +++ b/src/cpu/intel/fsp_model_406dx/Kconfig @@ -0,0 +1,65 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. +## +## This 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. +## + +config CPU_INTEL_FSP_MODEL_406DX + bool + +if CPU_INTEL_FSP_MODEL_406DX + +config CPU_SPECIFIC_OPTIONS + def_bool y + select PLATFORM_USES_FSP1_0 + select ARCH_BOOTBLOCK_X86_32 + select ARCH_VERSTAGE_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 + select SMP + select SSE2 + select UDELAY_LAPIC + select SUPPORT_CPU_UCODE_IN_CBFS if HAVE_FSP_BIN + select PARALLEL_CPU_INIT + select TSC_SYNC_MFENCE + select LAPIC_MONOTONIC_TIMER + +choice + prompt "Rangeley CPU Stepping" + default FSP_MODEL_406DX_B0 + +config FSP_MODEL_406DX_A1 + bool "A1" + +config FSP_MODEL_406DX_B0 + bool "B0" + +endchoice + +config BOOTBLOCK_CPU_INIT + string + default "cpu/intel/fsp_model_406dx/bootblock.c" + +config ENABLE_VMX + bool "Enable VMX for virtualization" + default n + +config CPU_MICROCODE_CBFS_LOC + hex + depends on SUPPORT_CPU_UCODE_IN_CBFS + default 0xfff60040 + +endif #CPU_INTEL_FSP_MODEL_406DX diff --git a/src/cpu/intel/fsp_model_406dx/Makefile.inc b/src/cpu/intel/fsp_model_406dx/Makefile.inc new file mode 100644 index 0000000000..f28e531098 --- /dev/null +++ b/src/cpu/intel/fsp_model_406dx/Makefile.inc @@ -0,0 +1,28 @@ +# +# This file is part of the coreboot project. +# +# Copyrignt (C) 2014 Sage Electronic Engineering, LLC. +# +# This 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. +# + +ramstage-y += model_406dx_init.c +subdirs-y += ../../x86/name + +ramstage-y += acpi.c + +CPPFLAGS_romstage += -I$(src)/cpu/intel/fsp_model_406dx +# We don't have microcode for this CPU +# Use CONFIG_CPU_MICROCODE_CBFS_EXTERNAL with a binary microcode file +# cpu_microcode_bins += ??? diff --git a/src/cpu/intel/fsp_model_406dx/acpi.c b/src/cpu/intel/fsp_model_406dx/acpi.c new file mode 100644 index 0000000000..abc35ad92a --- /dev/null +++ b/src/cpu/intel/fsp_model_406dx/acpi.c @@ -0,0 +1,306 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2009 coresystems GmbH + * Copyright (C) 2011 The Chromium OS Authors. All rights reserved. + * Copyright (C) 2013 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "model_406dx.h" +#include "chip.h" + +static int get_cores_per_package(void) +{ + struct cpuinfo_x86 c; + struct cpuid_result result; + int cores = 1; + + get_fms(&c, cpuid_eax(1)); + if (c.x86 != 6) + return 1; + + result = cpuid_ext(0xb, 1); + cores = result.ebx & 0xff; + + return cores; +} + +static void generate_C_state_entries(void) +{ + struct cpu_info *info; + struct cpu_driver *cpu; + struct device *lapic; + struct cpu_intel_model_406dx_config *conf = NULL; + + /* Find the SpeedStep CPU in the device tree using magic APIC ID */ + lapic = dev_find_lapic(SPEEDSTEP_APIC_MAGIC); + if (!lapic) + return; + conf = lapic->chip_info; + if (!conf) + return; + + /* Find CPU map of supported C-states */ + info = cpu_info(); + if (!info) + return; + cpu = find_cpu_driver(info->cpu); + if (!cpu || !cpu->cstates) + return; + + acpigen_emit_byte(0x14); /* MethodOp */ + acpigen_write_len_f(); /* PkgLength */ + acpigen_emit_namestring("_CST"); + acpigen_emit_byte(0x00); /* No Arguments */ + + /* If running on AC power */ + acpigen_emit_byte(0xa0); /* IfOp */ + acpigen_write_len_f(); /* PkgLength */ + acpigen_emit_namestring("PWRS"); + acpigen_emit_byte(0xa4); /* ReturnOp */ + acpigen_pop_len(); + + /* Else on battery power */ + acpigen_emit_byte(0xa4); /* ReturnOp */ + acpigen_pop_len(); +} + +static acpi_tstate_t tss_table_fine[] = { + { 100, 1000, 0, 0x00, 0 }, + { 94, 940, 0, 0x1f, 0 }, + { 88, 880, 0, 0x1e, 0 }, + { 82, 820, 0, 0x1d, 0 }, + { 75, 760, 0, 0x1c, 0 }, + { 69, 700, 0, 0x1b, 0 }, + { 63, 640, 0, 0x1a, 0 }, + { 57, 580, 0, 0x19, 0 }, + { 50, 520, 0, 0x18, 0 }, + { 44, 460, 0, 0x17, 0 }, + { 38, 400, 0, 0x16, 0 }, + { 32, 340, 0, 0x15, 0 }, + { 25, 280, 0, 0x14, 0 }, + { 19, 220, 0, 0x13, 0 }, + { 13, 160, 0, 0x12, 0 }, +}; + +static acpi_tstate_t tss_table_coarse[] = { + { 100, 1000, 0, 0x00, 0 }, + { 88, 875, 0, 0x1f, 0 }, + { 75, 750, 0, 0x1e, 0 }, + { 63, 625, 0, 0x1d, 0 }, + { 50, 500, 0, 0x1c, 0 }, + { 38, 375, 0, 0x1b, 0 }, + { 25, 250, 0, 0x1a, 0 }, + { 13, 125, 0, 0x19, 0 }, +}; + +static void generate_T_state_entries(int core, int cores_per_package) +{ + /* Indicate SW_ALL coordination for T-states */ + acpigen_write_TSD_package(core, cores_per_package, SW_ALL); + + /* Indicate FFixedHW so OS will use MSR */ + acpigen_write_empty_PTC(); + + /* Set a T-state limit that can be modified in NVS */ + acpigen_write_TPC("\\TLVL"); + + /* + * CPUID.(EAX=6):EAX[5] indicates support + * for extended throttle levels. + */ + if (cpuid_eax(6) & (1 << 5)) + acpigen_write_TSS_package( + ARRAY_SIZE(tss_table_fine), tss_table_fine); + else + acpigen_write_TSS_package( + ARRAY_SIZE(tss_table_coarse), tss_table_coarse); +} + +static int calculate_power(int tdp, int p1_ratio, int ratio) +{ + u32 m; + u32 power; + + /* + * M = ((1.1 - ((p1_ratio - ratio) * 0.00625)) / 1.1) ^ 2 + * + * Power = (ratio / p1_ratio) * m * tdp + */ + + m = (110000 - ((p1_ratio - ratio) * 625)) / 11; + m = (m * m) / 1000; + + power = ((ratio * 100000 / p1_ratio) / 100); + power *= (m / 100) * (tdp / 1000); + power /= 1000; + + return (int)power; +} + +static void generate_P_state_entries(int core, int cores_per_package) +{ + int ratio_min, ratio_max, ratio_turbo, ratio_step; + int coord_type, power_max, num_entries; + int ratio, power, clock, clock_max; + msr_t msr; + + /* Rangeley uses hardware only control */ + coord_type = HW_ALL; + + /* Get bus ratio limits and calculate clock speeds */ + msr = rdmsr(MSR_PLATFORM_INFO); + ratio_min = (msr.hi >> (40-32)) & 0xff; /* Max Efficiency Ratio */ + + /* Determine if this CPU has configurable TDP */ + if (cpu_config_tdp_levels()) { + /* Set max ratio to nominal TDP ratio */ + msr = rdmsr(MSR_CONFIG_TDP_NOMINAL); + ratio_max = msr.lo & 0xff; + } else { + /* Max Non-Turbo Ratio */ + ratio_max = (msr.lo >> 8) & 0xff; + } + clock_max = ratio_max * RANGELEY_BCLK; + + /* Calculate CPU TDP in mW */ + msr = rdmsr(MSR_PKG_POWER_SKU_UNIT); + power_max = 2 << ((msr.lo & 0xf) - 1); + + + /* Write _PCT indicating use of FFixedHW */ + acpigen_write_empty_PCT(); + + /* Write _PPC with no limit on supported P-state */ + acpigen_write_PPC_NVS(); + + /* Write PSD indicating configured coordination type */ + acpigen_write_PSD_package(core, cores_per_package, coord_type); + + /* Add P-state entries in _PSS table */ + acpigen_write_name("_PSS"); + + /* Determine ratio points */ + ratio_step = PSS_RATIO_STEP; + num_entries = (ratio_max - ratio_min) / ratio_step; + while (num_entries > PSS_MAX_ENTRIES-1) { + ratio_step <<= 1; + num_entries >>= 1; + } + + /* P[T] is Turbo state if enabled */ + if (get_turbo_state() == TURBO_ENABLED) { + /* _PSS package count including Turbo */ + acpigen_write_package(num_entries + 2); + + msr = rdmsr(MSR_TURBO_RATIO_LIMIT); + ratio_turbo = msr.lo & 0xff; + + /* Add entry for Turbo ratio */ + acpigen_write_PSS_package( + clock_max + 1, /*MHz*/ + power_max, /*mW*/ + PSS_LATENCY_TRANSITION, /*lat1*/ + PSS_LATENCY_BUSMASTER, /*lat2*/ + ratio_turbo << 8, /*control*/ + ratio_turbo << 8); /*status*/ + } else { + /* _PSS package count without Turbo */ + acpigen_write_package(num_entries + 1); + } + + /* First regular entry is max non-turbo ratio */ + acpigen_write_PSS_package( + clock_max, /*MHz*/ + power_max, /*mW*/ + PSS_LATENCY_TRANSITION, /*lat1*/ + PSS_LATENCY_BUSMASTER, /*lat2*/ + ratio_max << 8, /*control*/ + ratio_max << 8); /*status*/ + + /* Generate the remaining entries */ + for (ratio = ratio_min + ((num_entries - 1) * ratio_step); + ratio >= ratio_min; ratio -= ratio_step) { + + /* Calculate power at this ratio */ + power = calculate_power(power_max, ratio_max, ratio); + clock = ratio * RANGELEY_BCLK; + + acpigen_write_PSS_package( + clock, /*MHz*/ + power, /*mW*/ + PSS_LATENCY_TRANSITION, /*lat1*/ + PSS_LATENCY_BUSMASTER, /*lat2*/ + ratio << 8, /*control*/ + ratio << 8); /*status*/ + } + + /* Fix package length */ + acpigen_pop_len(); +} + +void generate_cpu_entries(device_t device) +{ + int coreID, cpuID, pcontrol_blk = PMB0_BASE, plen = 6; + int totalcores = dev_count_cpu(); + int cores_per_package = get_cores_per_package(); + int numcpus = totalcores/cores_per_package; + + printk(BIOS_DEBUG, "Found %d CPU(s) with %d core(s) each.\n", + numcpus, cores_per_package); + + for (cpuID = 1; cpuID <= numcpus; cpuID++) { + for (coreID=1; coreID<=cores_per_package; coreID++) { + if (coreID>1) { + pcontrol_blk = 0; + plen = 0; + } + + /* Generate processor \_PR.CPUx */ + acpigen_write_processor( + (cpuID-1)*cores_per_package+coreID-1, + pcontrol_blk, plen); + + /* Generate P-state tables */ + generate_P_state_entries( + cpuID-1, cores_per_package); + + /* Generate C-state tables */ + generate_C_state_entries(); + + /* Generate T-state tables */ + generate_T_state_entries( + cpuID-1, cores_per_package); + + acpigen_pop_len(); + } + } +} + +struct chip_operations cpu_intel_model_406dx_ops = { + CHIP_NAME("Intel Rangeley CPU") +}; diff --git a/src/cpu/intel/fsp_model_406dx/acpi/cpu.asl b/src/cpu/intel/fsp_model_406dx/acpi/cpu.asl new file mode 100644 index 0000000000..114dbe3b98 --- /dev/null +++ b/src/cpu/intel/fsp_model_406dx/acpi/cpu.asl @@ -0,0 +1,101 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 The ChromiumOS Authors. 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. + */ + +/* These devices are created at runtime */ +External (\_PR.CP00, DeviceObj) +External (\_PR.CP01, DeviceObj) +External (\_PR.CP02, DeviceObj) +External (\_PR.CP03, DeviceObj) +External (\_PR.CP04, DeviceObj) +External (\_PR.CP05, DeviceObj) +External (\_PR.CP06, DeviceObj) +External (\_PR.CP07, DeviceObj) + +/* Notify OS to re-read CPU tables, assuming ^2 CPU count */ +Method (PNOT) +{ + If (LGreaterEqual (\PCNT, 2)) { + Notify (\_PR.CP00, 0x81) // _CST + Notify (\_PR.CP01, 0x81) // _CST + } + If (LGreaterEqual (\PCNT, 4)) { + Notify (\_PR.CP02, 0x81) // _CST + Notify (\_PR.CP03, 0x81) // _CST + } + If (LGreaterEqual (\PCNT, 8)) { + Notify (\_PR.CP04, 0x81) // _CST + Notify (\_PR.CP05, 0x81) // _CST + Notify (\_PR.CP06, 0x81) // _CST + Notify (\_PR.CP07, 0x81) // _CST + } +} + +/* Notify OS to re-read CPU _PPC limit, assuming ^2 CPU count */ +Method (PPCN) +{ + If (LGreaterEqual (\PCNT, 2)) { + Notify (\_PR.CP00, 0x80) // _PPC + Notify (\_PR.CP01, 0x80) // _PPC + } + If (LGreaterEqual (\PCNT, 4)) { + Notify (\_PR.CP02, 0x80) // _PPC + Notify (\_PR.CP03, 0x80) // _PPC + } + If (LGreaterEqual (\PCNT, 8)) { + Notify (\_PR.CP04, 0x80) // _PPC + Notify (\_PR.CP05, 0x80) // _PPC + Notify (\_PR.CP06, 0x80) // _PPC + Notify (\_PR.CP07, 0x80) // _PPC + } +} + +/* Notify OS to re-read Throttle Limit tables, assuming ^2 CPU count */ +Method (TNOT) +{ + If (LGreaterEqual (\PCNT, 2)) { + Notify (\_PR.CP00, 0x82) // _TPC + Notify (\_PR.CP01, 0x82) // _TPC + } + If (LGreaterEqual (\PCNT, 4)) { + Notify (\_PR.CP02, 0x82) // _TPC + Notify (\_PR.CP03, 0x82) // _TPC + } + If (LGreaterEqual (\PCNT, 8)) { + Notify (\_PR.CP04, 0x82) // _TPC + Notify (\_PR.CP05, 0x82) // _TPC + Notify (\_PR.CP06, 0x82) // _TPC + Notify (\_PR.CP07, 0x82) // _TPC + } +} + +/* Return a package containing enabled processor entries */ +Method (PPKG) +{ + If (LGreaterEqual (\PCNT, 8)) { + Return (Package() {\_PR.CP00, \_PR.CP01, \_PR.CP02, \_PR.CP03, + \_PR.CP04, \_PR.CP05, \_PR.CP06, \_PR.CP07}) + } ElseIf (LGreaterEqual (\PCNT, 4)) { + Return (Package() {\_PR.CP00, \_PR.CP01, \_PR.CP02, \_PR.CP03}) + } ElseIf (LGreaterEqual (\PCNT, 2)) { + Return (Package() {\_PR.CP00, \_PR.CP01}) + } Else { + Return (Package() {\_PR.CP00}) + } +} diff --git a/src/cpu/intel/fsp_model_406dx/bootblock.c b/src/cpu/intel/fsp_model_406dx/bootblock.c new file mode 100644 index 0000000000..a685eaac71 --- /dev/null +++ b/src/cpu/intel/fsp_model_406dx/bootblock.c @@ -0,0 +1,95 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Google Inc. + * Copyright (C) 2013-2014 Sage Electronic Engineering LLC. + * + * This 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "model_406dx.h" + +/* + * check for a warm reset and do a hard reset instead. + */ +static void check_for_warm_reset(void) +{ + + /* + * Check if INIT# is asserted by port 0xCF9 and whether RCBA has been set. + * If either is true, then this is a warm reset so execute a Hard Reset + */ + if ( (inb(0xcf9) == 0x04) || + (pci_io_read_config32(SOC_LPC_DEV, RCBA) & RCBA_ENABLE) ) { + outb(0x00, 0xcf9); + outb(0x06, 0xcf9); + } +} + +static void set_var_mtrr(int reg, uint32_t base, uint32_t size, int type) +{ +#ifndef CONFIG_CPU_ADDR_BITS +#error "CONFIG_CPU_ADDR_BITS must be set." +#endif + + /* Bit Bit 32-35 of MTRRphysMask should be set to 1 */ + msr_t basem, maskm; + basem.lo = base | type; + basem.hi = 0; + wrmsr(MTRRphysBase_MSR(reg), basem); + maskm.lo = ~(size - 1) | MTRRphysMaskValid; + maskm.hi = (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1; + wrmsr(MTRRphysMask_MSR(reg), maskm); +} + +static void enable_rom_caching(void) +{ + msr_t msr; + + disable_cache(); + set_var_mtrr(1, 0xffffffff - CACHE_ROM_SIZE + 1, + CACHE_ROM_SIZE, MTRR_TYPE_WRPROT); + enable_cache(); + + /* Enable Variable MTRRs */ + msr.hi = 0x00000000; + msr.lo = 0x00000800; + wrmsr(MTRRdefType_MSR, msr); +} + +static void set_no_evict_mode_msr(void) +{ + msr_t msr; + msr.hi = 0x00000000; + msr.lo = 0x00000000; + + wrmsr(MSR_NO_EVICT_MODE, msr); +} + +static void bootblock_cpu_init(void) +{ + /* Check for Warm Reset */ + check_for_warm_reset(); + enable_rom_caching(); + set_no_evict_mode_msr(); +} diff --git a/src/cpu/intel/fsp_model_406dx/chip.h b/src/cpu/intel/fsp_model_406dx/chip.h new file mode 100644 index 0000000000..a59e4031d3 --- /dev/null +++ b/src/cpu/intel/fsp_model_406dx/chip.h @@ -0,0 +1,36 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 The Chromium OS Authors. 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. + */ + +#ifndef CPU_FSP_MODEL406DX_CHIP_H +#define CPU_FSP_MODEL406DX_CHIP_H + +/* Magic value used to locate this chip in the device tree */ +#define SPEEDSTEP_APIC_MAGIC 0xACAC + +struct cpu_intel_fsp_model_406dx_config { + int c1_battery; /* ACPI C1 on Battery Power */ + int c2_battery; /* ACPI C2 on Battery Power */ + int c3_battery; /* ACPI C3 on Battery Power */ + + int c1_acpower; /* ACPI C1 on AC Power */ + int c2_acpower; /* ACPI C2 on AC Power */ + int c3_acpower; /* ACPI C3 on AC Power */ +}; + +#endif /* CPU_FSP_MODEL406DX_CHIP_H */ diff --git a/src/cpu/intel/fsp_model_406dx/model_406dx.h b/src/cpu/intel/fsp_model_406dx/model_406dx.h new file mode 100644 index 0000000000..d1d7a59738 --- /dev/null +++ b/src/cpu/intel/fsp_model_406dx/model_406dx.h @@ -0,0 +1,112 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. + * Copyright (C) 2013 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#ifndef _CPU_INTEL_MODEL_406DX_H +#define _CPU_INTEL_MODEL_406DX_H + +/* Rangeley bus clock is fixed at 100MHz */ +#define RANGELEY_BCLK 100 + +#define IA32_FEATURE_CONTROL 0x3a +#define CPUID_VMX (1 << 5) +#define CPUID_SMX (1 << 6) +#define MSR_FEATURE_CONFIG 0x13c +#define MSR_FLEX_RATIO 0x194 +#define FLEX_RATIO_LOCK (1 << 20) +#define FLEX_RATIO_EN (1 << 16) +#define IA32_PLATFORM_DCA_CAP 0x1f8 +#define IA32_MISC_ENABLE 0x1a0 +#define MSR_TEMPERATURE_TARGET 0x1a2 +#define IA32_PERF_CTL 0x199 +#define IA32_THERM_INTERRUPT 0x19b +#define IA32_ENERGY_PERFORMANCE_BIAS 0x1b0 +#define ENERGY_POLICY_PERFORMANCE 0 +#define ENERGY_POLICY_NORMAL 6 +#define ENERGY_POLICY_POWERSAVE 15 +#define IA32_PACKAGE_THERM_INTERRUPT 0x1b2 +#define MSR_LT_LOCK_MEMORY 0x2e7 +#define IA32_MC0_STATUS 0x401 + +#define MSR_NO_EVICT_MODE 0x2e0 +#define MSR_PIC_MSG_CONTROL 0x2e +#define MSR_PLATFORM_INFO 0xce +#define PLATFORM_INFO_SET_TDP (1 << 29) +#define MSR_PMG_CST_CONFIG_CONTROL 0xe2 +#define MSR_PMG_IO_CAPTURE_BASE 0xe4 + +#define MSR_MISC_PWR_MGMT 0x1aa +#define MISC_PWR_MGMT_EIST_HW_DIS (1 << 0) +#define MSR_TURBO_RATIO_LIMIT 0x1ad +#define MSR_POWER_CTL 0x1fc + +#define MSR_PKGC3_IRTL 0x60a +#define MSR_PKGC6_IRTL 0x60b +#define MSR_PKGC7_IRTL 0x60c +#define IRTL_VALID (1 << 15) +#define IRTL_1_NS (0 << 10) +#define IRTL_32_NS (1 << 10) +#define IRTL_1024_NS (2 << 10) +#define IRTL_32768_NS (3 << 10) +#define IRTL_1048576_NS (4 << 10) +#define IRTL_33554432_NS (5 << 10) +#define IRTL_RESPONSE_MASK (0x3ff) + +/* long duration in low dword, short duration in high dword */ +#define MSR_PKG_POWER_LIMIT 0x610 +#define PKG_POWER_LIMIT_MASK 0x7fff +#define PKG_POWER_LIMIT_EN (1 << 15) +#define PKG_POWER_LIMIT_CLAMP (1 << 16) +#define PKG_POWER_LIMIT_TIME_SHIFT 17 +#define PKG_POWER_LIMIT_TIME_MASK 0x7f + +#define MSR_PP0_CURRENT_CONFIG 0x601 +#define PP0_CURRENT_LIMIT (112 << 3) /* 112 A */ +#define MSR_PP1_CURRENT_CONFIG 0x602 +#define PP1_CURRENT_LIMIT_SNB (35 << 3) /* 35 A */ +#define PP1_CURRENT_LIMIT_IVB (50 << 3) /* 50 A */ +#define MSR_PKG_POWER_SKU_UNIT 0x606 +#define MSR_PKG_POWER_SKU 0x614 +#define MSR_PP0_POWER_LIMIT 0x638 +#define MSR_PP1_POWER_LIMIT 0x640 + +#define IVB_CONFIG_TDP_MIN_CPUID 0x306a2 +#define MSR_CONFIG_TDP_NOMINAL 0x648 +#define MSR_CONFIG_TDP_LEVEL1 0x649 +#define MSR_CONFIG_TDP_LEVEL2 0x64a +#define MSR_CONFIG_TDP_CONTROL 0x64b +#define MSR_TURBO_ACTIVATION_RATIO 0x64c + +/* P-state configuration */ +#define PSS_MAX_ENTRIES 8 +#define PSS_RATIO_STEP 2 +#define PSS_LATENCY_TRANSITION 10 +#define PSS_LATENCY_BUSMASTER 10 + +#ifndef __ROMCC__ +#ifdef __SMM__ +/* Lock MSRs */ +void intel_model_406dx_finalize_smm(void); +#else +int cpu_config_tdp_levels(void); +#endif +#endif + +#endif /* _CPU_INTEL_MODEL_406DX_H */ diff --git a/src/cpu/intel/fsp_model_406dx/model_406dx_init.c b/src/cpu/intel/fsp_model_406dx/model_406dx_init.c new file mode 100644 index 0000000000..739495c95d --- /dev/null +++ b/src/cpu/intel/fsp_model_406dx/model_406dx_init.c @@ -0,0 +1,210 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. + * Copyright (C) 2014 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "model_406dx.h" +#include "chip.h" + +static void enable_vmx(void) +{ + struct cpuid_result regs; + msr_t msr; + int enable = IS_ENABLED(CONFIG_ENABLE_VMX); + + regs = cpuid(1); + /* Check that the VMX is supported before reading or writing the MSR. */ + if (!((regs.ecx & CPUID_VMX) || (regs.ecx & CPUID_SMX))) + return; + + msr = rdmsr(IA32_FEATURE_CONTROL); + + if (msr.lo & (1 << 0)) { + printk(BIOS_ERR, "VMX is locked, so %s will do nothing\n", __func__); + /* VMX locked. If we set it again we get an illegal + * instruction + */ + return; + } + + /* The IA32_FEATURE_CONTROL MSR may initialize with random values. + * It must be cleared regardless of VMX config setting. + */ + msr.hi = msr.lo = 0; + + printk(BIOS_DEBUG, "%s VMX\n", enable ? "Enabling" : "Disabling"); + + if (enable) { + msr.lo |= (1 << 2); + if (regs.ecx & CPUID_SMX) + msr.lo |= (1 << 1); + } + + wrmsr(IA32_FEATURE_CONTROL, msr); +} + +int cpu_config_tdp_levels(void) +{ + msr_t platform_info; + + /* Minimum CPU revision */ + if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID) + return 0; + + /* Bits 34:33 indicate how many levels supported */ + platform_info = rdmsr(MSR_PLATFORM_INFO); + return (platform_info.hi >> 1) & 3; +} + +static void configure_misc(void) +{ + msr_t msr; + + msr = rdmsr(IA32_MISC_ENABLE); + msr.lo |= (1 << 0); /* Fast String enable */ + msr.lo |= (1 << 3); /* TM1/TM2/EMTTM enable */ + msr.lo |= (1 << 16); /* Enhanced SpeedStep Enable */ + wrmsr(IA32_MISC_ENABLE, msr); + + /* Disable Thermal interrupts */ + msr.lo = 0; + msr.hi = 0; + wrmsr(IA32_THERM_INTERRUPT, msr); +} + +static void configure_mca(void) +{ + msr_t msr; + int i; + + msr.lo = msr.hi = 0; + /* This should only be done on a cold boot */ + for (i = 0; i < 6; i++) + wrmsr(IA32_MC0_STATUS + (i * 4), msr); +} + +/* + * Initialize any extra cores/threads in this package. + */ +static void intel_cores_init(struct device *cpu) +{ + struct cpuid_result result; + unsigned threads_per_package, threads_per_core, i; + + /* Logical processors (threads) per core */ + result = cpuid_ext(0xb, 0); + threads_per_core = result.ebx & 0xffff; + + /* Logical processors (threads) per package */ + result = cpuid_ext(0xb, 1); + threads_per_package = result.ebx & 0xffff; + + /* Only initialize extra cores from BSP */ + if (cpu->path.apic.apic_id) + return; + + printk(BIOS_DEBUG, "CPU: %u has %u cores, %u threads per core\n", + cpu->path.apic.apic_id, threads_per_package/threads_per_core, + threads_per_core); + + for (i = 1; i < threads_per_package; ++i) { + struct device_path cpu_path; + struct device *new; + + /* Build the cpu device path */ + cpu_path.type = DEVICE_PATH_APIC; + cpu_path.apic.apic_id = + cpu->path.apic.apic_id + i; + + /* Update APIC ID if no hyperthreading */ + if (threads_per_core == 1) + cpu_path.apic.apic_id <<= 1; + + /* Allocate the new cpu device structure */ + new = alloc_dev(cpu->bus, &cpu_path); + if (!new) + continue; + + printk(BIOS_DEBUG, "CPU: %u has core %u\n", + cpu->path.apic.apic_id, + new->path.apic.apic_id); + +#if IS_ENABLED(CONFIG_SMP) && CONFIG_MAX_CPUS > 1 + /* Start the new cpu */ + if (!start_cpu(new)) { + /* Record the error in cpu? */ + printk(BIOS_ERR, "CPU %u would not start!\n", + new->path.apic.apic_id); + } +#endif + } +} + +static void model_406dx_init(struct device *cpu) +{ + char processor_name[49]; + + /* Turn on caching if we haven't already */ + x86_enable_cache(); + + /* Clear out pending MCEs */ + configure_mca(); + + /* Print processor name */ + fill_processor_name(processor_name); + printk(BIOS_INFO, "CPU: %s.\n", processor_name); + + x86_mtrr_check(); + + /* Enable the local cpu apics */ + setup_lapic(); + + /* Enable virtualization */ + enable_vmx(); + + /* Configure Enhanced SpeedStep and Thermal Sensors */ + configure_misc(); + + /* Start up extra cores */ + intel_cores_init(cpu); +} + +static struct device_operations cpu_dev_ops = { + .init = model_406dx_init, +}; + +static struct cpu_device_id cpu_table[] = { + { X86_VENDOR_INTEL, 0x406d0 }, /* Intel Avoton/Rangeley A1 */ + { X86_VENDOR_INTEL, 0x406d8 }, /* Intel Avoton/Rangeley B0 */ + { 0, 0 }, +}; + +static const struct cpu_driver driver __cpu_driver = { + .ops = &cpu_dev_ops, + .id_table = cpu_table, +}; diff --git a/src/mainboard/intel/mohonpeak/Kconfig b/src/mainboard/intel/mohonpeak/Kconfig new file mode 100644 index 0000000000..996cea29a3 --- /dev/null +++ b/src/mainboard/intel/mohonpeak/Kconfig @@ -0,0 +1,86 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. +## +## This 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. +## + +if BOARD_INTEL_MOHONPEAK + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select CPU_INTEL_SOCKET_RPGA989 + select NORTHBRIDGE_INTEL_FSP_RANGELEY + select SOUTHBRIDGE_INTEL_FSP_RANGELEY + select BOARD_ROMSIZE_KB_2048 #actual chip is 8MB + select HAVE_ACPI_TABLES + select HAVE_OPTION_TABLE + select MMCONF_SUPPORT + select POST_IO + select HAVE_FSP_BIN if FSP_PACKAGE_DEFAULT + +config MAINBOARD_DIR + string + default intel/mohonpeak + +config MAINBOARD_PART_NUMBER + string + default "Mohon Peak CRB" + +config MAX_CPUS + int + default 16 + +config CACHE_ROM_SIZE_OVERRIDE + hex + default 0x800000 + +config FSP_FILE + string + default "../intel/fsp/rangeley/FvFsp.bin" + +config CBFS_SIZE + hex + default 0x00200000 + +config ENABLE_FSP_FAST_BOOT + bool + depends on HAVE_FSP_BIN + default y + +config VIRTUAL_ROM_SIZE + hex + depends on ENABLE_FSP_FAST_BOOT + default 0x400000 + +config FSP_PACKAGE_DEFAULT + bool "Configure defaults for the Intel FSP package" + default n + +config UART_FOR_CONSOLE + int + default 1 + help + The Mohon Peak board uses COM2 (2f8) for the serial console. + +config SEABIOS_MALLOC_UPPERMEMORY + bool + default n + help + The Avoton/Rangeley chip does not allow devices to write into the 0xe000 + segment. This means that USB/SATA devices will not work in SeaBIOS unless + we put the SeaBIOS buffer area down in the 0x9000 segment. + +endif # BOARD_INTEL_MOHONPEAK diff --git a/src/mainboard/intel/mohonpeak/Kconfig.name b/src/mainboard/intel/mohonpeak/Kconfig.name new file mode 100644 index 0000000000..2fc6540d06 --- /dev/null +++ b/src/mainboard/intel/mohonpeak/Kconfig.name @@ -0,0 +1,2 @@ +config BOARD_INTEL_MOHONPEAK + bool "Mohon Peak CRB" diff --git a/src/mainboard/intel/mohonpeak/Makefile.inc b/src/mainboard/intel/mohonpeak/Makefile.inc new file mode 100644 index 0000000000..37b43b4d40 --- /dev/null +++ b/src/mainboard/intel/mohonpeak/Makefile.inc @@ -0,0 +1,20 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2014 Sage Electronics Engineering, LLC. +## +## This 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. +## + +ramstage-y += irqroute.c diff --git a/src/mainboard/intel/mohonpeak/acpi/ec.asl b/src/mainboard/intel/mohonpeak/acpi/ec.asl new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/mainboard/intel/mohonpeak/acpi/mainboard.asl b/src/mainboard/intel/mohonpeak/acpi/mainboard.asl new file mode 100644 index 0000000000..a55894c5d7 --- /dev/null +++ b/src/mainboard/intel/mohonpeak/acpi/mainboard.asl @@ -0,0 +1,27 @@ +/* + * 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. + */ + +Device (PWRB) +{ + Name(_HID, EisaId("PNP0C0C")) + + // Wake + Name(_PRW, Package(){0x1d, 0x05}) +} diff --git a/src/mainboard/intel/mohonpeak/acpi/platform.asl b/src/mainboard/intel/mohonpeak/acpi/platform.asl new file mode 100644 index 0000000000..efefb99402 --- /dev/null +++ b/src/mainboard/intel/mohonpeak/acpi/platform.asl @@ -0,0 +1,64 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 The Chromium OS Authors. 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. + */ + +/* 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 _WAK method is called on system wakeup */ + +Method(_WAK,1) +{ + Return(Package(){0,0}) +} diff --git a/src/mainboard/intel/mohonpeak/acpi/superio.asl b/src/mainboard/intel/mohonpeak/acpi/superio.asl new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/mainboard/intel/mohonpeak/acpi/thermal.asl b/src/mainboard/intel/mohonpeak/acpi/thermal.asl new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/mainboard/intel/mohonpeak/acpi_tables.c b/src/mainboard/intel/mohonpeak/acpi_tables.c new file mode 100644 index 0000000000..b670904b46 --- /dev/null +++ b/src/mainboard/intel/mohonpeak/acpi_tables.c @@ -0,0 +1,83 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 The Chromium OS Authors. All rights reserved. + * Copyright (C) 2013 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static global_nvs_t *gnvs_; + +void acpi_create_gnvs(global_nvs_t *gnvs) +{ + gnvs_ = gnvs; + memset((void *)gnvs, 0, sizeof(*gnvs)); + gnvs->apic = 1; + gnvs->mpen = 1; /* Enable Multi Processing */ + gnvs->pcnt = dev_count_cpu(); + + /* Enable USB ports in S3 */ + gnvs->s3u0 = 1; + gnvs->s3u1 = 1; + + /* + * Enable Front USB ports in S5 by default + * to be consistent with back port behavior + */ + gnvs->s5u0 = 1; + gnvs->s5u1 = 1; + + /* IGD Displays */ + gnvs->ndid = 3; + gnvs->did[0] = 0x80000100; + gnvs->did[1] = 0x80000240; + gnvs->did[2] = 0x80000410; + gnvs->did[3] = 0x80000410; + gnvs->did[4] = 0x00000005; + +} + +unsigned long acpi_fill_madt(unsigned long current) +{ + /* Local APICs */ + current = acpi_create_madt_lapics(current); + + /* IOAPIC */ + current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, + 2, IO_APIC_ADDR, 0); + + /* INT_SRC_OVR */ + current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) + current, 0, 0, 2, 0); + current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) + current, 0, 9, 9, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH); + + return current; +} diff --git a/src/mainboard/intel/mohonpeak/board_info.txt b/src/mainboard/intel/mohonpeak/board_info.txt new file mode 100644 index 0000000000..f49af8aac5 --- /dev/null +++ b/src/mainboard/intel/mohonpeak/board_info.txt @@ -0,0 +1,4 @@ +Category: eval +ROM protocol: SPI +Flashrom support: y +Release year: 2014 diff --git a/src/mainboard/intel/mohonpeak/cmos.layout b/src/mainboard/intel/mohonpeak/cmos.layout new file mode 100644 index 0000000000..4353e7d736 --- /dev/null +++ b/src/mainboard/intel/mohonpeak/cmos.layout @@ -0,0 +1,117 @@ +## +## This file is part of the coreboot project. +## +## 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. +## + +# ----------------------------------------------------------------- +entries + +# ----------------------------------------------------------------- +# Status Register A +# ----------------------------------------------------------------- +# Status Register B +# ----------------------------------------------------------------- +# Status Register C +#96 4 r 0 status_c_rsvd +#100 1 r 0 uf_flag +#101 1 r 0 af_flag +#102 1 r 0 pf_flag +#103 1 r 0 irqf_flag +# ----------------------------------------------------------------- +# Status Register D +#104 7 r 0 status_d_rsvd +#111 1 r 0 valid_cmos_ram +# ----------------------------------------------------------------- +# Diagnostic Status Register +#112 8 r 0 diag_rsvd1 + +# ----------------------------------------------------------------- +0 120 r 0 reserved_memory +#120 264 r 0 unused + +# ----------------------------------------------------------------- +# RTC_BOOT_BYTE (coreboot hardcoded) +384 1 e 4 boot_option +385 1 e 4 last_boot +388 4 r 0 reboot_bits +#390 2 r 0 unused? + +# ----------------------------------------------------------------- +# coreboot config options: console +392 3 e 5 baud_rate +395 4 e 6 debug_level +#399 1 r 0 unused + +# coreboot config options: cpu +400 1 e 2 hyper_threading +#401 7 r 0 unused + +# coreboot config options: southbridge +408 1 e 1 nmi +409 2 e 7 power_on_after_fail +#411 5 r 0 unused + +# MRC Scrambler Seed values +896 32 r 0 mrc_scrambler_seed +928 32 r 0 mrc_scrambler_seed_s3 + +# coreboot config options: check sums +984 16 h 0 check_sum +#1000 24 r 0 amd_reserved + +#save timestamps in pre-ram boot areas +1719 64 h 0 timestamp_value1 +1783 64 h 0 timestamp_value2 +1847 64 h 0 timestamp_value3 +1911 64 h 0 timestamp_value4 +1975 64 h 0 timestamp_value5 + +# ----------------------------------------------------------------- + +enumerations + +#ID value text +1 0 Disable +1 1 Enable +2 0 Enable +2 1 Disable +4 0 Fallback +4 1 Normal +5 0 115200 +5 1 57600 +5 2 38400 +5 3 19200 +5 4 9600 +5 5 4800 +5 6 2400 +5 7 1200 +6 1 Emergency +6 2 Alert +6 3 Critical +6 4 Error +6 5 Warning +6 6 Notice +6 7 Info +6 8 Debug +6 9 Spew +7 0 Disable +7 1 Enable +7 2 Keep +# ----------------------------------------------------------------- +checksums + +checksum 392 415 984 diff --git a/src/mainboard/intel/mohonpeak/devicetree.cb b/src/mainboard/intel/mohonpeak/devicetree.cb new file mode 100644 index 0000000000..9874b98b68 --- /dev/null +++ b/src/mainboard/intel/mohonpeak/devicetree.cb @@ -0,0 +1,68 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2013 Sage Electronic Engineering, LLC. +# +# This 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. +# +chip northbridge/intel/fsp_rangeley + + device cpu_cluster 0 on + chip cpu/intel/socket_rPGA989 + device lapic 0 on end + end + chip cpu/intel/fsp_model_406dx + # Magic APIC ID to locate this chip + device lapic 0xACAC off end + + register "c1_battery" = "3" # ACPI(C1) = MWAIT(C3) + register "c2_battery" = "4" # ACPI(C2) = MWAIT(C6) + register "c3_battery" = "5" # ACPI(C3) = MWAIT(C7) + + register "c1_acpower" = "3" # ACPI(C1) = MWAIT(C3) + register "c2_acpower" = "4" # ACPI(C2) = MWAIT(C6) + register "c3_acpower" = "5" # ACPI(C3) = MWAIT(C7) + end + end + + device domain 0 on + device pci 00.0 on end # host bridge + device pci 1.0 on end # PCIe Port #1 + device pci 2.0 on end # PCIe Port #2 + device pci 3.0 on end # PCIe Port #3 + device pci 4.0 on end # PCIe Port #4 + chip southbridge/intel/fsp_rangeley # Rangeley SB + + register "ide_legacy_combined" = "0x0" + register "sata_ahci" = "0x1" + register "sata_port_map" = "0x0f" + + register "fadt_pm_profile" = "PM_DESKTOP" + register "fadt_boot_arch" = "ACPI_FADT_LEGACY_FREE" + + device pci 0b.0 on end # IQIA + device pci 0e.0 on end # RAS + device pci 13.0 on end # SMBus 1 + device pci 14.0 on end # GbE 0 + device pci 14.1 on end # GbE 1 + device pci 14.2 on end # GbE 2 + device pci 14.3 on end # GbE 3 + device pci 16.0 on end # USB EHCI + device pci 17.0 on end # SATA 2.0 + device pci 18.0 on end # SATA 3.0 + device pci 1f.0 on end # LPC bridge + device pci 1f.3 on end # SMBus 0 + end + end +end diff --git a/src/mainboard/intel/mohonpeak/dsdt.asl b/src/mainboard/intel/mohonpeak/dsdt.asl new file mode 100644 index 0000000000..c44d56f21a --- /dev/null +++ b/src/mainboard/intel/mohonpeak/dsdt.asl @@ -0,0 +1,53 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2011 The ChromiumOS Authors. 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. + */ + +DefinitionBlock( + "dsdt.aml", + "DSDT", + 0x02, // DSDT revision: ACPI v2.0 + "COREv4", // OEM id + "COREBOOT", // OEM table id + 0x20110725 // OEM revision +) +{ + // Include debug methods + #include + + // Some generic macros + #include "acpi/platform.asl" + + // global NVS and variables + #include + + #include "acpi/thermal.asl" + + #include + + Scope (\_SB) { + Device (PCI0) + { + #include + #include + } + } + + /* Chipset specific sleep states */ + #include +} diff --git a/src/mainboard/intel/mohonpeak/fadt.c b/src/mainboard/intel/mohonpeak/fadt.c new file mode 100644 index 0000000000..7889f5f741 --- /dev/null +++ b/src/mainboard/intel/mohonpeak/fadt.c @@ -0,0 +1,42 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#include +#include + +void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) +{ + acpi_fill_in_fadt(fadt,facs,dsdt); + +#define PLATFORM_HAS_FADT_CUSTOMIZATIONS 0 + + + /* + * Platform specific customizations go here. + * Update the #define above if customizations are added. + */ + + +#if PLATFORM_HAS_FADT_CUSTOMIZATIONS + header->checksum = 0; + header->checksum = + acpi_checksum((void *) fadt, sizeof(acpi_fadt_t)); +#endif + +} diff --git a/src/mainboard/intel/mohonpeak/gpio.h b/src/mainboard/intel/mohonpeak/gpio.h new file mode 100644 index 0000000000..7333eb05ad --- /dev/null +++ b/src/mainboard/intel/mohonpeak/gpio.h @@ -0,0 +1,178 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 The Chromium OS Authors. 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. + */ + +#ifndef MOHONPEAK_GPIO_H +#define MOHONPEAK_GPIO_H + +#include + +/* Core GPIO */ +const struct soc_gpio soc_gpio_mode = { + .gpio15 = GPIO_MODE_GPIO, /* Board ID GPIO */ + .gpio17 = GPIO_MODE_GPIO, /* Board ID GPIO */ +}; + +const struct soc_gpio soc_gpio_direction = { + .gpio15 = GPIO_DIR_INPUT, /* Board ID GPIO */ + .gpio17 = GPIO_DIR_INPUT, /* Board ID GPIO */ +}; + +const struct soc_gpio soc_gpio_level = { +}; + +const struct soc_gpio soc_gpio_tpe = { +}; + +const struct soc_gpio soc_gpio_tne = { +}; + +const struct soc_gpio soc_gpio_ts = { +}; + +/* Keep the CFIO struct in register order, not gpio order. */ +const struct soc_cfio soc_cfio_core[] = { + { 0x8000, 0x0000, 0x0004, 0x040c }, /* CFIO gpios_28 */ + { 0x8000, 0x0000, 0x0002, 0x040c }, /* CFIO gpios_27 */ + { 0x8500, 0x0000, 0x0002, 0x040c }, /* CFIO gpios_26 */ + { 0x8480, 0x0000, 0x0002, 0x040c }, /* CFIO gpios_21 */ + { 0x8480, 0x0000, 0x0002, 0x040c }, /* CFIO gpios_22 */ + { 0x8480, 0x0000, 0x0002, 0x040c }, /* CFIO gpios_23 */ + { 0x8000, 0x0000, 0x0004, 0x040c }, /* CFIO gpios_25 */ + { 0x8480, 0x0000, 0x0002, 0x040c }, /* CFIO gpios_24 */ + { 0x80c028, 0x30003, 0x0004, 0x040c }, /* CFIO gpios_19 */ + { 0x80c028, 0x30003, 0x0004, 0x040c }, /* CFIO gpios_20 */ + { 0xc028, 0x30003, 0x0004, 0x040c }, /* CFIO gpios_18 */ + { 0x04a9, 0x30003, 0x0002, 0x040c }, /* CFIO gpios_17 */ + { 0x80c028, 0x30003, 0x0004, 0x040c }, /* CFIO gpios_7 */ + { 0xc028, 0x30003, 0x0004, 0x040c }, /* CFIO gpios_4 */ + { 0xc028, 0x30003, 0x0004, 0x040c }, /* CFIO gpios_5 */ + { 0xc528, 0x30003, 0x0002, 0x040c }, /* CFIO gpios_6 */ + { 0xc028, 0x30003, 0x0004, 0x040c }, /* CFIO gpios_1 */ + { 0xc028, 0x20002, 0x0004, 0x040c }, /* CFIO gpios_2 */ + { 0xc028, 0x20002, 0x0004, 0x040c }, /* CFIO gpios_3 */ + { 0xc528, 0x30003, 0x0002, 0x040c }, /* CFIO gpios_0 */ + { 0x0000, 0x0000, 0x0000, 0x0000 }, /* CFIO Reserved */ + { 0xc4a8, 0x30003, 0x0002, 0x040c }, /* CFIO gpios_10 */ + { 0xc4a8, 0x30003, 0x0002, 0x040c }, /* CFIO gpios_13 */ + { 0xc4a8, 0x30003, 0x0000, 0x040c }, /* CFIO gpios_14 */ + { 0xc4a8, 0x30003, 0x0002, 0x040c }, /* CFIO gpios_11 */ + { 0xc4a8, 0x30003, 0x0000, 0x040c }, /* CFIO gpios_8 */ + { 0xc4a8, 0x30003, 0x0002, 0x040c }, /* CFIO gpios_9 */ + { 0xc4a8, 0x30003, 0x0000, 0x040c }, /* CFIO gpios_12 */ + { 0xc4a8, 0x30003, 0x0002, 0x040c }, /* CFIO gpios_29 */ + { 0xc4a8, 0x30003, 0x0002, 0x040c }, /* CFIO gpios_30 */ + { 0x04a9, 0x30003, 0x0002, 0x040c }, /* CFIO gpios_15 */ + { 0xc028, 0x30003, 0x0004, 0x040c }, /* CFIO gpios_16 */ +}; + +/* SUS GPIO */ +const struct soc_gpio soc_gpio_sus_mode = { + .gpio2 = GPIO_MODE_GPIO, +}; + +const struct soc_gpio soc_gpio_sus_direction = { + .gpio2 = GPIO_DIR_INPUT, +}; + +const struct soc_gpio soc_gpio_sus_level = { +}; + +const struct soc_gpio soc_gpio_sus_tpe = { +}; + +const struct soc_gpio soc_gpio_sus_tne = { +}; + +const struct soc_gpio soc_gpio_sus_ts = { +}; + +const struct soc_gpio soc_gpio_sus_we = { +}; + + +/* Keep the CFIO struct in register order, not gpio order. */ +const struct soc_cfio soc_cfio_sus[] = { + { 0xc028, 0x30003, 0x0004, 0x040c }, /* CFIO SUS gpios_21 */ + { 0xc028, 0x30003, 0x0004, 0x040c }, /* CFIO SUS gpios_20 */ + { 0xc028, 0x30003, 0x0004, 0x040c }, /* CFIO SUS gpios_19 */ + { 0xc028, 0x30003, 0x0004, 0x040c }, /* CFIO SUS gpios_22 */ + { 0xc4a8, 0x30003, 0x0002, 0x040c }, /* CFIO SUS gpios_17 */ + { 0xc4a8, 0x30003, 0x0002, 0x040c }, /* CFIO SUS gpios_18 */ + { 0x0000, 0x0000, 0x0000, 0x0000 }, /* CFIO Reserved */ + { 0x0000, 0x0000, 0x0000, 0x0000 }, /* CFIO Reserved */ + { 0x0000, 0x0000, 0x0000, 0x0000 }, /* CFIO Reserved */ + { 0xc4a8, 0x30003, 0x0002, 0x040c }, /* CFIO SUS gpios_14 */ + { 0xc028, 0x30003, 0x0004, 0x040c }, /* CFIO SUS gpios_13 */ + { 0xc028, 0x30003, 0x0004, 0x040c }, /* CFIO SUS gpios_15 */ + { 0xc028, 0x30003, 0x0004, 0x040c }, /* CFIO SUS gpios_16 */ + { 0xc4a8, 0x30003, 0x0002, 0x040c }, /* CFIO SUS gpios_25 */ + { 0xc4a8, 0x30003, 0x0002, 0x040c }, /* CFIO SUS gpios_24 */ + { 0xc4a8, 0x30003, 0x0002, 0x040c }, /* CFIO SUS gpios_26 */ + { 0xc4a8, 0x30003, 0x0002, 0x040c }, /* CFIO SUS gpios_27 */ + { 0xc4a8, 0x30003, 0x0002, 0x040c }, /* CFIO SUS gpios_23 */ + { 0xc4a8, 0x30003, 0x0003, 0x040c }, /* CFIO SUS gpios_2 */ + { 0xc4a8, 0x30003, 0x0003, 0x040c }, /* CFIO SUS gpios_1 */ + { 0x8050, 0x0000, 0x0004, 0x040c }, /* CFIO SUS gpios_7 */ + { 0x0000, 0x0000, 0x0000, 0x0000 }, /* CFIO Reserved */ + { 0x0000, 0x0000, 0x0000, 0x0000 }, /* CFIO Reserved */ + { 0xc028, 0x30003, 0x0004, 0x040c }, /* CFIO SUS gpios_3 */ + { 0xc4a8, 0x30003, 0x0003, 0x040c }, /* CFIO SUS gpios_0 */ + { 0x0000, 0x0000, 0x0000, 0x0000 }, /* CFIO Reserved */ + { 0x0000, 0x0000, 0x0000, 0x0000 }, /* CFIO Reserved */ + { 0x8000, 0x0000, 0x0004, 0x040c }, /* CFIO SUS gpios_12 */ + { 0x8050, 0x0000, 0x0004, 0x040c }, /* CFIO SUS gpios_6 */ + { 0xc028, 0x30003, 0x0004, 0x040c }, /* CFIO SUS gpios_10 */ + { 0xc4a8, 0x30003, 0x0002, 0x040c }, /* CFIO SUS gpios_9 */ + { 0xc4a8, 0x30003, 0x0002, 0x040c }, /* CFIO SUS gpios_8 */ + { 0x0000, 0x0000, 0x0000, 0x0000 }, /* CFIO Reserved */ + { 0x0000, 0x0000, 0x0000, 0x0000 }, /* CFIO Reserved */ + { 0x8050, 0x0000, 0x0004, 0x040c }, /* CFIO SUS gpios_4 */ + { 0xc4a8, 0x30003, 0x0002, 0x040c }, /* CFIO SUS gpios_11 */ + { 0x0000, 0x0000, 0x0000, 0x0000 }, /* CFIO Reserved */ + { 0x0000, 0x0000, 0x0000, 0x0000 }, /* CFIO Reserved */ + { 0x0000, 0x0000, 0x0000, 0x0000 }, /* CFIO Reserved */ + { 0x0000, 0x0000, 0x0000, 0x0000 }, /* CFIO Reserved */ + { 0xc028, 0x30003, 0x0004, 0x040c }, /* CFIO SUS gpios_5 */ +}; + +const struct soc_gpio_map gpio_map = { + .core = { + .mode = &soc_gpio_mode, + .direction = &soc_gpio_direction, + .level = &soc_gpio_level, + .tpe = &soc_gpio_tpe, + .tne = &soc_gpio_tne, + .ts = &soc_gpio_ts, + .cfio_init = &soc_cfio_core[0], + .cfio_entrynum = sizeof(soc_cfio_core) / sizeof(struct soc_cfio), + }, + .sus = { + .mode = &soc_gpio_sus_mode, + .direction = &soc_gpio_sus_direction, + .level = &soc_gpio_sus_level, + .tpe = &soc_gpio_sus_tpe, + .tne = &soc_gpio_sus_tne, + .ts = &soc_gpio_sus_ts, + .we = &soc_gpio_sus_we, + .cfio_init = &soc_cfio_sus[0], + .cfio_entrynum = sizeof(soc_cfio_sus) / sizeof(struct soc_cfio), + }, +}; + +#endif /* MOHONPEAK_GPIO_H */ diff --git a/src/mainboard/intel/mohonpeak/irq_tables.c b/src/mainboard/intel/mohonpeak/irq_tables.c new file mode 100644 index 0000000000..e7989f7cae --- /dev/null +++ b/src/mainboard/intel/mohonpeak/irq_tables.c @@ -0,0 +1,67 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. + * Copyright (C) 2013, Intel Corporation. + * + * This 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. + */ + +#include + +#define PIRQA 0x08 +#define PIRQB 0x09 +#define PIRQC 0x0a +#define PIRQD 0x0b +#define PIRQE 0x0c +#define PIRQF 0x0d +#define PIRQG 0x0e +#define PIRQH 0x0f + +#define PCI_IRQS 0xDCF0 + +const struct irq_routing_table intel_irq_routing_table = { + PIRQ_SIGNATURE, /* u32 signature */ + PIRQ_VERSION, /* u16 version */ + 32+16*CONFIG_IRQ_SLOT_COUNT, /* There can be total 18 devices on the bus */ + 0x00, /* Where the interrupt router lies (bus) */ + (0x1f<<3)|0x0, /* Where the interrupt router lies (dev) */ + 0, /* IRQs devoted exclusively to PCI usage */ + 0x8086, /* Vendor */ + 0x0F1C, /* Device */ + 0, /* miniport */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */ + 0x86, /* u8 checksum. */ + { + /* bus, dev|fn, {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu */ + {0x00,(0x01<<3)|0x0, {{PIRQA, PCI_IRQS}, {PIRQB, PCI_IRQS}, {PIRQC, PCI_IRQS}, {PIRQD, PCI_IRQS}}, 0x0, 0x0}, // PCIE Port 1: INTA-PIRQA, INTB-PIRQB, INTC-PIRQC, INTD-PIRQD + {0x00,(0x02<<3)|0x0, {{PIRQA, PCI_IRQS}, {PIRQB, PCI_IRQS}, {PIRQC, PCI_IRQS}, {PIRQD, PCI_IRQS}}, 0x0, 0x0}, // PCIE Port 2: INTA-PIRQA, INTB-PIRQB, INTC-PIRQC, INTD-PIRQD + {0x00,(0x03<<3)|0x0, {{PIRQE, PCI_IRQS}, {PIRQF, PCI_IRQS}, {PIRQG, PCI_IRQS}, {PIRQH, PCI_IRQS}}, 0x0, 0x0}, // PCIE Port 3: INTA-PIRQE, INTB-PIRQF, INTC-PIRQG, INTD-PIRQH + {0x00,(0x04<<3)|0x0, {{PIRQE, PCI_IRQS}, {PIRQF, PCI_IRQS}, {PIRQG, PCI_IRQS}, {PIRQH, PCI_IRQS}}, 0x0, 0x0}, // PCIE Port 4: INTA-PIRQE, INTB-PIRQF, INTC-PIRQG, INTD-PIRQH + {0x00,(0x0b<<3)|0x0, {{PIRQA, PCI_IRQS}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, // IQAT INTA-PIRQA + {0x00,(0x0f<<3)|0x0, {{PIRQA, PCI_IRQS}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, // RCEC INTA-PIRQA + {0x00,(0x13<<3)|0x0, {{PIRQA, PCI_IRQS}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, // SMBUS #1 INTA-PIRQA + {0x00,(0x14<<3)|0x0, {{PIRQE, PCI_IRQS}, {PIRQF, PCI_IRQS}, {PIRQG, PCI_IRQS}, {PIRQH, PCI_IRQS}}, 0x0, 0x0}, // GbE, INTA-PIRQE, INTB-PIRQF, INTC-PIRQG, INTD-PIRQH + {0x00,(0x16<<3)|0x0, {{PIRQH, PCI_IRQS}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, // EHCI INTA-PIRQH + {0x00,(0x17<<3)|0x0, {{PIRQD, PCI_IRQS}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, // SATA2 INTA-PIRQD + {0x00,(0x18<<3)|0x0, {{PIRQD, PCI_IRQS}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, // SATA3 INTA-PIRQD + {0x00,(0x1f<<3)|0x0, {{0x00, 0x0000}, {PIRQC, PCI_IRQS}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, // LPC/SMBUS #0 INTB - PIRQC + } +}; + +unsigned long write_pirq_routing_table(unsigned long addr) +{ + return copy_pirq_routing_table(addr, &intel_irq_routing_table); +} diff --git a/src/mainboard/intel/mohonpeak/irqroute.c b/src/mainboard/intel/mohonpeak/irqroute.c new file mode 100644 index 0000000000..12d88e0082 --- /dev/null +++ b/src/mainboard/intel/mohonpeak/irqroute.c @@ -0,0 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * Copyright (C) 2014 Sage Electronics Engineering, LLC. + * + * This 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. + */ + +#include "irqroute.h" + +DEFINE_IRQ_ROUTES; diff --git a/src/mainboard/intel/mohonpeak/irqroute.h b/src/mainboard/intel/mohonpeak/irqroute.h new file mode 100644 index 0000000000..1fc03b9a39 --- /dev/null +++ b/src/mainboard/intel/mohonpeak/irqroute.h @@ -0,0 +1,73 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * Copyright (C) 2014 Sage Electronics Engineering, LLC. + * + * This 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. + */ + +#ifndef IRQROUTE_H +#define IRQROUTE_H + +#include +#include + +/* + * IR01h PCIe INT(ABCD) - PIRQ ABCD + * IR02h PCIe INT(ABCD) - PIRQ ABCD + * IR03h PCIe INT(ABCD) - PIRQ ABCD + * IR04h PCIe INT(ABCD) - PIRQ ABCD + * IR0Bh IQIA INT(ABCD) - PIRQ EFGH + * IR0Eh RAS INT(A) - PIRQ A + * IR13h SMBUS1 INT(A) - PIRQ B + * IR15h GBE INT(A) - PIRQ CDEF + * IR1Dh EHCI INT(A) - PIRQ G + * IR13h SATA2.0 INT(A) - PIRQ H + * IR13h SATA3.0 INT(A) - PIRQ A + * IR1Fh LPC INT(ABCD) - PIRQ HGBC + */ +#define PCI_DEV_PIRQ_ROUTES \ + PCI_DEV_PIRQ_ROUTE(PCIE_PORT1_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(PCIE_PORT2_DEV, D, C, B, A), \ + PCI_DEV_PIRQ_ROUTE(PCIE_PORT3_DEV, E, F, G, H), \ + PCI_DEV_PIRQ_ROUTE(PCIE_PORT4_DEV, H, G, F, E), \ + PCI_DEV_PIRQ_ROUTE(IQAT_DEV, E, F, G, H), \ + PCI_DEV_PIRQ_ROUTE(HOST_BRIDGE_DEV, H, A, A, A), \ + PCI_DEV_PIRQ_ROUTE(RCEC_DEV, A, A, A, A), \ + PCI_DEV_PIRQ_ROUTE(SMBUS1_DEV, B, A, A, A), \ + PCI_DEV_PIRQ_ROUTE(GBE_DEV, C, D, E, F), \ + PCI_DEV_PIRQ_ROUTE(USB2_DEV, G, A, A, A), \ + PCI_DEV_PIRQ_ROUTE(SATA2_DEV, H, A, A, A), \ + PCI_DEV_PIRQ_ROUTE(SATA3_DEV, A, A, A, A), \ + PCI_DEV_PIRQ_ROUTE(PCU_DEV, H, G, B, C) + +/* + * Route each PIRQ[A-H] to a PIC IRQ[0-15] + * Reserved: 0, 1, 2, 8, 13 + * PS2 keyboard: 12 + * ACPI/SCI: 9 + * Floppy: 6 + */ +#define PIRQ_PIC_ROUTES \ + PIRQ_PIC(A, 10), \ + PIRQ_PIC(B, 11), \ + PIRQ_PIC(C, 10), \ + PIRQ_PIC(D, 11), \ + PIRQ_PIC(E, 14), \ + PIRQ_PIC(F, 15), \ + PIRQ_PIC(G, 14), \ + PIRQ_PIC(H, 15) + +#endif /* IRQROUTE_H */ \ No newline at end of file diff --git a/src/mainboard/intel/mohonpeak/mainboard.c b/src/mainboard/intel/mohonpeak/mainboard.c new file mode 100644 index 0000000000..c2a105b375 --- /dev/null +++ b/src/mainboard/intel/mohonpeak/mainboard.c @@ -0,0 +1,34 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2011 The ChromiumOS Authors. 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. + */ + +#include + +/* + * mainboard_enable is executed as first thing after enumerate_buses(). + * This is the earliest point to add customization. + */ +static void mainboard_enable(device_t dev) +{ + +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; diff --git a/src/mainboard/intel/mohonpeak/romstage.c b/src/mainboard/intel/mohonpeak/romstage.c new file mode 100644 index 0000000000..8c0cca66d8 --- /dev/null +++ b/src/mainboard/intel/mohonpeak/romstage.c @@ -0,0 +1,86 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2010 coresystems GmbH + * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. + * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gpio.h" + +static void interrupt_routing_config(void) +{ + u8 *ilb_base = (u8 *)(pci_read_config32(SOC_LPC_DEV, IBASE) & ~0xf); + + /* + * Initialize Interrupt Routings for each device in ilb_base_address. + * IR01 map to PCIe device 0x01 ... IR31 to device 0x1F. + * PIRQ_A maps to IRQ 16 ... PIRQ_H maps tp IRQ 23. + * This should match devicetree and the ACPI IRQ routing/ + */ + write32(ilb_base + ILB_ACTL, 0x0000); /* ACTL bit 2:0 SCIS IRQ9 */ + write16(ilb_base + ILB_IR01, 0x3210); /* IR01h IR(ABCD) - PIRQ(ABCD) */ + write16(ilb_base + ILB_IR02, 0x3210); /* IR02h IR(ABCD) - PIRQ(ABCD) */ + write16(ilb_base + ILB_IR03, 0x7654); /* IR03h IR(ABCD) - PIRQ(EFGH) */ + write16(ilb_base + ILB_IR04, 0x7654); /* IR04h IR(ABCD) - PIRQ(EFGH) */ + write16(ilb_base + ILB_IR20, 0x7654); /* IR14h IR(ABCD) - PIRQ(EFGH) */ + write16(ilb_base + ILB_IR22, 0x0007); /* IR16h IR(A) - PIRQ(H) */ + write16(ilb_base + ILB_IR23, 0x0003); /* IR17h IR(A) - PIRQ(D) */ + write16(ilb_base + ILB_IR24, 0x0003); /* IR18h IR(A) - PIRQ(D) */ + write16(ilb_base + ILB_IR31, 0x0020); /* IR1Fh IR(B) - PIRQ(C) */ +} + +/** + * /brief mainboard call for setup that needs to be done before fsp init + * + */ +void early_mainboard_romstage_entry(void) +{ + setup_soc_gpios(&gpio_map); +} + +/** + * /brief mainboard call for setup that needs to be done after fsp init + * + */ +void late_mainboard_romstage_entry(void) +{ + interrupt_routing_config(); +} + +/** + * Get function disables - most of these will be done automatically + * @param mask pointer to the function-disable bitfield + */ +void get_func_disables(uint32_t *mask) +{ + +} + +void romstage_fsp_rt_buffer_callback(FSP_INIT_RT_BUFFER *FspRtBuffer) +{ + /* No overrides needed */ + return; +} diff --git a/src/mainboard/intel/mohonpeak/thermal.h b/src/mainboard/intel/mohonpeak/thermal.h new file mode 100644 index 0000000000..a92d410da5 --- /dev/null +++ b/src/mainboard/intel/mohonpeak/thermal.h @@ -0,0 +1,33 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 The Chromium OS Authors. 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. + */ + +#ifndef MOHONPEAK_THERMAL_H +#define MOHONPEAK_THERMAL_H + + +/* Temperature which OS will shutdown at */ +#define CRITICAL_TEMPERATURE 100 + +/* Temperature which OS will throttle CPU */ +#define PASSIVE_TEMPERATURE 90 + +/* Tj_max value for calculating PECI CPU temperature */ +#define MAX_TEMPERATURE 100 + +#endif diff --git a/src/northbridge/intel/fsp_rangeley/Kconfig b/src/northbridge/intel/fsp_rangeley/Kconfig new file mode 100644 index 0000000000..0ac81df65d --- /dev/null +++ b/src/northbridge/intel/fsp_rangeley/Kconfig @@ -0,0 +1,92 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2010 Google Inc. +## Copyright (C) 2013 Sage Electronic Engineering, LLC. +## +## This 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. +## + +config NORTHBRIDGE_INTEL_FSP_RANGELEY + bool + select CPU_INTEL_FSP_MODEL_406DX + +if NORTHBRIDGE_INTEL_FSP_RANGELEY + +config MMCONF_BASE_ADDRESS + hex + default 0xe0000000 + +choice + prompt "Set TSEG Size" + default SET_TSEG_1MB if SET_DEFAULT_TSEG_1MB + default SET_TSEG_2MB if SET_DEFAULT_TSEG_2MB + default SET_TSEG_4MB if SET_DEFAULT_TSEG_4MB + default SET_TSEG_8MB if SET_DEFAULT_TSEG_8MB + +config SET_TSEG_1MB + bool "1 MB" + help + Set the TSEG area to 1 MB. + +config SET_TSEG_2MB + bool "2 MB" + help + Set the TSEG area to 2 MB. + +config SET_TSEG_4MB + bool "4 MB" + help + Set the TSEG area to 4 MB. + +config SET_TSEG_8MB + bool "8 MB" + help + Set the TSEG area to 8 MB. +endchoice + +config SMM_TSEG_SIZE + hex + default 0x200000 if SET_TSEG_2MB + default 0x400000 if SET_TSEG_4MB + default 0x800000 if SET_TSEG_8MB + default 0x100000 # SET_TSEG_1MB + +config SMM_RESERVED_SIZE + hex + default 0x200000 if SET_TSEG_2MB + default 0x400000 if SET_TSEG_4MB + default 0x800000 if SET_TSEG_8MB + default 0x100000 # SET_TSEG_1MB + +config SET_DEFAULT_TSEG_1MB + bool + default n + +config SET_DEFAULT_TSEG_2MB + bool + default n + +config SET_DEFAULT_TSEG_4MB + bool + default n + +config SET_DEFAULT_TSEG_8MB + bool + default n + +# Rangeley Specific FSP Kconfig +source src/northbridge/intel/fsp_rangeley/fsp/Kconfig + +endif # NORTHBRIDGE_INTEL_FSP_RANGELEY diff --git a/src/northbridge/intel/fsp_rangeley/Makefile.inc b/src/northbridge/intel/fsp_rangeley/Makefile.inc new file mode 100644 index 0000000000..3b88913452 --- /dev/null +++ b/src/northbridge/intel/fsp_rangeley/Makefile.inc @@ -0,0 +1,41 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2010 Google Inc. +# Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. +# +# This 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. +# + +ifeq ($(CONFIG_NORTHBRIDGE_INTEL_FSP_RANGELEY),y) + +subdirs-y += fsp +ramstage-y += northbridge.c +ramstage-y += raminit.c + +ramstage-y += acpi.c +ramstage-y += port_access.c + +romstage-y += raminit.c +romstage-y += ../../../arch/x86/walkcbfs.S +romstage-y += port_access.c + +smm-$(CONFIG_HAVE_SMI_HANDLER) += udelay.c + +CPPFLAGS_common += -I$(src)/mainboard/$(MAINBOARDDIR) + +CPPFLAGS_common += -I$(src)/northbridge/intel/fsp_rangeley/ +CPPFLAGS_common += -I$(src)/northbridge/intel/fsp_rangeley/fsp + +endif diff --git a/src/northbridge/intel/fsp_rangeley/acpi.c b/src/northbridge/intel/fsp_rangeley/acpi.c new file mode 100644 index 0000000000..c726155b75 --- /dev/null +++ b/src/northbridge/intel/fsp_rangeley/acpi.c @@ -0,0 +1,78 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 The Chromium OS Authors + * Copyright (C) 2013 Sage Electronic Engineering, LLC + * + * This 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "northbridge.h" + +unsigned long acpi_fill_mcfg(unsigned long current) +{ + device_t dev; + u32 pciexbar = 0; + u32 pciexbar_reg; + int max_buses; + int pci_dev_id; + + for (pci_dev_id = PCI_DEVICE_ID_RG_MIN; pci_dev_id <= PCI_DEVICE_ID_RG_MAX; pci_dev_id++) { + dev = dev_find_device(PCI_VENDOR_ID_INTEL, pci_dev_id, 0); + if (dev) + break; + } + + if (!dev) + return current; + + pciexbar_reg = sideband_read(B_UNIT, BECREG); + + /* MMCFG not supported or not enabled. */ + if (!(pciexbar_reg & (1 << 0))) + return current; + + /* 256MB ECAM range */ + pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)); + max_buses = 256; + + current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *) current, + pciexbar, 0x0, 0x0, max_buses - 1); + + return current; +} + +void northbridge_acpi_fill_ssdt_generator(device_t device) +{ + u32 bmbound; + char pscope[] = "\\_SB.PCI0"; + + bmbound = sideband_read(B_UNIT, BMBOUND); + acpigen_write_scope(pscope); + acpigen_write_name_dword("BMBD", bmbound); + acpigen_pop_len(); + generate_cpu_entries(device); +} diff --git a/src/northbridge/intel/fsp_rangeley/acpi/hostbridge.asl b/src/northbridge/intel/fsp_rangeley/acpi/hostbridge.asl new file mode 100644 index 0000000000..a991494769 --- /dev/null +++ b/src/northbridge/intel/fsp_rangeley/acpi/hostbridge.asl @@ -0,0 +1,139 @@ +/* + * 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. + */ + +#include + +Name(_HID,EISAID("PNP0A08")) // PCIe +Name(_CID,EISAID("PNP0A03")) // PCI + +Name(_ADR, 0) +Name(_BBN, 0) + +// This is in the SSDT and can be accessed by the DSDT +External (BMBD) + +// Current Resource Settings + +Method (_CRS, 0, Serialized) +{ + Name (MCRS, ResourceTemplate() + { + // Bus Numbers + WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode, + 0x0000, 0x0000, 0x00ff, 0x0000, 0x0100,,, PB00) + + // IO Region 0 + DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, 0x0000, 0x0cf7, 0x0000, 0x0cf8,,, PI00) + + // PCI Config Space + Io (Decode16, 0x0cf8, 0x0cf8, 0x0001, 0x0008) + + // IO Region 1 + DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, 0x0d00, 0xffff, 0x0000, 0xf300,,, PI01) + + // VGA memory (0xa0000-0xbffff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000a0000, 0x000bffff, 0x00000000, + 0x00020000,,, ASEG) + + // OPROM reserved (0xd0000-0xd3fff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000d0000, 0x000d3fff, 0x00000000, + 0x00004000,,, OPR0) + + // OPROM reserved (0xd4000-0xd7fff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000d4000, 0x000d7fff, 0x00000000, + 0x00004000,,, OPR1) + + // OPROM reserved (0xd8000-0xdbfff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000d8000, 0x000dbfff, 0x00000000, + 0x00004000,,, OPR2) + + // OPROM reserved (0xdc000-0xdffff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000dc000, 0x000dffff, 0x00000000, + 0x00004000,,, OPR3) + + // 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, 0, 0x00000000, + 0,,, PM01) + + // TPM Area (0xfed40000-0xfed44fff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0xfed40000, 0xfed44fff, 0x00000000, + 0x00005000,,, TPMR) + }) // End MCRS + + // Find PCI resource area in MCRS + CreateDwordField(MCRS, PM01._MIN, PMIN) + CreateDwordField(MCRS, PM01._MAX, PMAX) + CreateDwordField(MCRS, PM01._LEN, PLEN) + + // Fix up PCI memory region + // Start with Top of Lower Usable DRAM + // Memory goes from BMBOUND to CONFIG_MMCONF_BASE_ADDRESS (PM01 above) + Store (BMBD, PMIN) + Store (Subtract(CONFIG_MMCONF_BASE_ADDRESS, 1), PMAX) + Add(Subtract(PMAX, PMIN), 1, PLEN) // Store Memory Size + + Return (MCRS) +} // End _CRS diff --git a/src/northbridge/intel/fsp_rangeley/acpi/rangeley.asl b/src/northbridge/intel/fsp_rangeley/acpi/rangeley.asl new file mode 100644 index 0000000000..78c87be931 --- /dev/null +++ b/src/northbridge/intel/fsp_rangeley/acpi/rangeley.asl @@ -0,0 +1,40 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2013 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#include "../northbridge.h" +#include "hostbridge.asl" + +/* PCI Device Resource Consumption */ +Device (PDRC) +{ + Name (_HID, EISAID("PNP0C02")) + Name (_UID, 1) + + Name (PDRS, ResourceTemplate() { + Memory32Fixed(ReadWrite, DEFAULT_ECBASE, 0x10000000) + }) + + // Current Resource Settings + Method (_CRS, 0, Serialized) + { + Return(PDRS) + } +} diff --git a/src/northbridge/intel/fsp_rangeley/chip.h b/src/northbridge/intel/fsp_rangeley/chip.h new file mode 100644 index 0000000000..5729421689 --- /dev/null +++ b/src/northbridge/intel/fsp_rangeley/chip.h @@ -0,0 +1,73 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2008 coresystems GmbH + * Copyright (C) 2015 Intel Corporation + * + * This 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. + */ + +#ifndef _FSP_RANGELEY_CHIP_H_ +#define _FSP_RANGELEY_CHIP_H_ + +#include +#include + +struct northbridge_intel_fsp_rangeley_config { + + /* Set the CPGC exp_loop_cnt field for RMT execution 2^(exp_loop_cnt -1) */ + /* Valid values: 0 - 15 */ + uint8_t MrcRmtCpgcExpLoopCntValue; + /* Set the CPGC num_bursts field for RMT execution 2^(num_bursts -1) */ + /* Valid values: 0 - 15 */ + uint8_t MrcRmtCpgcNumBursts; + /* DIMM SPD SMBus Addresses */ + uint8_t SpdBaseAddress_0_0; + uint8_t SpdBaseAddress_0_1; + uint8_t SpdBaseAddress_1_0; + uint8_t SpdBaseAddress_1_1; + + uint8_t EnableLan; + uint8_t EnableSata2; + uint8_t EnableSata3; + uint8_t EnableIQAT; + uint8_t EnableUsb20; + uint8_t PrintDebugMessages; + uint8_t Fastboot; + uint8_t EccSupport; + uint8_t SpdWriteProtect; + /* Enable = Memory Down, Disable = DIMM */ + uint8_t MemoryDown; + /* Enable the Rank Margin Tool, needs PrintDebugMessages */ + uint8_t MrcRmtSupport; + + /* PCIe port bifurcation control */ + uint8_t Bifurcation; + #define BIFURCATION_4_4_4_4 0 + #define BIFURCATION_4_4_8 1 + #define BIFURCATION_8_4_4 2 + #define BIFURCATION_8_8 3 + #define BIFURCATION_16 4 + + /* PCIe port de-emphasis control */ + uint8_t PcdPcieRootPort1DeEmphasis; + uint8_t PcdPcieRootPort2DeEmphasis; + uint8_t PcdPcieRootPort3DeEmphasis; + uint8_t PcdPcieRootPort4DeEmphasis; + #define DE_EMPHASIS_DEFAULT 0 + #define DE_EMPHASIS_MINUS_6_0_DB 1 + #define DE_EMPHASIS_MINUS_3_5_DB 2 +}; + +#endif diff --git a/src/northbridge/intel/fsp_rangeley/fsp/Kconfig b/src/northbridge/intel/fsp_rangeley/fsp/Kconfig new file mode 100644 index 0000000000..3fee76ac03 --- /dev/null +++ b/src/northbridge/intel/fsp_rangeley/fsp/Kconfig @@ -0,0 +1,49 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2014 Sage Electronic Engineering, LLC. +## +## This 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. +## + +config RANGELEY_FSP_SPECIFIC_OPTIONS + def_bool y + select PLATFORM_USES_FSP1_0 + select USE_GENERIC_FSP_CAR_INC + select FSP_USES_UPD + select ENABLE_MRC_CACHE #rangeley FSP always needs MRC data + +config FSP_FILE + string + default "../intel/fsp/rangeley/FvFsp.bin" + help + The path and filename of the Intel FSP binary for this platform. + +config FSP_LOC + hex + default 0xfff80000 + help + The location in CBFS that the FSP is located. This must match the + value that is set in the FSP binary. If the FSP needs to be moved, + rebase the FSP with Intel's BCT (tool). + + The Rangeley FSP is built with a preferred base address of 0xFFF80000 + +config DCACHE_RAM_BASE + hex + default 0xfef00000 + +config DCACHE_RAM_SIZE + hex + default 0x4000 diff --git a/src/northbridge/intel/fsp_rangeley/fsp/Makefile.inc b/src/northbridge/intel/fsp_rangeley/fsp/Makefile.inc new file mode 100644 index 0000000000..282570351b --- /dev/null +++ b/src/northbridge/intel/fsp_rangeley/fsp/Makefile.inc @@ -0,0 +1,21 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2014 Sage Electronic Engineering, LLC. +# +# This 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. +# + +ramstage-y += chipset_fsp_util.c +romstage-y += chipset_fsp_util.c diff --git a/src/northbridge/intel/fsp_rangeley/fsp/chipset_fsp_util.c b/src/northbridge/intel/fsp_rangeley/fsp/chipset_fsp_util.c new file mode 100644 index 0000000000..94767eaef4 --- /dev/null +++ b/src/northbridge/intel/fsp_rangeley/fsp/chipset_fsp_util.c @@ -0,0 +1,185 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. + * Copyright (C) 2015 Intel Corporation + * + * This 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../chip.h" + +#ifdef __PRE_RAM__ +#include +#endif + +#ifdef __PRE_RAM__ + +/* Copy the default UPD region and settings to a buffer for modification */ +static void GetUpdDefaultFromFsp + (FSP_INFO_HEADER *FspInfo, UPD_DATA_REGION *UpdData) +{ + VPD_DATA_REGION *VpdDataRgnPtr; + UPD_DATA_REGION *UpdDataRgnPtr; + VpdDataRgnPtr = (VPD_DATA_REGION *)(UINT32)(FspInfo->CfgRegionOffset + + FspInfo->ImageBase); + UpdDataRgnPtr = (UPD_DATA_REGION *)(UINT32) + (VpdDataRgnPtr->PcdUpdRegionOffset + FspInfo->ImageBase); + memcpy((void*)UpdData, (void*)UpdDataRgnPtr, sizeof(UPD_DATA_REGION)); +} + +typedef struct northbridge_intel_fsp_rangeley_config config_t; + +/** + * Update the UPD data based on values from devicetree.cb + * + * @param UpdData Pointer to the UPD Data structure + */ +static void ConfigureDefaultUpdData(UPD_DATA_REGION *UpdData) +{ + ROMSTAGE_CONST struct device *dev; + ROMSTAGE_CONST config_t *config; + printk(BIOS_DEBUG, "Configure Default UPD Data\n"); + + dev = dev_find_slot(0, SOC_DEV_FUNC); + config = dev->chip_info; + + /* Set SPD addresses */ + if(config->SpdBaseAddress_0_0) { + UpdData->PcdSpdBaseAddress_0_0 = config->SpdBaseAddress_0_0; + } + if(config->SpdBaseAddress_0_1) { + UpdData->PcdSpdBaseAddress_0_1 = config->SpdBaseAddress_0_1; + } + if(config->SpdBaseAddress_1_0) { + UpdData->PcdSpdBaseAddress_1_0 = config->SpdBaseAddress_1_0; + } + if(config->SpdBaseAddress_1_1) { + UpdData->PcdSpdBaseAddress_1_1 = config->SpdBaseAddress_1_1; + } + if(config->EccSupport) { + UpdData->PcdEccSupport = config->EccSupport; + } + if(config->PrintDebugMessages) { + UpdData->PcdPrintDebugMessages = config->PrintDebugMessages; + } + if(config->Bifurcation) { + UpdData->PcdBifurcation = config->Bifurcation; + } + if(config->MemoryDown) { + UpdData->PcdMemoryDown = config->MemoryDown; + } + + UpdData->PcdMrcInitTsegSize = CONFIG_SMM_TSEG_SIZE >> 20; + + if(config->MrcRmtCpgcExpLoopCntValue) { + UpdData->PcdMrcRmtCpgcExpLoopCntValue = + config->MrcRmtCpgcExpLoopCntValue; + } + if(config->MrcRmtCpgcNumBursts) { + UpdData->PcdMrcRmtCpgcNumBursts = config->MrcRmtCpgcNumBursts; + } +#if IS_ENABLED(CONFIG_ENABLE_FSP_FAST_BOOT) + UpdData->PcdFastboot = UPD_ENABLE; +#endif + /* + * Loop through all the SOC devices in the devicetree + * enabling and disabling them as requested. + */ + for (; dev; dev = dev->sibling) { + + if (dev->path.type != DEVICE_PATH_PCI) + continue; + + switch (dev->path.pci.devfn) { + case GBE1_DEV_FUNC: + case GBE2_DEV_FUNC: + case GBE3_DEV_FUNC: + case GBE4_DEV_FUNC: + UpdData->PcdEnableLan |= dev->enabled; + printk(BIOS_DEBUG, "PcdEnableLan %d\n", + UpdData->PcdEnableLan); + break; + case SATA2_DEV_FUNC: + UpdData->PcdEnableSata2 = dev->enabled; + printk(BIOS_DEBUG, "PcdEnableSata2 %d\n", + UpdData->PcdEnableSata2); + break; + case SATA3_DEV_FUNC: + UpdData->PcdEnableSata3 = dev->enabled; + printk(BIOS_DEBUG, "PcdEnableSata3 %d\n", + UpdData->PcdEnableSata3); + break; + case IQAT_DEV_FUNC: + UpdData->PcdEnableIQAT |= dev->enabled; + printk(BIOS_DEBUG, "PcdEnableIQAT %d\n", + UpdData->PcdEnableIQAT); + break; + case USB2_DEV_FUNC: + UpdData->PcdEnableUsb20 = dev->enabled; + printk(BIOS_DEBUG, "PcdEnableUsb20 %d\n", + UpdData->PcdEnableUsb20); + break; + } + } + + /* Set PCIe de-emphasis */ + UPD_DEFAULT_CHECK(PcdPcieRootPort1DeEmphasis); + UPD_DEFAULT_CHECK(PcdPcieRootPort2DeEmphasis); + UPD_DEFAULT_CHECK(PcdPcieRootPort3DeEmphasis); + UPD_DEFAULT_CHECK(PcdPcieRootPort4DeEmphasis); +} + +/* Set up the Rangeley specific structures for the call into the FSP */ +void chipset_fsp_early_init(FSP_INIT_PARAMS *pFspInitParams, + FSP_INFO_HEADER *fsp_ptr) +{ + FSP_INIT_RT_BUFFER *pFspRtBuffer = pFspInitParams->RtBufferPtr; + + /* Initialize the UPD Data */ + GetUpdDefaultFromFsp (fsp_ptr, pFspRtBuffer->Common.UpdDataRgnPtr); + ConfigureDefaultUpdData(pFspRtBuffer->Common.UpdDataRgnPtr); + pFspInitParams->NvsBufferPtr = NULL; + pFspRtBuffer->Common.BootMode = BOOT_WITH_FULL_CONFIGURATION; + + /* Find the fastboot cache that was saved in the ROM */ + pFspInitParams->NvsBufferPtr = find_and_set_fastboot_cache(); + + return; +} + +/* The FSP returns here after the fsp_early_init call */ +void ChipsetFspReturnPoint(EFI_STATUS Status, + VOID *HobListPtr) +{ + *(void **)CBMEM_FSP_HOB_PTR=HobListPtr; + + if (Status == 0xFFFFFFFF) { + soft_reset(); + } + romstage_main_continue(Status, HobListPtr); +} + +#endif /* __PRE_RAM__ */ diff --git a/src/northbridge/intel/fsp_rangeley/fsp/chipset_fsp_util.h b/src/northbridge/intel/fsp_rangeley/fsp/chipset_fsp_util.h new file mode 100644 index 0000000000..3c4b97eccc --- /dev/null +++ b/src/northbridge/intel/fsp_rangeley/fsp/chipset_fsp_util.h @@ -0,0 +1,52 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#ifndef CHIPSET_FSP_UTIL_H +#define CHIPSET_FSP_UTIL_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#define FSP_RESERVE_MEMORY_SIZE 0x200000 + +#define FSP_INFO_HEADER_GUID \ + { \ + 0x912740BE, 0x2284, 0x4734, {0xB9, 0x71, 0x84, 0xB0, 0x27, 0x35, 0x3F, 0x0C} \ + } + +#define FSP_NON_VOLATILE_STORAGE_HOB_GUID \ + { \ + 0x721acf02, 0x4d77, 0x4c2a, { 0xb3, 0xdc, 0x27, 0xb, 0x7b, 0xa9, 0xe4, 0xb0} \ + } + +/* + *The FSP Image ID is different for each platform's FSP and + * can be used to verify that the right FSP binary is loaded. + * For the Rangeley FSP, the Image Id is "AVN-FSP0". + */ +#define FSP_IMAGE_ID_DWORD0 0x2d4e5641 /* 'AVN-' */ +#define FSP_IMAGE_ID_DWORD1 0x30505346 /* 'FSP0' */ + +#endif /* CHIPSET_FSP_UTIL_H */ diff --git a/src/northbridge/intel/fsp_rangeley/northbridge.c b/src/northbridge/intel/fsp_rangeley/northbridge.c new file mode 100644 index 0000000000..cd0c8a3965 --- /dev/null +++ b/src/northbridge/intel/fsp_rangeley/northbridge.c @@ -0,0 +1,276 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. + * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "chip.h" +#include "northbridge.h" +#include +#include + +static int bridge_revision_id = -1; + +int bridge_silicon_revision(void) +{ + if (bridge_revision_id < 0) { + uint8_t stepping = cpuid_eax(1) & 0xf; + uint8_t bridge_id = pci_read_config16( + dev_find_slot(0, PCI_DEVFN(0, 0)), + PCI_DEVICE_ID) & 0xf0; + bridge_revision_id = bridge_id | stepping; + } + return bridge_revision_id; +} + +/* Reserve everything between A segment and 1MB: + * + * 0xa0000 - 0xbffff: legacy VGA + * 0xc0000 - 0xcffff: VGA OPROM (needed by kernel) + * 0xe0000 - 0xfffff: SeaBIOS, if used, otherwise DMI + */ +static const int legacy_hole_base_k = 0xa0000 / 1024; +static const int legacy_hole_size_k = 384; + +static int get_pcie_bar(u32 *base, u32 *len) +{ + device_t dev; + u32 pciexbar_reg; + + *base = 0; + *len = 0; + + dev = dev_find_slot(0, PCI_DEVFN(0, 0)); + if (!dev) + return 0; + + pciexbar_reg = sideband_read(B_UNIT, BECREG); + + if (!(pciexbar_reg & (1 << 0))) + return 0; + + *base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) | + (1 << 28)); + *len = 256 * 1024 * 1024; /* 256MB ECAM range */ + return 1; + +} + +static int add_fixed_resources(struct device *dev, int index) +{ + struct resource *resource; + u32 pcie_config_base, pcie_config_size; + + + if (get_pcie_bar(&pcie_config_base, &pcie_config_size)) { + printk(BIOS_DEBUG, "Adding PCIe config bar base=0x%08x " + "size=0x%x\n", pcie_config_base, pcie_config_size); + resource = new_resource(dev, index++); + resource->base = (resource_t) pcie_config_base; + resource->size = (resource_t) pcie_config_size; + resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE | + IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED; + } + + resource = new_resource(dev, index++); /* Local APIC */ + resource->base = LAPIC_DEFAULT_BASE; + resource->size = 0x00001000; + resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE | + IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED; + + mmio_resource(dev, index++, legacy_hole_base_k, legacy_hole_size_k); + + return index; +} + +static void mc_add_dram_resources(device_t dev) +{ + u32 tomlow, bmbound, bsmmrrl, bsmmrrh; + u64 bmbound_hi; + int index = 0; + + /* + * These are the host memory ranges : + * - 0 -> SMM (SMMRRL) : cacheable + * - SMM -> LOW TOM (BMBOUND) : cacheable WP + * - 4GB -> HIGH TOM (BMBOUND_HI): cacheable + * + */ + + tomlow = bmbound = sideband_read(B_UNIT, BMBOUND); + printk(BIOS_SPEW, "Top of Low Used DRAM (BMBOUND): 0x%08x\n", bmbound); + + bmbound_hi = (u64)(sideband_read(B_UNIT, BMBOUND_HI)) << 4; + printk(BIOS_SPEW, "Top of Upper Used DRAM (BMBOUND_HI): 0x%llx\n", bmbound_hi); + + bsmmrrl = sideband_read(B_UNIT, BSMMRRL) << 20; + bsmmrrh = ((sideband_read(B_UNIT, BSMMRRH) + 1) << 20) - 1; + if (bsmmrrl) { + tomlow = bsmmrrl; + printk(BIOS_DEBUG, "SMM memory location: 0x%x SMM memory size: 0x%x\n", bsmmrrl, (bsmmrrh - bsmmrrl + 1)); + printk(BIOS_DEBUG, "Subtracting %dM for SMM\n", (bmbound - bsmmrrl) >> 20); + } + tomlow -= FSP_RESERVE_MEMORY_SIZE; + printk(BIOS_SPEW, "Available memory below 4GB: 0x%08x (%dM)\n", tomlow, tomlow >> 20); + + /* Report the memory regions. */ + ram_resource(dev, index++, 0, legacy_hole_base_k); + ram_resource(dev, index++, legacy_hole_base_k + legacy_hole_size_k, + ((tomlow >> 10) - (legacy_hole_base_k + legacy_hole_size_k))); + + mmio_resource(dev, index++, tomlow >> 10, (bmbound - bsmmrrl) >> 10); + + if (bmbound_hi > 0x100000000) { + ram_resource(dev, index++, 0x100000000 >> 10, (bmbound_hi - 0x100000000) >> 10 ); + printk(BIOS_INFO, "Available memory above 4GB: %lluM\n", (bmbound_hi - 0x100000000) >> 20); + } + + index = add_fixed_resources(dev, index); +} + +static void mc_read_resources(device_t dev) +{ + /* Call the normal read_resources */ + pci_dev_read_resources(dev); + + /* Calculate and add DRAM resources. */ + mc_add_dram_resources(dev); +} + +static void pci_domain_set_resources(device_t dev) +{ + /* + * Assign memory resources for PCI devices + */ + mc_add_dram_resources(dev); + + assign_resources(dev->link_list); +} + +static void mc_set_resources(device_t dev) +{ + /* Call the normal set_resources */ + pci_dev_set_resources(dev); +} + +static void intel_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)); + } +} + +static void northbridge_init(struct device *dev) +{ +} + +static void northbridge_enable(device_t dev) +{ +} + +static struct pci_operations intel_pci_ops = { + .set_subsystem = intel_set_subsystem, +}; + +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 mc_ops = { + .read_resources = mc_read_resources, + .set_resources = mc_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = northbridge_init, + .acpi_fill_ssdt_generator = northbridge_acpi_fill_ssdt_generator, + .enable = northbridge_enable, + .scan_bus = 0, + .ops_pci = &intel_pci_ops, +}; + +/* + * The following entries are taken from Intel document number 510524, rev 1.6: + * Rangeley SoC External Design Specification (EDS) + * Section 10.3 PCI Configuration Space + * Table 10-6. PCI Devices and Functions + * + * These are the Device ID values for the item at bus 0, device 0, function 0. + */ +static const unsigned short pci_device_ids[] = { + 0x1f00, 0x1f01, 0x1f02, 0x1f03, + 0x1f04, 0x1f05, 0x1f06, 0x1f07, + 0x1f08, 0x1f09, 0x1f0a, 0x1f0b, + 0x1f0c, 0x1f0d, 0x1f0e, 0x1f0f, + 0, /* -- END OF LIST -- */ +}; + +static const struct pci_driver mc_driver __pci_driver = { + .ops = &mc_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; + +static void cpu_bus_init(device_t dev) +{ + initialize_cpus(dev->link_list); +} + +static struct device_operations cpu_bus_ops = { + .read_resources = DEVICE_NOOP, + .set_resources = DEVICE_NOOP, + .enable_resources = DEVICE_NOOP, + .init = cpu_bus_init, + .scan_bus = 0, +}; + +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; + } +} + +struct chip_operations northbridge_intel_fsp_rangeley_ops = { + CHIP_NAME("Intel Rangeley Northbridge") + .enable_dev = enable_dev, +}; diff --git a/src/northbridge/intel/fsp_rangeley/northbridge.h b/src/northbridge/intel/fsp_rangeley/northbridge.h new file mode 100644 index 0000000000..dc4676bfd9 --- /dev/null +++ b/src/northbridge/intel/fsp_rangeley/northbridge.h @@ -0,0 +1,85 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2008 coresystems GmbH + * Copyright (C) 2011 Google Inc. + * Copyright (C) 2013 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#ifndef __NORTHBRIDGE_INTEL_RANGELEY_NORTHBRIDGE_H__ +#define __NORTHBRIDGE_INTEL_RANGELEY_NORTHBRIDGE_H__ + +#define DEFAULT_ECBASE CONFIG_MMCONF_BASE_ADDRESS + +/* Everything below this line is ignored in the DSDT */ +#ifndef __ACPI__ + +#include +#include + +/* Device 0:0.0 PCI configuration space (Host Bridge) */ + +/* SideBand B-UNIT */ +#define B_UNIT 3 + #define BNOCACHE 0x23 + #define BNOCACHECTL 0x24 + #define BMBOUND 0x25 + #define BMBOUND_HI 0x26 + #define BECREG 0x27 + #define BMISC 0x28 + #define BSMMRRL 0x2E + #define BSMMRRH 0x2F + #define BIMR0L 0x80 + #define BIMR0H 0x81 + #define BIMR0RAC 0x82 + #define BIMR0WAC 0x83 + +/* SideBand C-UNIT */ +#define C_UNIT 8 + +/* SideBand D-UNIT */ +#define D_UNIT 1 + +/* SideBand P-UNIT */ +#define P_UNIT 4 + +#ifndef __ASSEMBLER__ +static inline void barrier(void) { asm("" ::: "memory"); } + +#define PCI_DEVICE_ID_RG_MIN 0x1F00 +#define PCI_DEVICE_ID_RG_MAX 0x1F0F +#define SKPAD 0xFC + +int bridge_silicon_revision(void); +void rangeley_late_initialization(void); +u32 sideband_read(int port, int reg); +void sideband_write(int port, int reg, long data); + +/* debugging functions */ +void print_pci_devices(void); +void dump_pci_device(unsigned dev); +void dump_pci_devices(void); +void dump_spd_registers(void); +void dump_mem(unsigned start, unsigned end); +void report_platform_info(void); + +#if ENV_RAMSTAGE +void northbridge_acpi_fill_ssdt_generator(device_t device); +#endif + +#endif /* #ifndef __ASSEMBLER__ */ +#endif /* #ifndef __ACPI__ */ +#endif /* #ifndef __NORTHBRIDGE_INTEL_RANGELEY_NORTHBRIDGE_H__ */ diff --git a/src/northbridge/intel/fsp_rangeley/port_access.c b/src/northbridge/intel/fsp_rangeley/port_access.c new file mode 100644 index 0000000000..41c137bf83 --- /dev/null +++ b/src/northbridge/intel/fsp_rangeley/port_access.c @@ -0,0 +1,72 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2009-2010 iWave Systems + * Copyright (C) 2013 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#ifndef __PRE_RAM__ +#define __PRE_RAM__ // Use simple device model for this file even in ramstage +#endif + +#include +#include +#include +#include +#include +#include "northbridge.h" + +/* + * Restricted Access Regions: + * + * MCR - Message Control Register + * 31 24 16 8 4 0 + * ---------------------------------------------------------------------------- + * | | | Target | Write | | + * | Opcode | Port | register | byte | Reserved | + * | | | Address | Enables | | + * ---------------------------------------------------------------------------- + * + * MDR - Message Data Register + * 31 0 + * ---------------------------------------------------------------------------- + * | | + * | Data | + * | | + * ---------------------------------------------------------------------------- + */ + +#define MSG_OPCODE_READ 0x10 << 24 +#define MSG_OPCODE_WRITE 0x11 << 24 + +#define MCR 0xD0 +#define MDR 0xD4 +#define MCRE 0xD8 + +u32 sideband_read(int port, int reg) +{ + pci_write_config32(PCI_DEV(0, 0, 0), MCR, + (MSG_OPCODE_READ | (port << 16) | (reg << 8))); + return pci_read_config32(PCI_DEV(0, 0, 0), MDR); +} + +void sideband_write(int port, int reg, long data) +{ + pci_write_config32(PCI_DEV(0, 0, 0), MDR, data); + pci_write_config32(PCI_DEV(0, 0, 0), MCR, + (MSG_OPCODE_WRITE | (port << 16) | (reg << 8) | (0xF << 4))); + pci_read_config32(PCI_DEV(0, 0, 0), MDR); +} diff --git a/src/northbridge/intel/fsp_rangeley/raminit.c b/src/northbridge/intel/fsp_rangeley/raminit.c new file mode 100644 index 0000000000..181beb299f --- /dev/null +++ b/src/northbridge/intel/fsp_rangeley/raminit.c @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Google Inc. + * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#include +#include +#include +#include +#include +#include "northbridge.h" +#include + +static uintptr_t smm_region_start(void) +{ + /* + * Calculate the top of usable (low) DRAM. + * The FSP's reserved memory sits just below the SMM region, + * allowing calculation of the top of usable memory. + */ + uintptr_t tom = sideband_read(B_UNIT, BMBOUND); + uintptr_t bsmmrrl = sideband_read(B_UNIT, BSMMRRL) << 20; + if (bsmmrrl) { + tom = bsmmrrl; + } + + return tom; +} + +void *cbmem_top(void) +{ + return (void *) (smm_region_start() - FSP_RESERVE_MEMORY_SIZE); +} diff --git a/src/northbridge/intel/fsp_rangeley/udelay.c b/src/northbridge/intel/fsp_rangeley/udelay.c new file mode 100644 index 0000000000..2256208d06 --- /dev/null +++ b/src/northbridge/intel/fsp_rangeley/udelay.c @@ -0,0 +1,68 @@ +/* + * This file is part of the coreboot project. + * + * 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. + */ + +#include +#include +#include +#include + +/** + * Intel Rangeley CPUs always run the TSC at BCLK=100MHz + */ + +/* Simple 32- to 64-bit multiplication. Uses 16-bit words to avoid overflow. + * This code is used to prevent use of libgcc's umoddi3. + */ +static inline void multiply_to_tsc(tsc_t *const tsc, const u32 a, const u32 b) +{ + tsc->lo = (a & 0xffff) * (b & 0xffff); + tsc->hi = ((tsc->lo >> 16) + + ((a & 0xffff) * (b >> 16)) + + ((b & 0xffff) * (a >> 16))); + tsc->lo = ((tsc->hi & 0xffff) << 16) | (tsc->lo & 0xffff); + tsc->hi = ((a >> 16) * (b >> 16)) + (tsc->hi >> 16); +} + +void udelay(u32 us) +{ + u32 dword; + tsc_t tsc, tsc1, tscd; + msr_t msr; + u32 fsb = 100, divisor; + u32 d; /* ticks per us */ + + msr = rdmsr(0xce); + divisor = (msr.lo >> 8) & 0xff; + + d = fsb * divisor; + multiply_to_tsc(&tscd, us, d); + + tsc1 = rdtsc(); + dword = tsc1.lo + tscd.lo; + if ((dword < tsc1.lo) || (dword < tscd.lo)) { + tsc1.hi++; + } + tsc1.lo = dword; + tsc1.hi += tscd.hi; + + do { + tsc = rdtsc(); + } while ((tsc.hi < tsc1.hi) + || ((tsc.hi == tsc1.hi) && (tsc.lo <= tsc1.lo))); +} diff --git a/src/southbridge/intel/fsp_rangeley/Kconfig b/src/southbridge/intel/fsp_rangeley/Kconfig new file mode 100644 index 0000000000..2c8ceacd9a --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/Kconfig @@ -0,0 +1,63 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2011 Google Inc. +## Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. +## +## This 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. +## + +config SOUTHBRIDGE_INTEL_FSP_RANGELEY + bool + +if SOUTHBRIDGE_INTEL_FSP_RANGELEY + +config SOUTH_BRIDGE_OPTIONS # dummy + def_bool y + select IOAPIC + select HAVE_HARD_RESET + select HAVE_USBDEBUG + select USE_WATCHDOG_ON_BOOT + select PCIEXP_ASPM + select PCIEXP_COMMON_CLOCK + select SPI_FLASH + select HAVE_INTEL_FIRMWARE + +config EHCI_BAR + hex + default 0xfef00000 + +config EHCI_DEBUG_OFFSET + hex + default 0xa0 + +config SERIRQ_CONTINUOUS_MODE + bool + default n + help + If you set this option to y, the serial IRQ machine will be + operated in continuous mode. + +config HPET_MIN_TICKS + hex + default 0x80 + +config IFD_BIN_PATH + string + depends on HAVE_IFD_BIN + default "../intel/mainboard/intel/rangeley" + help + The path and filename to the descriptor.bin file. + +endif diff --git a/src/southbridge/intel/fsp_rangeley/Makefile.inc b/src/southbridge/intel/fsp_rangeley/Makefile.inc new file mode 100644 index 0000000000..2a66b90ec8 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/Makefile.inc @@ -0,0 +1,38 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2010 Google Inc. +## Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. +## +## This 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. +## + +ifeq ($(CONFIG_SOUTHBRIDGE_INTEL_FSP_RANGELEY),y) + +ramstage-y += soc.c +ramstage-y += lpc.c +ramstage-y += sata.c +ramstage-y += reset.c +ramstage-y += watchdog.c +ramstage-y += spi.c +ramstage-y += smbus.c +ramstage-y += acpi.c + +romstage-y += early_usb.c early_smbus.c gpio.c reset.c early_spi.c early_init.c +romstage-y += romstage.c + +romstage-$(CONFIG_USBDEBUG) += usb_debug.c +ramstage-$(CONFIG_USBDEBUG) += usb_debug.c + +endif diff --git a/src/southbridge/intel/fsp_rangeley/acpi.c b/src/southbridge/intel/fsp_rangeley/acpi.c new file mode 100644 index 0000000000..18e5a8a3b9 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/acpi.c @@ -0,0 +1,201 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#include +#include +#include +#include +#include +#include + +#if IS_ENABLED(CONFIG_HAVE_SMI_HANDLER) +#include +#endif + +/** + * Fill in the FADT with generic values that can be overridden later. + */ + +typedef struct southbridge_intel_fsp_rangeley_config config_t; + +void acpi_fill_in_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) +{ + acpi_header_t *header = &(fadt->header); + struct device *lpcdev = dev_find_slot(SOC_LPC_DEVFN); + u16 pmbase = pci_read_config16(lpcdev, ABASE) & 0xfff0; + config_t *config = lpcdev->chip_info; + + memset((void *) fadt, 0, sizeof(acpi_fadt_t)); + + /* + * Reference section 5.2.9 Fixed ACPI Description Table (FADT) + * in the ACPI 3.0b specification. + */ + + /* FADT Header Structure */ + memcpy(header->signature, "FACP", 4); + header->length = sizeof(acpi_fadt_t); + header->revision = ACPI_FADT_REV_ACPI_3_0; + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); + memcpy(header->asl_compiler_id, ASLC, 4); + header->asl_compiler_revision = 1; + + /* ACPI Pointers */ + fadt->firmware_ctrl = (unsigned long) facs; + fadt->dsdt = (unsigned long) dsdt; + + fadt->model = 0; /* reserved, should be 0 ACPI 3.0 */ + fadt->preferred_pm_profile = config->fadt_pm_profile; /* unknown is default */ + + /* System Management */ + fadt->sci_int = 0x09; + fadt->smi_cmd = 0x00; /* disable SMM */ + fadt->acpi_enable = 0x00; /* unused if SMI_CMD = 0 */ + fadt->acpi_disable = 0x00; /* unused if SMI_CMD = 0 */ + + /* Enable ACPI */ + outl(inl(pmbase + PM1_CNT) | SCI_EN, pmbase + PM1_CNT); + + /* Power Control */ + fadt->s4bios_req = 0x00; + fadt->pstate_cnt = 0x00; + + /* Control Registers - Base Address */ + fadt->pm1a_evt_blk = pmbase + PM1_STS; + fadt->pm1b_evt_blk = 0x00; /* Not Used */ + fadt->pm1a_cnt_blk = pmbase + PM1_CNT; + fadt->pm1b_cnt_blk = 0x00; /* Not Used */ + fadt->pm2_cnt_blk = pmbase + PM2A_CNT_BLK; + fadt->pm_tmr_blk = pmbase + PM1_TMR; + fadt->gpe0_blk = pmbase + GPE0_STS; + fadt->gpe1_blk = 0x00; /* Not Used */ + + /* Control Registers - Length */ + fadt->pm1_evt_len = 4; /* 32 bits */ + fadt->pm1_cnt_len = 2; /* 32 bit register, 16 bits used */ + fadt->pm2_cnt_len = 1; /* 8 bits */ + fadt->pm_tmr_len = 4; /* 32 bits */ + fadt->gpe0_blk_len = 8; /* 64 bits */ + fadt->gpe1_blk_len = 0; + fadt->gpe1_base = 0; + fadt->cst_cnt = 0; + fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED; + fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED; + fadt->flush_size = 0; /* set to 0 if WBINVD is 1 in flags */ + fadt->flush_stride = 0; /* set to 0 if WBINVD is 1 in flags */ + fadt->duty_offset = 1; + fadt->duty_width = 0; + + /* RTC Registers */ + fadt->day_alrm = 0x0D; + fadt->mon_alrm = 0x00; + fadt->century = 0x00; + fadt->iapc_boot_arch = config->fadt_boot_arch; /* legacy free default */ + + fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED | + ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON | + ACPI_FADT_RESET_REGISTER | ACPI_FADT_SLEEP_TYPE | + ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK; + + /* Reset Register */ + fadt->reset_reg.space_id = ACPI_ADDRESS_SPACE_IO; + fadt->reset_reg.bit_width = 8; + fadt->reset_reg.bit_offset = 0; + fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS; + fadt->reset_reg.addrl = 0xCF9; + fadt->reset_reg.addrh = 0x00; + fadt->reset_value = 6; + + /* Reserved Bits */ + fadt->res3 = 0x00; /* reserved, MUST be 0 ACPI 3.0 */ + fadt->res4 = 0x00; /* reserved, MUST be 0 ACPI 3.0 */ + fadt->res5 = 0x00; /* reserved, MUST be 0 ACPI 3.0 */ + + /* Extended ACPI Pointers */ + fadt->x_firmware_ctl_l = (unsigned long)facs; + fadt->x_firmware_ctl_h = 0x00; + fadt->x_dsdt_l = (unsigned long)dsdt; + fadt->x_dsdt_h = 0x00; + + /* PM1 Status & PM1 Enable */ + fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO; + fadt->x_pm1a_evt_blk.bit_width = 32; + fadt->x_pm1a_evt_blk.bit_offset = 0; + fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS; + fadt->x_pm1a_evt_blk.addrl = fadt->pm1a_evt_blk; + fadt->x_pm1a_evt_blk.addrh = 0x00; + + fadt->x_pm1b_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO; + fadt->x_pm1b_evt_blk.bit_width = 0; + fadt->x_pm1b_evt_blk.bit_offset = 0; + fadt->x_pm1b_evt_blk.access_size = 0; + fadt->x_pm1b_evt_blk.addrl = fadt->pm1b_evt_blk; + fadt->x_pm1b_evt_blk.addrh = 0x00; + + /* PM1 Control Registers */ + fadt->x_pm1a_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO; + fadt->x_pm1a_cnt_blk.bit_width = 16; + fadt->x_pm1a_cnt_blk.bit_offset = 0; + fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS; + fadt->x_pm1a_cnt_blk.addrl = fadt->pm1a_cnt_blk; + fadt->x_pm1a_cnt_blk.addrh = 0x00; + + fadt->x_pm1b_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO; + fadt->x_pm1b_cnt_blk.bit_width = 0; + fadt->x_pm1b_cnt_blk.bit_offset = 0; + fadt->x_pm1b_cnt_blk.access_size = 0; + fadt->x_pm1b_cnt_blk.addrl = fadt->pm1b_cnt_blk; + fadt->x_pm1b_cnt_blk.addrh = 0x00; + + /* PM2 Control Registers */ + fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO; + fadt->x_pm2_cnt_blk.bit_width = 8; + fadt->x_pm2_cnt_blk.bit_offset = 0; + fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS; + fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk; + fadt->x_pm2_cnt_blk.addrh = 0x00; + + /* PM1 Timer Register */ + fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO; + fadt->x_pm_tmr_blk.bit_width = 32; + fadt->x_pm_tmr_blk.bit_offset = 0; + fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS; + fadt->x_pm_tmr_blk.addrl = fadt->pm_tmr_blk; + fadt->x_pm_tmr_blk.addrh = 0x00; + + /* General-Purpose Event Registers */ + fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO; + fadt->x_gpe0_blk.bit_width = 64; /* EventStatus + EventEnable */ + fadt->x_gpe0_blk.bit_offset = 0; + fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS; + fadt->x_gpe0_blk.addrl = fadt->gpe0_blk; + fadt->x_gpe0_blk.addrh = 0x00; + + fadt->x_gpe1_blk.space_id = ACPI_ADDRESS_SPACE_IO; + fadt->x_gpe1_blk.bit_width = 0; + fadt->x_gpe1_blk.bit_offset = 0; + fadt->x_gpe1_blk.access_size = 0; + fadt->x_gpe1_blk.addrl = fadt->gpe1_blk; + fadt->x_gpe1_blk.addrh = 0x00; + + header->checksum = + acpi_checksum((void *) fadt, sizeof(acpi_fadt_t)); +} diff --git a/src/southbridge/intel/fsp_rangeley/acpi/globalnvs.asl b/src/southbridge/intel/fsp_rangeley/acpi/globalnvs.asl new file mode 100644 index 0000000000..1cb12cfae1 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/acpi/globalnvs.asl @@ -0,0 +1,185 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 The Chromium OS Authors + * + * This 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. + */ + +/* Global Variables */ + +Name(\PICM, 0) // IOAPIC/8259 +Name(\DSEN, 1) // Display Output Switching Enable + +/* Global ACPI memory region. This region is used for passing information + * between coreboot (aka "the system bios"), ACPI, and the SMI handler. + * Since we don't know where this will end up in memory at ACPI compile time, + * we have to fix it up in coreboot's ACPI creation phase. + */ + + +External(NVSA) +OperationRegion (GNVS, SystemMemory, NVSA, 0xf00) +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) + /* Processor Identification */ + Offset (0x28), + APIC, 8, // 0x28 - APIC Enabled by coreboot + MPEN, 8, // 0x29 - Multi Processor Enable + PCP0, 8, // 0x2a - PDC CPU/CORE 0 + PCP1, 8, // 0x2b - PDC CPU/CORE 1 + PPCM, 8, // 0x2c - Max. PPC state + PCNT, 8, // 0x2d - Processor count + /* Super I/O & CMOS config */ + Offset (0x32), + NATP, 8, // 0x32 - + S5U0, 8, // 0x33 - Enable USB0 in S5 + S5U1, 8, // 0x34 - Enable USB1 in S5 + S3U0, 8, // 0x35 - Enable USB0 in S3 + S3U1, 8, // 0x36 - Enable USB1 in S3 + S33G, 8, // 0x37 - Enable 3G in S3 + CMEM, 32, // 0x38 - CBMEM TOC + /* Integrated Graphics Device */ + Offset (0x3c), + IGDS, 8, // 0x3c - IGD state (primary = 1) + TLST, 8, // 0x3d - Display Toggle List pointer + CADL, 8, // 0x3e - Currently Attached Devices List + PADL, 8, // 0x3f - Previously Attached Devices List + CSTE, 16, // 0x40 - Current display state + NSTE, 16, // 0x42 - Next display state + SSTE, 16, // 0x44 - Set display state + Offset (0x46), + NDID, 8, // 0x46 - Number of Device IDs + DID1, 32, // 0x47 - Device ID 1 + DID2, 32, // 0x4b - Device ID 2 + DID3, 32, // 0x4f - Device ID 3 + DID4, 32, // 0x53 - Device ID 4 + DID5, 32, // 0x57 - Device ID 5 + /* Backlight Control */ + Offset (0x64), + BLCS, 8, // 0x64 - Backlight control possible? + BRTL, 8, // 0x65 - Brightness Level + ODDS, 8, // 0x66 + /* Ambient Light Sensors */ + Offset (0x6e), + ALSE, 8, // 0x6e - ALS enable + ALAF, 8, // 0x6f - Ambient light adjustment factor + LLOW, 8, // 0x70 - LUX Low + LHIH, 8, // 0x71 - LUX High + /* EMA */ + Offset (0x78), + EMAE, 8, // 0x78 - EMA enable + EMAP, 16, // 0x79 - EMA pointer + EMAL, 16, // 0x7b - EMA length + /* MEF */ + Offset (0x82), + MEFE, 8, // 0x82 - MEF enable + /* TPM support */ + Offset (0x8c), + TPMP, 8, // 0x8c - TPM + TPME, 8, // 0x8d - TPM enable + /* SATA */ + Offset (0x96), + GTF0, 56, // 0x96 - GTF task file buffer for port 0 + GTF1, 56, // 0x9d - GTF task file buffer for port 1 + GTF2, 56, // 0xa4 - GTF task file buffer for port 2 + IDEM, 8, // 0xab - IDE mode (compatible / enhanced) + IDET, 8, // 0xac - IDE + /* IGD OpRegion */ + Offset (0xb4), + ASLB, 32, // 0xb4 - IGD OpRegion Base Address + IBTT, 8, // 0xb8 - IGD boot panel device + IPAT, 8, // 0xb9 - IGD panel type cmos option + ITVF, 8, // 0xba - IGD TV format cmos option + ITVM, 8, // 0xbb - IGD TV minor format option + IPSC, 8, // 0xbc - IGD panel scaling + IBLC, 8, // 0xbd - IGD BLC config + IBIA, 8, // 0xbe - IGD BIA config + ISSC, 8, // 0xbf - IGD SSC config + I409, 8, // 0xc0 - IGD 0409 modified settings + I509, 8, // 0xc1 - IGD 0509 modified settings + I609, 8, // 0xc2 - IGD 0609 modified settings + I709, 8, // 0xc3 - IGD 0709 modified settings + IDMM, 8, // 0xc4 - IGD Power conservation feature + IDMS, 8, // 0xc5 - IGD DVMT memory size + IF1E, 8, // 0xc6 - IGD function 1 enable + HVCO, 8, // 0xc7 - IGD HPLL VCO + NXD1, 32, // 0xc8 - IGD _DGS next DID1 + NXD2, 32, // 0xcc - IGD _DGS next DID2 + NXD3, 32, // 0xd0 - IGD _DGS next DID3 + NXD4, 32, // 0xd4 - IGD _DGS next DID4 + NXD5, 32, // 0xd8 - IGD _DGS next DID5 + NXD6, 32, // 0xdc - IGD _DGS next DID6 + NXD7, 32, // 0xe0 - IGD _DGS next DID7 + NXD8, 32, // 0xe4 - IGD _DGS next DID8 + + ISCI, 8, // 0xe8 - IGD SMI/SCI mode (0: SCI) + PAVP, 8, // 0xe9 - IGD PAVP data + Offset (0xeb), + OSCC, 8, // 0xeb - PCIe OSC control + NPCE, 8, // 0xec - native pcie support + PLFL, 8, // 0xed - platform flavor + BREV, 8, // 0xee - board revision + DPBM, 8, // 0xef - digital port b mode + DPCM, 8, // 0xf0 - digital port c mode + DPDM, 8, // 0xf1 - digital port d mode + ALFP, 8, // 0xf2 - active lfp + IMON, 8, // 0xf3 - current graphics turbo imon value + MMIO, 8, // 0xf4 - 64bit mmio support +} + +/* 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/southbridge/intel/fsp_rangeley/acpi/irq_helper.h b/src/southbridge/intel/fsp_rangeley/acpi/irq_helper.h new file mode 100644 index 0000000000..bf1f6c0bf2 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/acpi/irq_helper.h @@ -0,0 +1,61 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * Copyright (C) 2014 Sage Electronics Engineering, LLC. + * + * This 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. + */ + +/* + * This file intentionally gets included multiple times, to set pic and apic + * modes, so should not have guard statements added. + */ + +/* + * This file will use irqroute.asl and mainboard/irqroute.h + * to generate the ACPI IRQ routing for the mainboard being compiled. + * This method uses #defines in irqroute.h along with the macros contained + * in this file to generate an IRQ routing for each PCI device in the system. + */ +#undef PCI_DEV_PIRQ_ROUTES +#undef ACPI_DEV_IRQ +#undef PCI_DEV_PIRQ_ROUTE +#undef PIRQ_PIC_ROUTES +#undef PIRQ_PIC +#undef IRQROUTE_H + +#if defined(PIC_MODE) + +#define ACPI_DEV_IRQ(dev_, pin_, pin_name_) \ + Package() { ## dev_ ## ffff, pin_, \_SB.PCI0.LPCB.LNK ## pin_name_, 0 } + +#else /* defined(PIC_MODE) */ + +#define ACPI_DEV_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_IRQ(dev_, 0, a_), \ + ACPI_DEV_IRQ(dev_, 1, b_), \ + ACPI_DEV_IRQ(dev_, 2, c_), \ + ACPI_DEV_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/southbridge/intel/fsp_rangeley/acpi/irqlinks.asl b/src/southbridge/intel/fsp_rangeley/acpi/irqlinks.asl new file mode 100644 index 0000000000..acc03f0ceb --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/acpi/irqlinks.asl @@ -0,0 +1,491 @@ +/* + * 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. + */ + +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/southbridge/intel/fsp_rangeley/acpi/irqroute.asl b/src/southbridge/intel/fsp_rangeley/acpi/irqroute.asl new file mode 100644 index 0000000000..75eb76c423 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/acpi/irqroute.asl @@ -0,0 +1,43 @@ +/* + * 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. + */ + +// PCI Interrupt Routing +Method(_PRT) +{ + /* + * PICM comes from _PIC, which returns the following: + * 0 – PIC mode + * 1 – APIC mode + * 2 – SAPIC mode + */ + If (PICM) { + Return (Package() { + #undef PIC_MODE + #include "irq_helper.h" + PCI_DEV_PIRQ_ROUTES + }) + } Else { + Return (Package() { + #define PIC_MODE + #include "irq_helper.h" + PCI_DEV_PIRQ_ROUTES + }) + } +} diff --git a/src/southbridge/intel/fsp_rangeley/acpi/lpc.asl b/src/southbridge/intel/fsp_rangeley/acpi/lpc.asl new file mode 100644 index 0000000000..fce5449744 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/acpi/lpc.asl @@ -0,0 +1,230 @@ +/* + * 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. + */ + +// Intel LPC Bus Device - 0:1f.0 + +Device (LPCB) +{ + Name(_ADR, 0x001f0000) + + OperationRegion(LPC0, PCI_Config, 0x00, 0x100) + Field (LPC0, AnyAcc, NoLock, Preserve) + { + Offset (0x40), + PMBS, 16, // ABASE + Offset (0x60), // Interrupt Routing Registers + PRTA, 8, + PRTB, 8, + PRTC, 8, + PRTD, 8, + Offset (0x68), + PRTE, 8, + PRTF, 8, + PRTG, 8, + PRTH, 8, + + Offset (0x80), // IO Decode Ranges + IOD0, 8, + IOD1, 8, + + Offset (0xb8), // GPIO Routing Control + GR00, 2, + GR01, 2, + GR02, 2, + GR03, 2, + GR04, 2, + GR05, 2, + GR06, 2, + GR07, 2, + GR08, 2, + GR09, 2, + GR10, 2, + GR11, 2, + GR12, 2, + GR13, 2, + GR14, 2, + GR15, 2, + + Offset (0xf0), // RCBA + RCEN, 1, + , 13, + RCBA, 18, + } + + #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) + + Name(BUF0, ResourceTemplate() + { + Memory32Fixed(ReadOnly, 0xfed00000, 0x400, FED0) + }) + + Method (_STA, 0) // Device Status + { + If (HPTE) { + // Note: Ancient versions of Windows don't want + // to see the HPET in order to work right + If (LGreaterEqual(OSYS, 2001)) { + Return (0xf) // Enable and show device + } Else { + Return (0xb) // Enable and don't show device + } + } + + Return (0x0) // Not enabled, don't show. + } + + Method (_CRS, 0, Serialized) // Current resources + { + If (HPTE) { + CreateDWordField(BUF0, \_SB.PCI0.LPCB.HPET.FED0._BAS, HPT0) + If (Lequal(HPAS, 1)) { + Store(0xfed01000, HPT0) + } + + If (Lequal(HPAS, 2)) { + Store(0xfed02000, HPT0) + } + + If (Lequal(HPAS, 3)) { + Store(0xfed03000, HPT0) + } + } + + Return (BUF0) + } + } + + Device(PIC) // 8259 Interrupt Controller + { + Name(_HID,EISAID("PNP0000")) + Name(_CRS, ResourceTemplate() + { + IO (Decode16, 0x20, 0x20, 0x01, 0x02) + IO (Decode16, 0x24, 0x24, 0x01, 0x02) + IO (Decode16, 0x28, 0x28, 0x01, 0x02) + IO (Decode16, 0x2c, 0x2c, 0x01, 0x02) + IO (Decode16, 0x30, 0x30, 0x01, 0x02) + IO (Decode16, 0x34, 0x34, 0x01, 0x02) + IO (Decode16, 0x38, 0x38, 0x01, 0x02) + IO (Decode16, 0x3c, 0x3c, 0x01, 0x02) + IO (Decode16, 0xa0, 0xa0, 0x01, 0x02) + IO (Decode16, 0xa4, 0xa4, 0x01, 0x02) + IO (Decode16, 0xa8, 0xa8, 0x01, 0x02) + IO (Decode16, 0xac, 0xac, 0x01, 0x02) + IO (Decode16, 0xb0, 0xb0, 0x01, 0x02) + IO (Decode16, 0xb4, 0xb4, 0x01, 0x02) + IO (Decode16, 0xb8, 0xb8, 0x01, 0x02) + IO (Decode16, 0xbc, 0xbc, 0x01, 0x02) + IO (Decode16, 0x4d0, 0x4d0, 0x01, 0x02) + IRQNoFlags () { 2 } + }) + } + + Device(MATH) // FPU + { + Name (_HID, EISAID("PNP0C04")) + Name (_CRS, ResourceTemplate() + { + IO (Decode16, 0xf0, 0xf0, 0x01, 0x01) + IRQNoFlags() { 13 } + }) + } + + Device(LDRC) // LPC device: Resource consumption + { + Name (_HID, EISAID("PNP0C02")) + Name (_UID, 2) + + Name (RBUF, ResourceTemplate() + { + IO (Decode16, 0x2e, 0x2e, 0x1, 0x02) // First SuperIO + IO (Decode16, 0x4e, 0x4e, 0x1, 0x02) // Second SuperIO + IO (Decode16, 0x61, 0x61, 0x1, 0x01) // NMI Status + IO (Decode16, 0x63, 0x63, 0x1, 0x01) // CPU Reserved + IO (Decode16, 0x65, 0x65, 0x1, 0x01) // CPU Reserved + IO (Decode16, 0x67, 0x67, 0x1, 0x01) // CPU Reserved + IO (Decode16, 0x80, 0x80, 0x1, 0x01) // Port 80 Post + IO (Decode16, 0x92, 0x92, 0x1, 0x01) // CPU Reserved + IO (Decode16, 0xb2, 0xb2, 0x1, 0x02) // SWSMI + //IO (Decode16, 0x800, 0x800, 0x1, 0x10) // ACPI I/O trap + IO (Decode16, DEFAULT_ABASE, DEFAULT_ABASE, 0x1, 0x80) // ICH7-M ACPI + IO (Decode16, DEFAULT_GPIOBASE, DEFAULT_GPIOBASE, 0x1, 0x40) // ICH7-M GPIO + }) + + 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" +} diff --git a/src/southbridge/intel/fsp_rangeley/acpi/pcie.asl b/src/southbridge/intel/fsp_rangeley/acpi/pcie.asl new file mode 100644 index 0000000000..68f22b8591 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/acpi/pcie.asl @@ -0,0 +1,169 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 The Chromium OS Authors. 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. + */ + +/* Intel 6/7 Series PCH PCIe support */ + +// PCI Express Ports + +Method (IRQM, 1, Serialized) { + + /* Interrupt Map INTA->INTA, INTB->INTB, INTC->INTC, INTD->INTD */ + Name (IQAA, Package() { + Package() { 0x0000ffff, 0, 0, 16 }, + Package() { 0x0000ffff, 1, 0, 17 }, + Package() { 0x0000ffff, 2, 0, 18 }, + Package() { 0x0000ffff, 3, 0, 19 } }) + Name (IQAP, Package() { + Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKD, 0 } }) + + /* Interrupt Map INTA->INTB, INTB->INTC, INTC->INTD, INTD->INTA */ + Name (IQBA, Package() { + Package() { 0x0000ffff, 0, 0, 17 }, + Package() { 0x0000ffff, 1, 0, 18 }, + Package() { 0x0000ffff, 2, 0, 19 }, + Package() { 0x0000ffff, 3, 0, 16 } }) + Name (IQBP, Package() { + Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKD, 0 }, + Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKA, 0 } }) + + /* Interrupt Map INTA->INTC, INTB->INTD, INTC->INTA, INTD->INTB */ + Name (IQCA, Package() { + Package() { 0x0000ffff, 0, 0, 18 }, + Package() { 0x0000ffff, 1, 0, 19 }, + Package() { 0x0000ffff, 2, 0, 16 }, + Package() { 0x0000ffff, 3, 0, 17 } }) + Name (IQCP, Package() { + Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKD, 0 }, + Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKA, 0 }, + Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKB, 0 } }) + + /* Interrupt Map INTA->INTD, INTB->INTA, INTC->INTB, INTD->INTC */ + Name (IQDA, Package() { + Package() { 0x0000ffff, 0, 0, 19 }, + Package() { 0x0000ffff, 1, 0, 16 }, + Package() { 0x0000ffff, 2, 0, 17 }, + Package() { 0x0000ffff, 3, 0, 18 } }) + Name (IQDP, Package() { + Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKD, 0 }, + Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKA, 0 }, + Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKC, 0 } }) + + Switch (ToInteger (Arg0)) { + /* PCIe Root Port 1 */ + Case (Package() { 1 }) { + If (PICM) { + Return (IQAA) + } Else { + Return (IQAP) + } + } + + /* PCIe Root Port 2 */ + Case (Package() { 2 }) { + If (PICM) { + Return (IQBA) + } Else { + Return (IQBP) + } + } + + /* PCIe Root Port 3 */ + Case (Package() { 3 }) { + If (PICM) { + Return (IQCA) + } Else { + Return (IQCP) + } + } + + /* PCIe Root Port 4 */ + Case (Package() { 4 }) { + If (PICM) { + Return (IQDA) + } Else { + Return (IQDP) + } + } + + Default { + If (PICM) { + Return (IQDA) + } Else { + Return (IQDP) + } + } + } +} + +Device (RP01) +{ + Name (_ADR, 0x00010000) + + #include "pcie_port.asl" + + Method (_PRT) + { + Return (IRQM (RPPN)) + } +} + +Device (RP02) +{ + Name (_ADR, 0x00020000) + + #include "pcie_port.asl" + + Method (_PRT) + { + Return (IRQM (RPPN)) + } +} + +Device (RP03) +{ + Name (_ADR, 0x00030000) + + #include "pcie_port.asl" + + Method (_PRT) + { + Return (IRQM (RPPN)) + } +} + +Device (RP04) +{ + Name (_ADR, 0x00040000) + + #include "pcie_port.asl" + + Method (_PRT) + { + Return (IRQM (RPPN)) + } +} diff --git a/src/southbridge/intel/fsp_rangeley/acpi/pcie_port.asl b/src/southbridge/intel/fsp_rangeley/acpi/pcie_port.asl new file mode 100644 index 0000000000..276227bb50 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/acpi/pcie_port.asl @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 The Chromium OS Authors. 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. + */ + +/* Included in each PCIe Root Port device */ + +OperationRegion (RPCS, PCI_Config, 0x00, 0xFF) +Field (RPCS, AnyAcc, NoLock, Preserve) +{ + Offset (0x4c), // Link Capabilities + , 24, + RPPN, 8, // Root Port Number +} diff --git a/src/southbridge/intel/fsp_rangeley/acpi/sata.asl b/src/southbridge/intel/fsp_rangeley/acpi/sata.asl new file mode 100644 index 0000000000..ec167159e0 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/acpi/sata.asl @@ -0,0 +1,81 @@ +/* + * 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. + */ + +// Intel SATA Controller 0:17.0 + +// Note: Some BIOSes put the S-ATA code into an SSDT to make it easily +// pluggable + +Device (SATA) +{ + Name (_ADR, 0x00170000) + + Device (PRID) + { + Name (_ADR, 0) + + // Get Timing Mode + Method (_GTM) + { + Name(PBUF, Buffer(20) { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00 }) + + CreateDwordField (PBUF, 0, PIO0) + CreateDwordField (PBUF, 4, DMA0) + CreateDwordField (PBUF, 8, PIO1) + CreateDwordField (PBUF, 12, DMA1) + CreateDwordField (PBUF, 16, FLAG) + + // TODO fill return structure + + Return (PBUF) + } + + // Set Timing Mode + Method (_STM, 3) + { + CreateDwordField (Arg0, 0, PIO0) + CreateDwordField (Arg0, 4, DMA0) + CreateDwordField (Arg0, 8, PIO1) + CreateDwordField (Arg0, 12, DMA1) + CreateDwordField (Arg0, 16, FLAG) + + // TODO: Do the deed + } + + Device (DSK0) + { + Name (_ADR, 0) + // TODO: _RMV ? + // TODO: _GTF ? + } + + Device (DSK1) + { + Name (_ADR, 1) + + // TODO: _RMV ? + // TODO: _GTF ? + } + + } +} diff --git a/src/southbridge/intel/fsp_rangeley/acpi/sleepstates.asl b/src/southbridge/intel/fsp_rangeley/acpi/sleepstates.asl new file mode 100644 index 0000000000..aabb397144 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/acpi/sleepstates.asl @@ -0,0 +1,30 @@ +/* + * 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. + */ + +Name(\_S0, Package(){0x0,0x0,0x0,0x0}) + +/* + * S1 and S3 sleep states are not supported + * 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/southbridge/intel/fsp_rangeley/acpi/smbus.asl b/src/southbridge/intel/fsp_rangeley/acpi/smbus.asl new file mode 100644 index 0000000000..efd323dea5 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/acpi/smbus.asl @@ -0,0 +1,240 @@ +/* + * 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. + */ + +// Intel SMBus Controller 0:1f.3 + +Device (SBUS) +{ + Name (_ADR, 0x001f0003) + +#ifdef ENABLE_SMBUS_METHODS + OperationRegion (SMBP, PCI_Config, 0x00, 0x100) + Field(SMBP, DWordAcc, NoLock, Preserve) + { + Offset(0x40), + , 2, + I2CE, 1 + } + + OperationRegion (SMBI, SystemIO, SMBUS_IO_BASE, 0x20) + Field (SMBI, ByteAcc, NoLock, Preserve) + { + HSTS, 8, // Host Status + , 8, + HCNT, 8, // Host Control + HCMD, 8, // Host Command + TXSA, 8, // Transmit Slave Address + DAT0, 8, // Host Data 0 + DAT1, 8, // Host Data 1 + HBDB, 8, // Host Block Data Byte + PECK, 8, // Packet Error Check + RXSA, 8, // Receive Slave Address + RXDA, 16, // Receive Slave Data + AUXS, 8, // Auxiliary Status + AUXC, 8, // Auxiliary Control + SLPC, 8, // SMLink Pin Control + SBPC, 8, // SMBus Pin Control + SSTS, 8, // Slave Status + SCMD, 8, // Slave Command + NADR, 8, // Notify Device Address + NDLB, 8, // Notify Data Low Byte + NDLH, 8, // Notify Data High Byte + } + + // Kill all SMBus communication + Method (KILL, 0, Serialized) + { + Or (HCNT, 0x02, HCNT) // Send Kill + Or (HSTS, 0xff, HSTS) // Clean Status + } + + // Check if last operation completed + // return Failure = 0, Success = 1 + Method (CMPL, 0, Serialized) + { + Store (4000, Local0) // Timeout 200ms in 50us steps + While (Local0) { + If (And(HSTS, 0x02)) { // Completion Status? + Return (1) // Operation Completed + } Else { + Stall (50) + Decrement (Local0) + If (LEqual(Local0, 0)) { + KILL() + } + } + } + + Return (0) // Failure + } + + + // Wait for SMBus to become ready + Method (SRDY, 0, Serialized) + { + Store (200, Local0) // Timeout 200ms + While (Local0) { + If (And(HSTS, 0x40)) { // IN_USE? + Sleep(1) // Wait 1ms + Decrement(Local0) // timeout-- + If (LEqual(Local0, 0)) { + Return (1) + } + } Else { + Store (0, Local0) // We're ready + } + } + + Store (4000, Local0) // Timeout 200ms (50us * 4000) + While (Local0) { + If (And (HSTS, 0x01)) { // Host Busy? + Stall(50) // Wait 50us + Decrement(Local0) // timeout-- + If (LEqual(Local0, 0)) { + KILL() + } + } Else { + Return (0) // Success + } + } + + Return (1) // Failure + } + + // SMBus Send Byte + // Arg0: Address + // Arg1: Data + // Return: 1 = Success, 0=Failure + + Method (SSXB, 2, Serialized) + { + + // Is the SMBus Controller Ready? + If (SRDY()) { + Return (0) + } + + // Send Byte + Store (0, I2CE) // SMBus Enable + Store (0xbf, HSTS) + Store (Arg0, TXSA) // Write Address + Store (Arg1, HCMD) // Write Data + + Store (0x48, HCNT) // Start + Byte Data Protocol + + If (CMPL()) { + Or (HSTS, 0xff, HSTS) // Clean up + Return (1) // Success + } + + Return (0) + } + + + // SMBus Receive Byte + // Arg0: Address + // Return: 0xffff = Failure, Data (8bit) = Success + + Method (SRXB, 2, Serialized) + { + + // Is the SMBus Controller Ready? + If (SRDY()) { + Return (0xffff) + } + + // Receive Byte + Store (0, I2CE) // SMBus Enable + Store (0xbf, HSTS) + Store (Or (Arg0, 1), TXSA) // Write Address + + Store (0x44, HCNT) // Start + + If (CMPL()) { + Or (HSTS, 0xff, HSTS) // Clean up + Return (DAT0) // Success + } + + Return (0xffff) + } + + + // SMBus Write Byte + // Arg0: Address + // Arg1: Command + // Arg2: Data + // Return: 1 = Success, 0=Failure + + Method (SWRB, 3, Serialized) + { + + // Is the SMBus Controller Ready? + If (SRDY()) { + Return (0) + } + + // Send Byte + Store (0, I2CE) // SMBus Enable + Store (0xbf, HSTS) + Store (Arg0, TXSA) // Write Address + Store (Arg1, HCMD) // Write Command + Store (Arg2, DAT0) // Write Data + + Store (0x48, HCNT) // Start + Byte Protocol + + If (CMPL()) { + Or (HSTS, 0xff, HSTS) // Clean up + Return (1) // Success + } + + Return (0) + } + + + // SMBus Read Byte + // Arg0: Address + // Arg1: Command + // Return: 0xffff = Failure, Data (8bit) = Success + + Method (SRDB, 2, Serialized) + { + + // Is the SMBus Controller Ready? + If (SRDY()) { + Return (0xffff) + } + + // Receive Byte + Store (0, I2CE) // SMBus Enable + Store (0xbf, HSTS) + Store (Or (Arg0, 1), TXSA) // Write Address + Store (Arg1, HCMD) // Command + + Store (0x48, HCNT) // Start + + If (CMPL()) { + Or (HSTS, 0xff, HSTS) // Clean up + Return (DAT0) // Success + } + + Return (0xffff) + } +#endif +} diff --git a/src/southbridge/intel/fsp_rangeley/acpi/soc.asl b/src/southbridge/intel/fsp_rangeley/acpi/soc.asl new file mode 100644 index 0000000000..77cd7ae488 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/acpi/soc.asl @@ -0,0 +1,276 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +/* Intel Rangeley support */ + +#include "../soc.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 + } + +#if IS_ENABLED(CONFIG_ACPI_INCLUDE_PMIO) + // PCH Power Management Registers, located at PMBASE (0x1f.0 0x40.l) + OperationRegion(PMIO, SystemIO, DEFAULT_ABASE, 0x80) + Field(PMIO, ByteAcc, NoLock, Preserve) + { + Offset(0x20), // GPE0_STS + , 16, + GS00, 1, // GPIO00 SCI/Wake Status + GS01, 1, // GPIO01 SCI/Wake Status + GS02, 1, // GPIO02 SCI/Wake Status + GS03, 1, // GPIO03 SCI/Wake Status + GS04, 1, // GPIO04 SCI/Wake Status + GS05, 1, // GPIO05 SCI/Wake Status + GS06, 1, // GPIO06 SCI/Wake Status + GS07, 1, // GPIO07 SCI/Wake Status + GS08, 1, // GPIO08 SCI/Wake Status + GS09, 1, // GPIO09 SCI/Wake Status + GS10, 1, // GPIO10 SCI/Wake Status + GS11, 1, // GPIO11 SCI/Wake Status + GS12, 1, // GPIO12 SCI/Wake Status + GS13, 1, // GPIO13 SCI/Wake Status + GS14, 1, // GPIO14 SCI/Wake Status + GS15, 1, // GPIO15 SCI/Wake Status + Offset(0x28), // GPE0_EN + , 16, + GE00, 1, // GPIO00 SCI/Wake Enable + GE01, 1, // GPIO01 SCI/Wake Enable + GE02, 1, // GPIO02 SCI/Wake Enable + GE03, 1, // GPIO03 SCI/Wake Enable + GE04, 1, // GPIO04 SCI/Wake Enable + GE05, 1, // GPIO05 SCI/Wake Enable + GE06, 1, // GPIO06 SCI/Wake Enable + GE07, 1, // GPIO07 SCI/Wake Enable + GE08, 1, // GPIO08 SCI/Wake Enable + GE09, 1, // GPIO09 SCI/Wake Enable + GE10, 1, // GPIO10 SCI/Wake Enable + GE11, 1, // GPIO11 SCI/Wake Enable + GE12, 1, // GPIO12 SCI/Wake Enable + GE13, 1, // GPIO13 SCI/Wake Enable + GE14, 1, // GPIO14 SCI/Wake Enable + GE15, 1, // GPIO15 SCI/Wake Enable + Offset(0x42), // General Purpose Control + , 1, // skip 1 bit + GPEC, 1, // SWGPE_CTRL + } +#endif + +#if IS_ENABLED(CONFIG_ACPI_INCLUDE_GPIO) + // GPIO IO mapped registers (0x1f.0 reg 0x48.l) + OperationRegion(GPIO, SystemIO, DEFAULT_GPIOBASE, 0x6c) + Field(GPIO, ByteAcc, NoLock, Preserve) + { + Offset(0x00), // GPIO Use Select + GU00, 8, + GU01, 8, + GU02, 8, + GU03, 8, + Offset(0x04), // GPIO IO Select + GIO0, 8, + GIO1, 8, + GIO2, 8, + GIO3, 8, + Offset(0x0c), // GPIO Level + GL00, 1, + GP01, 1, + GP02, 1, + GP0e, 1, + GP04, 1, + GP05, 1, + GP06, 1, + GP07, 1, + GP08, 1, + GP09, 1, + GP10, 1, + GP11, 1, + GP12, 1, + GP13, 1, + GP14, 1, + GP15, 1, + GP16, 1, + GP17, 1, + GP18, 1, + GP19, 1, + GP20, 1, + GP21, 1, + GP22, 1, + GP23, 1, + GP24, 1, + GP25, 1, + GP26, 1, + GP27, 1, + GP28, 1, + GP29, 1, + GP30, 1, + GP31, 1, + Offset(0x18), // GPIO Blink + GB00, 8, + GB01, 8, + GB02, 8, + GB03, 8, + Offset(0x2c), // GPIO Invert + GIV0, 8, + GIV1, 8, + GIV2, 8, + GIV3, 8, + Offset(0x30), // GPIO Use Select 2 + GU04, 8, + GU05, 8, + GU06, 8, + GU07, 8, + Offset(0x34), // GPIO IO Select 2 + GIO4, 8, + GIO5, 8, + GIO6, 8, + GIO7, 8, + Offset(0x38), // GPIO Level 2 + GP32, 1, + GP33, 1, + GP34, 1, + GP35, 1, + GP36, 1, + GP37, 1, + GP38, 1, + GP39, 1, + GP40, 1, + GP41, 1, + GP42, 1, + GP43, 1, + GP44, 1, + GP45, 1, + GP46, 1, + GP47, 1, + GP48, 1, + GP49, 1, + GP50, 1, + GP51, 1, + GP52, 1, + GP53, 1, + GP54, 1, + GP55, 1, + GP56, 1, + GP57, 1, + GP58, 1, + GP59, 1, + GP60, 1, + GP61, 1, + GP62, 1, + GP63, 1, + Offset(0x40), // GPIO Use Select 3 + GU08, 8, + GU09, 4, + Offset(0x44), // GPIO IO Select 3 + GIO8, 8, + GIO9, 4, + Offset(0x48), // GPIO Level 3 + GP64, 1, + GP65, 1, + GP66, 1, + GP67, 1, + GP68, 1, + GP69, 1, + GP70, 1, + GP71, 1, + GP72, 1, + GP73, 1, + GP74, 1, + GP75, 1, + } +#endif + + // ICH7 Root Complex Register Block. Memory Mapped through RCBA) + OperationRegion(RCRB, SystemMemory, DEFAULT_RCBA, 0x4000) + Field(RCRB, DWordAcc, Lock, Preserve) + { + Offset(0x0000), // Backbone + Offset(0x1000), // Chipset + Offset(0x3000), // Legacy Configuration Registers + Offset(0x3404), // High Performance Timer Configuration + HPAS, 2, // Address Select + , 5, + HPTE, 1, // Address Enable + Offset(0x3418), // FD (Function Disable) + , 1, // Reserved + PCID, 1, // PCI bridge disable + SA1D, 1, // SATA1 disable + SMBD, 1, // SMBUS disable + HDAD, 1, // Azalia disable + , 8, // Reserved + EH2D, 1, // EHCI #2 disable + LPBD, 1, // LPC bridge disable + EH1D, 1, // EHCI #1 disable + RP1D, 1, // Root Port 1 disable + RP2D, 1, // Root Port 2 disable + RP3D, 1, // Root Port 3 disable + RP4D, 1, // Root Port 4 disable + TTRD, 1, // Thermal sensor registers disable + SA2D, 1, // SATA2 disable + Offset(0x3428), // FD2 (Function Disable 2) + BDFD, 1, // Display BDF + ME1D, 1, // ME Interface 1 disable + ME2D, 1, // ME Interface 2 disable + IDRD, 1, // IDE redirect disable + KTCT, 1, // Keyboard Text redirect disable + } +} + +// PCI Express Ports 0:[1-4].0 +#include "pcie.asl" + +// USB 0:16.0 +#include "usb.asl" + +// LPC Bridge 0:1f.0 +#include "lpc.asl" + +// SATA 0:17.0 +#include "sata.asl" + +// SMBus 0:1f.3 +#include "smbus.asl" + +// IRQ routing for each PCI device +#include "irqroute.asl" + +Method (_OSC, 4) +{ + /* Check for proper GUID */ + If (LEqual (Arg0, ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) + { + /* Let OS control everything */ + Return (Arg3) + } + Else + { + /* Unrecognized UUID */ + CreateDWordField (Arg3, 0, CDW1) + Or (CDW1, 4, CDW1) + Return (Arg3) + } +} diff --git a/src/southbridge/intel/fsp_rangeley/acpi/usb.asl b/src/southbridge/intel/fsp_rangeley/acpi/usb.asl new file mode 100644 index 0000000000..274a570f80 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/acpi/usb.asl @@ -0,0 +1,52 @@ +/* + * 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. + */ + +/* Intel Rangeley USB support */ + +// EHCI Controller 0:16.0 + +Device (EHC1) +{ + Name(_ADR, 0x00160000) + + Name (_PRW, Package(){ 13, 4 }) // Power Resources for Wake + + // Leave USB ports on for to allow Wake from USB + + Method(_S3D,0) // Highest D State in S3 State + { + Return (2) + } + + Method(_S4D,0) // Highest D State in S4 State + { + Return (2) + } + + Device (HUB7) + { + Name (_ADR, 0x00000000) + + Device (PRT1) { Name (_ADR, 1) } // USB Port 0 + Device (PRT2) { Name (_ADR, 2) } // USB Port 1 + Device (PRT3) { Name (_ADR, 3) } // USB Port 2 + Device (PRT4) { Name (_ADR, 4) } // USB Port 3 + } +} diff --git a/src/southbridge/intel/fsp_rangeley/chip.h b/src/southbridge/intel/fsp_rangeley/chip.h new file mode 100644 index 0000000000..790270023a --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/chip.h @@ -0,0 +1,88 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#ifndef SOUTHBRIDGE_INTEL_RANGELEY_CHIP_H +#define SOUTHBRIDGE_INTEL_RANGELEY_CHIP_H + +#include + +struct southbridge_intel_fsp_rangeley_config { + + /** + * GPI Routing configuration + * + * Only the lower two bits have a meaning: + * 00: No effect + * 01: SMI# (if corresponding ALT_GPI_SMI_EN bit is also set) + * 10: SCI (if corresponding GPIO_EN bit is also set) + * 11: reserved + */ + uint8_t gpi0_routing; + uint8_t gpi1_routing; + uint8_t gpi2_routing; + uint8_t gpi3_routing; + uint8_t gpi4_routing; + uint8_t gpi5_routing; + uint8_t gpi6_routing; + uint8_t gpi7_routing; + uint8_t gpi8_routing; + uint8_t gpi9_routing; + uint8_t gpi10_routing; + uint8_t gpi11_routing; + uint8_t gpi12_routing; + uint8_t gpi13_routing; + uint8_t gpi14_routing; + uint8_t gpi15_routing; + + uint32_t gpe0_en; + uint16_t alt_gp_smi_en; + + /* IDE configuration */ + uint32_t ide_legacy_combined; + uint32_t sata_ahci; + uint8_t sata_port_map; + uint32_t sata_port0_gen3_tx; + uint32_t sata_port1_gen3_tx; + + uint32_t gen1_dec; + uint32_t gen2_dec; + uint32_t gen3_dec; + uint32_t gen4_dec; + + /* Enable linear PCIe Root Port function numbers starting at zero */ + uint8_t pcie_port_coalesce; + + /* Override PCIe ASPM */ + uint8_t pcie_aspm_f0; + uint8_t pcie_aspm_f1; + uint8_t pcie_aspm_f2; + uint8_t pcie_aspm_f3; + uint8_t pcie_aspm_f4; + uint8_t pcie_aspm_f5; + uint8_t pcie_aspm_f6; + uint8_t pcie_aspm_f7; + + /* ACPI configuration */ + uint8_t fadt_pm_profile; + uint16_t fadt_boot_arch; + +}; + +#endif /* SOUTHBRIDGE_INTEL_RANGELEY_CHIP_H */ diff --git a/src/southbridge/intel/fsp_rangeley/early_init.c b/src/southbridge/intel/fsp_rangeley/early_init.c new file mode 100644 index 0000000000..448cbeb410 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/early_init.c @@ -0,0 +1,79 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2010 coresystems GmbH + * Copyright (C) 2011 Google Inc + * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "pci_devs.h" +#include "soc.h" + +static void rangeley_setup_bars(void) +{ + /* Setting up Southbridge. */ + printk(BIOS_DEBUG, "Setting up static southbridge registers..."); + pci_write_config32(LPC_BDF, RCBA, (uintptr_t)DEFAULT_RCBA | RCBA_ENABLE); + pci_write_config32(LPC_BDF, ABASE, DEFAULT_ABASE | SET_BAR_ENABLE); + pci_write_config32(LPC_BDF, PBASE, DEFAULT_PBASE | SET_BAR_ENABLE); + printk(BIOS_DEBUG, " done.\n"); + + printk(BIOS_DEBUG, "Disabling Watchdog timer..."); + /* Disable the watchdog reboot and turn off the watchdog timer */ + write8((void *)(DEFAULT_PBASE + PMC_CFG), + read8((void *)(DEFAULT_PBASE + PMC_CFG)) | NO_REBOOT); // disable reboot on timer trigger + outw(DEFAULT_ABASE + TCO1_CNT, inw(DEFAULT_ABASE + TCO1_CNT) | + TCO_TMR_HALT); // disable watchdog timer + + printk(BIOS_DEBUG, " done.\n"); + +} + +static void reset_rtc(void) +{ + uint32_t pbase = pci_read_config32(LPC_BDF, PBASE) & + 0xfffffff0; + uint32_t gen_pmcon1 = read32((void *)(pbase + GEN_PMCON1)); + int rtc_failed = !!(gen_pmcon1 & RPS); + + if (rtc_failed) { + printk(BIOS_DEBUG, + "RTC Failure detected. Resetting Date to %s\n", + coreboot_dmi_date); + + /* Clear the power failure flag */ + write32((void *)(DEFAULT_PBASE + GEN_PMCON1), + gen_pmcon1 & ~RPS); + } + + cmos_init(rtc_failed); +} + +void rangeley_sb_early_initialization(void) +{ + /* Setup all BARs required for early PCIe and raminit */ + rangeley_setup_bars(); + + reset_rtc(); +} diff --git a/src/southbridge/intel/fsp_rangeley/early_smbus.c b/src/southbridge/intel/fsp_rangeley/early_smbus.c new file mode 100644 index 0000000000..f46f5e9812 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/early_smbus.c @@ -0,0 +1,61 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-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. + */ + +#include +#include +#include +#include +#include "soc.h" +#include "smbus.h" + +void enable_smbus(void) +{ + device_t dev; + + /* Set the SMBus device statically. */ + dev = PCI_DEV(0x0, 0x1f, 0x3); + + /* Check to make sure we've got the right device. */ + if (pci_read_config16(dev, 0x0) != 0x8086) { + die("SMBus controller not found!"); + } + + /* Set SMBus I/O base. */ + pci_write_config32(dev, SMB_BASE, + SMBUS_IO_BASE | PCI_BASE_ADDRESS_SPACE_IO); + + /* Set SMBus enable. */ + pci_write_config8(dev, HOSTC, HST_EN); + + /* Set SMBus I/O space enable. */ + pci_write_config16(dev, PCI_COMMAND, PCI_COMMAND_IO); + + /* Disable interrupt generation. */ + outb(0, SMBUS_IO_BASE + SMBHSTCTL); + + /* Clear any lingering errors, so transactions can run. */ + outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); + printk(BIOS_DEBUG, "SMBus controller enabled.\n"); +} + +int smbus_read_byte(unsigned device, unsigned address) +{ + return do_smbus_read_byte(SMBUS_IO_BASE, device, address); +} diff --git a/src/southbridge/intel/fsp_rangeley/early_spi.c b/src/southbridge/intel/fsp_rangeley/early_spi.c new file mode 100644 index 0000000000..26495e0152 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/early_spi.c @@ -0,0 +1,114 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 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. + */ + +#include +#include +#include +#include +#include +#include "soc.h" + +#define SPI_DELAY 10 /* 10us */ +#define SPI_RETRY 200000 /* 2s */ + +static int early_spi_read_block(u32 offset, u8 size, u8 *buffer) +{ + u32 *ptr32 = (u32*)buffer; + u32 i; + + /* Clear status bits */ + RCBA16(SPIBAR_HSFS) |= SPIBAR_HSFS_AEL | SPIBAR_HSFS_FCERR | + SPIBAR_HSFS_FDONE; + + if (RCBA16(SPIBAR_HSFS) & SPIBAR_HSFS_SCIP) { + printk(BIOS_ERR, "SPI ERROR: transaction in progress\n"); + return -1; + } + + /* Set flash address */ + RCBA32(SPIBAR_FADDR) = offset; + + /* Setup read transaction */ + RCBA16(SPIBAR_HSFC) = SPIBAR_HSFC_BYTE_COUNT(size) | + SPIBAR_HSFC_CYCLE_READ; + + /* Start transaction */ + RCBA16(SPIBAR_HSFC) |= SPIBAR_HSFC_GO; + + /* Wait for completion */ + for (i = 0; i < SPI_RETRY; i++) { + if (RCBA16(SPIBAR_HSFS) & SPIBAR_HSFS_SCIP) { + /* Cycle in progress, wait 1ms */ + udelay(SPI_DELAY); + continue; + } + + if (RCBA16(SPIBAR_HSFS) & SPIBAR_HSFS_AEL) { + printk(BIOS_ERR, "SPI ERROR: Access Error\n"); + return -1; + + } + + if (RCBA16(SPIBAR_HSFS) & SPIBAR_HSFS_FCERR) { + printk(BIOS_ERR, "SPI ERROR: Flash Cycle Error\n"); + return -1; + } + break; + } + + if (i >= SPI_RETRY) { + printk(BIOS_ERR, "SPI ERROR: Timeout\n"); + return -1; + } + + /* Read the data */ + for (i = 0; i < size; i+=sizeof(u32)) { + if (size-i >= 4) { + /* reading >= dword */ + *ptr32++ = RCBA32(SPIBAR_FDATA(i/sizeof(u32))); + } else { + /* reading < dword */ + u8 j, *ptr8 = (u8*)ptr32; + u32 temp = RCBA32(SPIBAR_FDATA(i/sizeof(u32))); + for (j = 0; j < (size-i); j++) { + *ptr8++ = temp & 0xff; + temp >>= 8; + } + } + } + + return size; +} + +int early_spi_read(u32 offset, u32 size, u8 *buffer) +{ + u32 current = 0; + + while (size > 0) { + u8 count = (size < 64) ? size : 64; + if (early_spi_read_block(offset + current, count, + buffer + current) < 0) + return -1; + size -= count; + current += count; + } + + return 0; +} diff --git a/src/southbridge/intel/fsp_rangeley/early_usb.c b/src/southbridge/intel/fsp_rangeley/early_usb.c new file mode 100644 index 0000000000..d5071c9abe --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/early_usb.c @@ -0,0 +1,47 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-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. + */ + +#include +#include +#include +#include +#include "soc.h" + +#define SOC_EHCI1_TEMP_BAR0 0xe8000000 + +/* + * Setup USB controller MMIO BAR to prevent the + * reference code from resetting the controller. + * + * The BAR will be re-assigned during device + * enumeration so these are only temporary. + */ +void enable_usb_bar(void) +{ + device_t usb0 = SOC_EHCI1_DEV; + u32 cmd; + + /* USB Controller 0 */ + pci_write_config32(usb0, PCI_BASE_ADDRESS_0, + SOC_EHCI1_TEMP_BAR0); + cmd = pci_read_config32(usb0, PCI_COMMAND); + cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config32(usb0, PCI_COMMAND, cmd); +} diff --git a/src/southbridge/intel/fsp_rangeley/gpio.c b/src/southbridge/intel/fsp_rangeley/gpio.c new file mode 100644 index 0000000000..a0f6f0f394 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/gpio.c @@ -0,0 +1,108 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 The Chromium OS Authors. All rights reserved. + * Copyright (C) 2013 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#include +#include +#include + +#include "soc.h" +#include "gpio.h" + +#define MAX_GPIO_NUMBER 31 /* zero based */ + +void setup_soc_gpios(const struct soc_gpio_map *gpio) +{ + u16 gpiobase = pci_read_config16(SOC_LPC_DEV, GBASE) & ~0xf; + u32 *cfiobase = (u32 *)(pci_read_config32(SOC_LPC_DEV, IOBASE) & ~0xf); + u32 cfio_cnt = 0; + + + /* GPIO */ + if (gpio->core.level) + outl(*((u32*)gpio->core.level), gpiobase + GPIO_SC_GP_LVL); + if (gpio->core.mode) + outl(*((u32*)gpio->core.mode), gpiobase + GPIO_SC_USE_SEL); + if (gpio->core.direction) + outl(*((u32*)gpio->core.direction), gpiobase + GPIO_SC_IO_SEL); + if (gpio->core.tpe) + outl(*((u32*)gpio->core.tpe), gpiobase + GPIO_SC_TPE); + if (gpio->core.tne) + outl(*((u32*)gpio->core.tne), gpiobase + GPIO_SC_TNE); + if (gpio->core.ts) + outl(*((u32*)gpio->core.ts), gpiobase + GPIO_SC_TS); + + /* GPIO SUS Well Set 1 */ + if (gpio->sus.level) + outl(*((u32*)gpio->sus.level), gpiobase + GPIO_SUS_GP_LVL); + if (gpio->sus.mode) + outl(*((u32*)gpio->sus.mode), gpiobase + GPIO_SUS_USE_SEL); + if (gpio->sus.direction) + outl(*((u32*)gpio->sus.direction), gpiobase + GPIO_SUS_IO_SEL); + if (gpio->sus.tpe) + outl(*((u32*)gpio->sus.tpe), gpiobase + GPIO_SUS_TPE); + if (gpio->sus.tne) + outl(*((u32*)gpio->sus.tne), gpiobase + GPIO_SUS_TNE); + if (gpio->sus.ts) + outl(*((u32*)gpio->sus.ts), gpiobase + GPIO_SUS_TS); + if (gpio->sus.we) + outl(*((u32*)gpio->sus.we), gpiobase + GPIO_SUS_WE); + + /* GPIO PAD Settings */ + /* CFIO Core Well Set 1 */ + if ((gpio->core.cfio_init != NULL) || (gpio->core.cfio_entrynum != 0)) { + write32(cfiobase + (0x0700 / sizeof(u32)), (u32)0x01001002); + for(cfio_cnt = 0; cfio_cnt < gpio->core.cfio_entrynum; cfio_cnt++) { + if (!((u32)gpio->core.cfio_init[cfio_cnt].pad_conf_0)) + continue; + write32(cfiobase + ((CFIO_PAD_CONF0 + (16*cfio_cnt))/sizeof(u32)), (u32)gpio->core.cfio_init[cfio_cnt].pad_conf_0); + write32(cfiobase + ((CFIO_PAD_CONF1 + (16*cfio_cnt))/sizeof(u32)), (u32)gpio->core.cfio_init[cfio_cnt].pad_conf_1); + write32(cfiobase + ((CFIO_PAD_VAL + (16*cfio_cnt))/sizeof(u32)), (u32)gpio->core.cfio_init[cfio_cnt].pad_val); + write32(cfiobase + ((CFIO_PAD_DFT + (16*cfio_cnt))/sizeof(u32)), (u32)gpio->core.cfio_init[cfio_cnt].pad_dft); + } + write32(cfiobase + (0x0700 / sizeof(u32)), (u32)0x01041002); + } + + /* CFIO SUS Well Set 1 */ + if ((gpio->sus.cfio_init != NULL) || (gpio->sus.cfio_entrynum != 0)) { + write32(cfiobase + (0x1700 / sizeof(u32)), (u32)0x01001002); + for(cfio_cnt = 0; cfio_cnt < gpio->sus.cfio_entrynum; cfio_cnt++) { + if (!((u32)gpio->sus.cfio_init[cfio_cnt].pad_conf_0)) + continue; + write32(cfiobase + ((CFIO_PAD_CONF0 + 0x1000 + (16*cfio_cnt))/sizeof(u32)), (u32)gpio->sus.cfio_init[cfio_cnt].pad_conf_0); + write32(cfiobase + ((CFIO_PAD_CONF1 + 0x1000 + (16*cfio_cnt))/sizeof(u32)), (u32)gpio->sus.cfio_init[cfio_cnt].pad_conf_1); + write32(cfiobase + ((CFIO_PAD_VAL + 0x1000 + (16*cfio_cnt))/sizeof(u32)), (u32)gpio->sus.cfio_init[cfio_cnt].pad_val); + write32(cfiobase + ((CFIO_PAD_DFT + 0x1000 + (16*cfio_cnt))/sizeof(u32)), (u32)gpio->sus.cfio_init[cfio_cnt].pad_dft); + } + write32(cfiobase + (0x1700 / sizeof(u32)), (u32)0x01041002); + } +} + +int get_gpio(int gpio_num) +{ + u16 gpio_base = pci_read_config16(SOC_LPC_DEV, GBASE) & ~0xf; + int bit; + + if (gpio_num > MAX_GPIO_NUMBER) + return 0; /* Ignore wrong GPIO numbers. */ + + bit = gpio_num % 32; + + return (inl(gpio_base + GPIO_SC_USE_SEL) >> bit) & 1; +} diff --git a/src/southbridge/intel/fsp_rangeley/gpio.h b/src/southbridge/intel/fsp_rangeley/gpio.h new file mode 100644 index 0000000000..0ead65cb40 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/gpio.h @@ -0,0 +1,128 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 The Chromium OS Authors. All rights reserved. + * Copyright (C) 2013 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#ifndef INTEL_RANGELEY_GPIO_H +#define INTEL_RANGELEY_GPIO_H + +#define GPIO_MODE_NATIVE 0 +#define GPIO_MODE_GPIO 1 +#define GPIO_MODE_NONE 1 + +#define GPIO_DIR_OUTPUT 0 +#define GPIO_DIR_INPUT 1 + +#define GPIO_LEVEL_LOW 0 +#define GPIO_LEVEL_HIGH 1 + +#define GPIO_TPE_DISABLE 0 +#define GPIO_TPE_ENABLE 1 + +#define GPIO_TNE_DISABLE 0 +#define GPIO_TNE_ENABLE 1 + +#define GPIO_TS_DISABLE 0 +#define GPIO_TS_ENABLE 1 + +#define GPIO_WE_DISABLE 0 +#define GPIO_WE_ENABLE 1 + +struct soc_gpio { + u32 gpio0 : 1; + u32 gpio1 : 1; + u32 gpio2 : 1; + u32 gpio3 : 1; + u32 gpio4 : 1; + u32 gpio5 : 1; + u32 gpio6 : 1; + u32 gpio7 : 1; + u32 gpio8 : 1; + u32 gpio9 : 1; + u32 gpio10 : 1; + u32 gpio11 : 1; + u32 gpio12 : 1; + u32 gpio13 : 1; + u32 gpio14 : 1; + u32 gpio15 : 1; + u32 gpio16 : 1; + u32 gpio17 : 1; + u32 gpio18 : 1; + u32 gpio19 : 1; + u32 gpio20 : 1; + u32 gpio21 : 1; + u32 gpio22 : 1; + u32 gpio23 : 1; + u32 gpio24 : 1; + u32 gpio25 : 1; + u32 gpio26 : 1; + u32 gpio27 : 1; + u32 gpio28 : 1; + u32 gpio29 : 1; + u32 gpio30 : 1; + u32 gpio31 : 1; +} __attribute__ ((packed)); + +struct soc_cfio { + u32 pad_conf_0; + u32 pad_conf_1; + u32 pad_val; + u32 pad_dft; +} __attribute__ ((packed)); + +struct soc_gpio_map { + /* GPIO core */ + struct { + const struct soc_gpio *mode; + const struct soc_gpio *direction; + const struct soc_gpio *level; + const struct soc_gpio *tpe; + const struct soc_gpio *tne; + const struct soc_gpio *ts; + const struct soc_cfio *cfio_init; + const u32 cfio_entrynum; + }core; + + /* GPIO SUS */ + struct { + const struct soc_gpio *mode; + const struct soc_gpio *direction; + const struct soc_gpio *level; + const struct soc_gpio *tpe; + const struct soc_gpio *tne; + const struct soc_gpio *ts; + const struct soc_gpio *we; + const struct soc_cfio *cfio_init; + const u32 cfio_entrynum; + }sus; + + +}; + +/* Configure GPIOs with mainboard provided settings */ +void setup_soc_gpios(const struct soc_gpio_map *gpio); + +/* Get GPIO pin value */ +int get_gpio(int gpio_num); +/* + * Get a number comprised of multiple GPIO values. gpio_num_array points to + * the array of GPIO pin numbers to scan, terminated by -1. + */ +unsigned get_gpios(const int *gpio_num_array); + +#endif diff --git a/src/southbridge/intel/fsp_rangeley/irq.h b/src/southbridge/intel/fsp_rangeley/irq.h new file mode 100644 index 0000000000..2028aaa3a9 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/irq.h @@ -0,0 +1,166 @@ +/* + * 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. + */ + +#ifndef _RANGELEY_IRQ_H_ +#define _RANGELEY_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_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 +#define PIRQ_PIC_IRQDISABLE 0x80 +#define PIRQ_PIC_UNKNOWN_UNUSED 0xff + + +/* 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 + +#define NUM_OF_PCI_DEVS 32 +#define NUM_PIRQS 8 + +struct rangeley_irq_route { + /* Per device configuration. */ + uint16_t pcidev[NUM_OF_PCI_DEVS]; + /* Route path for each internal PIRQx in PIC mode. */ + uint8_t pic[NUM_PIRQS]; +}; + +extern const struct rangeley_irq_route global_rangeley_irq_route; + +#define DEFINE_IRQ_ROUTES \ + const struct rangeley_irq_route global_rangeley_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 /* _RANGELEY_IRQ_H_ */ diff --git a/src/southbridge/intel/fsp_rangeley/lpc.c b/src/southbridge/intel/fsp_rangeley/lpc.c new file mode 100644 index 0000000000..c04708194c --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/lpc.c @@ -0,0 +1,478 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2013 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "soc.h" +#include "irq.h" +#include "nvs.h" + +#define NMI_OFF 0 + +#define ENABLE_ACPI_MODE_IN_COREBOOT 0 +#define TEST_SMM_FLASH_LOCKDOWN 0 + +typedef struct southbridge_intel_fsp_rangeley_config config_t; + +static void soc_enable_apic(struct device *dev) +{ + int i; + u32 reg32; + volatile u32 *ioapic_index = (volatile u32 *)(IO_APIC_ADDR); + volatile u32 *ioapic_data = (volatile u32 *)(IO_APIC_ADDR + 0x10); + u8 *ilb_base = (u8 *)(pci_read_config32(dev, IBASE) & ~0x0f); + + /* + * Enable ACPI I/O and power management. + * Set SCI IRQ to IRQ9 + */ + write32(ilb_base + ILB_OIC, 0x100); /* AEN */ + reg32 = read32(ilb_base + ILB_OIC); /* Read back per BWG */ + write32(ilb_base + ILB_ACTL, 0); /* ACTL bit 2:0 SCIS IRQ9 */ + + *ioapic_index = 0; + *ioapic_data = (1 << 25); + + /* Affirm full set of redirection table entries ("write once") */ + *ioapic_index = 1; + reg32 = *ioapic_data; + *ioapic_index = 1; + *ioapic_data = reg32; + + *ioapic_index = 0; + reg32 = *ioapic_data; + printk(BIOS_DEBUG, "Southbridge APIC ID = %x\n", (reg32 >> 24) & 0x0f); + if (reg32 != (1 << 25)) + die("APIC Error\n"); + + printk(BIOS_SPEW, "Dumping IOAPIC registers\n"); + for (i=0; i<3; i++) { + *ioapic_index = i; + printk(BIOS_SPEW, " reg 0x%04x:", i); + reg32 = *ioapic_data; + printk(BIOS_SPEW, " 0x%08x\n", reg32); + } + + *ioapic_index = 3; /* Select Boot Configuration register. */ + *ioapic_data = 1; /* Use Processor System Bus to deliver interrupts. */ +} + +static void soc_enable_serial_irqs(struct device *dev) +{ + u8 *ibase; + + ibase = (u8 *)(pci_read_config32(dev, IBASE) & ~0xF); + + /* Set packet length and toggle silent mode bit for one frame. */ + write8(ibase + ILB_SERIRQ_CNTL, (1 << 7)); + +#if !CONFIG_SERIRQ_CONTINUOUS_MODE + write8(ibase + ILB_SERIRQ_CNTL, 0); +#endif +} + +/* + * Write PCI config space IRQ assignments. PCI devices have the INT_LINE + * (0x3C) and INT_PIN (0x3D) registers which report interrupt routing + * information to operating systems and drivers. The INT_PIN register is + * generally read only and reports which interrupt pin A - D it uses. The + * INT_LINE register is configurable and reports which IRQ (generally the + * PIC IRQs 1 - 15) it will use. This needs to take interrupt pin swizzling + * on devices that are downstream on a PCI bridge into account. + * + * This function will loop through all enabled PCI devices and program the + * INT_LINE register with the correct PIC IRQ number for the INT_PIN that it + * uses. It then configures each interrupt in the pic to be level triggered. + */ +static void write_pci_config_irqs(void) +{ + device_t irq_dev; + device_t targ_dev; + uint8_t int_line = 0; + uint8_t original_int_pin = 0; + uint8_t new_int_pin = 0; + uint16_t current_bdf = 0; + uint16_t parent_bdf = 0; + uint8_t pirq = 0; + uint8_t device_num = 0; + const struct rangeley_irq_route *ir = &global_rangeley_irq_route; + + if (ir == NULL) { + printk(BIOS_WARNING, "Warning: Can't write PCI IRQ assignments because" + " 'global_rangeley_irq_route' structure does not exist\n"); + return; + } + + /* + * Loop through all enabled devices and program their + * INT_LINE, INT_PIN registers from values taken from + * the Interrupt Route registers in the ILB + */ + printk(BIOS_DEBUG, "PCI_CFG IRQ: Write PCI config space IRQ assignments\n"); + for(irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) { + + if ((irq_dev->path.type != DEVICE_PATH_PCI) || + (!irq_dev->enabled)) + continue; + + current_bdf = irq_dev->path.pci.devfn | + irq_dev->bus->secondary << 8; + + /* + * Step 1: Get the INT_PIN and device structure to look for + * in the pirq_data table defined in the mainboard directory. + */ + targ_dev = NULL; + new_int_pin = get_pci_irq_pins(irq_dev, &targ_dev); + if (targ_dev == NULL || new_int_pin < 1) + continue; + + /* Get the original INT_PIN for record keeping */ + original_int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN); + + parent_bdf = targ_dev->path.pci.devfn + | targ_dev->bus->secondary << 8; + device_num = PCI_SLOT(parent_bdf); + + if (ir->pcidev[device_num] == 0) { + printk(BIOS_WARNING, + "Warning: PCI Device %d does not have an IRQ entry, skipping it\n", + device_num); + continue; + } + + /* Find the PIRQ that is attached to the INT_PIN this device uses */ + pirq = (ir->pcidev[device_num] >> ((new_int_pin - 1) * 4)) & 0xF; + + /* Get the INT_LINE this device/function will use */ + int_line = ir->pic[pirq]; + + if (int_line != PIRQ_PIC_IRQDISABLE) { + /* Set this IRQ to level triggered since it is used by a PCI device */ + i8259_configure_irq_trigger(int_line, IRQ_LEVEL_TRIGGERED); + /* Set the Interrupt Line register in PCI config space */ + pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, int_line); + } else { + /* Set the Interrupt line register as "unknown or unused" */ + pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, + PIRQ_PIC_UNKNOWN_UNUSED); + } + + printk(BIOS_SPEW, "\tINT_PIN\t\t: %d (%s)\n", + original_int_pin, pin_to_str(original_int_pin)); + if (parent_bdf != current_bdf) + printk(BIOS_SPEW, "\tSwizzled to\t: %d (%s)\n", + new_int_pin, pin_to_str(new_int_pin)); + printk(BIOS_SPEW, "\tPIRQ\t\t: %c\n" + "\tINT_LINE\t: 0x%X (IRQ %d)\n", + 'A' + pirq, int_line, int_line); + } + printk(BIOS_DEBUG, "PCI_CFG IRQ: Finished writing PCI config space IRQ assignments\n"); +} + +static void soc_pirq_init(device_t dev) +{ + int i, j; + int pirq; + u8 *ibase = (u8 *)(pci_read_config32(dev, IBASE) & ~0xF); + u8 *pr_base = ibase + 0x08; + u16 *ir_base = (u16 *)(ibase + 0x20); + u32 *actl = (u32 *)ibase; + const struct rangeley_irq_route *ir = &global_rangeley_irq_route; + + /* Set up the PIRQ PIC routing based on static config. */ + printk(BIOS_SPEW, "Start writing IRQ assignments\n" + "PIRQ\tA \tB \tC \tD \tE \tF \tG \tH\n" + "IRQ "); + for (i = 0; i < NUM_PIRQS; i++) { + write8(pr_base + i*sizeof(ir->pic[i]), ir->pic[i]); + printk(BIOS_SPEW, "\t%d", ir->pic[i]); + } + printk(BIOS_SPEW, "\n\n"); + + /* Set up the per device PIRQ routing based on static config. */ + printk(BIOS_SPEW, "\t\t\tPIRQ[A-H] routed to each INT_PIN[A-D]\n" + "Dev\tINTA (IRQ)\tINTB (IRQ)\tINTC (IRQ)\tINTD (IRQ)\n"); + for (i = 0; i < NUM_OF_PCI_DEVS; i++) { + write16(ir_base + i, ir->pcidev[i]); + + /* If the entry is more than just 0, print it out */ + if(ir->pcidev[i]) { + printk(BIOS_SPEW, " %d: ", i); + for (j = 0; j < 4; j++) { + pirq = (ir->pcidev[i] >> (j * 4)) & 0xF; + printk(BIOS_SPEW, "\t%-4c (%d)", 'A' + pirq, ir->pic[pirq]); + } + printk(BIOS_SPEW, "\n"); + } + } + + /* Route SCI to IRQ9 */ + write32(actl, (read32(actl) & ~SCIS_MASK) | SCIS_IRQ9); + printk(BIOS_SPEW, "Finished writing IRQ assignments\n"); + + /* Write IRQ assignments to PCI config space */ + write_pci_config_irqs(); +} + +static void soc_power_options(device_t dev) +{ + u8 reg8; + u16 pmbase; + u32 reg32; + + /* Get the chip configuration */ + config_t *config = dev->chip_info; + + int nmi_option; + + /* Set up NMI on errors. */ + reg8 = inb(0x61); + reg8 &= 0x0f; /* Higher Nibble must be 0 */ + reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */ + // reg8 &= ~(1 << 2); /* PCI SERR# Enable */ + reg8 |= (1 << 2); /* PCI SERR# Disable for now */ + outb(reg8, 0x61); + + reg8 = inb(0x70); + nmi_option = NMI_OFF; + get_option(&nmi_option, "nmi"); + if (nmi_option) { + printk(BIOS_INFO, "NMI sources enabled.\n"); + reg8 &= ~(1 << 7); /* Set NMI. */ + } else { + printk(BIOS_INFO, "NMI sources disabled.\n"); + reg8 |= ( 1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */ + } + outb(reg8, 0x70); + + pmbase = pci_read_config16(dev, ABASE) & ~0xf; + + outl(config->gpe0_en, pmbase + GPE0_EN); + outw(config->alt_gp_smi_en, pmbase + ALT_GP_SMI_EN); + + /* Set up power management block and determine sleep mode */ + reg32 = inl(pmbase + PM1_CNT); // PM1_CNT + reg32 &= ~(7 << 10); // SLP_TYP + reg32 |= (1 << 0); // SCI_EN + outl(reg32, pmbase + PM1_CNT); +} + +/* Disable the HPET, Clear the counter, and re-enable it. */ +static void enable_hpet(void) +{ + write8((u8 *)HPET_GCFG, 0x00); + write32((u32 *)HPET_MCV, 0x00000000); + write32((u32 *)(HPET_MCV + 0x04), 0x00000000); + write8((u8 *)HPET_GCFG, 0x01); +} + +static void soc_disable_smm_only_flashing(struct device *dev) +{ + u8 reg8; + + printk(BIOS_SPEW, "Enabling BIOS updates outside of SMM... "); + reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */ + reg8 &= ~(1 << 5); + pci_write_config8(dev, 0xdc, reg8); +} + +static void lpc_init(struct device *dev) +{ + printk(BIOS_DEBUG, "soc: lpc_init\n"); + + /* Set the value for PCI command register. */ + pci_write_config16(dev, PCI_COMMAND, 0x000f); + + /* IO APIC initialization. */ + soc_enable_apic(dev); + + soc_enable_serial_irqs(dev); + + /* Setup the PIRQ. */ + soc_pirq_init(dev); + + /* Setup power options. */ + soc_power_options(dev); + + /* Initialize power management */ + switch (soc_silicon_type()) { + case SOC_TYPE_RANGELEY: + break; + default: + printk(BIOS_DEBUG, "Unknown Chipset: 0x%04x\n", dev->device); + } + + /* Initialize ISA DMA. */ + isa_dma_init(); + + /* Initialize the High Precision Event Timers, if present. */ + enable_hpet(); + + setup_i8259(); + + /* Interrupt 9 should be level triggered (SCI) */ + i8259_configure_irq_trigger(9, 1); + + soc_disable_smm_only_flashing(dev); +} + +static void soc_lpc_read_resources(device_t dev) +{ + struct resource *res; + config_t *config = dev->chip_info; + u8 io_index = 0; + + /* Get the normal PCI resources of this device. */ + pci_dev_read_resources(dev); + + /* Add an extra subtractive resource for both memory and I/O. */ + res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0)); + res->base = 0; + res->size = 0x1000; + res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | + IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + + res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0)); + res->base = 0xff800000; + res->size = 0x00800000; /* 8 MB for flash */ + res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | + IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + + res = new_resource(dev, 3); /* IOAPIC */ + res->base = IO_APIC_ADDR; + res->size = 0x00001000; + res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + + /* Set SOC IO decode ranges if required.*/ + if ((config->gen1_dec & 0xFFFC) > 0x1000) { + res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0)); + res->base = config->gen1_dec & 0xFFFC; + res->size = (config->gen1_dec >> 16) & 0xFC; + res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | + IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + } + + if ((config->gen2_dec & 0xFFFC) > 0x1000) { + res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0)); + res->base = config->gen2_dec & 0xFFFC; + res->size = (config->gen2_dec >> 16) & 0xFC; + res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | + IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + } + + if ((config->gen3_dec & 0xFFFC) > 0x1000) { + res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0)); + res->base = config->gen3_dec & 0xFFFC; + res->size = (config->gen3_dec >> 16) & 0xFC; + res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | + IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + } + + if ((config->gen4_dec & 0xFFFC) > 0x1000) { + res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0)); + res->base = config->gen4_dec & 0xFFFC; + res->size = (config->gen4_dec >> 16) & 0xFC; + res->flags = IORESOURCE_IO| IORESOURCE_SUBTRACTIVE | + IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + } +} + +static void soc_lpc_enable_resources(device_t dev) +{ + return pci_dev_enable_resources(dev); +} + +static void soc_lpc_enable(device_t dev) +{ + soc_enable(dev); +} + +static void 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)); + } +} + +static void southbridge_inject_dsdt(device_t dev) +{ + global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof (*gnvs)); + + if (gnvs) { + memset(gnvs, 0, sizeof(*gnvs)); + acpi_create_gnvs(gnvs); + acpi_save_gnvs((unsigned long)gnvs); +#if CONFIG_HAVE_SMI_HANDLER + /* And tell SMI about it */ + smm_setup_structures(gnvs, NULL, NULL); +#endif + + /* Add it to DSDT. */ + acpigen_write_scope("\\"); + acpigen_write_name_dword("NVSA", (u32) gnvs); + acpigen_pop_len(); + } +} + +static struct pci_operations pci_ops = { + .set_subsystem = set_subsystem, +}; + +static struct device_operations device_ops = { + .read_resources = soc_lpc_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = soc_lpc_enable_resources, + .init = lpc_init, + .write_acpi_tables = acpi_write_hpet, + .acpi_inject_dsdt_generator = southbridge_inject_dsdt, + .enable = soc_lpc_enable, + .scan_bus = scan_lpc_bus, + .ops_pci = &pci_ops, +}; + +/* IDs for LPC device of Intel 89xx Series Chipset */ +static const unsigned short pci_device_ids[] = { 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, + 0 }; + +static const struct pci_driver soc_lpc __pci_driver = { + .ops = &device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; diff --git a/src/southbridge/intel/fsp_rangeley/nvs.h b/src/southbridge/intel/fsp_rangeley/nvs.h new file mode 100644 index 0000000000..cabbdea941 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/nvs.h @@ -0,0 +1,156 @@ +/* + * 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. + */ + +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) */ + /* Thermal policy */ + u8 tlvl; /* 0x11 - Throttle Level Limit */ + u8 flvl; /* 0x12 - Current FAN Level */ + u8 tcrt; /* 0x13 - Critical Threshold */ + u8 tpsv; /* 0x14 - Passive Threshold */ + u8 tmax; /* 0x15 - CPU Tj_max */ + u8 f0of; /* 0x16 - FAN 0 OFF Threshold */ + u8 f0on; /* 0x17 - FAN 0 ON Threshold */ + u8 f0pw; /* 0x18 - FAN 0 PWM value */ + u8 f1of; /* 0x19 - FAN 1 OFF Threshold */ + u8 f1on; /* 0x1a - FAN 1 ON Threshold */ + u8 f1pw; /* 0x1b - FAN 1 PWM value */ + u8 f2of; /* 0x1c - FAN 2 OFF Threshold */ + u8 f2on; /* 0x1d - FAN 2 ON Threshold */ + u8 f2pw; /* 0x1e - FAN 2 PWM value */ + u8 f3of; /* 0x1f - FAN 3 OFF Threshold */ + u8 f3on; /* 0x20 - FAN 3 ON Threshold */ + u8 f3pw; /* 0x21 - FAN 3 PWM value */ + u8 f4of; /* 0x22 - FAN 4 OFF Threshold */ + u8 f4on; /* 0x23 - FAN 4 ON Threshold */ + u8 f4pw; /* 0x24 - FAN 4 PWM value */ + u8 tmps; /* 0x25 - Temperature Sensor ID */ + u8 rsvd3[2]; + /* Processor Identification */ + u8 apic; /* 0x28 - APIC enabled */ + u8 mpen; /* 0x29 - MP capable/enabled */ + u8 pcp0; /* 0x2a - PDC CPU/CORE 0 */ + u8 pcp1; /* 0x2b - PDC CPU/CORE 1 */ + u8 ppcm; /* 0x2c - Max. PPC state */ + u8 pcnt; /* 0x2d - Processor Count */ + u8 rsvd4[4]; + /* Super I/O & CMOS config */ + u8 natp; /* 0x32 - SIO type */ + u8 s5u0; /* 0x33 - Enable USB0 in S5 */ + u8 s5u1; /* 0x34 - Enable USB1 in S5 */ + u8 s3u0; /* 0x35 - Enable USB0 in S3 */ + u8 s3u1; /* 0x36 - Enable USB1 in S3 */ + u8 s33g; /* 0x37 - Enable S3 in 3G */ + u32 obsolete_cmem; /* 0x38 - CBMEM TOC */ + /* Integrated Graphics Device */ + u8 igds; /* 0x3c - IGD state */ + u8 tlst; /* 0x3d - Display Toggle List Pointer */ + u8 cadl; /* 0x3e - currently attached devices */ + u8 padl; /* 0x3f - previously attached devices */ + u16 cste; /* 0x40 - current display state */ + u16 nste; /* 0x42 - next display state */ + u16 sste; /* 0x44 - set display state */ + u8 ndid; /* 0x46 - number of device ids */ + u32 did[5]; /* 0x47 - 5b device id 1..5 */ + u8 rsvd5[0x9]; + /* Backlight Control */ + u8 blcs; /* 0x64 - Backlight Control possible */ + u8 brtl; + u8 odds; + u8 rsvd6[0x7]; + /* Ambient Light Sensors*/ + u8 alse; /* 0x6e - ALS enable */ + u8 alaf; + u8 llow; + u8 lhih; + u8 rsvd7[0x6]; + /* Extended Mobile Access */ + u8 emae; /* 0x78 - EMA enable */ + u16 emap; /* 0x79 - EMA pointer */ + u16 emal; /* 0x7a - EMA Length */ + u8 rsvd8[0x5]; + /* MEF */ + u8 mefe; /* 0x82 - MEF enable */ + u8 rsvd9[0x9]; + /* TPM support */ + u8 tpmp; /* 0x8c - TPM */ + u8 tpme; + u8 rsvd10[8]; + /* SATA */ + u8 gtf0[7]; /* 0x96 - GTF task file buffer for port 0 */ + u8 gtf1[7]; + u8 gtf2[7]; + u8 idem; + u8 idet; + u8 rsvd11[7]; + /* IGD OpRegion (not implemented yet) */ + u32 aslb; /* 0xb4 - IGD OpRegion Base Address */ + u8 ibtt; /* 0xb8 - IGD boot type */ + u8 ipat; /* 0xb9 - IGD panel type */ + u8 itvf; /* 0xba - IGD TV format */ + u8 itvm; /* 0xbb - IGD TV minor format */ + u8 ipsc; /* 0xbc - IGD Panel Scaling */ + u8 iblc; /* 0xbd - IGD BLC configuration */ + u8 ibia; /* 0xbe - IGD BIA configuration */ + u8 issc; /* 0xbf - IGD SSC configuration */ + u8 i409; /* 0xc0 - IGD 0409 modified settings */ + u8 i509; /* 0xc1 - IGD 0509 modified settings */ + u8 i609; /* 0xc2 - IGD 0609 modified settings */ + u8 i709; /* 0xc3 - IGD 0709 modified settings */ + u8 idmm; /* 0xc4 - IGD Power Conservation */ + u8 idms; /* 0xc5 - IGD DVMT memory size */ + u8 if1e; /* 0xc6 - IGD Function 1 Enable */ + u8 hvco; /* 0xc7 - IGD HPLL VCO */ + u32 nxd[8]; /* 0xc8 - IGD next state DIDx for _DGS */ + u8 isci; /* 0xe8 - IGD SMI/SCI mode (0: SCI) */ + u8 pavp; /* 0xe9 - IGD PAVP data */ + u8 rsvd12; /* 0xea - rsvd */ + u8 oscc; /* 0xeb - PCIe OSC control */ + u8 npce; /* 0xec - native pcie support */ + u8 plfl; /* 0xed - platform flavor */ + u8 brev; /* 0xee - board revision */ + u8 dpbm; /* 0xef - digital port b mode */ + u8 dpcm; /* 0xf0 - digital port c mode */ + u8 dpdm; /* 0xf1 - digital port c mode */ + u8 alfp; /* 0xf2 - active lfp */ + u8 imon; /* 0xf3 - current graphics turbo imon value */ + u8 mmio; /* 0xf4 - 64bit mmio support */ + u8 rsvd13[11]; /* 0xf5 - rsvd */ + +} __attribute__((packed)) global_nvs_t; + +void acpi_create_gnvs(global_nvs_t *gnvs); +#ifdef __SMM__ +/* Used in SMM to find the ACPI GNVS address */ +global_nvs_t *smm_get_gnvs(void); +#endif diff --git a/src/southbridge/intel/fsp_rangeley/pci_devs.h b/src/southbridge/intel/fsp_rangeley/pci_devs.h new file mode 100644 index 0000000000..03b0193f5f --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/pci_devs.h @@ -0,0 +1,137 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#ifndef _RANGELEY_PCI_DEVS_H_ +#define _RANGELEY_PCI_DEVS_H_ + +#define BUS0 0 + +/* All these devices live on bus 0 with the associated device and function */ +#define DEV_FUNC(x,y) ((x<<3) | y) + +/* Host Bridge */ +#define SOC_DEV 0x0 +#define SOC_FUNC 0 +# define SOC_DEVID 0x1f08 +# define SOC_DEV_FUNC DEV_FUNC(SOC_DEV,SOC_FUNC) + +/* PCIE Port 1 */ +#define PCIE_PORT1_DEV 0x1 +#define PCIE_PORT1_FUNC 0 +# define PCIE_PORT1_DEVID 0x1f10 +# define PCIE_PORT1_DEV_FUNC DEV_FUNC(PCIE_PORT1_DEV,PCIE_PORT1_FUNC) + +/* PCIE Port 2 */ +#define PCIE_PORT2_DEV 0x2 +#define PCIE_PORT2_FUNC 0 +# define PCIE_PORT2_DEVID 0x1f11 +# define PCIE_PORT2_DEV_FUNC DEV_FUNC(PCIE_PORT2_DEV,PCIE_PORT2_FUNC) + +/* PCIE Port 3 */ +#define PCIE_PORT3_DEV 0x3 +#define PCIE_PORT3_FUNC 0 +# define PCIE_PORT3_DEVID 0x1f12 +# define PCIE_PORT3_DEV_FUNC DEV_FUNC(PCIE_PORT3_DEV,PCIE_PORT3_FUNC) + +/* PCIE Port 4 */ +#define PCIE_PORT4_DEV 0x4 +#define PCIE_PORT4_FUNC 0 +# define PCIE_PORT4_DEVID 0x1f13 +# define PCIE_PORT4_DEV_FUNC DEV_FUNC(PCIE_PORT4_DEV,PCIE_PORT4_FUNC) + +/* Host Bridge, Fabric, and RAS Registers */ +#define HOST_BRIDGE_DEV 0xe +#define HOST_BRIDGE_FUNC 0 +# define HOST_BRIDGE_DEVID 0x1f14 +# define HOST_BRIDGE_DEV_FUNC DEV_FUNC(HOST_BRIDGE_DEV,HOST_BRIDGE_FUNC) + +/* Root Complex Event Collector (RCEC) */ +#define RCEC_DEV 0xf +#define RCEC_FUNC 0 +# define RCEC_DEVID 0x1f16 +# define RCEC_DEV_FUNC DEV_FUNC(RCEC_DEV,RCEC_FUNC) + +/* SMBus 2.0 1 */ +#define SMBUS1_DEV 0x13 +#define SMBUS1_FUNC 0 +# define SMBUS1_DEVID 0x1f15 +# define SMBUS1_DEV_FUNC DEV_FUNC(SMBUS1_DEV,SMBUS1_FUNC) + +/* Gigabit Ethernet (GbE) */ +#define GBE_DEV 0x14 +#define GBE_DEVID 0x1f41 +#define GBE1_DEV GBE_DEV +#define GBE1_FUNC 0 +# define GBE1_DEVID GBE_DEVID +# define GBE1_DEV_FUNC DEV_FUNC(GBE1_DEV,GBE1_FUNC) +#define GBE2_DEV GBE_DEV +#define GBE2_FUNC 1 +# define GBE2_DEVID GBE_DEVID +# define GBE2_DEV_FUNC DEV_FUNC(GBE2_DEV,GBE2_FUNC) +#define GBE3_DEV GBE_DEV +#define GBE3_FUNC 2 +# define GBE3_DEVID GBE_DEVID +# define GBE3_DEV_FUNC DEV_FUNC(GBE3_DEV,GBE3_FUNC) +#define GBE4_DEV GBE_DEV +#define GBE4_FUNC 3 +# define GBE4_DEVID GBE_DEVID +# define GBE4_DEV_FUNC DEV_FUNC(GBE4_DEV,GBE4_FUNC) + +/* USB 2.0 */ +#define USB2_DEV 0x16 +#define USB2_FUNC 0 +# define USB2_DEVID 0x1f2c +# define USB2_DEV_FUNC DEV_FUNC(USB2_DEV,USB2_FUNC) + +/* SATA Gen 2 */ +#define SATA2_DEV 0x17 +#define SATA2_FUNC 0 +# define SATA2_DEVID 0x1f22 +# define SATA2_DEV_FUNC DEV_FUNC(SATA2_DEV,SATA2_FUNC) + +/* SATA Gen 3 */ +#define SATA3_DEV 0x18 +#define SATA3_FUNC 0 +# define SATA3_DEVID 0x1f32 +# define SATA3_DEV_FUNC DEV_FUNC(SATA3_DEV,SATA3_FUNC) + +/* Platform Control Unit (PCU) */ +#define PCU_DEV 0x1f + +/* Low Pin Count (LPC/ISA) */ +#define LPC_DEV PCU_DEV +#define LPC_FUNC 0 +# define LPC_DEVID 0x1f38 +# define LPC_DEV_FUNC DEV_FUNC(LPC_DEV,LPC_FUNC) +# define LPC_BDF PCI_DEV(BUS0, LPC_DEV, LPC_FUNC) + +/* SMBus 2.0 0 */ +#define SMBUS0_DEV PCU_DEV +#define SMBUS0_FUNC 3 +# define SMBUS0_DEVID 0x1f3c +# define SMBUS0_DEV_FUNC DEV_FUNC(SMBUS0_DEV,SMBUS0_FUNC) + +/* Intel QuickAssist Integrated Accelerator (IQIA) */ +#define IQAT_DEV 0xb +#define IQAT_FUNC 0 +# define IQAT_DEVID 0x1f18 +# define IQAT_DEV_FUNC DEV_FUNC(IQAT_DEV,IQAT_FUNC) + +#endif /* _RANGELEY_PCI_DEVS_H_ */ diff --git a/src/southbridge/intel/fsp_rangeley/reset.c b/src/southbridge/intel/fsp_rangeley/reset.c new file mode 100644 index 0000000000..8ef890ab56 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/reset.c @@ -0,0 +1,34 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2013 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#include +#include + +void soft_reset(void) +{ + hard_reset(); +} + +void hard_reset(void) +{ + outb(0x02, 0xcf9); + outb(0x06, 0xcf9); +} diff --git a/src/southbridge/intel/fsp_rangeley/romstage.c b/src/southbridge/intel/fsp_rangeley/romstage.c new file mode 100644 index 0000000000..bc58b487c0 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/romstage.c @@ -0,0 +1,143 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "northbridge/intel/fsp_rangeley/northbridge.h" +#include "southbridge/intel/fsp_rangeley/soc.h" +#include "southbridge/intel/fsp_rangeley/gpio.h" +#include "southbridge/intel/fsp_rangeley/romstage.h" +#include +#include +#include +#include "gpio.h" + +void main(FSP_INFO_HEADER *fsp_info_header) +{ + uint32_t fd_mask = 0; + uint32_t *func_dis = (uint32_t *)(DEFAULT_PBASE + PBASE_FUNC_DIS); + + /* + * Do not use the Serial Console before it is setup. + * This causes the I/O to clog and a side effect is + * that the reset button stops functioning. So + * instead just use outb so it doesn't output to the + * console when CONFIG_CONSOLE_POST. + */ + outb(0x40, 0x80); + + timestamp_init(get_initial_timestamp()); + timestamp_add_now(TS_START_ROMSTAGE); + + /* Rangeley UART POR state is enabled */ + console_init(); + post_code(0x41); + + /* Enable GPIOs BAR */ + pci_write_config32(SOC_LPC_DEV, GBASE, DEFAULT_GPIOBASE|0x02); + + early_mainboard_romstage_entry(); + + post_code(0x42); + rangeley_sb_early_initialization(); + + post_code(0x46); + /* Program any required function disables */ + get_func_disables(&fd_mask); + + if (fd_mask != 0) { + write32(func_dis, read32(func_dis) | fd_mask); + /* Ensure posted write hits. */ + read32(func_dis); + } + + timestamp_add_now(TS_BEFORE_INITRAM); + + /* + * Call early init to initialize memory and chipset. This function returns + * to the romstage_main_continue function with a pointer to the HOB + * structure. + */ + post_code(0x47); + printk(BIOS_DEBUG, "Starting the Intel FSP (early_init)\n"); + fsp_early_init(fsp_info_header); + die("Uh Oh! fsp_early_init should not return here.\n"); +} + +/******************************************************************************* + * The FSP early_init function returns to this function. + * Memory is setup and the stack is set by the FSP. + */ +void romstage_main_continue(EFI_STATUS status, void *hob_list_ptr) { + int cbmem_was_initted; + void *cbmem_hob_ptr; + + timestamp_add_now(TS_AFTER_INITRAM); + + post_code(0x48); + printk(BIOS_DEBUG, "%s status: %x hob_list_ptr: %x\n", + __func__, (u32) status, (u32) hob_list_ptr); + +#if IS_ENABLED(CONFIG_USBDEBUG_IN_ROMSTAGE) + /* FSP reconfigures USB, so reinit it to have debug */ + usbdebug_init(); +#endif /* IS_ENABLED(CONFIG_USBDEBUG_IN_ROMSTAGE) */ + + printk(BIOS_DEBUG, "FSP Status: 0x%0x\n", (u32)status); + + post_code(0x4b); + late_mainboard_romstage_entry(); + + post_code(0x4c); + + /* Decode E0000 and F0000 segment to DRAM */ + sideband_write(B_UNIT, BMISC, sideband_read(B_UNIT, BMISC) | (1 << 1) | (1 << 0)); + + quick_ram_check(); + post_code(0x4d); + + cbmem_was_initted = !cbmem_recovery(0); + + /* Save the HOB pointer in CBMEM to be used in ramstage*/ + cbmem_hob_ptr = cbmem_add (CBMEM_ID_HOB_POINTER, sizeof(*hob_list_ptr)); + *(u32*)cbmem_hob_ptr = (u32)hob_list_ptr; + post_code(0x4e); + + post_code(0x4f); + + /* Load the ramstage. */ + copy_and_run(); + while (1); +} + +uint64_t get_initial_timestamp(void) +{ + return 0; +} diff --git a/src/southbridge/intel/fsp_rangeley/romstage.h b/src/southbridge/intel/fsp_rangeley/romstage.h new file mode 100644 index 0000000000..f3b7242d06 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/romstage.h @@ -0,0 +1,39 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * Copyright (C) 2014 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#ifndef _RANGELEY_ROMSTAGE_H_ +#define _RANGELEY_ROMSTAGE_H_ + +#if !defined(__PRE_RAM__) +#error "Don't include romstage.h from a ramstage compilation unit!" +#endif + +#include +#include +#include + +void main(FSP_INFO_HEADER *fsp_info_header); +void early_mainboard_romstage_entry(void); +void late_mainboard_romstage_entry(void); +void get_func_disables(uint32_t *mask); + +void romstage_main_continue(EFI_STATUS status, void *hob_list_ptr); + +#endif /* _RANGELEY_ROMSTAGE_H_ */ diff --git a/src/southbridge/intel/fsp_rangeley/sata.c b/src/southbridge/intel/fsp_rangeley/sata.c new file mode 100644 index 0000000000..f1398c95c0 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/sata.c @@ -0,0 +1,135 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2013 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#include +#include +#include +#include +#include +#include "soc.h" + +typedef struct southbridge_intel_fsp_rangeley_config config_t; + +static void sata_init(struct device *dev) +{ + u32 reg32; + u16 reg16; + u32 *abar; + + /* Get the chip configuration */ + config_t *config = dev->chip_info; + + printk(BIOS_DEBUG, "SATA: Initializing...\n"); + + if (config == NULL) { + printk(BIOS_ERR, "SATA: ERROR: Device not in devicetree.cb!\n"); + return; + } + + /* SATA configuration is handled by the FSP */ + + /* Enable BARs */ + pci_write_config16(dev, PCI_COMMAND, 0x0007); + + if (config->ide_legacy_combined) { + printk(BIOS_DEBUG, "SATA: Controller in combined mode.\n"); + + /* Set the controller mode */ + reg16 = pci_read_config16(dev, SATA_MAP); + reg16 &= ~(3 << 6); + pci_write_config16(dev, SATA_MAP, reg16); + + /* No AHCI: clear AHCI base */ + pci_write_config32(dev, 0x24, 0x00000000); + + /* And without AHCI BAR no memory decoding */ + reg16 = pci_read_config16(dev, PCI_COMMAND); + reg16 &= ~PCI_COMMAND_MEMORY; + pci_write_config16(dev, PCI_COMMAND, reg16); + } else if(config->sata_ahci) { + printk(BIOS_DEBUG, "SATA: Controller in AHCI mode.\n"); + + /* Set the controller mode */ + reg16 = pci_read_config16(dev, SATA_MAP); + reg16 &= ~(3 << 6); + reg16 |= (1 << 6); + pci_write_config16(dev, SATA_MAP, reg16); + + /* Initialize AHCI memory-mapped space */ + abar = (u32 *)pci_read_config32(dev, PCI_BASE_ADDRESS_5); + printk(BIOS_DEBUG, "ABAR: %p\n", abar); + + /* Enable AHCI Mode */ + reg32 = read32(abar + 0x01); + reg32 |= (1 << 31); + write32(abar + 0x01, reg32); + } else { + printk(BIOS_DEBUG, "SATA: Controller in plain mode.\n"); + } + + /* Spin up the drives as early as possible via the Port Enable */ + reg16 = pci_read_config16(dev, SATA_PSC); + reg16 &= ~0x3f; + pci_write_config16(dev, SATA_PSC, reg16); + reg16 = pci_read_config16(dev, SATA_PSC); + reg16 |= 0x3f; + pci_write_config16(dev, SATA_PSC, reg16); + +} + +static void sata_enable(device_t dev) +{ +} + +static void sata_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)); + } +} + +static struct pci_operations sata_pci_ops = { + .set_subsystem = sata_set_subsystem, +}; + +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 = 0, + .ops_pci = &sata_pci_ops, +}; + +static const unsigned short pci_device_ids[] = { 0x1f20, 0x1f21, 0x1f22, 0x1f23, + 0x1f30, 0x1f31, 0x1f32, 0x1f33, + 0 }; + +static const struct pci_driver soc_sata __pci_driver = { + .ops = &sata_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; diff --git a/src/southbridge/intel/fsp_rangeley/smbus.c b/src/southbridge/intel/fsp_rangeley/smbus.c new file mode 100644 index 0000000000..7864b1e157 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/smbus.c @@ -0,0 +1,99 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2013 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "soc.h" +#include "smbus.h" + +static int lsmbus_read_byte(device_t dev, u8 address) +{ + u16 device; + struct resource *res; + struct bus *pbus; + + device = dev->path.i2c.device; + pbus = get_pbus_smbus(dev); + res = find_resource(pbus->dev, 0x20); + + return do_smbus_read_byte(res->base, device, address); +} + +static struct smbus_bus_operations lops_smbus_bus = { + .read_byte = lsmbus_read_byte, +}; + +static void smbus_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)); + } +} + +static struct pci_operations smbus_pci_ops = { + .set_subsystem = smbus_set_subsystem, +}; + +static void rangeley_smbus_read_resources(device_t dev) +{ + struct resource *res; + + /* + * The SMBus has two BARS. + * BAR0 - MMIO, not used at boot time + * BAR4 - IO, Used to talk to the SMBUS during boot, so we maintain + * the default setting in the resource allocator. + */ + + res = pci_get_resource(dev, PCI_BASE_ADDRESS_0); + + res = new_resource(dev, PCI_BASE_ADDRESS_4); + res->base = SMBUS_IO_BASE; + res->size = 32; + res->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_RESERVE | + IORESOURCE_STORED | IORESOURCE_ASSIGNED; + +} + +static struct device_operations smbus_ops = { + .read_resources = rangeley_smbus_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = 0, + .scan_bus = scan_smbus, + .ops_smbus_bus = &lops_smbus_bus, + .ops_pci = &smbus_pci_ops, +}; + +static const struct pci_driver rangeley_smbus __pci_driver = { + .ops = &smbus_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x1F3C, +}; diff --git a/src/southbridge/intel/fsp_rangeley/smbus.h b/src/southbridge/intel/fsp_rangeley/smbus.h new file mode 100644 index 0000000000..6789e051e1 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/smbus.h @@ -0,0 +1,99 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2005 Yinghai Lu + * Copyright (C) 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. + */ + +#include +#include "soc.h" + +static void smbus_delay(void) +{ + inb(0x80); +} + +static int smbus_wait_until_ready(u16 smbus_base) +{ + unsigned loops = SMBUS_TIMEOUT; + unsigned char byte; + do { + smbus_delay(); + if (--loops == 0) + break; + byte = inb(smbus_base + SMBHSTSTAT); + } while (byte & 1); + return loops ? 0 : -1; +} + +static int smbus_wait_until_done(u16 smbus_base) +{ + unsigned loops = SMBUS_TIMEOUT; + unsigned char byte; + do { + smbus_delay(); + if (--loops == 0) + break; + byte = inb(smbus_base + SMBHSTSTAT); + } while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0); + return loops ? 0 : -1; +} + +static int do_smbus_read_byte(unsigned smbus_base, unsigned device, unsigned address) +{ + unsigned char global_status_register; + unsigned char byte; + + if (smbus_wait_until_ready(smbus_base) < 0) { + return SMBUS_WAIT_UNTIL_READY_TIMEOUT; + } + /* Setup transaction */ + /* Disable interrupts */ + outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL); + /* Set the device I'm talking too */ + outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD); + /* Set the command/address... */ + outb(address & 0xff, smbus_base + SMBHSTCMD); + /* Set up for a byte data read */ + outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2), + (smbus_base + SMBHSTCTL)); + /* Clear any lingering errors, so the transaction will run */ + outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT); + + /* Clear the data byte... */ + outb(0, smbus_base + SMBHSTDAT0); + + /* Start the command */ + outb((inb(smbus_base + SMBHSTCTL) | 0x40), + smbus_base + SMBHSTCTL); + + /* Poll for transaction completion */ + if (smbus_wait_until_done(smbus_base) < 0) { + return SMBUS_WAIT_UNTIL_DONE_TIMEOUT; + } + + global_status_register = inb(smbus_base + SMBHSTSTAT); + + /* Ignore the "In Use" status... */ + global_status_register &= ~(3 << 5); + + /* Read results of transaction */ + byte = inb(smbus_base + SMBHSTDAT0); + if (global_status_register != (1 << 1)) { + return SMBUS_ERROR; + } + return byte; +} diff --git a/src/southbridge/intel/fsp_rangeley/soc.c b/src/southbridge/intel/fsp_rangeley/soc.c new file mode 100644 index 0000000000..bc6a4525aa --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/soc.c @@ -0,0 +1,99 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2012 The Chromium OS Authors. All rights reserved. + * Copyright (C) 2013 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#include +#include +#include +#include +#include "soc.h" + +static int soc_revision_id = -1; +static int soc_type = -1; + +int soc_silicon_revision(void) +{ + if (soc_revision_id < 0) + soc_revision_id = pci_read_config8( + dev_find_slot(0, PCI_DEVFN(0x1f, 0)), + PCI_REVISION_ID); + return soc_revision_id; +} + +int soc_silicon_type(void) +{ + if (soc_type < 0) + soc_type = pci_read_config8( + dev_find_slot(0, PCI_DEVFN(0x1f, 0)), + PCI_DEVICE_ID + 1); + return soc_type; +} + +int soc_silicon_supported(int type, int rev) +{ + int cur_type = soc_silicon_type(); + int cur_rev = soc_silicon_revision(); + + switch (type) { + case SOC_TYPE_RANGELEY: + if (cur_type == SOC_TYPE_RANGELEY && cur_rev >= rev) + return 1; + } + + return 0; +} + +/* Set bit in Function Disable register to hide this device */ +static void soc_hide_devfn(unsigned devfn) +{ +/* TODO Function Disable. */ +} + + + + +void soc_enable(device_t dev) +{ + u32 reg32; + + if (!dev->enabled) { + printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev)); + + /* Ensure memory, IO, and bus master are all disabled */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 &= ~(PCI_COMMAND_MASTER | + PCI_COMMAND_MEMORY | PCI_COMMAND_IO); + pci_write_config32(dev, PCI_COMMAND, reg32); + + /* Hide this device if possible */ + soc_hide_devfn(dev->path.pci.devfn); + } else { + /* Enable SERR */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 |= PCI_COMMAND_SERR; + pci_write_config32(dev, PCI_COMMAND, reg32); + } +} + +struct chip_operations southbridge_intel_fsp_rangeley_ops = { + CHIP_NAME("Intel Rangeley Southbridge") + .enable_dev = soc_enable, +}; diff --git a/src/southbridge/intel/fsp_rangeley/soc.h b/src/southbridge/intel/fsp_rangeley/soc.h new file mode 100644 index 0000000000..61ec266c42 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/soc.h @@ -0,0 +1,452 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2012 The Chromium OS Authors. All rights reserved. + * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#ifndef SOUTHBRIDGE_INTEL_RANGELEY_SOC_H +#define SOUTHBRIDGE_INTEL_RANGELEY_SOC_H + +/* SOC types */ +#define SOC_TYPE_RANGELEY 0x1F + +/* + * It does not matter where we put the SMBus I/O base, as long as we + * keep it consistent and don't interfere with other devices. Stage2 + * will relocate this anyways. + * Our solution is to have SMB initialization move the I/O to SMBUS_IO_BASE + * again. But handling static BARs is a generic problem that should be + * solved in the device allocator. + */ + +/* Southbridge internal device IO BARs (Set to match FSP settings) */ +#define SMBUS_IO_BASE 0xefa0 +#define SMBUS_SLAVE_ADDR 0x24 +#define DEFAULT_GPIOBASE 0x0500 +#define DEFAULT_ABASE 0x0400 + +/* Southbridge internal device MEM BARs (Set to match FSP settings) */ +#define DEFAULT_IBASE 0xfed08000 +#define DEFAULT_PBASE 0xfed03000 +#ifndef __ACPI__ +#define DEFAULT_RCBA ((u8 *)0xfed1c000) +#else +#define DEFAULT_RCBA 0xfed1c000 +#endif + +#ifndef __ACPI__ +#define DEBUG_PERIODIC_SMIS 0 + +#if defined (__SMM__) && !defined(__ASSEMBLER__) +void intel_soc_finalize_smm(void); +#endif + +#if !defined(__ASSEMBLER__) && !defined(__ROMCC__) +#if !defined(__PRE_RAM__) && !defined(__SMM__) +#include "chip.h" +int soc_silicon_revision(void); +int soc_silicon_type(void); +int soc_silicon_supported(int type, int rev); +void soc_enable(device_t dev); + +#include +void acpi_fill_in_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt); + +#if CONFIG_ELOG +void soc_log_state(void); +#endif +#else +void enable_smbus(void); +void enable_usb_bar(void); +int smbus_read_byte(unsigned device, unsigned address); +int early_spi_read(u32 offset, u32 size, u8 *buffer); +void rangeley_sb_early_initialization(void); +#endif +#endif + +#define MAINBOARD_POWER_OFF 0 +#define MAINBOARD_POWER_ON 1 +#define MAINBOARD_POWER_KEEP 2 + +#ifndef CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL +#define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON +#endif + +#define SOC_EHCI1_DEV PCI_DEV(0, 0x1d, 0) +#define PCIE_DEV_SLOT0 1 +#define PCIE_DEV_SLOT1 2 +#define PCIE_DEV_SLOT2 3 +#define PCIE_DEV_SLOT3 4 + +/* PCI Configuration Space (D31:F0): LPC */ +#define SOC_LPC_DEV PCI_DEV(0, 0x1f, 0) +#define SOC_LPC_DEVFN 0, PCI_DEVFN(0x1f,0) + + +/* Southbridge IO BARs */ +#define ABASE 0x40 /* IO BAR */ +#define PBASE 0x44 /* MEM BAR */ +#define GBASE 0x48 /* IO BAR */ +#define IOBASE 0x4C /* MEM BAR */ +#define IBASE 0x50 /* MEM BAR */ +#define SBASE 0x54 /* MEM BAR */ +#define MPBASE 0x58 /* MEM BAR */ +#define SET_BAR_ENABLE 0x02 + +/* Rangeley ILB defines */ +#define ILB_ACTL 0 +#define ILB_PIRQA_ROUT 0x8 +#define ILB_PIRQB_ROUT 0x9 +#define ILB_PIRQC_ROUT 0xA +#define ILB_PIRQD_ROUT 0xB +#define ILB_PIRQE_ROUT 0xC +#define ILB_PIRQF_ROUT 0xD +#define ILB_PIRQG_ROUT 0xE +#define ILB_PIRQH_ROUT 0xF +#define ILB_SERIRQ_CNTL 0x10 +#define ILB_IR00 0x20 +#define ILB_IR01 0x22 +#define ILB_IR02 0x24 +#define ILB_IR03 0x26 +#define ILB_IR04 0x28 +#define ILB_IR05 0x2A +#define ILB_IR06 0x2C +#define ILB_IR07 0x2E +#define ILB_IR08 0x30 +#define ILB_IR09 0x32 +#define ILB_IR10 0x34 +#define ILB_IR11 0x36 +#define ILB_IR12 0x38 +#define ILB_IR13 0x3A +#define ILB_IR14 0x3C +#define ILB_IR15 0x3E +#define ILB_IR16 0x40 +#define ILB_IR17 0x42 +#define ILB_IR18 0x44 +#define ILB_IR19 0x46 +#define ILB_IR20 0x48 +#define ILB_IR21 0x4A +#define ILB_IR22 0x4C +#define ILB_IR23 0x4E +#define ILB_IR24 0x50 +#define ILB_IR25 0x52 +#define ILB_IR26 0x54 +#define ILB_IR27 0x56 +#define ILB_IR28 0x58 +#define ILB_IR29 0x5A +#define ILB_IR30 0x5C +#define ILB_IR31 0x5E +#define ILB_OIC 0x60 + +/* PCI Configuration Space (D31:F2/5) */ +#define SOC_SATA_DEV PCI_DEV(0, 0x17, 0) +#define SOC_SATA2_DEV PCI_DEV(0, 0x18, 0) + +#define SATA_SIRI 0xa0 /* SATA Indexed Register Index */ +#define SATA_SIRD 0xa4 /* SATA Indexed Register Data */ +#define SATA_SP 0xd0 /* Scratchpad */ +#define SATA_MAP 0x90 +#define SATA_PSC 0x92 + +/* SATA IOBP Registers */ +#define SATA_IOBP_SP0G3IR 0xea000151 +#define SATA_IOBP_SP1G3IR 0xea000051 + +/* PCI Configuration Space (D31:F3): SMBus */ +#define SOC_SMBUS_DEV PCI_DEV(0, 0x1f, 3) +#define SMB_BASE 0x20 +#define HOSTC 0x40 +#define SMB_RCV_SLVA 0x09 + +/* HOSTC bits */ +#define I2C_EN (1 << 2) +#define SMB_SMI_EN (1 << 1) +#define HST_EN (1 << 0) + +/* SMBus I/O bits. */ +#define SMBHSTSTAT 0x0 +#define SMBHSTCTL 0x2 +#define SMBHSTCMD 0x3 +#define SMBXMITADD 0x4 +#define SMBHSTDAT0 0x5 +#define SMBHSTDAT1 0x6 +#define SMBBLKDAT 0x7 +#define SMBTRNSADD 0x9 +#define SMBSLVDATA 0xa +#define SMLINK_PIN_CTL 0xe +#define SMBUS_PIN_CTL 0xf + +#define SMBUS_TIMEOUT (10 * 1000 * 100) + +/* Root Complex Register Block */ +#define RCBA 0xf0 +#define RCBA_ENABLE 0x01 + +#define RCBA8(x) *((volatile u8 *)(DEFAULT_RCBA + x)) +#define RCBA16(x) *((volatile u16 *)(DEFAULT_RCBA + x)) +#define RCBA32(x) *((volatile u32 *)(DEFAULT_RCBA + x)) + +#define RCBA_AND_OR(bits, x, and, or) \ + RCBA##bits(x) = ((RCBA##bits(x) & (and)) | (or)) +#define RCBA8_AND_OR(x, and, or) RCBA_AND_OR(8, x, and, or) +#define RCBA16_AND_OR(x, and, or) RCBA_AND_OR(16, x, and, or) +#define RCBA32_AND_OR(x, and, or) RCBA_AND_OR(32, x, and, or) +#define RCBA32_OR(x, or) RCBA_AND_OR(32, x, ~0UL, or) + +/* Root Port configuration space hide */ +#define RPFN_HIDE(port) (1 << (((port) * 4) + 3)) +/* Get the function number assigned to a Root Port */ +#define RPFN_FNGET(reg,port) (((reg) >> ((port) * 4)) & 7) +/* Set the function number for a Root Port */ +#define RPFN_FNSET(port,func) (((func) & 7) << ((port) * 4)) +/* Root Port function number mask */ +#define RPFN_FNMASK(port) (7 << ((port) * 4)) + + +#define NOINT 0 +#define INTA 1 +#define INTB 2 +#define INTC 3 +#define INTD 4 + +#define DIR_IDR 12 /* Interrupt D Pin Offset */ +#define DIR_ICR 8 /* Interrupt C Pin Offset */ +#define DIR_IBR 4 /* Interrupt B Pin Offset */ +#define DIR_IAR 0 /* Interrupt A Pin Offset */ + +#define PIRQA 0 +#define PIRQB 1 +#define PIRQC 2 +#define PIRQD 3 +#define PIRQE 4 +#define PIRQF 5 +#define PIRQG 6 +#define PIRQH 7 + +/* IO Buffer Programming */ +#define IOBPIRI 0x2330 +#define IOBPD 0x2334 +#define IOBPS 0x2338 +#define IOBPS_RW_BX ((1 << 9)|(1 << 10)) +#define IOBPS_WRITE_AX ((1 << 9)|(1 << 10)) +#define IOBPS_READ_AX ((1 << 8)|(1 << 9)|(1 << 10)) + + + +#define DIR_ROUTE(x,a,b,c,d) \ + RCBA32(x) = (((d) << DIR_IDR) | ((c) << DIR_ICR) | \ + ((b) << DIR_IBR) | ((a) << DIR_IAR)) + +/* PBASE Registers */ +#define PMC_CFG 0x08 +#define SPS (1 << 5) +#define NO_REBOOT (1 << 4) +#define SX_ENT_TO_EN (1 << 3) +#define TIMING_T581 (1 << 0) + +#define GEN_PMCON1 0x20 +# 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) + +/* Function Disable PBASE + 0x34 */ +#define PBASE_FUNC_DIS 0x34 +#define PBASE_DISABLE_QUICKASSIST (1 << 0) +#define PBASE_DISABLE_GBE(x) (1 << (12 + x)) +#define PBASE_DISABLE_SATA2 (1 << 22) +#define PBASE_DISABLE_EHCI (1 << 23) +#define PBASE_DISABLE_SATA3 (1 << 23) + +/* GPIOBASE */ +#define GPIO_SC_USE_SEL 0x00 +#define GPIO_SC_IO_SEL 0x04 +#define GPIO_SC_GP_LVL 0x08 +#define GPIO_SC_TPE 0x0c +#define GPIO_SC_TNE 0x10 +#define GPIO_SC_TS 0x14 +#define GPIO_SUS_USE_SEL 0x80 +#define GPIO_SUS_IO_SEL 0x84 +#define GPIO_SUS_GP_LVL 0x88 +#define GPIO_SUS_TPE 0x8c +#define GPIO_SUS_TNE 0x90 +#define GPIO_SUS_TS 0x94 +#define GPIO_SUS_WE 0x98 + +/* IOBASE */ +#define CFIO_PAD_CONF0 0x00 +#define CFIO_PAD_CONF1 0x04 +#define CFIO_PAD_VAL 0x08 +#define CFIO_PAD_DFT 0x0C + +/* ACPI BASE */ +#define PM1_STS 0x00 +#define WAK_STS (1 << 15) +#define PCIEXPWAK_STS (1 << 14) +#define PRBTNOR_STS (1 << 11) +#define RTC_STS (1 << 10) +#define PWRBTN_STS (1 << 8) +#define GBL_STS (1 << 5) +#define BM_STS (1 << 4) +#define TMROF_STS (1 << 0) +#define PM1_EN 0x02 +#define PCIEXPWAK_DIS (1 << 14) +#define RTC_EN (1 << 10) +#define PWRBTN_EN (1 << 8) +#define GBL_EN (1 << 5) +#define TMROF_EN (1 << 0) +#define PM1_CNT 0x04 +#define SLP_EN (1 << 13) +#define SLP_TYP (7 << 10) +#define SLP_TYP_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 PROC_CNT 0x10 +#define LV2 0x14 +#define LV3 0x15 +#define LV4 0x16 +#define PM2_CNT 0x50 // mobile only +#define GPE0_STS 0x20 +#define PME_B0_STS (1 << 13) +#define PME_STS (1 << 11) +#define BATLOW_STS (1 << 10) +#define PCI_EXP_STS (1 << 9) +#define RI_STS (1 << 8) +#define SMB_WAK_STS (1 << 7) +#define TCOSCI_STS (1 << 6) +#define SWGPE_STS (1 << 2) +#define HOT_PLUG_STS (1 << 1) +#define GPE0_EN 0x28 +#define PME_B0_EN (1 << 13) +#define PME_EN (1 << 11) +#define TCOSCI_EN (1 << 6) +#define SMI_EN 0x30 +#define INTEL_USB2_EN (1 << 18) // Intel-Specific USB2 SMI logic +#define LEGACY_USB2_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 MCSMI_EN (1 << 11) // Trap microcontroller range access +#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 LEGACY_USB_EN (1 << 3) // Legacy USB circuit SMI logic +#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_GP_SMI_EN 0x38 +#define ALT_GP_SMI_STS 0x3a +#define GPE_CNTL 0x42 +#define DEVACT_STS 0x44 +#define PM2A_CNT_BLK 0x50 +#define SS_CNT 0x50 +#define C3_RES 0x54 +#define TCO1_STS 0x64 +#define DMISCI_STS (1 << 9) +#define TCO2_STS 0x66 +#define TCO1_CNT 0x68 +#define TCO_TMR_HALT (1 << 11) +#define TCO_LOCK (1 << 12) + +/* + * SPI Opcode Menu setup for SPIBAR lockdown + * should support most common flash chips. + */ + +#define SPI_OPMENU_0 0x01 /* WRSR: Write Status Register */ +#define SPI_OPTYPE_0 0x01 /* Write, no address */ + +#define SPI_OPMENU_1 0x02 /* BYPR: Byte Program */ +#define SPI_OPTYPE_1 0x03 /* Write, address required */ + +#define SPI_OPMENU_2 0x03 /* READ: Read Data */ +#define SPI_OPTYPE_2 0x02 /* Read, address required */ + +#define SPI_OPMENU_3 0x05 /* RDSR: Read Status Register */ +#define SPI_OPTYPE_3 0x00 /* Read, no address */ + +#define SPI_OPMENU_4 0x20 /* SE20: Sector Erase 0x20 */ +#define SPI_OPTYPE_4 0x03 /* Write, address required */ + +#define SPI_OPMENU_5 0x9f /* RDID: Read ID */ +#define SPI_OPTYPE_5 0x00 /* Read, no address */ + +#define SPI_OPMENU_6 0xd8 /* BED8: Block Erase 0xd8 */ +#define SPI_OPTYPE_6 0x03 /* Write, address required */ + +#define SPI_OPMENU_7 0x0b /* FAST: Fast Read */ +#define SPI_OPTYPE_7 0x02 /* Read, address required */ + +#define SPI_OPMENU_UPPER ((SPI_OPMENU_7 << 24) | (SPI_OPMENU_6 << 16) | \ + (SPI_OPMENU_5 << 8) | SPI_OPMENU_4) +#define SPI_OPMENU_LOWER ((SPI_OPMENU_3 << 24) | (SPI_OPMENU_2 << 16) | \ + (SPI_OPMENU_1 << 8) | SPI_OPMENU_0) + +#define SPI_OPTYPE ((SPI_OPTYPE_7 << 14) | (SPI_OPTYPE_6 << 12) | \ + (SPI_OPTYPE_5 << 10) | (SPI_OPTYPE_4 << 8) | \ + (SPI_OPTYPE_3 << 6) | (SPI_OPTYPE_2 << 4) | \ + (SPI_OPTYPE_1 << 2) | (SPI_OPTYPE_0)) + +#define SPI_OPPREFIX ((0x50 << 8) | 0x06) /* EWSR and WREN */ + +#define SPIBAR_HSFS 0x04 /* SPI hardware sequence status */ +#define SPIBAR_HSFS_SCIP (1 << 5) /* SPI Cycle In Progress */ +#define SPIBAR_HSFS_AEL (1 << 2) /* SPI Access Error Log */ +#define SPIBAR_HSFS_FCERR (1 << 1) /* SPI Flash Cycle Error */ +#define SPIBAR_HSFS_FDONE (1 << 0) /* SPI Flash Cycle Done */ +#define SPIBAR_HSFC 0x06 /* SPI hardware sequence control */ +#define SPIBAR_HSFC_BYTE_COUNT(c) (((c - 1) & 0x3f) << 8) +#define SPIBAR_HSFC_CYCLE_READ (0 << 1) /* Read cycle */ +#define SPIBAR_HSFC_CYCLE_WRITE (2 << 1) /* Write cycle */ +#define SPIBAR_HSFC_CYCLE_ERASE (3 << 1) /* Erase cycle */ +#define SPIBAR_HSFC_GO (1 << 0) /* GO: start SPI transaction */ +#define SPIBAR_FADDR 0x08 /* SPI flash address */ +#define SPIBAR_FDATA(n) (0x3810 + (4 * n)) /* SPI flash data */ + +/* HPET Registers - Base is set in hardware to 0xFED00000 */ +#define HPET_GCID 0xFED00000 /* General Capabilities and ID */ +#define HPET_GCFG 0xFED00010 /* General Configuration */ +#define HPET_GIS 0xFED00020 /* General Interrupt Status */ +#define HPET_MCV 0xFED000F0 /* Main Counter Value */ +#define HPET_T0C 0xFED00100 /* Timer 0 Configuration and Capabilities */ +#define HPET_T0CV_L 0xFED00108 /* Lower Timer 0 Comparator Value */ +#define HPET_T0CV_U 0xFED0010C /* Upper Timer 0 Comparator Value */ +#define HPET_T1C 0xFED00120 /* Timer 1 Configuration and Capabilities */ +#define HPET_T1CV 0xFED00128 /* Timer 1 Comparator Value */ +#define HPET_T2C 0xFED00140 /* Timer 2 Configuration and Capabilities */ +#define HPET_T2CV 0xFED00148 /* Timer 2 Comparator Value */ + + +#endif /* __ACPI__ */ +#endif /* SOUTHBRIDGE_INTEL_RANGELEY_PCH_H */ diff --git a/src/southbridge/intel/fsp_rangeley/spi.c b/src/southbridge/intel/fsp_rangeley/spi.c new file mode 100644 index 0000000000..8a4eabce3c --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/spi.c @@ -0,0 +1,753 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * Copyright (C) 2013, Intel Corporation. + * + * This 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. + */ + +/* This file is derived from the flashrom project. */ +#include +#include +#include +#include +#include +#include +#include + +#include + +static int ich_status_poll(u16 bitmask, int wait_til_set); + +#ifdef __SMM__ +#include +#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 +#include +#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 ich7_spi_regs { + uint16_t spis; + uint16_t spic; + uint32_t spia; + uint64_t spid[8]; + uint64_t _pad; + uint32_t bbar; + uint16_t preop; + uint16_t optype; + uint8_t opmenu[8]; +} __attribute__((packed)) ich7_spi_regs; + +typedef struct ich9_spi_regs { + uint32_t bfpr; // 0 + uint16_t hsfs; // 4 + uint16_t hsfc; // 6 + uint32_t faddr; // 8 + uint32_t _reserved0; // 0xC + uint32_t fdata[16]; // 0x10 + uint32_t frap; // 0x50 + uint32_t freg[5]; // 0x54 + uint32_t _reserved1[3]; // 0x67 + uint32_t pr[5]; // 0x74 + uint32_t _reserved2[2]; // 0x88 + uint8_t ssfs; // 0x90 + uint8_t ssfc[3]; // 0x91 + uint16_t preop; // 0x94 + uint16_t optype; // 0x96 + uint8_t opmenu[8]; // 0x98 + uint32_t bbar; // 0xB0 + 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 ich10_spi_regs { + uint32_t bfpr; + uint16_t hsfs; + uint16_t hsfc; + uint32_t faddr; + uint32_t _reserved0; + uint32_t fdata[16]; + uint32_t fracc; + 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]; + uint8_t _reserved3[16]; + 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[36]; + uint32_t scs; + uint32_t bcr; + uint32_t tcgc; +} __attribute__((packed)) ich10_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; + uint8_t *bcr; +} 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 { + BCR_BIOSWE = 0x0001, + BCR_BLE = 0x0002, + BCR_SRC_MASK = 0x000c, + BCR_SRC_SHIFT = 0x0002, + BCR_SRC_NO_PREF = 0x0000, + BCR_SRC_NO_PREF_CACHE = 0x0004, + BCR_SRC_EN_PREF_CACHE = 0x0008, + BCR_TSS = 0x0010, + BCR_SMMBWP = 0x0020, + BCR_RESERVED_MASK = 0xffc0 +}; + +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 IS_ENABLED(CONFIG_DEBUG_SPI_FLASH) + +static u8 readb_(const void *addr) +{ + u8 v = read8(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(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(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((unsigned long)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; + + if (cntlr.bbar == NULL) + return; + + 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; +} + +/* + * Check if this device ID matches one of supported Intel SOC devices. + * + * Return the ICH version if there is a match, or zero otherwise. + */ +static inline int get_ich_version(uint16_t device_id) +{ + + if ((device_id >= PCI_DEVICE_ID_INTEL_RANGELEY_LPC_MIN && + device_id <= PCI_DEVICE_ID_INTEL_RANGELEY_LPC_MAX)) + return 10; + + return 0; +} + +void spi_init(void) +{ + int ich_version = 0; + uint8_t bios_cntl; + device_t dev; + uint32_t ids; + uint16_t vendor_id, device_id; + +#ifdef __SMM__ + dev = PCI_DEV(0, 31, 0); +#else + dev = dev_find_slot(0, PCI_DEVFN(31, 0)); +#endif + pci_read_config_dword(dev, 0, &ids); + vendor_id = ids; + device_id = (ids >> 16); + + if (vendor_id != PCI_VENDOR_ID_INTEL) { + printk(BIOS_DEBUG, "SPI: No SOC found.\n"); + return; + } + + ich_version = get_ich_version(device_id); + + if (!ich_version) { + printk(BIOS_DEBUG, "SPI: No known SOC found.\n"); + return; + } + + switch (ich_version) { + case 10: + { + uint8_t *spibase; /* SPI Base Address */ + uint32_t sbase; /* SPI Base Address Register */ + pci_read_config_dword(dev, 0x54, &sbase); + /* Bits 31-9 are the base address, 8-4 are reserved, 3-0 are used. */ + spibase = (uint8_t *)(sbase & 0xffffff00); + ich10_spi_regs *ich10_spi = + (ich10_spi_regs *)(spibase); + ichspi_lock = readw_(&ich10_spi->hsfs) & HSFS_FLOCKDN; + cntlr.opmenu = ich10_spi->opmenu; + cntlr.menubytes = sizeof(ich10_spi->opmenu); + cntlr.optype = &ich10_spi->optype; + cntlr.addr = &ich10_spi->faddr; + cntlr.data = (uint8_t *)ich10_spi->fdata; + cntlr.databytes = sizeof(ich10_spi->fdata); + cntlr.status = &ich10_spi->ssfs; + cntlr.control = (uint16_t *)ich10_spi->ssfc; + cntlr.bbar = NULL; + cntlr.preop = &ich10_spi->preop; + cntlr.bcr = (uint8_t *)&ich10_spi->bcr; + break; + } + default: + printk(BIOS_DEBUG, "ICH SPI: Unrecognized ICH version %d.\n", ich_version); + } + + ich_set_bbar(0); + + /* Disable the BIOS write protect so write commands are allowed. */ + switch (ich_version) { + case 10: + { + /* Deassert SMM BIOS write protect(SMM BWP) and assert enable flash write(BIOSWE) */ + bios_cntl = readb_(cntlr.bcr); + bios_cntl &= ~BCR_SMMBWP; + bios_cntl |= BCR_BIOSWE; + writeb_(bios_cntl, cntlr.bcr); + break; + } + + default: + break; + } +} + +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 = 60000; /* This will result in 600 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 (!ichspi_lock && 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. + */ + 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 + * bitesout 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; + } + + goto spi_xfer_exit; + } + + /* + * 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; + } + } + +spi_xfer_exit: + /* Clear atomic preop now that xfer is done */ + writew_(0, cntlr.preop); + + return 0; +} diff --git a/src/southbridge/intel/fsp_rangeley/watchdog.c b/src/southbridge/intel/fsp_rangeley/watchdog.c new file mode 100644 index 0000000000..1ea4985769 --- /dev/null +++ b/src/southbridge/intel/fsp_rangeley/watchdog.c @@ -0,0 +1,56 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2011 Google Inc. + * Copyright (C) 2013 Sage Electronic Engineering, LLC. + * + * This 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. + */ + +#include +#include +#include +#include +#include +#include "soc.h" + +void watchdog_off(void) +{ + device_t dev; + u32 value, abase; + + /* Turn off the watchdog. */ + dev = dev_find_slot(0, PCI_DEVFN(0x1f, 0)); + + /* Enable I/O space. */ + value = pci_read_config16(dev, 0x04); + value |= 1; + pci_write_config16(dev, 0x04, value); + + /* Get TCO base. */ + abase = (pci_read_config32(dev, ABASE) & ~0xf); + + /* Disable the watchdog timer. */ + value = inw(abase + 0x68); + value |= 1 << 11; + outw(value, abase + 0x68); + + /* Clear TCO timeout status. */ + outw(0x0008, abase + 0x64); + outw(0x0002, abase + 0x66); + + printk(BIOS_DEBUG, "TCO Watchdog disabled\n"); +} diff --git a/src/vendorcode/intel/Kconfig b/src/vendorcode/intel/Kconfig index 1d1049e14b..580089f397 100644 --- a/src/vendorcode/intel/Kconfig +++ b/src/vendorcode/intel/Kconfig @@ -20,6 +20,7 @@ config FSP_VENDORCODE_HEADER_PATH string default "fsp1_0/baytrail" if SOC_INTEL_FSP_BAYTRAIL + default "fsp1_0/rangeley" if CPU_INTEL_FSP_MODEL_406DX config UEFI_2_4_BINDING def_bool n -- cgit v1.2.3