diff options
Diffstat (limited to 'src')
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, +}; |