sb/intel/i82801gx: Add the option to lock the platform

This allows to lock down spi among other things
Mostly copied from bd82x6x.

Tested on Intel DG41WV with the MRC_CACHE driver write protecting the
mrc_cache region.

Change-Id: If9c3a6118f4586d51c093edec896c347ba904b8f
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/23358
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
diff --git a/src/southbridge/intel/i82801gx/Kconfig b/src/southbridge/intel/i82801gx/Kconfig
index 9fd19ed..2670d23 100644
--- a/src/southbridge/intel/i82801gx/Kconfig
+++ b/src/southbridge/intel/i82801gx/Kconfig
@@ -26,6 +26,7 @@
 	select SOUTHBRIDGE_INTEL_COMMON_GPIO
 	select SOUTHBRIDGE_INTEL_COMMON_SMBUS
 	select SOUTHBRIDGE_INTEL_COMMON_SPI
+	select HAVE_INTEL_CHIPSET_LOCKDOWN
 
 if SOUTHBRIDGE_INTEL_I82801GX
 
diff --git a/src/southbridge/intel/i82801gx/i82801gx.h b/src/southbridge/intel/i82801gx/i82801gx.h
index 1038baf..36c79eb 100644
--- a/src/southbridge/intel/i82801gx/i82801gx.h
+++ b/src/southbridge/intel/i82801gx/i82801gx.h
@@ -368,6 +368,53 @@
 #define DEVACT_STS	0x44
 #define SS_CNT		0x50
 #define C3_RES		0x54
+#define TCO1_CNT	0x68
+
+/* SPIBAR
+ *
+ * SPI Opcode Menu setup for SPIBAR lockdown
+ * should support most common flash chips.
+ */
+
+#define PREOP		0x54
+#define OPTYPE		0x56
+#define OPMENU		0x58
+
+#define SPI_OPMENU_0 0x01 /* WRSR: Write Status Register */
+#define SPI_OPTYPE_0 0x01 /* Write, no address */
+
+#define SPI_OPMENU_1 0x02 /* BYPR: Byte Program */
+#define SPI_OPTYPE_1 0x03 /* Write, address required */
+
+#define SPI_OPMENU_2 0x03 /* READ: Read Data */
+#define SPI_OPTYPE_2 0x02 /* Read, address required */
+
+#define SPI_OPMENU_3 0x05 /* RDSR: Read Status Register */
+#define SPI_OPTYPE_3 0x00 /* Read, no address */
+
+#define SPI_OPMENU_4 0x20 /* SE20: Sector Erase 0x20 */
+#define SPI_OPTYPE_4 0x03 /* Write, address required */
+
+#define SPI_OPMENU_5 0x9f /* RDID: Read ID */
+#define SPI_OPTYPE_5 0x00 /* Read, no address */
+
+#define SPI_OPMENU_6 0xd8 /* BED8: Block Erase 0xd8 */
+#define SPI_OPTYPE_6 0x03 /* Write, address required */
+
+#define SPI_OPMENU_7 0x0b /* FAST: Fast Read */
+#define SPI_OPTYPE_7 0x02 /* Read, address required */
+
+#define SPI_OPMENU_UPPER ((SPI_OPMENU_7 << 24) | (SPI_OPMENU_6 << 16) | \
+			  (SPI_OPMENU_5 << 8) | SPI_OPMENU_4)
+#define SPI_OPMENU_LOWER ((SPI_OPMENU_3 << 24) | (SPI_OPMENU_2 << 16) | \
+			  (SPI_OPMENU_1 << 8) | SPI_OPMENU_0)
+
+#define SPI_OPTYPE ((SPI_OPTYPE_7 << 14) | (SPI_OPTYPE_6 << 12) | \
+		    (SPI_OPTYPE_5 << 10) | (SPI_OPTYPE_4 << 8) |  \
+		    (SPI_OPTYPE_3 << 6) | (SPI_OPTYPE_2 << 4) |	  \
+		    (SPI_OPTYPE_1 << 2) | (SPI_OPTYPE_0))
+
+#define SPI_OPPREFIX ((0x50 << 8) | 0x06) /* EWSR and WREN */
 
 #endif /* __ACPI__ */
 #endif				/* SOUTHBRIDGE_INTEL_I82801GX_I82801GX_H */
diff --git a/src/southbridge/intel/i82801gx/lpc.c b/src/southbridge/intel/i82801gx/lpc.c
index ab426ab..acc57a7 100644
--- a/src/southbridge/intel/i82801gx/lpc.c
+++ b/src/southbridge/intel/i82801gx/lpc.c
@@ -645,6 +645,40 @@
 	}
 }
 
+#define SPIBAR16(x) RCBA16(0x3020 + x)
+#define SPIBAR32(x) RCBA32(0x3020 + x)
+
+static void lpc_final(struct device *dev)
+{
+	u16 tco1_cnt;
+
+	if (!IS_ENABLED(CONFIG_INTEL_CHIPSET_LOCKDOWN))
+		return;
+
+	SPIBAR16(PREOP) = SPI_OPPREFIX;
+	/* Set SPI opcode menu */
+	SPIBAR16(OPTYPE) = SPI_OPTYPE;
+	SPIBAR32(OPMENU) = SPI_OPMENU_LOWER;
+	SPIBAR32(OPMENU + 4) = SPI_OPMENU_UPPER;
+
+	/* Lock SPIBAR */
+	SPIBAR16(0) = SPIBAR16(0) | (1 << 15);
+
+	/* BIOS Interface Lockdown */
+	RCBA32(0x3410) |= 1 << 0;
+
+	/* Global SMI Lock */
+	pci_or_config16(dev, GEN_PMCON_1, 1 << 4);
+
+	/* TCO_Lock */
+	tco1_cnt = inw(DEFAULT_PMBASE + 0x60 + TCO1_CNT);
+	tco1_cnt |= (1 << 12); /* TCO lock */
+	outw(tco1_cnt, DEFAULT_PMBASE + 0x60 + TCO1_CNT);
+
+	/* Indicate finalize step with post code */
+	outb(POST_OS_BOOT, 0x80);
+}
+
 static void set_subsystem(struct device *dev, unsigned int vendor,
 			  unsigned int device)
 {
@@ -698,6 +732,7 @@
 	.scan_bus		= scan_lpc_bus,
 	.enable			= i82801gx_enable,
 	.ops_pci		= &pci_ops,
+	.final			= lpc_final,
 };
 
 /* 27b0: 82801GH (ICH7 DH) */