summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/amd/picasso/BiosCallOuts.c166
-rw-r--r--src/soc/amd/picasso/Kconfig389
-rw-r--r--src/soc/amd/picasso/acpi.c406
-rw-r--r--src/soc/amd/picasso/acpi/acpi_wake_source.asl32
-rw-r--r--src/soc/amd/picasso/acpi/cpu.asl49
-rw-r--r--src/soc/amd/picasso/acpi/globalnvs.asl77
-rw-r--r--src/soc/amd/picasso/acpi/northbridge.asl134
-rw-r--r--src/soc/amd/picasso/acpi/pci_int.asl469
-rw-r--r--src/soc/amd/picasso/acpi/pcie.asl99
-rw-r--r--src/soc/amd/picasso/acpi/sb_fch.asl153
-rw-r--r--src/soc/amd/picasso/acpi/sb_pci0_fch.asl619
-rw-r--r--src/soc/amd/picasso/acpi/sleepstates.asl39
-rw-r--r--src/soc/amd/picasso/acpi/soc.asl31
-rw-r--r--src/soc/amd/picasso/acpi/usb.asl392
-rw-r--r--src/soc/amd/picasso/bootblock/bootblock.c122
-rw-r--r--src/soc/amd/picasso/chip.c175
-rw-r--r--src/soc/amd/picasso/chip.h81
-rw-r--r--src/soc/amd/picasso/cpu.c155
-rw-r--r--src/soc/amd/picasso/enable_usbdebug.c42
-rw-r--r--src/soc/amd/picasso/finalize.c60
-rw-r--r--src/soc/amd/picasso/gpio.c67
-rw-r--r--src/soc/amd/picasso/i2c.c241
-rw-r--r--src/soc/amd/picasso/include/soc/acpi.h40
-rw-r--r--src/soc/amd/picasso/include/soc/amd_pci_int_defs.h61
-rw-r--r--src/soc/amd/picasso/include/soc/cpu.h35
-rw-r--r--src/soc/amd/picasso/include/soc/gpio.h308
-rw-r--r--src/soc/amd/picasso/include/soc/i2c.h49
-rw-r--r--src/soc/amd/picasso/include/soc/iomap.h88
-rw-r--r--src/soc/amd/picasso/include/soc/northbridge.h133
-rw-r--r--src/soc/amd/picasso/include/soc/nvs.h67
-rw-r--r--src/soc/amd/picasso/include/soc/pci_devs.h198
-rw-r--r--src/soc/amd/picasso/include/soc/romstage.h21
-rw-r--r--src/soc/amd/picasso/include/soc/smbus.h35
-rw-r--r--src/soc/amd/picasso/include/soc/smi.h242
-rw-r--r--src/soc/amd/picasso/include/soc/southbridge.h415
-rw-r--r--src/soc/amd/picasso/makefile.inc316
-rw-r--r--src/soc/amd/picasso/mca.c214
-rw-r--r--src/soc/amd/picasso/monotonic_timer.c38
-rw-r--r--src/soc/amd/picasso/nb_util.c40
-rw-r--r--src/soc/amd/picasso/northbridge.c492
-rw-r--r--src/soc/amd/picasso/pmutil.c27
-rw-r--r--src/soc/amd/picasso/ramtop.c151
-rw-r--r--src/soc/amd/picasso/reset.c73
-rw-r--r--src/soc/amd/picasso/romstage.c247
-rw-r--r--src/soc/amd/picasso/sata.c48
-rw-r--r--src/soc/amd/picasso/sm.c104
-rw-r--r--src/soc/amd/picasso/smbus.c191
-rw-r--r--src/soc/amd/picasso/smbus_spd.c76
-rw-r--r--src/soc/amd/picasso/smi.c38
-rw-r--r--src/soc/amd/picasso/smi_util.c138
-rw-r--r--src/soc/amd/picasso/smihandler.c287
-rw-r--r--src/soc/amd/picasso/southbridge.c675
-rw-r--r--src/soc/amd/picasso/spi.c189
-rw-r--r--src/soc/amd/picasso/tsc_freq.c49
-rw-r--r--src/soc/amd/picasso/uart.c30
-rw-r--r--src/soc/amd/picasso/usb.c85
56 files changed, 9198 insertions, 0 deletions
diff --git a/src/soc/amd/picasso/BiosCallOuts.c b/src/soc/amd/picasso/BiosCallOuts.c
new file mode 100644
index 0000000000..c55e73499a
--- /dev/null
+++ b/src/soc/amd/picasso/BiosCallOuts.c
@@ -0,0 +1,166 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011, 2017 Advanced Micro Devices, Inc.
+ * Copyright (C) 2013 Sage Electronic Engineering, LLC
+ * Copyright (C) 2017 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.
+ */
+
+#include <device/device.h>
+#include <device/pci_def.h>
+#include <amdblocks/BiosCallOuts.h>
+#include <console/console.h>
+#include <soc/southbridge.h>
+#include <soc/pci_devs.h>
+#include <stdlib.h>
+#include <amdblocks/agesawrapper.h>
+#include <amdblocks/dimm_spd.h>
+#include <amdblocks/car.h>
+
+#include "chip.h"
+
+void __weak platform_FchParams_reset(FCH_RESET_DATA_BLOCK *FchParams_reset) {}
+
+AGESA_STATUS agesa_fch_initreset(uint32_t Func, uintptr_t FchData,
+ void *ConfigPtr)
+{
+ AMD_CONFIG_PARAMS *StdHeader = ConfigPtr;
+
+ if (StdHeader->Func == AMD_INIT_RESET) {
+ FCH_RESET_DATA_BLOCK *FchParams_reset;
+ FchParams_reset = (FCH_RESET_DATA_BLOCK *)FchData;
+ printk(BIOS_DEBUG, "Fch OEM config in INIT RESET ");
+
+ /* Get platform specific configuration changes */
+ platform_FchParams_reset(FchParams_reset);
+
+ printk(BIOS_DEBUG, "Done\n");
+ }
+
+ return AGESA_SUCCESS;
+}
+
+AGESA_STATUS agesa_fch_initenv(uint32_t Func, uintptr_t FchData,
+ void *ConfigPtr)
+{
+ AMD_CONFIG_PARAMS *StdHeader = ConfigPtr;
+ const struct device *dev = pcidev_path_on_root(SATA_DEVFN);
+
+ if (StdHeader->Func == AMD_INIT_ENV) {
+ FCH_DATA_BLOCK *FchParams_env = (FCH_DATA_BLOCK *)FchData;
+ printk(BIOS_DEBUG, "Fch OEM config in INIT ENV ");
+
+ /* XHCI configuration */
+ if (CONFIG(STONEYRIDGE_XHCI_ENABLE))
+ FchParams_env->Usb.Xhci0Enable = TRUE;
+ else
+ FchParams_env->Usb.Xhci0Enable = FALSE;
+ FchParams_env->Usb.Xhci1Enable = FALSE;
+
+ /* SATA configuration */
+ FchParams_env->Sata.SataClass = CONFIG_STONEYRIDGE_SATA_MODE;
+ if (dev && dev->enabled) {
+ switch ((SATA_CLASS)CONFIG_STONEYRIDGE_SATA_MODE) {
+ case SataRaid:
+ case SataAhci:
+ case SataAhci7804:
+ case SataLegacyIde:
+ FchParams_env->Sata.SataIdeMode = FALSE;
+ break;
+ case SataIde2Ahci:
+ case SataIde2Ahci7804:
+ default: /* SataNativeIde */
+ FchParams_env->Sata.SataIdeMode = TRUE;
+ break;
+ }
+ } else
+ FchParams_env->Sata.SataIdeMode = FALSE;
+
+ /* Platform updates */
+ platform_FchParams_env(FchParams_env);
+
+ printk(BIOS_DEBUG, "Done\n");
+ }
+
+ return AGESA_SUCCESS;
+}
+
+AGESA_STATUS agesa_ReadSpd(uint32_t Func, uintptr_t Data, void *ConfigPtr)
+{
+ uint8_t spd_address;
+ int err;
+ DEVTREE_CONST struct device *dev;
+ DEVTREE_CONST struct soc_amd_stoneyridge_config *conf;
+ AGESA_READ_SPD_PARAMS *info = ConfigPtr;
+
+ if (!ENV_ROMSTAGE)
+ return AGESA_UNSUPPORTED;
+
+ dev = pcidev_path_on_root(DCT_DEVFN);
+ if (dev == NULL)
+ return AGESA_ERROR;
+
+ conf = dev->chip_info;
+ if (conf == NULL)
+ return AGESA_ERROR;
+
+ if (info->SocketId >= ARRAY_SIZE(conf->spd_addr_lookup))
+ return AGESA_ERROR;
+ if (info->MemChannelId >= ARRAY_SIZE(conf->spd_addr_lookup[0]))
+ return AGESA_ERROR;
+ if (info->DimmId >= ARRAY_SIZE(conf->spd_addr_lookup[0][0]))
+ return AGESA_ERROR;
+
+ spd_address = conf->spd_addr_lookup
+ [info->SocketId][info->MemChannelId][info->DimmId];
+ if (spd_address == 0)
+ return AGESA_ERROR;
+
+ err = mainboard_read_spd(spd_address, (void *)info->Buffer,
+ CONFIG_DIMM_SPD_SIZE);
+
+ /* Read the SPD if the mainboard didn't fill the buffer */
+ if (err || (*info->Buffer == 0))
+ err = sb_read_spd(spd_address, (void *)info->Buffer,
+ CONFIG_DIMM_SPD_SIZE);
+
+ if (err)
+ return AGESA_ERROR;
+
+ return AGESA_SUCCESS;
+}
+
+AGESA_STATUS agesa_HaltThisAp(uint32_t Func, uintptr_t Data, void *ConfigPtr)
+{
+ AGESA_HALT_THIS_AP_PARAMS *info = ConfigPtr;
+ uint32_t flags = 0;
+
+ if (info->PrimaryCore == TRUE)
+ return AGESA_UNSUPPORTED; /* force normal path */
+ if (info->ExecWbinvd == TRUE)
+ flags |= 1;
+ if (info->CacheEn == TRUE)
+ flags |= 2;
+
+ ap_teardown_car(flags); /* does not return */
+
+ /* Should never reach here */
+ return AGESA_UNSUPPORTED;
+}
+
+/* Allow mainboards to fill the SPD buffer */
+__weak int mainboard_read_spd(uint8_t spdAddress, char *buf,
+ size_t len)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+ return -1; /* SPD not read */
+}
diff --git a/src/soc/amd/picasso/Kconfig b/src/soc/amd/picasso/Kconfig
new file mode 100644
index 0000000000..ba82565bf4
--- /dev/null
+++ b/src/soc/amd/picasso/Kconfig
@@ -0,0 +1,389 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2017 Advanced Micro Devices, 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.
+##
+
+config SOC_AMD_STONEYRIDGE_FP4
+ bool
+ help
+ AMD Stoney Ridge FP4 support
+
+config SOC_AMD_STONEYRIDGE_FT4
+ bool
+ help
+ AMD Stoney Ridge FT4 support
+
+if SOC_AMD_STONEYRIDGE_FP4 || SOC_AMD_STONEYRIDGE_FT4
+
+config CPU_SPECIFIC_OPTIONS
+ def_bool y
+ select ARCH_BOOTBLOCK_X86_32
+ select ARCH_VERSTAGE_X86_32
+ select ARCH_ROMSTAGE_X86_32
+ select ARCH_RAMSTAGE_X86_32
+ select X86_AMD_FIXED_MTRRS
+ select ACPI_AMD_HARDWARE_SLEEP_VALUES
+ select COLLECT_TIMESTAMPS_NO_TSC
+ select DRIVERS_I2C_DESIGNWARE
+ select GENERIC_GPIO_LIB
+ select GENERIC_UDELAY
+ select IOAPIC
+ select HAVE_USBDEBUG_OPTIONS
+ select HAVE_MONOTONIC_TIMER
+ select SPI_FLASH if HAVE_ACPI_RESUME
+ select TSC_SYNC_LFENCE
+ select COLLECT_TIMESTAMPS
+ select SOC_AMD_PI
+ select SOC_AMD_COMMON
+ select SOC_AMD_COMMON_BLOCK
+ select SOC_AMD_COMMON_BLOCK_IOMMU
+ select SOC_AMD_COMMON_BLOCK_ACPIMMIO
+ select SOC_AMD_COMMON_BLOCK_BANKED_GPIOS
+ select SOC_AMD_COMMON_BLOCK_ACPI
+ select SOC_AMD_COMMON_BLOCK_LPC
+ select SOC_AMD_COMMON_BLOCK_PCI
+ select SOC_AMD_COMMON_BLOCK_HDA
+ select SOC_AMD_COMMON_BLOCK_SATA
+ select SOC_AMD_COMMON_BLOCK_PI
+ select SOC_AMD_COMMON_BLOCK_PSP
+ select SOC_AMD_COMMON_BLOCK_CAR
+ select SOC_AMD_COMMON_BLOCK_S3
+ select C_ENVIRONMENT_BOOTBLOCK
+ select BOOT_DEVICE_SUPPORTS_WRITES if BOOT_DEVICE_SPI_FLASH
+ select BOOT_DEVICE_SPI_FLASH_RW_NOMMAP_EARLY if BOOT_DEVICE_SPI_FLASH
+ select CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM
+ select PARALLEL_MP
+ select PARALLEL_MP_AP_WORK
+ select HAVE_SMI_HANDLER
+ select SMM_TSEG
+ select POSTCAR_STAGE
+ select POSTCAR_CONSOLE
+ select SSE2
+ select RTC
+ select SOC_AMD_PSP_SELECTABLE_SMU_FW
+
+config VBOOT
+ select VBOOT_SEPARATE_VERSTAGE
+ select VBOOT_STARTS_IN_BOOTBLOCK
+ select VBOOT_SAVE_RECOVERY_REASON_ON_REBOOT
+ select VBOOT_VBNV_CMOS
+ select VBOOT_VBNV_CMOS_BACKUP_TO_FLASH
+
+config UDELAY_LAPIC_FIXED_FSB
+ int
+ default 200
+
+# TODO: Sync these with definitions in PI vendorcode.
+# DCACHE_RAM_BASE must equal BSP_STACK_BASE_ADDR.
+# DCACHE_RAM_SIZE must equal BSP_STACK_SIZE.
+
+config DCACHE_RAM_BASE
+ hex
+ default 0x30000
+
+config DCACHE_RAM_SIZE
+ hex
+ default 0x10000
+
+config DCACHE_BSP_STACK_SIZE
+ depends on C_ENVIRONMENT_BOOTBLOCK
+ hex
+ default 0x4000
+ help
+ The amount of anticipated stack usage in CAR by bootblock and
+ other stages.
+
+config PRERAM_CBMEM_CONSOLE_SIZE
+ hex
+ default 0x1600
+ help
+ Increase this value if preram cbmem console is getting truncated
+
+config CPU_ADDR_BITS
+ int
+ default 48
+
+config BOTTOMIO_POSITION
+ hex "Bottom of 32-bit IO space"
+ default 0xD0000000
+ help
+ If PCI peripherals with big BARs are connected to the system
+ the bottom of the IO must be decreased to allocate such
+ devices.
+
+ Declare the beginning of the 128MB-aligned MMIO region. This
+ option is useful when PCI peripherals requesting large address
+ ranges are present.
+
+config MMCONF_BASE_ADDRESS
+ hex
+ default 0xF8000000
+
+config MMCONF_BUS_NUMBER
+ int
+ default 64
+
+config VGA_BIOS_ID
+ string
+ default "1002,98e4"
+ help
+ The default VGA BIOS PCI vendor/device ID should be set to the
+ result of the map_oprom_vendev() function in northbridge.c.
+
+config VGA_BIOS_FILE
+ string
+ default "3rdparty/blobs/soc/amd/stoneyridge/VBIOS.bin"
+
+config S3_VGA_ROM_RUN
+ bool
+ default n
+
+config HEAP_SIZE
+ hex
+ default 0xc0000
+
+config EHCI_BAR
+ hex
+ default 0xfef00000
+
+config STONEYRIDGE_XHCI_ENABLE
+ bool "Enable Stoney Ridge XHCI Controller"
+ default y
+ help
+ The XHCI controller must be enabled and the XHCI firmware
+ must be added in order to have USB 3.0 support configured
+ by coreboot. The OS will be responsible for enabling the XHCI
+ controller if the XHCI firmware is available but the
+ XHCI controller is not enabled by coreboot.
+
+config STONEYRIDGE_XHCI_FWM
+ bool "Add xhci firmware"
+ default y
+ help
+ Add Stoney Ridge XHCI Firmware to support the onboard USB 3.0
+
+config STONEYRIDGE_GEC_FWM
+ bool
+ default n
+ help
+ Add Stoney Ridge GEC Firmware to support the onboard gigabit Ethernet MAC.
+ Must be connected to a Broadcom B50610 or B50610M PHY on the motherboard.
+
+config STONEYRIDGE_XHCI_FWM_FILE
+ string "XHCI firmware path and filename"
+ default "3rdparty/blobs/soc/amd/stoneyridge/xhci.bin"
+ depends on STONEYRIDGE_XHCI_FWM
+
+config STONEYRIDGE_GEC_FWM_FILE
+ string "GEC firmware path and filename"
+ depends on STONEYRIDGE_GEC_FWM
+
+config AMD_PUBKEY_FILE
+ string "AMD public Key"
+ default "3rdparty/blobs/soc/amd/stoneyridge/PSP/AmdPubKeyST.bin"
+
+config STONEYRIDGE_SATA_MODE
+ int "SATA Mode"
+ default 0
+ range 0 6
+ help
+ Select the mode in which SATA should be driven.
+ The default is NATIVE.
+ 0: NATIVE mode does not require a ROM.
+ 2: AHCI may work with or without AHCI ROM. It depends on the payload support.
+ For example, seabios does not require the AHCI ROM.
+ 3: LEGACY IDE
+ 4: IDE to AHCI
+ 5: AHCI7804: ROM Required, and AMD driver required in the OS.
+ 6: IDE to AHCI7804: ROM Required, and AMD driver required in the OS.
+
+comment "NATIVE"
+ depends on STONEYRIDGE_SATA_MODE = 0
+
+comment "AHCI"
+ depends on STONEYRIDGE_SATA_MODE = 2
+
+comment "LEGACY IDE"
+ depends on STONEYRIDGE_SATA_MODE = 3
+
+comment "IDE to AHCI"
+ depends on STONEYRIDGE_SATA_MODE = 4
+
+comment "AHCI7804"
+ depends on STONEYRIDGE_SATA_MODE = 5
+
+comment "IDE to AHCI7804"
+ depends on STONEYRIDGE_SATA_MODE = 6
+
+if STONEYRIDGE_SATA_MODE = 2 || STONEYRIDGE_SATA_MODE = 5
+
+config AHCI_ROM_ID
+ string "AHCI device PCI IDs"
+ default "1022,7801" if STONEYRIDGE_SATA_MODE = 2
+ default "1022,7804" if STONEYRIDGE_SATA_MODE = 5
+
+endif # STONEYRIDGE_SATA_MODE = 2 || STONEYRIDGE_SATA_MODE = 5
+
+config STONEYRIDGE_LEGACY_FREE
+ bool "System is legacy free"
+ help
+ Select y if there is no keyboard controller in the system.
+ This sets variables in AGESA and ACPI.
+
+config SERIRQ_CONTINUOUS_MODE
+ bool
+ default n
+ help
+ Set this option to y for serial IRQ in continuous mode.
+ Otherwise it is in quiet mode.
+
+config STONEYRIDGE_ACPI_IO_BASE
+ hex
+ default 0x400
+ help
+ Base address for the ACPI registers.
+ This value must match the hardcoded value of AGESA.
+
+config STONEYRIDGE_UART
+ bool "UART controller on Stoney Ridge"
+ default n
+ select DRIVERS_UART_8250MEM
+ select DRIVERS_UART_8250MEM_32
+ select NO_UART_ON_SUPERIO
+ select UART_OVERRIDE_REFCLK
+ help
+ There are two UART controllers in Stoney Ridge.
+ The UART registers are memory-mapped. UART
+ controller 0 registers range from FEDC_6000h
+ to FEDC_6FFFh. UART controller 1 registers
+ range from FEDC_8000h to FEDC_8FFFh.
+
+config CONSOLE_UART_BASE_ADDRESS
+ depends on CONSOLE_SERIAL
+ hex
+ default 0xfedc6000
+
+config SMM_TSEG_SIZE
+ hex
+ default 0x800000 if SMM_TSEG && HAVE_SMI_HANDLER
+ default 0x0
+
+config SMM_RESERVED_SIZE
+ hex
+ default 0x150000
+
+config SMM_MODULE_STACK_SIZE
+ hex
+ default 0x800
+
+config ACPI_CPU_STRING
+ string
+ default "\\_PR.P%03d"
+
+config ACPI_BERT
+ bool "Build ACPI BERT Table"
+ default y
+ depends on HAVE_ACPI_TABLES
+ help
+ Report Machine Check errors identified in POST to the OS in an
+ ACPI Boot Error Record Table. This option reserves an 8MB region
+ for building the error structures.
+
+config USE_PSPSECUREOS
+ bool "Include PSP SecureOS blobs in AMD firmware"
+ default y
+ help
+ Include the PspSecureOs, PspTrustlet and TrustletKey binaries
+ in the amdfw section.
+
+ If unsure, answer 'y'
+
+config SOC_AMD_SMU_FANLESS
+ bool
+ depends on SOC_AMD_PSP_SELECTABLE_SMU_FW
+ default n if SOC_AMD_SMU_NOTFANLESS
+ default y
+
+config SOC_AMD_SMU_FANNED
+ bool
+ depends on SOC_AMD_PSP_SELECTABLE_SMU_FW
+ default n
+ select SOC_AMD_SMU_NOTFANLESS
+
+config SOC_AMD_SMU_NOTFANLESS # helper symbol - do not use
+ bool
+ depends on SOC_AMD_PSP_SELECTABLE_SMU_FW
+
+config AMDFW_OUTSIDE_CBFS
+ bool "The AMD firmware is outside CBFS"
+ default n
+ help
+ The AMDFW (PSP) is typically locatable in cbfs. Select this
+ option to manually attach the generated amdfw.rom outside of
+ cbfs. The location is selected by the FWM position.
+
+config AMD_FWM_POSITION_INDEX
+ int "Firmware Directory Table location (0 to 5)"
+ range 0 5
+ default 0 if BOARD_ROMSIZE_KB_512
+ default 1 if BOARD_ROMSIZE_KB_1024
+ default 2 if BOARD_ROMSIZE_KB_2048
+ default 3 if BOARD_ROMSIZE_KB_4096
+ default 4 if BOARD_ROMSIZE_KB_8192
+ default 5 if BOARD_ROMSIZE_KB_16384
+ help
+ Typically this is calculated by the ROM size, but there may
+ be situations where you want to put the firmware directory
+ table in a different location.
+ 0: 512 KB - 0xFFFA0000
+ 1: 1 MB - 0xFFF20000
+ 2: 2 MB - 0xFFE20000
+ 3: 4 MB - 0xFFC20000
+ 4: 8 MB - 0xFF820000
+ 5: 16 MB - 0xFF020000
+
+comment "AMD Firmware Directory Table set to location for 512KB ROM"
+ depends on AMD_FWM_POSITION_INDEX = 0
+comment "AMD Firmware Directory Table set to location for 1MB ROM"
+ depends on AMD_FWM_POSITION_INDEX = 1
+comment "AMD Firmware Directory Table set to location for 2MB ROM"
+ depends on AMD_FWM_POSITION_INDEX = 2
+comment "AMD Firmware Directory Table set to location for 4MB ROM"
+ depends on AMD_FWM_POSITION_INDEX = 3
+comment "AMD Firmware Directory Table set to location for 8MB ROM"
+ depends on AMD_FWM_POSITION_INDEX = 4
+comment "AMD Firmware Directory Table set to location for 16MB ROM"
+ depends on AMD_FWM_POSITION_INDEX = 5
+
+config DIMM_SPD_SIZE
+ int
+ default 512 # DDR4
+
+config RO_REGION_ONLY
+ string
+ depends on CHROMEOS
+ default "apu/amdfw"
+
+config DRIVERS_I2C_DESIGNWARE_CLOCK_MHZ
+ int
+ default 133
+
+config MAINBOARD_POWER_RESTORE
+ def_bool n
+ help
+ This option determines what state to go to once power is restored
+ after having been lost in S0. Select this option to automatically
+ return to S0. Otherwise the system will remain in S5 once power
+ is restored.
+
+endif # SOC_AMD_STONEYRIDGE_FP4 || SOC_AMD_STONEYRIDGE_FT4
diff --git a/src/soc/amd/picasso/acpi.c b/src/soc/amd/picasso/acpi.c
new file mode 100644
index 0000000000..d1ea24ffd5
--- /dev/null
+++ b/src/soc/amd/picasso/acpi.c
@@ -0,0 +1,406 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012, 2017 Advanced Micro Devices, Inc.
+ * Copyright (C) 2014 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * ACPI - create the Fixed ACPI Description Tables (FADT)
+ */
+
+#include <string.h>
+#include <console/console.h>
+#include <arch/acpi.h>
+#include <arch/acpigen.h>
+#include <device/pci_ops.h>
+#include <arch/ioapic.h>
+#include <cpu/x86/smm.h>
+#include <cbmem.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <amdblocks/acpimmio.h>
+#include <amdblocks/acpi.h>
+#include <soc/acpi.h>
+#include <soc/pci_devs.h>
+#include <soc/southbridge.h>
+#include <soc/northbridge.h>
+#include <soc/nvs.h>
+#include <soc/gpio.h>
+#include <version.h>
+
+unsigned long acpi_fill_madt(unsigned long current)
+{
+ /* create all subtables for processors */
+ current = acpi_create_madt_lapics(current);
+
+ /* Write Kern IOAPIC, only one */
+ current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *)current,
+ CONFIG_MAX_CPUS, IO_APIC_ADDR, 0);
+
+ current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *)current,
+ CONFIG_MAX_CPUS+1, IO_APIC2_ADDR, 24);
+
+ /* 0: mean bus 0--->ISA */
+ /* 0: PIC 0 */
+ /* 2: APIC 2 */
+ /* 5 mean: 0101 --> Edge-triggered, Active high */
+ current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
+ current, 0, 0, 2, 0);
+ current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
+ current, 0, 9, 9, 0xf);
+
+ /* create all subtables for processors */
+ current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)current,
+ 0xff, 5, 1);
+ /* 1: LINT1 connect to NMI */
+
+ return current;
+}
+
+/*
+ * Reference section 5.2.9 Fixed ACPI Description Table (FADT)
+ * in the ACPI 3.0b specification.
+ */
+void acpi_create_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt)
+{
+ acpi_header_t *header = &(fadt->header);
+
+ printk(BIOS_DEBUG, "pm_base: 0x%04x\n", STONEYRIDGE_ACPI_IO_BASE);
+
+ /* Prepare the header */
+ memset((void *)fadt, 0, sizeof(acpi_fadt_t));
+ memcpy(header->signature, "FACP", 4);
+ header->length = sizeof(acpi_fadt_t);
+ header->revision = get_acpi_table_revision(FADT);
+ 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 = asl_revision;
+
+ fadt->firmware_ctrl = (u32) facs;
+ fadt->dsdt = (u32) dsdt;
+ fadt->reserved = 0; /* reserved, should be 0 ACPI 3.0 */
+ fadt->preferred_pm_profile = FADT_PM_PROFILE;
+ fadt->sci_int = 9; /* IRQ 09 - ACPI SCI */
+
+ if (CONFIG(HAVE_SMI_HANDLER)) {
+ fadt->smi_cmd = APM_CNT;
+ fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
+ fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
+ fadt->s4bios_req = 0; /* Not supported */
+ fadt->pstate_cnt = 0; /* Not supported */
+ fadt->cst_cnt = 0; /* Not supported */
+ acpi_disable_sci();
+ } else {
+ fadt->smi_cmd = 0; /* disable system management mode */
+ fadt->acpi_enable = 0; /* unused if SMI_CMD = 0 */
+ fadt->acpi_disable = 0; /* unused if SMI_CMD = 0 */
+ fadt->s4bios_req = 0; /* unused if SMI_CMD = 0 */
+ fadt->pstate_cnt = 0; /* unused if SMI_CMD = 0 */
+ fadt->cst_cnt = 0x00; /* unused if SMI_CMD = 0 */
+ acpi_enable_sci();
+ }
+
+ fadt->pm1a_evt_blk = ACPI_PM_EVT_BLK;
+ fadt->pm1b_evt_blk = 0x0000;
+ fadt->pm1a_cnt_blk = ACPI_PM1_CNT_BLK;
+ fadt->pm1b_cnt_blk = 0x0000;
+ fadt->pm2_cnt_blk = 0x0000;
+ fadt->pm_tmr_blk = ACPI_PM_TMR_BLK;
+ fadt->gpe0_blk = ACPI_GPE0_BLK;
+ fadt->gpe1_blk = 0x0000; /* No gpe1 block */
+
+ fadt->pm1_evt_len = 4; /* 32 bits */
+ fadt->pm1_cnt_len = 2; /* 16 bits */
+ fadt->pm2_cnt_len = 0;
+ fadt->pm_tmr_len = 4; /* 32 bits */
+ fadt->gpe0_blk_len = 8; /* 64 bits */
+ fadt->gpe1_blk_len = 0;
+ fadt->gpe1_base = 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; /* CLK_VAL bits 3:1 */
+ fadt->duty_width = 3; /* CLK_VAL bits 3:1 */
+ fadt->day_alrm = 0; /* 0x7d these have to be */
+ fadt->mon_alrm = 0; /* 0x7e added to cmos.layout */
+ fadt->century = 0; /* 0x7f to make rtc alarm work */
+ fadt->iapc_boot_arch = FADT_BOOT_ARCH; /* See table 5-10 */
+ fadt->res2 = 0; /* reserved, MUST be 0 ACPI 3.0 */
+ fadt->flags = ACPI_FADT_WBINVD | /* See table 5-10 ACPI 3.0a spec */
+ ACPI_FADT_C1_SUPPORTED |
+ ACPI_FADT_SLEEP_BUTTON |
+ ACPI_FADT_S4_RTC_WAKE |
+ ACPI_FADT_32BIT_TIMER |
+ ACPI_FADT_RESET_REGISTER |
+ ACPI_FADT_PCI_EXPRESS_WAKE |
+ ACPI_FADT_PLATFORM_CLOCK |
+ ACPI_FADT_S4_RTC_VALID |
+ ACPI_FADT_REMOTE_POWER_ON;
+
+ /* Format is from 5.2.3.1: Generic Address Structure */
+ /* reset_reg: see section 4.7.3.6 ACPI 3.0a spec */
+ /* 8 bit write of value 0x06 to 0xCF9 in IO space */
+ 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 = SYS_RESET;
+ fadt->reset_reg.addrh = 0x0;
+
+ fadt->reset_value = 6;
+
+ fadt->ARM_boot_arch = 0; /* MUST be 0 ACPI 3.0 */
+ fadt->FADT_MinorVersion = 0; /* MUST be 0 ACPI 3.0 */
+
+ fadt->x_firmware_ctl_l = 0; /* set to 0 if firmware_ctrl is used */
+ fadt->x_firmware_ctl_h = 0;
+ fadt->x_dsdt_l = (u32) dsdt;
+ fadt->x_dsdt_h = 0;
+
+ 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_WORD_ACCESS;
+ fadt->x_pm1a_evt_blk.addrl = ACPI_PM_EVT_BLK;
+ fadt->x_pm1a_evt_blk.addrh = 0x0;
+
+ 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 = 0x0;
+ fadt->x_pm1b_evt_blk.addrh = 0x0;
+
+
+ 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 = 0;
+ fadt->x_pm1a_cnt_blk.addrl = ACPI_PM1_CNT_BLK;
+ fadt->x_pm1a_cnt_blk.addrh = 0x0;
+
+ 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 = 0x0;
+ fadt->x_pm1b_cnt_blk.addrh = 0x0;
+
+ /*
+ * Note: Under this current AMD C state implementation, this is no
+ * longer used and should not be reported to OS.
+ */
+ fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm2_cnt_blk.bit_width = 0;
+ 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 = 0;
+ fadt->x_pm2_cnt_blk.addrh = 0x0;
+
+
+ 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 = ACPI_PM_TMR_BLK;
+ fadt->x_pm_tmr_blk.addrh = 0x0;
+
+
+ fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_gpe0_blk.bit_width = 64; /* EventStatus + Event Enable */
+ fadt->x_gpe0_blk.bit_offset = 0;
+ fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+ fadt->x_gpe0_blk.addrl = ACPI_GPE0_BLK;
+ fadt->x_gpe0_blk.addrh = 0x0;
+
+
+ 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 = 0;
+ fadt->x_gpe1_blk.addrh = 0x0;
+
+ header->checksum = acpi_checksum((void *)fadt, sizeof(acpi_fadt_t));
+}
+
+void generate_cpu_entries(struct device *device)
+{
+ int cores, cpu;
+
+ /* Stoney Ridge is single node, just report # of cores */
+ cores = pci_read_config32(SOC_NB_DEV, NB_CAPABILITIES2) & CMP_CAP_MASK;
+ cores++; /* number of cores is CmpCap+1 */
+
+ printk(BIOS_DEBUG, "ACPI \\_PR report %d core(s)\n", cores);
+
+ /* Generate BSP \_PR.P000 */
+ acpigen_write_processor(0, ACPI_GPE0_BLK, 6);
+ acpigen_pop_len();
+
+ /* Generate AP \_PR.Pxxx */
+ for (cpu = 1; cpu < cores; cpu++) {
+ acpigen_write_processor(cpu, 0, 0);
+ acpigen_pop_len();
+ }
+}
+
+unsigned long southbridge_write_acpi_tables(struct device *device,
+ unsigned long current,
+ struct acpi_rsdp *rsdp)
+{
+ return acpi_write_hpet(device, current, rsdp);
+}
+
+static void acpi_create_gnvs(struct global_nvs_t *gnvs)
+{
+ /* Clear out GNVS. */
+ memset(gnvs, 0, sizeof(*gnvs));
+
+ if (CONFIG(CONSOLE_CBMEM))
+ gnvs->cbmc = (uintptr_t)cbmem_find(CBMEM_ID_CONSOLE);
+
+ if (CONFIG(CHROMEOS)) {
+ /* Initialize Verified Boot data */
+ chromeos_init_chromeos_acpi(&gnvs->chromeos);
+ gnvs->chromeos.vbt2 = ACTIVE_ECFW_RO;
+ }
+
+ /* Set unknown wake source */
+ gnvs->pm1i = ~0ULL;
+ gnvs->gpei = ~0ULL;
+
+ /* CPU core count */
+ gnvs->pcnt = dev_count_cpu();
+}
+
+void southbridge_inject_dsdt(struct device *device)
+{
+ struct global_nvs_t *gnvs;
+
+ gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
+
+ if (gnvs) {
+ acpi_create_gnvs(gnvs);
+
+ /* Add it to DSDT */
+ acpigen_write_scope("\\");
+ acpigen_write_name_dword("NVSA", (uintptr_t)gnvs);
+ acpigen_pop_len();
+ }
+}
+
+static void acpigen_soc_get_gpio_in_local5(uintptr_t addr)
+{
+ /*
+ * Store (\_SB.GPR2 (addr), Local5)
+ * \_SB.GPR2 is used to read control byte 2 from control register.
+ * / It is defined in gpio_lib.asl.
+ */
+ acpigen_write_store();
+ acpigen_emit_namestring("\\_SB.GPR2");
+ acpigen_write_integer(addr);
+ acpigen_emit_byte(LOCAL5_OP);
+}
+
+static int acpigen_soc_get_gpio_val(unsigned int gpio_num, uint32_t mask)
+{
+ if (gpio_num >= SOC_GPIO_TOTAL_PINS) {
+ printk(BIOS_WARNING, "Warning: Pin %d should be smaller than"
+ " %d\n", gpio_num, SOC_GPIO_TOTAL_PINS);
+ return -1;
+ }
+ uintptr_t addr = (uintptr_t) gpio_get_address(gpio_num);
+
+ acpigen_soc_get_gpio_in_local5(addr);
+
+ /* If (And (Local5, mask)) */
+ acpigen_write_if_and(LOCAL5_OP, mask);
+
+ /* Store (One, Local0) */
+ acpigen_write_store_ops(ONE_OP, LOCAL0_OP);
+
+ acpigen_pop_len(); /* If */
+
+ /* Else */
+ acpigen_write_else();
+
+ /* Store (Zero, Local0) */
+ acpigen_write_store_ops(ZERO_OP, LOCAL0_OP);
+
+ acpigen_pop_len(); /* Else */
+
+ return 0;
+}
+
+static int acpigen_soc_set_gpio_val(unsigned int gpio_num, uint32_t val)
+{
+ if (gpio_num >= SOC_GPIO_TOTAL_PINS) {
+ printk(BIOS_WARNING, "Warning: Pin %d should be smaller than"
+ " %d\n", gpio_num, SOC_GPIO_TOTAL_PINS);
+ return -1;
+ }
+ uintptr_t addr = (uintptr_t) gpio_get_address(gpio_num);
+
+ /* Store (0x40, Local0) */
+ acpigen_write_store();
+ acpigen_write_integer(GPIO_PIN_OUT);
+ acpigen_emit_byte(LOCAL0_OP);
+
+ acpigen_soc_get_gpio_in_local5(addr);
+
+ if (val) {
+ /* Or (Local5, GPIO_PIN_OUT, Local5) */
+ acpigen_write_or(LOCAL5_OP, LOCAL0_OP, LOCAL5_OP);
+ } else {
+ /* Not (GPIO_PIN_OUT, Local6) */
+ acpigen_write_not(LOCAL0_OP, LOCAL6_OP);
+
+ /* And (Local5, Local6, Local5) */
+ acpigen_write_and(LOCAL5_OP, LOCAL6_OP, LOCAL5_OP);
+ }
+
+ /*
+ * SB.GPW2 (addr, Local5)
+ * \_SB.GPW2 is used to write control byte in control register
+ * / byte 2. It is defined in gpio_lib.asl.
+ */
+ acpigen_emit_namestring("\\_SB.GPW2");
+ acpigen_write_integer(addr);
+ acpigen_emit_byte(LOCAL5_OP);
+
+ return 0;
+}
+
+int acpigen_soc_read_rx_gpio(unsigned int gpio_num)
+{
+ return acpigen_soc_get_gpio_val(gpio_num, GPIO_PIN_IN);
+}
+
+int acpigen_soc_get_tx_gpio(unsigned int gpio_num)
+{
+ return acpigen_soc_get_gpio_val(gpio_num, GPIO_PIN_OUT);
+}
+
+int acpigen_soc_set_tx_gpio(unsigned int gpio_num)
+{
+ return acpigen_soc_set_gpio_val(gpio_num, 1);
+}
+
+int acpigen_soc_clear_tx_gpio(unsigned int gpio_num)
+{
+ return acpigen_soc_set_gpio_val(gpio_num, 0);
+}
diff --git a/src/soc/amd/picasso/acpi/acpi_wake_source.asl b/src/soc/amd/picasso/acpi/acpi_wake_source.asl
new file mode 100644
index 0000000000..fa01802618
--- /dev/null
+++ b/src/soc/amd/picasso/acpi/acpi_wake_source.asl
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 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.
+ */
+
+Scope (\_SB)
+{
+ Method (_SWS)
+ {
+ /* Index into PM1 for device that caused wake */
+ Return (\PM1I)
+ }
+}
+
+Scope (\_GPE)
+{
+ Method (_SWS)
+ {
+ /* Index into GPE for device that caused wake */
+ Return (\GPEI)
+ }
+}
diff --git a/src/soc/amd/picasso/acpi/cpu.asl b/src/soc/amd/picasso/acpi/cpu.asl
new file mode 100644
index 0000000000..414326ecf1
--- /dev/null
+++ b/src/soc/amd/picasso/acpi/cpu.asl
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Sage Electronic Engineering, LLC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/* Required function by EC, Notify OS to re-read CPU tables */
+Method (PNOT)
+{
+}
+
+/*
+ * Processor Object
+ */
+/* These devices are created at runtime */
+External (\_PR.P000, DeviceObj)
+External (\_PR.P001, DeviceObj)
+External (\_PR.P002, DeviceObj)
+External (\_PR.P003, DeviceObj)
+External (\_PR.P004, DeviceObj)
+External (\_PR.P005, DeviceObj)
+External (\_PR.P006, DeviceObj)
+External (\_PR.P007, DeviceObj)
+
+/* Return a package containing enabled processor entries */
+Method (PPKG)
+{
+ If (LGreaterEqual (\PCNT, 2)) {
+ Return (Package ()
+ {
+ \_PR.P000,
+ \_PR.P001
+ })
+ } Else {
+ Return (Package ()
+ {
+ \_PR.P000
+ })
+ }
+}
diff --git a/src/soc/amd/picasso/acpi/globalnvs.asl b/src/soc/amd/picasso/acpi/globalnvs.asl
new file mode 100644
index 0000000000..03d205f8d3
--- /dev/null
+++ b/src/soc/amd/picasso/acpi/globalnvs.asl
@@ -0,0 +1,77 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
+ *
+ * This program is free software; 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.
+ */
+
+/*
+ * NOTE: The layout of the GNVS structure below must match the layout in
+ * soc/amd/stoneyridge/include/soc/nvs.h !!!
+ *
+ */
+
+External (NVSA)
+
+OperationRegion (GNVS, SystemMemory, NVSA, 0x1000)
+Field (GNVS, ByteAcc, NoLock, Preserve)
+{
+ /* Miscellaneous */
+ Offset (0x00),
+ PCNT, 8, // 0x00 - Processor Count
+ PPCM, 8, // 0x01 - Max PPC State
+ LIDS, 8, // 0x02 - LID State
+ PWRS, 8, // 0x03 - AC Power State
+ DPTE, 8, // 0x04 - Enable DPTF
+ CBMC, 32, // 0x05 - 0x08 - coreboot Memory Console
+ PM1I, 64, // 0x09 - 0x10 - System Wake Source - PM1 Index
+ GPEI, 64, // 0x11 - 0x18 - GPE Wake Source
+ NHLA, 64, // 0x19 - 0x20 - NHLT Address
+ NHLL, 32, // 0x21 - 0x24 - NHLT Length
+ PRT0, 32, // 0x25 - 0x28 - PERST_0 Address
+ SCDP, 8, // 0x29 - SD_CD GPIO portid
+ SCDO, 8, // 0x2A - GPIO pad offset relative to the community
+ TMPS, 8, // 0x2B - Temperature Sensor ID
+ TLVL, 8, // 0x2C - Throttle Level Limit
+ FLVL, 8, // 0x2D - Current FAN Level
+ TCRT, 8, // 0x2E - Critical Threshold
+ TPSV, 8, // 0x2F - Passive Threshold
+ TMAX, 8, // 0x30 - CPU Tj_max
+ Offset (0x34), // 0x34 - AOAC Device Enables
+ , 5,
+ IC0E, 1, // I2C0, 5
+ IC1E, 1, // I2C1, 6
+ IC2E, 1, // I2C2, 7
+ IC3E, 1, // I2C3, 8
+ , 2,
+ UT0E, 1, // UART0, 11
+ UT1E, 1, // UART1, 12
+ , 2,
+ ST_E, 1, // SATA, 15
+ , 2,
+ EHCE, 1, // EHCI, 18
+ , 4,
+ XHCE, 1, // XCHI, 23
+ SD_E, 1, // SD, 24
+ , 2,
+ ESPI, 1, // ESPI, 27
+ , 4,
+ FW00, 16, // 0x38 - xHCI FW ROM addr, boot RAM
+ FW02, 16, // 0x3A - xHCI FW ROM addr, Instruction RAM
+ FW01, 32, // 0x3C - xHCI FW RAM addr, boot RAM
+ FW03, 32, // 0x40 - xHCI FW RAM addr, Instruction RAM
+ EH10, 32, // 0x44 - EHCI BAR
+ /* ChromeOS stuff (0x100 -> 0xfff, size 0xeff) */
+ Offset (0x100),
+ #include <vendorcode/google/chromeos/acpi/gnvs.asl>
+}
diff --git a/src/soc/amd/picasso/acpi/northbridge.asl b/src/soc/amd/picasso/acpi/northbridge.asl
new file mode 100644
index 0000000000..fe78534403
--- /dev/null
+++ b/src/soc/amd/picasso/acpi/northbridge.asl
@@ -0,0 +1,134 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Sage Electronic Engineering, LLC
+ * Copyright (C) 2016 Advanced Micro Devices, 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.
+ */
+
+/* Note: Only need HID on Primary Bus */
+External (TOM1)
+External (TOM2)
+Name(_HID, EISAID("PNP0A08")) /* PCI Express Root Bridge */
+Name(_CID, EISAID("PNP0A03")) /* PCI Root Bridge */
+Name(_ADR, 0x00180000) /* Dev# = BSP Dev#, Func# = 0 */
+
+/* Describe the Northbridge devices */
+
+Method(_BBN, 0, NotSerialized) /* Bus number = 0 */
+{
+ Return(Zero)
+}
+
+Method(_STA, 0, NotSerialized)
+{
+ Return(0x0B) /* Status is visible */
+}
+
+Method(_PRT,0, NotSerialized)
+{
+ If(PMOD)
+ {
+ Return(APR0) /* APIC mode */
+ }
+ Return (PR0) /* PIC Mode */
+}
+
+Device(AMRT) {
+ Name(_ADR, 0x00000000)
+} /* end AMRT */
+
+/* Internal Graphics */
+Device(IGFX) {
+ Name(_ADR, 0x00010000)
+}
+
+/* Gpp 0 */
+Device(PBR4) {
+ Name(_ADR, 0x00020001)
+ Method(_PRT,0) {
+ If(PMOD){ Return(APS4) } /* APIC mode */
+ Return (PS4) /* PIC Mode */
+ } /* end _PRT */
+} /* end PBR4 */
+
+/* Gpp 1 */
+Device(PBR5) {
+ Name(_ADR, 0x00020002)
+ Method(_PRT,0) {
+ If(PMOD){ Return(APS5) } /* APIC mode */
+ Return (PS5) /* PIC Mode */
+ } /* end _PRT */
+} /* end PBR5 */
+
+/* Gpp 2 */
+Device(PBR6) {
+ Name(_ADR, 0x00020003)
+ Method(_PRT,0) {
+ If(PMOD){ Return(APS6) } /* APIC mode */
+ Return (PS6) /* PIC Mode */
+ } /* end _PRT */
+} /* end PBR6 */
+
+/* Gpp 3 */
+Device(PBR7) {
+ Name(_ADR, 0x00020004)
+ Method(_PRT,0) {
+ If(PMOD){ Return(APS7) } /* APIC mode */
+ Return (PS7) /* PIC Mode */
+ } /* end _PRT */
+} /* end PBR7 */
+
+/* Gpp 4 */
+Device(PBR8) {
+ Name(_ADR, 0x00020005)
+ Method(_PRT,0) {
+ If(PMOD){ Return(APS8) } /* APIC mode */
+ Return (PS8) /* PIC Mode */
+ } /* end _PRT */
+} /* end PBR8 */
+
+Device(AZHD) { /* 0:9.2 - HD Audio */
+ Name(_ADR, 0x00090002)
+ OperationRegion(AZPD, PCI_Config, 0x00, 0x100)
+ Field(AZPD, AnyAcc, NoLock, Preserve) {
+ offset (0x42),
+ NSDI, 1,
+ NSDO, 1,
+ NSEN, 1,
+ offset (0x44),
+ IPCR, 4,
+ offset (0x54),
+ PWST, 2,
+ , 6,
+ PMEB, 1,
+ , 6,
+ PMST, 1,
+ offset (0x62),
+ MMCR, 1,
+ offset (0x64),
+ MMLA, 32,
+ offset (0x68),
+ MMHA, 32,
+ offset (0x6c),
+ MMDT, 16,
+ }
+
+ Method (_INI, 0, NotSerialized)
+ {
+ If (LEqual (OSVR, 0x03))
+ {
+ Store (Zero, NSEN)
+ Store (One, NSDO)
+ Store (One, NSDI)
+ }
+ }
+} /* end AZHD */
diff --git a/src/soc/amd/picasso/acpi/pci_int.asl b/src/soc/amd/picasso/acpi/pci_int.asl
new file mode 100644
index 0000000000..617b9eb86c
--- /dev/null
+++ b/src/soc/amd/picasso/acpi/pci_int.asl
@@ -0,0 +1,469 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Sage Electronic Engineering, LLC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+ /* PCIe Configuration Space for CONFIG_MMCONF_BUS_NUMBER busses */
+ OperationRegion(PCFG, SystemMemory, PCBA, PCLN) /* Each bus consumes 1MB */
+ Field(PCFG, ByteAcc, NoLock, Preserve) {
+ /* Byte offsets are computed using the following technique:
+ * ((bus number + 1) * ((device number * 8) * 4096)) + register offset
+ * The 8 comes from 8 functions per device, and 4096 bytes per function config space
+ */
+ Offset(0x00088024), /* Byte offset to SATA register 24h - Bus 0, Device 17, Function 0 */
+ STB5, 32,
+ Offset(0x00098042), /* Byte offset to OHCI0 register 42h - Bus 0, Device 19, Function 0 */
+ PT0D, 1,
+ PT1D, 1,
+ PT2D, 1,
+ PT3D, 1,
+ PT4D, 1,
+ PT5D, 1,
+ PT6D, 1,
+ PT7D, 1,
+ PT8D, 1,
+ PT9D, 1,
+ Offset(0x000a0004), /* Byte offset to SMBUS register 4h - Bus 0, Device 20, Function 0 */
+ SBIE, 1,
+ SBME, 1,
+ Offset(0x000a0008), /* Byte offset to SMBUS register 8h - Bus 0, Device 20, Function 0 */
+ SBRI, 8,
+ Offset(0x000a0014), /* Byte offset to SMBUS register 14h - Bus 0, Device 20, Function 0 */
+ SBB1, 32,
+ Offset(0x000a0078), /* Byte offset to SMBUS register 78h - Bus 0, Device 20, Function 0 */
+ ,14,
+ P92E, 1, /* Port92 decode enable */
+ }
+
+ OperationRegion(SB5, SystemMemory, STB5, 0x1000)
+ Field(SB5, AnyAcc, NoLock, Preserve){
+ /* Port 0 */
+ Offset(0x120), /* Port 0 Task file status */
+ P0ER, 1,
+ , 2,
+ P0DQ, 1,
+ , 3,
+ P0BY, 1,
+ Offset(0x128), /* Port 0 Serial ATA status */
+ P0DD, 4,
+ , 4,
+ P0IS, 4,
+ Offset(0x12c), /* Port 0 Serial ATA control */
+ P0DI, 4,
+ Offset(0x130), /* Port 0 Serial ATA error */
+ , 16,
+ P0PR, 1,
+
+ /* Port 1 */
+ offset(0x1a0), /* Port 1 Task file status */
+ P1ER, 1,
+ , 2,
+ P1DQ, 1,
+ , 3,
+ P1BY, 1,
+ Offset(0x1a8), /* Port 1 Serial ATA status */
+ P1DD, 4,
+ , 4,
+ P1IS, 4,
+ Offset(0x1ac), /* Port 1 Serial ATA control */
+ P1DI, 4,
+ Offset(0x1b0), /* Port 1 Serial ATA error */
+ , 16,
+ P1PR, 1,
+
+ /* Port 2 */
+ Offset(0x220), /* Port 2 Task file status */
+ P2ER, 1,
+ , 2,
+ P2DQ, 1,
+ , 3,
+ P2BY, 1,
+ Offset(0x228), /* Port 2 Serial ATA status */
+ P2DD, 4,
+ , 4,
+ P2IS, 4,
+ Offset(0x22c), /* Port 2 Serial ATA control */
+ P2DI, 4,
+ Offset(0x230), /* Port 2 Serial ATA error */
+ , 16,
+ P2PR, 1,
+
+ /* Port 3 */
+ Offset(0x2a0), /* Port 3 Task file status */
+ P3ER, 1,
+ , 2,
+ P3DQ, 1,
+ , 3,
+ P3BY, 1,
+ Offset(0x2a8), /* Port 3 Serial ATA status */
+ P3DD, 4,
+ , 4,
+ P3IS, 4,
+ Offset(0x2aC), /* Port 3 Serial ATA control */
+ P3DI, 4,
+ Offset(0x2b0), /* Port 3 Serial ATA error */
+ , 16,
+ P3PR, 1,
+ }
+
+ Method(_PIC, 0x01, NotSerialized)
+ {
+ If (Arg0)
+ {
+ \_SB.CIRQ()
+ }
+ Store(Arg0, PMOD)
+ }
+
+ Method(CIRQ, 0x00, NotSerialized){
+ }
+
+ Name(IRQB, ResourceTemplate(){
+ IRQ(Level,ActiveLow,Shared){15}
+ })
+
+ Name(IRQP, ResourceTemplate(){
+ IRQ(Level,ActiveLow,Exclusive){3, 4, 5, 7, 10, 11, 12, 15}
+ })
+
+ Name(PITF, ResourceTemplate(){
+ IRQ(Level,ActiveLow,Exclusive){9}
+ })
+
+ Device(INTA) {
+ Name(_HID, EISAID("PNP0C0F"))
+ Name(_UID, 1)
+
+ Method(_STA, 0) {
+ if (PIRA) {
+ Return(0x0b) /* sata is invisible */
+ } else {
+ Return(0x09) /* sata is disabled */
+ }
+ } /* End Method(_SB.INTA._STA) */
+
+ Method(_DIS ,0) {
+ /* DBGO("\\_SB\\LNKA\\_DIS\n") */
+ } /* End Method(_SB.INTA._DIS) */
+
+ Method(_PRS ,0) {
+ /* DBGO("\\_SB\\LNKA\\_PRS\n") */
+ Return(IRQP)
+ } /* Method(_SB.INTA._PRS) */
+
+ Method(_CRS ,0) {
+ /* DBGO("\\_SB\\LNKA\\_CRS\n") */
+ CreateWordField(IRQB, 0x1, IRQN)
+ ShiftLeft(1, PIRA, IRQN)
+ Return(IRQB)
+ } /* Method(_SB.INTA._CRS) */
+
+ Method(_SRS, 1) {
+ /* DBGO("\\_SB\\LNKA\\_SRS\n") */
+ CreateWordField(ARG0, 1, IRQM)
+
+ /* Use lowest available IRQ */
+ FindSetRightBit(IRQM, Local0)
+ if (Local0) {
+ Decrement(Local0)
+ }
+ Store(Local0, PIRA)
+ } /* End Method(_SB.INTA._SRS) */
+ } /* End Device(INTA) */
+
+ Device(INTB) {
+ Name(_HID, EISAID("PNP0C0F"))
+ Name(_UID, 2)
+
+ Method(_STA, 0) {
+ if (PIRB) {
+ Return(0x0b) /* sata is invisible */
+ } else {
+ Return(0x09) /* sata is disabled */
+ }
+ } /* End Method(_SB.INTB._STA) */
+
+ Method(_DIS ,0) {
+ /* DBGO("\\_SB\\LNKB\\_DIS\n") */
+ } /* End Method(_SB.INTB._DIS) */
+
+ Method(_PRS ,0) {
+ /* DBGO("\\_SB\\LNKB\\_PRS\n") */
+ Return(IRQP)
+ } /* Method(_SB.INTB._PRS) */
+
+ Method(_CRS ,0) {
+ /* DBGO("\\_SB\\LNKB\\_CRS\n") */
+ CreateWordField(IRQB, 0x1, IRQN)
+ ShiftLeft(1, PIRB, IRQN)
+ Return(IRQB)
+ } /* Method(_SB.INTB._CRS) */
+
+ Method(_SRS, 1) {
+ /* DBGO("\\_SB\\LNKB\\_CRS\n") */
+ CreateWordField(ARG0, 1, IRQM)
+
+ /* Use lowest available IRQ */
+ FindSetRightBit(IRQM, Local0)
+ if (Local0) {
+ Decrement(Local0)
+ }
+ Store(Local0, PIRB)
+ } /* End Method(_SB.INTB._SRS) */
+ } /* End Device(INTB) */
+
+ Device(INTC) {
+ Name(_HID, EISAID("PNP0C0F"))
+ Name(_UID, 3)
+
+ Method(_STA, 0) {
+ if (PIRC) {
+ Return(0x0b) /* sata is invisible */
+ } else {
+ Return(0x09) /* sata is disabled */
+ }
+ } /* End Method(_SB.INTC._STA) */
+
+ Method(_DIS ,0) {
+ /* DBGO("\\_SB\\LNKC\\_DIS\n") */
+ } /* End Method(_SB.INTC._DIS) */
+
+ Method(_PRS ,0) {
+ /* DBGO("\\_SB\\LNKC\\_PRS\n") */
+ Return(IRQP)
+ } /* Method(_SB.INTC._PRS) */
+
+ Method(_CRS ,0) {
+ /* DBGO("\\_SB\\LNKC\\_CRS\n") */
+ CreateWordField(IRQB, 0x1, IRQN)
+ ShiftLeft(1, PIRC, IRQN)
+ Return(IRQB)
+ } /* Method(_SB.INTC._CRS) */
+
+ Method(_SRS, 1) {
+ /* DBGO("\\_SB\\LNKC\\_CRS\n") */
+ CreateWordField(ARG0, 1, IRQM)
+
+ /* Use lowest available IRQ */
+ FindSetRightBit(IRQM, Local0)
+ if (Local0) {
+ Decrement(Local0)
+ }
+ Store(Local0, PIRC)
+ } /* End Method(_SB.INTC._SRS) */
+ } /* End Device(INTC) */
+
+ Device(INTD) {
+ Name(_HID, EISAID("PNP0C0F"))
+ Name(_UID, 4)
+
+ Method(_STA, 0) {
+ if (PIRD) {
+ Return(0x0b) /* sata is invisible */
+ } else {
+ Return(0x09) /* sata is disabled */
+ }
+ } /* End Method(_SB.INTD._STA) */
+
+ Method(_DIS ,0) {
+ /* DBGO("\\_SB\\LNKD\\_DIS\n") */
+ } /* End Method(_SB.INTD._DIS) */
+
+ Method(_PRS ,0) {
+ /* DBGO("\\_SB\\LNKD\\_PRS\n") */
+ Return(IRQP)
+ } /* Method(_SB.INTD._PRS) */
+
+ Method(_CRS ,0) {
+ /* DBGO("\\_SB\\LNKD\\_CRS\n") */
+ CreateWordField(IRQB, 0x1, IRQN)
+ ShiftLeft(1, PIRD, IRQN)
+ Return(IRQB)
+ } /* Method(_SB.INTD._CRS) */
+
+ Method(_SRS, 1) {
+ /* DBGO("\\_SB\\LNKD\\_CRS\n") */
+ CreateWordField(ARG0, 1, IRQM)
+
+ /* Use lowest available IRQ */
+ FindSetRightBit(IRQM, Local0)
+ if (Local0) {
+ Decrement(Local0)
+ }
+ Store(Local0, PIRD)
+ } /* End Method(_SB.INTD._SRS) */
+ } /* End Device(INTD) */
+
+ Device(INTE) {
+ Name(_HID, EISAID("PNP0C0F"))
+ Name(_UID, 5)
+
+ Method(_STA, 0) {
+ if (PIRE) {
+ Return(0x0b) /* sata is invisible */
+ } else {
+ Return(0x09) /* sata is disabled */
+ }
+ } /* End Method(_SB.INTE._STA) */
+
+ Method(_DIS ,0) {
+ /* DBGO("\\_SB\\LNKE\\_DIS\n") */
+ } /* End Method(_SB.INTE._DIS) */
+
+ Method(_PRS ,0) {
+ /* DBGO("\\_SB\\LNKE\\_PRS\n") */
+ Return(IRQP)
+ } /* Method(_SB.INTE._PRS) */
+
+ Method(_CRS ,0) {
+ /* DBGO("\\_SB\\LNKE\\_CRS\n") */
+ CreateWordField(IRQB, 0x1, IRQN)
+ ShiftLeft(1, PIRE, IRQN)
+ Return(IRQB)
+ } /* Method(_SB.INTE._CRS) */
+
+ Method(_SRS, 1) {
+ /* DBGO("\\_SB\\LNKE\\_CRS\n") */
+ CreateWordField(ARG0, 1, IRQM)
+
+ /* Use lowest available IRQ */
+ FindSetRightBit(IRQM, Local0)
+ if (Local0) {
+ Decrement(Local0)
+ }
+ Store(Local0, PIRE)
+ } /* End Method(_SB.INTE._SRS) */
+ } /* End Device(INTE) */
+
+ Device(INTF) {
+ Name(_HID, EISAID("PNP0C0F"))
+ Name(_UID, 6)
+
+ Method(_STA, 0) {
+ if (PIRF) {
+ Return(0x0b) /* sata is invisible */
+ } else {
+ Return(0x09) /* sata is disabled */
+ }
+ } /* End Method(_SB.INTF._STA) */
+
+ Method(_DIS ,0) {
+ /* DBGO("\\_SB\\LNKF\\_DIS\n") */
+ } /* End Method(_SB.INTF._DIS) */
+
+ Method(_PRS ,0) {
+ /* DBGO("\\_SB\\LNKF\\_PRS\n") */
+ Return(PITF)
+ } /* Method(_SB.INTF._PRS) */
+
+ Method(_CRS ,0) {
+ /* DBGO("\\_SB\\LNKF\\_CRS\n") */
+ CreateWordField(IRQB, 0x1, IRQN)
+ ShiftLeft(1, PIRF, IRQN)
+ Return(IRQB)
+ } /* Method(_SB.INTF._CRS) */
+
+ Method(_SRS, 1) {
+ /* DBGO("\\_SB\\LNKF\\_CRS\n") */
+ CreateWordField(ARG0, 1, IRQM)
+
+ /* Use lowest available IRQ */
+ FindSetRightBit(IRQM, Local0)
+ if (Local0) {
+ Decrement(Local0)
+ }
+ Store(Local0, PIRF)
+ } /* End Method(_SB.INTF._SRS) */
+ } /* End Device(INTF) */
+
+ Device(INTG) {
+ Name(_HID, EISAID("PNP0C0F"))
+ Name(_UID, 7)
+
+ Method(_STA, 0) {
+ if (PIRG) {
+ Return(0x0b) /* sata is invisible */
+ } else {
+ Return(0x09) /* sata is disabled */
+ }
+ } /* End Method(_SB.INTG._STA) */
+
+ Method(_DIS ,0) {
+ /* DBGO("\\_SB\\LNKG\\_DIS\n") */
+ } /* End Method(_SB.INTG._DIS) */
+
+ Method(_PRS ,0) {
+ /* DBGO("\\_SB\\LNKG\\_PRS\n") */
+ Return(IRQP)
+ } /* Method(_SB.INTG._CRS) */
+
+ Method(_CRS ,0) {
+ /* DBGO("\\_SB\\LNKG\\_CRS\n") */
+ CreateWordField(IRQB, 0x1, IRQN)
+ ShiftLeft(1, PIRG, IRQN)
+ Return(IRQB)
+ } /* Method(_SB.INTG._CRS) */
+
+ Method(_SRS, 1) {
+ /* DBGO("\\_SB\\LNKG\\_CRS\n") */
+ CreateWordField(ARG0, 1, IRQM)
+
+ /* Use lowest available IRQ */
+ FindSetRightBit(IRQM, Local0)
+ if (Local0) {
+ Decrement(Local0)
+ }
+ Store(Local0, PIRG)
+ } /* End Method(_SB.INTG._SRS) */
+ } /* End Device(INTG) */
+
+ Device(INTH) {
+ Name(_HID, EISAID("PNP0C0F"))
+ Name(_UID, 8)
+
+ Method(_STA, 0) {
+ if (PIRH) {
+ Return(0x0b) /* sata is invisible */
+ } else {
+ Return(0x09) /* sata is disabled */
+ }
+ } /* End Method(_SB.INTH._STA) */
+
+ Method(_DIS ,0) {
+ /* DBGO("\\_SB\\LNKH\\_DIS\n") */
+ } /* End Method(_SB.INTH._DIS) */
+
+ Method(_PRS ,0) {
+ /* DBGO("\\_SB\\LNKH\\_PRS\n") */
+ Return(IRQP)
+ } /* Method(_SB.INTH._CRS) */
+
+ Method(_CRS ,0) {
+ /* DBGO("\\_SB\\LNKH\\_CRS\n") */
+ CreateWordField(IRQB, 0x1, IRQN)
+ ShiftLeft(1, PIRH, IRQN)
+ Return(IRQB)
+ } /* Method(_SB.INTH._CRS) */
+
+ Method(_SRS, 1) {
+ /* DBGO("\\_SB\\LNKH\\_CRS\n") */
+ CreateWordField(ARG0, 1, IRQM)
+
+ /* Use lowest available IRQ */
+ FindSetRightBit(IRQM, Local0)
+ if (Local0) {
+ Decrement(Local0)
+ }
+ Store(Local0, PIRH)
+ } /* End Method(_SB.INTH._SRS) */
+ } /* End Device(INTH) */
diff --git a/src/soc/amd/picasso/acpi/pcie.asl b/src/soc/amd/picasso/acpi/pcie.asl
new file mode 100644
index 0000000000..925187209c
--- /dev/null
+++ b/src/soc/amd/picasso/acpi/pcie.asl
@@ -0,0 +1,99 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Sage Electronic Engineering, LLC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+ /* PCI IRQ mapping registers, C00h-C01h. */
+ OperationRegion(PRQM, SystemIO, 0x00000c00, 0x00000002)
+ Field(PRQM, ByteAcc, NoLock, Preserve) {
+ PRQI, 0x00000008,
+ PRQD, 0x00000008, /* Offset: 1h */
+ }
+ IndexField(PRQI, PRQD, ByteAcc, NoLock, Preserve) {
+ PIRA, 0x00000008, /* Index 0 */
+ PIRB, 0x00000008, /* Index 1 */
+ PIRC, 0x00000008, /* Index 2 */
+ PIRD, 0x00000008, /* Index 3 */
+ PIRE, 0x00000008, /* Index 4 */
+ PIRF, 0x00000008, /* Index 5 */
+ PIRG, 0x00000008, /* Index 6 */
+ PIRH, 0x00000008, /* Index 7 */
+ }
+
+ /* PCI Error control register */
+ OperationRegion(PERC, SystemIO, 0x00000c14, 0x00000001)
+ Field(PERC, ByteAcc, NoLock, Preserve) {
+ SENS, 0x00000001,
+ PENS, 0x00000001,
+ SENE, 0x00000001,
+ PENE, 0x00000001,
+ }
+
+ /* Client Management index/data registers */
+ OperationRegion(CMT, SystemIO, 0x00000c50, 0x00000002)
+ Field(CMT, ByteAcc, NoLock, Preserve) {
+ CMTI, 8,
+ /* Client Management Data register */
+ G64E, 1,
+ G64O, 1,
+ G32O, 2,
+ , 2,
+ GPSL, 2,
+ }
+
+ /* GPM Port register */
+ OperationRegion(GPT, SystemIO, 0x00000c52, 0x00000001)
+ Field(GPT, ByteAcc, NoLock, Preserve) {
+ GPB0,1,
+ GPB1,1,
+ GPB2,1,
+ GPB3,1,
+ GPB4,1,
+ GPB5,1,
+ GPB6,1,
+ GPB7,1,
+ }
+
+ /* Flash ROM program enable register */
+ OperationRegion(FRE, SystemIO, 0x00000c6F, 0x00000001)
+ Field(FRE, ByteAcc, NoLock, Preserve) {
+ , 0x00000006,
+ FLRE, 0x00000001,
+ }
+
+ /* PM2 index/data registers */
+ OperationRegion(PM2R, SystemIO, 0x00000Cd0, 0x00000002)
+ Field(PM2R, ByteAcc, NoLock, Preserve) {
+ PM2I, 0x00000008,
+ PM2D, 0x00000008,
+ }
+
+ /* Power Management I/O registers, TODO:PMIO is quite different in SB800. */
+ OperationRegion(PIOR, SystemIO, 0x00000Cd6, 0x00000002)
+ Field(PIOR, ByteAcc, NoLock, Preserve) {
+ PIOI, 0x00000008,
+ PIOD, 0x00000008,
+ }
+
+ IndexField (PIOI, PIOD, ByteAcc, NoLock, Preserve) {
+ Offset(0x60), /* AcpiPm1EvgBlk */
+ P1EB, 16,
+ Offset(0xee),
+ UPWS, 3,
+ }
+ OperationRegion (P1E0, SystemIO, P1EB, 0x04)
+ Field (P1E0, ByteAcc, Nolock, Preserve) {
+ Offset(0x02),
+ , 14,
+ PEWD, 1,
+ }
diff --git a/src/soc/amd/picasso/acpi/sb_fch.asl b/src/soc/amd/picasso/acpi/sb_fch.asl
new file mode 100644
index 0000000000..e7975f8d94
--- /dev/null
+++ b/src/soc/amd/picasso/acpi/sb_fch.asl
@@ -0,0 +1,153 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015-2016 Advanced Micro Devices, 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.
+ */
+
+#include <soc/gpio.h>
+#include <soc/iomap.h>
+
+Device (AAHB)
+{
+ Name (_HID, "AAHB0000")
+ Name (_UID, 0x0)
+ Name (_CRS, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, ALINK_AHB_ADDRESS, 0x2000)
+ })
+
+ Method (_STA, 0x0, NotSerialized)
+ {
+ Return (0x0F)
+ }
+}
+
+Device (GPIO)
+{
+ Name (_HID, GPIO_DEVICE_NAME)
+ Name (_CID, GPIO_DEVICE_NAME)
+ Name (_UID, 0)
+ Name (_DDN, GPIO_DEVICE_DESC)
+
+ Name (_CRS, ResourceTemplate()
+ {
+ Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , )
+ { 7 }
+ Memory32Fixed (ReadWrite, 0xFED81500, 0x300)
+ })
+
+ Method (_STA, 0x0, NotSerialized)
+ {
+ Return (0x0F)
+ }
+}
+
+Device (FUR0)
+{
+ Name (_HID, "AMD0020")
+ Name (_UID, 0x0)
+ Name (_CRS, ResourceTemplate()
+ {
+ IRQ (Edge, ActiveHigh, Exclusive) { 10 }
+ Memory32Fixed (ReadWrite, 0xFEDC6000, 0x2000)
+ })
+ Method (_STA, 0x0, NotSerialized)
+ {
+ Return (0x0F)
+ }
+}
+
+Device (FUR1) {
+ Name (_HID, "AMD0020")
+ Name (_UID, 0x1)
+ Name (_CRS, ResourceTemplate()
+ {
+ IRQ (Edge, ActiveHigh, Exclusive) { 11 }
+ Memory32Fixed (ReadWrite, 0xFEDC8000, 0x2000)
+ })
+ Method (_STA, 0x0, NotSerialized)
+ {
+ Return (0x0F)
+ }
+}
+
+Device (I2CA) {
+ Name (_HID, "AMD0010")
+ Name (_UID, 0x0)
+ Name (_CRS, ResourceTemplate()
+ {
+ IRQ (Edge, ActiveHigh, Exclusive) { 3 }
+ Memory32Fixed (ReadWrite, 0xFEDC2000, 0x1000)
+ })
+
+ Method (_STA, 0x0, NotSerialized)
+ {
+ Return (0x0F)
+ }
+}
+
+Device (I2CB)
+{
+ Name (_HID, "AMD0010")
+ Name (_UID, 0x1)
+ Name (_CRS, ResourceTemplate()
+ {
+ IRQ (Edge, ActiveHigh, Exclusive) { 15 }
+ Memory32Fixed (ReadWrite, 0xFEDC3000, 0x1000)
+ })
+ Method (_STA, 0x0, NotSerialized)
+ {
+ Return (0x0F)
+ }
+}
+
+Device (I2CC) {
+ Name (_HID, "AMD0010")
+ Name (_UID, 0x2)
+ Name (_CRS, ResourceTemplate()
+ {
+ IRQ (Edge, ActiveHigh, Exclusive) { 6 }
+ Memory32Fixed (ReadWrite, 0xFEDC4000, 0x1000)
+ })
+
+ Method (_STA, 0x0, NotSerialized)
+ {
+ Return (0x0F)
+ }
+}
+
+Device (I2CD)
+{
+ Name (_HID, "AMD0010")
+ Name (_UID, 0x3)
+ Name (_CRS, ResourceTemplate() {
+ IRQ (Edge, ActiveHigh, Exclusive) { 14 }
+ Memory32Fixed(ReadWrite, 0xFEDC5000, 0x1000)
+ })
+ Method (_STA, 0x0, NotSerialized)
+ {
+ Return (0x0F)
+ }
+}
+
+Device (MISC)
+{
+ Name (_HID, "AMD0040")
+ Name (_UID, 0x3)
+ Name (_CRS, ResourceTemplate() {
+ Memory32Fixed(ReadWrite, ACPIMMIO_MISC_BASE, 0x100)
+ })
+ Method (_STA, 0x0, NotSerialized)
+ {
+ Return (0x0F)
+ }
+}
diff --git a/src/soc/amd/picasso/acpi/sb_pci0_fch.asl b/src/soc/amd/picasso/acpi/sb_pci0_fch.asl
new file mode 100644
index 0000000000..3623814080
--- /dev/null
+++ b/src/soc/amd/picasso/acpi/sb_pci0_fch.asl
@@ -0,0 +1,619 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 Advanced Micro Devices, 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.
+ */
+
+External(\_SB.ALIB, MethodObj)
+
+/* System Bus */
+/* _SB.PCI0 */
+
+/* Operating System Capabilities Method */
+Method(_OSC,4)
+{
+ /* Check for proper PCI/PCIe UUID */
+ If(LEqual(Arg0,ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766")))
+ {
+ /* Let OS control everything */
+ Return (Arg3)
+ } Else {
+ CreateDWordField(Arg3,0,CDW1)
+ Or(CDW1,4,CDW1) // Unrecognized UUID
+ Return(Arg3)
+ }
+}
+
+/* Describe the Southbridge devices */
+
+/* 0:11.0 - SATA */
+Device(STCR) {
+ Name(_ADR, 0x00110000)
+} /* end STCR */
+
+/* 0:14.0 - SMBUS */
+Device(SBUS) {
+ Name(_ADR, 0x00140000)
+} /* end SBUS */
+
+#include "usb.asl"
+
+/* 0:14.2 - I2S Audio */
+
+/* 0:14.3 - LPC */
+#include <soc/amd/common/acpi/lpc.asl>
+
+/* 0:14.7 - SD Controller */
+Device(SDCN) {
+ Name(_ADR, 0x00140007)
+
+ Method(_PS0) {
+ FDDC(24, 0)
+ }
+ Method(_PS3) {
+ FDDC(24, 3)
+ }
+ Method(_PSC) {
+ Return(SDTD)
+ }
+} /* end SDCN */
+
+Name(CRES, ResourceTemplate() {
+ /* Set the Bus number and Secondary Bus number for the PCI0 device
+ * The Secondary bus range for PCI0 lets the system
+ * know what bus values are allowed on the downstream
+ * side of this PCI bus if there is a PCI-PCI bridge.
+ * PCI busses can have 256 secondary busses which
+ * range from [0-0xFF] but they do not need to be
+ * sequential.
+ */
+ WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
+ 0x0000, /* address granularity */
+ 0x0000, /* range minimum */
+ 0x00ff, /* range maximum */
+ 0x0000, /* translation */
+ 0x0100, /* length */
+ ,, PSB0) /* ResourceSourceIndex, ResourceSource, DescriptorName */
+
+ IO(Decode16, 0x0cf8, 0x0cf8, 1, 8)
+
+ WORDIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+ 0x0000, /* address granularity */
+ 0x0000, /* range minimum */
+ 0x0cf7, /* range maximum */
+ 0x0000, /* translation */
+ 0x0cf8 /* length */
+ )
+ WORDIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+ 0x0000, /* address granularity */
+ 0x03b0, /* range minimum */
+ 0x03df, /* range maximum */
+ 0x0000, /* translation */
+ 0x0030 /* length */
+ )
+
+ WORDIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+ 0x0000, /* address granularity */
+ 0x0d00, /* range minimum */
+ 0xffff, /* range maximum */
+ 0x0000, /* translation */
+ 0xf300 /* length */
+ )
+
+ Memory32Fixed(READONLY, 0x000a0000, 0x00020000, VGAM) /* VGA memory space */
+ Memory32Fixed(READONLY, 0x000c0000, 0x00020000, EMM1) /* Assume C0000-E0000 empty */
+
+ /* memory space for PCI BARs below 4GB */
+ Memory32Fixed(ReadOnly, 0x00000000, 0x00000000, MMIO)
+}) /* End Name(_SB.PCI0.CRES) */
+
+Method(_CRS, 0) {
+ /* DBGO("\\_SB\\PCI0\\_CRS\n") */
+ CreateDWordField(CRES, ^MMIO._BAS, MM1B)
+ CreateDWordField(CRES, ^MMIO._LEN, MM1L)
+
+ /*
+ * Declare memory between TOM1 and 4GB as available
+ * for PCI MMIO.
+ * Use ShiftLeft to avoid 64bit constant (for XP).
+ * This will work even if the OS does 32bit arithmetic, as
+ * 32bit (0x00000000 - TOM1) will wrap and give the same
+ * result as 64bit (0x100000000 - TOM1).
+ */
+ Store(TOM1, MM1B)
+ ShiftLeft(0x10000000, 4, Local0)
+ Subtract(Local0, TOM1, Local0)
+ Store(Local0, MM1L)
+
+ Return(CRES) /* note to change the Name buffer */
+} /* end of Method(_SB.PCI0._CRS) */
+
+/*
+ *
+ * FIRST METHOD CALLED UPON BOOT
+ *
+ * 1. If debugging, print current OS and ACPI interpreter.
+ * 2. Get PCI Interrupt routing from ACPI VSM, this
+ * value is based on user choice in BIOS setup.
+ */
+Method(_INI, 0, Serialized) {
+ /* DBGO("\\_SB\\_INI\n") */
+ /* DBGO(" DSDT.ASL code from ") */
+ /* DBGO(__DATE__) */
+ /* DBGO(" ") */
+ /* DBGO(__TIME__) */
+ /* DBGO("\n Sleep states supported: ") */
+ /* DBGO("\n") */
+ /* DBGO(" \\_OS=") */
+ /* DBGO(\_OS) */
+ /* DBGO("\n \\_REV=") */
+ /* DBGO(\_REV) */
+ /* DBGO("\n") */
+
+ /* Determine the OS we're running on */
+ OSFL()
+
+ /* Send ALIB Function 1 the AC/DC state */
+ Name(F1BF, Buffer(0x03){})
+ CreateWordField(F1BF, 0, F1SZ)
+ CreateByteField(F1BF, 2, F1DA)
+
+ Store(3, F1SZ)
+ Store(\PWRS, F1DA)
+
+ \_SB.ALIB(1, F1BF)
+
+} /* End Method(_SB._INI) */
+
+Method(OSFL, 0){
+
+ if (LNotEqual(OSVR, Ones)) {Return(OSVR)} /* OS version was already detected */
+
+ if (CondRefOf(\_OSI))
+ {
+ Store(1, OSVR) /* Assume some form of XP */
+ if (\_OSI("Windows 2006")) /* Vista */
+ {
+ Store(2, OSVR)
+ }
+ } else {
+ If(WCMP(\_OS,"Linux")) {
+ Store(3, OSVR) /* Linux */
+ } Else {
+ Store(4, OSVR) /* Gotta be WinCE */
+ }
+ }
+ Return(OSVR)
+}
+
+OperationRegion(SMIC, SystemMemory, 0xfed80000, 0x80000)
+Field( SMIC, ByteAcc, NoLock, Preserve) {
+ /* MISC registers */
+ offset (0x03ee),
+ U3PS, 2, /* Usb3PowerSel */
+
+ offset (0x0e28),
+ ,29 ,
+ SARP, 1, /* Sata Ref Clock Powerdown */
+ U2RP, 1, /* Usb2 Ref Clock Powerdown */
+ U3RP, 1, /* Usb3 Ref Clock Powerdown */
+
+ /* XHCI_PM registers */
+ offset (0x1c00),
+ , 1,
+ ,6,
+ U3PY, 1,
+ , 7,
+ UD3P, 1, /* bit 15 */
+ U3PR, 1, /* bit 16 */
+ , 11,
+ FWLM, 1, /* FirmWare Load Mode */
+ FPLS, 1, /* Fw PreLoad Start */
+ FPLC, 1, /* Fw PreLoad Complete */
+
+ offset (0x1c04),
+ UA04, 16,
+ , 15,
+ ROAM, 1, /* 1= ROM 0=RAM */
+
+ offset (0x1c08),
+ UA08, 32,
+
+ /* AOAC Registers */
+ offset (0x1e4a), /* I2C0 D3 Control */
+ I0TD, 2,
+ , 1,
+ I0PD, 1,
+ offset (0x1e4b), /* I2C0 D3 State */
+ I0DS, 3,
+
+ offset (0x1e4c), /* I2C1 D3 Control */
+ I1TD, 2,
+ , 1,
+ I1PD, 1,
+ offset (0x1e4d), /* I2C1 D3 State */
+ I1DS, 3,
+
+ offset (0x1e4e), /* I2C2 D3 Control */
+ I2TD, 2,
+ , 1,
+ I2PD, 1,
+ offset (0x1e4f), /* I2C2 D3 State */
+ I2DS, 3,
+
+ offset (0x1e50), /* I2C3 D3 Control */
+ I3TD, 2,
+ , 1,
+ I3PD, 1,
+ offset (0x1e51), /* I2C3 D3 State */
+ I3DS, 3,
+
+ offset (0x1e56), /* UART0 D3 Control */
+ U0TD, 2,
+ , 1,
+ U0PD, 1,
+ offset (0x1e57), /* UART0 D3 State */
+ U0DS, 3,
+
+ offset (0x1e58), /* UART1 D3 Control */
+ U1TD, 2,
+ , 1,
+ U1PD, 1,
+ offset (0x1e59), /* UART1 D3 State */
+ U1DS, 3,
+
+ offset (0x1e5e), /* SATA D3 Control */
+ SATD, 2,
+ , 1,
+ SAPD, 1,
+ offset (0x1e5f), /* SATA D3 State */
+ SADS, 3,
+
+ offset (0x1e64), /* USB2 D3 Control */
+ U2TD, 2,
+ , 1,
+ U2PD, 1,
+ offset (0x1e65), /* USB2 D3 State */
+ U2DS, 3,
+
+ offset (0x1e6e), /* USB3 D3 Control */
+ U3TD, 2,
+ , 1,
+ U3PD, 1,
+ offset (0x1e6f), /* USB3 D3 State */
+ U3DS, 3,
+
+ offset (0x1e70), /* SD D3 Control */
+ SDTD, 2,
+ , 1,
+ SDPD, 1,
+ , 1,
+ , 1,
+ SDRT, 1,
+ SDSC, 1,
+
+ offset (0x1e71), /* SD D3 State */
+ SDDS, 3,
+
+ offset (0x1e80), /* Shadow Register Request */
+ , 15,
+ RQ15, 1,
+ , 2,
+ RQ18, 1,
+ , 4,
+ RQ23, 1,
+ RQ24, 1,
+ , 5,
+ RQTY, 1,
+ offset (0x1e84), /* Shadow Register Status */
+ , 15,
+ SASR, 1, /* SATA 15 Shadow Reg Request Status Register */
+ , 2,
+ U2SR, 1, /* USB2 18 Shadow Reg Request Status Register */
+ , 4,
+ U3SR, 1, /* USB3 23 Shadow Reg Request Status Register */
+ SDSR, 1, /* SD 24 Shadow Reg Request Status Register */
+
+ offset (0x1ea0), /* PwrGood Control */
+ PG1A, 1,
+ PG2_, 1,
+ ,1,
+ U3PG, 1, /* Usb3 Power Good BIT3 */
+
+ offset (0x1ea3), /* PwrGood Control b[31:24] */
+ PGA3, 8 ,
+}
+
+OperationRegion(FCFG, SystemMemory, PCBA, 0x01000000)
+Field(FCFG, DwordAcc, NoLock, Preserve)
+{
+ /* XHCI */
+ Offset(0x00080010), /* Base address */
+ XHBA, 32,
+ Offset(0x0008002c), /* Subsystem ID / Vendor ID */
+ XH2C, 32,
+
+ Offset(0x00080048), /* Indirect PCI Index Register */
+ IDEX, 32,
+ DATA, 32,
+ Offset(0x00080054), /* PME Control / Status */
+ U_PS, 2,
+
+ /* EHCI */
+ Offset(0x00090004), /* Control */
+ , 1,
+ EHME, 1,
+ Offset(0x00090010), /* Base address */
+ EHBA, 32,
+ Offset(0x0009002c), /* Subsystem ID / Vendor ID */
+ EH2C, 32,
+ Offset(0x00090054), /* EHCI Spare 1 */
+ EH54, 8,
+ Offset(0x00090064), /* Misc Control 2 */
+ EH64, 8,
+
+ Offset(0x000900c4), /* PME Control / Status */
+ E_PS, 2,
+
+ /* LPC Bridge */
+ Offset(0x000a30cb), /* ClientRomProtect[31:24] */
+ , 7,
+ AUSS, 1, /* AutoSizeStart */
+}
+
+/*
+ * Arg0:device:
+ * 5=I2C0, 6=I2C1, 7=I2C2, 8=I2C3, 11=UART0, 12=UART1,
+ * 15=SATA, 18=EHCI, 23=xHCI, 24=SD
+ * Arg1:D-state
+ */
+Mutex (FDAS, 0) /* FCH Device AOAC Semophore */
+Method(FDDC, 2, Serialized)
+{
+ Acquire(FDAS, 0xffff)
+
+ if(LEqual(Arg1, 0)) {
+ Switch(ToInteger(Arg0)) {
+ Case(Package() {5, 15, 24}) {
+ Store(One, PG1A)
+ }
+ Case(Package() {6, 7, 8, 11, 12, 18}) {
+ Store(One, PG2_)
+ }
+ }
+ /* put device into D0 */
+ Switch(ToInteger(Arg0))
+ {
+ Case(5) {
+ Store(0x00, I0TD)
+ Store(One, I0PD)
+ Store(I0DS, Local0)
+ while(LNotEqual(Local0,0x7)) {
+ Store(I0DS, Local0)
+ }
+ }
+ Case(6) {
+ Store(0x00, I1TD)
+ Store(One, I1PD)
+ Store(I1DS, Local0)
+ while(LNotEqual(Local0,0x7)) {
+ Store(I1DS, Local0)
+ }
+ }
+ Case(7) {
+ Store(0x00, I2TD)
+ Store(One, I2PD)
+ Store(I2DS, Local0)
+ while(LNotEqual(Local0,0x7)) {
+ Store(I2DS, Local0)
+ }
+ }
+ Case(8) {Store(0x00, I3TD)
+ Store(One, I3PD)
+ Store(I3DS, Local0)
+ while(LNotEqual(Local0,0x7)) {
+ Store(I3DS, Local0)
+ }
+ }
+ Case(11) {
+ Store(0x00, U0TD)
+ Store(One, U0PD)
+ Store(U0DS, Local0)
+ while(LNotEqual(Local0,0x7)) {
+ Store(U0DS, Local0)
+ }
+ }
+ Case(12) {
+ Store(0x00, U1TD)
+ Store(One, U1PD)
+ Store(U1DS, Local0)
+ while(LNotEqual(Local0,0x7)) {
+ Store(U1DS, Local0)
+ }
+ }
+/* todo Case(15) { STD0()} */ /* SATA */
+ Case(18) { U2D0()} /* EHCI */
+ Case(23) { U3D0()} /* XHCI */
+ Case(24) { /* SD */
+ Store(0x00, SDTD)
+ Store(One, SDPD)
+ Store(SDDS, Local0)
+ while(LNotEqual(Local0,0x7)) {
+ Store(SDDS, Local0)
+ }
+ }
+ }
+ } else {
+ /* put device into D3cold */
+ Switch(ToInteger(Arg0))
+ {
+ Case(5) {
+ Store(Zero, I0PD)
+ Store(I0DS, Local0)
+ while(LNotEqual(Local0,0x0)) {
+ Store(I0DS, Local0)
+ }
+ Store(0x03, I0TD)
+ }
+ Case(6) {
+ Store(Zero, I1PD)
+ Store(I1DS, Local0)
+ while(LNotEqual(Local0,0x0)) {
+ Store(I1DS, Local0)
+ }
+ Store(0x03, I1TD)
+ }
+ Case(7) {
+ Store(Zero, I2PD)
+ Store(I2DS, Local0)
+ while(LNotEqual(Local0,0x0)) {
+ Store(I2DS, Local0)
+ }
+ Store(0x03, I2TD)}
+ Case(8) {
+ Store(Zero, I3PD)
+ Store(I3DS, Local0)
+ while(LNotEqual(Local0,0x0)) {
+ Store(I3DS, Local0)
+ }
+ Store(0x03, I3TD)
+ }
+ Case(11) {
+ Store(Zero, U0PD)
+ Store(U0DS, Local0)
+ while(LNotEqual(Local0,0x0)) {
+ Store(U0DS, Local0)
+ }
+ Store(0x03, U0TD)
+ }
+ Case(12) {
+ Store(Zero, U1PD)
+ Store(U1DS, Local0)
+ while(LNotEqual(Local0,0x0)) {
+ Store(U1DS, Local0)
+ }
+ Store(0x03, U1TD)
+ }
+/* todo Case(15) { STD3()} */ /* SATA */
+ Case(18) { U2D3()} /* EHCI */
+ Case(23) { U3D3()} /* XHCI */
+ Case(24) { /* SD */
+ Store(Zero, SDPD)
+ Store(SDDS, Local0)
+ while(LNotEqual(Local0,0x0)) {
+ Store(SDDS, Local0)
+ }
+ Store(0x03, SDTD)
+ }
+ }
+ /* Turn off Power */
+ if(LEqual(I0TD, 3)) {
+ if(LEqual(SATD, 3)) {
+ if(LEqual(SDTD, 3)) { Store(Zero, PG1A) }
+ }
+ }
+ if(LEqual(I1TD, 3)) {
+ if(LEqual(I2TD, 3)) {
+ if(LEqual(I3TD, 3)) {
+ if(LEqual(U0TD, 3)) {
+ if(LEqual(U1TD, 3)) {
+ if(LEqual(U2TD, 3)) {
+ Store(Zero, PG2_)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ Release(FDAS)
+}
+
+Method(FPTS,0, Serialized) /* FCH _PTS */
+{
+ if(LEqual(\XHCE, one)) {
+ if(LNotEqual(U3TD, 0x03)) {
+ FDDC(23, 3)
+ }
+ }
+ if(LNotEqual(U2TD, 0x03)) {
+ FDDC(18, 3)
+ }
+}
+
+Method(FWAK,0, Serialized) /* FCH _WAK */
+{
+ if(LEqual(\XHCE, one)) {
+ if(LEqual(U3TD, 0x03)) {
+ FDDC(23, 0)
+ }
+ }
+ if(LEqual(U2TD, 0x03)) {
+ FDDC(18, 0)
+ }
+ if(LEqual(\UT0E, zero)) {
+ if(LNotEqual(U0TD, 0x03)) {
+ FDDC(11, 3)
+ }
+ }
+ if(LEqual(\UT1E, zero)) {
+ if(LNotEqual(U1TD, 0x03)) {
+ FDDC(12, 3)
+ }
+ }
+ if(LEqual(\IC0E, zero)) {
+ if(LNotEqual(I0TD, 0x03)) {
+ FDDC(5, 3)
+ }
+ }
+ if(LEqual(\IC1E, zero)) {
+ if(LNotEqual(I1TD, 0x03)) {
+ FDDC(6, 3)
+ }
+ }
+ if(LEqual(\IC2E, zero)) {
+ if(LNotEqual(I2TD, 0x03)) {
+ FDDC(7, 3)
+ }
+ }
+ if(LEqual(\IC3E, zero)) {
+ if(LNotEqual(I3TD, 0x03)) {
+ FDDC(8, 3)
+ }
+ }
+}
+
+/*
+ * Helper for setting a bit in AOACxA0 PwrGood Control
+ * Arg0: bit to set or clear
+ * Arg1: 0 = clear bit[Arg0], non-zero = set bit[Arg0]
+ */
+Method(PWGC,2, Serialized)
+{
+ And (PGA3, 0xdf, Local0) /* do SwUsb3SlpShutdown below */
+ if(Arg1) {
+ Or(Arg0, Local0, Local0)
+ } else {
+ Not(Arg0, Local1)
+ And(Local1, Local0, Local0)
+ }
+ Store(Local0, PGA3)
+ if(LEqual(Arg0, 0x20)) { /* if SwUsb3SlpShutdown */
+ Store(PGA3, Local0)
+ And(Arg0, Local0, Local0)
+ while(LNot(Local0)) { /* wait SwUsb3SlpShutdown to complete */
+ Store(PGA3, Local0)
+ And(Arg0, Local0, Local0)
+ }
+ }
+}
diff --git a/src/soc/amd/picasso/acpi/sleepstates.asl b/src/soc/amd/picasso/acpi/sleepstates.asl
new file mode 100644
index 0000000000..d4aabdb7af
--- /dev/null
+++ b/src/soc/amd/picasso/acpi/sleepstates.asl
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/* S1 support: bit 0, S2 Support: bit 1, etc. S0 & S5 assumed */
+Name(SSFG, 0x09)
+If (CONFIG(HAVE_ACPI_RESUME)) {
+ Store(0x0D, SSFG)
+}
+
+/* Supported sleep states: */
+Name(\_S0, Package () {0x00, 0x00, 0x00, 0x00} ) /* (S0) - working state */
+
+If (And(SSFG, 0x01)) {
+ Name(\_S1, Package () {0x01, 0x01, 0x00, 0x00} ) /* (S1) - sleeping w/CPU context */
+}
+If (And(SSFG, 0x02)) {
+ Name(\_S2, Package () {0x02, 0x02, 0x00, 0x00} ) /* (S2) - "light" Suspend to RAM */
+}
+If (And(SSFG, 0x04)) {
+ Name(\_S3, Package () {0x03, 0x03, 0x00, 0x00} ) /* (S3) - Suspend to RAM */
+}
+If (And(SSFG, 0x08)) {
+ Name(\_S4, Package () {0x04, 0x04, 0x00, 0x00} ) /* (S4) - Suspend to Disk */
+}
+
+Name(\_S5, Package () {0x05, 0x05, 0x00, 0x00} ) /* (S5) - Soft Off */
diff --git a/src/soc/amd/picasso/acpi/soc.asl b/src/soc/amd/picasso/acpi/soc.asl
new file mode 100644
index 0000000000..52c7ee6c00
--- /dev/null
+++ b/src/soc/amd/picasso/acpi/soc.asl
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2017 Advanced Micro Devices, 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.
+ */
+
+Device(PCI0) {
+ /* Describe the AMD Northbridge */
+ #include "northbridge.asl"
+
+ /* Describe the AMD Fusion Controller Hub */
+ #include "sb_pci0_fch.asl"
+}
+
+/* Describe PCI INT[A-H] for the Southbridge */
+#include "pci_int.asl"
+
+/* Describe the devices in the Southbridge */
+#include "sb_fch.asl"
+
+/* Add GPIO library */
+#include <soc/amd/common/acpi/gpio_bank_lib.asl>
diff --git a/src/soc/amd/picasso/acpi/usb.asl b/src/soc/amd/picasso/acpi/usb.asl
new file mode 100644
index 0000000000..f2ee8f6427
--- /dev/null
+++ b/src/soc/amd/picasso/acpi/usb.asl
@@ -0,0 +1,392 @@
+/*
+ * 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.
+ */
+
+/* 0:12.0 - EHCI */
+Device(EHC0) {
+ Name(_ADR, 0x00120000)
+ Name(_PRW, Package() { 0xb, 3 })
+ Device (RHUB) {
+ Name (_ADR, Zero)
+ Device (HS01) { Name (_ADR, 1) }
+ Device (HS02) { Name (_ADR, 2) }
+ Device (HS03) { Name (_ADR, 3) }
+ Device (HS04) { Name (_ADR, 4) }
+ Device (HS05) { Name (_ADR, 5) }
+ Device (HS06) { Name (_ADR, 6) }
+ Device (HS07) { Name (_ADR, 7) }
+ Device (HS08) { Name (_ADR, 8) }
+ }
+
+ Name(_PR0, Package() { P0U2 }) /* Indicate support for D0 */
+ Name(_PR3, Package() { P3U2 }) /* Indicate support for D3cold */
+
+ Method(_S0W,0) {
+ Return(0)
+ }
+
+ Method(_S3W,0) {
+ Return(4)
+ }
+
+ Method(_S4W,0) {
+ Return(4)
+ }
+} /* end EHC0 */
+
+
+/* 0:10.0 - XHCI 0*/
+Device(XHC0) {
+ Name(_ADR, 0x00100000)
+ Name(_PRW, Package() { 0xb, 3 })
+ Device (SS01) { Name (_ADR, 1) }
+ Device (SS02) { Name (_ADR, 2) }
+ Device (SS03) { Name (_ADR, 3) }
+
+ Name(_PR0, Package() { P0U3 }) /* Indicate support for D0 */
+ Name(_PR3, Package() { P3U3 }) /* Indicate support for D3cold */
+
+ Method(_S0W,0) {
+ Return(0)
+ }
+
+ Method(_S3W,0) {
+ Return(4)
+ }
+
+ Method(_S4W,0) {
+ Return(4)
+ }
+
+} /* end XHC0 */
+
+Scope(\_SB)
+{
+ Name(XHD0, 0)
+ Name(XHD3, 0)
+ PowerResource(P0U3, 0, 0) {
+ Method(_STA) {
+ Return(XHD0)
+ }
+ Method(_ON) {
+ Store(0x01, XHD0)
+ }
+ Method(_OFF) {
+ Store(0x00, XHD0)
+ }
+ }
+ PowerResource(P3U3, 0, 0) {
+ Method(_STA) {
+ Return(XHD3)
+ }
+ Method(_ON) {
+ Store(0x01, XHD3)
+ }
+ Method(_OFF) {
+ Store(0x00, XHD3)
+ }
+ }
+
+ Name(EHD0, 0)
+ Name(EHD3, 0)
+ PowerResource(P0U2, 0, 0) {
+ Method(_STA) {
+ Return(EHD0)
+ }
+ Method(_ON) {
+ Store(0x01, EHD0)
+ }
+ Method(_OFF) {
+ Store(0x00, EHD0)
+ }
+ }
+ PowerResource(P3U2, 0, 0) {
+ Method(_STA) {
+ Return(EHD3)
+ }
+ Method(_ON) {
+ Store(0x01, EHD3)
+ }
+ Method(_OFF) {
+ Store(0x00, EHD3)
+ }
+ }
+}
+
+OperationRegion(EHMC, SystemMemory, EH10, 0x100)
+Field(EHMC, DwordAcc, NoLock, Preserve)
+{
+ Offset(0xb0),
+ , 5,
+ ESIM, 1,
+}
+
+Method(U2D3,0, Serialized)
+{
+ if (LNotEqual(EH10, Zero)) {
+ Store (EH10, EHBA)
+ Store (One, EHME)
+ Store (ESIM, SSIM)
+ }
+
+ if (LEqual(E_PS, 3)) {
+ Store (Zero, RQTY)
+ Store (One, RQ18)
+
+ Store (U2SR, Local0)
+ while (Local0) {
+ Store (U2SR, Local0)
+ }
+
+ Store (Zero, U2PD)
+
+ Store (U2DS, Local0)
+ while (LNotEqual(Local0, Zero)) {
+ Store (U2DS, Local0)
+ }
+
+ Store (0x03,U2TD)
+
+ if (LEqual(U3TD, 0x03)) { /* Shutdown USB2 PLL */
+ PWGC (0x40, 0)
+ Store (One, U2RP)
+ }
+ }
+}
+
+Method(U2D0,0, Serialized)
+{
+ PWGC (0x40, 1)
+ Store (Zero, U2RP)
+ Store (0x00,U2TD)
+
+ Store (Zero, U2TD)
+ Store (One, U2PD)
+
+ Store (U2DS, Local0)
+ while (LNotEqual(Local0,0x7)) {
+ Store (U2DS, Local0)
+ }
+
+ Store (One, RQTY)
+ Store (One, RQ18)
+ Store (U2SR, Local0)
+ while (LNot(Local0)) {
+ Store (U2SR, Local0)
+ }
+ Store (EHID, EH2C)
+
+
+ if (LNotEqual(EH10, Zero)) {
+ Store (EH10, EHBA)
+ Store (One, EHME)
+ Store (SSIM, ESIM)
+ }
+
+ Store (ES54, EH54)
+ Store (ES64, EH64)
+}
+
+Method(LXFW,3, Serialized) //Load Xhci FirmWare
+{
+ Store (One, FWLM) /* Firmware Load Mode */
+ Store (Arg0, ROAM) /* ROM/RAM */
+ Store (Arg1, UA04)
+ Store (Arg2, UA08)
+ Store (One, FPLS) /* Firmware Preload Start */
+ Store (FPLC, Local0) /* Firmware Preload Complete */
+ while (LNot(Local0)) {
+ Store (FPLC, Local0)
+ }
+ Store (Zero, FPLS)
+}
+
+Method(U3D3,0, Serialized)
+{
+ if (LEqual(U_PS, 3)) {
+ X0_S ()
+
+ Or (PGA3, 0x20, PGA3) /* SwUsb3SlpShutdown */
+ And (PGA3, 0x20, Local0)
+ while (LNot(Local0)) { /* wait for it to complete */
+ And (PGA3, 0x20, Local0)
+ }
+ Store (One, UD3P) /* U3P_D3Cold_PWRDN */
+
+ Store (Zero, U3PD) /* PwrOnDev */
+ Store (U3DS, Local0)
+ while (Local0) { /* RstBState, RefClkOkState, PwrRstBState */
+ Store (U3DS, Local0)
+ }
+
+ Store (0x3, U3TD) /* TargetedDeviceState */
+
+ Store (One, U3RP) /* USB3_RefClk_Pwdn */
+
+ if (Lequal(U2TD, 0x3)) { /* If EHCI targeted in D3cold */
+ And (PGA3, 0x9f, PGA3) /* SwUsb2S5RstB */
+ Store (One, U2RP) /* USB2_RefClk_Pwdn */
+ }
+ Store (Zero, U3PG) /* XhcPwrGood */
+ Store (One, U3PS) /* Usb3PowerSel */
+ }
+}
+
+Method(U3D0,0, Serialized)
+{
+ Store (Zero, U3PS) /* Usb3PowerSel */
+ Store (One, U3PG) /* XhcPwrGood */
+
+ Store (Zero, U2RP)
+ Store (Zero, U3RP)
+
+ And (PGA3, 0xdf, Local0)
+ Or (Local0, 0x40, Local0)
+ Store (Local0, PGA3) /* SwUsb2S5RstB */
+
+ Store (Zero, U3TD) /* TargetedDeviceState */
+ Store (One, U3PD) /* PwrOnDev */
+
+ Store (U3DS, Local0) /* wait for RstBState, RefClkOkState, PwrRstBState */
+ while (LNot(Lequal(Local0, 0x7))) {
+ Store (U3DS, Local0)
+ }
+
+ Store (U3PY, Local0) /* USB3 PHY Lock */
+ while (LNot(Local0)) {
+ Store (U3PY, Local0)
+ }
+
+ Store (Zero, U3PR) /* U3P_RESTORE_RESET */
+
+ Store (AUSS, Local0) /* AutoSizeStart */
+ if (LNotEqual(Local0,1)) {
+ Store(One, AUSS)
+ }
+ Store (AUSS, Local0)
+ while (LNotEqual(Local0,1)) {
+ Store (AUSS, Local0)
+ }
+
+ LXFW (1, FW00, FW01)
+ LXFW (0, FW02, FW03)
+
+ X0_R ()
+
+ Store (One, U3PR) /* U3P_RESTORE_RESET */
+ Store (Zero, UD3P) /* U3P_D3Cold_PWRDN */
+ Store (One, U3TD) /* TargetedDeviceState */
+}
+
+Name (SVBF, Buffer (0x1000) {0}) /* length from FchCarrizo.asl, new fields */
+CreateDWordField(SVBF, 0x000, S000) /* will be easier to add from there */
+CreateDWordField(SVBF, 0x004, S004)
+CreateDWordField(SVBF, 0x008, S008)
+CreateDWordField(SVBF, 0x00C, S00C)
+CreateDWordField(SVBF, 0x018, S018)
+CreateDWordField(SVBF, 0x01C, S01C)
+CreateDWordField(SVBF, 0x020, S020)
+CreateDWordField(SVBF, 0x030, S030)
+CreateDWordField(SVBF, 0x118, S118)
+CreateDWordField(SVBF, 0x158, S158)
+CreateDWordField(SVBF, 0x198, S198)
+CreateDWordField(SVBF, 0x1D8, S1D8)
+CreateDWordField(SVBF, 0x300, S300)
+CreateDWordField(SVBF, 0x304, S304)
+CreateDWordField(SVBF, 0x308, S308)
+CreateDWordField(SVBF, 0x30C, S30C)
+CreateDWordField(SVBF, 0x310, S310)
+CreateDWordField(SVBF, 0x428, S428)
+CreateDWordField(SVBF, 0x438, S438)
+CreateDWordField(SVBF, 0x43C, S43C)
+CreateDWordField(SVBF, 0x458, S458)
+CreateDWordField(SVBF, 0x468, S468)
+CreateDWordField(SVBF, 0x46C, S46C)
+CreateDWordField(SVBF, 0x470, S470)
+CreateDWordField(SVBF, 0x480, S480)
+CreateDWordField(SVBF, 0x484, S484)
+CreateDWordField(SVBF, 0x488, S488)
+CreateDWordField(SVBF, 0x48C, S48C)
+CreateDWordField(SVBF, 0x730, EHID) /* EHCI SSID */
+CreateDWordField(SVBF, 0x734, XHID) /* XHCI SSID */
+CreateByteField(SVBF, 0x740, ES54) /* EHCI PCIx54 */
+CreateByteField(SVBF, 0x741, ES64) /* EHCI PCIx64 */
+CreateDWordField(SVBF, 0x7B0, SSIM) /* EHCI SIM BIT */
+
+Method(X0_S,0)
+{
+ Store (XH2C, XHID)
+ Store (0x00000000, IDEX) Store (DATA, S000)
+ Store (0x00000004, IDEX) Store (DATA, S004)
+ Store (0x00000008, IDEX) Store (DATA, S008)
+ Store (0x0000000c, IDEX) Store (DATA, S00C)
+ Store (0x00000018, IDEX) Store (DATA, S018)
+ Store (0x0000001c, IDEX) Store (DATA, S01C)
+ Store (0x00000020, IDEX) Store (DATA, S020)
+ Store (0x00000030, IDEX) Store (DATA, S030)
+ Store (0x00000118, IDEX) Store (DATA, S118)
+ Store (0x00000158, IDEX) Store (DATA, S158)
+ Store (0x00000198, IDEX) Store (DATA, S198)
+ Store (0x000001d8, IDEX) Store (DATA, S1D8)
+ Store (0x00000300, IDEX) Store (DATA, S300)
+ Store (0x00000304, IDEX) Store (DATA, S304)
+ Store (0x00000308, IDEX) Store (DATA, S308)
+ Store (0x0000030c, IDEX) Store (DATA, S30C)
+ Store (0x00000310, IDEX) Store (DATA, S310)
+ Store (0x40000028, IDEX) Store (DATA, S428)
+ Store (0x40000038, IDEX) Store (DATA, S438)
+ Store (0x4000003c, IDEX) Store (DATA, S43C)
+ Store (0x40000058, IDEX) Store (DATA, S458)
+ Store (0x40000068, IDEX) Store (DATA, S468)
+ Store (0x4000006c, IDEX) Store (DATA, S46C)
+ Store (0x40000070, IDEX) Store (DATA, S470)
+ Store (0x40000080, IDEX) Store (DATA, S480)
+ Store (0x40000084, IDEX) Store (DATA, S484)
+ Store (0x40000088, IDEX) Store (DATA, S488)
+ Store (0x4000008c, IDEX) Store (DATA, S48C)
+}
+
+Method(X0_R,0)
+{
+ Store (XHID, XH2C)
+ Store (0x00000000, IDEX) Store (S000, DATA)
+ Store (0x00000004, IDEX) Store (S004, DATA)
+ Store (0x00000008, IDEX) Store (S008, DATA)
+ Store (0x0000000c, IDEX) Store (S00C, DATA)
+ Store (0x00000018, IDEX) Store (S018, DATA)
+ Store (0x0000001c, IDEX) Store (S01C, DATA)
+ Store (0x00000020, IDEX) Store (S020, DATA)
+ Store (0x00000030, IDEX) Store (S030, DATA)
+ Store (0x00000118, IDEX) Store (S118, DATA)
+ Store (0x00000158, IDEX) Store (S158, DATA)
+ Store (0x00000198, IDEX) Store (S198, DATA)
+ Store (0x000001d8, IDEX) Store (S1D8, DATA)
+ Store (0x00000300, IDEX) Store (S300, DATA)
+ Store (0x00000304, IDEX) Store (S304, DATA)
+ Store (0x00000308, IDEX) Store (S308, DATA)
+ Store (0x0000030c, IDEX) Store (S30C, DATA)
+ Store (0x00000310, IDEX) Store (S310, DATA)
+ Store (0x40000028, IDEX) Store (S428, DATA)
+ Store (0x40000038, IDEX) Store (S438, DATA)
+ Store (0x4000003c, IDEX) Store (S43C, DATA)
+ Store (0x40000058, IDEX) Store (S458, DATA)
+ Store (0x40000068, IDEX) Store (S468, DATA)
+ Store (0x4000006c, IDEX) Store (S46C, DATA)
+ Store (0x40000070, IDEX) Store (S470, DATA)
+ Store (0x40000080, IDEX) Store (S480, DATA)
+ Store (0x40000084, IDEX) Store (S484, DATA)
+ Store (0x40000088, IDEX) Store (S488, DATA)
+ Store (0x4000008c, IDEX) Store (S48C, DATA)
+}
diff --git a/src/soc/amd/picasso/bootblock/bootblock.c b/src/soc/amd/picasso/bootblock/bootblock.c
new file mode 100644
index 0000000000..9239030d6c
--- /dev/null
+++ b/src/soc/amd/picasso/bootblock/bootblock.c
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corporation..
+ * Copyright (C) 2017 Advanced Micro Devices
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdint.h>
+#include <assert.h>
+#include <console/console.h>
+#include <cpu/x86/msr.h>
+#include <cpu/amd/msr.h>
+#include <cpu/x86/mtrr.h>
+#include <smp/node.h>
+#include <bootblock_common.h>
+#include <amdblocks/agesawrapper.h>
+#include <amdblocks/agesawrapper_call.h>
+#include <soc/pci_devs.h>
+#include <soc/cpu.h>
+#include <soc/northbridge.h>
+#include <soc/southbridge.h>
+#include <amdblocks/psp.h>
+#include <timestamp.h>
+#include <halt.h>
+
+#if CONFIG_PI_AGESA_TEMP_RAM_BASE < 0x100000
+#error "Error: CONFIG_PI_AGESA_TEMP_RAM_BASE must be >= 1MB"
+#endif
+#if CONFIG_PI_AGESA_CAR_HEAP_BASE < 0x100000
+#error "Error: CONFIG_PI_AGESA_CAR_HEAP_BASE must be >= 1MB"
+#endif
+
+/* Set the MMIO Configuration Base Address, Bus Range, and misc MTRRs. */
+static void amd_initmmio(void)
+{
+ msr_t mmconf;
+ msr_t mtrr_cap = rdmsr(MTRR_CAP_MSR);
+ int mtrr;
+
+ mmconf.hi = 0;
+ mmconf.lo = CONFIG_MMCONF_BASE_ADDRESS | MMIO_RANGE_EN
+ | fms(CONFIG_MMCONF_BUS_NUMBER) << MMIO_BUS_RANGE_SHIFT;
+ wrmsr(MMIO_CONF_BASE, mmconf);
+
+ /*
+ * todo: AGESA currently writes variable MTRRs. Once that is
+ * corrected, un-hardcode this MTRR.
+ *
+ * Be careful not to use get_free_var_mtrr/set_var_mtrr pairs
+ * where all cores execute the path. Both cores within a compute
+ * unit share MTRRs. Programming core0 has the appearance of
+ * modifying core1 too. Using the pair again will create
+ * duplicate copies.
+ */
+ mtrr = (mtrr_cap.lo & MTRR_CAP_VCNT) - SOC_EARLY_VMTRR_FLASH;
+ set_var_mtrr(mtrr, FLASH_BASE_ADDR, CONFIG_ROM_SIZE, MTRR_TYPE_WRPROT);
+
+ mtrr = (mtrr_cap.lo & MTRR_CAP_VCNT) - SOC_EARLY_VMTRR_CAR_HEAP;
+ set_var_mtrr(mtrr, CONFIG_PI_AGESA_CAR_HEAP_BASE,
+ CONFIG_PI_AGESA_HEAP_SIZE, MTRR_TYPE_WRBACK);
+
+ mtrr = (mtrr_cap.lo & MTRR_CAP_VCNT) - SOC_EARLY_VMTRR_TEMPRAM;
+ set_var_mtrr(mtrr, CONFIG_PI_AGESA_TEMP_RAM_BASE,
+ CONFIG_PI_AGESA_HEAP_SIZE, MTRR_TYPE_UNCACHEABLE);
+}
+
+asmlinkage void bootblock_c_entry(uint64_t base_timestamp)
+{
+ amd_initmmio();
+ /*
+ * Call lib/bootblock.c main with BSP, shortcut for APs
+ */
+ if (!boot_cpu()) {
+ void (*ap_romstage_entry)(void) =
+ (void (*)(void))get_ap_entry_ptr();
+
+ ap_romstage_entry(); /* execution does not return */
+ halt();
+ }
+
+ /* TSC cannot be relied upon. Override the TSC value passed in. */
+ bootblock_main_with_timestamp(timestamp_get(), NULL, 0);
+}
+
+void bootblock_soc_early_init(void)
+{
+ /*
+ * This call (sb_reset_i2c_slaves) was originally early at
+ * bootblock_c_entry, but had to be moved here. There was an
+ * unexplained delay in the middle of the i2c transaction when
+ * we had it in bootblock_c_entry. Moving it to this point
+ * (or adding delays) fixes the issue. It seems like the processor
+ * just pauses but we don't know why.
+ */
+ sb_reset_i2c_slaves();
+ bootblock_fch_early_init();
+ post_code(0x90);
+}
+
+void bootblock_soc_init(void)
+{
+ if (CONFIG(STONEYRIDGE_UART))
+ assert(CONFIG_UART_FOR_CONSOLE >= 0
+ && CONFIG_UART_FOR_CONSOLE <= 1);
+
+ u32 val = cpuid_eax(1);
+ printk(BIOS_DEBUG, "Family_Model: %08x\n", val);
+
+ bootblock_fch_init();
+
+ /* Initialize any early i2c buses. */
+ i2c_soc_early_init();
+}
diff --git a/src/soc/amd/picasso/chip.c b/src/soc/amd/picasso/chip.c
new file mode 100644
index 0000000000..7221f955f6
--- /dev/null
+++ b/src/soc/amd/picasso/chip.c
@@ -0,0 +1,175 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2017 Advanced Micro Devices, 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.
+ */
+
+#include <bootstate.h>
+#include <console/console.h>
+#include <cpu/amd/mtrr.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <drivers/i2c/designware/dw_i2c.h>
+#include <romstage_handoff.h>
+#include <soc/acpi.h>
+#include <soc/cpu.h>
+#include <soc/northbridge.h>
+#include <soc/pci_devs.h>
+#include <soc/southbridge.h>
+#include <amdblocks/psp.h>
+#include <amdblocks/agesawrapper.h>
+#include <amdblocks/agesawrapper_call.h>
+
+#include "chip.h"
+
+/* Supplied by i2c.c */
+extern struct device_operations stoneyridge_i2c_mmio_ops;
+extern const char *i2c_acpi_name(const struct device *dev);
+
+struct device_operations cpu_bus_ops = {
+ .read_resources = DEVICE_NOOP,
+ .set_resources = DEVICE_NOOP,
+ .enable_resources = DEVICE_NOOP,
+ .init = stoney_init_cpus,
+ .acpi_fill_ssdt_generator = generate_cpu_entries,
+};
+
+const char *soc_acpi_name(const struct device *dev)
+{
+ if (dev->path.type == DEVICE_PATH_DOMAIN)
+ return "PCI0";
+
+ if (dev->path.type == DEVICE_PATH_USB) {
+ switch (dev->path.usb.port_type) {
+ case 0:
+ /* Root Hub */
+ return "RHUB";
+ case 2:
+ /* USB2 ports */
+ switch (dev->path.usb.port_id) {
+ case 0: return "HS01";
+ case 1: return "HS02";
+ case 2: return "HS03";
+ case 3: return "HS04";
+ case 4: return "HS05";
+ case 5: return "HS06";
+ case 6: return "HS07";
+ case 7: return "HS08";
+ }
+ break;
+ case 3:
+ /* USB3 ports */
+ switch (dev->path.usb.port_id) {
+ case 0: return "SS01";
+ case 1: return "SS02";
+ case 2: return "SS03";
+ }
+ break;
+ }
+ return NULL;
+ }
+
+ if (dev->path.type != DEVICE_PATH_PCI)
+ return NULL;
+
+ switch (dev->path.pci.devfn) {
+ case GFX_DEVFN:
+ return "IGFX";
+ case PCIE0_DEVFN:
+ return "PBR4";
+ case PCIE1_DEVFN:
+ return "PBR5";
+ case PCIE2_DEVFN:
+ return "PBR6";
+ case PCIE3_DEVFN:
+ return "PBR7";
+ case PCIE4_DEVFN:
+ return "PBR8";
+ case HDA1_DEVFN:
+ return "AZHD";
+ case EHCI1_DEVFN:
+ return "EHC0";
+ case LPC_DEVFN:
+ return "LPCB";
+ case SATA_DEVFN:
+ return "STCR";
+ case SD_DEVFN:
+ return "SDCN";
+ case SMBUS_DEVFN:
+ return "SBUS";
+ case XHCI_DEVFN:
+ return "XHC0";
+ default:
+ return NULL;
+ }
+};
+
+struct device_operations pci_domain_ops = {
+ .read_resources = pci_domain_read_resources,
+ .set_resources = domain_set_resources,
+ .enable_resources = domain_enable_resources,
+ .scan_bus = pci_domain_scan_bus,
+ .acpi_name = soc_acpi_name,
+};
+
+static void enable_dev(struct device *dev)
+{
+ /* Set the operations if it is a special bus type */
+ if (dev->path.type == DEVICE_PATH_DOMAIN)
+ dev->ops = &pci_domain_ops;
+ else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER)
+ dev->ops = &cpu_bus_ops;
+ else if (dev->path.type == DEVICE_PATH_PCI)
+ sb_enable(dev);
+ else if (dev->path.type == DEVICE_PATH_MMIO)
+ if (i2c_acpi_name(dev) != NULL)
+ dev->ops = &stoneyridge_i2c_mmio_ops;
+}
+
+static void soc_init(void *chip_info)
+{
+ southbridge_init(chip_info);
+ setup_bsp_ramtop();
+}
+
+static void soc_final(void *chip_info)
+{
+ southbridge_final(chip_info);
+ fam15_finalize(chip_info);
+}
+
+struct chip_operations soc_amd_stoneyridge_ops = {
+ CHIP_NAME("AMD StoneyRidge SOC")
+ .enable_dev = enable_dev,
+ .init = soc_init,
+ .final = soc_final
+};
+
+static void earliest_ramstage(void *unused)
+{
+ int s3_resume = acpi_s3_resume_allowed() &&
+ romstage_handoff_is_resume();
+ if (!s3_resume) {
+ post_code(0x46);
+ if (CONFIG(SOC_AMD_PSP_SELECTABLE_SMU_FW))
+ psp_load_named_blob(MBOX_BIOS_CMD_SMU_FW2, "smu_fw2");
+
+ post_code(0x47);
+ do_agesawrapper(AMD_INIT_ENV, "amdinitenv");
+ } else {
+ /* Complete the initial system restoration */
+ post_code(0x46);
+ do_agesawrapper(AMD_S3LATE_RESTORE, "amds3laterestore");
+ }
+}
+
+BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, earliest_ramstage, NULL);
diff --git a/src/soc/amd/picasso/chip.h b/src/soc/amd/picasso/chip.h
new file mode 100644
index 0000000000..d1a7d30199
--- /dev/null
+++ b/src/soc/amd/picasso/chip.h
@@ -0,0 +1,81 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010-2017 Advanced Micro Devices, 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.
+ */
+
+#ifndef __STONEYRIDGE_CHIP_H__
+#define __STONEYRIDGE_CHIP_H__
+
+#include <stddef.h>
+#include <stdint.h>
+#include <commonlib/helpers.h>
+#include <drivers/i2c/designware/dw_i2c.h>
+#include <soc/i2c.h>
+#include <arch/acpi_device.h>
+
+#define MAX_NODES 1
+#define MAX_DRAM_CH 1
+#define MAX_DIMMS_PER_CH 2
+
+#define STONEY_I2C_DEV_MAX 4
+
+struct soc_amd_stoneyridge_config {
+ u8 spd_addr_lookup[MAX_NODES][MAX_DRAM_CH][MAX_DIMMS_PER_CH];
+ enum {
+ DRAM_CONTENTS_KEEP,
+ DRAM_CONTENTS_CLEAR
+ } dram_clear_on_reset;
+
+ enum {
+ /* Do not enable UMA in the system. */
+ UMAMODE_NONE,
+ /* Enable UMA with a specific size. */
+ UMAMODE_SPECIFIED_SIZE,
+ /* Let AGESA determine the proper size. Non-legacy requires
+ * the resolution to be specified PLATFORM_CONFIGURATION */
+ UMAMODE_AUTO_LEGACY,
+ UMAMODE_AUTO_NON_LEGACY,
+ } uma_mode;
+
+ /* Used if UMAMODE_SPECIFIED_SIZE is set. */
+ size_t uma_size;
+
+ /*
+ * If sb_reset_i2c_slaves() is called, this devicetree register
+ * defines which I2C SCL will be toggled 9 times at 100 KHz.
+ * For example, should we need I2C0 and I2C3 have their slave
+ * devices reseted by toggling SCL, use:
+ *
+ * register i2c_scl_reset = (GPIO_I2C0_SCL | GPIO_I2C3_SCL)
+ */
+ u8 i2c_scl_reset;
+ struct dw_i2c_bus_config i2c[STONEY_I2C_DEV_MAX];
+ u8 stapm_percent;
+ u32 stapm_time_ms;
+ u32 stapm_power_mw;
+ /*
+ * This specifies the LVDS/eDP power-up sequence time for the delay
+ * between VaryBL and BLON.
+ * 0 - Use the VBIOS default (default). The video BIOS default is 32ms.
+ * n - Values other than zero specify a setting of (4 * n) milliseconds
+ * time delay.
+ */
+ u8 lvds_poseq_varybl_to_blon;
+ u8 lvds_poseq_blon_to_varybl;
+};
+
+typedef struct soc_amd_stoneyridge_config config_t;
+
+extern struct device_operations pci_domain_ops;
+
+#endif /* __STONEYRIDGE_CHIP_H__ */
diff --git a/src/soc/amd/picasso/cpu.c b/src/soc/amd/picasso/cpu.c
new file mode 100644
index 0000000000..1d9804d99c
--- /dev/null
+++ b/src/soc/amd/picasso/cpu.c
@@ -0,0 +1,155 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015-2016 Intel Corp.
+ * Copyright (C) 2017 Advanced Micro Devices, 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.
+ */
+
+#include <cpu/cpu.h>
+#include <cpu/x86/mp.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/msr.h>
+#include <cpu/amd/msr.h>
+#include <cpu/x86/lapic.h>
+#include <device/device.h>
+#include <device/pci_ops.h>
+#include <soc/pci_devs.h>
+#include <soc/cpu.h>
+#include <soc/northbridge.h>
+#include <soc/smi.h>
+#include <soc/iomap.h>
+#include <console/console.h>
+
+/*
+ * MP and SMM loading initialization.
+ */
+struct smm_relocation_attrs {
+ uint32_t smbase;
+ uint32_t tseg_base;
+ uint32_t tseg_mask;
+};
+
+static struct smm_relocation_attrs relo_attrs;
+
+/*
+ * Do essential initialization tasks before APs can be fired up -
+ *
+ * 1. Prevent race condition in MTRR solution. Enable MTRRs on the BSP. This
+ * creates the MTRR solution that the APs will use. Otherwise APs will try to
+ * apply the incomplete solution as the BSP is calculating it.
+ */
+static void pre_mp_init(void)
+{
+ x86_setup_mtrrs_with_detect();
+ x86_mtrr_check();
+}
+
+static int get_cpu_count(void)
+{
+ return (pci_read_config16(SOC_HT_DEV, D18F0_CPU_CNT) & CPU_CNT_MASK)
+ + 1;
+}
+
+static void get_smm_info(uintptr_t *perm_smbase, size_t *perm_smsize,
+ size_t *smm_save_state_size)
+{
+ void *smm_base;
+ size_t smm_size;
+ void *handler_base;
+ size_t handler_size;
+
+ /* Initialize global tracking state. */
+ smm_region_info(&smm_base, &smm_size);
+ smm_subregion(SMM_SUBREGION_HANDLER, &handler_base, &handler_size);
+
+ relo_attrs.smbase = (uint32_t)smm_base;
+ relo_attrs.tseg_base = relo_attrs.smbase;
+ relo_attrs.tseg_mask = ALIGN_DOWN(~(smm_size - 1), 128 * KiB);
+ relo_attrs.tseg_mask |= SMM_TSEG_WB;
+
+ *perm_smbase = (uintptr_t)handler_base;
+ *perm_smsize = handler_size;
+ *smm_save_state_size = sizeof(amd64_smm_state_save_area_t);
+}
+
+static void relocation_handler(int cpu, uintptr_t curr_smbase,
+ uintptr_t staggered_smbase)
+{
+ msr_t tseg_base, tseg_mask;
+ amd64_smm_state_save_area_t *smm_state;
+
+ tseg_base.lo = relo_attrs.tseg_base;
+ tseg_base.hi = 0;
+ wrmsr(SMM_ADDR_MSR, tseg_base);
+ tseg_mask.lo = relo_attrs.tseg_mask;
+ tseg_mask.hi = ((1 << (cpu_phys_address_size() - 32)) - 1);
+ wrmsr(SMM_MASK_MSR, tseg_mask);
+ smm_state = (void *)(SMM_AMD64_SAVE_STATE_OFFSET + curr_smbase);
+ smm_state->smbase = staggered_smbase;
+}
+
+static const struct mp_ops mp_ops = {
+ .pre_mp_init = pre_mp_init,
+ .get_cpu_count = get_cpu_count,
+ .get_smm_info = get_smm_info,
+ .relocation_handler = relocation_handler,
+ .post_mp_init = enable_smi_generation,
+};
+
+void stoney_init_cpus(struct device *dev)
+{
+ /* Clear for take-off */
+ if (mp_init_with_smm(dev->link_list, &mp_ops) < 0)
+ printk(BIOS_ERR, "MP initialization failure.\n");
+
+ /* The flash is now no longer cacheable. Reset to WP for performance. */
+ mtrr_use_temp_range(FLASH_BASE_ADDR, CONFIG_ROM_SIZE, MTRR_TYPE_WRPROT);
+
+ set_warm_reset_flag();
+}
+
+static void model_15_init(struct device *dev)
+{
+ check_mca();
+ setup_lapic();
+
+ /*
+ * Per AMD, sync an undocumented MSR with the PSP base address.
+ * Experiments showed that if you write to the MSR after it has
+ * been previously programmed, it causes a general protection fault.
+ * Also, the MSR survives warm reset and S3 cycles, so we need to
+ * test if it was previously written before writing to it.
+ */
+ msr_t psp_msr;
+ uint32_t psp_bar; /* Note: NDA BKDG names this 32-bit register BAR3 */
+ psp_bar = pci_read_config32(SOC_PSP_DEV, PCI_BASE_ADDRESS_4);
+ psp_bar &= ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
+ psp_msr = rdmsr(0xc00110a2);
+ if (psp_msr.lo == 0) {
+ psp_msr.lo = psp_bar;
+ wrmsr(0xc00110a2, psp_msr);
+ }
+}
+
+static struct device_operations cpu_dev_ops = {
+ .init = model_15_init,
+};
+
+static struct cpu_device_id cpu_table[] = {
+ { X86_VENDOR_AMD, 0x670f00 },
+ { 0, 0 },
+};
+
+static const struct cpu_driver model_15 __cpu_driver = {
+ .ops = &cpu_dev_ops,
+ .id_table = cpu_table,
+};
diff --git a/src/soc/amd/picasso/enable_usbdebug.c b/src/soc/amd/picasso/enable_usbdebug.c
new file mode 100644
index 0000000000..19b9550847
--- /dev/null
+++ b/src/soc/amd/picasso/enable_usbdebug.c
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010 Advanced Micro Devices, 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.
+ */
+
+// Use simple device model for this file even in ramstage
+#define __SIMPLE_DEVICE__
+
+#include <stdint.h>
+#include <device/pci_ops.h>
+#include <device/pci_ehci.h>
+#include <device/pci_def.h>
+#include <soc/pci_devs.h>
+#include <soc/southbridge.h>
+
+pci_devfn_t pci_ehci_dbg_dev(unsigned int hcd_idx)
+{
+ pm_io_write8(PM_USB_ENABLE, PM_USB_ALL_CONTROLLERS);
+ return SOC_EHCI1_DEV;
+}
+
+void pci_ehci_dbg_set_port(pci_devfn_t dev, unsigned int port)
+{
+ u32 reg32, value;
+
+ value = (port & 0x3) << DEBUG_PORT_SELECT_SHIFT;
+ value |= DEBUG_PORT_ENABLE;
+ reg32 = pci_read_config32(SOC_EHCI1_DEV, EHCI_HUB_CONFIG4);
+ reg32 &= ~DEBUG_PORT_MASK;
+ reg32 |= value;
+ pci_write_config32(SOC_EHCI1_DEV, EHCI_HUB_CONFIG4, reg32);
+}
diff --git a/src/soc/amd/picasso/finalize.c b/src/soc/amd/picasso/finalize.c
new file mode 100644
index 0000000000..6572e1a201
--- /dev/null
+++ b/src/soc/amd/picasso/finalize.c
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2018 Advanced Micro Devices, 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.
+ */
+
+#include <cpu/x86/mp.h>
+#include <cpu/x86/msr.h>
+#include <cpu/amd/msr.h>
+#include <bootstate.h>
+#include <timer.h>
+#include <console/console.h>
+
+static void per_core_finalize(void *unused)
+{
+ msr_t hwcr, mask;
+
+ /* Finalize SMM settings */
+ hwcr = rdmsr(HWCR_MSR);
+ if (hwcr.lo & SMM_LOCK) /* Skip if already locked, avoid GPF */
+ return;
+
+ if (CONFIG(SMM_TSEG)) {
+ mask = rdmsr(SMM_MASK_MSR);
+ mask.lo |= SMM_TSEG_VALID;
+ wrmsr(SMM_MASK_MSR, mask);
+ }
+
+ hwcr.lo |= SMM_LOCK;
+ wrmsr(HWCR_MSR, hwcr);
+}
+
+static void finalize_cores(void)
+{
+ int r;
+ printk(BIOS_SPEW, "Lock SMM configuration\n");
+
+ r = mp_run_on_all_cpus(per_core_finalize, NULL, 10 * USECS_PER_MSEC);
+ if (r)
+ printk(BIOS_WARNING, "Failed to finalize all cores\n");
+}
+
+static void soc_finalize(void *unused)
+{
+ finalize_cores();
+
+ post_code(POST_OS_BOOT);
+}
+
+BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, soc_finalize, NULL);
+BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, soc_finalize, NULL);
diff --git a/src/soc/amd/picasso/gpio.c b/src/soc/amd/picasso/gpio.c
new file mode 100644
index 0000000000..f63a0d93a4
--- /dev/null
+++ b/src/soc/amd/picasso/gpio.c
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Google Inc.
+ * Copyright (C) 2015 Intel Corporation
+ * Copyright (C) 2017 Advanced Micro Devices, 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.
+ */
+
+#include <stdint.h>
+#include <amdblocks/gpio_banks.h>
+#include <amdblocks/acpimmio.h>
+#include <soc/gpio.h>
+#include <soc/smi.h>
+
+static const struct soc_amd_event gpio_event_table[] = {
+ { GPIO_1, GEVENT_19 },
+ { GPIO_2, GEVENT_8 },
+ { GPIO_3, GEVENT_2 },
+ { GPIO_4, GEVENT_4 },
+ { GPIO_5, GEVENT_7 },
+ { GPIO_6, GEVENT_10 },
+ { GPIO_7, GEVENT_11 },
+ { GPIO_8, GEVENT_23 },
+ { GPIO_9, GEVENT_22 },
+ { GPIO_11, GEVENT_18 },
+ { GPIO_13, GEVENT_21 },
+ { GPIO_14, GEVENT_6 },
+ { GPIO_15, GEVENT_20 },
+ { GPIO_16, GEVENT_12 },
+ { GPIO_17, GEVENT_13 },
+ { GPIO_18, GEVENT_14 },
+ { GPIO_21, GEVENT_5 },
+ { GPIO_22, GEVENT_3 },
+ { GPIO_23, GEVENT_16 },
+ { GPIO_24, GEVENT_15 },
+ { GPIO_65, GEVENT_0 },
+ { GPIO_66, GEVENT_1 },
+ { GPIO_68, GEVENT_9 },
+ { GPIO_69, GEVENT_17 },
+};
+
+void soc_route_sci(uint8_t event)
+{
+ smi_write8(SMI_SCI_MAP(event), event);
+}
+
+void soc_get_gpio_event_table(const struct soc_amd_event **table, size_t *items)
+{
+ *table = gpio_event_table;
+ *items = ARRAY_SIZE(gpio_event_table);
+}
+
+void soc_gpio_hook(uint8_t gpio, uint8_t mux)
+{
+ /* Always program Gevent when WAKE_L_AGPIO2 is configured as WAKE_L */
+ if ((gpio == 2) && !(mux & AMD_GPIO_MUX_MASK))
+ soc_route_sci(GPIO_2_EVENT);
+}
diff --git a/src/soc/amd/picasso/i2c.c b/src/soc/amd/picasso/i2c.c
new file mode 100644
index 0000000000..7f65a4f3f3
--- /dev/null
+++ b/src/soc/amd/picasso/i2c.c
@@ -0,0 +1,241 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2017 Google
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <device/mmio.h>
+#include <arch/acpi.h>
+#include <console/console.h>
+#include <delay.h>
+#include <drivers/i2c/designware/dw_i2c.h>
+#include <amdblocks/acpimmio.h>
+#include <soc/iomap.h>
+#include <soc/pci_devs.h>
+#include <soc/southbridge.h>
+#include <soc/i2c.h>
+#include "chip.h"
+
+#define I2C_BUS_ADDRESS(x) (I2C_BASE_ADDRESS + I2C_DEVICE_SIZE * (x))
+#define I2CA_BASE_ADDRESS (I2C_BUS_ADDRESS(0))
+#define I2CB_BASE_ADDRESS (I2C_BUS_ADDRESS(1))
+#define I2CC_BASE_ADDRESS (I2C_BUS_ADDRESS(2))
+#define I2CD_BASE_ADDRESS (I2C_BUS_ADDRESS(3))
+
+/* Global to provide access to chip.c */
+const char *i2c_acpi_name(const struct device *dev);
+
+static const uintptr_t i2c_bus_address[] = {
+ I2CA_BASE_ADDRESS,
+ I2CB_BASE_ADDRESS,
+ I2CC_BASE_ADDRESS,
+ I2CD_BASE_ADDRESS,
+};
+
+uintptr_t dw_i2c_base_address(unsigned int bus)
+{
+ return bus < I2C_DEVICE_COUNT ? i2c_bus_address[bus] : 0;
+}
+
+static const struct soc_amd_stoneyridge_config *get_soc_config(void)
+{
+ const struct device *dev = pcidev_path_on_root(GNB_DEVFN);
+
+ if (!dev || !dev->chip_info) {
+ printk(BIOS_ERR, "%s: Could not find SoC devicetree config!\n",
+ __func__);
+ return NULL;
+ }
+
+ return dev->chip_info;
+}
+
+const struct dw_i2c_bus_config *dw_i2c_get_soc_cfg(unsigned int bus)
+{
+ const struct soc_amd_stoneyridge_config *config;
+
+ if (bus >= ARRAY_SIZE(i2c_bus_address))
+ return NULL;
+
+ config = get_soc_config();
+ if (config == NULL)
+ return NULL;
+
+ return &config->i2c[bus];
+}
+
+const char *i2c_acpi_name(const struct device *dev)
+{
+ switch (dev->path.mmio.addr) {
+ case I2CA_BASE_ADDRESS:
+ return "I2CA";
+ case I2CB_BASE_ADDRESS:
+ return "I2CB";
+ case I2CC_BASE_ADDRESS:
+ return "I2CC";
+ case I2CD_BASE_ADDRESS:
+ return "I2CD";
+ default:
+ return NULL;
+ }
+}
+
+int dw_i2c_soc_dev_to_bus(struct device *dev)
+{
+ switch (dev->path.mmio.addr) {
+ case I2CA_BASE_ADDRESS:
+ return 0;
+ case I2CB_BASE_ADDRESS:
+ return 1;
+ case I2CC_BASE_ADDRESS:
+ return 2;
+ case I2CD_BASE_ADDRESS:
+ return 3;
+ }
+ return -1;
+}
+
+static void dw_i2c_soc_init(bool is_early_init)
+{
+ size_t i;
+ const struct soc_amd_stoneyridge_config *config;
+
+ config = get_soc_config();
+
+ if (config == NULL)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(config->i2c); i++) {
+ const struct dw_i2c_bus_config *cfg = &config->i2c[i];
+
+ if (cfg->early_init != is_early_init)
+ continue;
+
+ if (dw_i2c_init(i, cfg))
+ printk(BIOS_ERR, "Failed to init i2c bus %zd\n", i);
+ }
+}
+
+void i2c_soc_early_init(void)
+{
+ dw_i2c_soc_init(true);
+}
+
+void i2c_soc_init(void)
+{
+ dw_i2c_soc_init(false);
+}
+
+struct device_operations stoneyridge_i2c_mmio_ops = {
+ /* TODO(teravest): Move I2C resource info here. */
+ .read_resources = DEVICE_NOOP,
+ .set_resources = DEVICE_NOOP,
+ .enable_resources = DEVICE_NOOP,
+ .scan_bus = scan_smbus,
+ .acpi_name = i2c_acpi_name,
+ .acpi_fill_ssdt_generator = dw_i2c_acpi_fill_ssdt,
+};
+
+/*
+ * I2C pins are open drain with external pull up, so in order to bit bang them
+ * all, SCL pins must become GPIO inputs with no pull, then they need to be
+ * toggled between input-no-pull and output-low. This table is for the initial
+ * conversion of all SCL pins to input with no pull.
+ */
+static const struct soc_amd_gpio i2c_2_gpi[] = {
+ PAD_GPI(I2C0_SCL_PIN, PULL_NONE),
+ PAD_GPI(I2C1_SCL_PIN, PULL_NONE),
+ PAD_GPI(I2C2_SCL_PIN, PULL_NONE),
+ PAD_GPI(I2C3_SCL_PIN, PULL_NONE),
+};
+#define saved_pins_count ARRAY_SIZE(i2c_2_gpi)
+
+/*
+ * To program I2C pins without destroying their programming, the registers
+ * that will be changed need to be saved first.
+ */
+static void save_i2c_pin_registers(uint8_t gpio,
+ struct soc_amd_i2c_save *save_table)
+{
+ uint32_t *gpio_ptr;
+
+ gpio_ptr = (uint32_t *)gpio_get_address(gpio);
+ save_table->mux_value = iomux_read8(gpio);
+ save_table->control_value = read32(gpio_ptr);
+}
+
+static void restore_i2c_pin_registers(uint8_t gpio,
+ struct soc_amd_i2c_save *save_table)
+{
+ uint32_t *gpio_ptr;
+
+ gpio_ptr = (uint32_t *)gpio_get_address(gpio);
+ iomux_write8(gpio, save_table->mux_value);
+ iomux_read8(gpio);
+ write32(gpio_ptr, save_table->control_value);
+ read32(gpio_ptr);
+}
+
+/* Slaves to be reset are controlled by devicetree register i2c_scl_reset */
+void sb_reset_i2c_slaves(void)
+{
+ const struct soc_amd_stoneyridge_config *cfg;
+ const struct device *dev = pcidev_path_on_root(GNB_DEVFN);
+ struct soc_amd_i2c_save save_table[saved_pins_count];
+ uint8_t i, j, control;
+
+ if (!dev || !dev->chip_info)
+ return;
+ cfg = dev->chip_info;
+ control = cfg->i2c_scl_reset & GPIO_I2C_MASK;
+ if (control == 0)
+ return;
+
+ /* Save and reprogram I2C SCL pins */
+ for (i = 0; i < saved_pins_count; i++)
+ save_i2c_pin_registers(i2c_2_gpi[i].gpio, &save_table[i]);
+ program_gpios(i2c_2_gpi, saved_pins_count);
+
+ /*
+ * Toggle SCL back and forth 9 times under 100KHz. A single read is
+ * needed after the writes to force the posted write to complete.
+ */
+ for (j = 0; j < 9; j++) {
+ if (control & GPIO_I2C0_SCL)
+ write32((uint32_t *)GPIO_I2C0_ADDRESS, GPIO_SCL_LOW);
+ if (control & GPIO_I2C1_SCL)
+ write32((uint32_t *)GPIO_I2C1_ADDRESS, GPIO_SCL_LOW);
+ if (control & GPIO_I2C2_SCL)
+ write32((uint32_t *)GPIO_I2C2_ADDRESS, GPIO_SCL_LOW);
+ if (control & GPIO_I2C3_SCL)
+ write32((uint32_t *)GPIO_I2C3_ADDRESS, GPIO_SCL_LOW);
+
+ read32((uint32_t *)GPIO_I2C3_ADDRESS); /* Flush posted write */
+ udelay(4); /* 4usec gets 85KHz for 1 pin, 70KHz for 4 pins */
+
+ if (control & GPIO_I2C0_SCL)
+ write32((uint32_t *)GPIO_I2C0_ADDRESS, GPIO_SCL_HIGH);
+ if (control & GPIO_I2C1_SCL)
+ write32((uint32_t *)GPIO_I2C1_ADDRESS, GPIO_SCL_HIGH);
+ if (control & GPIO_I2C2_SCL)
+ write32((uint32_t *)GPIO_I2C2_ADDRESS, GPIO_SCL_HIGH);
+ if (control & GPIO_I2C3_SCL)
+ write32((uint32_t *)GPIO_I2C3_ADDRESS, GPIO_SCL_HIGH);
+
+ read32((uint32_t *)GPIO_I2C3_ADDRESS); /* Flush posted write */
+ udelay(4);
+ }
+
+ /* Restore I2C pins. */
+ for (i = 0; i < saved_pins_count; i++)
+ restore_i2c_pin_registers(i2c_2_gpi[i].gpio, &save_table[i]);
+}
diff --git a/src/soc/amd/picasso/include/soc/acpi.h b/src/soc/amd/picasso/include/soc/acpi.h
new file mode 100644
index 0000000000..15a41edce6
--- /dev/null
+++ b/src/soc/amd/picasso/include/soc/acpi.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.)
+ *
+ * This program is free software; 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.
+ */
+
+#ifndef __SOC_STONEYRIDGE_ACPI_H__
+#define __SOC_STONEYRIDGE_ACPI_H__
+
+#include <arch/acpi.h>
+
+#if CONFIG(STONEYRIDGE_LEGACY_FREE)
+ #define FADT_BOOT_ARCH ACPI_FADT_LEGACY_FREE
+#else
+ #define FADT_BOOT_ARCH (ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042)
+#endif
+
+#ifndef FADT_PM_PROFILE
+ #define FADT_PM_PROFILE PM_UNSPECIFIED
+#endif
+
+unsigned long southbridge_write_acpi_tables(struct device *device,
+ unsigned long current, struct acpi_rsdp *rsdp);
+
+void southbridge_inject_dsdt(struct device *device);
+
+const char *soc_acpi_name(const struct device *dev);
+
+#endif /* __SOC_STONEYRIDGE_ACPI_H__ */
diff --git a/src/soc/amd/picasso/include/soc/amd_pci_int_defs.h b/src/soc/amd/picasso/include/soc/amd_pci_int_defs.h
new file mode 100644
index 0000000000..beef2bcc81
--- /dev/null
+++ b/src/soc/amd/picasso/include/soc/amd_pci_int_defs.h
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Sage Electronic Engineering, LLC.
+ * Copyright (C) 2017 Advanced Micro Devices, 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.
+ */
+
+#ifndef __AMD_PCI_INT_DEFS_H__
+#define __AMD_PCI_INT_DEFS_H__
+
+/*
+ * PIRQ and device routing - these define the index into the
+ * FCH PCI_INTR 0xC00/0xC01 interrupt routing table.
+ */
+
+#define PIRQ_NC 0x1f /* Not Used */
+#define PIRQ_A 0x00 /* INT A */
+#define PIRQ_B 0x01 /* INT B */
+#define PIRQ_C 0x02 /* INT C */
+#define PIRQ_D 0x03 /* INT D */
+#define PIRQ_E 0x04 /* INT E */
+#define PIRQ_F 0x05 /* INT F */
+#define PIRQ_G 0x06 /* INT G */
+#define PIRQ_H 0x07 /* INT H */
+#define PIRQ_MISC 0x08 /* Miscellaneous IRQ Settings - See FCH Spec */
+#define PIRQ_MISC0 0x09 /* Miscellaneous0 IRQ Settings */
+#define PIRQ_MISC1 0x0a /* Miscellaneous1 IRQ Settings */
+#define PIRQ_MISC2 0x0b /* Miscellaneous2 IRQ Settings */
+#define PIRQ_SIRQA 0x0c /* Serial IRQ INTA */
+#define PIRQ_SIRQB 0x0d /* Serial IRQ INTB */
+#define PIRQ_SIRQC 0x0e /* Serial IRQ INTC */
+#define PIRQ_SIRQD 0x0f /* Serial IRQ INTD */
+#define PIRQ_SCI 0x10 /* SCI IRQ */
+#define PIRQ_SMBUS 0x11 /* SMBUS 14h.0 */
+#define PIRQ_ASF 0x12 /* ASF */
+#define PIRQ_HDA 0x13 /* HDA 14h.2 */
+#define PIRQ_FC 0x14 /* FC */
+#define PIRQ_PMON 0x16 /* Performance Monitor */
+#define PIRQ_SD 0x17 /* SD */
+#define PIRQ_SDIO 0x1a /* SDIO */
+#define PIRQ_EHCI 0x30 /* USB EHCI 12h.0 */
+#define PIRQ_XHCI 0x34 /* USB XHCI 10h.0 */
+#define PIRQ_SATA 0x41 /* SATA 11h.0 */
+#define PIRQ_GPIO 0x62 /* GPIO Controller Interrupt */
+#define PIRQ_I2C0 0x70
+#define PIRQ_I2C1 0x71
+#define PIRQ_I2C2 0x72
+#define PIRQ_I2C3 0x73
+#define PIRQ_UART0 0x74
+#define PIRQ_UART1 0x75
+
+#endif /* __AMD_PCI_INT_DEFS_H__ */
diff --git a/src/soc/amd/picasso/include/soc/cpu.h b/src/soc/amd/picasso/include/soc/cpu.h
new file mode 100644
index 0000000000..934a9f2983
--- /dev/null
+++ b/src/soc/amd/picasso/include/soc/cpu.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2017 Advanced Micro Devices, 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.
+ */
+
+#ifndef __STONEYRIDGE_CPU_H__
+#define __STONEYRIDGE_CPU_H__
+
+#include <device/device.h>
+
+/*
+ * Set a variable MTRR in bootblock and/or romstage. AGESA will use the lowest
+ * numbered registers. Any values defined below are subtracted from the
+ * highest numbered registers.
+ *
+ * todo: Revisit this once AGESA no longer programs MTRRs.
+ */
+#define SOC_EARLY_VMTRR_FLASH 1
+#define SOC_EARLY_VMTRR_CAR_HEAP 2
+#define SOC_EARLY_VMTRR_TEMPRAM 3
+
+void stoney_init_cpus(struct device *dev);
+void check_mca(void);
+
+#endif /* __STONEYRIDGE_CPU_H__ */
diff --git a/src/soc/amd/picasso/include/soc/gpio.h b/src/soc/amd/picasso/include/soc/gpio.h
new file mode 100644
index 0000000000..d8774f051a
--- /dev/null
+++ b/src/soc/amd/picasso/include/soc/gpio.h
@@ -0,0 +1,308 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2017 Advanced Micro Devices, 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.
+ */
+
+#ifndef __STONEYRIDGE_GPIO_H__
+#define __STONEYRIDGE_GPIO_H__
+
+#define GPIO_DEVICE_NAME "AMD0030"
+#define GPIO_DEVICE_DESC "GPIO Controller"
+
+#ifndef __ACPI__
+#include <soc/iomap.h>
+#include <amdblocks/gpio_banks.h>
+
+/* The following sections describe only the GPIOs defined for this SOC */
+
+#define SOC_GPIO_TOTAL_PINS 149
+
+/* Bank 0: GPIO_0 - GPIO_62 */
+#define GPIO_0 0
+#define GPIO_1 1
+#define GPIO_2 2
+#define GPIO_3 3
+#define GPIO_4 4
+#define GPIO_5 5
+#define GPIO_6 6
+#define GPIO_7 7
+#define GPIO_8 8
+#define GPIO_9 9
+#define GPIO_10 10
+#define GPIO_11 11
+#define GPIO_12 12
+#define GPIO_13 13
+#define GPIO_14 14
+#define GPIO_15 15
+#define GPIO_16 16
+#define GPIO_17 17
+#define GPIO_18 18
+#define GPIO_19 19
+#define GPIO_20 20
+#define GPIO_21 21
+#define GPIO_22 22
+#define GPIO_23 23
+#define GPIO_24 24
+#define GPIO_25 25
+#define GPIO_26 26
+#define GPIO_39 39
+#define GPIO_40 40
+#define GPIO_42 42
+
+/* Bank 1: GPIO_64 - GPIO_127 */
+#define GPIO_64 64
+#define GPIO_65 65
+#define GPIO_66 66
+#define GPIO_67 67
+#define GPIO_68 68
+#define GPIO_69 69
+#define GPIO_70 70
+#define GPIO_71 71
+#define GPIO_72 72
+#define GPIO_74 74
+#define GPIO_75 75
+#define GPIO_76 76
+#define GPIO_84 84
+#define GPIO_85 85
+#define GPIO_86 86
+#define GPIO_87 87
+#define GPIO_88 88
+#define GPIO_89 89
+#define GPIO_90 90
+#define GPIO_91 91
+#define GPIO_92 92
+#define GPIO_93 93
+#define GPIO_95 95
+#define GPIO_96 96
+#define GPIO_97 97
+#define GPIO_98 98
+#define GPIO_99 99
+#define GPIO_100 100
+#define GPIO_101 101
+#define GPIO_102 102
+#define GPIO_113 113
+#define GPIO_114 114
+#define GPIO_115 115
+#define GPIO_116 116
+#define GPIO_117 117
+#define GPIO_118 118
+#define GPIO_119 119
+#define GPIO_120 120
+#define GPIO_121 121
+#define GPIO_122 122
+#define GPIO_126 126
+
+/* Bank 2: GPIO_128 - GPIO_183 */
+#define GPIO_129 129
+#define GPIO_130 130
+#define GPIO_131 131
+#define GPIO_132 132
+#define GPIO_133 133
+#define GPIO_134 134
+#define GPIO_135 135
+#define GPIO_136 136
+#define GPIO_137 137
+#define GPIO_138 138
+#define GPIO_139 139
+#define GPIO_140 140
+#define GPIO_141 141
+#define GPIO_142 142
+#define GPIO_143 143
+#define GPIO_144 144
+#define GPIO_145 145
+#define GPIO_146 146
+#define GPIO_147 147
+#define GPIO_148 148
+
+#define GPIO_SCL_HIGH 0
+#define GPIO_SCL_LOW GPIO_OUTPUT_ENABLE
+
+/* IOMUX function names and values generated from BKDG. */
+#define GPIO_0_IOMUX_PWR_BTN_L 0
+#define GPIO_0_IOMUX_GPIOxx 1
+#define GPIO_1_IOMUX_SYS_RESET_L 0
+#define GPIO_1_IOMUX_GPIOxx 1
+#define GPIO_2_IOMUX_WAKE_L 0
+#define GPIO_2_IOMUX_GPIOxx 1
+#define GPIO_3_IOMUX_GPIOxx 0
+#define GPIO_4_IOMUX_GPIOxx 0
+#define GPIO_5_IOMUX_GPIOxx 0
+#define GPIO_5_IOMUX_DEVSLP0_S5 1
+#define GPIO_6_IOMUX_GPIOxx 0
+#define GPIO_6_IOMUX_LDT_RST_L 1
+#define GPIO_7_IOMUX_GPIOxx 0
+#define GPIO_7_IOMUX_LDT_PWROK 1
+#define GPIO_8_IOMUX_GPIOxx 0
+#define GPIO_8_IOMUX_SerPortTX_OUT 1
+#define GPIO_9_IOMUX_GPIOxx 0
+#define GPIO_9_IOMUX_SerPortRX_OUT 1
+#define GPIO_10_IOMUX_S0A3_GPIO 0
+#define GPIO_10_IOMUX_GPIOxx 1
+#define GPIO_11_IOMUX_GPIOxx 0
+#define GPIO_11_IOMUX_USB_OC7_L 1
+#define GPIO_12_IOMUX_IR_LED_L 0
+#define GPIO_12_IOMUX_LLB_L 1
+#define GPIO_12_IOMUX_GPIOxx 2
+#define GPIO_13_IOMUX_USB_OC5_L 0
+#define GPIO_13_IOMUX_GPIOxx 1
+#define GPIO_14_IOMUX_USB_OC6_L 0
+#define GPIO_14_IOMUX_GPIOxx 1
+#define GPIO_15_IOMUX_IR_RX1 0
+#define GPIO_15_IOMUX_GPIOxx 1
+#define GPIO_16_IOMUX_USB_OC0_L 0
+#define GPIO_16_IOMUX_TRST_L 1
+#define GPIO_16_IOMUX_GPIOxx 2
+#define GPIO_17_IOMUX_USB_OC1_L 0
+#define GPIO_17_IOMUX_TDI 1
+#define GPIO_17_IOMUX_GPIOxx 2
+#define GPIO_18_IOMUX_USB_OC2_L 0
+#define GPIO_18_IOMUX_TCK 1
+#define GPIO_18_IOMUX_GPIOxx 2
+#define GPIO_19_IOMUX_SCL1 0
+#define GPIO_19_IOMUX_I2C3_SCL 1
+#define GPIO_19_IOMUX_GPIOxx 2
+#define GPIO_20_IOMUX_SDA1 0
+#define GPIO_20_IOMUX_I2C3_SDA 1
+#define GPIO_20_IOMUX_GPIOxx 2
+#define GPIO_21_IOMUX_LPC_PD_L 0
+#define GPIO_21_IOMUX_GPIOxx 1
+#define GPIO_22_IOMUX_LPC_PME_L 0
+#define GPIO_22_IOMUX_GPIOxx 1
+#define GPIO_23_IOMUX_USB_OC4_L 0
+#define GPIO_23_IOMUX_IR_RX0 1
+#define GPIO_23_IOMUX_GPIOxx 2
+#define GPIO_24_IOMUX_USB_OC3_L 0
+#define GPIO_24_IOMUX_GPIOxx 1
+#define GPIO_25_IOMUX_SD0_CD 0
+#define GPIO_25_IOMUX_GPIOxx 1
+#define GPIO_26_IOMUX_PCIE_RST_L 0
+#define GPIO_26_IOMUX_GPIOxx 1
+#define GPIO_39_IOMUX_VDDGFX_PD 0
+#define GPIO_39_IOMUX_GPIOxx 1
+#define GPIO_40_IOMUX_GPIOxx 0
+#define GPIO_42_IOMUX_S5_MUX_CTRL 0
+#define GPIO_42_IOMUX_GPIOxx 1
+#define GPIO_64_IOMUX_GPIOxx 0
+#define GPIO_65_IOMUX_GPIOxx 0
+#define GPIO_66_IOMUX_GPIOxx 0
+#define GPIO_67_IOMUX_GPIOxx 0
+#define GPIO_67_IOMUX_DEVSLP0 1
+#define GPIO_69_IOMUX_GPIOxx 0
+#define GPIO_69_IOMUX_SGPIO_LOAD 1
+#define GPIO_70_IOMUX_GPIOxx 0
+#define GPIO_70_IOMUX_DEVSLP1 1
+#define GPIO_74_IOMUX_LPCCLK0 0
+#define GPIO_74_IOMUX_GPIOxx 1
+#define GPIO_75_IOMUX_LPCCLK1 0
+#define GPIO_75_IOMUX_GPIOxx 1
+#define GPIO_76_IOMUX_GPIOxx 0
+#define GPIO_76_IOMUX_SPI_TPM_CS_L 1
+#define GPIO_84_IOMUX_FANIN0 0
+#define GPIO_84_IOMUX_GPIOxx 1
+#define GPIO_85_IOMUX_FANOUT0 0
+#define GPIO_85_IOMUX_GPIOxx 1
+#define GPIO_86_IOMUX_GPIOxx 1
+#define GPIO_87_IOMUX_SERIRQ 0
+#define GPIO_87_IOMUX_GPIOxx 1
+#define GPIO_88_IOMUX_LPC_CLKRUN_L 0
+#define GPIO_88_IOMUX_GPIOxx 1
+#define GPIO_90_IOMUX_GPIOxx 0
+#define GPIO_91_IOMUX_SPKR 0
+#define GPIO_91_IOMUX_GPIOxx 1
+#define GPIO_92_IOMUX_CLK_REQ0_L 0
+#define GPIO_92_IOMUX_SATA_IS0_L 1
+#define GPIO_92_IOMUX_SATA_ZP0_L 2
+#define GPIO_92_IOMUX_GPIOxx 3
+#define GPIO_93_IOMUX_SD0_LED 0
+#define GPIO_93_IOMUX_GPIOxx 1
+#define GPIO_95_IOMUX_GPIOxx 0
+#define GPIO_96_IOMUX_GPIOxx 0
+#define GPIO_97_IOMUX_GPIOxx 0
+#define GPIO_98_IOMUX_GPIOxx 0
+#define GPIO_99_IOMUX_GPIOxx 0
+#define GPIO_100_IOMUX_GPIOxx 0
+#define GPIO_101_IOMUX_SD0_WP 0
+#define GPIO_101_IOMUX_GPIOxx 1
+#define GPIO_102_IOMUX_SD0_PWR_CTRL 0
+#define GPIO_102_IOMUX_GPIOxx 1
+#define GPIO_113_IOMUX_SCL0 0
+#define GPIO_113_IOMUX_I2C2_SCL 1
+#define GPIO_113_IOMUX_GPIOxx 2
+#define GPIO_114_IOMUX_SDA0 0
+#define GPIO_114_IOMUX_I2C2_SDA 1
+#define GPIO_114_IOMUX_GPIOxx 2
+#define GPIO_115_IOMUX_CLK_REQ1_L 0
+#define GPIO_115_IOMUX_GPIOxx 1
+#define GPIO_116_IOMUX_CLK_REQ2_L 0
+#define GPIO_116_IOMUX_GPIOxx 1
+#define GPIO_117_IOMUX_ESPI_CLK 0
+#define GPIO_117_IOMUX_GPIOxx 1
+#define GPIO_118_IOMUX_SPI_CS1_L 0
+#define GPIO_118_IOMUX_GPIOxx 1
+#define GPIO_119_IOMUX_SPI_CS2_L 0
+#define GPIO_119_IOMUX_ESPI_CS_L 1
+#define GPIO_119_IOMUX_GPIOxx 2
+#define GPIO_120_IOMUX_ESPI_DAT1 0
+#define GPIO_120_IOMUX_GPIOxx 1
+#define GPIO_121_IOMUX_ESPI_DAT0 0
+#define GPIO_121_IOMUX_GPIOxx 1
+#define GPIO_122_IOMUX_ESPI_DAT2 0
+#define GPIO_122_IOMUX_GPIOxx 1
+#define GPIO_126_IOMUX_GA20IN 0
+#define GPIO_126_IOMUX_GPIOxx 1
+#define GPIO_129_IOMUX_KBRST_L 0
+#define GPIO_129_IOMUX_GPIOxx 1
+#define GPIO_130_IOMUX_SATA_ACT_L 0
+#define GPIO_130_IOMUX_GPIOxx 1
+#define GPIO_131_IOMUX_CLK_REQ3_L 0
+#define GPIO_131_IOMUX_SATA_IS1_L 1
+#define GPIO_131_IOMUX_SATA_ZP1_L 2
+#define GPIO_131_IOMUX_GPIOxx 3
+#define GPIO_132_IOMUX_CLK_REQG_L 0
+#define GPIO_132_IOMUX_OSCIN 1
+#define GPIO_132_IOMUX_GPIOxx 2
+#define GPIO_133_IOMUX_ESPI_DAT3 0
+#define GPIO_133_IOMUX_GPIOxx 1
+#define GPIO_135_IOMUX_UART0_CTS_L 0
+#define GPIO_135_IOMUX_GPIOxx 1
+#define GPIO_136_IOMUX_UART0_RXD 0
+#define GPIO_136_IOMUX_GPIOxx 1
+#define GPIO_137_IOMUX_UART0_RTS_L 0
+#define GPIO_137_IOMUX_GPIOxx 1
+#define GPIO_138_IOMUX_UART0_TXD 0
+#define GPIO_138_IOMUX_GPIOxx 1
+#define GPIO_139_IOMUX_UART0_INTR 0
+#define GPIO_139_IOMUX_GPIOxx 1
+#define GPIO_140_IOMUX_UART1_CTS_L 0
+#define GPIO_140_IOMUX_GPIOxx 1
+#define GPIO_141_IOMUX_UART1_RXD 0
+#define GPIO_141_IOMUX_GPIOxx 1
+#define GPIO_142_IOMUX_UART1_RTS_L 0
+#define GPIO_142_IOMUX_GPIOxx 1
+#define GPIO_143_IOMUX_UART1_TXD 0
+#define GPIO_143_IOMUX_GPIOxx 1
+#define GPIO_144_IOMUX_UART1_INTR 0
+#define GPIO_144_IOMUX_GPIOxx 1
+#define GPIO_145_IOMUX_I2C0_SCL 0
+#define GPIO_145_IOMUX_GPIOxx 1
+#define GPIO_146_IOMUX_I2C0_SDA 0
+#define GPIO_146_IOMUX_GPIOxx 1
+#define GPIO_147_IOMUX_I2C1_SCL 0
+#define GPIO_147_IOMUX_GPIOxx 1
+#define GPIO_148_IOMUX_I2C1_SDA 0
+#define GPIO_148_IOMUX_GPIOxx 1
+
+#define GPIO_2_EVENT GEVENT_8
+
+#endif /* __ACPI__ */
+#endif /* __STONEYRIDGE_GPIO_H__ */
diff --git a/src/soc/amd/picasso/include/soc/i2c.h b/src/soc/amd/picasso/include/soc/i2c.h
new file mode 100644
index 0000000000..62575d0fb8
--- /dev/null
+++ b/src/soc/amd/picasso/include/soc/i2c.h
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2018 Advanced Micro Devices, 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.
+ */
+
+#ifndef __STONEYRIDGE_I2C_H__
+#define __STONEYRIDGE_I2C_H__
+
+#include <soc/gpio.h>
+
+struct soc_amd_i2c_save {
+ uint32_t control_value;
+ uint8_t mux_value;
+};
+
+#define GPIO_I2C0_SCL BIT(0)
+#define GPIO_I2C1_SCL BIT(1)
+#define GPIO_I2C2_SCL BIT(2)
+#define GPIO_I2C3_SCL BIT(3)
+#define GPIO_I2C_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3))
+
+#define I2C0_SCL_PIN GPIO_145
+#define I2C1_SCL_PIN GPIO_147
+#define I2C2_SCL_PIN GPIO_113
+#define I2C3_SCL_PIN GPIO_19
+
+#define GPIO_I2C0_ADDRESS GPIO_BANK2_CONTROL(I2C0_SCL_PIN)
+#define GPIO_I2C1_ADDRESS GPIO_BANK2_CONTROL(I2C1_SCL_PIN)
+#define GPIO_I2C2_ADDRESS GPIO_BANK1_CONTROL(I2C2_SCL_PIN)
+#define GPIO_I2C3_ADDRESS GPIO_BANK0_CONTROL(I2C3_SCL_PIN)
+
+#define I2C0_SCL_PIN_IOMUX_GPIOxx GPIO_145_IOMUX_GPIOxx
+#define I2C1_SCL_PIN_IOMUX_GPIOxx GPIO_147_IOMUX_GPIOxx
+#define I2C2_SCL_PIN_IOMUX_GPIOxx GPIO_113_IOMUX_GPIOxx
+#define I2C3_SCL_PIN_IOMUX_GPIOxx GPIO_19_IOMUX_GPIOxx
+
+void sb_reset_i2c_slaves(void);
+
+#endif /* __STONEYRIDGE_I2C_H__ */
diff --git a/src/soc/amd/picasso/include/soc/iomap.h b/src/soc/amd/picasso/include/soc/iomap.h
new file mode 100644
index 0000000000..612b6e871b
--- /dev/null
+++ b/src/soc/amd/picasso/include/soc/iomap.h
@@ -0,0 +1,88 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2017 Raptor Engineering, LLC
+ * Copyright 2017 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.
+ */
+
+#ifndef __SOC_STONEYRIDGE_IOMAP_H__
+#define __SOC_STONEYRIDGE_IOMAP_H__
+
+/* MMIO Ranges */
+#define PSP_MAILBOX_BAR3_BASE 0xf0a00000
+#define SPI_BASE_ADDRESS 0xfec10000
+#define IO_APIC2_ADDR 0xfec20000
+
+/*
+ * AcpiMmio blocks are at fixed offsets from FED8_0000h and enabled in PMx04[1].
+ * All ranges not specified as supported below may, or may not, be listed in
+ * any documentation but should be considered reserved through FED8_1FFFh.
+ */
+#include <amdblocks/acpimmio_map.h>
+#define SUPPORTS_ACPIMMIO_SMI_BASE 1 /* 0xfed80100 */
+#define SUPPORTS_ACPIMMIO_PMIO_BASE 1 /* 0xfed80300 */
+#define SUPPORTS_ACPIMMIO_BIOSRAM_BASE 1 /* 0xfed80500 */
+#define SUPPORTS_ACPIMMIO_ACPI_BASE 1 /* 0xfed80800 */
+#define SUPPORTS_ACPIMMIO_ASF_BASE 1 /* 0xfed80900 */
+#define SUPPORTS_ACPIMMIO_SMBUS_BASE 1 /* 0xfed80a00 */
+#define SUPPORTS_ACPIMMIO_IOMUX_BASE 1 /* 0xfed80d00 */
+#define SUPPORTS_ACPIMMIO_MISC_BASE 1 /* 0xfed80e00 */
+#define SUPPORTS_ACPIMMIO_GPIO0_BASE 1 /* 0xfed81500 */
+#define SUPPORTS_ACPIMMIO_GPIO1_BASE 1 /* 0xfed81800 */
+#define SUPPORTS_ACPIMMIO_GPIO2_BASE 1 /* 0xfed81700 */
+#define SUPPORTS_ACPIMMIO_XHCIPM_BASE 1 /* 0xfed81c00 */
+#define SUPPORTS_ACPIMMIO_AOAC_BASE 1 /* 0xfed81e00 */
+
+#define ALINK_AHB_ADDRESS 0xfedc0000
+
+/* I2C fixed address */
+#define I2C_BASE_ADDRESS 0xfedc2000
+#define I2C_DEVICE_SIZE 0x00001000
+#define I2C_DEVICE_COUNT 4
+
+#if CONFIG(HPET_ADDRESS_OVERRIDE)
+#error HPET address override is not allowed and must be fixed at 0xfed00000
+#endif
+#define HPET_BASE_ADDRESS 0xfed00000
+
+#define APU_UART0_BASE 0xfedc6000
+#define APU_UART1_BASE 0xfedc8000
+
+#define FLASH_BASE_ADDR ((0xffffffff - CONFIG_ROM_SIZE) + 1)
+
+/* I/O Ranges */
+#define ACPI_SMI_CTL_PORT 0xb2
+#define STONEYRIDGE_ACPI_IO_BASE CONFIG_STONEYRIDGE_ACPI_IO_BASE
+#define ACPI_PM_EVT_BLK (STONEYRIDGE_ACPI_IO_BASE + 0x00) /* 4 bytes */
+#define ACPI_PM1_STS (ACPI_PM_EVT_BLK + 0x00) /* 2 bytes */
+#define ACPI_PM1_EN (ACPI_PM_EVT_BLK + 0x02) /* 2 bytes */
+#define ACPI_PM1_CNT_BLK (STONEYRIDGE_ACPI_IO_BASE + 0x04) /* 2 bytes */
+#define ACPI_CPU_CONTROL (STONEYRIDGE_ACPI_IO_BASE + 0x08) /* 6 bytes */
+#define ACPI_GPE0_BLK (STONEYRIDGE_ACPI_IO_BASE + 0x10) /* 8 bytes */
+#define ACPI_GPE0_STS (ACPI_GPE0_BLK + 0x00) /* 4 bytes */
+#define ACPI_GPE0_EN (ACPI_GPE0_BLK + 0x04) /* 4 bytes */
+#define ACPI_PM_TMR_BLK (STONEYRIDGE_ACPI_IO_BASE + 0x18) /* 4 bytes */
+#define SMB_BASE_ADDR 0xb00
+#define PM2_INDEX 0xcd0
+#define PM2_DATA 0xcd1
+#define BIOSRAM_INDEX 0xcd4
+#define BIOSRAM_DATA 0xcd5
+#define AB_INDX 0xcd8
+#define AB_DATA (AB_INDX+4)
+#define SYS_RESET 0xcf9
+
+/* BiosRam Ranges at 0xfed80500 or I/O 0xcd4/0xcd5 */
+#define BIOSRAM_CBMEM_TOP 0xf0 /* 4 bytes */
+#define BIOSRAM_UMA_SIZE 0xf4 /* 4 bytes */
+#define BIOSRAM_UMA_BASE 0xf8 /* 8 bytes */
+
+#endif /* __SOC_STONEYRIDGE_IOMAP_H__ */
diff --git a/src/soc/amd/picasso/include/soc/northbridge.h b/src/soc/amd/picasso/include/soc/northbridge.h
new file mode 100644
index 0000000000..60a6ea22bb
--- /dev/null
+++ b/src/soc/amd/picasso/include/soc/northbridge.h
@@ -0,0 +1,133 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Advanced Micro Devices, Inc.
+ * Copyright (C) 2015 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __PI_STONEYRIDGE_NORTHBRIDGE_H__
+#define __PI_STONEYRIDGE_NORTHBRIDGE_H__
+
+#include <device/device.h>
+#include <types.h>
+
+/* D0F0 - Root Complex */
+
+/* NB IOAPIC registers */
+#define NB_IOAPIC_INDEX 0xf8
+#define NB_IOAPIC_DATA 0xfc
+#define NB_IOAPIC_FEATURE_CTRL 0x00
+#define NB_IOAPIC_ADDRESS_LOW 0x01
+#define NB_IOAPIC_ADDRESS_HIGH 0x02
+#define NB_IOAPIC_GBIF_IRR 0x0f
+#define NB_IOAPIC_BR0_IRR 0x10
+#define NB_IOAPIC_BR1_IRR 0x11
+#define NB_IOAPIC_BR2_IRR 0x12
+#define NB_IOAPIC_BR3_IRR 0x13
+#define NB_IOAPIC_BR4_IRR 0x14
+#define NB_IOAPIC_APG_IRR 0x2f
+#define NB_IOAPIC_SPG_IRR 0x30
+#define NB_IOAPIC_SER_IRQ_IRR 0x31
+#define NB_IOAPIC_SCRATCH0 0x3e
+#define NB_IOAPIC_SCRATCH1 0x3f
+
+#define AP_SCRATCH_REG NB_IOAPIC_SCRATCH0
+
+/* D1F1 - HDA Configuration Registers */
+#define HDA_DEV_CTRL_STATUS 0x60
+#define HDA_NO_SNOOP_EN BIT(11)
+
+/* D18F0 - HT Configuration Registers */
+#define D18F0_NODE_ID 0x60
+#define D18F0_CPU_CNT 0x62 /* BKDG defines as a field in DWORD 0x60 */
+# define CPU_CNT_MASK 0x1f /* CpuCnt + 1 = no. CPUs */
+#define HT_INIT_CONTROL 0x6c
+# define HTIC_BIOSR_DETECT ((1 << 5) | (1 << 9) | (1 << 10))
+# define HTIC_COLD_RST_DET BIT(4)
+
+/* D18F1 - Address Map Registers */
+
+/* MMIO base and limit */
+#define D18F1_MMIO_BASE0_LO 0x80
+# define MMIO_WE (1 << 1)
+# define MMIO_RE (1 << 0)
+#define D18F1_MMIO_LIMIT0_LO 0x84
+# define MMIO_NP (1 << 7)
+#define D18F1_IO_BASE0_LO 0xc0
+#define D18F1_IO_BASE1_LO 0xc8
+#define D18F1_IO_BASE2_LO 0xd0
+#define D18F1_IO_BASE3_LO 0xd8
+#define D18F1_MMIO_BASE7_LO 0xb8
+#define D18F1_MMIO_BASELIM0_HI 0x180
+#define D18F1_MMIO_BASE8_LO 0x1a0
+#define D18F1_MMIO_LIMIT8_LO 0x1a4
+#define D18F1_MMIO_BASE11_LO 0x1b8
+#define D18F1_MMIO_BASELIM8_HI 0x1c0
+#define NB_MMIO_BASE_LO(reg) ((reg) * 2 * sizeof(uint32_t) + (((reg) < 8) \
+ ? D18F1_MMIO_BASE0_LO \
+ : D18F1_MMIO_BASE8_LO \
+ - 8 * sizeof(uint64_t)))
+#define NB_MMIO_LIMIT_LO(reg) (NB_MMIO_BASE_LO(reg) + sizeof(uint32_t))
+#define NB_MMIO_BASELIM_HI(reg) ((reg) * sizeof(uint32_t) + (((reg) < 8) \
+ ? D18F1_MMIO_BASELIM0_HI \
+ : D18F1_MMIO_BASELIM8_HI \
+ - 8 * sizeof(uint32_t)))
+/* I/O base and limit */
+#define D18F1_IO_BASE0 0xc0
+# define IO_WE (1 << 1)
+# define IO_RE (1 << 0)
+#define D18F1_IO_LIMIT0 0xc4
+#define NB_IO_BASE(reg) ((reg) * 2 * sizeof(uint32_t) + D18F1_IO_BASE0)
+#define NB_IO_LIMIT(reg) (NB_IO_BASE(reg) + sizeof(uint32_t))
+
+#define D18F1_DRAM_HOLE 0xf0
+# define DRAM_HOIST_VALID (1 << 1)
+# define DRAM_HOLE_VALID (1 << 0)
+#define D18F1_VGAEN 0xf4
+# define VGA_ADDR_ENABLE (1 << 0)
+
+/* D18F5 */
+#define NB_CAPABILITIES2 0x84
+#define CMP_CAP_MASK 0xff
+
+enum {
+ /* SMM handler area. */
+ SMM_SUBREGION_HANDLER,
+ /* SMM cache region. */
+ SMM_SUBREGION_CACHE,
+ /* Chipset specific area. */
+ SMM_SUBREGION_CHIPSET,
+ /* Total sub regions supported. */
+ SMM_SUBREGION_NUM,
+};
+
+/*
+ * Fills in the arguments for the entire SMM region covered by chipset
+ * protections. e.g. TSEG.
+ */
+void smm_region_info(void **start, size_t *size);
+/*
+ * Fills in the start and size for the requested SMM subregion. Returns
+ * 0 on success, < 0 on failure.
+ */
+int smm_subregion(int sub, void **start, size_t *size);
+void domain_enable_resources(struct device *dev);
+void domain_set_resources(struct device *dev);
+void fam15_finalize(void *chip_info);
+uint32_t nb_ioapic_read(unsigned int index);
+void nb_ioapic_write(unsigned int index, uint32_t value);
+void *get_ap_entry_ptr(void);
+void set_ap_entry_ptr(void *entry);
+void set_warm_reset_flag(void);
+int is_warm_reset(void);
+
+#endif /* __PI_STONEYRIDGE_NORTHBRIDGE_H__ */
diff --git a/src/soc/amd/picasso/include/soc/nvs.h b/src/soc/amd/picasso/include/soc/nvs.h
new file mode 100644
index 0000000000..08d46973c0
--- /dev/null
+++ b/src/soc/amd/picasso/include/soc/nvs.h
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.)
+ *
+ * This program is free software; 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.
+ */
+
+/*
+ * NOTE: The layout of the global_nvs_t structure below must match the layout
+ * in soc/soc/amd/stoneyridge/acpi/globalnvs.asl !!!
+ *
+ */
+
+#ifndef __SOC_STONEYRIDGE_NVS_H__
+#define __SOC_STONEYRIDGE_NVS_H__
+
+#include <commonlib/helpers.h>
+#include <stdint.h>
+#include <vendorcode/google/chromeos/gnvs.h>
+#include <soc/southbridge.h>
+
+typedef struct global_nvs_t {
+ /* Miscellaneous */
+ uint8_t pcnt; /* 0x00 - Processor Count */
+ uint8_t ppcm; /* 0x01 - Max PPC State */
+ uint8_t lids; /* 0x02 - LID State */
+ uint8_t pwrs; /* 0x03 - AC Power State */
+ uint8_t dpte; /* 0x04 - Enable DPTF */
+ uint32_t cbmc; /* 0x05 - 0x08 - coreboot Memory Console */
+ uint64_t pm1i; /* 0x09 - 0x10 - System Wake Source - PM1 Index */
+ uint64_t gpei; /* 0x11 - 0x18 - GPE Wake Source */
+ uint64_t nhla; /* 0x19 - 0x20 - NHLT Address */
+ uint32_t nhll; /* 0x21 - 0x24 - NHLT Length */
+ uint32_t prt0; /* 0x25 - 0x28 - PERST_0 Address */
+ uint8_t scdp; /* 0x29 - SD_CD GPIO portid */
+ uint8_t scdo; /* 0x2A - GPIO pad relative offset */
+ uint8_t tmps; /* 0x2B - Temperature Sensor ID */
+ uint8_t tlvl; /* 0x2C - Throttle Level Limit */
+ uint8_t flvl; /* 0x2D - Current FAN Level */
+ uint8_t tcrt; /* 0x2E - Critical Threshold */
+ uint8_t tpsv; /* 0x2F - Passive Threshold */
+ uint8_t tmax; /* 0x30 - CPU Tj_max */
+ uint8_t pad1[3];
+ aoac_devs_t aoac; /* 0x34 - AOAC device enables */
+ uint16_t fw00; /* 0x38 - XhciFwRomAddr_Rom, Boot RAM */
+ uint16_t fw02; /* 0x3A - XhciFwRomAddr_Ram, Instr RAM */
+ uint32_t fw01; /* 0x3C - XhciFwRamAddr_Rom, Boot RAM sz/base */
+ uint32_t fw03; /* 0x40 - XhciFwRomAddr_Ram, Instr RAM sz/base */
+ uint32_t eh10; /* 0x40 - EHCI BAR */
+ uint8_t unused[184];
+
+ /* ChromeOS specific (0x100 - 0xfff) */
+ chromeos_acpi_t chromeos;
+} __packed global_nvs_t;
+check_member(global_nvs_t, chromeos, GNVS_CHROMEOS_ACPI_OFFSET);
+
+#endif /* __SOC_STONEYRIDGE_NVS_H__ */
diff --git a/src/soc/amd/picasso/include/soc/pci_devs.h b/src/soc/amd/picasso/include/soc/pci_devs.h
new file mode 100644
index 0000000000..02fed7ab1e
--- /dev/null
+++ b/src/soc/amd/picasso/include/soc/pci_devs.h
@@ -0,0 +1,198 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Sage Electronic Engineering, LLC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __PI_STONEYRIDGE_PCI_DEVS_H__
+#define __PI_STONEYRIDGE_PCI_DEVS_H__
+
+#include <device/pci_def.h>
+
+#if !defined(__SIMPLE_DEVICE__)
+#include <device/device.h>
+#define _SOC_DEV(slot, func) pcidev_on_root(slot, func)
+#else
+#define _SOC_DEV(slot, func) PCI_DEV(0, slot, func)
+#endif
+
+/* GNB Root Complex */
+#define GNB_DEV 0x0
+#define GNB_FUNC 0
+#define GNB_DEVID 0x1576
+#define GNB_DEVFN PCI_DEVFN(GNB_DEV, GNB_FUNC)
+#define SOC_GNB_DEV _SOC_DEV(GNB_DEV, GNB_FUNC)
+
+/* IOMMU */
+#define IOMMU_DEV 0x0
+#define IOMMU_FUNC 2
+#define IOMMU_DEVID 0x1577
+#define IOMMU_DEVFN PCI_DEVFN(IOMMU_DEV, IOMMU_FUNC)
+#define SOC_IOMMU_DEV _SOC_DEV(IOMMU_DEV, IOMMU_FUNC)
+
+/* Internal Graphics */
+#define GFX_DEV 0x1
+#define GFX_FUNC 0
+#define GFX_DEVID 0x98e4 /* subject to SKU/OPN variation */
+#define GFX_DEVFN PCI_DEVFN(GFX_DEV, GFX_FUNC)
+#define SOC_GFX_DEV _SOC_DEV(GFX_DEV, GFX_FUNC)
+
+/* HD Audio 0 */
+#define HDA0_DEV 0x1
+#define HDA0_FUNC 1
+#define HDA0_DEVID 0x15b3
+#define HDA0_DEVFN PCI_DEVFN(HDA0_DEV, HDA0_FUNC)
+#define SOC_HDA0_DEV _SOC_DEV(HDA0_DEV, HDA0_FUNC)
+
+/* Host Bridge */
+#define HOST_DEV 0x2
+#define HOST_FUNC 0
+#define HOST_DEVID 0x157b
+#define HOST_DEVFN PCI_DEVFN(HOST_DEV, HOST_FUNC)
+#define SOC_HOST_DEV _SOC_DEV(HOST_DEV, HOST_FUNC)
+
+/* PCIe GPP Bridge 0 */
+#define PCIE0_DEV 0x2
+#define PCIE0_FUNC 1
+#define PCIE0_DEVID 0x157c
+#define PCIE0_DEVFN PCI_DEVFN(PCIE0_DEV, PCIE0_FUNC)
+#define SOC_PCIE0_DEV _SOC_DEV(PCIE0_DEV, PCIE0_FUNC)
+
+/* PCIe GPP Bridge 1 */
+#define PCIE1_DEV 0x2
+#define PCIE1_FUNC 2
+#define PCIE1_DEVID 0x157c
+#define PCIE1_DEVFN PCI_DEVFN(PCIE1_DEV, PCIE1_FUNC)
+#define SOC_PCIE1_DEV _SOC_DEV(PCIE1_DEV, PCIE1_FUNC)
+
+/* PCIe GPP Bridge 2 */
+#define PCIE2_DEV 0x2
+#define PCIE2_FUNC 3
+#define PCIE2_DEVID 0x157c
+#define PCIE2_DEVFN PCI_DEVFN(PCIE2_DEV, PCIE2_FUNC)
+#define SOC_PCIE2_DEV _SOC_DEV(PCIE2_DEV, PCIE2_FUNC)
+
+/* PCIe GPP Bridge 3 */
+#define PCIE3_DEV 0x2
+#define PCIE3_FUNC 4
+#define PCIE3_DEVID 0x157c
+#define PCIE3_DEVFN PCI_DEVFN(PCIE3_DEV, PCIE3_FUNC)
+#define SOC_PCIE3_DEV _SOC_DEV(PCIE3_DEV, PCIE3_FUNC)
+
+/* PCIe GPP Bridge 4 */
+#define PCIE4_DEV 0x2
+#define PCIE4_FUNC 5
+#define PCIE4_DEVID 0x157c
+#define PCIE4_DEVFN PCI_DEVFN(PCIE4_DEV, PCIE4_FUNC)
+#define SOC_PCIE4_DEV _SOC_DEV(PCIE4_DEV, PCIE4_FUNC)
+
+/* Platform Security Processor */
+#define PSP_DEV 0x8
+#define PSP_FUNC 0
+#define PSP_DEVID 0x1578
+#define PSP_DEVFN PCI_DEVFN(PSP_DEV, PSP_FUNC)
+#define SOC_PSP_DEV _SOC_DEV(PSP_DEV, PSP_FUNC)
+
+/* HD Audio 1 */
+#define HDA1_DEV 0x9
+#define HDA1_FUNC 2
+#define HDA1_DEVID 0x157a
+#define HDA1_DEVFN PCI_DEVFN(HDA1_DEV, HDA1_FUNC)
+#define SOC_HDA1_DEV _SOC_DEV(HDA1_DEV, HDA1_FUNC)
+
+/* HT Configuration */
+#define HT_DEV 0x18
+#define HT_FUNC 0
+#define HT_DEVID 0x15b0
+#define HT_DEVFN PCI_DEVFN(HT_DEV, HT_FUNC)
+#define SOC_HT_DEV _SOC_DEV(HT_DEV, HT_FUNC)
+
+/* Address Maps */
+#define ADDR_DEV 0x18
+#define ADDR_FUNC 1
+#define ADDR_DEVID 0x15b1
+#define ADDR_DEVFN PCI_DEVFN(ADDR_DEV, ADDR_FUNC)
+#define SOC_ADDR_DEV _SOC_DEV(ADDR_DEV, ADDR_FUNC)
+
+/* DRAM Configuration */
+#define DCT_DEV 0x18
+#define DCT_FUNC 2
+#define DCT_DEVID 0x15b2
+#define DCT_DEVFN PCI_DEVFN(DCT_DEV, DCT_FUNC)
+#define SOC_DCT_DEV _SOC_DEV(DCT_DEV, DCT_FUNC)
+
+/* Misc. Configuration */
+#define MISC_DEV 0x18
+#define MISC_FUNC 3
+#define MISC_DEVID 0x15b3
+#define MISC_DEVFN PCI_DEVFN(MISC_DEV, MISC_FUNC)
+#define SOC_MISC_DEV _SOC_DEV(MISC_DEV, MISC_FUNC)
+
+/* PM Configuration */
+#define PM_DEV 0x18
+#define PM_FUNC 4
+#define PM_DEVID 0x15b4
+#define PM_DEVFN PCI_DEVFN(PM_DEV, PM_FUNC)
+#define SOC_PM_DEV _SOC_DEV(PM_DEV, PM_FUNC)
+
+/* Northbridge Configuration */
+#define NB_DEV 0x18
+#define NB_FUNC 5
+#define NB_DEVID 0x15b5
+#define NB_DEVFN PCI_DEVFN(NB_DEV, NB_FUNC)
+#define SOC_NB_DEV _SOC_DEV(NB_DEV, NB_FUNC)
+
+/* XHCI */
+#define XHCI_DEV 0x10
+#define XHCI_FUNC 0
+#define XHCI_DEVID 0x7914
+#define XHCI_DEVFN PCI_DEVFN(XHCI_DEV, XHCI_FUNC)
+#define SOC_XHCI_DEV _SOC_DEV(XHCI_DEV, XHCI_FUNC)
+
+/* SATA */
+#define SATA_DEV 0x11
+#define SATA_FUNC 0
+#define SATA_IDE_DEVID 0x7900
+#define AHCI_DEVID_MS 0x7901
+#define AHCI_DEVID_AMD 0x7904
+#define SATA_DEVFN PCI_DEVFN(SATA_DEV, SATA_FUNC)
+#define SOC_SATA_DEV _SOC_DEV(SATA_DEV, SATA_FUNC)
+
+/* EHCI */
+#define EHCI_DEV 0x12
+#define EHCI_FUNC 0
+#define EHCI_DEVID 0x7908
+#define EHCI1_DEVFN PCI_DEVFN(EHCI_DEV, EHCI_FUNC)
+#define SOC_EHCI1_DEV _SOC_DEV(EHCI_DEV, EHCI_FUNC)
+
+/* SMBUS */
+#define SMBUS_DEV 0x14
+#define SMBUS_FUNC 0
+#define SMBUS_DEVID 0x790b
+#define SMBUS_DEVFN PCI_DEVFN(SMBUS_DEV, SMBUS_FUNC)
+#define SOC_SMBUS_DEV _SOC_DEV(SMBUS_DEV, SMBUS_FUNC)
+
+/* LPC BUS */
+#define PCU_DEV 0x14
+#define LPC_FUNC 3
+#define LPC_DEVID 0x790e
+#define LPC_DEVFN PCI_DEVFN(PCU_DEV, LPC_FUNC)
+#define SOC_LPC_DEV _SOC_DEV(PCU_DEV, LPC_FUNC)
+
+/* SD Controller */
+#define SD_DEV 0x14
+#define SD_FUNC 7
+#define SD_DEVID 0x7906
+#define SD_DEVFN PCI_DEVFN(SD_DEV, SD_FUNC)
+#define SOC_SD_DEV _SOC_DEV(SD_DEV, SD_FUNC)
+
+#endif /* __PI_STONEYRIDGE_PCI_DEVS_H__ */
diff --git a/src/soc/amd/picasso/include/soc/romstage.h b/src/soc/amd/picasso/include/soc/romstage.h
new file mode 100644
index 0000000000..6ce79b424e
--- /dev/null
+++ b/src/soc/amd/picasso/include/soc/romstage.h
@@ -0,0 +1,21 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2018 Google 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.
+ */
+
+#ifndef __STONEYRIDGE_ROMSTAGE_H__
+#define __STONEYRIDGE_ROMSTAGE_H__
+
+void mainboard_romstage_entry(int s3_resume);
+
+#endif /* __STONEYRIDGE_ROMSTAGE_H__ */
diff --git a/src/soc/amd/picasso/include/soc/smbus.h b/src/soc/amd/picasso/include/soc/smbus.h
new file mode 100644
index 0000000000..391084d807
--- /dev/null
+++ b/src/soc/amd/picasso/include/soc/smbus.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010 Advanced Micro Devices, 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.
+ */
+
+#ifndef __STONEYRIDGE_SMBUS_H__
+#define __STONEYRIDGE_SMBUS_H__
+
+#include <stdint.h>
+#include <soc/iomap.h>
+
+#define SMB_SPEED_400KHZ (66000000 / (400000 * 4))
+
+/*
+ * Between 1-10 seconds, We should never timeout normally
+ * Longer than this is just painful when a timeout condition occurs.
+ */
+#define SMBUS_TIMEOUT (100 * 1000 * 10)
+
+int do_smbus_read_byte(u32 mmio, u8 device, u8 address);
+int do_smbus_write_byte(u32 mmio, u8 device, u8 address, u8 val);
+int do_smbus_recv_byte(u32 mmio, u8 device);
+int do_smbus_send_byte(u32 mmio, u8 device, u8 val);
+
+#endif /* __STONEYRIDGE_SMBUS_H__ */
diff --git a/src/soc/amd/picasso/include/soc/smi.h b/src/soc/amd/picasso/include/soc/smi.h
new file mode 100644
index 0000000000..000eed8554
--- /dev/null
+++ b/src/soc/amd/picasso/include/soc/smi.h
@@ -0,0 +1,242 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2017 Advanced Micro Devices, Inc.
+ * Copyright (C) 2014 Alexandru Gagniuc <mr.nuke.me@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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.
+ */
+
+#ifndef __SOUTHBRIDGE_AMD_PI_STONEYRIDGE_SMI_H__
+#define __SOUTHBRIDGE_AMD_PI_STONEYRIDGE_SMI_H__
+
+
+#define SMI_GEVENTS 24
+#define SCIMAPS 58
+#define SCI_GPES 32
+
+#define SMI_EVENT_STATUS 0x0
+#define SMI_EVENT_ENABLE 0x04
+#define SMI_SCI_TRIG 0x08
+#define SMI_SCI_LEVEL 0x0c
+#define SMI_SCI_STATUS 0x10
+#define SMI_SCI_EN 0x14
+#define SMI_SCI_MAP0 0x40
+# define SMI_SCI_MAP(X) (SMI_SCI_MAP0 + (X))
+
+/* SMI source and status */
+#define SMITYPE_AGPIO65 0
+#define SMITYPE_AGPIO66 1
+#define SMITYPE_AGPIO3 2
+#define SMITYPE_LPCPME_AGPIO22 3
+#define SMITYPE_GPIO4 4
+#define SMITYPE_LPCPD_AGPIOG21 5
+#define SMITYPE_IRTX1_G15 6
+#define SMITYPE_AGPIO5_DEVSLP0 7
+#define SMITYPE_WAKE_AGPIO2 8
+#define SMITYPE_APIO68_SGPIOCLK 9
+#define SMITYPE_AGPIO6 10
+#define SMITYPE_GPIO7 11
+#define SMITYPE_USBOC0_TRST_AGPIO16 12
+#define SMITYPE_USB0C1_TDI_AGPIO17 13
+#define SMITYPE_USBOC2_TCK_AGPIO18 14
+#define SMITYPE_TDO_USB0C3_AGPIO24 15
+#define SMITYPE_ACPRES_USBOC4_IRRX0_AGPIO23 16
+/* 17 Reserved */
+#define SMITYPE_BLINK_AGPIO11_USBOC7 18
+#define SMITYPE_SYSRESET_AGPIO1 19
+#define SMITYPE_IRRX1_AGPIO15 20
+#define SMITYPE_IRTX0_USBOC5_AGPIO13 21
+#define SMITYPE_GPIO9_SERPORTRX 22
+#define SMITYPE_GPIO8_SEPORTTX 23
+#define GEVENT_MASK ((1 << SMITYPE_AGPIO65) \
+ | (1 << SMITYPE_AGPIO66) \
+ | (1 << SMITYPE_AGPIO3) \
+ | (1 << SMITYPE_LPCPME_AGPIO22) \
+ | (1 << SMITYPE_GPIO4) \
+ | (1 << SMITYPE_LPCPD_AGPIOG21) \
+ | (1 << SMITYPE_IRTX1_G15) \
+ | (1 << SMITYPE_AGPIO5_DEVSLP0) \
+ | (1 << SMITYPE_WAKE_AGPIO2) \
+ | (1 << SMITYPE_APIO68_SGPIOCLK) \
+ | (1 << SMITYPE_AGPIO6) \
+ | (1 << SMITYPE_GPIO7) \
+ | (1 << SMITYPE_USBOC0_TRST_AGPIO16) \
+ | (1 << SMITYPE_USB0C1_TDI_AGPIO17) \
+ | (1 << SMITYPE_USBOC2_TCK_AGPIO18) \
+ | (1 << SMITYPE_TDO_USB0C3_AGPIO24) \
+ | (1 << SMITYPE_ACPRES_USBOC4_IRRX0_AGPIO23) \
+ | (1 << SMITYPE_BLINK_AGPIO11_USBOC7) \
+ | (1 << SMITYPE_SYSRESET_AGPIO1) \
+ | (1 << SMITYPE_IRRX1_AGPIO15) \
+ | (1 << SMITYPE_IRTX0_USBOC5_AGPIO13) \
+ | (1 << SMITYPE_GPIO9_SERPORTRX))
+#define SMITYPE_EHCI0_WAKE 24
+#define SMITYPE_EHCI1_WAKE 25
+#define SMITYPE_ESPI_SYS 26
+#define SMITYPE_ESPI_WAKE_PME 27
+/* 28-32 Reserved */
+#define SMITYPE_FCH_FAKE0 33
+#define SMITYPE_FCH_FAKE1 34
+#define SMITYPE_FCH_FAKE2 35
+/* 36 Reserved */
+#define SMITYPE_SATA_GEVENT0 37
+#define SMITYPE_SATA_GEVENT1 38
+#define SMITYPE_ACP_WAKE 39
+#define SMITYPE_ECG 40
+#define SMITYPE_GPIO_CTL 41
+#define SMITYPE_CIR_PME 42
+#define SMITYPE_ALT_HPET_ALARM 43
+#define SMITYPE_FAN_THERMAL 44
+#define SMITYPE_ASF_MASTER_SLAVE 45
+#define SMITYPE_I2S_WAKE 46
+#define SMITYPE_SMBUS0_MASTER 47
+#define SMITYPE_TWARN 48
+#define SMITYPE_TRAFFIC_MON 49
+#define SMITYPE_ILLB 50
+#define SMITYPE_PWRBUTTON_UP 51
+#define SMITYPE_PROCHOT 52
+#define SMITYPE_APU_HW 53
+#define SMITYPE_NB_SCI 54
+#define SMITYPE_RAS_SERR 55
+#define SMITYPE_XHC0_PME 56
+/* 57 Reserved */
+#define SMITYPE_ACDC_TIMER 58
+/* 59-62 Reserved */
+#define SMITYPE_TEMP_TSI 63
+#define SMITYPE_KB_RESET 64
+#define SMITYPE_SLP_TYP 65
+#define SMITYPE_AL2H_ACPI 66
+#define SMITYPE_AHCI 67
+/* 68-71 Reserved */
+#define SMITYPE_GBL_RLS 72
+#define SMITYPE_BIOS_RLS 73
+#define SMITYPE_PWRBUTTON_DOWN 74
+#define SMITYPE_SMI_CMD_PORT 75
+#define SMITYPE_USB_SMI 76
+#define SMITYPE_SERIRQ 77
+#define SMITYPE_SMBUS0_INTR 78
+#define SMITYPE_XHC_ERROR 80
+#define SMITYPE_INTRUDER 81
+#define SMITYPE_VBAT_LOW 82
+#define SMITYPE_PROTHOT 83
+#define SMITYPE_PCI_SERR 84
+#define SMITYPE_GPP_SERR 85
+/* 85-88 Reserved */
+#define SMITYPE_TMERTRIP 89
+#define SMITYPE_EMUL60_64 90
+#define SMITYPE_USB_FLR 91
+#define SMITYPE_SATA_FLR 92
+#define SMITYPE_AZ_FLR 93
+/* 94-132 Reserved */
+#define SMITYPE_FANIN0 133
+/* 134-137 Reserved */
+#define SMITYPE_FAKE0 138
+#define SMITYPE_FAKE1 139
+#define SMITYPE_FAKE2 140
+/* 141 Reserved */
+#define SMITYPE_SHORT_TIMER 142
+#define SMITYPE_LONG_TIMER 143
+#define SMITYPE_AB_SMI 144
+#define SMITYPE_SOFT_RESET 145
+/* 146-147 Reserved */
+#define SMITYPE_IOTRAP0 148
+/* 149-151 Reserved */
+#define SMITYPE_MEMTRAP0 152
+/* 153-155 Reserved */
+#define SMITYPE_CFGTRAP0 156
+/* 157-159 Reserved */
+#define NUMBER_SMITYPES 160
+#define TYPE_TO_MASK(X) (1 << (X) % 32)
+
+#define SMI_REG_SMISTS0 0x80
+#define SMI_REG_SMISTS1 0x84
+#define SMI_REG_SMISTS2 0x88
+#define SMI_REG_SMISTS3 0x8c
+#define SMI_REG_SMISTS4 0x90
+
+#define SMI_REG_POINTER 0x94
+# define SMI_STATUS_SRC_SCI (1 << 0)
+# define SMI_STATUS_SRC_0 (1 << 1) /* SMIx80 */
+# define SMI_STATUS_SRC_1 (1 << 2) /* SMIx84... */
+# define SMI_STATUS_SRC_2 (1 << 3)
+# define SMI_STATUS_SRC_3 (1 << 4)
+# define SMI_STATUS_SRC_4 (1 << 5)
+
+#define SMI_TIMER 0x96
+#define SMI_TIMER_MASK 0x7fff
+#define SMI_TIMER_EN (1 << 15)
+
+#define SMI_REG_SMITRIG0 0x98
+# define SMITRG0_EOS (1 << 28)
+# define SMI_TIMER_SEL (1 << 29)
+# define SMITRG0_SMIENB (1 << 31)
+
+#define SMI_REG_CONTROL0 0xa0
+#define SMI_REG_CONTROL1 0xa4
+#define SMI_REG_CONTROL2 0xa8
+#define SMI_REG_CONTROL3 0xac
+#define SMI_REG_CONTROL4 0xb0
+#define SMI_REG_CONTROL5 0xb4
+#define SMI_REG_CONTROL6 0xb8
+#define SMI_REG_CONTROL7 0xbc
+#define SMI_REG_CONTROL8 0xc0
+#define SMI_REG_CONTROL9 0xc4
+
+enum smi_mode {
+ SMI_MODE_DISABLE = 0,
+ SMI_MODE_SMI = 1,
+ SMI_MODE_NMI = 2,
+ SMI_MODE_IRQ13 = 3,
+};
+
+enum smi_sci_type {
+ INTERRUPT_NONE,
+ INTERRUPT_SCI,
+ INTERRUPT_SMI,
+ INTERRUPT_BOTH,
+};
+
+enum smi_sci_lvl {
+ SMI_SCI_LVL_LOW,
+ SMI_SCI_LVL_HIGH,
+};
+
+enum smi_sci_dir {
+ SMI_SCI_EDG,
+ SMI_SCI_LVL,
+};
+
+struct smi_sources_t {
+ int type;
+ void (*handler)(void);
+};
+
+struct sci_source {
+ uint8_t scimap; /* SCIMAP 0-57 */
+ uint8_t gpe; /* 32 GPEs */
+ uint8_t direction; /* Active High or Low, smi_sci_lvl */
+ uint8_t level; /* Edge or Level, smi_sci_dir */
+};
+
+uint16_t pm_acpi_smi_cmd_port(void);
+void configure_smi(uint8_t smi_num, uint8_t mode);
+void configure_gevent_smi(uint8_t gevent, uint8_t mode, uint8_t level);
+void configure_scimap(const struct sci_source *sci);
+void disable_gevent_smi(uint8_t gevent);
+void gpe_configure_sci(const struct sci_source *scis, size_t num_gpes);
+void soc_route_sci(uint8_t event);
+
+#ifndef __SMM__
+void enable_smi_generation(void);
+#endif
+
+#endif /* __SOUTHBRIDGE_AMD_PI_STONEYRIDGE_SMI_H__ */
diff --git a/src/soc/amd/picasso/include/soc/southbridge.h b/src/soc/amd/picasso/include/soc/southbridge.h
new file mode 100644
index 0000000000..ad4040759c
--- /dev/null
+++ b/src/soc/amd/picasso/include/soc/southbridge.h
@@ -0,0 +1,415 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010-2017 Advanced Micro Devices, 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.
+ */
+
+#ifndef __STONEYRIDGE_H__
+#define __STONEYRIDGE_H__
+
+#include <types.h>
+#include <device/device.h>
+#include <device/pci_def.h>
+#include <soc/iomap.h>
+#include "chip.h"
+
+/*
+ * AcpiMmio Region
+ * - fixed addresses offset from 0xfed80000
+ */
+
+/* Power management registers: 0xfed80300 or index/data at IO 0xcd6/cd7 */
+#define PM_DECODE_EN 0x00
+#define CF9_IO_EN BIT(1)
+#define LEGACY_IO_EN BIT(0)
+#define PM_ISA_CONTROL 0x04
+#define MMIO_EN BIT(1)
+#define PM_PCI_CTRL 0x08
+#define FORCE_SLPSTATE_RETRY BIT(25)
+#define FORCE_STPCLK_RETRY BIT(24)
+
+#define SMB_ASF_IO_BASE 0x01 /* part of PM_DECODE_EN */
+
+#define PWR_RESET_CFG 0x10
+#define TOGGLE_ALL_PWR_GOOD BIT(1)
+
+#define PM_SERIRQ_CONF 0x54
+#define PM_SERIRQ_NUM_BITS_17 0x0000
+#define PM_SERIRQ_NUM_BITS_18 0x0004
+#define PM_SERIRQ_NUM_BITS_19 0x0008
+#define PM_SERIRQ_NUM_BITS_20 0x000c
+#define PM_SERIRQ_NUM_BITS_21 0x0010
+#define PM_SERIRQ_NUM_BITS_22 0x0014
+#define PM_SERIRQ_NUM_BITS_23 0x0018
+#define PM_SERIRQ_NUM_BITS_24 0x001c
+#define PM_SERIRQ_MODE BIT(6)
+#define PM_SERIRQ_ENABLE BIT(7)
+
+#define PM_RTC_SHADOW 0x5b /* state when power resumes */
+#define PM_S5_AT_POWER_RECOVERY 0x04 /* S5 */
+#define PM_RESTORE_S0_IF_PREV_S0 0x07 /* S0 if previously at S0 */
+
+#define PM_EVT_BLK 0x60
+#define WAK_STS BIT(15) /*AcpiPmEvtBlkx00 Pm1Status */
+#define PCIEXPWAK_STS BIT(14)
+#define RTC_STS BIT(10)
+#define PWRBTN_STS BIT(8)
+#define GBL_STS BIT(5)
+#define BM_STS BIT(4)
+#define TIMER_STS BIT(0)
+#define PCIEXPWAK_DIS BIT(14) /*AcpiPmEvtBlkx02 Pm1Enable */
+#define RTC_EN BIT(10)
+#define PWRBTN_EN BIT(8)
+#define GBL_EN BIT(5)
+#define TIMER_STS BIT(0)
+#define PM1_CNT_BLK 0x62
+#define PM_TMR_BLK 0x64
+#define PM_CPU_CTRL 0x66
+#define PM_GPE0_BLK 0x68
+#define PM_ACPI_SMI_CMD 0x6a
+#define PM_ACPI_CONF 0x74
+#define PM_ACPI_DECODE_STD BIT(0)
+#define PM_ACPI_GLOBAL_EN BIT(1)
+#define PM_ACPI_RTC_EN_EN BIT(2)
+#define PM_ACPI_TIMER_EN_EN BIT(4)
+#define PM_ACPI_MASK_ARB_DIS BIT(6)
+#define PM_ACPI_BIOS_RLS BIT(7)
+#define PM_ACPI_PWRBTNEN_EN BIT(8)
+#define PM_ACPI_REDUCED_HW_EN BIT(9)
+#define PM_ACPI_BLOCK_PCIE_PME BIT(24)
+#define PM_ACPI_PCIE_WAK_MASK BIT(25)
+#define PM_ACPI_WAKE_AS_GEVENT BIT(27)
+#define PM_ACPI_NB_PME_GEVENT BIT(28)
+#define PM_ACPI_RTC_WAKE_EN BIT(29)
+#define PM_RST_CTRL1 0xbe
+#define SLPTYPE_CONTROL_EN BIT(5)
+#define PM_RST_STATUS 0xc0
+#define PM_PCIB_CFG 0xea
+#define PM_GENINT_DISABLE BIT(0)
+#define PM_LPC_GATING 0xec
+#define PM_LPC_AB_NO_BYPASS_EN BIT(2)
+#define PM_LPC_A20_EN BIT(1)
+#define PM_LPC_ENABLE BIT(0)
+#define PM_USB_ENABLE 0xef
+#define PM_USB_ALL_CONTROLLERS 0x7f
+
+/* SMBUS MMIO offsets 0xfed80a00 */
+#define SMBHSTSTAT 0x0
+#define SMBHST_STAT_FAILED 0x10
+#define SMBHST_STAT_COLLISION 0x08
+#define SMBHST_STAT_ERROR 0x04
+#define SMBHST_STAT_INTERRUPT 0x02
+#define SMBHST_STAT_BUSY 0x01
+#define SMBHST_STAT_CLEAR 0xff
+#define SMBHST_STAT_NOERROR 0x02
+#define SMBHST_STAT_VAL_BITS 0x1f
+#define SMBHST_STAT_ERROR_BITS 0x1c
+
+#define SMBSLVSTAT 0x1
+#define SMBSLV_STAT_ALERT 0x20
+#define SMBSLV_STAT_SHADOW2 0x10
+#define SMBSLV_STAT_SHADOW1 0x08
+#define SMBSLV_STAT_SLV_STS 0x04
+#define SMBSLV_STAT_SLV_INIT 0x02
+#define SMBSLV_STAT_SLV_BUSY 0x01
+#define SMBSLV_STAT_CLEAR 0x1f
+
+#define SMBHSTCTRL 0x2
+#define SMBHST_CTRL_RST 0x80
+#define SMBHST_CTRL_STRT 0x40
+#define SMBHST_CTRL_QCK_RW 0x00
+#define SMBHST_CTRL_BTE_RW 0x04
+#define SMBHST_CTRL_BDT_RW 0x08
+#define SMBHST_CTRL_WDT_RW 0x0c
+#define SMBHST_CTRL_BLK_RW 0x14
+#define SMBHST_CTRL_MODE_BITS 0x1c
+#define SMBHST_CTRL_KILL 0x02
+#define SMBHST_CTRL_IEN 0x01
+
+#define SMBHSTCMD 0x3
+#define SMBHSTADDR 0x4
+#define SMBHSTDAT0 0x5
+#define SMBHSTDAT1 0x6
+#define SMBHSTBLKDAT 0x7
+#define SMBSLVCTRL 0x8
+#define SMBSLVCMD_SHADOW 0x9
+#define SMBSLVEVT 0xa
+#define SMBSLVDAT 0xc
+#define SMBTIMING 0xe
+
+/* FCH MISC Registers 0xfed80e00 */
+#define GPP_CLK_CNTRL 0x00
+#define GPP_CLK2_REQ_MAP_SHIFT 8
+#define GPP_CLK2_REQ_MAP_MASK (0xf << GPP_CLK2_REQ_MAP_SHIFT)
+#define GPP_CLK2_REQ_MAP_CLK_REQ2 3
+#define GPP_CLK0_REQ_MAP_SHIFT 0
+#define GPP_CLK0_REQ_MAP_MASK (0xf << GPP_CLK0_REQ_MAP_SHIFT)
+#define GPP_CLK0_REQ_MAP_CLK_REQ0 1
+#define MISC_CGPLL_CONFIG1 0x08
+#define CG1PLL_SPREAD_SPECTRUM_ENABLE BIT(0)
+#define MISC_CGPLL_CONFIG3 0x10
+#define CG1PLL_REFDIV_SHIFT 0
+#define CG1PLL_REFDIV_MASK (0x3ff << CG1PLL_REFDIV_SHIFT)
+#define CG1PLL_FBDIV_SHIFT 10
+#define CG1PLL_FBDIV_MASK (0xfff << CG1PLL_FBDIV_SHIFT)
+#define MISC_CGPLL_CONFIG4 0x14
+#define SS_STEP_SIZE_DSFRAC_SHIFT 0
+#define SS_STEP_SIZE_DSFRAC_MASK (0xffff << SS_STEP_SIZE_DSFRAC_SHIFT)
+#define SS_AMOUNT_DSFRAC_SHIFT 16
+#define SS_AMOUNT_DSFRAC_MASK (0xffff << SS_AMOUNT_DSFRAC_SHIFT)
+#define MISC_CGPLL_CONFIG5 0x18
+#define SS_AMOUNT_NFRAC_SLIP_SHIFT 8
+#define SS_AMOUNT_NFRAC_SLIP_MASK (0xf << SS_AMOUNT_NFRAC_SLIP_SHIFT)
+#define MISC_CGPLL_CONFIG6 0x1c
+#define CG1PLL_LF_MODE_SHIFT 9
+#define CG1PLL_LF_MODE_MASK (0x1ff << CG1PLL_LF_MODE_SHIFT)
+#define MISC_CLK_CNTL1 0x40
+#define CG1PLL_FBDIV_TEST BIT(26)
+#define OSCOUT1_CLK_OUTPUT_ENB BIT(2) /* 0 = Enabled, 1 = Disabled */
+#define OSCOUT2_CLK_OUTPUT_ENB BIT(7) /* 0 = Enabled, 1 = Disabled */
+
+/* XHCI_PM Registers: 0xfed81c00 */
+#define XHCI_PM_INDIRECT_INDEX 0x48
+#define XHCI_PM_INDIRECT_DATA 0x4c
+#define XHCI_OVER_CURRENT_CONTROL 0x30
+#define USB_OC0 0
+#define USB_OC1 1
+#define USB_OC2 2
+#define USB_OC3 3
+#define USB_OC4 4
+#define USB_OC5 5
+#define USB_OC6 6
+#define USB_OC7 7
+#define USB_OC_DISABLE 0xf
+#define USB_OC_DISABLE_ALL 0xffff
+#define OC_PORT0_SHIFT 0
+#define OC_PORT1_SHIFT 4
+#define OC_PORT2_SHIFT 8
+#define OC_PORT3_SHIFT 12
+
+#define EHCI_OVER_CURRENT_CONTROL 0x70
+#define EHCI_HUB_CONFIG4 0x90
+#define DEBUG_PORT_SELECT_SHIFT 16
+#define DEBUG_PORT_ENABLE BIT(18)
+#define DEBUG_PORT_MASK (BIT(16) | BIT(17) | BIT(18))
+
+/* FCH AOAC Registers 0xfed81e00 */
+#define FCH_AOAC_D3_CONTROL_CLK_GEN 0x40
+#define FCH_AOAC_D3_CONTROL_I2C0 0x4a
+#define FCH_AOAC_D3_CONTROL_I2C1 0x4c
+#define FCH_AOAC_D3_CONTROL_I2C2 0x4e
+#define FCH_AOAC_D3_CONTROL_I2C3 0x50
+#define FCH_AOAC_D3_CONTROL_UART0 0x56
+#define FCH_AOAC_D3_CONTROL_UART1 0x58
+#define FCH_AOAC_D3_CONTROL_AMBA 0x62
+#define FCH_AOAC_D3_CONTROL_USB2 0x64
+#define FCH_AOAC_D3_CONTROL_USB3 0x6e
+/* Bit definitions for all FCH_AOAC_D3_CONTROL_* Registers */
+#define FCH_AOAC_TARGET_DEVICE_STATE (BIT(0) + BIT(1))
+#define FCH_AOAC_DEVICE_STATE BIT(2)
+#define FCH_AOAC_PWR_ON_DEV BIT(3)
+#define FCH_AOAC_SW_PWR_ON_RSTB BIT(4)
+#define FCH_AOAC_SW_REF_CLK_OK BIT(5)
+#define FCH_AOAC_SW_RST_B BIT(6)
+#define FCH_AOAC_IS_SW_CONTROL BIT(7)
+
+#define FCH_AOAC_D3_STATE_CLK_GEN 0x41
+#define FCH_AOAC_D3_STATE_I2C0 0x4b
+#define FCH_AOAC_D3_STATE_I2C1 0x4d
+#define FCH_AOAC_D3_STATE_I2C2 0x4f
+#define FCH_AOAC_D3_STATE_I2C3 0x51
+#define FCH_AOAC_D3_STATE_UART0 0x57
+#define FCH_AOAC_D3_STATE_UART1 0x59
+#define FCH_AOAC_D3_STATE_AMBA 0x63
+#define FCH_AOAC_D3_STATE_USB2 0x65
+#define FCH_AOAC_D3_STATE_USB3 0x6f
+/* Bit definitions for all FCH_AOAC_D3_STATE_* Registers */
+#define FCH_AOAC_PWR_RST_STATE BIT(0)
+#define FCH_AOAC_RST_CLK_OK_STATE BIT(1)
+#define FCH_AOAC_RST_B_STATE BIT(2)
+#define FCH_AOAC_DEV_OFF_GATING_STATE BIT(3)
+#define FCH_AOAC_D3COLD BIT(4)
+#define FCH_AOAC_CLK_OK_STATE BIT(5)
+#define FCH_AOAC_STAT0 BIT(6)
+#define FCH_AOAC_STAT1 BIT(7)
+
+#define PM1_LIMIT 16
+#define GPE0_LIMIT 28
+#define TOTAL_BITS(a) (8 * sizeof(a))
+
+/* SATA Controller D11F0 */
+#define SATA_MISC_CONTROL_REG 0x40
+#define SATA_MISC_SUBCLASS_WREN BIT(0)
+/* Register in AHCIBaseAddress (BAR5 at D11F0x24) */
+#define SATA_CAPABILITIES_REG 0xfc
+#define SATA_CAPABILITY_SPM BIT(12)
+
+/* SPI Controller (base address in D14F3xA0) */
+#define SPI_BASE_ALIGNMENT BIT(6)
+
+#define SPI_CNTRL0 0x00
+#define SPI_BUSY BIT(31)
+#define SPI_READ_MODE_MASK (BIT(30) | BIT(29) | BIT(18))
+/* Nominal is 16.7MHz on older devices, 33MHz on newer */
+#define SPI_READ_MODE_NOM 0x00000000
+#define SPI_READ_MODE_DUAL112 ( BIT(29) )
+#define SPI_READ_MODE_QUAD114 ( BIT(29) | BIT(18))
+#define SPI_READ_MODE_DUAL122 (BIT(30) )
+#define SPI_READ_MODE_QUAD144 (BIT(30) | BIT(18))
+#define SPI_READ_MODE_NORMAL66 (BIT(30) | BIT(29) )
+#define SPI_READ_MODE_FAST (BIT(30) | BIT(29) | BIT(18))
+#define SPI_FIFO_PTR_CLR BIT(20)
+#define SPI_ARB_ENABLE BIT(19)
+#define EXEC_OPCODE BIT(16)
+#define SPI_CNTRL1 0x0c
+#define SPI_CMD_CODE 0x45
+#define SPI_CMD_TRIGGER 0x47
+#define SPI_CMD_TRIGGER_EXECUTE BIT(7)
+#define SPI_TX_BYTE_COUNT 0x48
+#define SPI_RX_BYTE_COUNT 0x4b
+#define SPI_STATUS 0x4c
+#define SPI_DONE_BYTE_COUNT_SHIFT 0
+#define SPI_DONE_BYTE_COUNT_MASK 0xff
+#define SPI_FIFO_WR_PTR_SHIFT 8
+#define SPI_FIFO_WR_PTR_MASK 0x7f
+#define SPI_FIFO_RD_PTR_SHIFT 16
+#define SPI_FIFO_RD_PTR_MASK 0x7f
+#define SPI_FIFO 0x80
+#define SPI_FIFO_DEPTH (0xc7 - SPI_FIFO)
+
+#define SPI100_ENABLE 0x20
+#define SPI_USE_SPI100 BIT(0)
+
+/* Use SPI_SPEED_16M-SPI_SPEED_66M below for the southbridge */
+#define SPI100_SPEED_CONFIG 0x22
+#define SPI_SPEED_66M (0x0)
+#define SPI_SPEED_33M ( BIT(0))
+#define SPI_SPEED_22M ( BIT(1) )
+#define SPI_SPEED_16M ( BIT(1) | BIT(0))
+#define SPI_SPEED_100M (BIT(2) )
+#define SPI_SPEED_800K (BIT(2) | BIT(0))
+#define SPI_NORM_SPEED_NEW_SH 12
+#define SPI_FAST_SPEED_NEW_SH 8
+#define SPI_ALT_SPEED_NEW_SH 4
+#define SPI_TPM_SPEED_NEW_SH 0
+
+#define SPI100_HOST_PREF_CONFIG 0x2c
+#define SPI_RD4DW_EN_HOST BIT(15)
+
+/* Platform Security Processor D8F0 */
+#define PSP_MAILBOX_BAR PCI_BASE_ADDRESS_4 /* BKDG: "BAR3" */
+#define PSP_BAR_ENABLES 0x48
+#define PSP_MAILBOX_BAR_EN 0x10
+
+/* IO 0xcf9 - Reset control port*/
+#define FULL_RST BIT(3)
+#define RST_CMD BIT(2)
+#define SYS_RST BIT(1)
+
+struct stoneyridge_aoac {
+ int enable;
+ int status;
+};
+
+typedef struct aoac_devs {
+ unsigned int :5;
+ unsigned int ic0e:1; /* 5: I2C0 */
+ unsigned int ic1e:1; /* 6: I2C1 */
+ unsigned int ic2e:1; /* 7: I2C2 */
+ unsigned int ic3e:1; /* 8: I2C3 */
+ unsigned int :2;
+ unsigned int ut0e:1; /* 11: UART0 */
+ unsigned int ut1e:1; /* 12: UART1 */
+ unsigned int :2;
+ unsigned int st_e:1; /* 15: SATA */
+ unsigned int :2;
+ unsigned int ehce:1; /* 18: EHCI */
+ unsigned int :4;
+ unsigned int xhce:1; /* 23: xHCI */
+ unsigned int sd_e:1; /* 24: SDIO */
+ unsigned int :2;
+ unsigned int espi:1; /* 27: ESPI */
+ unsigned int :4;
+} __packed aoac_devs_t;
+
+struct soc_power_reg {
+ uint16_t pm1_sts;
+ uint16_t pm1_en;
+ uint32_t gpe0_sts;
+ uint32_t gpe0_en;
+ uint16_t wake_from;
+};
+
+#define XHCI_FW_SIG_OFFSET 0xc
+#define XHCI_FW_ADDR_OFFSET 0x6
+#define XHCI_FW_SIZE_OFFSET 0x8
+#define XHCI_FW_BOOTRAM_SIZE 0x8000
+
+void enable_aoac_devices(void);
+void sb_clk_output_48Mhz(u32 osc);
+void sb_disable_4dw_burst(void);
+void sb_enable(struct device *dev);
+void southbridge_final(void *chip_info);
+void southbridge_init(void *chip_info);
+void sb_read_mode(u32 mode);
+void sb_set_spi100(u16 norm, u16 fast, u16 alt, u16 tpm);
+void bootblock_fch_early_init(void);
+void bootblock_fch_init(void);
+/**
+ * @brief Save the UMA bize returned by AGESA
+ *
+ * @param size = in bytes
+ *
+ * @return none
+ */
+void save_uma_size(uint32_t size);
+/**
+ * @brief Save the UMA base address returned by AGESA
+ *
+ * @param base = 64bit base address
+ *
+ * @return none
+ */
+void save_uma_base(uint64_t base);
+/**
+ * @brief Get the saved UMA size
+ *
+ * @param none
+ *
+ * @return size in bytes
+ */
+uint32_t get_uma_size(void);
+/**
+ * @brief Get the saved UMA base
+ *
+ * @param none
+ *
+ * @return 64bit base address
+ */
+uint64_t get_uma_base(void);
+/*
+ * Call the mainboard to get the USB Over Current Map. The mainboard
+ * returns the map and 0 on Success or -1 on error or no map. There is
+ * a default weak function in usb.c if the mainboard doesn't have any
+ * over current support.
+ */
+int mainboard_get_xhci_oc_map(uint16_t *usb_oc_map);
+int mainboard_get_ehci_oc_map(uint16_t *usb_oc_map);
+
+/* Initialize all the i2c buses that are marked with early init. */
+void i2c_soc_early_init(void);
+
+/* Initialize all the i2c buses that are not marked with early init. */
+void i2c_soc_init(void);
+
+#endif /* __STONEYRIDGE_H__ */
diff --git a/src/soc/amd/picasso/makefile.inc b/src/soc/amd/picasso/makefile.inc
new file mode 100644
index 0000000000..babd878524
--- /dev/null
+++ b/src/soc/amd/picasso/makefile.inc
@@ -0,0 +1,316 @@
+#*****************************************************************************
+#
+# Copyright (c) 2012, 2016-2017 Advanced Micro Devices, Inc.
+# 2013 - 2014 Sage Electronic Engineering, LLC
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Advanced Micro Devices, Inc. nor the names of
+# its contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#*****************************************************************************
+ifeq ($(CONFIG_SOC_AMD_STONEYRIDGE_FP4)$(CONFIG_SOC_AMD_STONEYRIDGE_FT4),y)
+
+subdirs-y += ../../../cpu/amd/mtrr/
+subdirs-y += ../../../cpu/x86/tsc
+subdirs-y += ../../../cpu/x86/lapic
+subdirs-y += ../../../cpu/x86/cache
+subdirs-y += ../../../cpu/x86/mtrr
+subdirs-y += ../../../cpu/x86/pae
+subdirs-y += ../../../cpu/x86/smm
+
+bootblock-$(CONFIG_STONEYRIDGE_UART) += uart.c
+bootblock-y += BiosCallOuts.c
+bootblock-y += bootblock/bootblock.c
+bootblock-y += gpio.c
+bootblock-y += i2c.c
+bootblock-$(CONFIG_USBDEBUG) += enable_usbdebug.c
+bootblock-y += monotonic_timer.c
+bootblock-y += pmutil.c
+bootblock-y += reset.c
+bootblock-y += tsc_freq.c
+bootblock-y += southbridge.c
+bootblock-y += nb_util.c
+bootblock-$(CONFIG_SPI_FLASH) += spi.c
+bootblock-$(CONFIG_HAVE_SMI_HANDLER) += smi_util.c
+
+romstage-y += BiosCallOuts.c
+romstage-y += i2c.c
+romstage-y += romstage.c
+romstage-$(CONFIG_USBDEBUG) += enable_usbdebug.c
+romstage-y += gpio.c
+romstage-y += monotonic_timer.c
+romstage-y += pmutil.c
+romstage-y += reset.c
+romstage-y += smbus.c
+romstage-y += smbus_spd.c
+romstage-y += ramtop.c
+romstage-$(CONFIG_STONEYRIDGE_UART) += uart.c
+romstage-y += tsc_freq.c
+romstage-y += southbridge.c
+romstage-y += nb_util.c
+romstage-$(CONFIG_SPI_FLASH) += spi.c
+romstage-$(CONFIG_HAVE_SMI_HANDLER) += smi_util.c
+
+verstage-y += gpio.c
+verstage-y += i2c.c
+verstage-y += monotonic_timer.c
+verstage-y += pmutil.c
+verstage-y += reset.c
+verstage-$(CONFIG_STONEYRIDGE_UART) += uart.c
+verstage-y += tsc_freq.c
+verstage-y += nb_util.c
+verstage-$(CONFIG_SPI_FLASH) += spi.c
+
+postcar-y += monotonic_timer.c
+postcar-$(CONFIG_STONEYRIDGE_UART) += uart.c
+postcar-y += ramtop.c
+postcar-y += nb_util.c
+postcar-$(CONFIG_VBOOT_MEASURED_BOOT) += i2c.c
+postcar-y += tsc_freq.c
+
+ramstage-y += BiosCallOuts.c
+ramstage-y += i2c.c
+ramstage-y += chip.c
+ramstage-y += cpu.c
+ramstage-y += mca.c
+ramstage-$(CONFIG_USBDEBUG) += enable_usbdebug.c
+ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c
+ramstage-y += gpio.c
+ramstage-y += monotonic_timer.c
+ramstage-y += southbridge.c
+ramstage-y += northbridge.c
+ramstage-y += pmutil.c
+ramstage-y += reset.c
+ramstage-y += sata.c
+ramstage-y += sm.c
+ramstage-y += smbus.c
+ramstage-y += ramtop.c
+ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smi.c
+ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smi_util.c
+ramstage-$(CONFIG_STONEYRIDGE_UART) += uart.c
+ramstage-y += usb.c
+ramstage-y += tsc_freq.c
+ramstage-$(CONFIG_SPI_FLASH) += spi.c
+ramstage-y += finalize.c
+ramstage-y += nb_util.c
+
+smm-y += monotonic_timer.c
+smm-y += smihandler.c
+smm-y += smi_util.c
+smm-y += tsc_freq.c
+smm-$(CONFIG_DEBUG_SMI) += uart.c
+smm-$(CONFIG_SPI_FLASH) += spi.c
+smm-y += nb_util.c
+smm-y += gpio.c
+
+CPPFLAGS_common += -I$(src)/soc/amd/stoneyridge
+CPPFLAGS_common += -I$(src)/soc/amd/stoneyridge/include
+CPPFLAGS_common += -I$(src)/soc/amd/stoneyridge/acpi
+
+# ROMSIG Normally At ROMBASE + 0x20000
+# Overridden by CONFIG_AMD_FWM_POSITION_INDEX
+# +-----------+---------------+----------------+------------+
+# |0x55AA55AA |EC ROM Address |GEC ROM Address |USB3 ROM |
+# +-----------+---------------+----------------+------------+
+# |PSPDIR ADDR|
+# +-----------+
+#
+# EC ROM should be 64K aligned.
+STONEYRIDGE_FWM_POSITION=$(call int-add, \
+ $(call int-subtract, 0xffffffff \
+ $(call int-shift-left, \
+ 0x80000 $(CONFIG_AMD_FWM_POSITION_INDEX))) 0x20000 1)
+
+### 0
+FIRMWARE_LOCATE=$(dir $(call strip_quotes, $(CONFIG_AMD_PUBKEY_FILE)))
+FIRMWARE_TYPE=ST
+
+###5
+PUBSIGNEDKEY_FILE=$(top)/$(FIRMWARE_LOCATE)/RtmPubSigned$(FIRMWARE_TYPE).key
+
+###1
+PSPBTLDR_FILE=$(top)/$(FIRMWARE_LOCATE)/PspBootLoader_prod_$(FIRMWARE_TYPE).sbin
+
+###3
+PSPRCVR_FILE=$(top)/$(FIRMWARE_LOCATE)/PspRecoveryBootLoader_prod_$(FIRMWARE_TYPE).sbin
+
+###4
+PSPNVRAM_FILE=$(top)/$(FIRMWARE_LOCATE)/PspNvram$(FIRMWARE_TYPE).bin
+
+###8 - Check for SMU firmware named either *.sbin or *.csbin
+### TODO: Remove *.sbin section after the blobs repo is updated.
+SMUFWM_FILE=$(top)/$(FIRMWARE_LOCATE)/SmuFirmware_$(FIRMWARE_TYPE).csbin
+SMUFWM_FN_FILE=$(top)/$(FIRMWARE_LOCATE)/SmuFirmware_$(FIRMWARE_TYPE)_FN.csbin
+ifeq ("$(wildcard $(SMUFWM_FILE))","")
+SMUFWM_FILE=$(top)/$(FIRMWARE_LOCATE)/SmuFirmware$(FIRMWARE_TYPE).sbin
+SMUFWM_FN_FILE=$(top)/$(FIRMWARE_LOCATE)/SmuFirmware$(FIRMWARE_TYPE)_FN.sbin
+endif
+
+###95
+SMUSCS_FILE=$(top)/$(FIRMWARE_LOCATE)/SmuScs$(FIRMWARE_TYPE).bin
+
+###9
+PSPSECUREDEBUG_FILE=$(top)/$(FIRMWARE_LOCATE)/PspSecureDebug$(FIRMWARE_TYPE).Key
+
+ifeq ($(CONFIG_USE_PSPSECUREOS),y)
+###2
+PSPSCUREOS_FILE=$(top)/$(FIRMWARE_LOCATE)/PspSecureOs_prod_$(FIRMWARE_TYPE).csbin
+
+###12
+PSPTRUSTLETS_FILE=$(wildcard $(top)/$(FIRMWARE_LOCATE)/PspTrustlets*_prod_$(FIRMWARE_TYPE).cbin)
+
+###13
+TRUSTLETKEY_FILE=$(top)/$(FIRMWARE_LOCATE)/TrustletKey_prod_$(FIRMWARE_TYPE).sbin
+endif
+
+###18- Check for SMU firmware2 named either *.sbin or *.csbin
+### TODO: Remove *.sbin section after the blobs repo is updated.
+SMUFIRMWARE2_FILE=$(top)/$(FIRMWARE_LOCATE)/SmuFirmware2_prod_$(FIRMWARE_TYPE).csbin
+SMUFIRMWARE2_FN_FILE=$(top)/$(FIRMWARE_LOCATE)/SmuFirmware2_prod_$(FIRMWARE_TYPE)_FN.csbin
+ifeq ("$(wildcard $(SMUFIRMWARE2_FILE))","")
+SMUFIRMWARE2_FILE=$(top)/$(FIRMWARE_LOCATE)/SmuFirmware2_prod_$(FIRMWARE_TYPE).sbin
+SMUFIRMWARE2_FN_FILE=$(top)/$(FIRMWARE_LOCATE)/SmuFirmware2_prod_$(FIRMWARE_TYPE)_FN.sbin
+endif
+
+add_opt_prefix=$(if $(call strip_quotes, $(1)), $(2) $(call strip_quotes, $(1)), )
+
+OPT_STONEYRIDGE_XHCI_FWM_FILE=$(call add_opt_prefix, $(CONFIG_STONEYRIDGE_XHCI_FWM_FILE), --xhci)
+OPT_STONEYRIDGE_GEC_FWM_FILE=$(call add_opt_prefix, $(CONFIG_STONEYRIDGE_GEC_FWM_FILEddd), --gec)
+
+OPT_AMD_PUBKEY_FILE=$(call add_opt_prefix, $(CONFIG_AMD_PUBKEY_FILE), --pubkey)
+OPT_PSPBTLDR_FILE=$(call add_opt_prefix, $(PSPBTLDR_FILE), --bootloader)
+OPT_SMUFWM_FILE=$(call add_opt_prefix, $(SMUFWM_FILE), --smufirmware)
+OPT_PSPRCVR_FILE=$(call add_opt_prefix, $(PSPRCVR_FILE), --recovery)
+OPT_PUBSIGNEDKEY_FILE=$(call add_opt_prefix, $(PUBSIGNEDKEY_FILE), --rtmpubkey)
+OPT_PSPNVRAM_FILE=$(call add_opt_prefix, $(PSPNVRAM_FILE), --nvram)
+OPT_PSPSECUREDEBUG_FILE=$(call add_opt_prefix, $(PSPSECUREDEBUG_FILE), --securedebug)
+ifeq ($(CONFIG_USE_PSPSECUREOS),y)
+OPT_PSPSCUREOS_FILE=$(call add_opt_prefix, $(PSPSCUREOS_FILE), --secureos)
+OPT_PSPTRUSTLETS_FILE=$(call add_opt_prefix, $(PSPTRUSTLETS_FILE), --trustlets)
+OPT_TRUSTLETKEY_FILE=$(call add_opt_prefix, $(TRUSTLETKEY_FILE), --trustletkey)
+endif
+OPT_SMUFIRMWARE2_FILE=$(call add_opt_prefix, $(SMUFIRMWARE2_FILE), --smufirmware2)
+OPT_SMUSCS_FILE=$(call add_opt_prefix, $(SMUSCS_FILE), --smuscs)
+SUBPROG_FN_SMU_FW=1
+OPT_SMUFWM_FN_FILE=$(call add_opt_prefix, $(SMUFWM_FN_FILE), --subprogram $(SUBPROG_FN_SMU_FW) --smufirmware)
+OPT_SMUFIRMWARE2_FN_FILE=$(call add_opt_prefix, $(SMUFIRMWARE2_FN_FILE), --subprogram $(SUBPROG_FN_SMU_FW) --smufirmware2)
+
+
+$(obj)/amdfw.rom: $(call strip_quotes, $(CONFIG_STONEYRIDGE_XHCI_FWM_FILE)) \
+ $(call strip_quotes, $(CONFIG_STONEYRIDGE_GEC_FWM_FILE)) \
+ $(call strip_quotes, $(CONFIG_AMD_PUBKEY_FILE)) \
+ $(call strip_quotes, $(PUBSIGNEDKEY_FILE)) \
+ $(call strip_quotes, $(PSPBTLDR_FILE)) \
+ $(call strip_quotes, $(PSPRCVR_FILE)) \
+ $(call strip_quotes, $(PSPSCUREOS_FILE)) \
+ $(call strip_quotes, $(PSPNVRAM_FILE)) \
+ $(call strip_quotes, $(SMUFWM_FILE)) \
+ $(call strip_quotes, $(SMUFWM_FN_FILE)) \
+ $(call strip_quotes, $(SMUSCS_FILE)) \
+ $(call strip_quotes, $(PSPSECUREDEBUG_FILE)) \
+ $(call strip_quotes, $(PSPTRUSTLETS_FILE)) \
+ $(call strip_quotes, $(TRUSTLETKEY_FILE)) \
+ $(call strip_quotes, $(SMUFIRMWARE2_FILE)) \
+ $(call strip_quotes, $(SMUFIRMWARE2_FN_FILE)) \
+ $(AMDFWTOOL)
+ rm -f $@
+ @printf " AMDFWTOOL $(subst $(obj)/,,$(@))\n"
+ $(AMDFWTOOL) \
+ $(OPT_STONEYRIDGE_XHCI_FWM_FILE) \
+ $(OPT_STONEYRIDGE_GEC_FWM_FILE) \
+ $(OPT_AMD_PUBKEY_FILE) \
+ $(OPT_PSPBTLDR_FILE) \
+ $(OPT_SMUFWM_FILE) \
+ $(OPT_PSPRCVR_FILE) \
+ $(OPT_PUBSIGNEDKEY_FILE) \
+ $(OPT_PSPSCUREOS_FILE) \
+ $(OPT_PSPNVRAM_FILE) \
+ $(OPT_PSPSECUREDEBUG_FILE) \
+ $(OPT_PSPTRUSTLETS_FILE) \
+ $(OPT_TRUSTLETKEY_FILE) \
+ $(OPT_SMUFIRMWARE2_FILE) \
+ $(OPT_SMUSCS_FILE) \
+ $(OPT_AMD_PUBKEY_FILE) \
+ $(OPT_PSPBTLDR_FILE) \
+ $(OPT_SMUFWM_FILE) \
+ $(OPT_SMUFWM_FN_FILE) \
+ $(OPT_PSPRCVR_FILE) \
+ $(OPT_PUBSIGNEDKEY_FILE) \
+ $(OPT_PSPSCUREOS_FILE) \
+ $(OPT_PSPNVRAM_FILE) \
+ $(OPT_PSPSECUREDEBUG_FILE) \
+ $(OPT_PSPTRUSTLETS_FILE) \
+ $(OPT_TRUSTLETKEY_FILE) \
+ $(OPT_SMUFIRMWARE2_FILE) \
+ $(OPT_SMUFIRMWARE2_FN_FILE) \
+ $(OPT_SMUSCS_FILE) \
+ --combo-capable \
+ --flashsize $(CONFIG_ROM_SIZE) \
+ --location $(shell printf "0x%x" $(STONEYRIDGE_FWM_POSITION)) \
+ --output $@
+
+ifeq ($(CONFIG_AMDFW_OUTSIDE_CBFS),y)
+PHONY+=add_amdfw
+INTERMEDIATE+=add_amdfw
+
+# Calculate firmware position inside the ROM
+STONEYRIDGE_FWM_ROM_POSITION=$(call int-add, \
+ $(call int-subtract, $(CONFIG_ROM_SIZE) \
+ $(call int-shift-left, \
+ 0x80000 $(CONFIG_AMD_FWM_POSITION_INDEX))) 0x20000)
+
+add_amdfw: $(obj)/coreboot.pre $(obj)/amdfw.rom
+ printf " DD Adding AMD Firmware at ROM offset 0x%x\n" \
+ "$(STONEYRIDGE_FWM_ROM_POSITION)"
+ dd if=$(obj)/amdfw.rom \
+ of=$(obj)/coreboot.pre conv=notrunc bs=1 \
+ seek=$(STONEYRIDGE_FWM_ROM_POSITION) >/dev/null 2>&1
+
+else # ifeq ($(CONFIG_AMDFW_OUTSIDE_CBFS),y)
+
+cbfs-files-y += apu/amdfw
+apu/amdfw-file := $(obj)/amdfw.rom
+apu/amdfw-position := $(STONEYRIDGE_FWM_POSITION)
+apu/amdfw-type := raw
+
+endif # ifeq ($(CONFIG_AMDFW_OUTSIDE_CBFS),y)
+
+ifeq ($(CONFIG_SOC_AMD_PSP_SELECTABLE_SMU_FW),y)
+
+cbfs-files-y += smu_fw
+cbfs-files-y += smu_fw2
+smu_fw-type := raw
+smu_fw2-type := raw
+
+ifeq ($(CONFIG_SOC_AMD_SMU_FANLESS),y)
+smu_fw-file := $(SMUFWM_FN_FILE)
+smu_fw2-file := $(SMUFIRMWARE2_FN_FILE)
+else ifeq ($(CONFIG_SOC_AMD_SMU_FANNED),y)
+smu_fw-file := $(SMUFWM_FILE)
+smu_fw2-file := $(SMUFIRMWARE2_FILE)
+else
+$(error "Proper SMU Firmware not selected")
+endif
+
+endif # ifeq ($(CONFIG_SOC_AMD_PSP_SELECTABLE_SMU_FW),y)
+
+endif # ($(CONFIG_SOC_AMD_STONEYRIDGE_FP4)$(CONFIG_SOC_AMD_STONEYRIDGE_FT4),y)
diff --git a/src/soc/amd/picasso/mca.c b/src/soc/amd/picasso/mca.c
new file mode 100644
index 0000000000..8a875d9206
--- /dev/null
+++ b/src/soc/amd/picasso/mca.c
@@ -0,0 +1,214 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2018 Advanced Micro Devices, 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.
+ */
+
+#include <cpu/x86/msr.h>
+#include <arch/acpi.h>
+#include <soc/cpu.h>
+#include <soc/northbridge.h>
+#include <console/console.h>
+#include <arch/bert_storage.h>
+#include <cper.h>
+
+struct mca_bank {
+ int bank;
+ msr_t ctl;
+ msr_t sts;
+ msr_t addr;
+ msr_t misc;
+ msr_t cmask;
+};
+
+static inline size_t mca_report_size_reqd(void)
+{
+ size_t size;
+
+ size = sizeof(acpi_generic_error_status_t);
+
+ size += sizeof(acpi_hest_generic_data_v300_t);
+ size += sizeof(cper_proc_generic_error_section_t);
+
+ size += sizeof(acpi_hest_generic_data_v300_t);
+ size += sizeof(cper_ia32x64_proc_error_section_t);
+
+ /* Check Error */
+ size += cper_ia32x64_check_sz();
+
+ /* Context of MCG_CAP, MCG_STAT, MCG_CTL */
+ size += cper_ia32x64_ctx_sz_bytype(CPER_IA32X64_CTX_MSR, 3);
+
+ /* Context of MCi_CTL, MCi_STATUS, MCi_ADDR, MCi_MISC */
+ size += cper_ia32x64_ctx_sz_bytype(CPER_IA32X64_CTX_MSR, 4);
+
+ /* Context of CTL_MASK */
+ size += cper_ia32x64_ctx_sz_bytype(CPER_IA32X64_CTX_MSR, 1);
+
+ return size;
+}
+
+static enum cper_x86_check_type error_to_chktype(struct mca_bank *mci)
+{
+ int error = mca_err_type(mci->sts);
+
+ if (error == MCA_ERRTYPE_BUS)
+ return X86_PROCESSOR_BUS_CHK;
+ if (error == MCA_ERRTYPE_INT)
+ return X86_PROCESSOR_MS_CHK;
+ if (error == MCA_ERRTYPE_MEM)
+ return X86_PROCESSOR_CACHE_CHK;
+ if (error == MCA_ERRTYPE_TLB)
+ return X86_PROCESSOR_TLB_CHK;
+
+ return X86_PROCESSOR_MS_CHK; /* unrecognized */
+}
+
+/* Fill additional information in the Generic Processor Error Section. */
+static void fill_generic_section(cper_proc_generic_error_section_t *sec,
+ struct mca_bank *mci)
+{
+ int type = mca_err_type(mci->sts);
+
+ if (type == MCA_ERRTYPE_BUS) /* try to map MCA errors to CPER types */
+ sec->error_type = GENPROC_ERRTYPE_BUS;
+ else if (type == MCA_ERRTYPE_INT)
+ sec->error_type = GENPROC_ERRTYPE_UARCH;
+ else if (type == MCA_ERRTYPE_MEM)
+ sec->error_type = GENPROC_ERRTYPE_CACHE;
+ else if (type == MCA_ERRTYPE_TLB)
+ sec->error_type = GENPROC_ERRTYPE_TLB;
+ else
+ sec->error_type = GENPROC_ERRTYPE_UNKNOWN;
+ sec->validation |= GENPROC_VALID_PROC_ERR_TYPE;
+}
+
+/* Convert an error reported by an MCA bank into BERT information to be reported
+ * by the OS. The ACPI driver doesn't recognize/parse the IA32/X64 structure,
+ * which is the best method to report MSR context. As a result, add two
+ * structures: A "processor generic error" that is parsed, and an IA32/X64 one
+ * to capture complete information.
+ *
+ * Future work may attempt to interpret the specific Family 15h error symptoms
+ * found in the MCA registers. This data could enhance the reporting of the
+ * Processor Generic section and the failing error/check added to the
+ * IA32/X64 section.
+ */
+static void build_bert_mca_error(struct mca_bank *mci)
+{
+ acpi_generic_error_status_t *status;
+ acpi_hest_generic_data_v300_t *gen_entry;
+ acpi_hest_generic_data_v300_t *x86_entry;
+ cper_proc_generic_error_section_t *gen_sec;
+ cper_ia32x64_proc_error_section_t *x86_sec;
+ cper_ia32x64_proc_error_info_t *chk;
+ cper_ia32x64_context_t *ctx;
+
+ if (mca_report_size_reqd() > bert_storage_remaining())
+ goto failed;
+
+ status = bert_new_event(&CPER_SEC_PROC_GENERIC_GUID);
+ if (!status)
+ goto failed;
+
+ gen_entry = acpi_hest_generic_data3(status);
+ gen_sec = section_of_acpientry(gen_sec, gen_entry);
+
+ fill_generic_section(gen_sec, mci);
+
+ x86_entry = bert_append_ia32x64(status);
+ x86_sec = section_of_acpientry(x86_sec, x86_entry);
+
+ chk = new_cper_ia32x64_check(status, x86_sec, error_to_chktype(mci));
+ if (!chk)
+ goto failed;
+
+ ctx = cper_new_ia32x64_context_msr(status, x86_sec, IA32_MCG_CAP, 3);
+ if (!ctx)
+ goto failed;
+ ctx = cper_new_ia32x64_context_msr(status, x86_sec,
+ IA32_MC0_CTL + (mci->bank * 4), 4);
+ if (!ctx)
+ goto failed;
+ ctx = cper_new_ia32x64_context_msr(status, x86_sec,
+ MC0_CTL_MASK + mci->bank, 1);
+ if (!ctx)
+ goto failed;
+
+ return;
+
+failed:
+ /* We're here because of a hardware error, don't break something else */
+ printk(BIOS_ERR, "Error: Not enough room in BERT region for Machine Check error\n");
+}
+
+static const char *const mca_bank_name[] = {
+ "Load-store unit",
+ "Instruction fetch unit",
+ "Combined unit",
+ "Reserved",
+ "Northbridge",
+ "Execution unit",
+ "Floating point unit"
+};
+
+void check_mca(void)
+{
+ int i;
+ msr_t cap;
+ struct mca_bank mci;
+ int num_banks;
+
+ cap = rdmsr(IA32_MCG_CAP);
+ num_banks = cap.lo & MCA_BANKS_MASK;
+
+ if (is_warm_reset()) {
+ for (i = 0 ; i < num_banks ; i++) {
+ if (i == 3) /* Reserved in Family 15h */
+ continue;
+
+ mci.sts = rdmsr(IA32_MC0_STATUS + (i * 4));
+ if (mci.sts.hi || mci.sts.lo) {
+ int core = cpuid_ebx(1) >> 24;
+
+ printk(BIOS_WARNING, "#MC Error: core %d, bank %d %s\n",
+ core, i, mca_bank_name[i]);
+
+ printk(BIOS_WARNING, " MC%d_STATUS = %08x_%08x\n",
+ i, mci.sts.hi, mci.sts.lo);
+ mci.addr = rdmsr(MC0_ADDR + (i * 4));
+ printk(BIOS_WARNING, " MC%d_ADDR = %08x_%08x\n",
+ i, mci.addr.hi, mci.addr.lo);
+ mci.misc = rdmsr(MC0_MISC + (i * 4));
+ printk(BIOS_WARNING, " MC%d_MISC = %08x_%08x\n",
+ i, mci.misc.hi, mci.misc.lo);
+ mci.ctl = rdmsr(IA32_MC0_CTL + (i * 4));
+ printk(BIOS_WARNING, " MC%d_CTL = %08x_%08x\n",
+ i, mci.ctl.hi, mci.ctl.lo);
+ mci.cmask = rdmsr(MC0_CTL_MASK + i);
+ printk(BIOS_WARNING, " MC%d_CTL_MASK = %08x_%08x\n",
+ i, mci.cmask.hi, mci.cmask.lo);
+
+ mci.bank = i;
+ if (CONFIG(ACPI_BERT)
+ && mca_valid(mci.sts))
+ build_bert_mca_error(&mci);
+ }
+ }
+ }
+
+ /* zero the machine check error status registers */
+ mci.sts.lo = 0;
+ mci.sts.hi = 0;
+ for (i = 0 ; i < num_banks ; i++)
+ wrmsr(IA32_MC0_STATUS + (i * 4), mci.sts);
+}
diff --git a/src/soc/amd/picasso/monotonic_timer.c b/src/soc/amd/picasso/monotonic_timer.c
new file mode 100644
index 0000000000..7ea571f635
--- /dev/null
+++ b/src/soc/amd/picasso/monotonic_timer.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2018 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; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <cpu/x86/msr.h>
+#include <timer.h>
+#include <timestamp.h>
+
+#define CU_PTSC_MSR 0xc0010280
+#define PTSC_FREQ_MHZ 100
+
+void timer_monotonic_get(struct mono_time *mt)
+{
+ mono_time_set_usecs(mt, timestamp_get());
+}
+
+uint64_t timestamp_get(void)
+{
+ unsigned long long val;
+ msr_t msr;
+
+ msr = rdmsr(CU_PTSC_MSR);
+
+ val = ((unsigned long long)msr.hi << 32) | msr.lo;
+
+ return val / PTSC_FREQ_MHZ;
+}
diff --git a/src/soc/amd/picasso/nb_util.c b/src/soc/amd/picasso/nb_util.c
new file mode 100644
index 0000000000..d5de067814
--- /dev/null
+++ b/src/soc/amd/picasso/nb_util.c
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2018 Advanced Micro Devices
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <soc/northbridge.h>
+#include <soc/pci_devs.h>
+#include <device/pci_ops.h>
+
+uint32_t nb_ioapic_read(unsigned int index)
+{
+ pci_write_config32(SOC_GNB_DEV, NB_IOAPIC_INDEX, index);
+ return pci_read_config32(SOC_GNB_DEV, NB_IOAPIC_DATA);
+}
+
+void nb_ioapic_write(unsigned int index, uint32_t value)
+{
+ pci_write_config32(SOC_GNB_DEV, NB_IOAPIC_INDEX, index);
+ pci_write_config32(SOC_GNB_DEV, NB_IOAPIC_DATA, value);
+}
+
+void *get_ap_entry_ptr(void)
+{
+ return (void *)nb_ioapic_read(AP_SCRATCH_REG);
+}
+
+void set_ap_entry_ptr(void *entry)
+{
+ nb_ioapic_write(AP_SCRATCH_REG, (uintptr_t)entry);
+}
diff --git a/src/soc/amd/picasso/northbridge.c b/src/soc/amd/picasso/northbridge.c
new file mode 100644
index 0000000000..5985832c81
--- /dev/null
+++ b/src/soc/amd/picasso/northbridge.c
@@ -0,0 +1,492 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015-2016 Advanced Micro Devices, 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.
+ */
+
+#include <device/pci_ops.h>
+#include <arch/ioapic.h>
+#include <arch/acpi.h>
+#include <arch/acpigen.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <cpu/amd/mtrr.h>
+#include <cpu/x86/lapic_def.h>
+#include <cpu/x86/msr.h>
+#include <cpu/amd/msr.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <romstage_handoff.h>
+#include <amdblocks/agesawrapper.h>
+#include <amdblocks/agesawrapper_call.h>
+#include <agesa_headers.h>
+#include <soc/cpu.h>
+#include <soc/northbridge.h>
+#include <soc/southbridge.h>
+#include <soc/pci_devs.h>
+#include <soc/iomap.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <arch/bert_storage.h>
+
+#include "chip.h"
+
+static void set_io_addr_reg(struct device *dev, u32 nodeid, u32 linkn, u32 reg,
+ u32 io_min, u32 io_max)
+{
+ u32 tempreg;
+
+ /* io range allocation. Limit */
+ tempreg = (nodeid & 0xf) | ((nodeid & 0x30) << (8 - 4)) | (linkn << 4)
+ | ((io_max & 0xf0) << (12 - 4));
+ pci_write_config32(SOC_ADDR_DEV, reg + 4, tempreg);
+ tempreg = 3 | ((io_min & 0xf0) << (12 - 4)); /* base: ISA and VGA ? */
+ pci_write_config32(SOC_ADDR_DEV, reg, tempreg);
+}
+
+static void set_mmio_addr_reg(u32 nodeid, u32 linkn, u32 reg, u32 index,
+ u32 mmio_min, u32 mmio_max)
+{
+ u32 tempreg;
+
+ /* io range allocation. Limit */
+ tempreg = (nodeid & 0xf) | (linkn << 4) | (mmio_max & 0xffffff00);
+ pci_write_config32(SOC_ADDR_DEV, reg + 4, tempreg);
+ tempreg = 3 | (nodeid & 0x30) | (mmio_min & 0xffffff00);
+ pci_write_config32(SOC_ADDR_DEV, reg, tempreg);
+}
+
+static void read_resources(struct device *dev)
+{
+ struct resource *res;
+
+ /*
+ * This MMCONF resource must be reserved in the PCI domain.
+ * It is not honored by the coreboot resource allocator if it is in
+ * the CPU_CLUSTER.
+ */
+ mmconf_resource(dev, MMIO_CONF_BASE);
+
+ /* NB IOAPIC2 resource */
+ res = new_resource(dev, IO_APIC2_ADDR); /* IOAPIC2 */
+ res->base = IO_APIC2_ADDR;
+ res->size = 0x00001000;
+ res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+}
+
+static void set_resource(struct device *dev, struct resource *res, u32 nodeid)
+{
+ resource_t rbase, rend;
+ unsigned int reg, link_num;
+ char buf[50];
+
+ /* Make certain the resource has actually been set */
+ if (!(res->flags & IORESOURCE_ASSIGNED))
+ return;
+
+ /* If I have already stored this resource don't worry about it */
+ if (res->flags & IORESOURCE_STORED)
+ return;
+
+ /* Only handle PCI memory and IO resources */
+ if (!(res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
+ return;
+
+ /* Ensure I am actually looking at a resource of function 1 */
+ if ((res->index & 0xffff) < 0x1000)
+ return;
+
+ /* Get the base address */
+ rbase = res->base;
+
+ /* Get the limit (rounded up) */
+ rend = resource_end(res);
+
+ /* Get the register and link */
+ reg = res->index & 0xfff; /* 4k */
+ link_num = IOINDEX_LINK(res->index);
+
+ if (res->flags & IORESOURCE_IO)
+ set_io_addr_reg(dev, nodeid, link_num, reg, rbase>>8, rend>>8);
+ else if (res->flags & IORESOURCE_MEM)
+ set_mmio_addr_reg(nodeid, link_num, reg,
+ (res->index >> 24), rbase >> 8, rend >> 8);
+
+ res->flags |= IORESOURCE_STORED;
+ snprintf(buf, sizeof(buf), " <node %x link %x>",
+ nodeid, link_num);
+ report_resource_stored(dev, res, buf);
+}
+
+/**
+ * I tried to reuse the resource allocation code in set_resource()
+ * but it is too difficult to deal with the resource allocation magic.
+ */
+
+static void create_vga_resource(struct device *dev)
+{
+ struct bus *link;
+
+ /* find out which link the VGA card is connected,
+ * we only deal with the 'first' vga card */
+ for (link = dev->link_list ; link ; link = link->next)
+ if (link->bridge_ctrl & PCI_BRIDGE_CTL_VGA)
+ break;
+
+ /* no VGA card installed */
+ if (link == NULL)
+ return;
+
+ printk(BIOS_DEBUG, "VGA: %s has VGA device\n", dev_path(dev));
+ /* Route A0000-BFFFF, IO 3B0-3BB 3C0-3DF */
+ pci_write_config32(SOC_ADDR_DEV, D18F1_VGAEN, VGA_ADDR_ENABLE);
+}
+
+static void set_resources(struct device *dev)
+{
+ struct bus *bus;
+ struct resource *res;
+
+
+ /* do we need this? */
+ create_vga_resource(dev);
+
+ /* Set each resource we have found */
+ for (res = dev->resource_list ; res ; res = res->next)
+ set_resource(dev, res, 0);
+
+ for (bus = dev->link_list ; bus ; bus = bus->next)
+ if (bus->children)
+ assign_resources(bus);
+}
+
+static void northbridge_init(struct device *dev)
+{
+ setup_ioapic((u8 *)IO_APIC2_ADDR, CONFIG_MAX_CPUS+1);
+}
+
+unsigned long acpi_fill_mcfg(unsigned long current)
+{
+
+ current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)current,
+ CONFIG_MMCONF_BASE_ADDRESS,
+ 0,
+ 0,
+ CONFIG_MMCONF_BUS_NUMBER);
+
+ return current;
+}
+
+static unsigned long acpi_fill_hest(acpi_hest_t *hest)
+{
+ void *addr, *current;
+
+ /* Skip the HEST header. */
+ current = (void *)(hest + 1);
+
+ addr = agesawrapper_getlateinitptr(PICK_WHEA_MCE);
+ if (addr != NULL)
+ current += acpi_create_hest_error_source(hest, current, 0,
+ (void *)((u32)addr + 2), *(uint16_t *)addr - 2);
+
+ addr = agesawrapper_getlateinitptr(PICK_WHEA_CMC);
+ if (addr != NULL)
+ current += acpi_create_hest_error_source(hest, current, 1,
+ (void *)((u32)addr + 2), *(uint16_t *)addr - 2);
+
+ return (unsigned long)current;
+}
+
+static void northbridge_fill_ssdt_generator(struct device *device)
+{
+ msr_t msr;
+ char pscope[] = "\\_SB.PCI0";
+
+ acpigen_write_scope(pscope);
+ msr = rdmsr(TOP_MEM);
+ acpigen_write_name_dword("TOM1", msr.lo);
+ msr = rdmsr(TOP_MEM2);
+ /*
+ * Since XP only implements parts of ACPI 2.0, we can't use a qword
+ * here.
+ * See http://www.acpi.info/presentations/S01USMOBS169_OS%2520new.ppt
+ * slide 22ff.
+ * Shift value right by 20 bit to make it fit into 32bit,
+ * giving us 1MB granularity and a limit of almost 4Exabyte of memory.
+ */
+ acpigen_write_name_dword("TOM2", (msr.hi << 12) | msr.lo >> 20);
+ acpigen_pop_len();
+}
+
+static unsigned long agesa_write_acpi_tables(struct device *device,
+ unsigned long current,
+ acpi_rsdp_t *rsdp)
+{
+ acpi_srat_t *srat;
+ acpi_slit_t *slit;
+ acpi_header_t *ssdt;
+ acpi_header_t *alib;
+ acpi_header_t *ivrs;
+ acpi_hest_t *hest;
+ acpi_bert_t *bert;
+
+ /* HEST */
+ current = ALIGN(current, 8);
+ hest = (acpi_hest_t *)current;
+ acpi_write_hest(hest, acpi_fill_hest);
+ acpi_add_table(rsdp, (void *)current);
+ current += hest->header.length;
+
+ /* BERT */
+ if (CONFIG(ACPI_BERT) && bert_errors_present()) {
+ /* Skip the table if no errors are present. ACPI driver reports
+ * a table with a 0-length region:
+ * BERT: [Firmware Bug]: table invalid.
+ */
+ void *rgn;
+ size_t size;
+ bert_errors_region(&rgn, &size);
+ if (!rgn) {
+ printk(BIOS_ERR, "Error: Can't find BERT storage area\n");
+ } else {
+ current = ALIGN(current, 8);
+ bert = (acpi_bert_t *)current;
+ acpi_write_bert(bert, (uintptr_t)rgn, size);
+ acpi_add_table(rsdp, (void *)current);
+ current += bert->header.length;
+ }
+ }
+
+ current = ALIGN(current, 8);
+ printk(BIOS_DEBUG, "ACPI: * IVRS at %lx\n", current);
+ ivrs = agesawrapper_getlateinitptr(PICK_IVRS);
+ if (ivrs != NULL) {
+ memcpy((void *)current, ivrs, ivrs->length);
+ ivrs = (acpi_header_t *)current;
+ current += ivrs->length;
+ acpi_add_table(rsdp, ivrs);
+ } else {
+ printk(BIOS_DEBUG, " AGESA IVRS table NULL. Skipping.\n");
+ }
+
+ /* SRAT */
+ current = ALIGN(current, 8);
+ printk(BIOS_DEBUG, "ACPI: * SRAT at %lx\n", current);
+ srat = (acpi_srat_t *)agesawrapper_getlateinitptr(PICK_SRAT);
+ if (srat != NULL) {
+ memcpy((void *)current, srat, srat->header.length);
+ srat = (acpi_srat_t *)current;
+ current += srat->header.length;
+ acpi_add_table(rsdp, srat);
+ } else {
+ printk(BIOS_DEBUG, " AGESA SRAT table NULL. Skipping.\n");
+ }
+
+ /* SLIT */
+ current = ALIGN(current, 8);
+ printk(BIOS_DEBUG, "ACPI: * SLIT at %lx\n", current);
+ slit = (acpi_slit_t *)agesawrapper_getlateinitptr(PICK_SLIT);
+ if (slit != NULL) {
+ memcpy((void *)current, slit, slit->header.length);
+ slit = (acpi_slit_t *)current;
+ current += slit->header.length;
+ acpi_add_table(rsdp, slit);
+ } else {
+ printk(BIOS_DEBUG, " AGESA SLIT table NULL. Skipping.\n");
+ }
+
+ /* ALIB */
+ current = ALIGN(current, 16);
+ printk(BIOS_DEBUG, "ACPI: * AGESA ALIB SSDT at %lx\n", current);
+ alib = (acpi_header_t *)agesawrapper_getlateinitptr(PICK_ALIB);
+ if (alib != NULL) {
+ memcpy((void *)current, alib, alib->length);
+ alib = (acpi_header_t *)current;
+ current += alib->length;
+ acpi_add_table(rsdp, (void *)alib);
+ } else {
+ printk(BIOS_DEBUG, " AGESA ALIB SSDT table NULL."
+ " Skipping.\n");
+ }
+
+ current = ALIGN(current, 16);
+ printk(BIOS_DEBUG, "ACPI: * SSDT at %lx\n", current);
+ ssdt = (acpi_header_t *)agesawrapper_getlateinitptr(PICK_PSTATE);
+ if (ssdt != NULL) {
+ memcpy((void *)current, ssdt, ssdt->length);
+ ssdt = (acpi_header_t *)current;
+ current += ssdt->length;
+ } else {
+ printk(BIOS_DEBUG, " AGESA PState table NULL. Skipping.\n");
+ }
+ acpi_add_table(rsdp, ssdt);
+
+ printk(BIOS_DEBUG, "ACPI: * SSDT for PState at %lx\n", current);
+ return current;
+}
+
+static struct device_operations northbridge_operations = {
+ .read_resources = read_resources,
+ .set_resources = set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = northbridge_init,
+ .acpi_fill_ssdt_generator = northbridge_fill_ssdt_generator,
+ .write_acpi_tables = agesa_write_acpi_tables,
+ .enable = 0,
+ .ops_pci = 0,
+};
+
+static const struct pci_driver family15_northbridge __pci_driver = {
+ .ops = &northbridge_operations,
+ .vendor = PCI_VENDOR_ID_AMD,
+ .device = PCI_DEVICE_ID_AMD_15H_MODEL_707F_NB_HT,
+};
+
+/*
+ * Enable VGA cycles. Set memory ranges of the FCH legacy devices (TPM, HPET,
+ * BIOS RAM, Watchdog Timer, IOAPIC and ACPI) as non-posted. Set remaining
+ * MMIO to posted. Route all I/O to the southbridge.
+ */
+void amd_initcpuio(void)
+{
+ uintptr_t topmem = bsp_topmem();
+ uintptr_t base, limit;
+
+ /* Enable legacy video routing: D18F1xF4 VGA Enable */
+ pci_write_config32(SOC_ADDR_DEV, D18F1_VGAEN, VGA_ADDR_ENABLE);
+
+ /* Non-posted: range(HPET-LAPIC) or 0xfed00000 through 0xfee00000-1 */
+ base = (HPET_BASE_ADDRESS >> 8) | MMIO_WE | MMIO_RE;
+ limit = (ALIGN_DOWN(LOCAL_APIC_ADDR - 1, 64 * KiB) >> 8) | MMIO_NP;
+ pci_write_config32(SOC_ADDR_DEV, NB_MMIO_LIMIT_LO(0), limit);
+ pci_write_config32(SOC_ADDR_DEV, NB_MMIO_BASE_LO(0), base);
+
+ /* Remaining PCI hole posted MMIO: TOM-HPET (TOM through 0xfed00000-1 */
+ base = (topmem >> 8) | MMIO_WE | MMIO_RE;
+ limit = ALIGN_DOWN(HPET_BASE_ADDRESS - 1, 64 * KiB) >> 8;
+ pci_write_config32(SOC_ADDR_DEV, NB_MMIO_LIMIT_LO(1), limit);
+ pci_write_config32(SOC_ADDR_DEV, NB_MMIO_BASE_LO(1), base);
+
+ /* Route all I/O downstream */
+ base = 0 | IO_WE | IO_RE;
+ limit = ALIGN_DOWN(0xffff, 4 * KiB);
+ pci_write_config32(SOC_ADDR_DEV, NB_IO_LIMIT(0), limit);
+ pci_write_config32(SOC_ADDR_DEV, NB_IO_BASE(0), base);
+}
+
+void fam15_finalize(void *chip_info)
+{
+ u32 value;
+
+ /* TODO: move IOAPIC code to dsdt.asl */
+ pci_write_config32(SOC_GNB_DEV, NB_IOAPIC_INDEX, 0);
+ pci_write_config32(SOC_GNB_DEV, NB_IOAPIC_DATA, 5);
+
+ /* disable No Snoop */
+ value = pci_read_config32(SOC_HDA0_DEV, HDA_DEV_CTRL_STATUS);
+ value &= ~HDA_NO_SNOOP_EN;
+ pci_write_config32(SOC_HDA0_DEV, HDA_DEV_CTRL_STATUS, value);
+}
+
+void domain_enable_resources(struct device *dev)
+{
+ /* Must be called after PCI enumeration and resource allocation */
+ if (!romstage_handoff_is_resume())
+ do_agesawrapper(AMD_INIT_MID, "amdinitmid");
+}
+
+void domain_set_resources(struct device *dev)
+{
+ uint64_t uma_base = get_uma_base();
+ uint32_t uma_size = get_uma_size();
+ uint32_t mem_useable = (uintptr_t)cbmem_top();
+ msr_t tom = rdmsr(TOP_MEM);
+ msr_t high_tom = rdmsr(TOP_MEM2);
+ uint64_t high_mem_useable;
+ int idx = 0x10;
+
+ /* 0x0 -> 0x9ffff */
+ ram_resource(dev, idx++, 0, 0xa0000 / KiB);
+
+ /* 0xa0000 -> 0xbffff: legacy VGA */
+ mmio_resource(dev, idx++, 0xa0000 / KiB, 0x20000 / KiB);
+
+ /* 0xc0000 -> 0xfffff: Option ROM */
+ reserved_ram_resource(dev, idx++, 0xc0000 / KiB, 0x40000 / KiB);
+
+ /*
+ * 0x100000 (1MiB) -> low top useable RAM
+ * cbmem_top() accounts for low UMA and TSEG if they are used.
+ */
+ ram_resource(dev, idx++, (1 * MiB) / KiB,
+ (mem_useable - (1 * MiB)) / KiB);
+
+ /* Low top useable RAM -> Low top RAM (bottom pci mmio hole) */
+ reserved_ram_resource(dev, idx++, mem_useable / KiB,
+ (tom.lo - mem_useable) / KiB);
+
+ /* If there is memory above 4GiB */
+ if (high_tom.hi) {
+ /* 4GiB -> high top useable */
+ if (uma_base >= (4ull * GiB))
+ high_mem_useable = uma_base;
+ else
+ high_mem_useable = ((uint64_t)high_tom.lo |
+ ((uint64_t)high_tom.hi << 32));
+
+ ram_resource(dev, idx++, (4ull * GiB) / KiB,
+ ((high_mem_useable - (4ull * GiB)) / KiB));
+
+ /* High top useable RAM -> high top RAM */
+ if (uma_base >= (4ull * GiB)) {
+ reserved_ram_resource(dev, idx++, uma_base / KiB,
+ uma_size / KiB);
+ }
+ }
+
+ assign_resources(dev->link_list);
+}
+
+/*********************************************************************
+ * Change the vendor / device IDs to match the generic VBIOS header. *
+ *********************************************************************/
+u32 map_oprom_vendev(u32 vendev)
+{
+ u32 new_vendev;
+ new_vendev =
+ ((vendev >= 0x100298e0) && (vendev <= 0x100298ef)) ?
+ 0x100298e0 : vendev;
+
+ if (vendev != new_vendev)
+ printk(BIOS_NOTICE, "Mapping PCI device %8x to %8x\n",
+ vendev, new_vendev);
+
+ return new_vendev;
+}
+
+__weak void set_board_env_params(GNB_ENV_CONFIGURATION *params) { }
+
+void SetNbEnvParams(GNB_ENV_CONFIGURATION *params)
+{
+ const struct device *dev = SOC_IOMMU_DEV;
+ params->IommuSupport = dev && dev->enabled;
+ set_board_env_params(params);
+}
+
+void SetNbMidParams(GNB_MID_CONFIGURATION *params)
+{
+ /* 0=Primary and decode all VGA resources, 1=Secondary - decode none */
+ params->iGpuVgaMode = 0;
+ params->GnbIoapicAddress = IO_APIC2_ADDR;
+}
diff --git a/src/soc/amd/picasso/pmutil.c b/src/soc/amd/picasso/pmutil.c
new file mode 100644
index 0000000000..59de34890f
--- /dev/null
+++ b/src/soc/amd/picasso/pmutil.c
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2017 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.
+ */
+
+#include <arch/acpi.h>
+#include <soc/southbridge.h>
+#include <amdblocks/acpimmio.h>
+#include <security/vboot/vboot_common.h>
+#include <security/vboot/vbnv.h>
+#include <pc80/mc146818rtc.h>
+
+int vbnv_cmos_failed(void)
+{
+ /* If CMOS power has failed, the century will be set to 0xff */
+ return cmos_read(RTC_CLK_ALTCENTURY) == 0xff;
+}
diff --git a/src/soc/amd/picasso/ramtop.c b/src/soc/amd/picasso/ramtop.c
new file mode 100644
index 0000000000..7c855bb1e1
--- /dev/null
+++ b/src/soc/amd/picasso/ramtop.c
@@ -0,0 +1,151 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define __SIMPLE_DEVICE__
+
+#include <assert.h>
+#include <stdint.h>
+#include <console/console.h>
+#include <cpu/x86/msr.h>
+#include <cpu/amd/msr.h>
+#include <cpu/amd/mtrr.h>
+#include <cbmem.h>
+#include <stage_cache.h>
+#include <arch/bert_storage.h>
+#include <soc/northbridge.h>
+#include <soc/iomap.h>
+#include <amdblocks/acpimmio.h>
+
+void backup_top_of_low_cacheable(uintptr_t ramtop)
+{
+ biosram_write32(BIOSRAM_CBMEM_TOP, ramtop);
+}
+
+uintptr_t restore_top_of_low_cacheable(void)
+{
+ return biosram_read32(BIOSRAM_CBMEM_TOP);
+}
+
+#if CONFIG(ACPI_BERT)
+ #if CONFIG_SMM_TSEG_SIZE == 0x0
+ #define BERT_REGION_MAX_SIZE 0x100000
+ #else
+ /* SMM_TSEG_SIZE must stay on a boundary appropriate for its granularity */
+ #define BERT_REGION_MAX_SIZE CONFIG_SMM_TSEG_SIZE
+ #endif
+#else
+ #define BERT_REGION_MAX_SIZE 0
+#endif
+
+void bert_reserved_region(void **start, size_t *size)
+{
+ if (CONFIG(ACPI_BERT))
+ *start = cbmem_top();
+ else
+ start = NULL;
+ *size = BERT_REGION_MAX_SIZE;
+}
+
+void *cbmem_top(void)
+{
+ msr_t tom = rdmsr(TOP_MEM);
+
+ if (!tom.lo)
+ return 0;
+
+ /* 8MB alignment to keep MTRR usage low */
+ return (void *)ALIGN_DOWN(restore_top_of_low_cacheable()
+ - CONFIG_SMM_TSEG_SIZE
+ - BERT_REGION_MAX_SIZE, 8*MiB);
+}
+
+static uintptr_t smm_region_start(void)
+{
+ return (uintptr_t)cbmem_top() + BERT_REGION_MAX_SIZE;
+}
+
+static size_t smm_region_size(void)
+{
+ return CONFIG_SMM_TSEG_SIZE;
+}
+
+void stage_cache_external_region(void **base, size_t *size)
+{
+ if (smm_subregion(SMM_SUBREGION_CACHE, base, size)) {
+ printk(BIOS_ERR, "ERROR: No cache SMM subregion.\n");
+ *base = NULL;
+ *size = 0;
+ }
+}
+
+void smm_region_info(void **start, size_t *size)
+{
+ *start = (void *)smm_region_start();
+ *size = smm_region_size();
+}
+
+/*
+ * For data stored in TSEG, ensure TValid is clear so R/W access can reach
+ * the DRAM when not in SMM.
+ */
+static void clear_tvalid(void)
+{
+ msr_t hwcr = rdmsr(HWCR_MSR);
+ msr_t mask = rdmsr(SMM_MASK_MSR);
+ int tvalid = !!(mask.lo & SMM_TSEG_VALID);
+
+ if (hwcr.lo & SMM_LOCK) {
+ if (!tvalid) /* not valid but locked means still accessible */
+ return;
+
+ printk(BIOS_ERR, "Error: can't clear TValid, already locked\n");
+ return;
+ }
+
+ mask.lo &= ~SMM_TSEG_VALID;
+ wrmsr(SMM_MASK_MSR, mask);
+}
+
+int smm_subregion(int sub, void **start, size_t *size)
+{
+ uintptr_t sub_base;
+ size_t sub_size;
+ const size_t cache_size = CONFIG_SMM_RESERVED_SIZE;
+
+ sub_base = smm_region_start();
+ sub_size = smm_region_size();
+
+ assert(sub_size > CONFIG_SMM_RESERVED_SIZE);
+
+ switch (sub) {
+ case SMM_SUBREGION_HANDLER:
+ /* Handler starts at the base of TSEG. */
+ sub_size -= cache_size;
+ break;
+ case SMM_SUBREGION_CACHE:
+ /* External cache is in the middle of TSEG. */
+ sub_base += sub_size - cache_size;
+ sub_size = cache_size;
+ clear_tvalid();
+ break;
+ default:
+ return -1;
+ }
+
+ *start = (void *)sub_base;
+ *size = sub_size;
+
+ return 0;
+}
diff --git a/src/soc/amd/picasso/reset.c b/src/soc/amd/picasso/reset.c
new file mode 100644
index 0000000000..ec5ee910d9
--- /dev/null
+++ b/src/soc/amd/picasso/reset.c
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010 Advanced Micro Devices, Inc.
+ * Copyright (C) 2017 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.
+ */
+
+#include <arch/io.h>
+#include <reset.h>
+#include <soc/northbridge.h>
+#include <soc/pci_devs.h>
+#include <device/pci_ops.h>
+#include <soc/southbridge.h>
+#include <amdblocks/acpimmio.h>
+#include <amdblocks/reset.h>
+
+void set_warm_reset_flag(void)
+{
+ u32 htic;
+ htic = pci_read_config32(SOC_HT_DEV, HT_INIT_CONTROL);
+ htic |= HTIC_COLD_RST_DET;
+ pci_write_config32(SOC_HT_DEV, HT_INIT_CONTROL, htic);
+}
+
+int is_warm_reset(void)
+{
+ u32 htic;
+ htic = pci_read_config32(SOC_HT_DEV, HT_INIT_CONTROL);
+ return !!(htic & HTIC_COLD_RST_DET);
+}
+
+/* Clear bits 5, 9 & 10, used to signal the reset type */
+static void clear_bios_reset(void)
+{
+ u32 htic;
+ htic = pci_read_config32(SOC_HT_DEV, HT_INIT_CONTROL);
+ htic &= ~HTIC_BIOSR_DETECT;
+ pci_write_config32(SOC_HT_DEV, HT_INIT_CONTROL, htic);
+}
+
+void do_cold_reset(void)
+{
+ clear_bios_reset();
+
+ /* De-assert and then assert all PwrGood signals on CF9 reset. */
+ pm_write16(PWR_RESET_CFG, pm_read16(PWR_RESET_CFG) |
+ TOGGLE_ALL_PWR_GOOD);
+ outb(RST_CMD | SYS_RST, SYS_RESET);
+}
+
+void do_warm_reset(void)
+{
+ set_warm_reset_flag();
+ clear_bios_reset();
+
+ /* Assert reset signals only. */
+ outb(RST_CMD | SYS_RST, SYS_RESET);
+}
+
+void do_board_reset(void)
+{
+ /* TODO: Would a warm_reset() suffice? */
+ do_cold_reset();
+}
diff --git a/src/soc/amd/picasso/romstage.c b/src/soc/amd/picasso/romstage.c
new file mode 100644
index 0000000000..12ee2a8aca
--- /dev/null
+++ b/src/soc/amd/picasso/romstage.c
@@ -0,0 +1,247 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015-2016 Advanced Micro Devices, Inc.
+ * Copyright (C) 2015 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <device/pci_ops.h>
+#include <arch/cpu.h>
+#include <arch/acpi.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/amd/mtrr.h>
+#include <cbmem.h>
+#include <commonlib/helpers.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <program_loading.h>
+#include <romstage_handoff.h>
+#include <elog.h>
+#include <amdblocks/agesawrapper.h>
+#include <amdblocks/agesawrapper_call.h>
+#include <soc/northbridge.h>
+#include <soc/romstage.h>
+#include <soc/southbridge.h>
+#include <amdblocks/psp.h>
+
+#include "chip.h"
+
+void __weak mainboard_romstage_entry(int s3_resume)
+{
+ /* By default, don't do anything */
+}
+
+static void load_smu_fw1(void)
+{
+ u32 base, limit, cmd;
+
+ /* Open a posted hole from 0x80000000 : 0xfed00000-1 */
+ base = (0x80000000 >> 8) | MMIO_WE | MMIO_RE;
+ limit = (ALIGN_DOWN(HPET_BASE_ADDRESS - 1, 64 * KiB) >> 8);
+ pci_write_config32(SOC_ADDR_DEV, D18F1_MMIO_LIMIT0_LO, limit);
+ pci_write_config32(SOC_ADDR_DEV, D18F1_MMIO_BASE0_LO, base);
+
+ /* Preload a value into "BAR3" and enable it */
+ pci_write_config32(SOC_PSP_DEV, PSP_MAILBOX_BAR, PSP_MAILBOX_BAR3_BASE);
+ pci_write_config32(SOC_PSP_DEV, PSP_BAR_ENABLES, PSP_MAILBOX_BAR_EN);
+
+ /* Enable memory access and master */
+ cmd = pci_read_config32(SOC_PSP_DEV, PCI_COMMAND);
+ cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+ pci_write_config32(SOC_PSP_DEV, PCI_COMMAND, cmd);
+
+ psp_load_named_blob(MBOX_BIOS_CMD_SMU_FW, "smu_fw");
+}
+
+static void agesa_call(void)
+{
+ post_code(0x37);
+ do_agesawrapper(AMD_INIT_RESET, "amdinitreset");
+
+ post_code(0x38);
+ /* APs will not exit amdinitearly */
+ do_agesawrapper(AMD_INIT_EARLY, "amdinitearly");
+}
+
+static void bsp_agesa_call(void)
+{
+ set_ap_entry_ptr(agesa_call); /* indicate the path to the AP */
+ agesa_call();
+}
+
+asmlinkage void car_stage_entry(void)
+{
+ struct postcar_frame pcf;
+ uintptr_t top_of_ram;
+ void *smm_base;
+ size_t smm_size;
+ uintptr_t tseg_base;
+ msr_t base, mask;
+ msr_t mtrr_cap = rdmsr(MTRR_CAP_MSR);
+ int vmtrrs = mtrr_cap.lo & MTRR_CAP_VCNT;
+ int s3_resume = acpi_s3_resume_allowed() && acpi_is_wakeup_s3();
+ int i;
+
+ console_init();
+
+ if (CONFIG(SOC_AMD_PSP_SELECTABLE_SMU_FW))
+ load_smu_fw1();
+
+ mainboard_romstage_entry(s3_resume);
+
+ bsp_agesa_call();
+
+ if (!s3_resume) {
+ post_code(0x40);
+ do_agesawrapper(AMD_INIT_POST, "amdinitpost");
+
+ post_code(0x41);
+ /*
+ * TODO: This is a hack to work around current AGESA behavior.
+ * AGESA needs to change to reflect that coreboot owns
+ * the MTRRs.
+ *
+ * After setting up DRAM, AGESA also completes the configuration
+ * of the MTRRs, setting regions to WB. Anything written to
+ * memory between now and and when CAR is dismantled will be
+ * in cache and lost. For now, set the regions UC to ensure
+ * the writes get to DRAM.
+ */
+ for (i = 0 ; i < vmtrrs ; i++) {
+ base = rdmsr(MTRR_PHYS_BASE(i));
+ mask = rdmsr(MTRR_PHYS_MASK(i));
+ if (!(mask.lo & MTRR_PHYS_MASK_VALID))
+ continue;
+
+ if ((base.lo & 0x7) == MTRR_TYPE_WRBACK) {
+ base.lo &= ~0x7;
+ base.lo |= MTRR_TYPE_UNCACHEABLE;
+ wrmsr(MTRR_PHYS_BASE(i), base);
+ }
+ }
+ /* Disable WB from to region 4GB-TOM2. */
+ msr_t sys_cfg = rdmsr(SYSCFG_MSR);
+ sys_cfg.lo &= ~SYSCFG_MSR_TOM2WB;
+ wrmsr(SYSCFG_MSR, sys_cfg);
+ if (CONFIG(ELOG_BOOT_COUNT))
+ boot_count_increment();
+ } else {
+ printk(BIOS_INFO, "S3 detected\n");
+ post_code(0x60);
+ do_agesawrapper(AMD_INIT_RESUME, "amdinitresume");
+
+ post_code(0x61);
+ }
+
+ post_code(0x42);
+ psp_notify_dram();
+
+ post_code(0x43);
+ if (cbmem_recovery(s3_resume))
+ printk(BIOS_CRIT, "Failed to recover cbmem\n");
+ if (romstage_handoff_init(s3_resume))
+ printk(BIOS_ERR, "Failed to set romstage handoff data\n");
+
+ post_code(0x44);
+ if (postcar_frame_init(&pcf, 1 * KiB))
+ die("Unable to initialize postcar frame.\n");
+
+ /*
+ * We need to make sure ramstage will be run cached. At this point exact
+ * location of ramstage in cbmem is not known. Instruct postcar to cache
+ * 16 megs under cbmem top which is a safe bet to cover ramstage.
+ */
+ top_of_ram = (uintptr_t) cbmem_top();
+ postcar_frame_add_mtrr(&pcf, top_of_ram - 16*MiB, 16*MiB,
+ MTRR_TYPE_WRBACK);
+
+ /* Cache the memory-mapped boot media. */
+ postcar_frame_add_romcache(&pcf, MTRR_TYPE_WRPROT);
+
+ /*
+ * Cache the TSEG region at the top of ram. This region is
+ * not restricted to SMM mode until SMM has been relocated.
+ * By setting the region to cacheable it provides faster access
+ * when relocating the SMM handler as well as using the TSEG
+ * region for other purposes.
+ */
+ smm_region_info(&smm_base, &smm_size);
+ tseg_base = (uintptr_t)smm_base;
+ postcar_frame_add_mtrr(&pcf, tseg_base, smm_size, MTRR_TYPE_WRBACK);
+
+ post_code(0x45);
+ run_postcar_phase(&pcf);
+
+ post_code(0x50); /* Should never see this post code. */
+}
+
+void SetMemParams(AMD_POST_PARAMS *PostParams)
+{
+ const struct soc_amd_stoneyridge_config *cfg;
+ const struct device *dev = pcidev_path_on_root(GNB_DEVFN);
+
+ if (!dev || !dev->chip_info) {
+ printk(BIOS_ERR, "ERROR: Cannot find SoC devicetree config\n");
+ /* In case of a BIOS error, only attempt to set UMA. */
+ PostParams->MemConfig.UmaMode = CONFIG(GFXUMA) ?
+ UMA_AUTO : UMA_NONE;
+ return;
+ }
+
+ cfg = dev->chip_info;
+
+ PostParams->MemConfig.EnableMemClr = cfg->dram_clear_on_reset;
+
+ switch (cfg->uma_mode) {
+ case UMAMODE_NONE:
+ PostParams->MemConfig.UmaMode = UMA_NONE;
+ break;
+ case UMAMODE_SPECIFIED_SIZE:
+ PostParams->MemConfig.UmaMode = UMA_SPECIFIED;
+ /* 64 KiB blocks. */
+ PostParams->MemConfig.UmaSize = cfg->uma_size / (64 * KiB);
+ break;
+ case UMAMODE_AUTO_LEGACY:
+ PostParams->MemConfig.UmaMode = UMA_AUTO;
+ PostParams->MemConfig.UmaVersion = UMA_LEGACY;
+ break;
+ case UMAMODE_AUTO_NON_LEGACY:
+ PostParams->MemConfig.UmaMode = UMA_AUTO;
+ PostParams->MemConfig.UmaVersion = UMA_NON_LEGACY;
+ break;
+ }
+}
+
+void soc_customize_init_early(AMD_EARLY_PARAMS *InitEarly)
+{
+ const struct soc_amd_stoneyridge_config *cfg;
+ const struct device *dev = pcidev_path_on_root(GNB_DEVFN);
+ struct _PLATFORM_CONFIGURATION *platform;
+
+ if (!dev || !dev->chip_info) {
+ printk(BIOS_WARNING, "Warning: Cannot find SoC devicetree"
+ " config, STAPM unchanged\n");
+ return;
+ }
+ cfg = dev->chip_info;
+ platform = &InitEarly->PlatformConfig;
+ if ((cfg->stapm_percent) && (cfg->stapm_time_ms) &&
+ (cfg->stapm_power_mw)) {
+ platform->PlatStapmConfig.CfgStapmScalar = cfg->stapm_percent;
+ platform->PlatStapmConfig.CfgStapmTimeConstant =
+ cfg->stapm_time_ms;
+ platform->PkgPwrLimitDC = cfg->stapm_power_mw;
+ platform->PkgPwrLimitAC = cfg->stapm_power_mw;
+ platform->PlatStapmConfig.CfgStapmBoost = StapmBoostEnabled;
+ }
+}
diff --git a/src/soc/amd/picasso/sata.c b/src/soc/amd/picasso/sata.c
new file mode 100644
index 0000000000..6740698dd2
--- /dev/null
+++ b/src/soc/amd/picasso/sata.c
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010 Advanced Micro Devices, 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.
+ */
+
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <device/pci_def.h>
+#include <amdblocks/sata.h>
+#include <soc/southbridge.h>
+
+void soc_enable_sata_features(struct device *dev)
+{
+ u8 *ahci_ptr;
+ u32 misc_ctl, cap_cfg;
+
+ u32 temp;
+
+ /* unlock the write-protect */
+ misc_ctl = pci_read_config32(dev, SATA_MISC_CONTROL_REG);
+ misc_ctl |= SATA_MISC_SUBCLASS_WREN;
+ pci_write_config32(dev, SATA_MISC_CONTROL_REG, misc_ctl);
+
+ /* set the SATA AHCI mode to allow port expanders */
+ ahci_ptr = (u8 *)(uintptr_t)ALIGN_DOWN(
+ pci_read_config32(dev, PCI_BASE_ADDRESS_5), 256);
+
+ cap_cfg = read32(ahci_ptr + SATA_CAPABILITIES_REG);
+ cap_cfg |= SATA_CAPABILITY_SPM;
+ write32(ahci_ptr + SATA_CAPABILITIES_REG, cap_cfg);
+
+ /* lock the write-protect */
+ temp = pci_read_config32(dev, SATA_MISC_CONTROL_REG);
+ temp &= ~SATA_MISC_SUBCLASS_WREN;
+ pci_write_config32(dev, SATA_MISC_CONTROL_REG, temp);
+};
diff --git a/src/soc/amd/picasso/sm.c b/src/soc/amd/picasso/sm.c
new file mode 100644
index 0000000000..803e628320
--- /dev/null
+++ b/src/soc/amd/picasso/sm.c
@@ -0,0 +1,104 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010 Advanced Micro Devices, 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.
+ */
+
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <device/smbus.h>
+#include <cpu/x86/lapic.h>
+#include <arch/ioapic.h>
+#include <stdlib.h>
+#include <soc/southbridge.h>
+#include <soc/smbus.h>
+
+/*
+* The southbridge enables all USB controllers by default in SMBUS Control.
+* The southbridge enables SATA by default in SMBUS Control.
+*/
+
+static void sm_init(struct device *dev)
+{
+ setup_ioapic(VIO_APIC_VADDR, CONFIG_MAX_CPUS);
+}
+
+static u32 get_sm_mmio(struct device *dev)
+{
+ struct resource *res;
+ struct bus *pbus;
+
+ pbus = get_pbus_smbus(dev);
+ res = find_resource(pbus->dev, 0x90);
+ if (res->base == SMB_BASE_ADDR)
+ return ACPIMMIO_SMBUS_BASE;
+
+ return ACPIMMIO_ASF_BASE;
+}
+
+static int lsmbus_recv_byte(struct device *dev)
+{
+ u8 device;
+
+ device = dev->path.i2c.device;
+ return do_smbus_recv_byte(get_sm_mmio(dev), device);
+}
+
+static int lsmbus_send_byte(struct device *dev, u8 val)
+{
+ u8 device;
+
+ device = dev->path.i2c.device;
+ return do_smbus_send_byte(get_sm_mmio(dev), device, val);
+}
+
+static int lsmbus_read_byte(struct device *dev, u8 address)
+{
+ u8 device;
+
+ device = dev->path.i2c.device;
+ return do_smbus_read_byte(get_sm_mmio(dev), device, address);
+}
+
+static int lsmbus_write_byte(struct device *dev, u8 address, u8 val)
+{
+ u8 device;
+
+ device = dev->path.i2c.device;
+ return do_smbus_write_byte(get_sm_mmio(dev), device, address, val);
+}
+static struct smbus_bus_operations lops_smbus_bus = {
+ .recv_byte = lsmbus_recv_byte,
+ .send_byte = lsmbus_send_byte,
+ .read_byte = lsmbus_read_byte,
+ .write_byte = lsmbus_write_byte,
+};
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = pci_dev_set_subsystem,
+};
+static struct device_operations smbus_ops = {
+ .read_resources = DEVICE_NOOP,
+ .set_resources = DEVICE_NOOP,
+ .enable_resources = pci_dev_enable_resources,
+ .init = sm_init,
+ .scan_bus = scan_smbus,
+ .ops_pci = &lops_pci,
+ .ops_smbus_bus = &lops_smbus_bus,
+};
+static const struct pci_driver smbus_driver __pci_driver = {
+ .ops = &smbus_ops,
+ .vendor = PCI_VENDOR_ID_AMD,
+ .device = PCI_DEVICE_ID_AMD_CZ_SMBUS,
+};
diff --git a/src/soc/amd/picasso/smbus.c b/src/soc/amd/picasso/smbus.c
new file mode 100644
index 0000000000..31457f98b8
--- /dev/null
+++ b/src/soc/amd/picasso/smbus.c
@@ -0,0 +1,191 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010 Advanced Micro Devices, 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.
+ */
+
+#include <arch/io.h>
+#include <stdint.h>
+#include <console/console.h>
+#include <amdblocks/acpimmio.h>
+#include <soc/smbus.h>
+#include <soc/southbridge.h>
+
+static u8 controller_read8(u32 base, u8 reg)
+{
+ switch (base) {
+ case ACPIMMIO_SMBUS_BASE:
+ return smbus_read8(reg);
+ case ACPIMMIO_ASF_BASE:
+ return asf_read8(reg);
+ default:
+ printk(BIOS_ERR, "Error attempting to read SMBus at address 0x%x\n",
+ base);
+ }
+ return 0xff;
+}
+
+static void controller_write8(u32 base, u8 reg, u8 val)
+{
+ switch (base) {
+ case ACPIMMIO_SMBUS_BASE:
+ smbus_write8(reg, val);
+ break;
+ case ACPIMMIO_ASF_BASE:
+ asf_write8(reg, val);
+ break;
+ default:
+ printk(BIOS_ERR, "Error attempting to write SMBus at address 0x%x\n",
+ base);
+ }
+}
+
+static int smbus_wait_until_ready(u32 mmio)
+{
+ u32 loops;
+ loops = SMBUS_TIMEOUT;
+ do {
+ u8 val;
+ val = controller_read8(mmio, SMBHSTSTAT);
+ val &= SMBHST_STAT_VAL_BITS;
+ if (val == 0) { /* ready now */
+ return 0;
+ }
+ controller_write8(mmio, SMBHSTSTAT, val);
+ } while (--loops);
+ return -2; /* time out */
+}
+
+static int smbus_wait_until_done(u32 mmio)
+{
+ u32 loops;
+ loops = SMBUS_TIMEOUT;
+ do {
+ u8 val;
+
+ val = controller_read8(mmio, SMBHSTSTAT);
+ val &= SMBHST_STAT_VAL_BITS; /* mask off reserved bits */
+ if (val & SMBHST_STAT_ERROR_BITS)
+ return -5; /* error */
+ if (val == SMBHST_STAT_NOERROR) {
+ controller_write8(mmio, SMBHSTSTAT, val); /* clr sts */
+ return 0;
+ }
+ } while (--loops);
+ return -3; /* timeout */
+}
+
+int do_smbus_recv_byte(u32 mmio, u8 device)
+{
+ u8 byte;
+
+ if (smbus_wait_until_ready(mmio) < 0)
+ return -2; /* not ready */
+
+ /* set the device I'm talking to */
+ controller_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 1);
+
+ byte = controller_read8(mmio, SMBHSTCTRL);
+ byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */
+ byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BTE_RW; /* set mode, start */
+ controller_write8(mmio, SMBHSTCTRL, byte);
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_done(mmio) < 0)
+ return -3; /* timeout or error */
+
+ /* read results of transaction */
+ byte = controller_read8(mmio, SMBHSTDAT0);
+
+ return byte;
+}
+
+int do_smbus_send_byte(u32 mmio, u8 device, u8 val)
+{
+ u8 byte;
+
+ if (smbus_wait_until_ready(mmio) < 0)
+ return -2; /* not ready */
+
+ /* set the command... */
+ controller_write8(mmio, SMBHSTDAT0, val);
+
+ /* set the device I'm talking to */
+ controller_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 0);
+
+ byte = controller_read8(mmio, SMBHSTCTRL);
+ byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */
+ byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BTE_RW; /* set mode, start */
+ controller_write8(mmio, SMBHSTCTRL, byte);
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_done(mmio) < 0)
+ return -3; /* timeout or error */
+
+ return 0;
+}
+
+int do_smbus_read_byte(u32 mmio, u8 device, u8 address)
+{
+ u8 byte;
+
+ if (smbus_wait_until_ready(mmio) < 0)
+ return -2; /* not ready */
+
+ /* set the command/address... */
+ controller_write8(mmio, SMBHSTCMD, address & 0xff);
+
+ /* set the device I'm talking to */
+ controller_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 1);
+
+ byte = controller_read8(mmio, SMBHSTCTRL);
+ byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */
+ byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BDT_RW; /* set mode, start */
+ controller_write8(mmio, SMBHSTCTRL, byte);
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_done(mmio) < 0)
+ return -3; /* timeout or error */
+
+ /* read results of transaction */
+ byte = controller_read8(mmio, SMBHSTDAT0);
+
+ return byte;
+}
+
+int do_smbus_write_byte(u32 mmio, u8 device, u8 address, u8 val)
+{
+ u8 byte;
+
+ if (smbus_wait_until_ready(mmio) < 0)
+ return -2; /* not ready */
+
+ /* set the command/address... */
+ controller_write8(mmio, SMBHSTCMD, address & 0xff);
+
+ /* set the device I'm talking to */
+ controller_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 0);
+
+ /* output value */
+ controller_write8(mmio, SMBHSTDAT0, val);
+
+ byte = controller_read8(mmio, SMBHSTCTRL);
+ byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */
+ byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BDT_RW; /* set mode, start */
+ controller_write8(mmio, SMBHSTCTRL, byte);
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_done(mmio) < 0)
+ return -3; /* timeout or error */
+
+ return 0;
+}
diff --git a/src/soc/amd/picasso/smbus_spd.c b/src/soc/amd/picasso/smbus_spd.c
new file mode 100644
index 0000000000..e57ecde578
--- /dev/null
+++ b/src/soc/amd/picasso/smbus_spd.c
@@ -0,0 +1,76 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012, 2017 Advanced Micro Devices, 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.
+ */
+
+#include <amdblocks/agesawrapper.h>
+#include <console/console.h>
+#include <device/pci_def.h>
+#include <device/device.h>
+#include <soc/southbridge.h>
+#include <soc/smbus.h>
+#include <amdblocks/dimm_spd.h>
+
+/*
+ * readspd - Read one or more SPD bytes from a DIMM.
+ * Start with offset zero and read sequentially.
+ * Optimization relies on autoincrement to avoid
+ * sending offset for every byte.
+ * Reads 128 bytes in 7-8 ms at 400 KHz.
+ */
+static int readspd(uint8_t SmbusSlaveAddress, char *buffer, size_t count)
+{
+ uint8_t dev_addr;
+ size_t index;
+ int error;
+ char *pbuf = buffer;
+
+ printk(BIOS_SPEW, "-------------READING SPD-----------\n");
+ printk(BIOS_SPEW, "SmbusSlave: 0x%08X, count: %zd\n",
+ SmbusSlaveAddress, count);
+
+ /*
+ * Convert received device address to the format accepted by
+ * do_smbus_read_byte and do_smbus_recv_byte.
+ */
+ dev_addr = (SmbusSlaveAddress >> 1);
+
+ /* Read the first SPD byte */
+ error = do_smbus_read_byte(ACPIMMIO_SMBUS_BASE, dev_addr, 0);
+ if (error < 0) {
+ printk(BIOS_ERR, "-------------SPD READ ERROR-----------\n");
+ return error;
+ }
+ *pbuf = (char) error;
+ pbuf++;
+
+ /* Read the remaining SPD bytes using do_smbus_recv_byte for speed */
+ for (index = 1 ; index < count ; index++) {
+ error = do_smbus_recv_byte(ACPIMMIO_SMBUS_BASE, dev_addr);
+ if (error < 0) {
+ printk(BIOS_ERR, "-------------SPD READ ERROR-----------\n");
+ return error;
+ }
+ *pbuf = (char) error;
+ pbuf++;
+ }
+ printk(BIOS_SPEW, "\n");
+ printk(BIOS_SPEW, "-------------FINISHED READING SPD-----------\n");
+
+ return 0;
+}
+
+int sb_read_spd(uint8_t spdAddress, char *buf, size_t len)
+{
+ return readspd(spdAddress, buf, len);
+}
diff --git a/src/soc/amd/picasso/smi.c b/src/soc/amd/picasso/smi.c
new file mode 100644
index 0000000000..4a0d833c7b
--- /dev/null
+++ b/src/soc/amd/picasso/smi.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Alexandru Gagniuc <mr.nuke.me@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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.
+ */
+
+/*
+ * Utilities for SMM setup
+ */
+
+#include <console/console.h>
+#include <amdblocks/acpimmio.h>
+#include <soc/southbridge.h>
+#include <soc/smi.h>
+
+void smm_setup_structures(void *gnvs, void *tcg, void *smi1)
+{
+ printk(BIOS_DEBUG, "%s STUB!!!\n", __func__);
+}
+
+/** Set the EOS bit and enable SMI generation from southbridge */
+void enable_smi_generation(void)
+{
+ uint32_t reg = smi_read32(SMI_REG_SMITRIG0);
+ reg &= ~SMITRG0_SMIENB; /* Enable SMI generation */
+ reg |= SMITRG0_EOS; /* Set EOS bit */
+ smi_write32(SMI_REG_SMITRIG0, reg);
+}
diff --git a/src/soc/amd/picasso/smi_util.c b/src/soc/amd/picasso/smi_util.c
new file mode 100644
index 0000000000..8759e2acb1
--- /dev/null
+++ b/src/soc/amd/picasso/smi_util.c
@@ -0,0 +1,138 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Alexandru Gagniuc <mr.nuke.me@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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.
+ */
+
+/*
+ * SMM utilities used in both SMM and normal mode
+ */
+
+#include <console/console.h>
+#include <soc/southbridge.h>
+#include <soc/smi.h>
+#include <amdblocks/acpimmio.h>
+
+void configure_smi(uint8_t smi_num, uint8_t mode)
+{
+ uint8_t reg32_offset, bit_offset;
+ uint32_t reg32;
+
+ if (smi_num >= NUMBER_SMITYPES) {
+ printk(BIOS_WARNING, "BUG: Invalid SMI: %u\n", smi_num);
+ return;
+ }
+
+ /* 16 sources per register, 2 bits per source; registers are 4 bytes */
+ reg32_offset = (smi_num / 16) * 4;
+ bit_offset = (smi_num % 16) * 2;
+
+ reg32 = smi_read32(SMI_REG_CONTROL0 + reg32_offset);
+ reg32 &= ~(0x3 << (bit_offset));
+ reg32 |= (mode & 0x3) << bit_offset;
+ smi_write32(SMI_REG_CONTROL0 + reg32_offset, reg32);
+}
+
+/**
+ * Configure generation of interrupts for given GEVENT pin
+ *
+ * @param gevent The GEVENT pin number. Valid values are 0 thru 23
+ * @param mode The type of event this pin should generate. Note that only
+ * SMI_MODE_SMI generates an SMI. SMI_MODE_DISABLE disables events.
+ * @param level SMI__SCI_LVL_LOW or SMI_SCI_LVL_HIGH
+ */
+void configure_gevent_smi(uint8_t gevent, uint8_t mode, uint8_t level)
+{
+ uint32_t reg32;
+ /* GEVENT pins range from [0:23] */
+ if (gevent >= SMI_GEVENTS) {
+ printk(BIOS_WARNING, "BUG: Invalid GEVENT: %u\n", gevent);
+ return;
+ }
+
+ /* SMI0 source is GEVENT0 and so on */
+ configure_smi(gevent, mode);
+
+ /* And set set the trigger level */
+ reg32 = smi_read32(SMI_REG_SMITRIG0);
+ reg32 &= ~(1 << gevent);
+ reg32 |= (level & 0x1) << gevent;
+ smi_write32(SMI_REG_SMITRIG0, reg32);
+}
+
+/**
+ * Configure generation of SCIs.
+ */
+void configure_scimap(const struct sci_source *sci)
+{
+ uint32_t reg32;
+
+ /* GEVENT pins range */
+ if (sci->scimap >= SCIMAPS) {
+ printk(BIOS_WARNING, "BUG: Invalid SCIMAP: %u\n",
+ sci->scimap);
+ return;
+ }
+
+ /* GPEs range from [0:31] */
+ if (sci->gpe >= SCI_GPES) {
+ printk(BIOS_WARNING, "BUG: Invalid SCI GPE: %u\n", sci->gpe);
+ return;
+ }
+
+ printk(BIOS_DEBUG, "SCIMAP %u maps to GPE %u (active %s, %s trigger)\n",
+ sci->scimap, sci->gpe,
+ (!!sci->direction) ? "high" : "low",
+ (!!sci->level) ? "level" : "edge");
+
+ /* Map Gevent to SCI GPE# */
+ smi_write8(SMI_SCI_MAP(sci->scimap), sci->gpe);
+
+ /* Set the trigger direction (high/low) */
+ reg32 = smi_read32(SMI_SCI_TRIG);
+ reg32 &= ~(1 << sci->gpe);
+ reg32 |= !!sci->direction << sci->gpe;
+ smi_write32(SMI_SCI_TRIG, reg32);
+
+ /* Set the trigger level (edge/level) */
+ reg32 = smi_read32(SMI_SCI_LEVEL);
+ reg32 &= ~(1 << sci->gpe);
+ reg32 |= !!sci->level << sci->gpe;
+ smi_write32(SMI_SCI_LEVEL, reg32);
+}
+
+void gpe_configure_sci(const struct sci_source *scis, size_t num_gpes)
+{
+ size_t i;
+
+ for (i = 0; i < num_gpes; i++)
+ configure_scimap(scis + i);
+}
+
+/** Disable events from given GEVENT pin */
+void disable_gevent_smi(uint8_t gevent)
+{
+ /* GEVENT pins range from [0:23] */
+ if (gevent > 23) {
+ printk(BIOS_WARNING, "BUG: Invalid GEVENT: %u\n", gevent);
+ return;
+ }
+
+ /* SMI0 source is GEVENT0 and so on */
+ configure_smi(gevent, SMI_MODE_DISABLE);
+}
+
+uint16_t pm_acpi_smi_cmd_port(void)
+{
+ return pm_read16(PM_ACPI_SMI_CMD);
+}
diff --git a/src/soc/amd/picasso/smihandler.c b/src/soc/amd/picasso/smihandler.c
new file mode 100644
index 0000000000..d8438bb366
--- /dev/null
+++ b/src/soc/amd/picasso/smihandler.c
@@ -0,0 +1,287 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2017 Advanced Micro Devices, Inc.
+ * Copyright (C) 2014 Alexandru Gagniuc <mr.nuke.me@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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.
+ */
+
+#include <arch/io.h>
+#include <console/console.h>
+#include <cpu/x86/smm.h>
+#include <cpu/x86/cache.h>
+#include <arch/acpi.h>
+#include <arch/hlt.h>
+#include <device/pci_def.h>
+#include <soc/smi.h>
+#include <soc/southbridge.h>
+#include <amdblocks/acpimmio.h>
+#include <amdblocks/acpi.h>
+#include <elog.h>
+
+/* bits in smm_io_trap */
+#define SMM_IO_TRAP_PORT_OFFSET 16
+#define SMM_IO_TRAP_PORT_ADDRESS_MASK 0xffff
+#define SMM_IO_TRAP_RW (1 << 0)
+#define SMM_IO_TRAP_VALID (1 << 1)
+
+static inline u16 get_io_address(u32 info)
+{
+ return ((info >> SMM_IO_TRAP_PORT_OFFSET) &
+ SMM_IO_TRAP_PORT_ADDRESS_MASK);
+}
+
+static void *find_save_state(int cmd)
+{
+ int core;
+ amd64_smm_state_save_area_t *state;
+ u32 smm_io_trap;
+ u8 reg_al;
+
+ /* Check all nodes looking for the one that issued the IO */
+ for (core = 0; core < CONFIG_MAX_CPUS; core++) {
+ state = smm_get_save_state(core);
+ smm_io_trap = state->smm_io_trap_offset;
+ /* Check for Valid IO Trap Word (bit1==1) */
+ if (!(smm_io_trap & SMM_IO_TRAP_VALID))
+ continue;
+ /* Make sure it was a write (bit0==0) */
+ if (smm_io_trap & SMM_IO_TRAP_RW)
+ continue;
+ /* Check for APMC IO port */
+ if (pm_acpi_smi_cmd_port() != get_io_address(smm_io_trap))
+ continue;
+ /* Check AL against the requested command */
+ reg_al = state->rax;
+ if (reg_al == cmd)
+ return state;
+ }
+ return NULL;
+}
+
+static void southbridge_smi_gsmi(void)
+{
+ u8 sub_command;
+ amd64_smm_state_save_area_t *io_smi;
+ u32 reg_ebx;
+
+ io_smi = find_save_state(APM_CNT_ELOG_GSMI);
+ if (!io_smi)
+ return;
+ /* Command and return value in EAX */
+ sub_command = (io_smi->rax >> 8) & 0xff;
+
+ /* Parameter buffer in EBX */
+ reg_ebx = io_smi->rbx;
+
+ /* drivers/elog/gsmi.c */
+ io_smi->rax = gsmi_exec(sub_command, &reg_ebx);
+}
+
+static void sb_apmc_smi_handler(void)
+{
+ const uint8_t cmd = inb(pm_acpi_smi_cmd_port());
+
+ switch (cmd) {
+ case APM_CNT_ACPI_ENABLE:
+ acpi_enable_sci();
+ break;
+ case APM_CNT_ACPI_DISABLE:
+ acpi_disable_sci();
+ break;
+ case APM_CNT_ELOG_GSMI:
+ if (CONFIG(ELOG_GSMI))
+ southbridge_smi_gsmi();
+ break;
+ }
+
+ mainboard_smi_apmc(cmd);
+}
+
+static void disable_all_smi_status(void)
+{
+ smi_write32(SMI_SCI_STATUS, smi_read32(SMI_SCI_STATUS));
+ smi_write32(SMI_EVENT_STATUS, smi_read32(SMI_EVENT_STATUS));
+ smi_write32(SMI_REG_SMISTS0, smi_read32(SMI_REG_SMISTS0));
+ smi_write32(SMI_REG_SMISTS1, smi_read32(SMI_REG_SMISTS1));
+ smi_write32(SMI_REG_SMISTS2, smi_read32(SMI_REG_SMISTS2));
+ smi_write32(SMI_REG_SMISTS3, smi_read32(SMI_REG_SMISTS3));
+ smi_write32(SMI_REG_SMISTS4, smi_read32(SMI_REG_SMISTS4));
+}
+
+static void sb_slp_typ_handler(void)
+{
+ uint32_t pci_ctrl, reg32;
+ uint16_t pm1cnt, reg16;
+ uint8_t slp_typ, rst_ctrl;
+
+ /* Figure out SLP_TYP */
+ pm1cnt = acpi_read16(MMIO_ACPI_PM1_CNT_BLK);
+ printk(BIOS_SPEW, "SMI#: SLP = 0x%04x\n", pm1cnt);
+ slp_typ = acpi_sleep_from_pm1(pm1cnt);
+
+ /* Do any mainboard sleep handling */
+ mainboard_smi_sleep(slp_typ);
+
+ switch (slp_typ) {
+ case ACPI_S0:
+ printk(BIOS_DEBUG, "SMI#: Entering S0 (On)\n");
+ break;
+ case ACPI_S3:
+ printk(BIOS_DEBUG, "SMI#: Entering S3 (Suspend-To-RAM)\n");
+ break;
+ case ACPI_S4:
+ printk(BIOS_DEBUG, "SMI#: Entering S4 (Suspend-To-Disk)\n");
+ break;
+ case ACPI_S5:
+ printk(BIOS_DEBUG, "SMI#: Entering S5 (Soft Power off)\n");
+ break;
+ default:
+ printk(BIOS_DEBUG, "SMI#: ERROR: SLP_TYP reserved\n");
+ break;
+ }
+
+ if (slp_typ >= ACPI_S3) {
+ /* Sleep Type Elog S3, S4, and S5 entry */
+ if (CONFIG(ELOG_GSMI))
+ elog_add_event_byte(ELOG_TYPE_ACPI_ENTER, slp_typ);
+
+ wbinvd();
+
+ disable_all_smi_status();
+
+ /* Do not send SMI before AcpiPm1CntBlkx00[SlpTyp] */
+ pci_ctrl = pm_read32(PM_PCI_CTRL);
+ pci_ctrl &= ~FORCE_SLPSTATE_RETRY;
+ pci_ctrl |= FORCE_STPCLK_RETRY;
+ pm_write32(PM_PCI_CTRL, pci_ctrl);
+
+ /* Enable SlpTyp */
+ rst_ctrl = pm_read8(PM_RST_CTRL1);
+ rst_ctrl |= SLPTYPE_CONTROL_EN;
+ pm_write8(PM_RST_CTRL1, rst_ctrl);
+
+ /*
+ * Before the final command, check if there's pending wake
+ * event. Read enable first, so that reading the actual status
+ * is as close as possible to entering S3. The idea is to
+ * minimize the opportunity for a wake event to happen before
+ * actually entering S3. If there's a pending wake event, log
+ * it and continue normal path. S3 will fail and the wake event
+ * becomes a SCI.
+ */
+ if (CONFIG(ELOG_GSMI)) {
+ reg16 = acpi_read16(MMIO_ACPI_PM1_EN);
+ reg16 &= acpi_read16(MMIO_ACPI_PM1_STS);
+ if (reg16)
+ elog_add_extended_event(
+ ELOG_SLEEP_PENDING_PM1_WAKE,
+ (u32)reg16);
+
+ reg32 = acpi_read32(MMIO_ACPI_GPE0_EN);
+ reg32 &= acpi_read32(MMIO_ACPI_GPE0_STS);
+ if (reg32)
+ elog_add_extended_event(
+ ELOG_SLEEP_PENDING_GPE0_WAKE,
+ reg32);
+ } /* if (CONFIG(ELOG_GSMI)) */
+
+ /*
+ * An IO cycle is required to trigger the STPCLK/STPGNT
+ * handshake when the Pm1 write is reissued.
+ */
+ outw(pm1cnt | SLP_EN, pm_read16(PM1_CNT_BLK));
+ hlt();
+ }
+}
+
+int southbridge_io_trap_handler(int smif)
+{
+ return 0;
+}
+
+/*
+ * Table of functions supported in the SMI handler. Note that SMI source setup
+ * in southbridge.c is unrelated to this list.
+ */
+static const struct smi_sources_t smi_sources[] = {
+ { .type = SMITYPE_SMI_CMD_PORT, .handler = sb_apmc_smi_handler },
+ { .type = SMITYPE_SLP_TYP, .handler = sb_slp_typ_handler},
+};
+
+static void process_smi_sci(void)
+{
+ const uint32_t status = smi_read32(SMI_SCI_STATUS);
+
+ /* Clear events to prevent re-entering SMI if event isn't handled */
+ smi_write32(SMI_SCI_STATUS, status);
+}
+
+static void *get_source_handler(int source)
+{
+ int i;
+
+ for (i = 0 ; i < ARRAY_SIZE(smi_sources) ; i++)
+ if (smi_sources[i].type == source)
+ return smi_sources[i].handler;
+
+ return NULL;
+}
+
+static void process_smi_sources(uint32_t reg)
+{
+ const uint32_t status = smi_read32(reg);
+ int bit_zero = 32 / sizeof(uint32_t) * (reg - SMI_REG_SMISTS0);
+ void (*source_handler)(void);
+ int i;
+
+ for (i = 0 ; i < 32 ; i++) {
+ if (status & (1 << i)) {
+ source_handler = get_source_handler(i + bit_zero);
+ if (source_handler)
+ source_handler();
+ }
+ }
+
+ if (reg == SMI_REG_SMISTS0)
+ if (status & GEVENT_MASK)
+ /* Gevent[23:0] are assumed to be mainboard-specific */
+ mainboard_smi_gpi(status & GEVENT_MASK);
+
+ /* Clear all events in this register */
+ smi_write32(reg, status);
+}
+
+void southbridge_smi_handler(void)
+{
+ const uint16_t smi_src = smi_read16(SMI_REG_POINTER);
+
+ if (smi_src & SMI_STATUS_SRC_SCI)
+ process_smi_sci();
+ if (smi_src & SMI_STATUS_SRC_0)
+ process_smi_sources(SMI_REG_SMISTS0);
+ if (smi_src & SMI_STATUS_SRC_1)
+ process_smi_sources(SMI_REG_SMISTS1);
+ if (smi_src & SMI_STATUS_SRC_2)
+ process_smi_sources(SMI_REG_SMISTS2);
+ if (smi_src & SMI_STATUS_SRC_3)
+ process_smi_sources(SMI_REG_SMISTS3);
+ if (smi_src & SMI_STATUS_SRC_4)
+ process_smi_sources(SMI_REG_SMISTS4);
+}
+
+void southbridge_smi_set_eos(void)
+{
+ uint32_t reg = smi_read32(SMI_REG_SMITRIG0);
+ reg |= SMITRG0_EOS;
+ smi_write32(SMI_REG_SMITRIG0, reg);
+}
diff --git a/src/soc/amd/picasso/southbridge.c b/src/soc/amd/picasso/southbridge.c
new file mode 100644
index 0000000000..45408ead02
--- /dev/null
+++ b/src/soc/amd/picasso/southbridge.c
@@ -0,0 +1,675 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010-2017 Advanced Micro Devices, 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.
+ */
+
+#include <console/console.h>
+#include <device/mmio.h>
+#include <bootstate.h>
+#include <cpu/x86/smm.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <cbmem.h>
+#include <amdblocks/amd_pci_util.h>
+#include <amdblocks/agesawrapper.h>
+#include <amdblocks/reset.h>
+#include <amdblocks/acpimmio.h>
+#include <amdblocks/lpc.h>
+#include <amdblocks/acpi.h>
+#include <soc/southbridge.h>
+#include <soc/smbus.h>
+#include <soc/smi.h>
+#include <soc/amd_pci_int_defs.h>
+#include <delay.h>
+#include <soc/pci_devs.h>
+#include <agesa_headers.h>
+#include <soc/nvs.h>
+#include <types.h>
+
+/*
+ * Table of devices that need their AOAC registers enabled and waited
+ * upon (usually about .55 milliseconds). Instead of individual delays
+ * waiting for each device to become available, a single delay will be
+ * executed.
+ */
+const static struct stoneyridge_aoac aoac_devs[] = {
+ { (FCH_AOAC_D3_CONTROL_UART0 + CONFIG_UART_FOR_CONSOLE * 2),
+ (FCH_AOAC_D3_STATE_UART0 + CONFIG_UART_FOR_CONSOLE * 2) },
+ { FCH_AOAC_D3_CONTROL_AMBA, FCH_AOAC_D3_STATE_AMBA },
+ { FCH_AOAC_D3_CONTROL_I2C0, FCH_AOAC_D3_STATE_I2C0 },
+ { FCH_AOAC_D3_CONTROL_I2C1, FCH_AOAC_D3_STATE_I2C1 },
+ { FCH_AOAC_D3_CONTROL_I2C2, FCH_AOAC_D3_STATE_I2C2 },
+ { FCH_AOAC_D3_CONTROL_I2C3, FCH_AOAC_D3_STATE_I2C3 }
+};
+
+static int is_sata_config(void)
+{
+ return !((SataNativeIde == CONFIG_STONEYRIDGE_SATA_MODE)
+ || (SataLegacyIde == CONFIG_STONEYRIDGE_SATA_MODE));
+}
+
+static inline int sb_sata_enable(void)
+{
+ /* True if IDE or AHCI. */
+ return (SataNativeIde == CONFIG_STONEYRIDGE_SATA_MODE) ||
+ (SataAhci == CONFIG_STONEYRIDGE_SATA_MODE);
+}
+
+static inline int sb_ide_enable(void)
+{
+ /* True if IDE or LEGACY IDE. */
+ return (SataNativeIde == CONFIG_STONEYRIDGE_SATA_MODE) ||
+ (SataLegacyIde == CONFIG_STONEYRIDGE_SATA_MODE);
+}
+
+void SetFchResetParams(FCH_RESET_INTERFACE *params)
+{
+ const struct device *dev = pcidev_path_on_root(SATA_DEVFN);
+ params->Xhci0Enable = CONFIG(STONEYRIDGE_XHCI_ENABLE);
+ if (dev && dev->enabled) {
+ params->SataEnable = sb_sata_enable();
+ params->IdeEnable = sb_ide_enable();
+ } else {
+ params->SataEnable = FALSE;
+ params->IdeEnable = FALSE;
+ }
+}
+
+void SetFchEnvParams(FCH_INTERFACE *params)
+{
+ const struct device *dev = pcidev_path_on_root(SATA_DEVFN);
+ params->AzaliaController = AzEnable;
+ params->SataClass = CONFIG_STONEYRIDGE_SATA_MODE;
+ if (dev && dev->enabled) {
+ params->SataEnable = is_sata_config();
+ params->IdeEnable = !params->SataEnable;
+ params->SataIdeMode = (CONFIG_STONEYRIDGE_SATA_MODE ==
+ SataLegacyIde);
+ } else {
+ params->SataEnable = FALSE;
+ params->IdeEnable = FALSE;
+ params->SataIdeMode = FALSE;
+ }
+}
+
+void SetFchMidParams(FCH_INTERFACE *params)
+{
+ SetFchEnvParams(params);
+}
+
+/*
+ * Table of APIC register index and associated IRQ name. Using IDX_XXX_NAME
+ * provides a visible association with the index, therefore helping
+ * maintainability of table. If a new index/name is defined in
+ * amd_pci_int_defs.h, just add the pair at the end of this table.
+ * Order is not important.
+ */
+const static struct irq_idx_name irq_association[] = {
+ { PIRQ_A, "INTA#" },
+ { PIRQ_B, "INTB#" },
+ { PIRQ_C, "INTC#" },
+ { PIRQ_D, "INTD#" },
+ { PIRQ_E, "INTE#" },
+ { PIRQ_F, "INTF#" },
+ { PIRQ_G, "INTG#" },
+ { PIRQ_H, "INTH#" },
+ { PIRQ_MISC, "Misc" },
+ { PIRQ_MISC0, "Misc0" },
+ { PIRQ_MISC1, "Misc1" },
+ { PIRQ_MISC2, "Misc2" },
+ { PIRQ_SIRQA, "Ser IRQ INTA" },
+ { PIRQ_SIRQB, "Ser IRQ INTB" },
+ { PIRQ_SIRQC, "Ser IRQ INTC" },
+ { PIRQ_SIRQD, "Ser IRQ INTD" },
+ { PIRQ_SCI, "SCI" },
+ { PIRQ_SMBUS, "SMBUS" },
+ { PIRQ_ASF, "ASF" },
+ { PIRQ_HDA, "HDA" },
+ { PIRQ_FC, "FC" },
+ { PIRQ_PMON, "PerMon" },
+ { PIRQ_SD, "SD" },
+ { PIRQ_SDIO, "SDIOt" },
+ { PIRQ_EHCI, "EHCI" },
+ { PIRQ_XHCI, "XHCI" },
+ { PIRQ_SATA, "SATA" },
+ { PIRQ_GPIO, "GPIO" },
+ { PIRQ_I2C0, "I2C0" },
+ { PIRQ_I2C1, "I2C1" },
+ { PIRQ_I2C2, "I2C2" },
+ { PIRQ_I2C3, "I2C3" },
+ { PIRQ_UART0, "UART0" },
+ { PIRQ_UART1, "UART1" },
+};
+
+const struct irq_idx_name *sb_get_apic_reg_association(size_t *size)
+{
+ *size = ARRAY_SIZE(irq_association);
+ return irq_association;
+}
+
+static void power_on_aoac_device(int aoac_device_control_register)
+{
+ uint8_t byte;
+
+ /* Power on the UART and AMBA devices */
+ byte = aoac_read8(aoac_device_control_register);
+ byte |= FCH_AOAC_PWR_ON_DEV;
+ aoac_write8(aoac_device_control_register, byte);
+}
+
+static bool is_aoac_device_enabled(int aoac_device_status_register)
+{
+ uint8_t byte;
+
+ byte = aoac_read8(aoac_device_status_register);
+ byte &= (FCH_AOAC_PWR_RST_STATE | FCH_AOAC_RST_CLK_OK_STATE);
+ if (byte == (FCH_AOAC_PWR_RST_STATE | FCH_AOAC_RST_CLK_OK_STATE))
+ return true;
+ else
+ return false;
+}
+
+void enable_aoac_devices(void)
+{
+ bool status;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(aoac_devs); i++)
+ power_on_aoac_device(aoac_devs[i].enable);
+
+ /* Wait for AOAC devices to indicate power and clock OK */
+ do {
+ udelay(100);
+ status = true;
+ for (i = 0; i < ARRAY_SIZE(aoac_devs); i++)
+ status &= is_aoac_device_enabled(aoac_devs[i].status);
+ } while (!status);
+}
+
+static void sb_enable_lpc(void)
+{
+ u8 byte;
+
+ /* Enable LPC controller */
+ byte = pm_io_read8(PM_LPC_GATING);
+ byte |= PM_LPC_ENABLE;
+ pm_io_write8(PM_LPC_GATING, byte);
+}
+
+static void sb_lpc_decode(void)
+{
+ u32 tmp = 0;
+
+ /* Enable I/O decode to LPC bus */
+ tmp = DECODE_ENABLE_PARALLEL_PORT0 | DECODE_ENABLE_PARALLEL_PORT2
+ | DECODE_ENABLE_PARALLEL_PORT4 | DECODE_ENABLE_SERIAL_PORT0
+ | DECODE_ENABLE_SERIAL_PORT1 | DECODE_ENABLE_SERIAL_PORT2
+ | DECODE_ENABLE_SERIAL_PORT3 | DECODE_ENABLE_SERIAL_PORT4
+ | DECODE_ENABLE_SERIAL_PORT5 | DECODE_ENABLE_SERIAL_PORT6
+ | DECODE_ENABLE_SERIAL_PORT7 | DECODE_ENABLE_AUDIO_PORT0
+ | DECODE_ENABLE_AUDIO_PORT1 | DECODE_ENABLE_AUDIO_PORT2
+ | DECODE_ENABLE_AUDIO_PORT3 | DECODE_ENABLE_MSS_PORT2
+ | DECODE_ENABLE_MSS_PORT3 | DECODE_ENABLE_FDC_PORT0
+ | DECODE_ENABLE_FDC_PORT1 | DECODE_ENABLE_GAME_PORT
+ | DECODE_ENABLE_KBC_PORT | DECODE_ENABLE_ACPIUC_PORT
+ | DECODE_ENABLE_ADLIB_PORT;
+
+ /* Decode SIOs at 2E/2F and 4E/4F */
+ if (CONFIG(STONEYRIDGE_LEGACY_FREE))
+ tmp |= DECODE_ALTERNATE_SIO_ENABLE | DECODE_SIO_ENABLE;
+
+ lpc_enable_decode(tmp);
+}
+
+static void sb_enable_cf9_io(void)
+{
+ uint32_t reg = pm_read32(PM_DECODE_EN);
+
+ pm_write32(PM_DECODE_EN, reg | CF9_IO_EN);
+}
+
+static void sb_enable_legacy_io(void)
+{
+ uint32_t reg = pm_read32(PM_DECODE_EN);
+
+ pm_write32(PM_DECODE_EN, reg | LEGACY_IO_EN);
+}
+
+void sb_clk_output_48Mhz(u32 osc)
+{
+ u32 ctrl;
+
+ /*
+ * Clear the disable for OSCOUT1 (signal typically named XnnM_25M_48M)
+ * or OSCOUT2 (USBCLK/25M_48M_OSC). The frequency defaults to 48MHz.
+ */
+ ctrl = misc_read32(MISC_CLK_CNTL1);
+
+ switch (osc) {
+ case 1:
+ ctrl &= ~OSCOUT1_CLK_OUTPUT_ENB;
+ break;
+ case 2:
+ ctrl &= ~OSCOUT2_CLK_OUTPUT_ENB;
+ break;
+ default:
+ return; /* do nothing if invalid */
+ }
+ misc_write32(MISC_CLK_CNTL1, ctrl);
+}
+
+static uintptr_t sb_init_spi_base(void)
+{
+ uintptr_t base;
+
+ /* Make sure the base address is predictable */
+ base = lpc_get_spibase();
+
+ if (base)
+ return base;
+
+ lpc_set_spibase(SPI_BASE_ADDRESS, SPI_ROM_ENABLE);
+ return SPI_BASE_ADDRESS;
+}
+
+void sb_set_spi100(u16 norm, u16 fast, u16 alt, u16 tpm)
+{
+ uintptr_t base = sb_init_spi_base();
+ write16((void *)(base + SPI100_SPEED_CONFIG),
+ (norm << SPI_NORM_SPEED_NEW_SH) |
+ (fast << SPI_FAST_SPEED_NEW_SH) |
+ (alt << SPI_ALT_SPEED_NEW_SH) |
+ (tpm << SPI_TPM_SPEED_NEW_SH));
+ write16((void *)(base + SPI100_ENABLE), SPI_USE_SPI100);
+}
+
+void sb_disable_4dw_burst(void)
+{
+ uintptr_t base = sb_init_spi_base();
+ write16((void *)(base + SPI100_HOST_PREF_CONFIG),
+ read16((void *)(base + SPI100_HOST_PREF_CONFIG))
+ & ~SPI_RD4DW_EN_HOST);
+}
+
+void sb_read_mode(u32 mode)
+{
+ uintptr_t base = sb_init_spi_base();
+ write32((void *)(base + SPI_CNTRL0),
+ (read32((void *)(base + SPI_CNTRL0))
+ & ~SPI_READ_MODE_MASK) | mode);
+}
+
+static void setup_spread_spectrum(int *reboot)
+{
+ uint16_t rstcfg = pm_read16(PWR_RESET_CFG);
+
+ rstcfg &= ~TOGGLE_ALL_PWR_GOOD;
+ pm_write16(PWR_RESET_CFG, rstcfg);
+
+ uint32_t cntl1 = misc_read32(MISC_CLK_CNTL1);
+
+ if (cntl1 & CG1PLL_FBDIV_TEST) {
+ printk(BIOS_DEBUG, "Spread spectrum is ready\n");
+ misc_write32(MISC_CGPLL_CONFIG1,
+ misc_read32(MISC_CGPLL_CONFIG1) |
+ CG1PLL_SPREAD_SPECTRUM_ENABLE);
+
+ return;
+ }
+
+ printk(BIOS_DEBUG, "Setting up spread spectrum\n");
+
+ uint32_t cfg6 = misc_read32(MISC_CGPLL_CONFIG6);
+ cfg6 &= ~CG1PLL_LF_MODE_MASK;
+ cfg6 |= (0x0f8 << CG1PLL_LF_MODE_SHIFT) & CG1PLL_LF_MODE_MASK;
+ misc_write32(MISC_CGPLL_CONFIG6, cfg6);
+
+ uint32_t cfg3 = misc_read32(MISC_CGPLL_CONFIG3);
+ cfg3 &= ~CG1PLL_REFDIV_MASK;
+ cfg3 |= (0x003 << CG1PLL_REFDIV_SHIFT) & CG1PLL_REFDIV_MASK;
+ cfg3 &= ~CG1PLL_FBDIV_MASK;
+ cfg3 |= (0x04b << CG1PLL_FBDIV_SHIFT) & CG1PLL_FBDIV_MASK;
+ misc_write32(MISC_CGPLL_CONFIG3, cfg3);
+
+ uint32_t cfg5 = misc_read32(MISC_CGPLL_CONFIG5);
+ cfg5 &= ~SS_AMOUNT_NFRAC_SLIP_MASK;
+ cfg5 |= (0x2 << SS_AMOUNT_NFRAC_SLIP_SHIFT) & SS_AMOUNT_NFRAC_SLIP_MASK;
+ misc_write32(MISC_CGPLL_CONFIG5, cfg5);
+
+ uint32_t cfg4 = misc_read32(MISC_CGPLL_CONFIG4);
+ cfg4 &= ~SS_AMOUNT_DSFRAC_MASK;
+ cfg4 |= (0xd000 << SS_AMOUNT_DSFRAC_SHIFT) & SS_AMOUNT_DSFRAC_MASK;
+ cfg4 &= ~SS_STEP_SIZE_DSFRAC_MASK;
+ cfg4 |= (0x02d5 << SS_STEP_SIZE_DSFRAC_SHIFT)
+ & SS_STEP_SIZE_DSFRAC_MASK;
+ misc_write32(MISC_CGPLL_CONFIG4, cfg4);
+
+ rstcfg |= TOGGLE_ALL_PWR_GOOD;
+ pm_write16(PWR_RESET_CFG, rstcfg);
+
+ cntl1 |= CG1PLL_FBDIV_TEST;
+ misc_write32(MISC_CLK_CNTL1, cntl1);
+
+ *reboot = 1;
+}
+
+static void setup_misc(int *reboot)
+{
+ /* Undocumented register */
+ uint32_t reg = misc_read32(0x50);
+ if (!(reg & BIT(16))) {
+ reg |= BIT(16);
+
+ misc_write32(0x50, reg);
+ *reboot = 1;
+ }
+}
+
+static void fch_smbus_init(void)
+{
+ pm_write8(SMB_ASF_IO_BASE, SMB_BASE_ADDR >> 8);
+ smbus_write8(SMBTIMING, SMB_SPEED_400KHZ);
+ /* Clear all SMBUS status bits */
+ smbus_write8(SMBHSTSTAT, SMBHST_STAT_CLEAR);
+ smbus_write8(SMBSLVSTAT, SMBSLV_STAT_CLEAR);
+ asf_write8(SMBHSTSTAT, SMBHST_STAT_CLEAR);
+ asf_write8(SMBSLVSTAT, SMBSLV_STAT_CLEAR);
+}
+
+/* Before console init */
+void bootblock_fch_early_init(void)
+{
+ int reboot = 0;
+
+ lpc_enable_rom();
+ sb_enable_lpc();
+ lpc_enable_port80();
+ sb_lpc_decode();
+ lpc_enable_spi_prefetch();
+ sb_init_spi_base();
+ sb_disable_4dw_burst(); /* Must be disabled on CZ(ST) */
+ enable_acpimmio_decode();
+ fch_smbus_init();
+ sb_enable_cf9_io();
+ setup_spread_spectrum(&reboot);
+ setup_misc(&reboot);
+
+ if (reboot)
+ warm_reset();
+
+ sb_enable_legacy_io();
+ enable_aoac_devices();
+}
+
+static void print_num_status_bits(int num_bits, uint32_t status,
+ const char *const bit_names[])
+{
+ int i;
+
+ if (!status)
+ return;
+
+ for (i = num_bits - 1; i >= 0; i--) {
+ if (status & (1 << i)) {
+ if (bit_names[i])
+ printk(BIOS_DEBUG, "%s ", bit_names[i]);
+ else
+ printk(BIOS_DEBUG, "BIT%d ", i);
+ }
+ }
+}
+
+static void sb_print_pmxc0_status(void)
+{
+ /* PMxC0 S5/Reset Status shows the source of previous reset. */
+ uint32_t pmxc0_status = pm_read32(PM_RST_STATUS);
+
+ static const char *const pmxc0_status_bits[32] = {
+ [0] = "ThermalTrip",
+ [1] = "FourSecondPwrBtn",
+ [2] = "Shutdown",
+ [3] = "ThermalTripFromTemp",
+ [4] = "RemotePowerDownFromASF",
+ [5] = "ShutDownFan0",
+ [16] = "UserRst",
+ [17] = "SoftPciRst",
+ [18] = "DoInit",
+ [19] = "DoReset",
+ [20] = "DoFullReset",
+ [21] = "SleepReset",
+ [22] = "KbReset",
+ [23] = "LtReset",
+ [24] = "FailBootRst",
+ [25] = "WatchdogIssueReset",
+ [26] = "RemoteResetFromASF",
+ [27] = "SyncFlood",
+ [28] = "HangReset",
+ [29] = "EcWatchdogRst",
+ };
+
+ printk(BIOS_DEBUG, "PMxC0 STATUS: 0x%x ", pmxc0_status);
+ print_num_status_bits(ARRAY_SIZE(pmxc0_status_bits), pmxc0_status,
+ pmxc0_status_bits);
+ printk(BIOS_DEBUG, "\n");
+}
+
+/* After console init */
+void bootblock_fch_init(void)
+{
+ sb_print_pmxc0_status();
+}
+
+void sb_enable(struct device *dev)
+{
+ printk(BIOS_DEBUG, "%s\n", __func__);
+}
+
+static void sb_init_acpi_ports(void)
+{
+ u32 reg;
+
+ /* We use some of these ports in SMM regardless of whether or not
+ * ACPI tables are generated. Enable these ports indiscriminately.
+ */
+
+ pm_write16(PM_EVT_BLK, ACPI_PM_EVT_BLK);
+ pm_write16(PM1_CNT_BLK, ACPI_PM1_CNT_BLK);
+ pm_write16(PM_TMR_BLK, ACPI_PM_TMR_BLK);
+ pm_write16(PM_GPE0_BLK, ACPI_GPE0_BLK);
+ /* CpuControl is in \_PR.CP00, 6 bytes */
+ pm_write16(PM_CPU_CTRL, ACPI_CPU_CONTROL);
+
+ if (CONFIG(HAVE_SMI_HANDLER)) {
+ /* APMC - SMI Command Port */
+ pm_write16(PM_ACPI_SMI_CMD, APM_CNT);
+ configure_smi(SMITYPE_SMI_CMD_PORT, SMI_MODE_SMI);
+
+ /* SMI on SlpTyp requires sending SMI before completion
+ * response of the I/O write. The BKDG also specifies
+ * clearing ForceStpClkRetry for SMI trapping.
+ */
+ reg = pm_read32(PM_PCI_CTRL);
+ reg |= FORCE_SLPSTATE_RETRY;
+ reg &= ~FORCE_STPCLK_RETRY;
+ pm_write32(PM_PCI_CTRL, reg);
+
+ /* Disable SlpTyp feature */
+ reg = pm_read8(PM_RST_CTRL1);
+ reg &= ~SLPTYPE_CONTROL_EN;
+ pm_write8(PM_RST_CTRL1, reg);
+
+ configure_smi(SMITYPE_SLP_TYP, SMI_MODE_SMI);
+ } else {
+ pm_write16(PM_ACPI_SMI_CMD, 0);
+ }
+
+ /* Decode ACPI registers and enable standard features */
+ pm_write8(PM_ACPI_CONF, PM_ACPI_DECODE_STD |
+ PM_ACPI_GLOBAL_EN |
+ PM_ACPI_RTC_EN_EN |
+ PM_ACPI_TIMER_EN_EN);
+}
+
+static int get_index_bit(uint32_t value, uint16_t limit)
+{
+ uint16_t i;
+ uint32_t t;
+
+ if (limit >= TOTAL_BITS(uint32_t))
+ return -1;
+
+ /* get a mask of valid bits. Ex limit = 3, set bits 0-2 */
+ t = (1 << limit) - 1;
+ if ((value & t) == 0)
+ return -1;
+ t = 1;
+ for (i = 0; i < limit; i++) {
+ if (value & t)
+ break;
+ t <<= 1;
+ }
+ return i;
+}
+
+static void set_nvs_sws(void *unused)
+{
+ struct soc_power_reg *sws;
+ struct global_nvs_t *gnvs;
+ int index;
+
+ sws = cbmem_find(CBMEM_ID_POWER_STATE);
+ if (sws == NULL)
+ return;
+ gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
+ if (gnvs == NULL)
+ return;
+
+ index = get_index_bit(sws->pm1_sts & sws->pm1_en, PM1_LIMIT);
+ if (index < 0)
+ gnvs->pm1i = ~0ULL;
+ else
+ gnvs->pm1i = index;
+
+ index = get_index_bit(sws->gpe0_sts & sws->gpe0_en, GPE0_LIMIT);
+ if (index < 0)
+ gnvs->gpei = ~0ULL;
+ else
+ gnvs->gpei = index;
+}
+
+BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, set_nvs_sws, NULL);
+
+void southbridge_init(void *chip_info)
+{
+ sb_init_acpi_ports();
+ acpi_clear_pm1_status();
+}
+
+static void set_sb_final_nvs(void)
+{
+ uintptr_t amdfw_rom;
+ uintptr_t xhci_fw;
+ uintptr_t fwaddr;
+ size_t fwsize;
+ const struct device *sd, *sata;
+
+ struct global_nvs_t *gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
+ if (gnvs == NULL)
+ return;
+
+ gnvs->aoac.ic0e = is_aoac_device_enabled(FCH_AOAC_D3_STATE_I2C0);
+ gnvs->aoac.ic1e = is_aoac_device_enabled(FCH_AOAC_D3_STATE_I2C1);
+ gnvs->aoac.ic2e = is_aoac_device_enabled(FCH_AOAC_D3_STATE_I2C2);
+ gnvs->aoac.ic3e = is_aoac_device_enabled(FCH_AOAC_D3_STATE_I2C3);
+ gnvs->aoac.ut0e = is_aoac_device_enabled(FCH_AOAC_D3_STATE_UART0);
+ gnvs->aoac.ut1e = is_aoac_device_enabled(FCH_AOAC_D3_STATE_UART1);
+ gnvs->aoac.ehce = is_aoac_device_enabled(FCH_AOAC_D3_STATE_USB2);
+ gnvs->aoac.xhce = is_aoac_device_enabled(FCH_AOAC_D3_STATE_USB3);
+ /* Rely on these being in sync with devicetree */
+ sd = pcidev_path_on_root(SD_DEVFN);
+ gnvs->aoac.sd_e = sd && sd->enabled ? 1 : 0;
+ sata = pcidev_path_on_root(SATA_DEVFN);
+ gnvs->aoac.st_e = sata && sata->enabled ? 1 : 0;
+ gnvs->aoac.espi = 1;
+
+ amdfw_rom = 0x20000 - (0x80000 << CONFIG_AMD_FWM_POSITION_INDEX);
+ xhci_fw = read32((void *)(amdfw_rom + XHCI_FW_SIG_OFFSET));
+
+ fwaddr = 2 + read16((void *)(xhci_fw + XHCI_FW_ADDR_OFFSET
+ + XHCI_FW_BOOTRAM_SIZE));
+ fwsize = read16((void *)(xhci_fw + XHCI_FW_SIZE_OFFSET
+ + XHCI_FW_BOOTRAM_SIZE));
+ gnvs->fw00 = 0;
+ gnvs->fw01 = ((32 * KiB) << 16) + 0;
+ gnvs->fw02 = fwaddr + XHCI_FW_BOOTRAM_SIZE;
+ gnvs->fw03 = fwsize << 16;
+
+ gnvs->eh10 = pci_read_config32(SOC_EHCI1_DEV, PCI_BASE_ADDRESS_0)
+ & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
+}
+
+void southbridge_final(void *chip_info)
+{
+ uint8_t restored_power = PM_S5_AT_POWER_RECOVERY;
+
+ if (CONFIG(MAINBOARD_POWER_RESTORE))
+ restored_power = PM_RESTORE_S0_IF_PREV_S0;
+ pm_write8(PM_RTC_SHADOW, restored_power);
+
+ set_sb_final_nvs();
+}
+
+/*
+ * Update the PCI devices with a valid IRQ number
+ * that is set in the mainboard PCI_IRQ structures.
+ */
+static void set_pci_irqs(void *unused)
+{
+ /* Write PCI_INTR regs 0xC00/0xC01 */
+ write_pci_int_table();
+
+ /* Write IRQs for all devicetree enabled devices */
+ write_pci_cfg_irqs();
+}
+
+/*
+ * Hook this function into the PCI state machine
+ * on entry into BS_DEV_ENABLE.
+ */
+BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_ENTRY, set_pci_irqs, NULL);
+
+void save_uma_size(uint32_t size)
+{
+ biosram_write32(BIOSRAM_UMA_SIZE, size);
+}
+
+void save_uma_base(uint64_t base)
+{
+ biosram_write32(BIOSRAM_UMA_BASE, (uint32_t) base);
+ biosram_write32(BIOSRAM_UMA_BASE + 4, (uint32_t) (base >> 32));
+}
+
+uint32_t get_uma_size(void)
+{
+ return biosram_read32(BIOSRAM_UMA_SIZE);
+}
+
+uint64_t get_uma_base(void)
+{
+ uint64_t base;
+ base = biosram_read32(BIOSRAM_UMA_BASE);
+ base |= ((uint64_t)(biosram_read32(BIOSRAM_UMA_BASE + 4)) << 32);
+ return base;
+}
diff --git a/src/soc/amd/picasso/spi.c b/src/soc/amd/picasso/spi.c
new file mode 100644
index 0000000000..8abfa160f4
--- /dev/null
+++ b/src/soc/amd/picasso/spi.c
@@ -0,0 +1,189 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, 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.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <device/mmio.h>
+#include <lib.h>
+#include <timer.h>
+#include <console/console.h>
+#include <commonlib/helpers.h>
+#include <spi_flash.h>
+#include <spi-generic.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ops.h>
+#include <soc/southbridge.h>
+#include <amdblocks/lpc.h>
+#include <soc/pci_devs.h>
+
+#define SPI_DEBUG_DRIVER CONFIG(DEBUG_SPI_FLASH)
+
+static uintptr_t spibar;
+
+static void set_spibar(uintptr_t base)
+{
+ spibar = base;
+}
+
+static inline uint8_t spi_read8(uint8_t reg)
+{
+ return read8((void *)(spibar + reg));
+}
+
+static inline uint32_t spi_read32(uint8_t reg)
+{
+ return read32((void *)(spibar + reg));
+}
+
+static inline void spi_write8(uint8_t reg, uint8_t val)
+{
+ write8((void *)(spibar + reg), val);
+}
+
+static inline void spi_write32(uint8_t reg, uint32_t val)
+{
+ write32((void *)(spibar + reg), val);
+}
+
+static void dump_state(const char *str)
+{
+ if (!SPI_DEBUG_DRIVER)
+ return;
+
+ printk(BIOS_DEBUG, "SPI: %s\n", str);
+ printk(BIOS_DEBUG, "Cntrl0: %x\n", spi_read32(SPI_CNTRL0));
+ printk(BIOS_DEBUG, "Status: %x\n", spi_read32(SPI_STATUS));
+ printk(BIOS_DEBUG, "TxByteCount: %x\n", spi_read8(SPI_TX_BYTE_COUNT));
+ printk(BIOS_DEBUG, "RxByteCount: %x\n", spi_read8(SPI_RX_BYTE_COUNT));
+ printk(BIOS_DEBUG, "CmdCode: %x\n", spi_read8(SPI_CMD_CODE));
+ hexdump((void *)(spibar + SPI_FIFO), SPI_FIFO_DEPTH);
+}
+
+static int wait_for_ready(void)
+{
+ const uint32_t timeout_ms = 500;
+ struct stopwatch sw;
+
+ stopwatch_init_msecs_expire(&sw, timeout_ms);
+
+ do {
+ if (!(spi_read32(SPI_STATUS) & SPI_BUSY))
+ return 0;
+ } while (!stopwatch_expired(&sw));
+
+ return -1;
+}
+
+static int execute_command(void)
+{
+ dump_state("Before Execute");
+
+ spi_write8(SPI_CMD_TRIGGER, SPI_CMD_TRIGGER_EXECUTE);
+
+ if (wait_for_ready())
+ printk(BIOS_DEBUG,
+ "FCH SPI Error: Timeout executing command\n");
+
+ dump_state("Transaction finished");
+
+ return 0;
+}
+
+void spi_init(void)
+{
+ set_spibar(lpc_get_spibase());
+}
+
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
+ size_t bytesout, void *din, size_t bytesin)
+{
+ size_t count;
+ uint8_t cmd;
+ uint8_t *bufin = din;
+ const uint8_t *bufout = dout;
+
+ if (SPI_DEBUG_DRIVER)
+ printk(BIOS_DEBUG, "%s(%zx, %zx)\n", __func__, bytesout,
+ bytesin);
+
+ /* First byte is cmd which cannot be sent through FIFO */
+ cmd = bufout[0];
+ bufout++;
+ bytesout--;
+
+ /*
+ * 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 (bytesout + bytesin > SPI_FIFO_DEPTH) {
+ printk(BIOS_DEBUG, "FCH SPI: Too much to write. Does your SPI"
+ " chip driver use spi_crop_chunk()?\n");
+ return -1;
+ }
+
+ if (wait_for_ready())
+ return -1;
+
+ spi_write8(SPI_CMD_CODE, cmd);
+ spi_write8(SPI_TX_BYTE_COUNT, bytesout);
+ spi_write8(SPI_RX_BYTE_COUNT, bytesin);
+
+ for (count = 0; count < bytesout; count++)
+ spi_write8(SPI_FIFO + count, bufout[count]);
+
+ if (execute_command())
+ return -1;
+
+ for (count = 0; count < bytesin; count++)
+ bufin[count] = spi_read8(SPI_FIFO + count + bytesout);
+
+ return 0;
+}
+
+int chipset_volatile_group_begin(const struct spi_flash *flash)
+{
+ return 0;
+}
+
+int chipset_volatile_group_end(const struct spi_flash *flash)
+{
+ return 0;
+}
+
+static int xfer_vectors(const struct spi_slave *slave,
+ struct spi_op vectors[], size_t count)
+{
+ return spi_flash_vector_helper(slave, vectors, count, spi_ctrlr_xfer);
+}
+
+static const struct spi_ctrlr spi_ctrlr = {
+ .xfer_vector = xfer_vectors,
+ .max_xfer_size = SPI_FIFO_DEPTH,
+ .flags = SPI_CNTRLR_DEDUCT_CMD_LEN | SPI_CNTRLR_DEDUCT_OPCODE_LEN,
+};
+
+const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {
+ {
+ .ctrlr = &spi_ctrlr,
+ .bus_start = 0,
+ .bus_end = 0,
+ },
+};
+
+const size_t spi_ctrlr_bus_map_count = ARRAY_SIZE(spi_ctrlr_bus_map);
diff --git a/src/soc/amd/picasso/tsc_freq.c b/src/soc/amd/picasso/tsc_freq.c
new file mode 100644
index 0000000000..29121b955e
--- /dev/null
+++ b/src/soc/amd/picasso/tsc_freq.c
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * Copyright (C) 2017 Advanced Micro Devices
+ *
+ * This program is free software; 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.
+ */
+
+#include <cpu/x86/msr.h>
+#include <cpu/amd/msr.h>
+#include <cpu/x86/tsc.h>
+#include <console/console.h>
+#include <soc/pci_devs.h>
+#include <device/pci_ops.h>
+
+unsigned long tsc_freq_mhz(void)
+{
+ msr_t msr;
+ uint8_t cpufid;
+ uint8_t cpudid;
+ uint8_t boost_states;
+
+ /*
+ * See the Family 15h Models 70h-7Fh BKDG (PID 55072) definition for
+ * MSR0000_0010. The TSC increments at the P0 frequency. According
+ * to the "Software P-state Numbering" section, P0 is the highest
+ * non-boosted state. freq = 100MHz * (CpuFid + 10h) / (2^(CpuDid)).
+ */
+ boost_states = (pci_read_config32(SOC_PM_DEV, CORE_PERF_BOOST_CTRL)
+ >> 2) & 0x7;
+
+ msr = rdmsr(PSTATE_0_MSR + boost_states);
+ if (!(msr.hi & 0x80000000))
+ die("Unknown error: cannot determine P-state 0\n");
+
+ cpufid = (msr.lo & 0x3f);
+ cpudid = (msr.lo & 0x1c0) >> 6;
+
+ return (100 * (cpufid + 0x10)) / (0x01 << cpudid);
+}
diff --git a/src/soc/amd/picasso/uart.c b/src/soc/amd/picasso/uart.c
new file mode 100644
index 0000000000..d5d30061bf
--- /dev/null
+++ b/src/soc/amd/picasso/uart.c
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Advanced Micro Devices, 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.
+ */
+
+#include <console/uart.h>
+#include <soc/southbridge.h>
+
+uintptr_t uart_platform_base(int idx)
+{
+ if (CONFIG_UART_FOR_CONSOLE < 0 || CONFIG_UART_FOR_CONSOLE > 1)
+ return 0;
+
+ return (uintptr_t)(APU_UART0_BASE + 0x2000 * (idx & 1));
+}
+
+unsigned int uart_platform_refclk(void)
+{
+ return 48000000;
+}
diff --git a/src/soc/amd/picasso/usb.c b/src/soc/amd/picasso/usb.c
new file mode 100644
index 0000000000..00f82375e8
--- /dev/null
+++ b/src/soc/amd/picasso/usb.c
@@ -0,0 +1,85 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010 Advanced Micro Devices, 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.
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <device/pci_ehci.h>
+#include <soc/acpi.h>
+#include <soc/pci_devs.h>
+#include <soc/southbridge.h>
+#include <amdblocks/acpimmio.h>
+
+static void set_usb_over_current(struct device *dev)
+{
+ uint16_t map = USB_OC_DISABLE_ALL;
+
+ if (dev->path.pci.devfn == XHCI_DEVFN) {
+ if (mainboard_get_xhci_oc_map(&map) == 0) {
+ xhci_pm_write32(XHCI_PM_INDIRECT_INDEX,
+ XHCI_OVER_CURRENT_CONTROL);
+ xhci_pm_write16(XHCI_PM_INDIRECT_DATA, map);
+ }
+ }
+
+ if (dev->path.pci.devfn == EHCI1_DEVFN) {
+ if (mainboard_get_ehci_oc_map(&map) == 0)
+ pci_write_config16(dev, EHCI_OVER_CURRENT_CONTROL, map);
+ }
+}
+
+int __weak mainboard_get_xhci_oc_map(uint16_t *map)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+ return -1;
+}
+
+int __weak mainboard_get_ehci_oc_map(uint16_t *map)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+ return -1;
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = pci_dev_set_subsystem,
+};
+
+static struct device_operations usb_ops = {
+ .read_resources = pci_ehci_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = set_usb_over_current,
+ .scan_bus = scan_usb_bus,
+ .acpi_name = soc_acpi_name,
+ .ops_pci = &lops_pci,
+};
+
+static const unsigned short pci_device_ids[] = {
+ PCI_DEVICE_ID_AMD_SB900_USB_18_0,
+ PCI_DEVICE_ID_AMD_SB900_USB_18_2,
+ PCI_DEVICE_ID_AMD_SB900_USB_20_5,
+ PCI_DEVICE_ID_AMD_CZ_USB_0,
+ PCI_DEVICE_ID_AMD_CZ_USB_1,
+ PCI_DEVICE_ID_AMD_CZ_USB3_0,
+ 0
+};
+
+static const struct pci_driver usb_0_driver __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_AMD,
+ .devices = pci_device_ids,
+};