diff options
author | Martin Roth <martinroth@chromium.org> | 2019-04-22 14:55:16 -0600 |
---|---|---|
committer | Martin Roth <martinroth@google.com> | 2019-07-02 14:11:11 +0000 |
commit | 5c354b9979c7e7ad9af668bad0e1b6a5c3003d26 (patch) | |
tree | c597ef067e0d6eb65c2ba7e4b5e754f49e65572c /src/soc | |
parent | 76378b3c01b52f4d4184284d3d07bf63fef2ca17 (diff) |
soc/amd/picasso: Create picasso as a copy of stoneyridge
So that everyone can see what's being updated from stoney, we're
starting with a direct copy of the stoney directory. There are
arguments both for and against doing it this way, but I believe
This the most transparent way. We've moved much of the duplicated
stoney code into the soc/amd/common directory and will continue
that work as it becomes obvious that we have unchanged code between
the SOCs.
Makefile.inc has been renamed as makefile.inc so that it won't
build in jenkins until the directory is updated.
Other than that change, this is an exact copy of the stoneyridge
SOC directory which will be updated in the follow-on commits in
the patch train.
TEST=None
BUG=b:130804851
Signed-off-by: Martin Roth <martinroth@chromium.org>
Change-Id: I6809bd1eea304f76dd9000c079b3ed09f94dbd3b
Reviewed-on: https://review.coreboot.org/c/coreboot/+/32407
Reviewed-by: Richard Spiegel <richard.spiegel@silverbackltd.com>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
Reviewed-by: HAOUAS Elyes <ehaouas@noos.fr>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/soc')
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, ®_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, +}; |