diff options
Diffstat (limited to 'src/soc/amd')
-rw-r--r-- | src/soc/amd/common/block/include/amdblocks/psp.h | 15 | ||||
-rw-r--r-- | src/soc/amd/common/block/psp/psp.c | 92 |
2 files changed, 96 insertions, 11 deletions
diff --git a/src/soc/amd/common/block/include/amdblocks/psp.h b/src/soc/amd/common/block/include/amdblocks/psp.h index f16bb44e47..6e1a1f0f05 100644 --- a/src/soc/amd/common/block/include/amdblocks/psp.h +++ b/src/soc/amd/common/block/include/amdblocks/psp.h @@ -21,6 +21,21 @@ #include <stdint.h> #include <compiler.h> +/* Extra, Special Purpose Registers in the PSP PCI Config Space */ + +/* PSP Mirror Features Capabilities and Control Register */ +#define PSP_PCI_MIRRORCTRL1_REG 0x44 /* PSP Mirror Ctrl Reg */ +#define PMNXTPTRW_MASK 0xff /* PCI AFCR pointer mask */ +#define PMNXTPTRW_EXPOSE 0xa4 /* Pointer to expose the AFCR */ + +#define PSP_PCI_EXT_HDR_CTRL 0x48 /* Extra PCI Header Ctrl */ +#define MAGIC_ENABLES 0x34 /* Extra PCI HDR Ctl Enables */ + +#define PSP_MAILBOX_BASE 0x70 /* Mailbox offset from PCIe BAR */ + +#define MSR_CU_CBBCFG 0xc00110a2 /* PSP Pvt Blk Base Addr */ +#define BAR3HIDE BIT(12) /* Bit to hide BAR3 addr */ + /* x86 to PSP commands */ #define MBOX_BIOS_CMD_DRAM_INFO 0x01 #define MBOX_BIOS_CMD_SMM_INFO 0x02 diff --git a/src/soc/amd/common/block/psp/psp.c b/src/soc/amd/common/block/psp/psp.c index a1a0e5baec..f8b1e6b326 100644 --- a/src/soc/amd/common/block/psp/psp.c +++ b/src/soc/amd/common/block/psp/psp.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2017 Advanced Micro Devices, Inc. + * Copyright (C) 2012-2018 Advanced Micro Devices, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,13 +14,17 @@ */ #include <arch/io.h> +#include <cpu/x86/msr.h> #include <cbfs.h> #include <region_file.h> #include <timer.h> #include <device/pci_def.h> #include <bootstate.h> #include <console/console.h> +#include <device/pci_ops.h> #include <amdblocks/psp.h> +#include <soc/iomap.h> +#include <soc/northbridge.h> static const char *psp_status_nobase = "error: PSP BAR3 not assigned"; static const char *psp_status_halted = "error: PSP in halted state"; @@ -30,6 +34,73 @@ static const char *psp_status_init_timeout = "error: PSP init timeout"; static const char *psp_status_cmd_timeout = "error: PSP command timeout"; static const char *psp_status_noerror = ""; +static void psp_bar_init_early(void) +{ + u32 psp_mmio_size; + u32 value32; + u32 base, limit; + + /* Check for presence of the PSP */ + if (pci_read_config32(SOC_PSP_DEV, PCI_VENDOR_ID) == 0xffffffff) { + printk(BIOS_WARNING, "PSP: SOC_PSP_DEV device not found at D%xF%x\n", + PSP_DEV, PSP_FUNC); + return; + } + + /* Check if PSP BAR has been assigned, and if so, just return */ + if (pci_read_config32(SOC_PSP_DEV, PCI_BASE_ADDRESS_4) & + ~PCI_BASE_ADDRESS_MEM_ATTR_MASK) + return; + + /* Otherwise, do an early init of the BAR */ + pci_write_config32(SOC_PSP_DEV, PCI_BASE_ADDRESS_4, 0xffffffff); + psp_mmio_size = ~pci_read_config32(SOC_PSP_DEV, PCI_BASE_ADDRESS_4) + 1; + printk(BIOS_SPEW, "PSP: BAR size is 0x%x\n", psp_mmio_size); + /* Assign BAR to an initial temporarily defined region */ + pci_write_config32(SOC_PSP_DEV, PCI_BASE_ADDRESS_4, + PSP_MAILBOX_BAR3_BASE); + + /* Route MMIO through the northbridge */ + pci_write_config32(SOC_PSP_DEV, PCI_COMMAND, + (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER)); + limit = ((PSP_MAILBOX_BAR3_BASE + psp_mmio_size - 1) >> 8) & ~0xff; + pci_write_config32(SOC_ADDR_DEV, NB_MMIO_LIMIT_LO(7), limit); + base = (PSP_MAILBOX_BAR3_BASE >> 8) | MMIO_WE | MMIO_RE; + pci_write_config32(SOC_ADDR_DEV, NB_MMIO_BASE_LO(7), base); + pci_write_config32(SOC_PSP_DEV, PSP_PCI_EXT_HDR_CTRL, MAGIC_ENABLES); + + /* Update the capability chain */ + value32 = pci_read_config32(SOC_PSP_DEV, PSP_PCI_MIRRORCTRL1_REG); + value32 &= ~PMNXTPTRW_MASK; + value32 |= PMNXTPTRW_EXPOSE; + pci_write_config32(SOC_PSP_DEV, PSP_PCI_MIRRORCTRL1_REG, value32); +} + +static uintptr_t get_psp_bar3_addr(void) +{ + uintptr_t psp_mmio; + + /* Check for presence of the PSP */ + if (pci_read_config32(SOC_PSP_DEV, PCI_VENDOR_ID) == 0xffffffff) { + printk(BIOS_WARNING, "PSP: No SOC_PSP_DEV found at D%xF%x\n", + PSP_DEV, PSP_FUNC); + return 0; + } + + /* D8F0x48[12] is the Bar3Hide flag, check it */ + if (pci_read_config32(SOC_PSP_DEV, PSP_PCI_EXT_HDR_CTRL) & BAR3HIDE) { + psp_mmio = rdmsr(MSR_CU_CBBCFG).lo; + if (psp_mmio == 0xffffffff) { + printk(BIOS_WARNING, "PSP: BAR hidden, MSR val uninitialized\n"); + return 0; + } + return psp_mmio; + } else { + return pci_read_config32(SOC_PSP_DEV, PCI_BASE_ADDRESS_4) & + ~PCI_BASE_ADDRESS_MEM_ATTR_MASK; + } +} + static const char *status_to_string(int err) { switch (err) { @@ -52,19 +123,18 @@ static const char *status_to_string(int err) static struct psp_mbox *get_mbox_address(void) { - UINT32 base; /* UINT32 for compatibility with PspBaseLib */ - BOOLEAN bar3_status; uintptr_t baseptr; - bar3_status = GetPspBar3Addr(&base); - if (!bar3_status) { - PspBarInitEarly(); - bar3_status = GetPspBar3Addr(&base); + baseptr = get_psp_bar3_addr(); + if (baseptr == 0) { + psp_bar_init_early(); + baseptr = get_psp_bar3_addr(); + if (baseptr == 0) { + printk(BIOS_WARNING, "PSP: %s(), psp_bar_init_early() failed...\n", + __func__); + return NULL; + } } - if (!bar3_status) - return NULL; - - baseptr = base; return (struct psp_mbox *)(baseptr + PSP_MAILBOX_BASE); } |