soc/amd/cezanne: add 0xcf9 reset

Change-Id: Ibb78661c102e0d0327f3e74173bf98bc40e13960
Signed-off-by: Felix Held <felix-coreboot@felixheld.de>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/48488
Reviewed-by: Marshall Dawson <marshalldawson3rd@gmail.com>
Reviewed-by: Mathew King <mathewk@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/src/soc/amd/cezanne/Kconfig b/src/soc/amd/cezanne/Kconfig
index be45de4..be4d432 100644
--- a/src/soc/amd/cezanne/Kconfig
+++ b/src/soc/amd/cezanne/Kconfig
@@ -13,6 +13,7 @@
 	select ARCH_VERSTAGE_X86_32
 	select ARCH_ROMSTAGE_X86_32
 	select ARCH_RAMSTAGE_X86_32
+	select HAVE_CF9_RESET
 	select IOAPIC
 	select RESET_VECTOR_IN_RAM
 	select SOC_AMD_COMMON
diff --git a/src/soc/amd/cezanne/Makefile.inc b/src/soc/amd/cezanne/Makefile.inc
index e7d0aea..353bdbe 100644
--- a/src/soc/amd/cezanne/Makefile.inc
+++ b/src/soc/amd/cezanne/Makefile.inc
@@ -7,10 +7,15 @@
 
 bootblock-y	+= bootblock.c
 bootblock-y	+= early_fch.c
+bootblock-y     += reset.c
 
+verstage_x86-y  += reset.c
+
+romstage-y      += reset.c
 romstage-y	+= romstage.c
 
 ramstage-y	+= chip.c
+ramstage-y      += reset.c
 
 CPPFLAGS_common += -I$(src)/soc/amd/cezanne/include
 
diff --git a/src/soc/amd/cezanne/include/soc/iomap.h b/src/soc/amd/cezanne/include/soc/iomap.h
index 96313ea..4d47f7e 100644
--- a/src/soc/amd/cezanne/include/soc/iomap.h
+++ b/src/soc/amd/cezanne/include/soc/iomap.h
@@ -4,6 +4,7 @@
 #define AMD_CEZANNE_IOMAP_H
 
 /* I/O Ranges */
-#define SMB_BASE_ADDR			0xb00
+#define NCP_ERR				0x00f0
+#define SMB_BASE_ADDR			0x0b00
 
 #endif /* AMD_CEZANNE_IOMAP_H */
diff --git a/src/soc/amd/cezanne/include/soc/reset.h b/src/soc/amd/cezanne/include/soc/reset.h
new file mode 100644
index 0000000..4cb94ce
--- /dev/null
+++ b/src/soc/amd/cezanne/include/soc/reset.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef AMD_CEZANNE_RESET_H
+#define AMD_CEZANNE_RESET_H
+
+void set_warm_reset_flag(void);
+int is_warm_reset(void);
+
+#endif /* AMD_CEZANNE_RESET_H */
diff --git a/src/soc/amd/cezanne/include/soc/southbridge.h b/src/soc/amd/cezanne/include/soc/southbridge.h
index 2456ebc..03ee2bb 100644
--- a/src/soc/amd/cezanne/include/soc/southbridge.h
+++ b/src/soc/amd/cezanne/include/soc/southbridge.h
@@ -5,6 +5,13 @@
 
 #include <soc/iomap.h>
 
+/* Power management registers:  0xfed80300 or index/data at IO 0xcd6/cd7 */
+#define PWR_RESET_CFG			0x10
+#define   TOGGLE_ALL_PWR_GOOD		(1 << 1)
+
+/* IO 0xf0 NCP Error */
+#define   NCP_WARM_BOOT			(1 << 7) /* Write-once */
+
 void fch_pre_init(void);
 void fch_early_init(void);
 
diff --git a/src/soc/amd/cezanne/reset.c b/src/soc/amd/cezanne/reset.c
new file mode 100644
index 0000000..89b5b80
--- /dev/null
+++ b/src/soc/amd/cezanne/reset.c
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <arch/io.h>
+#include <cf9_reset.h>
+#include <reset.h>
+#include <soc/reset.h>
+#include <soc/southbridge.h>
+#include <amdblocks/acpimmio.h>
+#include <amdblocks/reset.h>
+
+void set_warm_reset_flag(void)
+{
+	uint8_t ncp = inw(NCP_ERR);
+
+	outb(NCP_ERR, ncp | NCP_WARM_BOOT);
+}
+
+int is_warm_reset(void)
+{
+	return !!(inb(NCP_ERR) & NCP_WARM_BOOT);
+}
+
+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)
+{
+	set_warm_reset_flag();
+
+	/* Assert reset signals only. */
+	outb(RST_CPU | SYS_RST, RST_CNT);
+}
+
+void do_board_reset(void)
+{
+	/* TODO: Would a warm_reset() suffice? */
+	do_cold_reset();
+}