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>
diff --git a/src/soc/amd/morgana/Kconfig b/src/soc/amd/morgana/Kconfig
new file mode 100644
index 0000000..8c7d87c
--- /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 0000000..6c80d23
--- /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 0000000..f3825f0
--- /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 0000000..55fbabb
--- /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 0000000..51a7cbd
--- /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 0000000..7ccb005
--- /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 0000000..efdce0b
--- /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 0000000..df9911c
--- /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 0000000..78c0e4c
--- /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 0000000..d4f96df
--- /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 0000000..57fac99
--- /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 0000000..2b97c6c
--- /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 0000000..8875c5e
--- /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 0000000..fe072a2
--- /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 0000000..161d86c
--- /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 0000000..fe5a1b8
--- /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 0000000..0249b8a
--- /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 0000000..f6ccf55
--- /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 0000000..1d0fc17
--- /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 0000000..f9f4649
--- /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 0000000..e1e8c26
--- /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 0000000..a68647c
--- /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 0000000..055aa9c
--- /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 0000000..873d333
--- /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 0000000..23a38ba
--- /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 0000000..132bac4
--- /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 0000000..2835c09
--- /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 0000000..c52f502
--- /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 0000000..ac85861
--- /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 0000000..eba4cd8
--- /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 0000000..d8217c6
--- /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 0000000..87db27d
--- /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 0000000..10b7249
--- /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 0000000..53b7bc2
--- /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 0000000..ab5f429
--- /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 0000000..0a6a799
--- /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 0000000..572c776
--- /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 0000000..4eb4e11
--- /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 0000000..d6ece12
--- /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 0000000..20b1cc8
--- /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 0000000..e99c525
--- /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 0000000..b622ee6
--- /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 0000000..308a861
--- /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 0000000..75f0beb
--- /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 0000000..45e0ed9
--- /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 0000000..c104a33
--- /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 0000000..47f3580
--- /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 0000000..8d1e5e4
--- /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 0000000..539ddb4
--- /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 0000000..2fc29aa
--- /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 *)&param, 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 *)&param, 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 *)&param, 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 *)&param, 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 *)&param, 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 *)&param, 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 *)&param, 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 *)&param, 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 *)&param, 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 *)&param, 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 *)&param, 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 *)&param, 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 *)&param, 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 *)&param, 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 *)&param, 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 *)&param, 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 *)&param, 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 *)&param, 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 0000000..2507ee1
--- /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 0000000..d2cba278
--- /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 0000000..83bfcee
--- /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 0000000..dce0b69
--- /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 0000000..5dd5d79
--- /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 0000000..1f44afa
--- /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 0000000..d8cd081
--- /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 0000000..0cf1af8
--- /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 0000000..9f62b18
--- /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);