summaryrefslogtreecommitdiff
path: root/src/southbridge/intel
diff options
context:
space:
mode:
authorMartin Roth <martinroth@google.com>2015-10-11 10:36:26 +0200
committerMartin Roth <martinroth@google.com>2015-10-14 22:49:03 +0000
commit58562405c8c416a415652516b8af31b204b4ff0d (patch)
tree3311f3f5feceea80a048337f0485fc9c956ee5ac /src/southbridge/intel
parent83e4c5613eecc5283d9a66997dc90e26384f9284 (diff)
downloadcoreboot-58562405c8c416a415652516b8af31b204b4ff0d.tar.xz
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 <martinroth@google.com> Reviewed-on: http://review.coreboot.org/11860 Tested-by: build bot (Jenkins) Reviewed-by: Marc Jones <marc@marcjonesconsulting.com> Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/southbridge/intel')
-rw-r--r--src/southbridge/intel/fsp_rangeley/Kconfig63
-rw-r--r--src/southbridge/intel/fsp_rangeley/Makefile.inc38
-rw-r--r--src/southbridge/intel/fsp_rangeley/acpi.c201
-rw-r--r--src/southbridge/intel/fsp_rangeley/acpi/globalnvs.asl185
-rw-r--r--src/southbridge/intel/fsp_rangeley/acpi/irq_helper.h61
-rw-r--r--src/southbridge/intel/fsp_rangeley/acpi/irqlinks.asl491
-rw-r--r--src/southbridge/intel/fsp_rangeley/acpi/irqroute.asl43
-rw-r--r--src/southbridge/intel/fsp_rangeley/acpi/lpc.asl230
-rw-r--r--src/southbridge/intel/fsp_rangeley/acpi/pcie.asl169
-rw-r--r--src/southbridge/intel/fsp_rangeley/acpi/pcie_port.asl29
-rw-r--r--src/southbridge/intel/fsp_rangeley/acpi/sata.asl81
-rw-r--r--src/southbridge/intel/fsp_rangeley/acpi/sleepstates.asl30
-rw-r--r--src/southbridge/intel/fsp_rangeley/acpi/smbus.asl240
-rw-r--r--src/southbridge/intel/fsp_rangeley/acpi/soc.asl276
-rw-r--r--src/southbridge/intel/fsp_rangeley/acpi/usb.asl52
-rw-r--r--src/southbridge/intel/fsp_rangeley/chip.h88
-rw-r--r--src/southbridge/intel/fsp_rangeley/early_init.c79
-rw-r--r--src/southbridge/intel/fsp_rangeley/early_smbus.c61
-rw-r--r--src/southbridge/intel/fsp_rangeley/early_spi.c114
-rw-r--r--src/southbridge/intel/fsp_rangeley/early_usb.c47
-rw-r--r--src/southbridge/intel/fsp_rangeley/gpio.c108
-rw-r--r--src/southbridge/intel/fsp_rangeley/gpio.h128
-rw-r--r--src/southbridge/intel/fsp_rangeley/irq.h166
-rw-r--r--src/southbridge/intel/fsp_rangeley/lpc.c478
-rw-r--r--src/southbridge/intel/fsp_rangeley/nvs.h156
-rw-r--r--src/southbridge/intel/fsp_rangeley/pci_devs.h137
-rw-r--r--src/southbridge/intel/fsp_rangeley/reset.c34
-rw-r--r--src/southbridge/intel/fsp_rangeley/romstage.c143
-rw-r--r--src/southbridge/intel/fsp_rangeley/romstage.h39
-rw-r--r--src/southbridge/intel/fsp_rangeley/sata.c135
-rw-r--r--src/southbridge/intel/fsp_rangeley/smbus.c99
-rw-r--r--src/southbridge/intel/fsp_rangeley/smbus.h99
-rw-r--r--src/southbridge/intel/fsp_rangeley/soc.c99
-rw-r--r--src/southbridge/intel/fsp_rangeley/soc.h452
-rw-r--r--src/southbridge/intel/fsp_rangeley/spi.c753
-rw-r--r--src/southbridge/intel/fsp_rangeley/watchdog.c56
36 files changed, 5660 insertions, 0 deletions
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 <string.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <arch/acpi.h>
+#include <southbridge/intel/fsp_rangeley/soc.h>
+#include <arch/io.h>
+
+#if IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)
+#include <cpu/x86/smm.h>
+#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 <arch/acpi.h>
+
+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 <stdint.h>
+#include <stdlib.h>
+#include <console/console.h>
+#include <arch/io.h>
+#include <device/pci_def.h>
+#include <pc80/mc146818rtc.h>
+#include <version.h>
+#include <device/pci_def.h>
+#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 <arch/io.h>
+#include <console/console.h>
+#include <device/pci_ids.h>
+#include <device/pci_def.h>
+#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 <arch/io.h>
+#include <console/console.h>
+#include <device/pci_ids.h>
+#include <device/pci_def.h>
+#include <delay.h>
+#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 <arch/io.h>
+#include <console/console.h>
+#include <device/pci_ids.h>
+#include <device/pci_def.h>
+#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 <stdint.h>
+#include <string.h>
+#include <arch/io.h>
+
+#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 <stdint.h>
+
+#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 <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <pc80/mc146818rtc.h>
+#include <pc80/isa-dma.h>
+#include <pc80/i8259.h>
+#include <arch/io.h>
+#include <arch/ioapic.h>
+#include <arch/acpi.h>
+#include <cpu/cpu.h>
+#include <elog.h>
+#include <string.h>
+#include <cbmem.h>
+#include <arch/acpi.h>
+#include <arch/acpigen.h>
+#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 <arch/io.h>
+#include <reset.h>
+
+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 <stdint.h>
+#include <string.h>
+#include <lib.h>
+#include <timestamp.h>
+#include <arch/io.h>
+#include <device/pci_def.h>
+#include <device/pnp_def.h>
+#include <cpu/x86/lapic.h>
+#include <pc80/mc146818rtc.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <drivers/intel/fsp1_0/fsp_util.h>
+#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 <arch/cpu.h>
+#include <arch/stages.h>
+#include <cpu/x86/msr.h>
+#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 <stdint.h>
+#include <arch/cpu.h>
+#include <drivers/intel/fsp1_0/fsp_util.h>
+
+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 <arch/io.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#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 <console/console.h>
+#include <device/device.h>
+#include <device/path.h>
+#include <device/smbus.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <arch/io.h>
+#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 <yinghailu@gmail.com>
+ * 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 <device/smbus_def.h>
+#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 <console/console.h>
+#include <delay.h>
+#include <device/device.h>
+#include <device/pci.h>
+#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 <arch/acpi.h>
+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 <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <delay.h>
+#include <arch/io.h>
+#include <console/console.h>
+#include <device/pci_ids.h>
+
+#include <spi-generic.h>
+
+static int ich_status_poll(u16 bitmask, int wait_til_set);
+
+#ifdef __SMM__
+#include <arch/pci_mmio_cfg.h>
+#define pci_read_config_byte(dev, reg, targ)\
+ *(targ) = pci_read_config8(dev, reg)
+#define pci_read_config_word(dev, reg, targ)\
+ *(targ) = pci_read_config16(dev, reg)
+#define pci_read_config_dword(dev, reg, targ)\
+ *(targ) = pci_read_config32(dev, reg)
+#define pci_write_config_byte(dev, reg, val)\
+ pci_write_config8(dev, reg, val)
+#define pci_write_config_word(dev, reg, val)\
+ pci_write_config16(dev, reg, val)
+#define pci_write_config_dword(dev, reg, val)\
+ pci_write_config32(dev, reg, val)
+#else /* !__SMM__ */
+#include <device/device.h>
+#include <device/pci.h>
+#define pci_read_config_byte(dev, reg, targ)\
+ *(targ) = pci_read_config8(dev, reg)
+#define pci_read_config_word(dev, reg, targ)\
+ *(targ) = pci_read_config16(dev, reg)
+#define pci_read_config_dword(dev, reg, targ)\
+ *(targ) = pci_read_config32(dev, reg)
+#define pci_write_config_byte(dev, reg, val)\
+ pci_write_config8(dev, reg, val)
+#define pci_write_config_word(dev, reg, val)\
+ pci_write_config16(dev, reg, val)
+#define pci_write_config_dword(dev, reg, val)\
+ pci_write_config32(dev, reg, val)
+#endif /* !__SMM__ */
+
+typedef struct spi_slave ich_spi_slave;
+
+static int ichspi_lock = 0;
+
+typedef struct 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 <console/console.h>
+#include <arch/io.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <watchdog.h>
+#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");
+}