diff options
author | Martin Roth <martin.roth@amd.corp-partner.google.com> | 2022-10-06 15:57:21 -0600 |
---|---|---|
committer | Martin Roth <martin.roth@amd.corp-partner.google.com> | 2022-10-10 21:48:30 +0000 |
commit | 1a3de8e5bcc5c83934fa2a690e125b843e8b01ab (patch) | |
tree | 0df3332114bde60848c018a9b5de245a9568ba4a | |
parent | 134908381f2b25063558f2ce1414fa70243c9c55 (diff) |
soc/amd/morgana: Add initial commit for new SoC
This is an initial framework for the Morgana SoC.
TODOs have been added to the files for both customization and
commonization.
Signed-off-by: Martin Roth <martin.roth@amd.corp-partner.google.com>
Change-Id: If92e129db10d41595e1dc18a7c1dfe99d57790cc
Reviewed-on: https://review.coreboot.org/c/coreboot/+/68195
Reviewed-by: Fred Reitberger <reitbergerfred@gmail.com>
Reviewed-by: Marshall Dawson <marshalldawson3rd@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
59 files changed, 5728 insertions, 0 deletions
diff --git a/src/soc/amd/morgana/Kconfig b/src/soc/amd/morgana/Kconfig new file mode 100644 index 0000000000..8c7d87c4d2 --- /dev/null +++ b/src/soc/amd/morgana/Kconfig @@ -0,0 +1,516 @@ +# SPDX-License-Identifier: GPL-2.0-only + +# TODO: Evaluate what can be moved to a common directory +# TODO: Update for Morgana + +config SOC_AMD_MORGANA + bool + help + AMD Morgana support + +if SOC_AMD_MORGANA + +config SOC_SPECIFIC_OPTIONS + def_bool y + select ACPI_SOC_NVS + select ARCH_BOOTBLOCK_X86_32 + select ARCH_VERSTAGE_X86_32 if !VBOOT_STARTS_BEFORE_BOOTBLOCK + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 + select ARCH_X86 + select BOOT_DEVICE_SUPPORTS_WRITES if BOOT_DEVICE_SPI_FLASH + select DRIVERS_USB_ACPI + select DRIVERS_USB_PCI_XHCI + select FSP_COMPRESS_FSP_M_LZMA if !ASYNC_FILE_LOADING + select FSP_COMPRESS_FSP_M_LZ4 if ASYNC_FILE_LOADING + select FSP_COMPRESS_FSP_S_LZ4 + select GENERIC_GPIO_LIB + select HAVE_ACPI_TABLES + select HAVE_CF9_RESET + select HAVE_EM100_SUPPORT + select HAVE_FSP_GOP + select HAVE_SMI_HANDLER + select IDT_IN_EVERY_STAGE + select PARALLEL_MP_AP_WORK + select PLATFORM_USES_FSP2_0 + select PROVIDES_ROM_SHARING + select PSP_SUPPORTS_EFS2_RELATIVE_ADDR if VBOOT_STARTS_BEFORE_BOOTBLOCK + select PSP_VERSTAGE_CCP_DMA if VBOOT_STARTS_BEFORE_BOOTBLOCK + select RESET_VECTOR_IN_RAM + select RTC + select SOC_AMD_COMMON + select SOC_AMD_COMMON_BLOCK_ACP_GEN2 + select SOC_AMD_COMMON_BLOCK_ACPI + select SOC_AMD_COMMON_BLOCK_ACPIMMIO + select SOC_AMD_COMMON_BLOCK_ACPI_ALIB + select SOC_AMD_COMMON_BLOCK_ACPI_CPPC + select SOC_AMD_COMMON_BLOCK_ACPI_GPIO + select SOC_AMD_COMMON_BLOCK_ACPI_IVRS + select SOC_AMD_COMMON_BLOCK_AOAC + select SOC_AMD_COMMON_BLOCK_APOB + select SOC_AMD_COMMON_BLOCK_APOB_HASH + select SOC_AMD_COMMON_BLOCK_BANKED_GPIOS + select SOC_AMD_COMMON_BLOCK_DATA_FABRIC + select SOC_AMD_COMMON_BLOCK_ESPI_EXTENDED_DECODE_RANGES + select SOC_AMD_COMMON_BLOCK_GRAPHICS + select SOC_AMD_COMMON_BLOCK_HAS_ESPI + select SOC_AMD_COMMON_BLOCK_HAS_ESPI_ALERT_ENABLE + select SOC_AMD_COMMON_BLOCK_I2C + select SOC_AMD_COMMON_BLOCK_I23C_PAD_CTRL + select SOC_AMD_COMMON_BLOCK_IOMMU + select SOC_AMD_COMMON_BLOCK_LPC + select SOC_AMD_COMMON_BLOCK_MCAX + select SOC_AMD_COMMON_BLOCK_NONCAR + select SOC_AMD_COMMON_BLOCK_PCI + select SOC_AMD_COMMON_BLOCK_PCI_MMCONF + select SOC_AMD_COMMON_BLOCK_PCIE_GPP_DRIVER + select SOC_AMD_COMMON_BLOCK_PM + select SOC_AMD_COMMON_BLOCK_PM_CHIPSET_STATE_SAVE + select SOC_AMD_COMMON_BLOCK_PSP_GEN2 + select SOC_AMD_COMMON_BLOCK_SMBUS + select SOC_AMD_COMMON_BLOCK_SMI + select SOC_AMD_COMMON_BLOCK_SMM + select SOC_AMD_COMMON_BLOCK_SMU + select SOC_AMD_COMMON_BLOCK_SPI + select SOC_AMD_COMMON_BLOCK_TSC_FAM17H_19H + select SOC_AMD_COMMON_BLOCK_UART + select SOC_AMD_COMMON_BLOCK_UCODE + select SOC_AMD_COMMON_FSP_CCX_CPPC_HOB + select SOC_AMD_COMMON_FSP_DMI_TABLES + select SOC_AMD_COMMON_FSP_PCI + select SSE2 + select UDK_2017_BINDING + select USE_FSP_NOTIFY_PHASE_POST_PCI_ENUM + select USE_FSP_NOTIFY_PHASE_READY_TO_BOOT + select USE_FSP_NOTIFY_PHASE_END_OF_FIRMWARE + select VBOOT_DEFINE_WIDEVINE_COUNTERS if VBOOT_STARTS_BEFORE_BOOTBLOCK + select X86_AMD_FIXED_MTRRS + select X86_INIT_NEED_1_SIPI + +config ARCH_ALL_STAGES_X86 + default n + +config CHIPSET_DEVICETREE + string + default "soc/amd/morgana/chipset.cb" + +config EARLY_RESERVED_DRAM_BASE + hex + default 0x2000000 + help + This variable defines the base address of the DRAM which is reserved + for usage by coreboot in early stages (i.e. before ramstage is up). + This memory gets reserved in BIOS tables to ensure that the OS does + not use it, thus preventing corruption of OS memory in case of S3 + resume. + +config EARLYRAM_BSP_STACK_SIZE + hex + default 0x1000 + +config PSP_APOB_DRAM_ADDRESS + hex + default 0x2001000 + help + Location in DRAM where the PSP will copy the AGESA PSP Output + Block. + +config PSP_APOB_DRAM_SIZE + hex + default 0x1E000 + +config PSP_SHAREDMEM_BASE + hex + default 0x201F000 if VBOOT + default 0x0 + help + This variable defines the base address in DRAM memory where PSP copies + the vboot workbuf. This is used in the linker script to have a static + allocation for the buffer as well as for adding relevant entries in + the BIOS directory table for the PSP. + +config PSP_SHAREDMEM_SIZE + hex + default 0x8000 if VBOOT + default 0x0 + help + Sets the maximum size for the PSP to pass the vboot workbuf and + any logs or timestamps back to coreboot. This will be copied + into main memory by the PSP and will be available when the x86 is + started. The workbuf's base depends on the address of the reset + vector. + +config PRE_X86_CBMEM_CONSOLE_SIZE + hex + default 0x1600 + help + Size of the CBMEM console used in PSP verstage. + +config PRERAM_CBMEM_CONSOLE_SIZE + hex + default 0x1600 + help + Increase this value if preram cbmem console is getting truncated + +config CBFS_MCACHE_SIZE + hex + default 0x2000 if VBOOT_STARTS_BEFORE_BOOTBLOCK + +config C_ENV_BOOTBLOCK_SIZE + hex + default 0x10000 + help + Sets the size of the bootblock stage that should be loaded in DRAM. + This variable controls the DRAM allocation size in linker script + for bootblock stage. + +config ROMSTAGE_ADDR + hex + default 0x2040000 + help + Sets the address in DRAM where romstage should be loaded. + +config ROMSTAGE_SIZE + hex + default 0x80000 + help + Sets the size of DRAM allocation for romstage in linker script. + +config FSP_M_ADDR + hex + default 0x20C0000 + help + Sets the address in DRAM where FSP-M should be loaded. cbfstool + performs relocation of FSP-M to this address. + +config FSP_M_SIZE + hex + default 0xC0000 + help + Sets the size of DRAM allocation for FSP-M in linker script. + +config FSP_TEMP_RAM_SIZE + hex + default 0x40000 + help + The amount of coreboot-allocated heap and stack usage by the FSP. + +config VERSTAGE_ADDR + hex + depends on VBOOT_SEPARATE_VERSTAGE + default 0x2180000 + help + Sets the address in DRAM where verstage should be loaded if running + as a separate stage on x86. + +config VERSTAGE_SIZE + hex + depends on VBOOT_SEPARATE_VERSTAGE + default 0x80000 + help + Sets the size of DRAM allocation for verstage in linker script if + running as a separate stage on x86. + +config ASYNC_FILE_LOADING + bool "Loads files from SPI asynchronously" + select COOP_MULTITASKING + select SOC_AMD_COMMON_BLOCK_LPC_SPI_DMA + select CBFS_PRELOAD + help + When enabled, the platform will use the LPC SPI DMA controller to + asynchronously load contents from the SPI ROM. This will improve + boot time because the CPUs can be performing useful work while the + SPI contents are being preloaded. + +config CBFS_CACHE_SIZE + hex + default 0x40000 if CBFS_PRELOAD + +config RO_REGION_ONLY + string + depends on VBOOT_SLOTS_RW_AB || VBOOT_SLOTS_RW_A + default "apu/amdfw" + +config ECAM_MMCONF_BASE_ADDRESS + default 0xF8000000 + +config ECAM_MMCONF_BUS_NUMBER + default 64 + +config MAX_CPUS + int + default 8 if SOC_AMD_MORGANA + default 16 + help + Maximum number of threads the platform can have. + +config CONSOLE_UART_BASE_ADDRESS + depends on CONSOLE_SERIAL && AMD_SOC_CONSOLE_UART + hex + default 0xfedc9000 if UART_FOR_CONSOLE = 0 + default 0xfedca000 if UART_FOR_CONSOLE = 1 + default 0xfedce000 if UART_FOR_CONSOLE = 2 + default 0xfedcf000 if UART_FOR_CONSOLE = 3 + default 0xfedd1000 if UART_FOR_CONSOLE = 4 + +config SMM_TSEG_SIZE + hex + default 0x800000 if HAVE_SMI_HANDLER + default 0x0 + +config SMM_RESERVED_SIZE + hex + default 0x180000 + +config SMM_MODULE_STACK_SIZE + hex + default 0x800 + +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. + +config ACPI_BERT_SIZE + hex + default 0x4000 if ACPI_BERT + default 0x0 + help + Specify the amount of DRAM reserved for gathering the data used to + generate the ACPI table. + +config DRIVERS_I2C_DESIGNWARE_CLOCK_MHZ + int + default 150 + +config DISABLE_SPI_FLASH_ROM_SHARING + def_bool n + help + Instruct the chipset to not honor the EGPIO67_SPI_ROM_REQ pin + which indicates a board level ROM transaction request. This + removes arbitration with board and assumes the chipset controls + the SPI flash bus entirely. + +config DISABLE_KEYBOARD_RESET_PIN + bool + help + Instruct the SoC to not use the state of GPIO_129 as keyboard reset + signal. When this pin is used as GPIO and the keyboard reset + functionality isn't disabled, configuring it as an output and driving + it as 0 will cause a reset. + +config ACPI_SSDT_PSD_INDEPENDENT + bool "Allow core p-state independent transitions" + default y + help + AMD recommends the ACPI _PSD object to be configured to cause + cores to transition between p-states independently. A vendor may + choose to generate _PSD object to allow cores to transition together. + +menu "PSP Configuration Options" + +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 AMDFW_CONFIG_FILE + string "AMD PSP Firmware config file" + default "src/soc/amd/morgana/fw.cfg" + help + Specify the path/location of AMD PSP Firmware config file. + +config PSP_DISABLE_POSTCODES + bool "Disable PSP post codes" + help + Disables the output of port80 post codes from PSP. + +config PSP_POSTCODES_ON_ESPI + bool "Use eSPI bus for PSP post codes" + default y + depends on !PSP_DISABLE_POSTCODES + help + Select to send PSP port80 post codes on eSPI bus. + If not selected, PSP port80 codes will be sent on LPC bus. + +config PSP_LOAD_MP2_FW + bool + default n + help + Include the MP2 firmwares and configuration into the PSP build. + + If unsure, answer 'n' + +config PSP_UNLOCK_SECURE_DEBUG + bool "Unlock secure debug" + default y + help + Select this item to enable secure debug options in PSP. + +config HAVE_PSP_WHITELIST_FILE + bool "Include a debug whitelist file in PSP build" + default n + help + Support secured unlock prior to reset using a whitelisted + serial number. This feature requires a signed whitelist image + and bootloader from AMD. + + If unsure, answer 'n' + +config PSP_WHITELIST_FILE + string "Debug whitelist file path" + depends on HAVE_PSP_WHITELIST_FILE + default "site-local/3rdparty/amd_blobs/morgana/PSP/wtl-mrg.sbin" + +config HAVE_SPL_FILE + bool "Have a mainboard specific SPL table file" + default n + help + Have a mainboard specific Security Patch Level (SPL) table file. SPL file + is required to support PSP FW anti-rollback and needs to be created by AMD. + The default SPL file applies to all boards that use the concerned SoC and + is dropped under 3rdparty/blobs. The mainboard specific SPL file override + can be applied through SPL_TABLE_FILE config. + + If unsure, answer 'n' + +config SPL_TABLE_FILE + string "SPL table file" + depends on HAVE_SPL_FILE + default "3rdparty/blobs/mainboard/\$(CONFIG_MAINBOARD_DIR)/TypeId0x55_SplTableBl_MRG.sbin" + +config HAVE_SPL_RW_AB_FILE + bool "Have a separate mainboard-specific SPL file in RW A/B partitions" + default n + depends on HAVE_SPL_FILE + depends on VBOOT_SLOTS_RW_AB + help + Have separate mainboard-specific Security Patch Level (SPL) table + file for the RW A/B FMAP partitions. See the help text of + HAVE_SPL_FILE for a more detailed description. + +config SPL_RW_AB_TABLE_FILE + string "Separate SPL table file for RW A/B partitions" + depends on HAVE_SPL_RW_AB_FILE + default "3rdparty/blobs/mainboard/\$(CONFIG_MAINBOARD_DIR)/TypeId0x55_SplTableBl_MRG.sbin" + +config PSP_SOFTFUSE_BITS + string "PSP Soft Fuse bits to enable" + default "34 28 6" + help + Space separated list of Soft Fuse bits to enable. + Bit 0: Enable secure debug (Set by PSP_UNLOCK_SECURE_DEBUG) + Bit 7: Disable PSP postcodes on Renoir and newer chips only + (Set by PSP_DISABLE_PORT80) + Bit 15: PSP debug output destination: + 0=SoC MMIO UART, 1=IO port 0x3F8 + Bit 29: Disable MP2 firmware loading (Set by PSP_LOAD_MP2_FW) + + See #55758 (NDA) for additional bit definitions. + +config PSP_VERSTAGE_FILE + string "Specify the PSP_verstage file path" + depends on VBOOT_STARTS_BEFORE_BOOTBLOCK + default "\$(obj)/psp_verstage.bin" + help + Add psp_verstage file to the build & PSP Directory Table + +config PSP_VERSTAGE_SIGNING_TOKEN + string "Specify the PSP_verstage Signature Token file path" + depends on VBOOT_STARTS_BEFORE_BOOTBLOCK + default "" + help + Add psp_verstage signature token to the build & PSP Directory Table + +endmenu + +config VBOOT + select VBOOT_VBNV_CMOS + select VBOOT_VBNV_CMOS_BACKUP_TO_FLASH + +config VBOOT_STARTS_BEFORE_BOOTBLOCK + def_bool n + depends on VBOOT + select ARCH_VERSTAGE_ARMV7 + help + Runs verstage on the PSP. Only available on + certain ChromeOS branded parts from AMD. + +config VBOOT_HASH_BLOCK_SIZE + hex + default 0x9000 + depends on VBOOT_STARTS_BEFORE_BOOTBLOCK + help + Because the bulk of the time in psp_verstage to hash the RO cbfs is + spent in the overhead of doing svc calls, increasing the hash block + size significantly cuts the verstage hashing time as seen below. + + 4k takes 180ms + 16k takes 44ms + 32k takes 33.7ms + 36k takes 32.5ms + There's actually still room for an even bigger stack, but we've + reached a point of diminishing returns. + +config CMOS_RECOVERY_BYTE + hex + default 0x51 + depends on VBOOT_STARTS_BEFORE_BOOTBLOCK + help + If the workbuf is not passed from the PSP to coreboot, set the + recovery flag and reboot. The PSP will read this byte, mark the + recovery request in VBNV, and reset the system into recovery mode. + + This is the byte before the default first byte used by VBNV + (0x26 + 0x0E - 1) + +if VBOOT_SLOTS_RW_AB && VBOOT_STARTS_BEFORE_BOOTBLOCK + +config RWA_REGION_ONLY + string + default "apu/amdfw_a" + help + Add a space-delimited list of filenames that should only be in the + RW-A section. + +config RWB_REGION_ONLY + string + default "apu/amdfw_b" + help + Add a space-delimited list of filenames that should only be in the + RW-B section. + +endif # VBOOT_SLOTS_RW_AB && VBOOT_STARTS_BEFORE_BOOTBLOCK + +endif # SOC_AMD_REMBRANDT_BASE diff --git a/src/soc/amd/morgana/Makefile.inc b/src/soc/amd/morgana/Makefile.inc new file mode 100644 index 0000000000..6c80d237ba --- /dev/null +++ b/src/soc/amd/morgana/Makefile.inc @@ -0,0 +1,330 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# TODO: Move as much as possible to common +# TODO: Update for Morgana + +ifeq ($(CONFIG_SOC_AMD_MORGANA),y) + +subdirs-$(CONFIG_VBOOT_STARTS_BEFORE_BOOTBLOCK) += psp_verstage + +# Beware that all-y also adds the compilation unit to verstage on PSP +all-y += config.c +all-y += aoac.c + +bootblock-y += bootblock.c +bootblock-y += early_fch.c +bootblock-y += espi_util.c +bootblock-y += gpio.c +bootblock-y += i2c.c +bootblock-y += reset.c +bootblock-y += uart.c + +verstage-y += i2c.c +verstage-y += espi_util.c +verstage_x86-y += gpio.c +verstage_x86-y += reset.c +verstage_x86-y += uart.c + +romstage-y += fsp_m_params.c +romstage-y += gpio.c +romstage-y += i2c.c +romstage-y += reset.c +romstage-y += romstage.c +romstage-y += uart.c + +ramstage-y += acpi.c +ramstage-y += agesa_acpi.c +ramstage-y += chip.c +ramstage-y += cpu.c +ramstage-y += data_fabric.c +ramstage-y += fch.c +ramstage-y += fsp_s_params.c +ramstage-y += gpio.c +ramstage-y += i2c.c +ramstage-y += mca.c +ramstage-y += preload.c +ramstage-y += reset.c +ramstage-y += root_complex.c +ramstage-y += uart.c +ramstage-y += xhci.c + +smm-y += gpio.c +smm-y += smihandler.c +smm-y += smu.c +smm-$(CONFIG_DEBUG_SMI) += uart.c + +CPPFLAGS_common += -I$(src)/soc/amd/morgana/include +CPPFLAGS_common += -I$(src)/soc/amd/morgana/acpi +CPPFLAGS_common += -I$(src)/vendorcode/amd/fsp/morgana +CPPFLAGS_common += -I$(src)/vendorcode/amd/fsp/common + +MAINBOARD_BLOBS_DIR:=$(top)/3rdparty/blobs/mainboard/$(MAINBOARDDIR) + +# ROMSIG Normally At ROMBASE + 0x20000 +# Overridden by CONFIG_AMD_FWM_POSITION_INDEX +# +-----------+---------------+----------------+------------+ +# |0x55AA55AA | | | | +# +-----------+---------------+----------------+------------+ +# | | PSPDIR ADDR | BIOSDIR ADDR | +# +-----------+---------------+----------------+ + +$(if $(CONFIG_AMD_FWM_POSITION_INDEX), ,\ + $(error Invalid AMD firmware position index. Check if the board sets a valid ROM size)) + +MORGANA_FWM_POSITION=$(call int-add, \ + $(call int-subtract, 0xffffffff \ + $(call int-shift-left, \ + 0x80000 $(CONFIG_AMD_FWM_POSITION_INDEX))) 0x20000 1) + +# 0x40 accounts for the cbfs_file struct + filename + metadata structs, aligned to 64 bytes +# Building the cbfs image will fail if the offset isn't large enough +AMD_FW_AB_POSITION := 0x40 + +MORGANA_FW_A_POSITION=$(call int-add, \ + $(shell awk '$$2 == "FMAP_SECTION_FW_MAIN_A_START" {print $$3}' $(obj)/fmap_config.h) \ + $(AMD_FW_AB_POSITION)) + +MORGANA_FW_B_POSITION=$(call int-add, \ + $(shell awk '$$2 == "FMAP_SECTION_FW_MAIN_B_START" {print $$3}' $(obj)/fmap_config.h) \ + $(AMD_FW_AB_POSITION)) +# +# PSP Directory Table items +# +# Certain ordering requirements apply, however these are ensured by amdfwtool. +# For more information see "AMD Platform Security Processor BIOS Architecture +# Design Guide for AMD Family 17h Processors" (PID #55758, NDA only). +# + +ifeq ($(CONFIG_PSP_DISABLE_POSTCODES),y) +PSP_SOFTFUSE_BITS += 7 +endif + +ifeq ($(CONFIG_PSP_UNLOCK_SECURE_DEBUG),y) +# Enable secure debug unlock +PSP_SOFTFUSE_BITS += 0 +OPT_TOKEN_UNLOCK="--token-unlock" +endif + +ifeq ($(CONFIG_PSP_LOAD_MP2_FW),y) +OPT_PSP_LOAD_MP2_FW="--load-mp2-fw" +else +# Disable MP2 firmware loading +PSP_SOFTFUSE_BITS += 29 +endif + +# Use additional Soft Fuse bits specified in Kconfig +PSP_SOFTFUSE_BITS += $(call strip_quotes, $(CONFIG_PSP_SOFTFUSE_BITS)) + +# type = 0x3a +ifeq ($(CONFIG_HAVE_PSP_WHITELIST_FILE),y) +PSP_WHITELIST_FILE=$(CONFIG_PSP_WHITELIST_FILE) +endif + +# type = 0x55 +ifeq ($(CONFIG_HAVE_SPL_FILE),y) +SPL_TABLE_FILE=$(CONFIG_SPL_TABLE_FILE) +ifeq ($(CONFIG_HAVE_SPL_RW_AB_FILE),y) +SPL_RW_AB_TABLE_FILE=$(CONFIG_SPL_RW_AB_TABLE_FILE) +else +SPL_RW_AB_TABLE_FILE=$(CONFIG_SPL_TABLE_FILE) +endif +endif + +# +# BIOS Directory Table items - proper ordering is managed by amdfwtool +# + +# type = 0x60 +PSP_APCB_FILES=$(APCB_SOURCES) $(APCB_SOURCES_RECOVERY) + +# type = 0x61 +PSP_APOB_BASE=$(CONFIG_PSP_APOB_DRAM_ADDRESS) + +# type = 0x62 +PSP_BIOSBIN_FILE=$(obj)/amd_biospsp.img +PSP_ELF_FILE=$(objcbfs)/bootblock.elf +PSP_BIOSBIN_SIZE=$(shell $(READELF_bootblock) -l $(PSP_ELF_FILE) | grep LOAD | awk '{print $$5}') +PSP_BIOSBIN_DEST=$(shell $(READELF_bootblock) -l $(PSP_ELF_FILE) | grep LOAD | awk '{print $$3}') + +# type = 0x63 - construct APOB NV base/size from flash map +# The flashmap section used for this is expected to be named RW_MRC_CACHE +APOB_NV_SIZE=$(shell awk '$$2 == "FMAP_SECTION_RW_MRC_CACHE_SIZE" {print $$3}' $(obj)/fmap_config.h) +APOB_NV_BASE=$(shell awk '$$2 == "FMAP_SECTION_RW_MRC_CACHE_START" {print $$3}' $(obj)/fmap_config.h) + +ifeq ($(CONFIG_VBOOT_STARTS_BEFORE_BOOTBLOCK),y) +# type = 0x6B - PSP Shared memory location +ifneq ($(CONFIG_PSP_SHAREDMEM_SIZE),0x0) +PSP_SHAREDMEM_SIZE=$(CONFIG_PSP_SHAREDMEM_SIZE) +PSP_SHAREDMEM_BASE=$(shell awk '$$3 == "_psp_sharedmem_dram" {printf "0x" $$1}' $(objcbfs)/bootblock.map) +endif + +# type = 0x52 - PSP Bootloader Userspace Application (verstage) +PSP_VERSTAGE_FILE=$(call strip_quotes,$(CONFIG_PSP_VERSTAGE_FILE)) +PSP_VERSTAGE_SIG_FILE=$(call strip_quotes,$(CONFIG_PSP_VERSTAGE_SIGNING_TOKEN)) +endif # CONFIG_VBOOT_STARTS_BEFORE_BOOTBLOCK + +ifeq ($(CONFIG_SEPARATE_SIGNED_PSPFW),y) +SIGNED_AMDFW_A_POSITION=$(call int-subtract, \ + $(shell awk '$$2 == "FMAP_SECTION_SIGNED_AMDFW_A_START" {print $$3}' $(obj)/fmap_config.h) \ + $(shell awk '$$2 == "FMAP_SECTION_FLASH_START" {print $$3}' $(obj)/fmap_config.h)) +SIGNED_AMDFW_B_POSITION=$(call int-subtract, \ + $(shell awk '$$2 == "FMAP_SECTION_SIGNED_AMDFW_B_START" {print $$3}' $(obj)/fmap_config.h) \ + $(shell awk '$$2 == "FMAP_SECTION_FLASH_START" {print $$3}' $(obj)/fmap_config.h)) +SIGNED_AMDFW_A_FILE=$(obj)/amdfw_a.rom.signed +SIGNED_AMDFW_B_FILE=$(obj)/amdfw_b.rom.signed +endif # CONFIG_SEPARATE_SIGNED_PSPFW + +# Helper function to return a value with given bit set +# Soft Fuse type = 0xb - See #55758 (NDA) for bit definitions. +set-bit=$(call int-shift-left, 1 $(call _toint,$1)) +PSP_SOFTFUSE=$(shell A=$(call int-add, \ + $(foreach bit,$(PSP_SOFTFUSE_BITS),$(call set-bit,$(bit)))); printf "0x%x" $$A) + +# +# Build the arguments to amdfwtool (order is unimportant). Missing file names +# result in empty OPT_ variables, i.e. the argument is not passed to amdfwtool. +# + +add_opt_prefix=$(if $(call strip_quotes, $(1)), $(2) $(call strip_quotes, $(1)), ) + +OPT_VERSTAGE_FILE=$(call add_opt_prefix, $(PSP_VERSTAGE_FILE), --verstage) +OPT_VERSTAGE_SIG_FILE=$(call add_opt_prefix, $(PSP_VERSTAGE_SIG_FILE), --verstage_sig) + +OPT_PSP_APCB_FILES= $(if $(APCB_SOURCES), --instance 0 --apcb $(APCB_SOURCES)) \ + $(if $(APCB_SOURCES_RECOVERY), --instance 10 --apcb $(APCB_SOURCES_RECOVERY)) \ + $(if $(APCB_SOURCES_68), --instance 18 --apcb $(APCB_SOURCES_68)) + +OPT_APOB_ADDR=$(call add_opt_prefix, $(PSP_APOB_BASE), --apob-base) +OPT_PSP_BIOSBIN_FILE=$(call add_opt_prefix, $(PSP_BIOSBIN_FILE), --bios-bin) +OPT_PSP_BIOSBIN_DEST=$(call add_opt_prefix, $(PSP_BIOSBIN_DEST), --bios-bin-dest) +OPT_PSP_BIOSBIN_SIZE=$(call add_opt_prefix, $(PSP_BIOSBIN_SIZE), --bios-uncomp-size) + +OPT_PSP_SHAREDMEM_BASE=$(call add_opt_prefix, $(PSP_SHAREDMEM_BASE), --sharedmem) +OPT_PSP_SHAREDMEM_SIZE=$(call add_opt_prefix, $(PSP_SHAREDMEM_SIZE), --sharedmem-size) +OPT_APOB_NV_SIZE=$(call add_opt_prefix, $(APOB_NV_SIZE), --apob-nv-size) +OPT_APOB_NV_BASE=$(call add_opt_prefix, $(APOB_NV_BASE),--apob-nv-base) +OPT_EFS_SPI_READ_MODE=$(call add_opt_prefix, $(CONFIG_EFS_SPI_READ_MODE), --spi-read-mode) +OPT_EFS_SPI_SPEED=$(call add_opt_prefix, $(CONFIG_EFS_SPI_SPEED), --spi-speed) +OPT_EFS_SPI_MICRON_FLAG=$(call add_opt_prefix, $(CONFIG_EFS_SPI_MICRON_FLAG), --spi-micron-flag) + +OPT_SIGNED_AMDFW_A_POSITION=$(call add_opt_prefix, $(SIGNED_AMDFW_A_POSITION), --signed-addr) +OPT_SIGNED_AMDFW_A_FILE=$(call add_opt_prefix, $(SIGNED_AMDFW_A_FILE), --signed-output) +OPT_SIGNED_AMDFW_B_POSITION=$(call add_opt_prefix, $(SIGNED_AMDFW_B_POSITION), --signed-addr) +OPT_SIGNED_AMDFW_B_FILE=$(call add_opt_prefix, $(SIGNED_AMDFW_B_FILE), --signed-output) + +OPT_PSP_SOFTFUSE=$(call add_opt_prefix, $(PSP_SOFTFUSE), --soft-fuse) + +OPT_WHITELIST_FILE=$(call add_opt_prefix, $(PSP_WHITELIST_FILE), --whitelist) +OPT_SPL_TABLE_FILE=$(call add_opt_prefix, $(SPL_TABLE_FILE), --spl-table) +OPT_SPL_RW_AB_TABLE_FILE=$(call add_opt_prefix, $(SPL_RW_AB_TABLE_FILE), --spl-table) + +# If vboot uses 2 RW slots, then 2 copies of PSP binaries are redundant +OPT_RECOVERY_AB_SINGLE_COPY=$(if $(CONFIG_VBOOT_SLOTS_RW_AB), --recovery-ab-single-copy) + +AMDFW_COMMON_ARGS=$(OPT_PSP_APCB_FILES) \ + $(OPT_APOB_ADDR) \ + $(OPT_PSP_BIOSBIN_FILE) \ + $(OPT_PSP_BIOSBIN_DEST) \ + $(OPT_PSP_BIOSBIN_SIZE) \ + $(OPT_PSP_SOFTFUSE) \ + $(OPT_PSP_LOAD_MP2_FW) \ + --use-pspsecureos \ + --load-s0i3 \ + --combo-capable \ + $(OPT_TOKEN_UNLOCK) \ + $(OPT_WHITELIST_FILE) \ + $(OPT_PSP_SHAREDMEM_BASE) \ + $(OPT_PSP_SHAREDMEM_SIZE) \ + $(OPT_EFS_SPI_READ_MODE) \ + $(OPT_EFS_SPI_SPEED) \ + $(OPT_EFS_SPI_MICRON_FLAG) \ + --config $(CONFIG_AMDFW_CONFIG_FILE) \ + --soc-name "Morgana" \ + --flashsize $(CONFIG_ROM_SIZE) \ + $(OPT_RECOVERY_AB_SINGLE_COPY) + +$(obj)/amdfw.rom: $(call strip_quotes, $(PSP_BIOSBIN_FILE)) \ + $(PSP_VERSTAGE_FILE) \ + $(PSP_VERSTAGE_SIG_FILE) \ + $$(PSP_APCB_FILES) \ + $(DEP_FILES) \ + $(AMDFWTOOL) \ + $(obj)/fmap_config.h \ + $(objcbfs)/bootblock.elf # this target also creates the .map file + $(if $(PSP_APCB_FILES), ,$(error APCB_SOURCES is not set)) + rm -f $@ + @printf " AMDFWTOOL $(subst $(obj)/,,$(@))\n" + $(AMDFWTOOL) \ + $(AMDFW_COMMON_ARGS) \ + $(OPT_APOB_NV_SIZE) \ + $(OPT_APOB_NV_BASE) \ + $(OPT_VERSTAGE_FILE) \ + $(OPT_VERSTAGE_SIG_FILE) \ + $(OPT_SPL_TABLE_FILE) \ + --location $(shell printf "%#x" $(MORGANA_FWM_POSITION)) \ + --output $@ + +$(PSP_BIOSBIN_FILE): $(PSP_ELF_FILE) $(AMDCOMPRESS) + rm -f $@ + @printf " AMDCOMPRS $(subst $(obj)/,,$(@))\n" + $(AMDCOMPRESS) --infile $(PSP_ELF_FILE) --outfile $@ --compress \ + --maxsize $(PSP_BIOSBIN_SIZE) + +$(obj)/amdfw_a.rom: $(obj)/amdfw.rom + rm -f $@ + @printf " AMDFWTOOL $(subst $(obj)/,,$(@))\n" + $(AMDFWTOOL) \ + $(AMDFW_COMMON_ARGS) \ + $(OPT_APOB_NV_SIZE) \ + $(OPT_APOB_NV_BASE) \ + $(OPT_SPL_RW_AB_TABLE_FILE) \ + $(OPT_SIGNED_AMDFW_A_POSITION) \ + $(OPT_SIGNED_AMDFW_A_FILE) \ + --location $(shell printf "%#x" $(MORGANA_FW_A_POSITION)) \ + --anywhere \ + --output $@ + +$(obj)/amdfw_b.rom: $(obj)/amdfw.rom + rm -f $@ + @printf " AMDFWTOOL $(subst $(obj)/,,$(@))\n" + $(AMDFWTOOL) \ + $(AMDFW_COMMON_ARGS) \ + $(OPT_APOB_NV_SIZE) \ + $(OPT_APOB_NV_BASE) \ + $(OPT_SPL_RW_AB_TABLE_FILE) \ + $(OPT_SIGNED_AMDFW_B_POSITION) \ + $(OPT_SIGNED_AMDFW_B_FILE) \ + --location $(shell printf "%#x" $(MORGANA_FW_B_POSITION)) \ + --anywhere \ + --output $@ + + +cbfs-files-y += apu/amdfw +apu/amdfw-file := $(obj)/amdfw.rom +apu/amdfw-position := $(MORGANA_FWM_POSITION) +apu/amdfw-type := raw + +ifeq ($(CONFIG_VBOOT_SLOTS_RW_AB)$(CONFIG_VBOOT_STARTS_BEFORE_BOOTBLOCK),yy) +cbfs-files-y += apu/amdfw_a +apu/amdfw_a-file := $(obj)/amdfw_a.rom +apu/amdfw_a-position := $(AMD_FW_AB_POSITION) +apu/amdfw_a-type := raw + +cbfs-files-y += apu/amdfw_b +apu/amdfw_b-file := $(obj)/amdfw_b.rom +apu/amdfw_b-position := $(AMD_FW_AB_POSITION) +apu/amdfw_b-type := raw + +ifeq ($(CONFIG_SEPARATE_SIGNED_PSPFW),y) +build_complete:: $(obj)/amdfw_a.rom $(obj)/amdfw_b.rom + @printf " Adding Signed ROM and HASH\n" + $(CBFSTOOL) $(obj)/coreboot.rom write -u -r SIGNED_AMDFW_A -i 0 -f $(obj)/amdfw_a.rom.signed + $(CBFSTOOL) $(obj)/coreboot.rom write -u -r SIGNED_AMDFW_B -i 0 -f $(obj)/amdfw_b.rom.signed + $(CBFSTOOL) $(obj)/coreboot.rom add -r FW_MAIN_A -f $(obj)/amdfw_a.rom.signed.hash \ + -n apu/amdfw_a_hash -t raw + $(CBFSTOOL) $(obj)/coreboot.rom add -r FW_MAIN_B -f $(obj)/amdfw_b.rom.signed.hash \ + -n apu/amdfw_b_hash -t raw +endif # CONFIG_SEPARATE_SIGNED_PSPFW +endif + +endif # ($(CONFIG_SOC_AMD_MORGANA),y) diff --git a/src/soc/amd/morgana/acpi.c b/src/soc/amd/morgana/acpi.c new file mode 100644 index 0000000000..f3825f0419 --- /dev/null +++ b/src/soc/amd/morgana/acpi.c @@ -0,0 +1,370 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ +/* TODO: See what can be made common */ + +/* ACPI - create the Fixed ACPI Description Tables (FADT) */ + +#include <acpi/acpi.h> +#include <acpi/acpigen.h> +#include <amdblocks/acpi.h> +#include <amdblocks/cppc.h> +#include <amdblocks/cpu.h> +#include <amdblocks/acpimmio.h> +#include <amdblocks/ioapic.h> +#include <arch/ioapic.h> +#include <arch/smp/mpspec.h> +#include <console/console.h> +#include <cpu/amd/cpuid.h> +#include <cpu/amd/msr.h> +#include <cpu/x86/smm.h> +#include <soc/acpi.h> +#include <soc/iomap.h> +#include <soc/msr.h> +#include <types.h> +#include "chip.h" + +unsigned long acpi_fill_madt(unsigned long current) +{ + /* create all subtables for processors */ + current = acpi_create_madt_lapics(current); + + current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *)current, + FCH_IOAPIC_ID, IO_APIC_ADDR, 0); + + current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *)current, + GNB_IOAPIC_ID, GNB_IO_APIC_ADDR, IO_APIC_INTERRUPTS); + + /* PIT is connected to legacy IRQ 0, but IOAPIC GSI 2 */ + current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)current, + MP_BUS_ISA, 0, 2, + MP_IRQ_TRIGGER_DEFAULT | MP_IRQ_POLARITY_DEFAULT); + /* SCI IRQ type override */ + current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)current, + MP_BUS_ISA, ACPI_SCI_IRQ, ACPI_SCI_IRQ, + MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_LOW); + current = acpi_fill_madt_irqoverride(current); + + /* create all subtables for processors */ + current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)current, + ACPI_MADT_LAPIC_NMI_ALL_PROCESSORS, + MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH, + 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_fill_fadt(acpi_fadt_t *fadt) +{ + const struct soc_amd_morgana_config *cfg = config_of_soc(); + + printk(BIOS_DEBUG, "pm_base: 0x%04x\n", ACPI_IO_BASE); + + fadt->sci_int = ACPI_SCI_IRQ; + + if (permanent_smi_handler()) { + fadt->smi_cmd = APM_CNT; + fadt->acpi_enable = APM_CNT_ACPI_ENABLE; + fadt->acpi_disable = APM_CNT_ACPI_DISABLE; + } + + fadt->pstate_cnt = 0; + + fadt->pm1a_evt_blk = ACPI_PM_EVT_BLK; + fadt->pm1a_cnt_blk = ACPI_PM1_CNT_BLK; + fadt->pm_tmr_blk = ACPI_PM_TMR_BLK; + fadt->gpe0_blk = ACPI_GPE0_BLK; + + fadt->pm1_evt_len = 4; /* 32 bits */ + fadt->pm1_cnt_len = 2; /* 16 bits */ + fadt->pm_tmr_len = 4; /* 32 bits */ + fadt->gpe0_blk_len = 8; /* 64 bits */ + + fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED; + fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED; + fadt->duty_offset = 0; /* Not supported */ + fadt->duty_width = 0; /* Not supported */ + fadt->day_alrm = RTC_DATE_ALARM; + fadt->mon_alrm = 0; + fadt->century = RTC_ALT_CENTURY; + fadt->iapc_boot_arch = cfg->common_config.fadt_boot_arch; /* legacy free default */ + fadt->flags |= ACPI_FADT_WBINVD | /* See table 5-34 ACPI 6.3 spec */ + ACPI_FADT_C1_SUPPORTED | + ACPI_FADT_S4_RTC_WAKE | + ACPI_FADT_32BIT_TIMER | + ACPI_FADT_PCI_EXPRESS_WAKE | + ACPI_FADT_PLATFORM_CLOCK | + ACPI_FADT_S4_RTC_VALID | + ACPI_FADT_REMOTE_POWER_ON; + if (cfg->s0ix_enable) + fadt->flags |= ACPI_FADT_LOW_PWR_IDLE_S0; + + fadt->flags |= cfg->common_config.fadt_flags; /* additional board-specific flags */ + + 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_pm1a_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO; + fadt->x_pm1a_cnt_blk.bit_width = 16; + fadt->x_pm1a_cnt_blk.bit_offset = 0; + fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS; + fadt->x_pm1a_cnt_blk.addrl = ACPI_PM1_CNT_BLK; + fadt->x_pm1a_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; + fadt->x_gpe0_blk.bit_offset = 0; + fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS; + fadt->x_gpe0_blk.addrl = ACPI_GPE0_BLK; + fadt->x_gpe0_blk.addrh = 0x0; +} + +static uint32_t get_pstate_core_freq(msr_t pstate_def) +{ + uint32_t core_freq, core_freq_mul, core_freq_div; + bool valid_freq_divisor; + + /* Core frequency multiplier */ + core_freq_mul = pstate_def.lo & PSTATE_DEF_LO_FREQ_MUL_MASK; + + /* Core frequency divisor ID */ + core_freq_div = + (pstate_def.lo & PSTATE_DEF_LO_FREQ_DIV_MASK) >> PSTATE_DEF_LO_FREQ_DIV_SHIFT; + + if (core_freq_div == 0) { + return 0; + } else if ((core_freq_div >= PSTATE_DEF_LO_FREQ_DIV_MIN) + && (core_freq_div <= PSTATE_DEF_LO_EIGHTH_STEP_MAX)) { + /* Allow 1/8 integer steps for this range */ + valid_freq_divisor = 1; + } else if ((core_freq_div > PSTATE_DEF_LO_EIGHTH_STEP_MAX) + && (core_freq_div <= PSTATE_DEF_LO_FREQ_DIV_MAX) && !(core_freq_div & 0x1)) { + /* Only allow 1/4 integer steps for this range */ + valid_freq_divisor = 1; + } else { + valid_freq_divisor = 0; + } + + if (valid_freq_divisor) { + /* 25 * core_freq_mul / (core_freq_div / 8) */ + core_freq = + ((PSTATE_DEF_LO_CORE_FREQ_BASE * core_freq_mul * 8) / (core_freq_div)); + } else { + printk(BIOS_WARNING, "Undefined core_freq_div %x used. Force to 1.\n", + core_freq_div); + core_freq = (PSTATE_DEF_LO_CORE_FREQ_BASE * core_freq_mul); + } + return core_freq; +} + +static uint32_t get_pstate_core_power(msr_t pstate_def) +{ + uint32_t voltage_in_uvolts, core_vid, current_value_amps, current_divisor, power_in_mw; + + /* Core voltage ID */ + core_vid = + (pstate_def.lo & PSTATE_DEF_LO_CORE_VID_MASK) >> PSTATE_DEF_LO_CORE_VID_SHIFT; + + /* Current value in amps */ + current_value_amps = + (pstate_def.lo & PSTATE_DEF_LO_CUR_VAL_MASK) >> PSTATE_DEF_LO_CUR_VAL_SHIFT; + + /* Current divisor */ + current_divisor = + (pstate_def.lo & PSTATE_DEF_LO_CUR_DIV_MASK) >> PSTATE_DEF_LO_CUR_DIV_SHIFT; + + /* Voltage */ + if (core_vid == 0x00) { + /* Voltage off for VID code 0x00 */ + voltage_in_uvolts = 0; + } else { + voltage_in_uvolts = + SERIAL_VID_BASE_MICROVOLTS + (SERIAL_VID_DECODE_MICROVOLTS * core_vid); + } + + /* Power in mW */ + power_in_mw = (voltage_in_uvolts) / 10 * current_value_amps; + + switch (current_divisor) { + case 0: + power_in_mw = power_in_mw / 100L; + break; + case 1: + power_in_mw = power_in_mw / 1000L; + break; + case 2: + power_in_mw = power_in_mw / 10000L; + break; + case 3: + /* current_divisor is set to an undefined value.*/ + printk(BIOS_WARNING, "Undefined current_divisor set for enabled P-state .\n"); + power_in_mw = 0; + break; + } + + return power_in_mw; +} + +/* + * Populate structure describing enabled p-states and return count of enabled p-states. + */ +static size_t get_pstate_info(struct acpi_sw_pstate *pstate_values, + struct acpi_xpss_sw_pstate *pstate_xpss_values) +{ + msr_t pstate_def; + size_t pstate_count, pstate; + uint32_t pstate_enable, max_pstate; + + pstate_count = 0; + max_pstate = (rdmsr(PS_LIM_REG).lo & PS_LIM_MAX_VAL_MASK) >> PS_MAX_VAL_SHFT; + + for (pstate = 0; pstate <= max_pstate; pstate++) { + pstate_def = rdmsr(PSTATE_0_MSR + pstate); + + pstate_enable = (pstate_def.hi & PSTATE_DEF_HI_ENABLE_MASK) + >> PSTATE_DEF_HI_ENABLE_SHIFT; + if (!pstate_enable) + continue; + + pstate_values[pstate_count].core_freq = get_pstate_core_freq(pstate_def); + pstate_values[pstate_count].power = get_pstate_core_power(pstate_def); + pstate_values[pstate_count].transition_latency = 0; + pstate_values[pstate_count].bus_master_latency = 0; + pstate_values[pstate_count].control_value = pstate; + pstate_values[pstate_count].status_value = pstate; + + pstate_xpss_values[pstate_count].core_freq = + (uint64_t)pstate_values[pstate_count].core_freq; + pstate_xpss_values[pstate_count].power = + (uint64_t)pstate_values[pstate_count].power; + pstate_xpss_values[pstate_count].transition_latency = 0; + pstate_xpss_values[pstate_count].bus_master_latency = 0; + pstate_xpss_values[pstate_count].control_value = (uint64_t)pstate; + pstate_xpss_values[pstate_count].status_value = (uint64_t)pstate; + pstate_count++; + } + + return pstate_count; +} + +void generate_cpu_entries(const struct device *device) +{ + int logical_cores; + size_t pstate_count, cpu, proc_blk_len; + struct acpi_sw_pstate pstate_values[MAX_PSTATES] = { {0} }; + struct acpi_xpss_sw_pstate pstate_xpss_values[MAX_PSTATES] = { {0} }; + uint32_t threads_per_core, proc_blk_addr; + uint32_t cstate_base_address = + rdmsr(MSR_CSTATE_ADDRESS).lo & MSR_CSTATE_ADDRESS_MASK; + + const acpi_addr_t perf_ctrl = { + .space_id = ACPI_ADDRESS_SPACE_FIXED, + .bit_width = 64, + .addrl = PS_CTL_REG, + }; + const acpi_addr_t perf_sts = { + .space_id = ACPI_ADDRESS_SPACE_FIXED, + .bit_width = 64, + .addrl = PS_STS_REG, + }; + + const acpi_cstate_t cstate_info[] = { + [0] = { + .ctype = 1, + .latency = 1, + .power = 0, + .resource = { + .space_id = ACPI_ADDRESS_SPACE_FIXED, + .bit_width = 2, + .bit_offset = 2, + .addrl = 0, + .addrh = 0, + }, + }, + [1] = { + .ctype = 2, + .latency = 0x12, + .power = 0, + .resource = { + .space_id = ACPI_ADDRESS_SPACE_IO, + .bit_width = 8, + .bit_offset = 0, + .addrl = cstate_base_address + 1, + .addrh = 0, + .access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS, + }, + }, + [2] = { + .ctype = 3, + .latency = 350, + .power = 0, + .resource = { + .space_id = ACPI_ADDRESS_SPACE_IO, + .bit_width = 8, + .bit_offset = 0, + .addrl = cstate_base_address + 2, + .addrh = 0, + .access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS, + }, + }, + }; + + threads_per_core = get_threads_per_core(); + pstate_count = get_pstate_info(pstate_values, pstate_xpss_values); + logical_cores = get_cpu_count(); + + for (cpu = 0; cpu < logical_cores; cpu++) { + + if (cpu == 0) { + /* BSP values for \_SB.Pxxx */ + proc_blk_len = 6; + proc_blk_addr = ACPI_GPE0_BLK; + } else { + /* AP values for \_SB.Pxxx */ + proc_blk_addr = 0; + proc_blk_len = 0; + } + + acpigen_write_processor(cpu, proc_blk_addr, proc_blk_len); + + acpigen_write_pct_package(&perf_ctrl, &perf_sts); + + acpigen_write_pss_object(pstate_values, pstate_count); + + acpigen_write_xpss_object(pstate_xpss_values, pstate_count); + + if (CONFIG(ACPI_SSDT_PSD_INDEPENDENT)) + acpigen_write_PSD_package(cpu / threads_per_core, threads_per_core, + HW_ALL); + else + acpigen_write_PSD_package(0, logical_cores, SW_ALL); + + acpigen_write_PPC(0); + + acpigen_write_CST_package(cstate_info, ARRAY_SIZE(cstate_info)); + + acpigen_write_CSD_package(cpu / threads_per_core, threads_per_core, + CSD_HW_ALL, 0); + + generate_cppc_entries(cpu); + + acpigen_pop_len(); + } + + acpigen_write_processor_package("PPKG", 0, logical_cores); +} diff --git a/src/soc/amd/morgana/acpi/globalnvs.asl b/src/soc/amd/morgana/acpi/globalnvs.asl new file mode 100644 index 0000000000..55fbabbb1c --- /dev/null +++ b/src/soc/amd/morgana/acpi/globalnvs.asl @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* TODO: Check if this is still correct */ + +/* + * NOTE: The layout of the GNVS structure below must match the layout in + * soc/amd/morgana/include/soc/nvs.h !!! + */ + +Field (GNVS, ByteAcc, NoLock, Preserve) +{ + /* Miscellaneous */ + , 8, // 0x00 - Processor Count + LIDS, 8, // 0x01 - LID State + , 8, // 0x02 - AC Power State + CBMC, 32, // 0x03 - 0x06 - coreboot Memory Console + PM1I, 64, // 0x07 - 0x0e - System Wake Source - PM1 Index + GPEI, 64, // 0x0f - 0x16 - GPE Wake Source + TMPS, 8, // 0x17 - Temperature Sensor ID + TCRT, 8, // 0x18 - Critical Threshold + TPSV, 8, // 0x19 - Passive Threshold +} diff --git a/src/soc/amd/morgana/acpi/mmio.asl b/src/soc/amd/morgana/acpi/mmio.asl new file mode 100644 index 0000000000..51a7cbd41c --- /dev/null +++ b/src/soc/amd/morgana/acpi/mmio.asl @@ -0,0 +1,390 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include <soc/amd/common/acpi/aoac.asl> +#include <soc/aoac_defs.h> +#include <soc/gpio.h> +#include <soc/iomap.h> +#include <amdblocks/acpimmio_map.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) + + Method (_CRS, 0) { + Local0 = ResourceTemplate() { + Interrupt ( + ResourceConsumer, + Level, + ActiveLow, + Shared, , , IRQR) + { 0 } + Memory32Fixed (ReadWrite, ACPIMMIO_GPIO0_BASE, 0x400) + } + CreateDWordField (Local0, IRQR._INT, IRQN) + If (PICM) { + IRQN = IGPI + } Else { + IRQN = PGPI + } + If (IRQN == 0x1f) { + Return (ResourceTemplate() { + Memory32Fixed (ReadWrite, ACPIMMIO_GPIO0_BASE, 0x400) + }) + } Else { + Return (Local0) + } + } + + Method (_STA, 0x0, NotSerialized) + { + Return (0x0F) + } +} + +Device (FUR0) +{ + Name (_HID, "AMDI0020") + Name (_UID, 0x0) + Method (_CRS, 0) { + Local0 = ResourceTemplate() { + Interrupt ( + ResourceConsumer, + Edge, + ActiveHigh, + Exclusive, , , IRQR) + { 0 } + Memory32Fixed (ReadWrite, APU_UART0_BASE, 0x1000) + } + CreateDWordField (Local0, IRQR._INT, IRQN) + If (PICM) { + IRQN = IUA0 + } Else { + IRQN = PUA0 + } + If (IRQN == 0x1f) { + Return (ResourceTemplate() { + Memory32Fixed (ReadWrite, APU_UART0_BASE, 0x1000) + }) + } Else { + Return (Local0) + } + } + + AOAC_DEVICE(FCH_AOAC_DEV_UART0, 0) +} + +Device (FUR1) { + Name (_HID, "AMDI0020") + Name (_UID, 0x1) + Method (_CRS, 0) { + Local0 = ResourceTemplate() { + Interrupt ( + ResourceConsumer, + Edge, + ActiveHigh, + Exclusive, , , IRQR) + { 0 } + Memory32Fixed (ReadWrite, APU_UART1_BASE, 0x1000) + } + CreateDWordField (Local0, IRQR._INT, IRQN) + If (PICM) { + IRQN = IUA1 + } Else { + IRQN = PUA1 + } + If (IRQN == 0x1f) { + Return (ResourceTemplate() { + Memory32Fixed (ReadWrite, APU_UART1_BASE, 0x1000) + }) + } Else { + Return (Local0) + } + } + + AOAC_DEVICE(FCH_AOAC_DEV_UART1, 0) +} + +Device (FUR2) { + Name (_HID, "AMDI0020") + Name (_UID, 0x2) + Method (_CRS, 0) { + Local0 = ResourceTemplate() { + Interrupt ( + ResourceConsumer, + Edge, + ActiveHigh, + Exclusive, , , IRQR) + { 0 } + Memory32Fixed (ReadWrite, APU_UART2_BASE, 0x1000) + } + CreateDWordField (Local0, IRQR._INT, IRQN) + If (PICM) { + IRQN = IUA2 + } Else { + IRQN = PUA2 + } + If (IRQN == 0x1f) { + Return (ResourceTemplate() { + Memory32Fixed (ReadWrite, APU_UART2_BASE, 0x1000) + }) + } Else { + Return (Local0) + } + } + + AOAC_DEVICE(FCH_AOAC_DEV_UART2, 0) +} + +Device (FUR3) { + Name (_HID, "AMDI0020") + Name (_UID, 0x3) + Method (_CRS, 0) { + Local0 = ResourceTemplate() { + Interrupt ( + ResourceConsumer, + Edge, + ActiveHigh, + Exclusive, , , IRQR) + { 0 } + Memory32Fixed (ReadWrite, APU_UART3_BASE, 0x1000) + } + CreateDWordField (Local0, IRQR._INT, IRQN) + If (PICM) { + IRQN = IUA3 + } Else { + IRQN = PUA3 + } + If (IRQN == 0x1f) { + Return (ResourceTemplate() { + Memory32Fixed (ReadWrite, APU_UART3_BASE, 0x1000) + }) + } Else { + Return (Local0) + } + } + + AOAC_DEVICE(FCH_AOAC_DEV_UART3, 0) +} + +Device (FUR4) { + Name (_HID, "AMDI0020") + Name (_UID, 0x4) + Method (_CRS, 0) { + Local0 = ResourceTemplate() { + Interrupt ( + ResourceConsumer, + Edge, + ActiveHigh, + Exclusive, , , IRQR) + { 0 } + Memory32Fixed (ReadWrite, APU_UART4_BASE, 0x1000) + } + CreateDWordField (Local0, IRQR._INT, IRQN) + If (PICM) { + IRQN = IUA4 + } Else { + IRQN = PUA4 + } + If (IRQN == 0x1f) { + Return (ResourceTemplate() { + Memory32Fixed (ReadWrite, APU_UART4_BASE, 0x1000) + }) + } Else { + Return (Local0) + } + } + + AOAC_DEVICE(FCH_AOAC_DEV_UART4, 0) +} + +Device (I2C0) { + Name (_HID, "AMDI0010") + Name (_UID, 0x0) + Method (_CRS, 0) { + Local0 = ResourceTemplate() { + Interrupt ( + ResourceConsumer, + Edge, + ActiveHigh, + Exclusive, , , IRQR) + { 0 } + Memory32Fixed (ReadWrite, APU_I2C0_BASE, 0x1000) + } + CreateDWordField (Local0, IRQR._INT, IRQN) + If (PICM) { + IRQN = II20 + } Else { + IRQN = PI20 + } + If (IRQN == 0x1f) { + Return (ResourceTemplate() { + Memory32Fixed (ReadWrite, APU_I2C0_BASE, 0x1000) + }) + } Else { + Return (Local0) + } + } + + Method (_STA, 0x0, NotSerialized) + { + Return (0x0F) + } + + AOAC_DEVICE(FCH_AOAC_DEV_I2C0, 0) +} + +Device (I2C1) { + Name (_HID, "AMDI0010") + Name (_UID, 0x1) + Method (_CRS, 0) { + Local0 = ResourceTemplate() { + Interrupt ( + ResourceConsumer, + Edge, + ActiveHigh, + Exclusive, , , IRQR) + { 0 } + Memory32Fixed (ReadWrite, APU_I2C1_BASE, 0x1000) + } + CreateDWordField (Local0, IRQR._INT, IRQN) + If (PICM) { + IRQN = II21 + } Else { + IRQN = PI21 + } + If (IRQN == 0x1f) { + Return (ResourceTemplate() { + Memory32Fixed (ReadWrite, APU_I2C1_BASE, 0x1000) + }) + } Else { + Return (Local0) + } + } + + Method (_STA, 0x0, NotSerialized) + { + Return (0x0F) + } + + AOAC_DEVICE(FCH_AOAC_DEV_I2C1, 0) +} + +Device (I2C2) { + Name (_HID, "AMDI0010") + Name (_UID, 0x2) + Method (_CRS, 0) { + Local0 = ResourceTemplate() { + Interrupt ( + ResourceConsumer, + Edge, + ActiveHigh, + Exclusive, , , IRQR) + { 0 } + Memory32Fixed (ReadWrite, APU_I2C2_BASE, 0x1000) + } + CreateDWordField (Local0, IRQR._INT, IRQN) + If (PICM) { + IRQN = II22 + } Else { + IRQN = PI22 + } + If (IRQN == 0x1f) { + Return (ResourceTemplate() { + Memory32Fixed (ReadWrite, APU_I2C2_BASE, 0x1000) + }) + } Else { + Return (Local0) + } + } + + Method (_STA, 0x0, NotSerialized) + { + Return (0x0F) + } + + AOAC_DEVICE(FCH_AOAC_DEV_I2C2, 0) +} + +Device (I2C3) +{ +#if CONFIG(SOC_AMD_COMMON_BLOCK_I2C3_TPM_SHARED_WITH_PSP) + Name (_HID, "AMDI0019") +#else + Name (_HID, "AMDI0010") +#endif + Name (_UID, 0x3) + Method (_CRS, 0) { + Local0 = ResourceTemplate() { + Interrupt ( + ResourceConsumer, + Edge, + ActiveHigh, + Exclusive, , , IRQR) + { 0 } + Memory32Fixed (ReadWrite, APU_I2C3_BASE, 0x1000) + } + CreateDWordField (Local0, IRQR._INT, IRQN) + If (PICM) { + IRQN = II23 + } Else { + IRQN = PI23 + } + If (IRQN == 0x1f) { + Return (ResourceTemplate() { + Memory32Fixed (ReadWrite, APU_I2C3_BASE, 0x1000) + }) + } Else { + Return (Local0) + } + } + Method (_STA, 0x0, NotSerialized) + { + Return (0x0F) + } + +/* If this device is shared with PSP, then PSP takes care of power management */ +#if !CONFIG(SOC_AMD_COMMON_BLOCK_I2C3_TPM_SHARED_WITH_PSP) + AOAC_DEVICE(FCH_AOAC_DEV_I2C3, 0) +#endif +} + +Device (MISC) +{ + Name (_HID, "AMD0040") + Name (_UID, 0x3) + Name (_CRS, ResourceTemplate() { + Memory32Fixed (ReadWrite, ACPIMMIO_MISC_BASE, 0x100) + }) + Name (_DSD, Package () + { + ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), + Package () + { + Package () { "is-rv", 1 }, + }, + }) + Method (_STA, 0x0, NotSerialized) + { + Return (0x0F) + } +} diff --git a/src/soc/amd/morgana/acpi/pci0.asl b/src/soc/amd/morgana/acpi/pci0.asl new file mode 100644 index 0000000000..7ccb00519f --- /dev/null +++ b/src/soc/amd/morgana/acpi/pci0.asl @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +Device(PCI0) { + Name(_HID, EISAID("PNP0A08")) /* PCI Express Root Bridge */ + Name(_CID, EISAID("PNP0A03")) /* PCI Root Bridge */ + External(TOM1, IntObj) /* Generated by root_complex.c */ + + Method(_BBN, 0, NotSerialized) { + Return(Zero) /* Bus number = 0 */ + } + + Method(_STA, 0, NotSerialized) { + Return(0x0B) /* Status is visible */ + } + + /* Operating System Capabilities Method */ + Method(_OSC, 4) { + CreateDWordField(Arg3, 0, CDW1) /* Capabilities dword 1 */ + + /* Check for proper PCI/PCIe UUID */ + If (Arg0 == ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766")) { + /* Let OS control everything */ + Return (Arg3) + } Else { + CDW1 |= 4 /* Unrecognized UUID */ + Return (Arg3) + } + } + Name(CRES, ResourceTemplate() { + 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 */ + 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) + }) + + Method(_CRS, 0) { + CreateDWordField(CRES, ^MMIO._BAS, MM1B) + CreateDWordField(CRES, ^MMIO._LEN, MM1L) + + /* Declare memory between TOM1 and MMCONF as available for PCI MMIO. */ + MM1B = TOM1 + Local0 = CONFIG_ECAM_MMCONF_BASE_ADDRESS + Local0 -= TOM1 + MM1L = Local0 + + CreateWordField(CRES, ^PSB0._MAX, BMAX) + CreateWordField(CRES, ^PSB0._LEN, BLEN) + BMAX = CONFIG_ECAM_MMCONF_BUS_NUMBER - 1 + BLEN = CONFIG_ECAM_MMCONF_BUS_NUMBER + + Return(CRES) /* note to change the Name buffer */ + } /* end of Method(_SB.PCI0._CRS) */ + + /* 0:14.3 - LPC */ + #include <soc/amd/common/acpi/lpc.asl> + +} /* End PCI0 scope */ diff --git a/src/soc/amd/morgana/acpi/pci_int_defs.asl b/src/soc/amd/morgana/acpi/pci_int_defs.asl new file mode 100644 index 0000000000..efdce0b5f8 --- /dev/null +++ b/src/soc/amd/morgana/acpi/pci_int_defs.asl @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +/* PCI IRQ mapping registers, C00h-C01h. */ +OperationRegion(PRQM, SystemIO, 0x00000c00, 0x00000002) + Field(PRQM, ByteAcc, NoLock, Preserve) { + PRQI, 0x00000008, + PRQD, 0x00000008, /* Offset: 1h */ +} +/* + * All PIC indexes are prefixed with P. + * All IO-APIC indexes are prefixed with I. + */ +IndexField(PRQI, PRQD, ByteAcc, NoLock, Preserve) { + PIRA, 0x00000008, /* Index 0: INTA */ + PIRB, 0x00000008, /* Index 1: INTB */ + PIRC, 0x00000008, /* Index 2: INTC */ + PIRD, 0x00000008, /* Index 3: INTD */ + PIRE, 0x00000008, /* Index 4: INTE */ + PIRF, 0x00000008, /* Index 5: INTF */ + PIRG, 0x00000008, /* Index 6: INTG */ + PIRH, 0x00000008, /* Index 7: INTH */ + + Offset (0x43), + PMMC, 0x00000008, /* Index 0x43: eMMC */ + + Offset (0x62), + PGPI, 0x00000008, /* Index 0x62: GPIO */ + + Offset (0x70), + PI20, 0x00000008, /* Index 0x70: I2C0 */ + PI21, 0x00000008, /* Index 0x71: I2C1 */ + PI22, 0x00000008, /* Index 0x72: I2C2 */ + PI23, 0x00000008, /* Index 0x73: I2C3 */ + PUA0, 0x00000008, /* Index 0x74: UART0 */ + PUA1, 0x00000008, /* Index 0x75: UART1 */ + PI24, 0x00000008, /* Index 0x76: I2C4 */ + PUA4, 0x00000008, /* Index 0x77: UART4 */ + PUA2, 0x00000008, /* Index 0x78: UART2 */ + PUA3, 0x00000008, /* Index 0x79: UART3 */ + + /* IO-APIC IRQs */ + Offset (0x80), + IORA, 0x00000008, /* Index 0x80: INTA */ + IORB, 0x00000008, /* Index 0x81: INTB */ + IORC, 0x00000008, /* Index 0x82: INTC */ + IORD, 0x00000008, /* Index 0x83: INTD */ + IORE, 0x00000008, /* Index 0x84: INTE */ + IORF, 0x00000008, /* Index 0x85: INTF */ + IORG, 0x00000008, /* Index 0x86: INTG */ + IORH, 0x00000008, /* Index 0x87: INTH */ + + Offset (0xC3), + IMMC, 0x00000008, /* Index 0xC3: eMMC */ + + Offset (0xE2), + IGPI, 0x00000008, /* Index 0xE2: GPIO */ + + Offset (0xF0), + II20, 0x00000008, /* Index 0xF0: I2C0 */ + II21, 0x00000008, /* Index 0xF1: I2C1 */ + II22, 0x00000008, /* Index 0xF2: I2C2 */ + II23, 0x00000008, /* Index 0xF3: I2C3 */ + IUA0, 0x00000008, /* Index 0xF4: UART0 */ + IUA1, 0x00000008, /* Index 0xF5: UART1 */ + II24, 0x00000008, /* Index 0xF6: I2C4 */ + IUA4, 0x00000008, /* Index 0xF7: UART4 */ + IUA2, 0x00000008, /* Index 0xF8: UART2 */ + IUA3, 0x00000008, /* Index 0xF9: UART3 */ +} diff --git a/src/soc/amd/morgana/acpi/soc.asl b/src/soc/amd/morgana/acpi/soc.asl new file mode 100644 index 0000000000..df9911c961 --- /dev/null +++ b/src/soc/amd/morgana/acpi/soc.asl @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include "globalnvs.asl" + +Scope(\_SB) { + /* global utility methods expected within the \_SB scope */ + #include <arch/x86/acpi/globutil.asl> + + #include <soc/amd/common/acpi/gpio_bank_lib.asl> + + #include <soc/amd/common/acpi/osc.asl> + + #include "pci_int_defs.asl" + + #include <soc/amd/common/acpi/pci_int.asl> + + #include "mmio.asl" + + #include "pci0.asl" +} /* End \_SB scope */ + +#include <soc/amd/common/acpi/alib.asl> + +#include <soc/amd/common/acpi/platform.asl> + +#include <soc/amd/common/acpi/sleepstates.asl> + +#include <soc/amd/common/acpi/upep.asl> + +#if CONFIG(SOC_AMD_COMMON_BLOCK_ACPI_DPTC) +#include <soc/amd/common/acpi/dptc.asl> +#endif + +/* Enable DPTC interface with AMD ALIB */ +External(\_SB.DPTC, MethodObj) + +/* + * Platform Notify + * + * This is called by soc/amd/common/acpi/platform.asl. + */ +Method (PNOT) +{ + /* Report AC/DC state to ALIB using WAL1() */ + \WAL1 () + + If (CondRefOf (\_SB.DPTC)) { + \_SB.DPTC() + } +} diff --git a/src/soc/amd/morgana/agesa_acpi.c b/src/soc/amd/morgana/agesa_acpi.c new file mode 100644 index 0000000000..78c0e4cdf3 --- /dev/null +++ b/src/soc/amd/morgana/agesa_acpi.c @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Make common? */ + +#include <acpi/acpi.h> +#include <amdblocks/acpi.h> +#include <device/device.h> +#include <FspGuids.h> +#include <soc/acpi.h> +#include <types.h> + +uintptr_t agesa_write_acpi_tables(const struct device *device, uintptr_t current, + acpi_rsdp_t *rsdp) +{ + acpi_ivrs_t *ivrs; + + /* add ALIB SSDT from HOB */ + current = add_agesa_fsp_acpi_table(AMD_FSP_ACPI_ALIB_HOB_GUID, "ALIB", rsdp, current); + + /* IVRS */ + current = ALIGN(current, 8); + ivrs = (acpi_ivrs_t *)current; + acpi_create_ivrs(ivrs, acpi_fill_ivrs); + current += ivrs->header.length; + acpi_add_table(rsdp, ivrs); + + return current; +} diff --git a/src/soc/amd/morgana/aoac.c b/src/soc/amd/morgana/aoac.c new file mode 100644 index 0000000000..d4f96df849 --- /dev/null +++ b/src/soc/amd/morgana/aoac.c @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include <stdint.h> +#include <amdblocks/acpimmio.h> +#include <amdblocks/aoac.h> +#include <soc/aoac_defs.h> +#include <soc/southbridge.h> +#include <delay.h> + +#define FCH_AOAC_UART_FOR_CONSOLE \ + (CONFIG_UART_FOR_CONSOLE == 0 ? FCH_AOAC_DEV_UART0 \ + : CONFIG_UART_FOR_CONSOLE == 1 ? FCH_AOAC_DEV_UART1 \ + : CONFIG_UART_FOR_CONSOLE == 2 ? FCH_AOAC_DEV_UART2 \ + : CONFIG_UART_FOR_CONSOLE == 3 ? FCH_AOAC_DEV_UART3 \ + : CONFIG_UART_FOR_CONSOLE == 4 ? FCH_AOAC_DEV_UART4 \ + : -1) +#if CONFIG(AMD_SOC_CONSOLE_UART) && FCH_AOAC_UART_FOR_CONSOLE == -1 +# error Unsupported UART_FOR_CONSOLE chosen +#endif + +/* + * 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. The console UART is handled separately from this table. + * + * TODO: Find out which I2C controllers we really need to enable here. + */ +const static unsigned int aoac_devs[] = { + FCH_AOAC_DEV_AMBA, + FCH_AOAC_DEV_I2C0, + FCH_AOAC_DEV_I2C1, + FCH_AOAC_DEV_I2C2, + FCH_AOAC_DEV_I2C3, + FCH_AOAC_DEV_ESPI, +}; + +void wait_for_aoac_enabled(unsigned int dev) +{ + while (!is_aoac_device_enabled(dev)) + udelay(100); +} + +void enable_aoac_devices(void) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(aoac_devs); i++) + power_on_aoac_device(aoac_devs[i]); + + if (CONFIG(AMD_SOC_CONSOLE_UART)) + power_on_aoac_device(FCH_AOAC_UART_FOR_CONSOLE); + + /* Wait for AOAC devices to indicate power and clock OK */ + for (i = 0; i < ARRAY_SIZE(aoac_devs); i++) + wait_for_aoac_enabled(aoac_devs[i]); + + if (CONFIG(AMD_SOC_CONSOLE_UART)) + wait_for_aoac_enabled(FCH_AOAC_UART_FOR_CONSOLE); +} diff --git a/src/soc/amd/morgana/bootblock.c b/src/soc/amd/morgana/bootblock.c new file mode 100644 index 0000000000..57fac992f6 --- /dev/null +++ b/src/soc/amd/morgana/bootblock.c @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include <amdblocks/amd_pci_mmconf.h> +#include <amdblocks/cpu.h> +#include <bootblock_common.h> +#include <console/console.h> +#include <cpu/x86/tsc.h> +#include <soc/southbridge.h> +#include <soc/psp_transfer.h> +#include <stdint.h> + +asmlinkage void bootblock_c_entry(uint64_t base_timestamp) +{ + early_cache_setup(); + write_resume_eip(); + enable_pci_mmconf(); + + /* + * base_timestamp is raw tsc value. We need to divide by tsc_freq_mhz + * to get micro-seconds granularity. + */ + base_timestamp /= tsc_freq_mhz(); + + if (CONFIG(VBOOT_STARTS_BEFORE_BOOTBLOCK)) + boot_with_psp_timestamp(base_timestamp); + + /* + * if VBOOT_STARTS_BEFORE_BOOTBLOCK is not selected or + * previous step did nothing, proceed with normal bootblock main. + */ + bootblock_main_with_basetime(base_timestamp); +} + +void bootblock_soc_early_init(void) +{ + fch_pre_init(); +} + +void bootblock_soc_init(void) +{ + u32 val = cpuid_eax(1); + printk(BIOS_DEBUG, "Family_Model: %08x\n", val); + + if (CONFIG(VBOOT_STARTS_BEFORE_BOOTBLOCK)) { + verify_psp_transfer_buf(); + show_psp_transfer_info(); + } + + fch_early_init(); +} diff --git a/src/soc/amd/morgana/chip.c b/src/soc/amd/morgana/chip.c new file mode 100644 index 0000000000..2b97c6cc74 --- /dev/null +++ b/src/soc/amd/morgana/chip.c @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include <amdblocks/aoac.h> +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <fsp/api.h> +#include <soc/acpi.h> +#include <soc/aoac_defs.h> +#include <soc/cpu.h> +#include <soc/data_fabric.h> +#include <soc/pci_devs.h> +#include <soc/southbridge.h> +#include <types.h> +#include "chip.h" + +/* Supplied by i2c.c */ +extern struct device_operations soc_amd_i2c_mmio_ops; +/* Supplied by uart.c */ +extern struct device_operations morgana_uart_mmio_ops; + +struct device_operations cpu_bus_ops = { + .read_resources = noop_read_resources, + .set_resources = noop_set_resources, + .init = mp_cpu_bus_init, + .acpi_fill_ssdt = generate_cpu_entries, +}; + +static const char *soc_acpi_name(const struct device *dev) +{ + if (dev->path.type == DEVICE_PATH_DOMAIN) + return "PCI0"; + + if (dev->path.type != DEVICE_PATH_PCI) + return NULL; + + printk(BIOS_WARNING, "Unknown PCI device: dev: %d, fn: %d\n", + PCI_SLOT(dev->path.pci.devfn), PCI_FUNC(dev->path.pci.devfn)); + return NULL; +}; + +static struct device_operations pci_domain_ops = { + .read_resources = pci_domain_read_resources, + .set_resources = pci_domain_set_resources, + .scan_bus = pci_domain_scan_bus, + .acpi_name = soc_acpi_name, +}; + +static void set_mmio_dev_ops(struct device *dev) +{ + switch (dev->path.mmio.addr) { + case APU_I2C0_BASE: + case APU_I2C1_BASE: + case APU_I2C2_BASE: + case APU_I2C3_BASE: + dev->ops = &soc_amd_i2c_mmio_ops; + break; + case APU_UART0_BASE: + case APU_UART1_BASE: + case APU_UART2_BASE: + case APU_UART3_BASE: + case APU_UART4_BASE: + dev->ops = &morgana_uart_mmio_ops; + break; + case APU_EMMC_BASE: + if (!dev->enabled) + power_off_aoac_device(FCH_AOAC_DEV_EMMC); + break; + } +} + +static void enable_dev(struct device *dev) +{ + /* Set the operations if it is a special bus type */ + switch (dev->path.type) { + case DEVICE_PATH_DOMAIN: + dev->ops = &pci_domain_ops; + break; + case DEVICE_PATH_CPU_CLUSTER: + dev->ops = &cpu_bus_ops; + break; + case DEVICE_PATH_MMIO: + set_mmio_dev_ops(dev); + break; + default: + break; + } +} + +static void soc_init(void *chip_info) +{ + default_dev_ops_root.write_acpi_tables = agesa_write_acpi_tables; + + fsp_silicon_init(); + + data_fabric_set_mmio_np(); + + fch_init(chip_info); +} + +static void soc_final(void *chip_info) +{ + fch_final(chip_info); +} + +struct chip_operations soc_amd_morgana_ops = { + CHIP_NAME("AMD Morgana SoC") + .enable_dev = enable_dev, + .init = soc_init, + .final = soc_final +}; diff --git a/src/soc/amd/morgana/chip.h b/src/soc/amd/morgana/chip.h new file mode 100644 index 0000000000..8875c5e83d --- /dev/null +++ b/src/soc/amd/morgana/chip.h @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#ifndef MORGANA_CHIP_H +#define MORGANA_CHIP_H + +#include <amdblocks/chip.h> +#include <amdblocks/i2c.h> +#include <gpio.h> +#include <soc/i2c.h> +#include <soc/southbridge.h> +#include <drivers/i2c/designware/dw_i2c.h> +#include <types.h> +#include <vendorcode/amd/fsp/morgana/FspUsb.h> + +struct soc_amd_morgana_config { + struct soc_amd_common_config common_config; + u8 i2c_scl_reset; + struct dw_i2c_bus_config i2c[I2C_CTRLR_COUNT]; + struct i2c_pad_control i2c_pad[I2C_CTRLR_COUNT]; + + /* Enable S0iX support */ + bool s0ix_enable; + + enum { + DOWNCORE_AUTO = 0, + DOWNCORE_1 = 1, /* Run with 1 physical core */ + DOWNCORE_2 = 3, /* Run with 2 physical cores */ + DOWNCORE_3 = 4, /* Run with 3 physical cores */ + DOWNCORE_4 = 6, /* Run with 4 physical cores */ + DOWNCORE_5 = 8, /* Run with 5 physical cores */ + DOWNCORE_6 = 9, /* Run with 6 physical cores */ + DOWNCORE_7 = 10, /* Run with 7 physical cores */ + } downcore_mode; + bool disable_smt; /* disable second thread on all physical cores */ + + uint8_t stt_control; + uint8_t stt_pcb_sensor_count; + uint16_t stt_min_limit; + uint16_t stt_m1; + uint16_t stt_m2; + uint16_t stt_m3; + uint16_t stt_m4; + uint16_t stt_m5; + uint16_t stt_m6; + uint16_t stt_c_apu; + uint16_t stt_c_gpu; + uint16_t stt_c_hs2; + uint16_t stt_alpha_apu; + uint16_t stt_alpha_gpu; + uint16_t stt_alpha_hs2; + uint16_t stt_skin_temp_apu; + uint16_t stt_skin_temp_gpu; + uint16_t stt_skin_temp_hs2; + uint16_t stt_error_coeff; + uint16_t stt_error_rate_coefficient; + + /* Default */ + uint8_t stapm_boost; + uint32_t stapm_time_constant_s; + uint32_t apu_only_sppt_limit; + uint32_t sustained_power_limit_mW; + uint32_t fast_ppt_limit_mW; + uint32_t slow_ppt_limit_mW; + uint32_t slow_ppt_time_constant_s; + uint32_t thermctl_limit_degreeC; + uint32_t vrm_current_limit_mA; + uint32_t vrm_maximum_current_limit_mA; + uint32_t vrm_soc_current_limit_mA; + /* Throttle (e.g., Low/No Battery) */ + uint32_t vrm_current_limit_throttle_mA; + uint32_t vrm_maximum_current_limit_throttle_mA; + uint32_t vrm_soc_current_limit_throttle_mA; + + uint8_t smartshift_enable; + + uint8_t system_configuration; + + uint8_t cppc_ctrl; + uint8_t cppc_perf_limit_max_range; + uint8_t cppc_perf_limit_min_range; + uint8_t cppc_epp_max_range; + uint8_t cppc_epp_min_range; + uint8_t cppc_preferred_cores; + + /* telemetry settings */ + uint32_t telemetry_vddcrvddfull_scale_current_mA; + uint32_t telemetry_vddcrvddoffset; + uint32_t telemetry_vddcrsocfull_scale_current_mA; + uint32_t telemetry_vddcrsocoffset; + + /* The array index is the general purpose PCIe clock output number. Values in here + aren't the values written to the register to have the default to be always on. */ + enum { + GPP_CLK_ON, /* GPP clock always on; default */ + GPP_CLK_REQ, /* GPP clock controlled by corresponding #CLK_REQx pin */ + GPP_CLK_OFF, /* GPP clk off */ + } gpp_clk_config[GPP_CLK_OUTPUT_AVAILABLE]; + + /* performance policy for the PCIe links: power consumption vs. link speed */ + enum { + DXIO_PSPP_DISABLED = 0, + DXIO_PSPP_PERFORMANCE, + DXIO_PSPP_BALANCED, + DXIO_PSPP_POWERSAVE, + } pspp_policy; + + uint8_t usb_phy_custom; + struct usb_phy_config usb_phy; +}; + +#endif /* MORGANA_CHIP_H */ diff --git a/src/soc/amd/morgana/chipset.cb b/src/soc/amd/morgana/chipset.cb new file mode 100644 index 0000000000..fe072a217e --- /dev/null +++ b/src/soc/amd/morgana/chipset.cb @@ -0,0 +1,95 @@ +# TODO: Update for Morgana + +chip soc/amd/morgana + device cpu_cluster 0 on + end + device domain 0 on + device pci 00.0 alias gnb on end + device pci 00.2 alias iommu off end + + device pci 01.0 on end # Dummy Host Bridge + + device pci 02.0 on end # Dummy Host Bridge, do not disable + device pci 02.1 alias gpp_bridge_0 off end + device pci 02.2 alias gpp_bridge_1 off end + device pci 02.3 alias gpp_bridge_2 off end + device pci 02.4 alias gpp_bridge_3 off end + device pci 02.5 alias gpp_bridge_4 off end + device pci 02.6 alias gpp_bridge_5 off end + + device pci 08.0 on end # Dummy Host Bridge, do not disable + device pci 08.1 alias gpp_bridge_a off # Internal GPP Bridge 0 to Bus A + device pci 0.0 alias gfx off end # Internal GPU (GFX) + device pci 0.1 alias gfx_hda off end # Display HD Audio Controller (GFXAZ) + device pci 0.2 alias crypto off end # Crypto Coprocessor + device pci 0.3 alias xhci_0 off + chip drivers/usb/acpi + register "type" = "UPC_TYPE_HUB" + device usb 0.0 alias xhci_0_root_hub off + chip drivers/usb/acpi + device usb 3.0 alias usb3_port0 off end + end + chip drivers/usb/acpi + device usb 2.0 alias usb2_port0 off end + end + chip drivers/usb/acpi + device usb 2.1 alias usb2_port1 off end + end + end + end + end + device pci 0.4 alias xhci_1 off + chip drivers/usb/acpi + register "type" = "UPC_TYPE_HUB" + device usb 0.0 alias xhci_1_root_hub off + chip drivers/usb/acpi + device usb 3.0 alias usb3_port2 off end + end + chip drivers/usb/acpi + device usb 3.1 alias usb3_port3 off end + end + chip drivers/usb/acpi + device usb 2.0 alias usb2_port2 off end + end + chip drivers/usb/acpi + device usb 2.1 alias usb2_port3 off end + end + chip drivers/usb/acpi + device usb 2.2 alias usb2_port4 off end + end + end + end + end + device pci 0.5 alias acp off end # Audio Processor (ACP) + device pci 0.6 alias hda off end # Audio Processor HD Audio Controller (main AZ) + device pci 0.7 alias mp2 off end # Sensor Fusion Hub (MP2) + end + device pci 08.2 alias gpp_bridge_b off end # Internal GPP Bridge 1 to Bus B + device pci 08.3 alias gpp_bridge_c off # Internal GPP Bridge 2 to Bus C + device pci 0.0 alias xhci_2 off end # Might also be a dummy device with different PCI DID + end + + device pci 14.0 alias smbus on end # primary FCH function + device pci 14.3 alias lpc_bridge on end + + device pci 18.0 alias data_fabric_0 on end + device pci 18.1 alias data_fabric_1 on end + device pci 18.2 alias data_fabric_2 on end + device pci 18.3 alias data_fabric_3 on end + device pci 18.4 alias data_fabric_4 on end + device pci 18.5 alias data_fabric_5 on end + device pci 18.6 alias data_fabric_6 on end + device pci 18.7 alias data_fabric_7 on end + end + + device mmio 0xfedc2000 alias i2c_0 off end + device mmio 0xfedc3000 alias i2c_1 off end + device mmio 0xfedc4000 alias i2c_2 off end + device mmio 0xfedc5000 alias i2c_3 off end + device mmio 0xfedc9000 alias uart_0 off end + device mmio 0xfedca000 alias uart_1 off end + device mmio 0xfedce000 alias uart_2 off end + device mmio 0xfedcf000 alias uart_3 off end + device mmio 0xfedd1000 alias uart_4 off end + device mmio 0xfedd5000 alias emmc off end +end diff --git a/src/soc/amd/morgana/config.c b/src/soc/amd/morgana/config.c new file mode 100644 index 0000000000..161d86cd49 --- /dev/null +++ b/src/soc/amd/morgana/config.c @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <amdblocks/chip.h> +#include <device/device.h> +#include "chip.h" + +const struct soc_amd_common_config *soc_get_common_config(void) +{ + /* config_of_soc calls die() internally if cfg was NULL, so no need to re-check */ + const struct soc_amd_morgana_config *cfg = config_of_soc(); + return &cfg->common_config; +} diff --git a/src/soc/amd/morgana/cpu.c b/src/soc/amd/morgana/cpu.c new file mode 100644 index 0000000000..fe5a1b8ae7 --- /dev/null +++ b/src/soc/amd/morgana/cpu.c @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include <acpi/acpi.h> +#include <amdblocks/cpu.h> +#include <amdblocks/iomap.h> +#include <amdblocks/mca.h> +#include <console/console.h> +#include <cpu/amd/microcode.h> +#include <cpu/cpu.h> +#include <cpu/x86/mp.h> +#include <cpu/x86/mtrr.h> +#include <acpi/acpi.h> +#include <device/device.h> +#include <soc/cpu.h> +#include <soc/iomap.h> + +_Static_assert(CONFIG_MAX_CPUS == 8, "Do not override MAX_CPUS. To reduce the number of " + "available cores, use the downcore_mode and disable_smt devicetree settings instead."); + +/* MP and SMM loading initialization */ + +void mp_init_cpus(struct bus *cpu_bus) +{ + extern const struct mp_ops amd_mp_ops_with_smm; + if (mp_init_with_smm(cpu_bus, &amd_mp_ops_with_smm) != CB_SUCCESS) + die_with_post_code(POST_HW_INIT_FAILURE, + "mp_init_with_smm failed. Halting.\n"); + + /* pre_mp_init made the flash not cacheable. Reset to WP for performance. */ + mtrr_use_temp_range(FLASH_BELOW_4GB_MAPPING_REGION_BASE, + FLASH_BELOW_4GB_MAPPING_REGION_SIZE, MTRR_TYPE_WRPROT); + + /* SMMINFO only needs to be set up when booting from S5 */ + if (!acpi_is_wakeup_s3()) + apm_control(APM_CNT_SMMINFO); +} + +static void zen_2_3_init(struct device *dev) +{ + check_mca(); + set_cstate_io_addr(); + + amd_update_microcode_from_cbfs(); +} + +static struct device_operations cpu_dev_ops = { + .init = zen_2_3_init, +}; + +static struct cpu_device_id cpu_table[] = { + { X86_VENDOR_AMD, MORGANA_A0_CPUID}, /* TODO: Update for Morgana */ + { 0, 0 }, +}; + +static const struct cpu_driver zen_2_3 __cpu_driver = { + .ops = &cpu_dev_ops, + .id_table = cpu_table, +}; diff --git a/src/soc/amd/morgana/data_fabric.c b/src/soc/amd/morgana/data_fabric.c new file mode 100644 index 0000000000..0249b8a426 --- /dev/null +++ b/src/soc/amd/morgana/data_fabric.c @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include <acpi/acpi_device.h> +#include <amdblocks/data_fabric.h> +#include <arch/hpet.h> +#include <console/console.h> +#include <cpu/x86/lapic_def.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <soc/data_fabric.h> +#include <soc/iomap.h> +#include <types.h> + +void data_fabric_set_mmio_np(void) +{ + /* + * Mark region from HPET-LAPIC or 0xfed00000-0xfee00000-1 as NP. + * + * AGESA has already programmed the NB MMIO routing, however nothing + * is yet marked as non-posted. + * + * If there exists an overlapping routing base/limit pair, trim its + * base or limit to avoid the new NP region. If any pair exists + * completely within HPET-LAPIC range, remove it. If any pair surrounds + * HPET-LAPIC, it must be split into two regions. + * + * TODO(b/156296146): Remove the settings from AGESA and allow coreboot + * to own everything. If not practical, consider erasing all settings + * and have coreboot reprogram them. At that time, make the source + * below more flexible. + * * Note that the code relies on the granularity of the HPET and + * LAPIC addresses being sufficiently large that the shifted limits + * +/-1 are always equivalent to the non-shifted values +/-1. + */ + + unsigned int i; + int reg; + uint32_t base, limit, ctrl; + const uint32_t np_bot = HPET_BASE_ADDRESS >> D18F0_MMIO_SHIFT; + const uint32_t np_top = (LAPIC_DEFAULT_BASE - 1) >> D18F0_MMIO_SHIFT; + + data_fabric_print_mmio_conf(); + + for (i = 0; i < NUM_NB_MMIO_REGS; i++) { + /* Adjust all registers that overlap */ + ctrl = data_fabric_broadcast_read32(0, NB_MMIO_CONTROL(i)); + if (!(ctrl & (DF_MMIO_WE | DF_MMIO_RE))) + continue; /* not enabled */ + + base = data_fabric_broadcast_read32(0, NB_MMIO_BASE(i)); + limit = data_fabric_broadcast_read32(0, NB_MMIO_LIMIT(i)); + + if (base > np_top || limit < np_bot) + continue; /* no overlap at all */ + + if (base >= np_bot && limit <= np_top) { + data_fabric_disable_mmio_reg(i); /* 100% within, so remove */ + continue; + } + + if (base < np_bot && limit > np_top) { + /* Split the configured region */ + data_fabric_broadcast_write32(0, NB_MMIO_LIMIT(i), np_bot - 1); + reg = data_fabric_find_unused_mmio_reg(); + if (reg < 0) { + /* Although a pair could be freed later, this condition is + * very unusual and deserves analysis. Flag an error and + * leave the topmost part unconfigured. */ + printk(BIOS_ERR, + "Error: Not enough NB MMIO routing registers\n"); + continue; + } + data_fabric_broadcast_write32(0, NB_MMIO_BASE(reg), np_top + 1); + data_fabric_broadcast_write32(0, NB_MMIO_LIMIT(reg), limit); + data_fabric_broadcast_write32(0, NB_MMIO_CONTROL(reg), ctrl); + continue; + } + + /* If still here, adjust only the base or limit */ + if (base <= np_bot) + data_fabric_broadcast_write32(0, NB_MMIO_LIMIT(i), np_bot - 1); + else + data_fabric_broadcast_write32(0, NB_MMIO_BASE(i), np_top + 1); + } + + reg = data_fabric_find_unused_mmio_reg(); + if (reg < 0) { + printk(BIOS_ERR, "Error: cannot configure region as NP\n"); + return; + } + + data_fabric_broadcast_write32(0, NB_MMIO_BASE(reg), np_bot); + data_fabric_broadcast_write32(0, NB_MMIO_LIMIT(reg), np_top); + data_fabric_broadcast_write32(0, NB_MMIO_CONTROL(reg), + (IOMS0_FABRIC_ID << DF_MMIO_DST_FABRIC_ID_SHIFT) | DF_MMIO_NP + | DF_MMIO_WE | DF_MMIO_RE); + + data_fabric_print_mmio_conf(); +} + +static const char *data_fabric_acpi_name(const struct device *dev) +{ + switch (dev->device) { + case PCI_DID_AMD_FAM17H_MODELA0H_DF0: + return "DFD0"; + case PCI_DID_AMD_FAM17H_MODELA0H_DF1: + return "DFD1"; + case PCI_DID_AMD_FAM17H_MODELA0H_DF2: + return "DFD2"; + case PCI_DID_AMD_FAM17H_MODELA0H_DF3: + return "DFD3"; + case PCI_DID_AMD_FAM17H_MODELA0H_DF4: + return "DFD4"; + case PCI_DID_AMD_FAM17H_MODELA0H_DF5: + return "DFD5"; + case PCI_DID_AMD_FAM17H_MODELA0H_DF6: + return "DFD6"; + case PCI_DID_AMD_FAM17H_MODELA0H_DF7: + return "DFD7"; + default: + printk(BIOS_ERR, "%s: Unhandled device id 0x%x\n", __func__, dev->device); + } + + return NULL; +} + +static struct device_operations data_fabric_ops = { + .read_resources = noop_read_resources, + .set_resources = noop_set_resources, + .acpi_name = data_fabric_acpi_name, + .acpi_fill_ssdt = acpi_device_write_pci_dev, +}; + +static const unsigned short pci_device_ids[] = { + PCI_DID_AMD_FAM17H_MODELA0H_DF0, /* TODO: Update for Morgana */ + PCI_DID_AMD_FAM17H_MODELA0H_DF1, + PCI_DID_AMD_FAM17H_MODELA0H_DF2, + PCI_DID_AMD_FAM17H_MODELA0H_DF3, + PCI_DID_AMD_FAM17H_MODELA0H_DF4, + PCI_DID_AMD_FAM17H_MODELA0H_DF5, + PCI_DID_AMD_FAM17H_MODELA0H_DF6, + PCI_DID_AMD_FAM17H_MODELA0H_DF7, + 0 +}; + +static const struct pci_driver data_fabric_driver __pci_driver = { + .ops = &data_fabric_ops, + .vendor = PCI_VID_AMD, + .devices = pci_device_ids, +}; diff --git a/src/soc/amd/morgana/early_fch.c b/src/soc/amd/morgana/early_fch.c new file mode 100644 index 0000000000..f6ccf554ef --- /dev/null +++ b/src/soc/amd/morgana/early_fch.c @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include <amdblocks/acpimmio.h> +#include <amdblocks/espi.h> +#include <amdblocks/i2c.h> +#include <amdblocks/lpc.h> +#include <amdblocks/pmlib.h> +#include <amdblocks/smbus.h> +#include <soc/i2c.h> +#include <soc/southbridge.h> +#include <soc/uart.h> + +#include "chip.h" + +/* Table to switch SCL pins to outputs to initially reset the I2C peripherals */ +static const struct soc_i2c_scl_pin i2c_scl_pins[] = { + I2C_RESET_SCL_PIN(I2C0_SCL_PIN, GPIO_I2C0_SCL), + I2C_RESET_SCL_PIN(I2C1_SCL_PIN, GPIO_I2C1_SCL), + I2C_RESET_SCL_PIN(I2C2_SCL_PIN, GPIO_I2C2_SCL), + I2C_RESET_SCL_PIN(I2C3_SCL_PIN, GPIO_I2C3_SCL), +}; + +static void reset_i2c_peripherals(void) +{ + const struct soc_amd_morgana_config *cfg = config_of_soc(); + struct soc_i2c_peripheral_reset_info reset_info; + + reset_info.i2c_scl_reset_mask = cfg->i2c_scl_reset & GPIO_I2C_MASK; + reset_info.i2c_scl = i2c_scl_pins; + reset_info.num_pins = ARRAY_SIZE(i2c_scl_pins); + sb_reset_i2c_peripherals(&reset_info); +} + +/* Before console init */ +void fch_pre_init(void) +{ + /* Enable_acpimmio_decode_pm04 to enable the ACPIMMIO decode which is needed to access + the GPIO registers. */ + enable_acpimmio_decode_pm04(); + /* Setup SPI base by calling lpc_early_init before setting up eSPI. */ + lpc_early_init(); + + /* Setup eSPI to enable port80 routing if the board is using eSPI and the eSPI + interface hasn't already been set up in verstage on PSP */ + if (CONFIG(SOC_AMD_COMMON_BLOCK_USE_ESPI) && !CONFIG(VBOOT_STARTS_BEFORE_BOOTBLOCK)) + configure_espi_with_mb_hook(); + + fch_spi_early_init(); + fch_smbus_init(); + fch_enable_cf9_io(); + fch_enable_legacy_io(); + fch_disable_legacy_dma_io(); + enable_aoac_devices(); + + /* + * On reset Range_0 defaults to enabled. We want to start with a clean + * slate to not have things unexpectedly enabled. + */ + clear_uart_legacy_config(); + + if (CONFIG(AMD_SOC_CONSOLE_UART)) + set_uart_config(CONFIG_UART_FOR_CONSOLE); + + /* disable the keyboard reset function before mainboard GPIO setup */ + if (CONFIG(DISABLE_KEYBOARD_RESET_PIN)) + fch_disable_kb_rst(); +} + +/* After console init */ +void fch_early_init(void) +{ + reset_i2c_peripherals(); + pm_set_power_failure_state(); + fch_print_pmxc0_status(); + i2c_soc_early_init(); + show_spi_speeds_and_modes(); + + if (CONFIG(DISABLE_SPI_FLASH_ROM_SHARING)) + lpc_disable_spi_rom_sharing(); +} diff --git a/src/soc/amd/morgana/espi_util.c b/src/soc/amd/morgana/espi_util.c new file mode 100644 index 0000000000..1d0fc1731a --- /dev/null +++ b/src/soc/amd/morgana/espi_util.c @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include <amdblocks/spi.h> +#include <soc/espi.h> +#include <types.h> + +#define ESPI_CNTRL_REGISTER 0x10 +#define LOCK_SPIX10_BIT2 BIT(3) +#define ESPI_MUX_SPI1 BIT(2) +#define ROM_ADDR_WR_PROT BIT(1) +#define DIS_ESPI_MASCTL_REG_WR BIT(0) + +void espi_switch_to_spi1_pads(void) +{ + uint8_t reg = spi_read8(ESPI_CNTRL_REGISTER); + + reg |= ESPI_MUX_SPI1; + + spi_write8(ESPI_CNTRL_REGISTER, reg); +} diff --git a/src/soc/amd/morgana/fch.c b/src/soc/amd/morgana/fch.c new file mode 100644 index 0000000000..f9f4649438 --- /dev/null +++ b/src/soc/amd/morgana/fch.c @@ -0,0 +1,230 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include <amdblocks/acpi.h> +#include <amdblocks/acpimmio.h> +#include <amdblocks/amd_pci_util.h> +#include <amdblocks/gpio.h> +#include <amdblocks/smi.h> +#include <assert.h> +#include <bootstate.h> +#include <cpu/x86/smm.h> +#include <amdblocks/i2c.h> +#include <soc/amd_pci_int_defs.h> +#include <soc/iomap.h> +#include <soc/i2c.h> +#include <soc/smi.h> +#include <soc/southbridge.h> +#include "chip.h" + +/* + * 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#/GENINT2" }, + { PIRQ_G, "INTG#" }, + { PIRQ_H, "INTH#" }, + { PIRQ_MISC, "Misc" }, + { PIRQ_MISC0, "Misc0" }, + { PIRQ_HPET_L, "HPET_L" }, + { PIRQ_HPET_H, "HPET_H" }, + { 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_PMON, "PerMon" }, + { PIRQ_SD, "SD" }, + { PIRQ_SDIO, "SDIO" }, + { PIRQ_CIR, "CIR" }, + { PIRQ_GPIOA, "GPIOa" }, + { PIRQ_GPIOB, "GPIOb" }, + { PIRQ_GPIOC, "GPIOc" }, + { PIRQ_EMMC, "eMMC" }, + { PIRQ_GPP0, "GPP0" }, + { PIRQ_GPP1, "GPP1" }, + { PIRQ_GPP2, "GPP2" }, + { PIRQ_GPP3, "GPP3" }, + { PIRQ_GPIO, "GPIO" }, + { PIRQ_I2C0, "I2C0" }, + { PIRQ_I2C1, "I2C1" }, + { PIRQ_I2C2, "I2C2" }, + { PIRQ_I2C3, "I2C3" }, + { PIRQ_UART0, "UART0" }, + { PIRQ_UART1, "UART1" }, + { PIRQ_I2C4, "I2C4" }, + { PIRQ_UART4, "UART4" }, + { PIRQ_UART2, "UART2" }, + { PIRQ_UART3, "UART3" }, +}; + +const struct irq_idx_name *sb_get_apic_reg_association(size_t *size) +{ + *size = ARRAY_SIZE(irq_association); + return irq_association; +} + +static void fch_clk_output_48Mhz(void) +{ + uint32_t ctrl = misc_read32(MISC_CLK_CNTL0); + /* Enable BP_X48M0 Clock Output */ + ctrl |= BP_X48M0_OUTPUT_EN; + /* Disable clock output in S0i3 */ + ctrl |= BP_X48M0_S0I3_DIS; + misc_write32(MISC_CLK_CNTL0, ctrl); +} + +static void fch_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); + + 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. */ + reg = pm_read32(PM_PCI_CTRL); + reg |= FORCE_SLPSTATE_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); +} + +/* configure the general purpose PCIe clock outputs according to the devicetree settings */ +static void gpp_clk_setup(void) +{ + const struct soc_amd_morgana_config *cfg = config_of_soc(); + + /* look-up table to be able to iterate over the PCIe clock output settings */ + const uint8_t gpp_clk_shift_lut[GPP_CLK_OUTPUT_COUNT] = { + GPP_CLK0_REQ_SHIFT, + GPP_CLK1_REQ_SHIFT, + GPP_CLK2_REQ_SHIFT, + GPP_CLK3_REQ_SHIFT, + GPP_CLK4_REQ_SHIFT, + GPP_CLK5_REQ_SHIFT, + GPP_CLK6_REQ_SHIFT, + }; + + uint32_t gpp_clk_ctl = misc_read32(GPP_CLK_CNTRL); + + for (int i = 0; i < GPP_CLK_OUTPUT_COUNT; i++) { + gpp_clk_ctl &= ~GPP_CLK_REQ_MASK(gpp_clk_shift_lut[i]); + /* + * The remapping of values is done so that the default of the enum used for the + * devicetree settings is the clock being enabled, so that a missing devicetree + * configuration for this will result in an always active clock and not an + * inactive PCIe clock output. Only the configuration for the clock outputs + * available on the package is provided via the devicetree; the rest is + * switched off unconditionally. + */ + switch (i < GPP_CLK_OUTPUT_AVAILABLE ? cfg->gpp_clk_config[i] : GPP_CLK_OFF) { + case GPP_CLK_REQ: + gpp_clk_ctl |= GPP_CLK_REQ_EXT(gpp_clk_shift_lut[i]); + break; + case GPP_CLK_OFF: + gpp_clk_ctl |= GPP_CLK_REQ_OFF(gpp_clk_shift_lut[i]); + break; + case GPP_CLK_ON: + default: + gpp_clk_ctl |= GPP_CLK_REQ_ON(gpp_clk_shift_lut[i]); + } + } + + misc_write32(GPP_CLK_CNTRL, gpp_clk_ctl); +} + +static void cgpll_clock_gate_init(void) +{ + uint32_t t; + + t = misc_read32(MISC_CLKGATEDCNTL); + t |= ALINKCLK_GATEOFFEN; + t |= BLINKCLK_GATEOFFEN; + t |= XTAL_PAD_S0I3_TURNOFF_EN; + t |= XTAL_PAD_S3_TURNOFF_EN; + t |= XTAL_PAD_S5_TURNOFF_EN; + misc_write32(MISC_CLKGATEDCNTL, t); + + t = misc_read32(MISC_CGPLL_CONFIGURATION0); + t |= USB_PHY_CMCLK_S3_DIS; + t |= USB_PHY_CMCLK_S0I3_DIS; + t |= USB_PHY_CMCLK_S5_DIS; + misc_write32(MISC_CGPLL_CONFIGURATION0, t); + + t = pm_read32(PM_ISACONTROL); + t |= ABCLKGATEEN; + pm_write32(PM_ISACONTROL, t); +} + +void fch_init(void *chip_info) +{ + i2c_soc_init(); + fch_init_acpi_ports(); + + acpi_pm_gpe_add_events_print_events(); + gpio_add_events(); + + gpp_clk_setup(); + fch_clk_output_48Mhz(); + cgpll_clock_gate_init(); +} + +void fch_final(void *chip_info) +{ +} + +static void set_pci_irqs(void *unused) +{ + /* Write PCI_INTR regs 0xC00/0xC01 */ + write_pci_int_table(); + + /* pirq_data is consumed by `write_pci_cfg_irqs` */ + populate_pirq_data(); + + /* 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); diff --git a/src/soc/amd/morgana/fsp_m_params.c b/src/soc/amd/morgana/fsp_m_params.c new file mode 100644 index 0000000000..e1e8c26caa --- /dev/null +++ b/src/soc/amd/morgana/fsp_m_params.c @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ +/* TODO: See what can be moved to common */ + +#include <amdblocks/apob_cache.h> +#include <amdblocks/ioapic.h> +#include <amdblocks/memmap.h> +#include <assert.h> +#include <console/uart.h> +#include <device/device.h> +#include <fsp/api.h> +#include <soc/platform_descriptors.h> +#include <soc/pci_devs.h> +#include <string.h> +#include <types.h> +#include <vendorcode/amd/fsp/morgana/FspUsb.h> +#include "chip.h" + +__weak void mb_pre_fspm(FSP_M_CONFIG *mcfg) +{ +} + +static void fill_dxio_descriptors(FSP_M_CONFIG *mcfg, + const fsp_dxio_descriptor *descs, size_t num) +{ + size_t i; + + ASSERT_MSG(num <= FSPM_UPD_DXIO_DESCRIPTOR_COUNT, + "Too many DXIO descriptors provided."); + + for (i = 0; i < num; i++) { + memcpy(mcfg->dxio_descriptor[i], &descs[i], sizeof(mcfg->dxio_descriptor[0])); + } +} + +static void fill_ddi_descriptors(FSP_M_CONFIG *mcfg, + const fsp_ddi_descriptor *descs, size_t num) +{ + size_t i; + + ASSERT_MSG(num <= FSPM_UPD_DDI_DESCRIPTOR_COUNT, + "Too many DDI descriptors provided."); + + for (i = 0; i < num; i++) { + memcpy(&mcfg->ddi_descriptor[i], &descs[i], sizeof(mcfg->ddi_descriptor[0])); + } +} + +static void fsp_fill_pcie_ddi_descriptors(FSP_M_CONFIG *mcfg) +{ + const fsp_dxio_descriptor *fsp_dxio = NULL; + const fsp_ddi_descriptor *fsp_ddi = NULL; + size_t num_dxio = 0; + size_t num_ddi = 0; + + mainboard_get_dxio_ddi_descriptors(&fsp_dxio, &num_dxio, + &fsp_ddi, &num_ddi); + fill_dxio_descriptors(mcfg, fsp_dxio, num_dxio); + fill_ddi_descriptors(mcfg, fsp_ddi, num_ddi); +} + +static void fsp_assign_ioapic_upds(FSP_M_CONFIG *mcfg) +{ + mcfg->gnb_ioapic_base = GNB_IO_APIC_ADDR; + mcfg->gnb_ioapic_id = GNB_IOAPIC_ID; + mcfg->fch_ioapic_id = FCH_IOAPIC_ID; +} + +void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version) +{ + FSP_M_CONFIG *mcfg = &mupd->FspmConfig; + const struct soc_amd_morgana_config *config = config_of_soc(); + + mupd->FspmArchUpd.NvsBufferPtr = (uintptr_t)soc_fill_apob_cache(); + + mcfg->pci_express_base_addr = CONFIG_ECAM_MMCONF_BASE_ADDRESS; + mcfg->tseg_size = CONFIG_SMM_TSEG_SIZE; + mcfg->serial_port_base = uart_platform_base(CONFIG_UART_FOR_CONSOLE); + mcfg->serial_port_use_mmio = CONFIG(DRIVERS_UART_8250MEM); + mcfg->serial_port_baudrate = get_uart_baudrate(); + mcfg->serial_port_refclk = uart_platform_refclk(); + + /* 0 is default */ + mcfg->ccx_down_core_mode = config->downcore_mode; + mcfg->ccx_disable_smt = config->disable_smt; + + /* when stt_control isn't 1, FSP will ignore the other stt values */ + mcfg->stt_control = config->stt_control; + mcfg->stt_pcb_sensor_count = config->stt_pcb_sensor_count; + mcfg->stt_min_limit = config->stt_min_limit; + mcfg->stt_m1 = config->stt_m1; + mcfg->stt_m2 = config->stt_m2; + mcfg->stt_m3 = config->stt_m3; + mcfg->stt_m4 = config->stt_m4; + mcfg->stt_m5 = config->stt_m5; + mcfg->stt_m6 = config->stt_m6; + mcfg->stt_c_apu = config->stt_c_apu; + mcfg->stt_c_gpu = config->stt_c_gpu; + mcfg->stt_c_hs2 = config->stt_c_hs2; + mcfg->stt_alpha_apu = config->stt_alpha_apu; + mcfg->stt_alpha_gpu = config->stt_alpha_gpu; + mcfg->stt_alpha_hs2 = config->stt_alpha_hs2; + mcfg->stt_skin_temp_apu = config->stt_skin_temp_apu; + mcfg->stt_skin_temp_gpu = config->stt_skin_temp_gpu; + mcfg->stt_skin_temp_hs2 = config->stt_skin_temp_hs2; + mcfg->stt_error_coeff = config->stt_error_coeff; + mcfg->stt_error_rate_coefficient = config->stt_error_rate_coefficient; + + /* all following fields being 0 is a valid config */ + mcfg->stapm_boost = config->stapm_boost; + mcfg->stapm_time_constant = config->stapm_time_constant_s; + mcfg->apu_only_sppt_limit = config->apu_only_sppt_limit; + mcfg->sustained_power_limit = config->sustained_power_limit_mW; + mcfg->fast_ppt_limit = config->fast_ppt_limit_mW; + mcfg->slow_ppt_limit = config->slow_ppt_limit_mW; + mcfg->slow_ppt_time_constant = config->slow_ppt_time_constant_s; + mcfg->thermctl_limit = config->thermctl_limit_degreeC; + + /* 0 is default */ + mcfg->smartshift_enable = config->smartshift_enable; + + /* 0 is default */ + mcfg->system_configuration = config->system_configuration; + + /* when cppc_ctrl is 0 the other values won't be used */ + mcfg->cppc_ctrl = config->cppc_ctrl; + mcfg->cppc_perf_limit_max_range = config->cppc_perf_limit_max_range; + mcfg->cppc_perf_limit_min_range = config->cppc_perf_limit_min_range; + mcfg->cppc_epp_max_range = config->cppc_epp_max_range; + mcfg->cppc_epp_min_range = config->cppc_epp_min_range; + mcfg->cppc_preferred_cores = config->cppc_preferred_cores; + + /* S0i3 enable */ + mcfg->s0i3_enable = config->s0ix_enable; + mcfg->iommu_support = is_devfn_enabled(IOMMU_DEVFN); + + /* voltage regulator telemetry settings */ + mcfg->telemetry_vddcrvddfull_scale_current = + config->telemetry_vddcrvddfull_scale_current_mA; + mcfg->telemetry_vddcrvddoffset = + config->telemetry_vddcrvddoffset; + mcfg->telemetry_vddcrsocfull_scale_current = + config->telemetry_vddcrsocfull_scale_current_mA; + mcfg->telemetry_vddcrsocOffset = + config->telemetry_vddcrsocoffset; + + /* PCIe power vs. speed */ + mcfg->pspp_policy = config->pspp_policy; + + mcfg->enable_nb_azalia = is_dev_enabled(DEV_PTR(gfx_hda)); + mcfg->hda_enable = is_dev_enabled(DEV_PTR(hda)); + + if (config->usb_phy_custom) { + /* devicetree config is const, use local copy */ + static struct usb_phy_config lcl_usb_phy; + lcl_usb_phy = config->usb_phy; + mcfg->usb_phy = &lcl_usb_phy; + mcfg->usb_phy->Version_Major = FSP_USB_STRUCT_MAJOR_VERSION; + mcfg->usb_phy->Version_Minor = FSP_USB_STRUCT_MINOR_VERSION; + mcfg->usb_phy->TableLength = sizeof(struct usb_phy_config); + } else { + mcfg->usb_phy = NULL; + } + + fsp_fill_pcie_ddi_descriptors(mcfg); + fsp_assign_ioapic_upds(mcfg); + mb_pre_fspm(mcfg); +} diff --git a/src/soc/amd/morgana/fsp_s_params.c b/src/soc/amd/morgana/fsp_s_params.c new file mode 100644 index 0000000000..a68647cb1c --- /dev/null +++ b/src/soc/amd/morgana/fsp_s_params.c @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include <acpi/acpi.h> +#include <amdblocks/apob_cache.h> +#include <device/pci.h> +#include <fsp/api.h> +#include <program_loading.h> + +static void fsp_assign_vbios_upds(FSP_S_CONFIG *scfg) +{ + scfg->vbios_buffer = CONFIG(RUN_FSP_GOP) ? PCI_VGA_RAM_IMAGE_START : 0; +} + +void platform_fsp_silicon_init_params_cb(FSPS_UPD *supd) +{ + FSP_S_CONFIG *scfg = &supd->FspsConfig; + + fsp_assign_vbios_upds(scfg); + + /* + * At this point FSP-S has been loaded into RAM. If we were to start loading the APOB + * before FSP-S was loaded, we would introduce contention onto the SPI bus and + * slow down the FSP-S read from SPI. Since FSP-S takes a while to execute and performs + * no SPI operations, we can read the APOB while FSP-S executes. + */ + start_apob_cache_read(); + /* + * We enqueue the payload to be loaded after the APOB. This might cause a bit of + * bus contention when loading uCode and OPROMs, but since those calls happen at + * different points in the boot state machine it's a little harder to sequence all the + * async loading correctly. So in order to keep the complexity down, we enqueue the + * payload preload here. The end goal will be to add uCode and OPROM preloading + * before the payload so that the sequencing is correct. + * + * While FSP-S is executing, it's not currently possible to enqueue other transactions + * because FSP-S doesn't call `thread_yield()`. So the payload will start loading + * right after FSP-S completes. + */ + if (!acpi_is_wakeup_s3()) + payload_preload(); +} diff --git a/src/soc/amd/morgana/fw.cfg b/src/soc/amd/morgana/fw.cfg new file mode 100644 index 0000000000..055aa9c15e --- /dev/null +++ b/src/soc/amd/morgana/fw.cfg @@ -0,0 +1,38 @@ +# PSP fw config file + +FIRMWARE_LOCATION 3rdparty/amd_blobs/morgana/psp + +# type file +AMD_PUBKEY_FILE TypeId0x00_Root.tkn +PSPBTLDR_AB_STAGE1_FILE TypeId0x01_PspBootLoader1.sbin +PSPSECUREOS_FILE TypeId0x02_PspOS.sbin +PSP_SMUFW1_SUB0_FILE TypeId0x08_SmuFirmware.sbin +PSPSECUREDEBUG_FILE TypeId0x09_SDU.stkn +PSPTRUSTLETS_FILE TypeId0x0C_FtpmDrv.csbin +PSP_SMUFW2_SUB0_FILE TypeId0x12_SmuFirmware2.sbin +PSP_SEC_DEBUG_FILE TypeId0x13_PspEarlyUnlock.sbin +PSP_HW_IPCFG_FILE TypeId0x20_HwIpCfg.sbin +PSP_IKEK_FILE TypeId0x21_PspiKek.bin +PSP_SECG0_FILE TypeId0x24_SecPolicy.sbin +PSP_MP2FW0_FILE TypeId0x25_Mp2Fw.sbin +AMD_DRIVER_ENTRIES TypeId0x28_PspSystemDriver.sbin +PSP_S0I3_FILE TypeId0x2D_AgesaRunTimeDrv.sbin +PSP_ABL0_FILE TypeId0x30_AgesaBootloaderU_LPDDR5.sbin +VBIOS_BTLOADER_FILE TypeId0x3C_VbiosBootLoader.sbin +SECURE_POLICY_L1_FILE TypeId0x45_SecPolicytOS.sbin +UNIFIEDUSB_FILE TypeId0x44_UnifiedUsb.sbin +KEYDBBL_FILE TypeId0x50_KeyDbBl.sbin +KEYDB_TOS_FILE TypeId0x51_KeyDbTos.sbin +SPL_TABLE_FILE TypeId0x55_SplTableBl.sbin +MSMU_FILE TypeId0x5A_Msmu.sbin +SPIROM_CONFIG_FILE TypeId0x5C_SpiRomConfig_Dual66.sbin +DMCUB_FILE TypeId0x71_DmcubFw.sbin +PSPBTLDR_AB_FILE TypeId0x73_PspBootLoader2.sbin +TA_IKEK_FILE TypeId0x8D_IkekTa.bin + +# BDT +PSP_PMUI_FILE_SUB0_INS1 TypeId0x64_Appb_Lpddr5Imem1.csbin +PSP_PMUD_FILE_SUB0_INS1 TypeId0x65_Appb_Lpddr5Dmem1.csbin +PSP_PMUI_FILE_SUB0_INS2 TypeId0x64_Appb_Lpddr5Imem2.csbin +PSP_PMUD_FILE_SUB0_INS2 TypeId0x65_Appb_Lpddr5Dmem2.csbin +PSP_MP2CFG_FILE TypeId0x6a_Mp2FwConfig.sbin diff --git a/src/soc/amd/morgana/gpio.c b/src/soc/amd/morgana/gpio.c new file mode 100644 index 0000000000..873d333bca --- /dev/null +++ b/src/soc/amd/morgana/gpio.c @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include <amdblocks/gpio.h> +#include <soc/gpio.h> +#include <types.h> + +/* see the IOMUX function table for the mapping from GPIO number to GEVENT number */ +static const struct soc_amd_event gpio_event_table[] = { + { GPIO_0, GEVENT_21 }, /* GPIO0 may only be used as PWR_BTN_L in ACPI */ + { 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_5 }, + { GPIO_16, GEVENT_12 }, + { GPIO_17, GEVENT_13 }, + { GPIO_18, GEVENT_14 }, + { GPIO_22, GEVENT_3 }, + { GPIO_23, GEVENT_16 }, + { GPIO_24, GEVENT_15 }, + { GPIO_29, GEVENT_9 }, + { GPIO_32, GEVENT_17 }, + { GPIO_40, GEVENT_20 }, + { GPIO_84, GEVENT_18 }, + { GPIO_89, GEVENT_0 }, + { GPIO_90, GEVENT_1 }, + { GPIO_91, GEVENT_6 }, +}; + +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); +} diff --git a/src/soc/amd/morgana/i2c.c b/src/soc/amd/morgana/i2c.c new file mode 100644 index 0000000000..23a38ba54d --- /dev/null +++ b/src/soc/amd/morgana/i2c.c @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include <amdblocks/i2c.h> +#include <console/console.h> +#include <soc/i2c.h> +#include <soc/southbridge.h> +#include "chip.h" + +#if ENV_X86 +static const struct soc_i2c_ctrlr_info i2c_ctrlr[I2C_CTRLR_COUNT] = { + { I2C_MASTER_MODE, APU_I2C0_BASE, "I2C0" }, + { I2C_MASTER_MODE, APU_I2C1_BASE, "I2C1" }, + { I2C_MASTER_MODE, APU_I2C2_BASE, "I2C2" }, + { I2C_MASTER_MODE, APU_I2C3_BASE, "I2C3" } +}; +#else +static struct soc_i2c_ctrlr_info i2c_ctrlr[I2C_CTRLR_COUNT] = { + { I2C_MASTER_MODE, 0, "" }, + { I2C_MASTER_MODE, 0, "" }, + { I2C_MASTER_MODE, 0, "" }, + { I2C_MASTER_MODE, 0, "" } +}; + +void i2c_set_bar(unsigned int bus, uintptr_t bar) +{ + if (bus >= ARRAY_SIZE(i2c_ctrlr)) { + printk(BIOS_ERR, "Error: i2c index out of bounds: %u.", bus); + return; + } + + i2c_ctrlr[bus].bar = bar; +} +#endif + +void soc_i2c_misc_init(unsigned int bus, const struct dw_i2c_bus_config *cfg) +{ + const struct soc_amd_morgana_config *config = config_of_soc(); + + if (bus >= ARRAY_SIZE(config->i2c_pad)) + return; + + fch_i23c_pad_init(bus, cfg->speed, &config->i2c_pad[bus]); +} + +const struct soc_i2c_ctrlr_info *soc_get_i2c_ctrlr_info(size_t *num_ctrlrs) +{ + *num_ctrlrs = ARRAY_SIZE(i2c_ctrlr); + return i2c_ctrlr; +} + +const struct dw_i2c_bus_config *soc_get_i2c_bus_config(size_t *num_buses) +{ + const struct soc_amd_morgana_config *config = config_of_soc(); + + *num_buses = ARRAY_SIZE(config->i2c); + return config->i2c; +} diff --git a/src/soc/amd/morgana/include/soc/acpi.h b/src/soc/amd/morgana/include/soc/acpi.h new file mode 100644 index 0000000000..132bac45c1 --- /dev/null +++ b/src/soc/amd/morgana/include/soc/acpi.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* TODO: Move to common */ + +#ifndef AMD_MORGANA_ACPI_H +#define AMD_MORGANA_ACPI_H + +#include <acpi/acpi.h> +#include <amdblocks/acpi.h> +#include <device/device.h> +#include <stdint.h> + +#define ACPI_SCI_IRQ 9 + +/* RTC Registers */ +#define RTC_DATE_ALARM 0x0d +#define RTC_ALT_CENTURY 0x32 +#define RTC_CENTURY 0x48 + +uintptr_t agesa_write_acpi_tables(const struct device *device, uintptr_t current, + acpi_rsdp_t *rsdp); + +#endif /* AMD_MORGANA_ACPI_H */ diff --git a/src/soc/amd/morgana/include/soc/amd_pci_int_defs.h b/src/soc/amd/morgana/include/soc/amd_pci_int_defs.h new file mode 100644 index 0000000000..2835c09e69 --- /dev/null +++ b/src/soc/amd/morgana/include/soc/amd_pci_int_defs.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#ifndef AMD_MORGANA_AMD_PCI_INT_DEFS_H +#define AMD_MORGANA_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 */ +#define PIRQ_MISC0 0x09 /* Miscellaneous0 IRQ Settings */ +#define PIRQ_HPET_L 0x0a /* HPET TMR{0..2}_CONF_CAP_H[0:7] */ +#define PIRQ_HPET_H 0x0b /* HPET TMR{0..2}_CONF_CAP_H[15:8] */ +#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 */ +#define PIRQ_ASF 0x12 /* ASF */ +/* 0x13-0x15 reserved */ +#define PIRQ_PMON 0x16 /* Performance Monitor */ +#define PIRQ_SD 0x17 /* SD */ +/* 0x18-0x19 reserved */ +#define PIRQ_SDIO 0x1a /* SDIO */ +/* 0x1b-0x1f reserved */ +#define PIRQ_CIR 0x20 /* CIR, no IRQ connected */ +#define PIRQ_GPIOA 0x21 /* GPIOa from PAD_FANIN0 */ +#define PIRQ_GPIOB 0x22 /* GPIOb from PAD_FANOUT0 */ +#define PIRQ_GPIOC 0x23 /* GPIOc no IRQ connected */ +/* 0x24-0x42 reserved */ +#define PIRQ_EMMC 0x43 /* eMMC */ +/* 0x44-0x4f reserved */ +#define PIRQ_GPP0 0x50 /* GPPInt0 */ +#define PIRQ_GPP1 0x51 /* GPPInt1 */ +#define PIRQ_GPP2 0x52 /* GPPInt2 */ +#define PIRQ_GPP3 0x53 /* GPPInt3 */ +/* 0x54-0x61 reserved */ +#define PIRQ_GPIO 0x62 /* GPIO Controller Interrupt */ +/* 0x63-0x6f reserved */ +#define PIRQ_I2C0 0x70 /* I2C0 */ +#define PIRQ_I2C1 0x71 /* I2C1 */ +#define PIRQ_I2C2 0x72 /* I2C2 */ +#define PIRQ_I2C3 0x73 /* I2C3 */ +#define PIRQ_UART0 0x74 /* UART0 */ +#define PIRQ_UART1 0x75 /* UART1 */ +#define PIRQ_I2C4 0x76 /* I2C4 */ +#define PIRQ_UART4 0x77 /* UART4 */ +#define PIRQ_UART2 0x78 /* UART2 */ +#define PIRQ_UART3 0x79 /* UART3 */ + +#endif /* AMD_MORGANA_AMD_PCI_INT_DEFS_H */ diff --git a/src/soc/amd/morgana/include/soc/aoac_defs.h b/src/soc/amd/morgana/include/soc/aoac_defs.h new file mode 100644 index 0000000000..c52f502a83 --- /dev/null +++ b/src/soc/amd/morgana/include/soc/aoac_defs.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#ifndef AMD_MORGANA_AOAC_DEFS_H +#define AMD_MORGANA_AOAC_DEFS_H + +/* FCH AOAC device offsets for AOAC_DEV_D3_CTL/AOAC_DEV_D3_STATE */ +#define FCH_AOAC_DEV_CLK_GEN 0 +#define FCH_AOAC_DEV_I2C0 5 +#define FCH_AOAC_DEV_I2C1 6 +#define FCH_AOAC_DEV_I2C2 7 +#define FCH_AOAC_DEV_I2C3 8 +#define FCH_AOAC_DEV_I2C4 9 +#define FCH_AOAC_DEV_I2C5 10 +#define FCH_AOAC_DEV_UART0 11 +#define FCH_AOAC_DEV_UART1 12 +#define FCH_AOAC_DEV_UART2 16 +#define FCH_AOAC_DEV_AMBA 17 +#define FCH_AOAC_DEV_UART4 20 +#define FCH_AOAC_DEV_UART3 26 +#define FCH_AOAC_DEV_ESPI 27 +#define FCH_AOAC_DEV_EMMC 28 + +#endif /* AMD_MORGANA_AOAC_DEFS_H */ diff --git a/src/soc/amd/morgana/include/soc/cpu.h b/src/soc/amd/morgana/include/soc/cpu.h new file mode 100644 index 0000000000..ac85861dca --- /dev/null +++ b/src/soc/amd/morgana/include/soc/cpu.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef AMD_MORGANA_CPU_H +#define AMD_MORGANA_CPU_H + +#define MORGANA_A0_CPUID 0x008a0f00 /* TODO: Update for Morgana */ + +#endif /* AMD_MORGANA_CPU_H */ diff --git a/src/soc/amd/morgana/include/soc/data_fabric.h b/src/soc/amd/morgana/include/soc/data_fabric.h new file mode 100644 index 0000000000..eba4cd8b98 --- /dev/null +++ b/src/soc/amd/morgana/include/soc/data_fabric.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#ifndef AMD_MORGANA_DATA_FABRIC_H +#define AMD_MORGANA_DATA_FABRIC_H + +#include <types.h> + +/* SoC-specific bits in D18F0_MMIO_CTRL0 */ +#define DF_MMIO_NP BIT(16) + +#define IOMS0_FABRIC_ID 9 + +#define NUM_NB_MMIO_REGS 8 + +void data_fabric_set_mmio_np(void); + +#endif /* AMD_MORGANA_DATA_FABRIC_H */ diff --git a/src/soc/amd/morgana/include/soc/espi.h b/src/soc/amd/morgana/include/soc/espi.h new file mode 100644 index 0000000000..d8217c6eab --- /dev/null +++ b/src/soc/amd/morgana/include/soc/espi.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#ifndef AMD_MORGANA_ESPI_H +#define AMD_MORGANA_ESPI_H + +void espi_switch_to_spi1_pads(void); + +#endif /* AMD_MORGANA_ESPI_H */ diff --git a/src/soc/amd/morgana/include/soc/gpio.h b/src/soc/amd/morgana/include/soc/gpio.h new file mode 100644 index 0000000000..87db27d5d1 --- /dev/null +++ b/src/soc/amd/morgana/include/soc/gpio.h @@ -0,0 +1,326 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#ifndef AMD_MORGANA_GPIO_H +#define AMD_MORGANA_GPIO_H + +#define GPIO_DEVICE_NAME "AMD0030" +#define GPIO_DEVICE_DESC "GPIO Controller" + +#ifndef __ACPI__ +#include <soc/iomap.h> +#include <amdblocks/gpio.h> +#endif /* !__ACPI__ */ + +#include <amdblocks/gpio_defs.h> + +/* The following sections describe only the GPIOs defined for this SOC */ + +#define SOC_GPIO_TOTAL_PINS 158 + +/* Bank 0: GPIO_0 - GPIO_63 */ +#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_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_26 26 +#define GPIO_27 27 +#define GPIO_29 29 +#define GPIO_30 30 +#define GPIO_31 31 +#define GPIO_32 32 +#define GPIO_38 38 +#define GPIO_39 39 +#define GPIO_40 40 +#define GPIO_42 42 + +/* Bank 1: GPIO_64 - GPIO_127 */ +#define GPIO_67 67 +#define GPIO_68 68 +#define GPIO_69 69 +#define GPIO_70 70 +#define GPIO_74 74 +#define GPIO_75 75 +#define GPIO_76 76 +#define GPIO_77 77 +#define GPIO_78 78 +#define GPIO_79 79 +#define GPIO_80 80 +#define GPIO_81 81 +#define GPIO_84 84 +#define GPIO_85 85 +#define GPIO_86 86 +#define GPIO_89 89 +#define GPIO_90 90 +#define GPIO_91 91 +#define GPIO_92 92 +#define GPIO_104 104 +#define GPIO_105 105 +#define GPIO_106 106 +#define GPIO_107 107 +#define GPIO_113 113 +#define GPIO_114 114 +#define GPIO_115 115 +#define GPIO_116 116 + +/* Bank 2: GPIO_128 - GPIO_191 */ +#define GPIO_130 130 +#define GPIO_131 131 +#define GPIO_132 132 +#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_153 153 +#define GPIO_154 154 +#define GPIO_155 155 +#define GPIO_156 156 +#define GPIO_157 157 + +/* IOMUX function names and values */ +#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 1 +#define GPIO_6_IOMUX_GPIOxx 0 +#define GPIO_6_IOMUX_DEVSLP1 1 +#define GPIO_6_IOMUX_MDIO0_SCL 2 +#define GPIO_7_IOMUX_GPIOxx 0 +#define GPIO_7_IOMUX_SVI_RST_L 1 +#define GPIO_8_IOMUX_GPIOxx 0 +#define GPIO_8_IOMUX_TMU_CLK_OUT0 1 +#define GPIO_8_IOMUX_TMU_CLK_OUT1 2 +#define GPIO_9_IOMUX_GPIOxx 0 +/* GPIO 9 IOMUX == 1 is also GPIOxx */ +#define GPIO_9_IOMUX_MDIO2_SCL 2 +#define GPIO_10_IOMUX_GPIOxx 0 +#define GPIO_10_IOMUX_S0A3_GPIO 1 +#define GPIO_11_IOMUX_GPIOxx 0 +#define GPIO_11_IOMUX_BLINK 1 +#define GPIO_11_IOMUX_MDIO3_SDA 2 +#define GPIO_12_IOMUX_LLB_L 0 +#define GPIO_12_IOMUX_GPIOxx 1 +#define GPIO_12_IOMUX_LPC_PME_L 2 +#define GPIO_13_IOMUX_USB_SBTX_0 0 +#define GPIO_13_IOMUX_GPIOxx 1 +#define GPIO_14_IOMUX_USB_SBTX_1 0 +#define GPIO_14_IOMUX_GPIOxx 1 +#define GPIO_16_IOMUX_USB_OC0_L 0 +#define GPIO_16_IOMUX_GPIOxx 1 +#define GPIO_17_IOMUX_USB_OC1_L 0 +#define GPIO_17_IOMUX_GPIOxx 1 +#define GPIO_18_IOMUX_USB_OC2_L 0 +#define GPIO_18_IOMUX_GPIOxx 1 +#define GPIO_19_IOMUX_SMBUS1_SCL 0 +#define GPIO_19_IOMUX_I2C3_SCL 1 +#define GPIO_19_IOMUX_I3C3_SCL 2 +#define GPIO_19_IOMUX_GPIOxx 3 +#define GPIO_20_IOMUX_SMBUS1_SDA 0 +#define GPIO_20_IOMUX_I2C3_SDA 1 +#define GPIO_20_IOMUX_I3C3_SDA 2 +#define GPIO_20_IOMUX_GPIOxx 3 +#define GPIO_21_IOMUX_ESPI_RESET_L 0 +#define GPIO_21_IOMUX_KBRST_L 1 +#define GPIO_21_IOMUX_GPIOxx 2 +#define GPIO_22_IOMUX_LDRQ0_L 0 +#define GPIO_22_IOMUX_ESPI_ALERT_D1 1 +#define GPIO_22_IOMUX_GPIOxx 2 +#define GPIO_22_IOMUX_SD0_CMD 3 +#define GPIO_23_IOMUX_AC_PRES 0 +#define GPIO_23_IOMUX_GPIOxx 1 +#define GPIO_23_IOMUX_MDIO2_SDA 2 +#define GPIO_24_IOMUX_USB_OC3_L 0 +#define GPIO_24_IOMUX_GPIOxx 1 +#define GPIO_26_IOMUX_PCIE_RST0_L 0 +#define GPIO_26_IOMUX_GPIOxx 1 +#define GPIO_27_IOMUX_GPIOxx 0 +#define GPIO_27_IOMUX_PCIE_RST1_L 1 +#define GPIO_29_IOMUX_SPI_TPM_CS_L 0 +#define GPIO_29_IOMUX_GPIOxx 1 +#define GPIO_30_IOMUX_SPI_CS2_L 0 +#define GPIO_30_IOMUX_ESPI_CS_L 1 +#define GPIO_30_IOMUX_GPIOxx 2 +#define GPIO_31_IOMUX_SPI_CS3_L 0 +#define GPIO_31_IOMUX_GPIOxx 1 +#define GPIO_32_IOMUX_GPIOxx 0 +#define GPIO_32_IOMUX_LPC_RST_L 1 +#define GPIO_32_IOMUX_MDIO3_SCL 2 +#define GPIO_38_IOMUX_CLK_REQ5_L 0 +#define GPIO_38_IOMUX_GPIOxx 1 +#define GPIO_38_IOMUX_MDIO1_SDA 2 +#define GPIO_39_IOMUX_CLK_REQ6_L 0 +#define GPIO_39_IOMUX_GPIOxx 1 +#define GPIO_39_IOMUX_MDIO1_SCL 2 +#define GPIO_40_IOMUX_GPIOxx 0 +/* GPIO 40 IOMUX == 1 is also GPIOxx */ +#define GPIO_40_IOMUX_MDIO0_SDA 2 +#define GPIO_42_IOMUX_GPIOxx 0 +#define GPIO_67_IOMUX_SPI_ROM_REQ 0 +#define GPIO_67_IOMUX_GPIOxx 1 +#define GPIO_68_IOMUX_SPI1_DAT2 0 +#define GPIO_68_IOMUX_GPIOxx 1 +#define GPIO_68_IOMUX_SERIRQ 2 +#define GPIO_68_IOMUX_SD0_DATA3 3 +#define GPIO_69_IOMUX_SPI1_DAT3 0 +#define GPIO_69_IOMUX_GPIOxx 1 +#define GPIO_69_IOMUX_SD0_CLK 2 +#define GPIO_70_IOMUX_SPI2_CLK 0 +#define GPIO_70_IOMUX_GPIOxx 1 +#define GPIO_74_IOMUX_SPI1_CS1_L 0 +#define GPIO_74_IOMUX_GPIOxx 1 +#define GPIO_74_IOMUX_GFX10_CAC_IPIO0 2 +#define GPIO_75_IOMUX_SPI2_CS1_L 0 +#define GPIO_75_IOMUX_LPCCLK1 1 +#define GPIO_75_IOMUX_GPIOxx 2 +#define GPIO_76_IOMUX_SPI_ROM_GNT 0 +#define GPIO_76_IOMUX_GPIOxx 1 +#define GPIO_77_IOMUX_SPI1_CLK 0 +#define GPIO_77_IOMUX_GPIOxx 1 +/* GPIO 77 IOMUX == 2 is also GPIOxx */ +#define GPIO_77_IOMUX_SD0_DATA0 3 +#define GPIO_78_IOMUX_SPI1_CS2_L 0 +#define GPIO_78_IOMUX_GPIOxx 1 +#define GPIO_78_IOMUX_GFX10_CAC_IPIO1 2 +#define GPIO_78_IOMUX_SD0_DATA1 3 +#define GPIO_79_IOMUX_SPI1_CS3_L 0 +#define GPIO_79_IOMUX_GPIOxx 1 +#define GPIO_79_IOMUX_LPC_CLKRUN_L 2 +#define GPIO_80_IOMUX_SPI1_DAT1 0 +#define GPIO_80_IOMUX_GPIOxx 1 +/* GPIO 80 IOMUX == 2 is also GPIOxx */ +#define GPIO_80_IOMUX_SD0_DATA2 3 +#define GPIO_81_IOMUX_SPI1_DAT0 0 +#define GPIO_81_IOMUX_GPIOxx 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 0 +#define GPIO_86_IOMUX_LPC_SMI_L 1 +#define GPIO_89_IOMUX_GENINT1_L 0 +#define GPIO_89_IOMUX_PSP_INTR0 1 +#define GPIO_89_IOMUX_GPIOxx 2 +#define GPIO_90_IOMUX_GENINT2_L 0 +#define GPIO_90_IOMUX_PSP_INTR1 1 +#define GPIO_90_IOMUX_GPIOxx 2 +#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_104_IOMUX_SPI2_DAT0 0 +#define GPIO_104_IOMUX_GPIOxx 1 +#define GPIO_105_IOMUX_SPI2_DAT1 0 +#define GPIO_105_IOMUX_GPIOxx 1 +#define GPIO_106_IOMUX_SPI2_DAT2 0 +#define GPIO_106_IOMUX_GPIOxx 1 +#define GPIO_107_IOMUX_SPI2_DAT3 0 +#define GPIO_107_IOMUX_GPIOxx 1 +#define GPIO_113_IOMUX_SMBUS0_SCL 0 +#define GPIO_113_IOMUX_I2C2_SCL 1 +#define GPIO_113_IOMUX_I3C2_SCL 2 +#define GPIO_113_IOMUX_GPIOxx 3 +#define GPIO_114_IOMUX_SMBUS0_SDA 0 +#define GPIO_114_IOMUX_I2C2_SDA 1 +#define GPIO_114_IOMUX_I3C2_SDA 2 +#define GPIO_114_IOMUX_GPIOxx 3 +#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_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_REQ4_L 0 +#define GPIO_132_IOMUX_OSCIN 1 +#define GPIO_132_IOMUX_GPIOxx 2 +#define GPIO_135_IOMUX_GPIOxx 0 +#define GPIO_135_IOMUX_UART2_CTS_L 1 +#define GPIO_135_IOMUX_UART3_TXD 2 +#define GPIO_136_IOMUX_GPIOxx 0 +#define GPIO_136_IOMUX_UART2_RXD 1 +#define GPIO_137_IOMUX_GPIOxx 0 +#define GPIO_137_IOMUX_UART2_RTS_L 1 +#define GPIO_137_IOMUX_UART3_RXD 2 +#define GPIO_138_IOMUX_GPIOxx 0 +#define GPIO_138_IOMUX_UART2_TXD 1 +#define GPIO_139_IOMUX_GPIOxx 0 +#define GPIO_139_IOMUX_UART2_INTR 1 +#define GPIO_140_IOMUX_GPIOxx 0 +#define GPIO_140_IOMUX_UART0_CTS_L 1 +#define GPIO_140_IOMUX_UART1_TXD 2 +#define GPIO_141_IOMUX_GPIOxx 0 +#define GPIO_141_IOMUX_UART0_RXD 1 +#define GPIO_142_IOMUX_GPIOxx 0 +#define GPIO_142_IOMUX_UART0_RTS_L 1 +#define GPIO_142_IOMUX_UART1_RXD 2 +#define GPIO_143_IOMUX_GPIOxx 0 +#define GPIO_143_IOMUX_UART0_TXD 1 +#define GPIO_144_IOMUX_GPIOxx 0 +#define GPIO_144_IOMUX_SHUTDOWN_L 1 +#define GPIO_144_IOMUX_UART0_INTR 2 +#define GPIO_145_IOMUX_I2C0_SCL 0 +#define GPIO_145_IOMUX_I3C0_SCL 1 +#define GPIO_145_IOMUX_GPIOxx 2 +#define GPIO_146_IOMUX_I2C0_SDA 0 +#define GPIO_146_IOMUX_I3C0_SDA 1 +#define GPIO_146_IOMUX_GPIOxx 2 +#define GPIO_147_IOMUX_I2C1_SCL 0 +#define GPIO_147_IOMUX_I3C1_SCL 1 +#define GPIO_147_IOMUX_GPIOxx 2 +#define GPIO_148_IOMUX_I2C1_SDA 0 +#define GPIO_148_IOMUX_I3C1_SDA 1 +#define GPIO_148_IOMUX_GPIOxx 2 +#define GPIO_153_IOMUX_GPIOxx 0 +#define GPIO_153_IOMUX_UART4_CTS_L 1 +#define GPIO_154_IOMUX_GPIOxx 0 +#define GPIO_154_IOMUX_UART4_RTS_L 1 +#define GPIO_155_IOMUX_GPIOxx 0 +#define GPIO_155_IOMUX_UART4_RXD 1 +#define GPIO_156_IOMUX_GPIOxx 0 +#define GPIO_156_IOMUX_UART4_TXD 1 +#define GPIO_157_IOMUX_GPIOxx 0 +#define GPIO_157_IOMUX_UART4_INTR 1 + +#endif /* AMD_MORGANA_GPIO_H */ diff --git a/src/soc/amd/morgana/include/soc/i2c.h b/src/soc/amd/morgana/include/soc/i2c.h new file mode 100644 index 0000000000..10b7249006 --- /dev/null +++ b/src/soc/amd/morgana/include/soc/i2c.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#ifndef AMD_MORGANA_I2C_H +#define AMD_MORGANA_I2C_H + +#include <soc/gpio.h> +#include <types.h> + +#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 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 i2c_set_bar(unsigned int bus, uintptr_t bar); + +#endif /* AMD_MORGANA_I2C_H */ diff --git a/src/soc/amd/morgana/include/soc/iomap.h b/src/soc/amd/morgana/include/soc/iomap.h new file mode 100644 index 0000000000..53b7bc2f42 --- /dev/null +++ b/src/soc/amd/morgana/include/soc/iomap.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#ifndef AMD_MORGANA_IOMAP_H +#define AMD_MORGANA_IOMAP_H + +#define I2C_MASTER_DEV_COUNT 4 +#define I2C_MASTER_START_INDEX 0 +#define I2C_PERIPHERAL_DEV_COUNT 0 /* TODO: Only master for now. */ +#define I2C_CTRLR_COUNT (I2C_MASTER_DEV_COUNT + I2C_PERIPHERAL_DEV_COUNT) + +#if ENV_X86 + +/* MMIO Ranges */ +/* IO_APIC_ADDR defined in arch/x86 0xfec00000 */ +#define GNB_IO_APIC_ADDR 0xfec01000 +#define SPI_BASE_ADDRESS 0xfec10000 + +/* FCH AL2AHB Registers */ +#define ALINK_AHB_ADDRESS 0xfedc0000 + +#define APU_I2C0_BASE 0xfedc2000 +#define APU_I2C1_BASE 0xfedc3000 +#define APU_I2C2_BASE 0xfedc4000 +#define APU_I2C3_BASE 0xfedc5000 + +#define APU_DMAC0_BASE 0xfedc7000 +#define APU_DMAC1_BASE 0xfedc8000 +#define APU_UART0_BASE 0xfedc9000 +#define APU_UART1_BASE 0xfedca000 +#define APU_DMAC2_BASE 0xfedcc000 +#define APU_DMAC3_BASE 0xfedcd000 +#define APU_UART2_BASE 0xfedce000 +#define APU_UART3_BASE 0xfedcf000 +#define APU_DMAC4_BASE 0xfedd0000 +#define APU_UART4_BASE 0xfedd1000 + +#define APU_EMMC_BASE 0xfedd5000 +#define APU_EMMC_CONFIG_BASE 0xfedd5800 + +#endif /* ENV_X86 */ + +#define FLASH_BASE_ADDR ((0xffffffff - CONFIG_ROM_SIZE) + 1) + +/* I/O Ranges */ +#define ACPI_IO_BASE 0x0400 +#define ACPI_PM_EVT_BLK (ACPI_IO_BASE + 0x00) +#define ACPI_PM1_STS (ACPI_PM_EVT_BLK + 0x00) +#define ACPI_PM1_EN (ACPI_PM_EVT_BLK + 0x02) +#define ACPI_PM1_CNT_BLK (ACPI_IO_BASE + 0x04) +#define ACPI_PM_TMR_BLK (ACPI_IO_BASE + 0x08) +#define ACPI_CPU_CONTROL (ACPI_IO_BASE + 0x10) +#define ACPI_GPE0_BLK (ACPI_IO_BASE + 0x20) +#define ACPI_GPE0_STS (ACPI_GPE0_BLK + 0x00) +#define ACPI_GPE0_EN (ACPI_GPE0_BLK + 0x04) +#define SMB_BASE_ADDR 0x0b00 + +#endif /* AMD_MORGANA_IOMAP_H */ diff --git a/src/soc/amd/morgana/include/soc/lpc.h b/src/soc/amd/morgana/include/soc/lpc.h new file mode 100644 index 0000000000..ab5f429bee --- /dev/null +++ b/src/soc/amd/morgana/include/soc/lpc.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#ifndef AMD_MORGANA_LPC_H +#define AMD_MORGANA_LPC_H + +/* LPC_MISC_CONTROL_BITS at D14F3x078 */ + +#define LPC_LDRQ0_PU_EN BIT(10) +#define LPC_LDRQ0_PD_EN BIT(9) + +#define SPI_BASE_ADDRESS_REGISTER 0xa0 +#define SPI_BASE_ALIGNMENT BIT(8) +#define SPI_BASE_RESERVED (BIT(5) | BIT(6) | BIT(7)) +#define PSP_SPI_MMIO_SEL BIT(4) +#define ROUTE_TPM_2_SPI BIT(3) +#define SPI_ABORT_ENABLE BIT(2) +#define SPI_ROM_ENABLE BIT(1) +#define SPI_ROM_ALT_ENABLE BIT(0) +#define SPI_PRESERVE_BITS (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4)) + +#endif /* AMD_MORGANA_LPC_H */ diff --git a/src/soc/amd/morgana/include/soc/msr.h b/src/soc/amd/morgana/include/soc/msr.h new file mode 100644 index 0000000000..0a6a7995d5 --- /dev/null +++ b/src/soc/amd/morgana/include/soc/msr.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#ifndef AMD_MORGANA_MSR_H +#define AMD_MORGANA_MSR_H + +/* MSRC001_00[6B:64] P-state [7:0] bit definitions */ +#define PSTATE_DEF_HI_ENABLE_SHIFT 31 +#define PSTATE_DEF_HI_ENABLE_MASK (0x1 << PSTATE_DEF_HI_ENABLE_SHIFT) +#define PSTATE_DEF_LO_CUR_DIV_SHIFT 30 +#define PSTATE_DEF_LO_CUR_DIV_MASK (0x3 << PSTATE_DEF_LO_CUR_DIV_SHIFT) +#define PSTATE_DEF_LO_CUR_VAL_SHIFT 22 +#define PSTATE_DEF_LO_CUR_VAL_MASK (0xFF << PSTATE_DEF_LO_CUR_VAL_SHIFT) +#define PSTATE_DEF_LO_CORE_VID_SHIFT 14 +#define PSTATE_DEF_LO_CORE_VID_MASK (0xFF << PSTATE_DEF_LO_CORE_VID_SHIFT) +#define PSTATE_DEF_LO_FREQ_DIV_SHIFT 8 +#define PSTATE_DEF_LO_FREQ_DIV_MASK (0x3F << PSTATE_DEF_LO_FREQ_DIV_SHIFT) +#define PSTATE_DEF_LO_FREQ_DIV_MIN 0x8 +#define PSTATE_DEF_LO_EIGHTH_STEP_MAX 0x1A +#define PSTATE_DEF_LO_FREQ_DIV_MAX 0x3E +#define PSTATE_DEF_LO_FREQ_MUL_SHIFT 0 +#define PSTATE_DEF_LO_FREQ_MUL_MASK (0xFF << PSTATE_DEF_LO_FREQ_MUL_SHIFT) +#define PSTATE_DEF_LO_CORE_FREQ_BASE 25 + +/* Value defined in Serial VID Interface 3.0 spec (#56413, NDA only) */ +#define SERIAL_VID_DECODE_MICROVOLTS 5000 +#define SERIAL_VID_BASE_MICROVOLTS 245000L + +#define MSR_CPPC_CAPABILITY_1 0xc00102b0 +#define SHIFT_CPPC_CAPABILITY_1_HIGHEST_PERF 24 +#define SHIFT_CPPC_CAPABILITY_1_NOMINAL_PERF 16 +#define SHIFT_CPPC_CAPABILITY_1_LOW_NON_LIN_PERF 8 +#define SHIFT_CPPC_CAPABILITY_1_LOWEST_PERF 0 + +#define MSR_CPPC_ENABLE 0xc00102b1 +#define MSR_CPPC_REQUEST 0xc00102b3 +#define SHIFT_CPPC_REQUEST_ENERGY_PERF_PREF 24 +#define SHIFT_CPPC_REQUEST_DES_PERF 16 +#define SHIFT_CPPC_REQUEST_MIN_PERF 8 +#define SHIFT_CPPC_REQUEST_MAX_PERF 0 + +#define MSR_CPPC_STATUS 0xc00102b4 + +#define MSR_MAX_PERFORMANCE_FREQUENCY_CLOCK_COUNT 0xe7 +#define MSR_ACTUAL_PERFORMANCE_FREQUENCY_CLOCK_COUNT 0xe8 + +#endif /* AMD_MORGANA_MSR_H */ diff --git a/src/soc/amd/morgana/include/soc/nvs.h b/src/soc/amd/morgana/include/soc/nvs.h new file mode 100644 index 0000000000..572c776a89 --- /dev/null +++ b/src/soc/amd/morgana/include/soc/nvs.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* TODO: Update for Morgana */ + +/* + * NOTE: The layout of the global_nvs structure below must match the layout + * in soc/soc/amd/morgana/acpi/globalnvs.asl !!! + * + */ + +#ifndef AMD_MORGANA_NVS_H +#define AMD_MORGANA_NVS_H + +#include <stdint.h> + +struct __packed global_nvs { + /* Miscellaneous */ + uint8_t unused_was_pcnt; /* 0x00 - Processor Count */ + uint8_t lids; /* 0x01 - LID State */ + uint8_t unused_was_pwrs; /* 0x02 - AC Power State */ + uint32_t cbmc; /* 0x03 - 0x06 - coreboot Memory Console */ + uint64_t pm1i; /* 0x07 - 0x0e - System Wake Source - PM1 Index */ + uint64_t gpei; /* 0x0f - 0x16 - GPE Wake Source */ + uint8_t tmps; /* 0x17 - Temperature Sensor ID */ + uint8_t tcrt; /* 0x18 - Critical Threshold */ + uint8_t tpsv; /* 0x19 - Passive Threshold */ +}; + +#endif /* AMD_MORGANA_NVS_H */ diff --git a/src/soc/amd/morgana/include/soc/pci_devs.h b/src/soc/amd/morgana/include/soc/pci_devs.h new file mode 100644 index 0000000000..4eb4e113cd --- /dev/null +++ b/src/soc/amd/morgana/include/soc/pci_devs.h @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#ifndef AMD_MORGANA_PCI_DEVS_H +#define AMD_MORGANA_PCI_DEVS_H + +#include <device/pci_def.h> +#include <amdblocks/pci_devs.h> + +/* GNB Root Complex */ +#define GNB_DEV 0x0 +#define GNB_FUNC 0 +#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_DEVFN PCI_DEVFN(IOMMU_DEV, IOMMU_FUNC) +#define SOC_IOMMU_DEV _SOC_DEV(IOMMU_DEV, IOMMU_FUNC) + +/* PCIe GFX/GPP Bridge device 1 with no ports */ +#define PCIE_GPP_BRIDGE_1_DEV 0x1 + +/* PCIe GPP Bridge device 2 with up to 6 ports */ +#define PCIE_GPP_BRIDGE_2_DEV 0x2 + +#define PCIE_GPP_2_0_FUNC 1 +#define PCIE_GPP_2_0_DEVFN PCI_DEVFN(PCIE_GPP_BRIDGE_2_DEV, PCIE_GPP_2_0_FUNC) +#define SOC_GPP_2_0_DEV _SOC_DEV(PCIE_GPP_BRIDGE_2_DEV, PCIE_GPP_2_0_FUNC) + +#define PCIE_GPP_2_1_FUNC 2 +#define PCIE_GPP_2_1_DEVFN PCI_DEVFN(PCIE_GPP_BRIDGE_2_DEV, PCIE_GPP_2_1_FUNC) +#define SOC_GPP_2_1_DEV _SOC_DEV(PCIE_GPP_BRIDGE_2_DEV, PCIE_GPP_2_1_FUNC) + +#define PCIE_GPP_2_2_FUNC 3 +#define PCIE_GPP_2_2_DEVFN PCI_DEVFN(PCIE_GPP_BRIDGE_2_DEV, PCIE_GPP_2_2_FUNC) +#define SOC_GPP_2_2_DEV _SOC_DEV(PCIE_GPP_BRIDGE_2_DEV, PCIE_GPP_2_2_FUNC) + +#define PCIE_GPP_2_3_FUNC 4 +#define PCIE_GPP_2_3_DEVFN PCI_DEVFN(PCIE_GPP_BRIDGE_2_DEV, PCIE_GPP_2_3_FUNC) +#define SOC_GPP_2_3_DEV _SOC_DEV(PCIE_GPP_BRIDGE_2_DEV, PCIE_GPP_2_3_FUNC) + +#define PCIE_GPP_2_4_FUNC 5 +#define PCIE_GPP_2_4_DEVFN PCI_DEVFN(PCIE_GPP_BRIDGE_2_DEV, PCIE_GPP_2_4_FUNC) +#define SOC_GPP_2_4_DEV _SOC_DEV(PCIE_GPP_BRIDGE_2_DEV, PCIE_GPP_2_4_FUNC) + +#define PCIE_GPP_2_5_FUNC 6 +#define PCIE_GPP_2_5_DEVFN PCI_DEVFN(PCIE_GPP_BRIDGE_2_DEV, PCIE_GPP_2_5_FUNC) +#define SOC_GPP_2_5_DEV _SOC_DEV(PCIE_GPP_BRIDGE_2_DEV, PCIE_GPP_2_5_FUNC) + +/* PCIe Bridges to Bus A, Bus B and Bus C devices */ +#define PCIE_ABC_BRIDGE_DEV 0x8 + +#define PCIE_ABC_A_FUNC 1 +#define PCIE_ABC_A_DEVFN PCI_DEVFN(PCIE_ABC_BRIDGE_DEV, PCIE_ABC_A_FUNC) +#define SOC_PCIE_ABC_A_DEV _SOC_DEV(PCIE_ABC_BRIDGE_DEV, PCIE_ABC_A_FUNC) + +#define GFX_DEV 0x0 +#define GFX_FUNC 0 +#define GFX_DEVFN PCI_DEVFN(GFX_DEV, GFX_FUNC) + +#define GFX_HDA_DEV 0x0 +#define GFX_HDA_FUNC 1 +#define GFX_HDA_DEVFN PCI_DEVFN(GFX_HDA_DEV, GFX_HDA_FUNC) + +#define XHCI0_DEV 0x0 +#define XHCI0_FUNC 3 +#define XHCI0_DEVFN PCI_DEVFN(XHCI0_DEV, XHCI0_FUNC) + +#define XHCI1_DEV 0x0 +#define XHCI1_FUNC 4 +#define XHCI1_DEVFN PCI_DEVFN(XHCI1_DEV, XHCI1_FUNC) + +#define AUDIO_DEV 0x0 +#define AUDIO_FUNC 5 +#define AUDIO_DEVFN PCI_DEVFN(AUDIO_DEV, AUDIO_FUNC) + +#define HD_AUDIO_DEV 0x0 +#define HD_AUDIO_FUNC 6 +#define HD_AUDIO_DEVFN PCI_DEVFN(HD_AUDIO_DEV, HD_AUDIO_FUNC) + +#define PCIE_ABC_B_FUNC 2 +#define PCIE_GPP_B_DEVFN PCI_DEVFN(PCIE_ABC_BRIDGE_DEV, PCIE_ABC_B_FUNC) +#define SOC_PCIE_GPP_B_DEV _SOC_DEV(PCIE_ABC_BRIDGE_DEV, PCIE_ABC_B_FUNC) + +#define PCIE_ABC_C_FUNC 3 +#define PCIE_GPP_C_DEVFN PCI_DEVFN(PCIE_ABC_BRIDGE_DEV, PCIE_ABC_C_FUNC) +#define SOC_PCIE_GPP_C_DEV _SOC_DEV(PCIE_ABC_BRIDGE_DEV, PCIE_ABC_C_FUNC) + +#define XHCI2_DEV 0x0 +#define XHCI2_FUNC 0 +#define XHCI2_DEVFN PCI_DEVFN(XHCI2_DEV, XHCI2_FUNC) + +/* SMBUS */ +#define SMBUS_DEV 0x14 +#define SMBUS_FUNC 0 +#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_DEVFN PCI_DEVFN(PCU_DEV, LPC_FUNC) +#define SOC_LPC_DEV _SOC_DEV(PCU_DEV, LPC_FUNC) + +/* Data Fabric functions */ +#define DF_DEV 0x18 + +#define DF_F0_DEVFN PCI_DEVFN(DF_DEV, 0) +#define SOC_DF_F0_DEV _SOC_DEV(DF_DEV, 0) + +#define DF_F1_DEVFN PCI_DEVFN(DF_DEV, 1) +#define SOC_DF_F1_DEV _SOC_DEV(DF_DEV, 1) + +#define DF_F2_DEVFN PCI_DEVFN(DF_DEV, 2) +#define SOC_DF_F2_DEV _SOC_DEV(DF_DEV, 2) + +#define DF_F3_DEVFN PCI_DEVFN(DF_DEV, 3) +#define SOC_DF_F3_DEV _SOC_DEV(DF_DEV, 3) + +#define DF_F4_DEVFN PCI_DEVFN(DF_DEV, 4) +#define SOC_DF_F4_DEV _SOC_DEV(DF_DEV, 4) + +#define DF_F5_DEVFN PCI_DEVFN(DF_DEV, 5) +#define SOC_DF_F5_DEV _SOC_DEV(DF_DEV, 5) + +#define DF_F6_DEVFN PCI_DEVFN(DF_DEV, 6) +#define SOC_DF_F6_DEV _SOC_DEV(DF_DEV, 6) + +#define DF_F7_DEVFN PCI_DEVFN(DF_DEV, 7) +#define SOC_DF_F7_DEV _SOC_DEV(DF_DEV, 7) + +#endif /* AMD_MORGANA_PCI_DEVS_H */ diff --git a/src/soc/amd/morgana/include/soc/platform_descriptors.h b/src/soc/amd/morgana/include/soc/platform_descriptors.h new file mode 100644 index 0000000000..d6ece12087 --- /dev/null +++ b/src/soc/amd/morgana/include/soc/platform_descriptors.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#ifndef AMD_MORGANA_PLATFORM_DESCRIPTORS_H +#define AMD_MORGANA_PLATFORM_DESCRIPTORS_H + +#include <types.h> +#include <platform_descriptors.h> +#include <FspmUpd.h> + +/* Mainboard callback to obtain DXI/PCIe and DDI descriptors. */ +void mainboard_get_dxio_ddi_descriptors( + const fsp_dxio_descriptor **dxio_descs, size_t *dxio_num, + const fsp_ddi_descriptor **ddi_descs, size_t *ddi_num); + +void mb_pre_fspm(FSP_M_CONFIG *mcfg); + +#endif /* AMD_MORGANA_PLATFORM_DESCRIPTORS_H */ diff --git a/src/soc/amd/morgana/include/soc/psp_transfer.h b/src/soc/amd/morgana/include/soc/psp_transfer.h new file mode 100644 index 0000000000..20b1cc82c6 --- /dev/null +++ b/src/soc/amd/morgana/include/soc/psp_transfer.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#ifndef AMD_MORGANA_PSP_TRANSFER_H +#define AMD_MORGANA_PSP_TRANSFER_H + +# if (CONFIG_CMOS_RECOVERY_BYTE != 0) +# define CMOS_RECOVERY_BYTE CONFIG_CMOS_RECOVERY_BYTE +# elif CONFIG(VBOOT_STARTS_BEFORE_BOOTBLOCK) +# error "Must set CONFIG_CMOS_RECOVERY_BYTE" +# endif + +#define CMOS_RECOVERY_MAGIC_VAL 0x96 + +#define TRANSFER_INFO_SIZE 64 +#define TIMESTAMP_BUFFER_SIZE 0x200 + +#define TRANSFER_MAGIC_VAL 0x50544953 + +/* Bit definitions for the psp_info field in the PSP transfer_info_struct */ +#define PSP_INFO_PRODUCTION_MODE 0x00000001UL +#define PSP_INFO_PRODUCTION_SILICON 0x00000002UL +#define PSP_INFO_VALID 0x80000000UL + +/* Area for things that would cause errors in a linker script */ +#if !defined(__ASSEMBLER__) +#include <stdint.h> + +struct transfer_info_struct { + uint32_t magic_val; /* Identifier */ + uint32_t struct_bytes; /* Size of this structure */ + uint32_t buffer_size; /* Size of the transfer buffer area */ + + /* Offsets from start of transfer buffer */ + uint32_t workbuf_offset; + uint32_t console_offset; + uint32_t timestamp_offset; + uint32_t fmap_offset; + + uint32_t unused1[5]; + + /* Fields reserved for the PSP */ + uint64_t timestamp; /* Offset 0x30 */ + uint32_t psp_unused; /* Offset 0x38 */ + uint32_t psp_info; /* Offset 0x3C */ +}; + +_Static_assert(sizeof(struct transfer_info_struct) == TRANSFER_INFO_SIZE, + "TRANSFER_INFO_SIZE is incorrect"); + +/* Make sure the PSP transferred information over to x86 side. */ +int transfer_buffer_valid(const struct transfer_info_struct *ptr); +/* Verify vboot work buffer is valid in transfer buffer */ +void verify_psp_transfer_buf(void); +/* Display the transfer block's PSP_info data */ +void show_psp_transfer_info(void); +/* Replays the pre-x86 cbmem console into the x86 cbmem console */ +void replay_transfer_buffer_cbmemc(void); +/* Called by bootblock_c_entry in the VBOOT_STARTS_BEFORE_BOOTBLOCK case */ +void boot_with_psp_timestamp(uint64_t base_timestamp); + +#endif +#endif /* AMD_MORGANA_PSP_TRANSFER_H */ diff --git a/src/soc/amd/morgana/include/soc/psp_verstage_addr.h b/src/soc/amd/morgana/include/soc/psp_verstage_addr.h new file mode 100644 index 0000000000..e99c525131 --- /dev/null +++ b/src/soc/amd/morgana/include/soc/psp_verstage_addr.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#ifndef AMD_MORGANA_PSP_VERSTAGE_ADDR_H +#define AMD_MORGANA_PSP_VERSTAGE_ADDR_H + +/* + * Start of available space is 0x0 and this is where the + * header for the user app (verstage) must be mapped. + * Size is 208KB + */ +#define PSP_SRAM_START 0x0 +#define PSP_SRAM_SIZE (208K) +#define VERSTAGE_START PSP_SRAM_START + +/* + * The top of the stack must be 4k aligned, so set the bottom as 4k aligned + * and make the size a multiple of 4k + */ + +#define PSP_VERSTAGE_STACK_START 0x2a000 +#define PSP_VERSTAGE_STACK_SIZE (40K) + +#endif /* AMD_MORGANA_PSP_VERSTAGE_ADDR_H */ diff --git a/src/soc/amd/morgana/include/soc/smi.h b/src/soc/amd/morgana/include/soc/smi.h new file mode 100644 index 0000000000..b622ee6067 --- /dev/null +++ b/src/soc/amd/morgana/include/soc/smi.h @@ -0,0 +1,191 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* TODO: Update for Morgana */ + +#ifndef AMD_MORGANA_SMI_H +#define AMD_MORGANA_SMI_H + +#include <types.h> + +#define SMI_GEVENTS 24 +#define SCIMAPS 64 /* 0..63 */ +#define SCI_GPES 32 +#define NUMBER_SMITYPES 160 + +#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_G_GENINT1_L 0 +#define SMITYPE_G_GENINT2_L 1 +#define SMITYPE_G_AGPIO3 2 +#define SMITYPE_G_ESPI_ALERT_L 3 +#define SMITYPE_G_AGPIO4 4 +#define SMITYPE_G_BLINK 5 +#define SMITYPE_G_SPKR 6 +#define SMITYPE_G_AGPIO5 7 +#define SMITYPE_G_WAKE_L 8 +#define SMITYPE_G_SPI_TPM_CS_L 9 +#define SMITYPE_G_AGPIO6 10 +#define SMITYPE_G_AGPIO7 11 +#define SMITYPE_G_USBOC0_L 12 +#define SMITYPE_G_USBOC1_L 13 +#define SMITYPE_G_USBOC2_L 14 +#define SMITYPE_G_USBOC3_L 15 +#define SMITYPE_G_AGPIO23 16 +#define SMITYPE_G_AGPIO32 17 +#define SMITYPE_G_FANIN0 18 +#define SMITYPE_G_SYSRESET_L 19 +#define SMITYPE_G_AGPIO40 20 +#define SMITYPE_G_PWR_BTN_L 21 +#define SMITYPE_G_AGPIO9 22 +#define SMITYPE_G_AGPIO8 23 +#define GEVENT_MASK ((1 << SMITYPE_G_GENINT1_L) \ + | (1 << SMITYPE_G_GENINT2_L) \ + | (1 << SMITYPE_G_AGPIO3) \ + | (1 << SMITYPE_G_ESPI_ALERT_L) \ + | (1 << SMITYPE_G_AGPIO4) \ + | (1 << SMITYPE_G_BLINK) \ + | (1 << SMITYPE_G_SPKR) \ + | (1 << SMITYPE_G_AGPIO5) \ + | (1 << SMITYPE_G_WAKE_L) \ + | (1 << SMITYPE_G_SPI_TPM_CS_L) \ + | (1 << SMITYPE_G_AGPIO6) \ + | (1 << SMITYPE_G_AGPIO7) \ + | (1 << SMITYPE_G_USBOC0_L) \ + | (1 << SMITYPE_G_USBOC1_L) \ + | (1 << SMITYPE_G_USBOC2_L) \ + | (1 << SMITYPE_G_USBOC3_L) \ + | (1 << SMITYPE_G_AGPIO23) \ + | (1 << SMITYPE_G_AGPIO32) \ + | (1 << SMITYPE_G_FANIN0) \ + | (1 << SMITYPE_G_SYSRESET_L) \ + | (1 << SMITYPE_G_AGPIO40) \ + | (1 << SMITYPE_G_PWR_BTN_L) \ + | (1 << SMITYPE_G_AGPIO9) \ + | (1 << SMITYPE_G_AGPIO8)) +#define SMITYPE_MP2_WAKE 24 +#define SMITYPE_MP2_GPIO0 25 +#define SMITYPE_ESPI_SYS 26 +#define SMITYPE_ESPI_WAKE_PME 27 +#define SMITYPE_MP2_GPIO1 28 +#define SMITYPE_GPP_PME 29 +#define SMITYPE_NB_GPP_HOT_PLUG 30 +/* 31 Reserved */ +#define SMITYPE_WAKE_L2 32 +#define SMITYPE_PSP 33 +/* 34,35 Reserved */ +#define SMITYPE_ESPI_SCI_B 36 +#define SMITYPE_CIO_FCH_PME_S5_0 37 +#define SMITYPE_CIO_FCH_PME_S5_1 38 +#define SMITYPE_AZPME 39 +#define SMITYPE_USB_PD_I2C4 40 +#define SMITYPE_GPIO_CTL 41 +#define SMITYPE_XHC2_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 +#define SMITYPE_XHC1_PME 57 +#define SMITYPE_ACDC_TIMER 58 +/* 59-60 Reserved */ +#define SMITYPE_XHC3_PME 61 +#define SMITYPE_XHC4_PME 62 +#define SMITYPE_CUR_TEMP_STATUS_5 63 +#define SMITYPE_KB_RESET 64 +#define SMITYPE_SLP_TYP 65 +#define SMITYPE_AL2H_ACPI 66 +/* 67 Reserved */ +#define SMITYPE_NB_GPP_PME_PULSE 68 +#define SMITYPE_NB_GPP_HP_PULSE 69 +#define SMITYPE_USB_PD_I2C4_INTR2 70 +/* 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 +/* 79-80 Reserved */ +#define SMITYPE_INTRUDER 81 +#define SMITYPE_VBAT_LOW 82 +#define SMITYPE_PROTHOT 83 +#define SMITYPE_PCI_SERR 84 +/* 85-89 Reserved */ +#define SMITYPE_EMUL60_64 90 +/* 91-132 Reserved */ +#define SMITYPE_FANIN0 133 +/* 134-140 Reserved */ +#define SMITYPE_CF9_WRITE 141 +#define SMITYPE_SHORT_TIMER 142 +#define SMITYPE_LONG_TIMER 143 +#define SMITYPE_AB_SMI 144 +#define SMITYPE_ANY_RESET 145 +#define SMITYPE_ESPI_SMI 146 +/* 147 Reserved */ +#define SMITYPE_IOTRAP0 148 +#define SMITYPE_IOTRAP1 149 +#define SMITYPE_IOTRAP2 150 +#define SMITYPE_IOTRAP3 151 +#define SMITYPE_MEMTRAP0 152 +/* 153-155 Reserved */ +#define SMITYPE_CFGTRAP0 156 +/* 157-159 Reserved */ + +#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 SMITRIG0_PSP (1 << 25) +# 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 + +#define SMI_MODE_MASK 0x03 + +#endif /* AMD_MORGANA_SMI_H */ diff --git a/src/soc/amd/morgana/include/soc/smu.h b/src/soc/amd/morgana/include/soc/smu.h new file mode 100644 index 0000000000..308a861771 --- /dev/null +++ b/src/soc/amd/morgana/include/soc/smu.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#ifndef AMD_MORGANA_SMU_H +#define AMD_MORGANA_SMU_H + +/* SMU mailbox register offsets in SMN */ +#define SMN_SMU_MESG_ID 0x3b10528 +#define SMN_SMU_MESG_RESP 0x3b10578 +#define SMN_SMU_MESG_ARGS_BASE 0x3b10998 + +#define SMU_NUM_ARGS 6 + +enum smu_message_id { + SMC_MSG_S3ENTRY = 0x0b, +}; + +/* + * Request the SMU put system into S3, S4, or S5. On entry, SlpTyp determines S-State and + * SlpTypeEn gets set by the SMU. Function does not return if successful. + */ +void smu_sx_entry(void); + +#endif /* AMD_MORGANA_SMU_H */ diff --git a/src/soc/amd/morgana/include/soc/southbridge.h b/src/soc/amd/morgana/include/soc/southbridge.h new file mode 100644 index 0000000000..75f0beb72f --- /dev/null +++ b/src/soc/amd/morgana/include/soc/southbridge.h @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#ifndef AMD_MORGANA_SOUTHBRIDGE_H +#define AMD_MORGANA_SOUTHBRIDGE_H + +#include <soc/iomap.h> + +/* Power management registers: 0xfed80300 or index/data at IO 0xcd6/cd7 */ +#define PM_ISACONTROL 0x04 +#define ABCLKGATEEN BIT(16) +#define PM_PCI_CTRL 0x08 +#define FORCE_SLPSTATE_RETRY BIT(25) +#define PWR_RESET_CFG 0x10 +#define TOGGLE_ALL_PWR_GOOD (1 << 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_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_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_SLPBTN_EN_EN BIT(3) +#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_S5_LPC_PIN_MODE_SEL BIT(10) +#define PM_ACPI_S5_LPC_PIN_MODE BIT(11) +#define PM_ACPI_LPC_RST_DIS BIT(12) +#define PM_ACPI_SEL_PWRGD_PAD BIT(13) +#define PM_ACPI_SEL_SMU_THERMTRIP BIT(14) +#define PM_ACPI_SW_S5PWRMUX_OVRD_N BIT(15) +#define PM_ACPI_SW_S5PWRMUX BIT(16) +#define PM_ACPI_EN_SHUTDOWN_MSG BIT(17) +#define PM_ACPI_EN_SYNC_FLOOD BIT(18) +#define PM_ACPI_FORCE_SPIUSEPIN_0 BIT(19) +#define PM_ACPI_EN_DF_INTRWAKE BIT(20) +#define PM_ACPI_MASK_USB_S5_RST BIT(21) +#define PM_ACPI_USE_RSMU_RESET BIT(22) +#define PM_ACPI_RST_USB_S5 BIT(23) +#define PM_ACPI_BLOCK_PCIE_PME BIT(24) +#define PM_ACPI_PCIE_WAK_MASK BIT(25) +#define PM_ACPI_PCIE_WAK_INTR_DIS BIT(26) +#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_ACPI_USE_GATED_ALINK_CLK BIT(30) +#define PM_ACPI_DELAY_GPP_OFF_TIME BIT(31) +#define PM_SPI_PAD_PU_PD 0x90 +#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 PM1_LIMIT 16 +#define GPE0_LIMIT 32 +#define TOTAL_BITS(a) (8 * sizeof(a)) + +#define FCH_LEGACY_UART_DECODE (ALINK_AHB_ADDRESS + 0x20) /* 0xfedc0020 */ + +/* FCH MISC Registers 0xfed80e00 */ +#define GPP_CLK_CNTRL 0x00 +#define GPP_CLK0_REQ_SHIFT 0 +#define GPP_CLK1_REQ_SHIFT 2 +#define GPP_CLK4_REQ_SHIFT 4 +#define GPP_CLK2_REQ_SHIFT 6 +#define GPP_CLK3_REQ_SHIFT 8 +#define GPP_CLK5_REQ_SHIFT 10 +#define GPP_CLK6_REQ_SHIFT 12 +#define GPP_CLK_OUTPUT_COUNT 7 +#define GPP_CLK_OUTPUT_AVAILABLE 4 +#define GPP_CLK_REQ_MASK(clk_shift) (0x3 << (clk_shift)) +#define GPP_CLK_REQ_ON(clk_shift) (0x3 << (clk_shift)) +#define GPP_CLK_REQ_EXT(clk_shift) (0x1 << (clk_shift)) +#define GPP_CLK_REQ_OFF(clk_shift) (0x0 << (clk_shift)) + +#define MISC_CLKGATEDCNTL 0x2c +#define ALINKCLK_GATEOFFEN BIT(16) +#define BLINKCLK_GATEOFFEN BIT(17) +#define XTAL_PAD_S0I3_TURNOFF_EN BIT(19) +#define XTAL_PAD_S3_TURNOFF_EN BIT(20) +#define XTAL_PAD_S5_TURNOFF_EN BIT(21) +#define MISC_CGPLL_CONFIGURATION0 0x30 +#define USB_PHY_CMCLK_S3_DIS BIT(8) +#define USB_PHY_CMCLK_S0I3_DIS BIT(9) +#define USB_PHY_CMCLK_S5_DIS BIT(10) +#define MISC_CLK_CNTL0 0x40 /* named MISC_CLK_CNTL1 on Picasso */ +#define BP_X48M0_S0I3_DIS BIT(4) +#define BP_X48M0_OUTPUT_EN BIT(2) /* 1=En, unlike Hudson, Kern */ + +void fch_pre_init(void); +void fch_early_init(void); +void fch_init(void *chip_info); +void fch_final(void *chip_info); + +void enable_aoac_devices(void); +void wait_for_aoac_enabled(unsigned int dev); + +#endif /* AMD_MORGANA_SOUTHBRIDGE_H */ diff --git a/src/soc/amd/morgana/include/soc/uart.h b/src/soc/amd/morgana/include/soc/uart.h new file mode 100644 index 0000000000..45e0ed9560 --- /dev/null +++ b/src/soc/amd/morgana/include/soc/uart.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#ifndef AMD_MORGANA_UART_H +#define AMD_MORGANA_UART_H + +#include <types.h> + +void set_uart_config(unsigned int idx); /* configure hardware of FCH UART selected by idx */ +void clear_uart_legacy_config(void); /* disable legacy I/O decode for FCH UART */ + +#endif /* AMD_MORGANA_UART_H */ diff --git a/src/soc/amd/morgana/mca.c b/src/soc/amd/morgana/mca.c new file mode 100644 index 0000000000..c104a33b23 --- /dev/null +++ b/src/soc/amd/morgana/mca.c @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include <amdblocks/mca.h> +#include <cpu/x86/msr.h> +#include <types.h> + +static const char *const mca_bank_name[] = { + [0] = "Load-store unit", + [1] = "Instruction fetch unit", + [2] = "L2 cache unit", + [3] = "Decode unit", + [4] = "", + [5] = "Execution unit", + [6] = "Floating point unit", + [7] = "L3 cache unit", + [8] = "L3 cache unit", + [9] = "L3 cache unit", + [10] = "L3 cache unit", + [11] = "UMC", + [12] = "UMC", + [13] = "CS", + [14] = "CS", + [15] = "NBIO", + [16] = "PIE", +}; + +bool mca_has_expected_bank_count(void) +{ + return ARRAY_SIZE(mca_bank_name) == mca_get_bank_count(); +} + +bool mca_is_valid_bank(unsigned int bank) +{ + return (bank < ARRAY_SIZE(mca_bank_name) && mca_bank_name[bank] != NULL); +} + +const char *mca_get_bank_name(unsigned int bank) +{ + if (mca_is_valid_bank(bank)) + return mca_bank_name[bank]; + else + return ""; +} diff --git a/src/soc/amd/morgana/preload.c b/src/soc/amd/morgana/preload.c new file mode 100644 index 0000000000..47f3580714 --- /dev/null +++ b/src/soc/amd/morgana/preload.c @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Move to common? */ + +#include <bootstate.h> +#include <fsp/api.h> + +static void start_fsps_preload(void *unused) +{ + preload_fsps(); +} + +BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, start_fsps_preload, NULL); diff --git a/src/soc/amd/morgana/psp_verstage/Makefile.inc b/src/soc/amd/morgana/psp_verstage/Makefile.inc new file mode 100644 index 0000000000..8d1e5e4aa0 --- /dev/null +++ b/src/soc/amd/morgana/psp_verstage/Makefile.inc @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ifeq $($(CONFIG_VBOOT_STARTS_BEFORE_BOOTBLOCK),y) + +subdirs-y += ../../common/psp_verstage + +verstage-generic-ccopts += -I$(src)/soc/amd/morgana/psp_verstage/include +verstage-generic-ccopts += -I$(src)/soc/amd/common/psp_verstage/include +verstage-generic-ccopts += -Isrc/vendorcode/amd/fsp/morgana/include +verstage-generic-ccopts += -Isrc/vendorcode/amd/fsp/common/include + +verstage-y += svc.c +verstage-y += chipset.c +verstage-y += uart.c + +verstage-y +=$(top)/src/vendorcode/amd/fsp/common/bl_uapp/bl_uapp_startup.S +verstage-y += $(top)/src/vendorcode/amd/fsp/common/bl_uapp/bl_uapp_end.S + +endif diff --git a/src/soc/amd/morgana/psp_verstage/chipset.c b/src/soc/amd/morgana/psp_verstage/chipset.c new file mode 100644 index 0000000000..539ddb4405 --- /dev/null +++ b/src/soc/amd/morgana/psp_verstage/chipset.c @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include <bl_uapp/bl_syscall_public.h> +#include <cbfs.h> +#include <console/console.h> +#include <psp_verstage.h> + +/* + * We can't pass pointer to hash table in the SPI. + * The AMD PSP team specifically required that whole hash table + * should be copied into memory before passing them to the PSP + * to reduce window of TOCTOU. + */ +#define MAX_NUM_HASH_ENTRIES 128 +static struct psp_fw_hash_table hash_table; +static struct psp_fw_entry_hash_256 hash_256[MAX_NUM_HASH_ENTRIES]; +static struct psp_fw_entry_hash_384 hash_384[MAX_NUM_HASH_ENTRIES]; + +void update_psp_fw_hash_table(const char *fname) +{ + uint8_t *spi_ptr = (uint8_t *)cbfs_map(fname, NULL); + uint32_t len; + + if (!spi_ptr) { + printk(BIOS_ERR, "Error: AMD Firmware hash table %s not found\n", fname); + /* + * If we don't supply hash table, the PSP will refuse to boot. + * So returning here is safe to do. + */ + return; + } + + memcpy(&hash_table, spi_ptr, offsetof(struct psp_fw_hash_table, fw_hash_256)); + + if (hash_table.no_of_entries_256 > MAX_NUM_HASH_ENTRIES || + hash_table.no_of_entries_384 > MAX_NUM_HASH_ENTRIES) { + printk(BIOS_ERR, "Error: Too many entries in AMD Firmware hash table" + " (SHA256:%d, SHA384:%d)\n", + hash_table.no_of_entries_256, hash_table.no_of_entries_384); + return; + } + + if (hash_table.no_of_entries_256 == 0 && + hash_table.no_of_entries_384 == 0) { + printk(BIOS_ERR, "Error: No entries in AMD Firmware hash table" + " (SHA256:%d, SHA384:%d)\n", + hash_table.no_of_entries_256, hash_table.no_of_entries_384); + return; + } + + spi_ptr += offsetof(struct psp_fw_hash_table, fw_hash_256); + + hash_table.fw_hash_256 = hash_256; + hash_table.fw_hash_384 = hash_384; + len = sizeof(struct psp_fw_entry_hash_256) * hash_table.no_of_entries_256; + memcpy(hash_256, spi_ptr, len); + + spi_ptr += len; + len = sizeof(struct psp_fw_entry_hash_384) * hash_table.no_of_entries_384; + memcpy(hash_384, spi_ptr, len); + + svc_set_fw_hash_table(&hash_table); +} + +uint32_t update_psp_bios_dir(uint32_t *psp_dir_offset, uint32_t *bios_dir_offset) +{ + return svc_update_psp_bios_dir(psp_dir_offset, bios_dir_offset); +} + +uint32_t save_uapp_data(void *address, uint32_t size) +{ + return svc_save_uapp_data(address, size); +} + +uint32_t get_bios_dir_addr(struct embedded_firmware *ef_table) +{ + return 0; +} + +int platform_set_sha_op(enum vb2_hash_algorithm hash_alg, + struct sha_generic_data *sha_op) +{ + if (hash_alg == VB2_HASH_SHA256) { + sha_op->SHAType = SHA_TYPE_256; + sha_op->DigestLen = 32; + } else if (hash_alg == VB2_HASH_SHA384) { + sha_op->SHAType = SHA_TYPE_384; + sha_op->DigestLen = 48; + } else { + return -1; + } + return 0; +} + + +/* Functions below are stub functions for not-yet-implemented PSP features. + * These functions should be replaced with proper implementations later. + */ + +uint32_t svc_write_postcode(uint32_t postcode) +{ + return 0; +} + +void platform_report_mode(int developer_mode_enabled) +{ + printk(BIOS_INFO, "Reporting %s mode\n", + developer_mode_enabled ? "Developer" : "Normal"); + if (developer_mode_enabled) + svc_set_platform_boot_mode(CHROME_BOOK_BOOT_MODE_DEVELOPER); + else + svc_set_platform_boot_mode(CHROME_BOOK_BOOT_MODE_NORMAL); +} diff --git a/src/soc/amd/morgana/psp_verstage/svc.c b/src/soc/amd/morgana/psp_verstage/svc.c new file mode 100644 index 0000000000..2fc29aae65 --- /dev/null +++ b/src/soc/amd/morgana/psp_verstage/svc.c @@ -0,0 +1,218 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include "svc.h" + +#include <assert.h> +#include <bl_uapp/bl_syscall_public.h> +#include <psp_verstage.h> +#include <stddef.h> +#include <string.h> + +void svc_exit(uint32_t status) +{ + uint32_t unused = 0; + SVC_CALL0(SVC_EXIT, unused); +} + +void svc_debug_print(const char *string) +{ + uint32_t unused = 0; + struct cmd_param_debug param = { + .debug_buffer = (char *)string, + .debug_buffer_len = strlen(string), + }; + SVC_CALL2(SVC_VERSTAGE_CMD, CMD_DEBUG_PRINT, (void *)¶m, unused); +} + +void svc_debug_print_ex(uint32_t dword0, + uint32_t dword1, uint32_t dword2, uint32_t dword3) +{ + uint32_t unused = 0; + struct cmd_param_debug_ex param = { + .word0 = dword0, + .word1 = dword1, + .word2 = dword2, + .word3 = dword3, + }; + SVC_CALL2(SVC_VERSTAGE_CMD, CMD_DEBUG_PRINT_EX, (void *)¶m, unused); +} + +uint32_t svc_get_boot_mode(uint32_t *boot_mode) +{ + uint32_t retval = 0; + struct cmd_param_get_boot_mode param = { + .ptr_boot_mode = boot_mode, + }; + SVC_CALL2(SVC_VERSTAGE_CMD, CMD_GET_BOOT_MODE, (void *)¶m, retval); + return retval; +} + +void svc_delay_in_usec(uint32_t delay) +{ + uint32_t unused = 0; + struct cmd_param_delay_in_micro_second param = { + .delay = delay, + }; + SVC_CALL2(SVC_VERSTAGE_CMD, CMD_DELAY_IN_MICRO_SECONDS, (void *)¶m, unused); +} + +uint32_t svc_get_spi_rom_info(struct spirom_info *spi_rom_info) +{ + uint32_t retval = 0; + struct cmd_param_spirom_info param = { + .ptr_spirom_info = spi_rom_info, + }; + SVC_CALL2(SVC_VERSTAGE_CMD, CMD_GET_SPI_INFO, (void *)¶m, retval); + return retval; +} + +uint32_t svc_map_fch_dev(enum fch_io_device io_device, + uint32_t arg1, uint32_t arg2, void **io_device_axi_addr) +{ + uint32_t retval = 0; + struct cmd_param_map_fch_io_device param = { + .io_device = io_device, + .arg1 = arg1, + .arg2 = arg2, + .pptr_io_device_addr_axi = io_device_axi_addr, + }; + assert(io_device < FCH_IO_DEVICE_END); + SVC_CALL2(SVC_VERSTAGE_CMD, CMD_MAP_FCH_IO_DEVICE, (void *)¶m, retval); + return retval; +} + +uint32_t svc_unmap_fch_dev(enum fch_io_device io_device, void *io_device_axi_addr) +{ + uint32_t retval = 0; + struct cmd_param_unmap_fch_io_device param = { + .io_device = io_device, + .ptr_io_device_addr_axi = io_device_axi_addr, + }; + assert(io_device < FCH_IO_DEVICE_END); + SVC_CALL2(SVC_VERSTAGE_CMD, CMD_UNMAP_FCH_IO_DEVICE, (void *)¶m, retval); + return retval; +} + +uint32_t svc_map_spi_rom(void *spi_rom_addr, + uint32_t size, void **spi_rom_axi_addr) +{ + uint32_t retval = 0; + struct cmd_param_map_spirom param = { + .spirom_addr = (uintptr_t)spi_rom_addr, + .size = size, + .ppspirom_addr_axi = spi_rom_axi_addr, + }; + SVC_CALL2(SVC_VERSTAGE_CMD, CMD_MAP_SPIROM_DEVICE, (void *)¶m, retval); + return retval; +} + +uint32_t svc_unmap_spi_rom(void *spi_rom_addr) +{ + uint32_t retval = 0; + struct cmd_param_unmap_spirom param = { + .ptr_spirom_addr_axi = spi_rom_addr, + }; + SVC_CALL2(SVC_VERSTAGE_CMD, CMD_UNMAP_SPIROM_DEVICE, (void *)¶m, retval); + return retval; +} + +uint32_t svc_update_psp_bios_dir(uint32_t *psp_dir_offset, + uint32_t *bios_dir_offset) +{ + uint32_t retval = 0; + struct cmd_param_psp_update param = { + .ptr_psp_dir_addr = psp_dir_offset, + }; + SVC_CALL2(SVC_VERSTAGE_CMD, CMD_UPDATE_PSP_BIOS_DIR, (void *)¶m, retval); + return retval; +} + +uint32_t svc_save_uapp_data(void *address, uint32_t size) +{ + uint32_t retval = 0; + struct cmd_param_copy_data_from_uapp param = { + .address = (uintptr_t)address, + .size = size, + }; + SVC_CALL2(SVC_VERSTAGE_CMD, CMD_COPY_DATA_FROM_UAPP, (void *)¶m, retval); + return retval; +} + +uint32_t svc_read_timer_val(enum psp_timer_type type, uint64_t *counter_value) +{ + unsigned int retval = 0; + struct cmd_param_read_timer_val param = { + .timer_type = type, + .ptr_counter_value = counter_value, + }; + assert(type < PSP_TIMER_TYPE_MAX); + SVC_CALL2(SVC_VERSTAGE_CMD, CMD_READ_TIMER_VAL, (void *)¶m, retval); + return retval; +} + +uint32_t svc_reset_system(enum reset_type reset_type) +{ + unsigned int retval = 0; + struct cmd_param_reset_system param = { + .reset_type = reset_type, + }; + assert(reset_type < RESET_TYPE_MAX); + SVC_CALL2(SVC_VERSTAGE_CMD, CMD_RESET_SYSTEM, (void *)¶m, retval); + return retval; +} + +uint32_t svc_crypto_sha(struct sha_generic_data *sha_op, enum sha_operation_mode sha_mode) +{ + uint32_t retval = 0; + struct cmd_param_sha param = { + .ptr_sha_op = sha_op, + }; + assert(sha_mode == SHA_GENERIC); + SVC_CALL2(SVC_VERSTAGE_CMD, CMD_SHA, (void *)¶m, retval); + return retval; +} + +uint32_t svc_modexp(struct mod_exp_params *mod_exp_param) +{ + uint32_t retval = 0; + struct cmd_param_modexp param = { + .ptr_modexp = mod_exp_param, + }; + SVC_CALL2(SVC_VERSTAGE_CMD, CMD_MODEXP, (void *)¶m, retval); + return retval; + +} + +uint32_t svc_ccp_dma(uint32_t spi_rom_offset, void *dest, uint32_t size) +{ + uint32_t retval = 0; + struct cmd_param_ccp_dma param = { + .spi_offset = spi_rom_offset, + .dst_addr = (uintptr_t)dest, + .size = size, + }; + SVC_CALL2(SVC_VERSTAGE_CMD, CMD_CCP_DMA, (void *)¶m, retval); + return retval; +} + +uint32_t svc_set_platform_boot_mode(enum chrome_platform_boot_mode boot_mode) +{ + uint32_t retval = 0; + struct cmd_param_set_platform_boot_mode param = { + .boot_mode = boot_mode, + }; + SVC_CALL2(SVC_VERSTAGE_CMD, CMD_SET_PLATFORM_BOOT_MODE, (void *)¶m, retval); + return retval; +} + +uint32_t svc_set_fw_hash_table(struct psp_fw_hash_table *hash_table) +{ + uint32_t retval = 0; + struct cmd_param_set_fw_hash_table param = { + .ptr_psp_fw_hash_table = hash_table, + }; + SVC_CALL2(SVC_VERSTAGE_CMD, CMD_SET_FW_HASH_TABLE, (void *)¶m, retval); + return retval; +} diff --git a/src/soc/amd/morgana/psp_verstage/svc.h b/src/soc/amd/morgana/psp_verstage/svc.h new file mode 100644 index 0000000000..2507ee1dc2 --- /dev/null +++ b/src/soc/amd/morgana/psp_verstage/svc.h @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ +/* TODO: See what can be made common */ + +#ifndef PSP_VERSTAGE_SVC_H +#define PSP_VERSTAGE_SVC_H + +#include <bl_uapp/bl_syscall_public.h> +#include <types.h> + +#define SVC_CALL4(SVC_ID, R0, R1, R2, R3, Ret) \ + __asm__ __volatile__ ( \ + "mov r0, %[reg0]\n\t" \ + "mov r1, %[reg1]\n\t" \ + "mov r2, %[reg2]\n\t" \ + "mov r3, %[reg3]\n\t" \ + "svc %[id]\n\t" \ + "mov %[result], r0\n\t" \ + : [result] "=r" (Ret) /* output */ \ + : [id] "i" (SVC_ID), [reg0] "r" (R0), [reg1] "r" (R1), [reg2] "r" (R2), \ + [reg3] "r" (R3) /* input(s) */ \ + : "r0", "r1", "r2", "r3", "memory", "cc" /* list of clobbered registers */) + +#define SVC_CALL3(SVC_ID, R0, R1, R2, Ret) \ + __asm__ __volatile__ ( \ + "mov r0, %[reg0]\n\t" \ + "mov r1, %[reg1]\n\t" \ + "mov r2, %[reg2]\n\t" \ + "svc %[id]\n\t" \ + "mov %[result], r0\n\t" \ + : [result] "=r" (Ret) /* output */ \ + : [id] "i" (SVC_ID), [reg0] "r" (R0), [reg1] "r" (R1), [reg2] "r" (R2) \ + : "r0", "r1", "r2", "memory", "cc" /* list of clobbered registers */) + +#define SVC_CALL2(SVC_ID, R0, R1, Ret) \ + __asm__ __volatile__ ( \ + "mov r0, %[reg0]\n\t" \ + "mov r1, %[reg1]\n\t" \ + "svc %[id]\n\t" \ + "mov %[result], r0\n\t" \ + : [result] "=r" (Ret) /* output */ \ + : [id] "i" (SVC_ID), [reg0] "r" (R0), [reg1] "r" (R1)/* input(s) */ \ + : "r0", "r1", "memory", "cc" /* list of clobbered registers */) + +#define SVC_CALL1(SVC_ID, R0, Ret) \ + __asm__ __volatile__ ( \ + "mov r0, %[reg0]\n\t" \ + "svc %[id]\n\t" \ + "mov %[result], r0\n\t" \ + : [result] "=r" (Ret) /* output */ \ + : [id] "i" (SVC_ID), [reg0] "r" (R0) /* input(s) */ \ + : "r0", "memory", "cc" /* list of clobbered registers */) + +#define SVC_CALL0(SVC_ID, Ret) \ + __asm__ __volatile__ ( \ + "svc %[id]\n\t" \ + "mov %[result], r0\n\t" \ + : [result] "=r" (Ret) /* output */ \ + : [id] "I" (SVC_ID) /* input(s) */ \ + : "memory", "cc" /* list of clobbered registers */) + +struct cmd_param_sha { + struct sha_generic_data *ptr_sha_op; +}; + +struct cmd_param_debug { + char *debug_buffer; + uint32_t debug_buffer_len; +}; + +struct cmd_param_debug_ex { + uint32_t word0; + uint32_t word1; + uint32_t word2; + uint32_t word3; +}; + +struct cmd_param_modexp { + struct mod_exp_params *ptr_modexp; +}; + +struct cmd_param_psp_update { + unsigned int *ptr_psp_dir_addr; +}; + +struct cmd_param_spirom_info { + struct spirom_info *ptr_spirom_info; +}; + +struct cmd_param_map_spirom { + unsigned int spirom_addr; + unsigned int size; + void **ppspirom_addr_axi; +}; + +struct cmd_param_unmap_spirom { + void *ptr_spirom_addr_axi; +}; + +struct cmd_param_read_timer_val { + enum psp_timer_type timer_type; + uint64_t *ptr_counter_value; +}; + +struct cmd_param_delay_in_micro_second { + uint32_t delay; +}; + +struct cmd_param_reset_system { + uint32_t reset_type; +}; + +struct cmd_param_get_boot_mode { + unsigned int *ptr_boot_mode; +}; + +struct cmd_param_copy_data_from_uapp { + unsigned int address; + unsigned int size; +}; + +struct cmd_param_map_fch_io_device { + enum fch_io_device io_device; + unsigned int arg1; + unsigned int arg2; + void **pptr_io_device_addr_axi; +}; + +struct cmd_param_unmap_fch_io_device { + enum fch_io_device io_device; + void *ptr_io_device_addr_axi; +}; + +struct cmd_param_ccp_dma { + uint32_t spi_offset; + uint32_t dst_addr; + uint32_t size; +}; + +struct cmd_param_set_platform_boot_mode { + uint32_t boot_mode; +}; + +struct cmd_param_set_fw_hash_table { + struct psp_fw_hash_table *ptr_psp_fw_hash_table; +}; + +#endif /* PSP_VERSTAGE_SVC_H */ diff --git a/src/soc/amd/morgana/psp_verstage/uart.c b/src/soc/amd/morgana/psp_verstage/uart.c new file mode 100644 index 0000000000..d2cba27891 --- /dev/null +++ b/src/soc/amd/morgana/psp_verstage/uart.c @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Can this be made common? Kconfig option? */ + +#include <bl_uapp/bl_syscall_public.h> +#include <amdblocks/uart.h> +#include <types.h> + +uintptr_t get_uart_base(unsigned int idx) +{ + /* Mapping the UART is not supported. */ + return 0; +} diff --git a/src/soc/amd/morgana/reset.c b/src/soc/amd/morgana/reset.c new file mode 100644 index 0000000000..83bfcee546 --- /dev/null +++ b/src/soc/amd/morgana/reset.c @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Move to common? */ + +#include <arch/io.h> +#include <cf9_reset.h> +#include <reset.h> +#include <soc/southbridge.h> +#include <amdblocks/acpimmio.h> +#include <amdblocks/reset.h> + +void do_cold_reset(void) +{ + /* 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_CPU | SYS_RST, RST_CNT); +} + +void do_warm_reset(void) +{ + /* Assert reset signals only. */ + outb(RST_CPU | SYS_RST, RST_CNT); +} + +void do_board_reset(void) +{ + do_cold_reset(); +} diff --git a/src/soc/amd/morgana/romstage.c b/src/soc/amd/morgana/romstage.c new file mode 100644 index 0000000000..dce0b69735 --- /dev/null +++ b/src/soc/amd/morgana/romstage.c @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <acpi/acpi.h> +#include <amdblocks/acpimmio.h> +#include <amdblocks/memmap.h> +#include <amdblocks/pmlib.h> +#include <arch/cpu.h> +#include <console/console.h> +#include <fsp/api.h> +#include <program_loading.h> +#include <romstage_common.h> + +void __noreturn romstage_main(void) +{ + post_code(0x40); + + /* Snapshot chipset state prior to any FSP call */ + fill_chipset_state(); + + fsp_memory_init(acpi_is_wakeup_s3()); + + /* Fixup settings FSP-M should not be changing */ + fch_disable_legacy_dma_io(); + + memmap_stash_early_dram_usage(); + + run_ramstage(); +} diff --git a/src/soc/amd/morgana/root_complex.c b/src/soc/amd/morgana/root_complex.c new file mode 100644 index 0000000000..5dd5d79579 --- /dev/null +++ b/src/soc/amd/morgana/root_complex.c @@ -0,0 +1,252 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include <acpi/acpigen.h> +#include <amdblocks/acpi.h> +#include <amdblocks/alib.h> +#include <amdblocks/ioapic.h> +#include <amdblocks/memmap.h> +#include <arch/ioapic.h> +#include <cbmem.h> +#include <console/console.h> +#include <cpu/amd/msr.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <fsp/util.h> +#include <soc/iomap.h> +#include <stdint.h> +#include "chip.h" + +#define DPTC_TOTAL_UPDATE_PARAMS 7 + +struct dptc_input { + uint16_t size; + struct alib_dptc_param params[DPTC_TOTAL_UPDATE_PARAMS]; +} __packed; + +#define DPTC_INPUTS(_thermctllmit, _sustained, _fast, _slow, \ + _vrmCurrentLimit, _vrmMaxCurrentLimit, _vrmSocCurrentLimit) \ + { \ + .size = sizeof(struct dptc_input), \ + .params = { \ + { \ + .id = ALIB_DPTC_THERMAL_CONTROL_LIMIT_ID, \ + .value = _thermctllmit, \ + }, \ + { \ + .id = ALIB_DPTC_SUSTAINED_POWER_LIMIT_ID, \ + .value = _sustained, \ + }, \ + { \ + .id = ALIB_DPTC_FAST_PPT_LIMIT_ID, \ + .value = _fast, \ + }, \ + { \ + .id = ALIB_DPTC_SLOW_PPT_LIMIT_ID, \ + .value = _slow, \ + }, \ + { \ + .id = ALIB_DPTC_VRM_CURRENT_LIMIT_ID, \ + .value = _vrmCurrentLimit, \ + }, \ + { \ + .id = ALIB_DPTC_VRM_MAXIMUM_CURRENT_LIMIT, \ + .value = _vrmMaxCurrentLimit, \ + }, \ + { \ + .id = ALIB_DPTC_VRM_SOC_CURRENT_LIMIT_ID, \ + .value = _vrmSocCurrentLimit, \ + }, \ + }, \ + } + +/* + * + * +--------------------------------+ + * | | + * | | + * | | + * | | + * | | + * | | + * | | + * reserved_dram_end +--------------------------------+ + * | | + * | verstage (if reqd) | + * | (VERSTAGE_SIZE) | + * +--------------------------------+ VERSTAGE_ADDR + * | | + * | FSP-M | + * | (FSP_M_SIZE) | + * +--------------------------------+ FSP_M_ADDR + * | romstage | + * | (ROMSTAGE_SIZE) | + * +--------------------------------+ ROMSTAGE_ADDR = BOOTBLOCK_END + * | | X86_RESET_VECTOR = BOOTBLOCK_END - 0x10 + * | bootblock | + * | (C_ENV_BOOTBLOCK_SIZE) | + * +--------------------------------+ BOOTBLOCK_ADDR = BOOTBLOCK_END - C_ENV_BOOTBLOCK_SIZE + * | Unused hole | + * | (30KiB) | + * +--------------------------------+ + * | FMAP cache (FMAP_SIZE) | + * +--------------------------------+ PSP_SHAREDMEM_BASE + PSP_SHAREDMEM_SIZE + PRERAM_CBMEM_CONSOLE_SIZE + 0x200 + * | Early Timestamp region (512B) | + * +--------------------------------+ PSP_SHAREDMEM_BASE + PSP_SHAREDMEM_SIZE + PRERAM_CBMEM_CONSOLE_SIZE + * | Preram CBMEM console | + * | (PRERAM_CBMEM_CONSOLE_SIZE) | + * +--------------------------------+ PSP_SHAREDMEM_BASE + PSP_SHAREDMEM_SIZE + * | PSP shared (vboot workbuf) | + * | (PSP_SHAREDMEM_SIZE) | + * +--------------------------------+ PSP_SHAREDMEM_BASE + * | APOB (120KiB) | + * +--------------------------------+ PSP_APOB_DRAM_ADDRESS + * | Early BSP stack | + * | (EARLYRAM_BSP_STACK_SIZE) | + * reserved_dram_start +--------------------------------+ EARLY_RESERVED_DRAM_BASE + * | DRAM | + * +--------------------------------+ 0x100000 + * | Option ROM | + * +--------------------------------+ 0xc0000 + * | Legacy VGA | + * +--------------------------------+ 0xa0000 + * | DRAM | + * +--------------------------------+ 0x0 + */ +static void read_resources(struct device *dev) +{ + uint32_t mem_usable = (uintptr_t)cbmem_top(); + unsigned int idx = 0; + const struct hob_header *hob = fsp_get_hob_list(); + const struct hob_resource *res; + struct resource *gnb_apic; + + uintptr_t early_reserved_dram_start, early_reserved_dram_end; + const struct memmap_early_dram *e = memmap_get_early_dram_usage(); + + early_reserved_dram_start = e->base; + early_reserved_dram_end = e->base + e->size; + + /* The root complex has no PCI BARs implemented, so there's no need to call + pci_dev_read_resources for it */ + + /* 0x0 - 0x9ffff */ + ram_resource_kb(dev, idx++, 0, 0xa0000 / KiB); + + /* 0xa0000 - 0xbffff: legacy VGA */ + mmio_resource_kb(dev, idx++, 0xa0000 / KiB, 0x20000 / KiB); + + /* 0xc0000 - 0xfffff: Option ROM */ + reserved_ram_resource_kb(dev, idx++, 0xc0000 / KiB, 0x40000 / KiB); + + /* 1MiB - bottom of DRAM reserved for early coreboot usage */ + ram_resource_kb(dev, idx++, (1 * MiB) / KiB, + (early_reserved_dram_start - (1 * MiB)) / KiB); + + /* DRAM reserved for early coreboot usage */ + reserved_ram_resource_kb(dev, idx++, early_reserved_dram_start / KiB, + (early_reserved_dram_end - early_reserved_dram_start) / KiB); + + /* + * top of DRAM consumed early - low top usable RAM + * cbmem_top() accounts for low UMA and TSEG if they are used. + */ + ram_resource_kb(dev, idx++, early_reserved_dram_end / KiB, + (mem_usable - early_reserved_dram_end) / KiB); + + mmconf_resource(dev, idx++); + + if (!hob) { + printk(BIOS_ERR, "Error: %s incomplete because no HOB list was found\n", + __func__); + return; + } + + for (; hob->type != HOB_TYPE_END_OF_HOB_LIST; hob = fsp_next_hob(hob)) { + + if (hob->type != HOB_TYPE_RESOURCE_DESCRIPTOR) + continue; + + res = fsp_hob_header_to_resource(hob); + + if (res->type == EFI_RESOURCE_SYSTEM_MEMORY && res->addr < mem_usable) + continue; /* 0 through low usable was set above */ + if (res->type == EFI_RESOURCE_MEMORY_MAPPED_IO) + continue; /* Done separately */ + + if (res->type == EFI_RESOURCE_SYSTEM_MEMORY) + ram_resource_kb(dev, idx++, res->addr / KiB, res->length / KiB); + else if (res->type == EFI_RESOURCE_MEMORY_RESERVED) + reserved_ram_resource_kb(dev, idx++, res->addr / KiB, res->length / KiB); + else + printk(BIOS_ERR, "Error: failed to set resources for type %d\n", + res->type); + } + + /* GNB IOAPIC resource */ + gnb_apic = new_resource(dev, idx++); + gnb_apic->base = GNB_IO_APIC_ADDR; + gnb_apic->size = 0x00001000; + gnb_apic->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; +} + +static void root_complex_init(struct device *dev) +{ + setup_ioapic((u8 *)GNB_IO_APIC_ADDR, GNB_IOAPIC_ID); +} + +static void acipgen_dptci(void) +{ + const struct soc_amd_morgana_config *config = config_of_soc(); + + /* Normal mode DPTC values. */ + struct dptc_input default_input = DPTC_INPUTS(config->thermctl_limit_degreeC, + config->sustained_power_limit_mW, + config->fast_ppt_limit_mW, + config->slow_ppt_limit_mW, + config->vrm_current_limit_mA, + config->vrm_maximum_current_limit_mA, + config->vrm_soc_current_limit_mA); + acpigen_write_alib_dptc_default((uint8_t *)&default_input, sizeof(default_input)); + + /* Low/No Battery */ + struct dptc_input no_battery_input = DPTC_INPUTS( + config->thermctl_limit_degreeC, + config->sustained_power_limit_mW, + config->fast_ppt_limit_mW, + config->slow_ppt_limit_mW, + config->vrm_current_limit_throttle_mA, + config->vrm_maximum_current_limit_throttle_mA, + config->vrm_soc_current_limit_throttle_mA); + acpigen_write_alib_dptc_no_battery((uint8_t *)&no_battery_input, + sizeof(no_battery_input)); +} + +static void root_complex_fill_ssdt(const struct device *device) +{ + acpi_fill_root_complex_tom(device); + if (CONFIG(SOC_AMD_COMMON_BLOCK_ACPI_DPTC)) + acipgen_dptci(); +} + +static const char *gnb_acpi_name(const struct device *dev) +{ + return "GNB"; +} + +static struct device_operations root_complex_operations = { + .read_resources = read_resources, + .set_resources = noop_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = root_complex_init, + .acpi_name = gnb_acpi_name, + .acpi_fill_ssdt = root_complex_fill_ssdt, +}; + +static const struct pci_driver family17_root_complex __pci_driver = { + .ops = &root_complex_operations, + .vendor = PCI_VID_AMD, + .device = PCI_DID_AMD_17H_MODEL_A0AF_NB, /* TODO: Update for Morgana */ +}; diff --git a/src/soc/amd/morgana/smihandler.c b/src/soc/amd/morgana/smihandler.c new file mode 100644 index 0000000000..1f44afa0b2 --- /dev/null +++ b/src/soc/amd/morgana/smihandler.c @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* TODO: Update for Morgana */ +/* TODO: What can be made common */ + +#include <acpi/acpi.h> +#include <amdblocks/acpi.h> +#include <amdblocks/acpimmio.h> +#include <amdblocks/psp.h> +#include <amdblocks/smi.h> +#include <amdblocks/smm.h> +#include <arch/hlt.h> +#include <arch/io.h> +#include <console/console.h> +#include <cpu/x86/cache.h> +#include <cpu/x86/smm.h> +#include <elog.h> +#include <soc/smi.h> +#include <soc/smu.h> +#include <soc/southbridge.h> +#include <types.h> + +static void fch_apmc_smi_handler(void) +{ + const uint8_t cmd = inb(pm_acpi_smi_cmd_port()); + + switch (cmd) { + case APM_CNT_ACPI_ENABLE: + acpi_clear_pm_gpe_status(); + acpi_enable_sci(); + break; + case APM_CNT_ACPI_DISABLE: + acpi_disable_sci(); + break; + case APM_CNT_ELOG_GSMI: + if (CONFIG(ELOG_GSMI)) + handle_smi_gsmi(); + break; + case APM_CNT_SMMSTORE: + if (CONFIG(SMMSTORE)) + handle_smi_store(); + break; + case APM_CNT_SMMINFO: + psp_notify_smm(); + break; + } + + mainboard_smi_apmc(cmd); +} + +/* + * Both the psp_notify_sx_info and the smu_sx_entry call will clobber the SMN index register + * during the SMN accesses. Since the SMI handler is the last thing that gets called before + * entering S3, this won't interfere with any indirect SMN accesses via the same register pair. + */ +static void fch_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) { + wbinvd(); + + clear_all_smi_status(); + + /* Do not send SMI before AcpiPm1CntBlkx00[SlpTyp] */ + pci_ctrl = pm_read32(PM_PCI_CTRL); + pci_ctrl &= ~FORCE_SLPSTATE_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)) */ + + if (slp_typ == ACPI_S3) + psp_notify_sx_info(ACPI_S3); + + smu_sx_entry(); /* Leave SlpTypeEn clear, SMU will set */ + printk(BIOS_ERR, "Error: System did not go to sleep\n"); + hlt(); + } +} + +int southbridge_io_trap_handler(int smif) +{ + return 0; +} + +/* + * Table of functions supported in the SMI handler. Note that SMI source setup + * in fch.c is unrelated to this list. + */ +static const struct smi_sources_t smi_sources[] = { + { .type = SMITYPE_SMI_CMD_PORT, .handler = fch_apmc_smi_handler }, + { .type = SMITYPE_SLP_TYP, .handler = fch_slp_typ_handler}, +}; + +void *get_smi_source_handler(int source) +{ + size_t i; + + for (i = 0 ; i < ARRAY_SIZE(smi_sources) ; i++) + if (smi_sources[i].type == source) + return smi_sources[i].handler; + + return NULL; +} diff --git a/src/soc/amd/morgana/smu.c b/src/soc/amd/morgana/smu.c new file mode 100644 index 0000000000..d8cd081bad --- /dev/null +++ b/src/soc/amd/morgana/smu.c @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <console/console.h> +#include <amdblocks/smu.h> +#include <soc/smu.h> + +/* TODO: can this be made common? */ + +/* + * Request the SMU to put system into S3, S4, or S5. On entry, SlpTyp determines S-State and + * SlpTypeEn gets set by the SMU. Function does not return if successful. + */ +void smu_sx_entry(void) +{ + struct smu_payload msg = { 0 }; /* Unused for SMC_MSG_S3ENTRY */ + + printk(BIOS_DEBUG, "SMU: Put system into S3/S4/S5\n"); + send_smu_message(SMC_MSG_S3ENTRY, &msg); +} diff --git a/src/soc/amd/morgana/uart.c b/src/soc/amd/morgana/uart.c new file mode 100644 index 0000000000..0cf1af8446 --- /dev/null +++ b/src/soc/amd/morgana/uart.c @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include <amdblocks/aoac.h> +#include <amdblocks/gpio.h> +#include <amdblocks/uart.h> +#include <commonlib/helpers.h> +#include <console/console.h> +#include <device/device.h> +#include <device/mmio.h> +#include <soc/aoac_defs.h> +#include <soc/gpio.h> +#include <soc/southbridge.h> +#include <soc/uart.h> +#include <types.h> + +static const struct { + uintptr_t base; + struct soc_amd_gpio mux[2]; +} uart_info[] = { + [0] = { APU_UART0_BASE, { + PAD_NF(GPIO_143, UART0_TXD, PULL_NONE), + PAD_NF(GPIO_141, UART0_RXD, PULL_NONE), + } }, + [1] = { APU_UART1_BASE, { + PAD_NF(GPIO_140, UART1_TXD, PULL_NONE), + PAD_NF(GPIO_142, UART1_RXD, PULL_NONE), + } }, + [2] = { APU_UART2_BASE, { + PAD_NF(GPIO_138, UART2_TXD, PULL_NONE), + PAD_NF(GPIO_136, UART2_RXD, PULL_NONE), + } }, + [3] = { APU_UART3_BASE, { + PAD_NF(GPIO_135, UART3_TXD, PULL_NONE), + PAD_NF(GPIO_137, UART3_RXD, PULL_NONE), + } }, + [4] = { APU_UART4_BASE, { + PAD_NF(GPIO_156, UART4_TXD, PULL_NONE), + PAD_NF(GPIO_155, UART4_RXD, PULL_NONE), + } }, +}; + +uintptr_t get_uart_base(unsigned int idx) +{ + if (idx >= ARRAY_SIZE(uart_info)) + return 0; + + return uart_info[idx].base; +} + +void clear_uart_legacy_config(void) +{ + write16p(FCH_LEGACY_UART_DECODE, 0); +} + +void set_uart_config(unsigned int idx) +{ + if (idx >= ARRAY_SIZE(uart_info)) + return; + + gpio_configure_pads(uart_info[idx].mux, 2); +} + +static const char *uart_acpi_name(const struct device *dev) +{ + switch (dev->path.mmio.addr) { + case APU_UART0_BASE: + return "FUR0"; + case APU_UART1_BASE: + return "FUR1"; + case APU_UART2_BASE: + return "FUR2"; + case APU_UART3_BASE: + return "FUR3"; + case APU_UART4_BASE: + return "FUR4"; + default: + return NULL; + } +} + +/* Even though this is called enable, it gets called for both enabled and disabled devices. */ +static void uart_enable(struct device *dev) +{ + unsigned int dev_id; + + switch (dev->path.mmio.addr) { + case APU_UART0_BASE: + dev_id = FCH_AOAC_DEV_UART0; + break; + case APU_UART1_BASE: + dev_id = FCH_AOAC_DEV_UART1; + break; + case APU_UART2_BASE: + dev_id = FCH_AOAC_DEV_UART2; + break; + case APU_UART3_BASE: + dev_id = FCH_AOAC_DEV_UART3; + break; + case APU_UART4_BASE: + dev_id = FCH_AOAC_DEV_UART4; + break; + default: + printk(BIOS_ERR, "%s: Unknown device: %s\n", __func__, dev_path(dev)); + return; + } + + if (dev->enabled) { + power_on_aoac_device(dev_id); + wait_for_aoac_enabled(dev_id); + } else { + power_off_aoac_device(dev_id); + } +} + +static void uart_read_resources(struct device *dev) +{ + mmio_resource_kb(dev, 0, dev->path.mmio.addr / KiB, 4); +} + +struct device_operations morgana_uart_mmio_ops = { + .read_resources = uart_read_resources, + .set_resources = noop_set_resources, + .scan_bus = scan_static_bus, + .enable = uart_enable, + .acpi_name = uart_acpi_name, + .acpi_fill_ssdt = uart_inject_ssdt, +}; diff --git a/src/soc/amd/morgana/xhci.c b/src/soc/amd/morgana/xhci.c new file mode 100644 index 0000000000..9f62b18a29 --- /dev/null +++ b/src/soc/amd/morgana/xhci.c @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for Morgana */ + +#include <amdblocks/gpio.h> +#include <amdblocks/smi.h> +#include <bootstate.h> +#include <device/device.h> +#include <device/pci_ids.h> +#include <drivers/usb/pci_xhci/pci_xhci.h> +#include <soc/pci_devs.h> +#include <soc/smi.h> + +static const struct sci_source xhci_sci_sources[] = { + { + .scimap = SMITYPE_XHC0_PME, + .gpe = GEVENT_31, + .direction = SMI_SCI_LVL_HIGH, + .level = SMI_SCI_EDG + }, + { + .scimap = SMITYPE_XHC1_PME, + .gpe = GEVENT_31, + .direction = SMI_SCI_LVL_HIGH, + .level = SMI_SCI_EDG + }, + { + .scimap = SMITYPE_XHC2_PME, + .gpe = GEVENT_31, + .direction = SMI_SCI_LVL_HIGH, + .level = SMI_SCI_EDG + } +}; + +enum cb_err pci_xhci_get_wake_gpe(const struct device *dev, int *gpe) +{ + if (dev->bus->dev->path.type != DEVICE_PATH_PCI) + return CB_ERR_ARG; + + if (dev->path.type != DEVICE_PATH_PCI) + return CB_ERR_ARG; + + if (dev->bus->dev->path.pci.devfn == PCIE_ABC_A_DEVFN) { + if (dev->path.pci.devfn == XHCI0_DEVFN) { + *gpe = xhci_sci_sources[0].gpe; + return CB_SUCCESS; + } else if (dev->path.pci.devfn == XHCI1_DEVFN) { + *gpe = xhci_sci_sources[1].gpe; + return CB_SUCCESS; + } + } else if (dev->bus->dev->path.pci.devfn == PCIE_GPP_C_DEVFN) { + if (dev->path.pci.devfn == XHCI2_DEVFN + && dev->device == PCI_DID_AMD_FAM17H_MODELA0H_XHCI2) { + *gpe = xhci_sci_sources[2].gpe; + return CB_SUCCESS; + } + } + + return CB_ERR_ARG; +} + +static void configure_xhci_sci(void *unused) +{ + gpe_configure_sci(xhci_sci_sources, ARRAY_SIZE(xhci_sci_sources) - 1); +} + +BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_ENTRY, configure_xhci_sci, NULL); |