soc/amd/stoneyridge: Load SMU fimware using PSP

Add the ability to locate the SMRAM-based SMU firmware early and
call the PSP library to load it prior to DRAM initialization.  This
is currently placed in bootblock to ensure the blob is loaded
before any reset occurs.

Add similar functionality in ramstage for SMU FW2 to the hook already
in place for running AmdInitEnv.  Rename the hook to make more sense.

This patch was tested using a pre-released PSP bootloader on a
google/kahlee system.

Leave the option unused until the bootloader is ready.

BUG=b:66339938

Change-Id: Iedf768e54a7c3b3e7cf07e266a6906923c0fad42
Signed-off-by: Marshall Dawson <marshalldawson3rd@gmail.com>
Reviewed-on: https://review.coreboot.org/22058
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
diff --git a/src/soc/amd/common/block/psp/Makefile.inc b/src/soc/amd/common/block/psp/Makefile.inc
index eebba16..d5f9386 100644
--- a/src/soc/amd/common/block/psp/Makefile.inc
+++ b/src/soc/amd/common/block/psp/Makefile.inc
@@ -1,2 +1,3 @@
+bootblock-$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP) += psp.c
 romstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP) += psp.c
 ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP) += psp.c
diff --git a/src/soc/amd/stoneyridge/bootblock/bootblock.c b/src/soc/amd/stoneyridge/bootblock/bootblock.c
index 461f32d..abe06fb 100644
--- a/src/soc/amd/stoneyridge/bootblock/bootblock.c
+++ b/src/soc/amd/stoneyridge/bootblock/bootblock.c
@@ -24,7 +24,10 @@
 #include <bootblock_common.h>
 #include <agesawrapper.h>
 #include <agesawrapper_call.h>
+#include <soc/pci_devs.h>
+#include <soc/northbridge.h>
 #include <soc/southbridge.h>
+#include <amdblocks/psp.h>
 
 asmlinkage void bootblock_c_entry(uint64_t base_timestamp)
 {
@@ -74,6 +77,33 @@
 		configure_stoneyridge_uart();
 }
 
+/*
+ * This step is in bootblock because the SMU FW1 must be loaded prior to
+ * issuing any reset to the system.  Set up just enough to get the command
+ * to the PSP.  A side effect of placing this step here is we will always
+ * load a RO version of FW1 and never a RW version.
+ *
+ * todo: If AMD develops a more robust methodology, move this function to
+ *       romstage.
+ */
+static void load_smu_fw1(void)
+{
+	u32 base, limit;
+
+	/* Open a posted hole from 0x80000000 : 0xfed00000-1 */
+	base =  0x80000000;
+	base = (0x80000000 >> 8) | MMIO_WE | MMIO_RE;
+	limit = (ALIGN_DOWN(HPET_BASE_ADDRESS - 1, 64 * KiB) >> 8);
+	pci_write_config32(SOC_ADDR_DEV, D18F1_MMIO_LIMIT0_LO, limit);
+	pci_write_config32(SOC_ADDR_DEV, D18F1_MMIO_BASE0_LO, base);
+
+	/* Preload a value into "BAR3" and enable it */
+	pci_write_config32(SOC_PSP_DEV, PSP_MAILBOX_BAR, PSP_MAILBOX_BAR3_BASE);
+	pci_write_config32(SOC_PSP_DEV, PSP_BAR_ENABLES, PSP_MAILBOX_BAR_EN);
+
+	psp_load_named_blob(MBOX_BIOS_CMD_SMU_FW, "smu_fw");
+}
+
 void bootblock_soc_init(void)
 {
 	if (IS_ENABLED(CONFIG_STONEYRIDGE_UART))
@@ -83,6 +113,9 @@
 	u32 val = cpuid_eax(1);
 	printk(BIOS_DEBUG, "Family_Model: %08x\n", val);
 
+	if (boot_cpu() && IS_ENABLED(CONFIG_SOC_AMD_PSP_SELECTABLE_SMU_FW))
+		load_smu_fw1();
+
 	post_code(0x37);
 	AGESAWRAPPER(amdinitreset);
 
diff --git a/src/soc/amd/stoneyridge/chip.c b/src/soc/amd/stoneyridge/chip.c
index 622e72c..8e4ab2e 100644
--- a/src/soc/amd/stoneyridge/chip.c
+++ b/src/soc/amd/stoneyridge/chip.c
@@ -23,6 +23,7 @@
 #include <soc/cpu.h>
 #include <soc/northbridge.h>
 #include <soc/southbridge.h>
+#include <amdblocks/psp.h>
 #include <agesawrapper.h>
 #include <agesawrapper_call.h>
 
@@ -78,10 +79,14 @@
 	.final = &soc_final
 };
 
-static void do_initenv(void *unused)
+static void earliest_ramstage(void *unused)
 {
 	post_code(0x46);
+	if (IS_ENABLED(CONFIG_SOC_AMD_PSP_SELECTABLE_SMU_FW))
+		psp_load_named_blob(MBOX_BIOS_CMD_SMU_FW2, "smu_fw2");
+
+	post_code(0x47);
 	AGESAWRAPPER(amdinitenv);
 }
 
-BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, do_initenv, NULL);
+BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, earliest_ramstage, NULL);