ACPI: Add helper fill_fadt_extended_pm_io()

Once platform code has filled in the (legacy) ACPI PM register
map, added function will fill in the extended entries in FADT.

TEST=samsung/lumpy and amd/mandolin FADT stays unchanged.

Change-Id: I90925fce35458cf5480bfefc7cdddebd41b42058
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/74913
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin L Roth <gaumless@gmail.com>
diff --git a/src/acpi/Makefile.inc b/src/acpi/Makefile.inc
index efa7e3b..0c49e68 100644
--- a/src/acpi/Makefile.inc
+++ b/src/acpi/Makefile.inc
@@ -14,6 +14,7 @@
 ramstage-y += pld.c
 ramstage-y += sata.c
 ramstage-y += soundwire.c
+ramstage-y += fadt_filler.c
 
 all-y += acpi_pm.c
 smm-y += acpi_pm.c
diff --git a/src/acpi/fadt_filler.c b/src/acpi/fadt_filler.c
new file mode 100644
index 0000000..af65dbb
--- /dev/null
+++ b/src/acpi/fadt_filler.c
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <acpi/acpi.h>
+#include <console/console.h>
+#include <stdint.h>
+
+static void fill_x_pm_io(acpi_addr_t *x_pm_blk, int access_size, uint16_t ioport, uint8_t len)
+{
+	x_pm_blk->space_id = ACPI_ADDRESS_SPACE_IO;
+	x_pm_blk->bit_width = len * 8;
+	x_pm_blk->bit_offset = 0;
+	x_pm_blk->access_size = access_size;
+	x_pm_blk->addrl = ioport;
+	x_pm_blk->addrh = 0x0;
+}
+
+static void do_sanity_error(const char *func, const int line)
+{
+	printk(BIOS_ERR, "ACPI: FADT error detected, %s line %d.\n", func, line);
+}
+
+#define fadt_sanity(x)	do { if (!(x)) do_sanity_error(__func__, __LINE__); } while (0)
+
+void fill_fadt_extended_pm_io(acpi_fadt_t *fadt)
+{
+	fadt_sanity(fadt->pm1a_evt_blk && (fadt->pm1_evt_len >= 4));
+
+	/* Upper word is reserved and Linux complains about 32 bit. */
+	fadt_sanity(fadt->pm1a_cnt_blk && (fadt->pm1_cnt_len == 2));
+
+	fill_x_pm_io(&fadt->x_pm1a_evt_blk, ACPI_ACCESS_SIZE_WORD_ACCESS,
+		     fadt->pm1a_evt_blk, fadt->pm1_evt_len);
+
+	fill_x_pm_io(&fadt->x_pm1a_cnt_blk, ACPI_ACCESS_SIZE_WORD_ACCESS,
+		     fadt->pm1a_cnt_blk, fadt->pm1_cnt_len);
+
+	if (fadt->pm1b_evt_blk)
+		fill_x_pm_io(&fadt->x_pm1b_evt_blk, ACPI_ACCESS_SIZE_WORD_ACCESS,
+			     fadt->pm1b_evt_blk, fadt->pm1_evt_len);
+
+	if (fadt->pm1b_cnt_blk)
+		fill_x_pm_io(&fadt->x_pm1b_cnt_blk, ACPI_ACCESS_SIZE_WORD_ACCESS,
+			     fadt->pm1b_cnt_blk, fadt->pm1_cnt_len);
+
+	if (fadt->pm_tmr_blk) {
+		fadt_sanity(fadt->pm_tmr_len == 4);
+		fill_x_pm_io(&fadt->x_pm_tmr_blk, ACPI_ACCESS_SIZE_DWORD_ACCESS,
+			     fadt->pm_tmr_blk, fadt->pm_tmr_len);
+	}
+
+	if (fadt->pm2_cnt_blk)
+		fill_x_pm_io(&fadt->x_pm2_cnt_blk, ACPI_ACCESS_SIZE_BYTE_ACCESS,
+			     fadt->pm2_cnt_blk, fadt->pm2_cnt_len);
+
+	/*
+	 * Windows 10 requires x_gpe0_blk to be set starting with FADT revision 5.
+	 * The bit_width field intentionally overflows here.
+	 * The OSPM can instead use the values in `fadt->gpe0_blk{,_len}`, which
+	 * seems to work fine on Linux 5.0 and Windows 10.
+	 *
+	 * FIXME: GPE1_BASE is not initialised.
+	 *
+	 */
+
+	if (fadt->gpe0_blk)
+		fill_x_pm_io(&fadt->x_gpe0_blk, ACPI_ACCESS_SIZE_BYTE_ACCESS,
+			     fadt->gpe0_blk, fadt->gpe0_blk_len);
+
+	if (fadt->gpe1_blk)
+		fill_x_pm_io(&fadt->x_gpe1_blk, ACPI_ACCESS_SIZE_BYTE_ACCESS,
+			     fadt->gpe1_blk, fadt->gpe1_blk_len);
+}
diff --git a/src/include/acpi/acpi.h b/src/include/acpi/acpi.h
index 151cdd0..1d68b8e 100644
--- a/src/include/acpi/acpi.h
+++ b/src/include/acpi/acpi.h
@@ -1537,6 +1537,8 @@
 void soc_fill_fadt(acpi_fadt_t *fadt);
 void mainboard_fill_fadt(acpi_fadt_t *fadt);
 
+void fill_fadt_extended_pm_io(acpi_fadt_t *fadt);
+
 void acpi_fill_gnvs(void);
 void acpi_fill_cnvs(void);
 
diff --git a/src/soc/amd/common/block/acpi/acpi.c b/src/soc/amd/common/block/acpi/acpi.c
index 5b4ef29..3ec2ec0 100644
--- a/src/soc/amd/common/block/acpi/acpi.c
+++ b/src/soc/amd/common/block/acpi/acpi.c
@@ -95,33 +95,7 @@
 
 void fill_fadt_extended_pm_regs(acpi_fadt_t *fadt)
 {
-	fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
-	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 = fadt->pm1a_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 = fadt->pm1_cnt_len * 8;
-	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 = fadt->pm1a_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 = fadt->pm_tmr_len * 8;
-	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 = fadt->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 = fadt->gpe0_blk_len * 8;
-	fadt->x_gpe0_blk.bit_offset = 0;
-	fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
-	fadt->x_gpe0_blk.addrh = 0x0;
+	fill_fadt_extended_pm_io(fadt);
 }
 
 int acpi_get_sleep_type(void)
diff --git a/src/soc/intel/alderlake/acpi.c b/src/soc/intel/alderlake/acpi.c
index 9e0e1bd..1dc14be7 100644
--- a/src/soc/intel/alderlake/acpi.c
+++ b/src/soc/intel/alderlake/acpi.c
@@ -155,12 +155,8 @@
 
 	fadt->pm_tmr_blk = pmbase + PM1_TMR;
 	fadt->pm_tmr_len = 4;
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->pm_tmr_blk;
-	fadt->x_pm_tmr_blk.addrh = 0x0;
+
+	fill_fadt_extended_pm_io(fadt);
 
 	if (config->s0ix_enable)
 		fadt->flags |= ACPI_FADT_LOW_PWR_IDLE_S0;
diff --git a/src/soc/intel/apollolake/acpi.c b/src/soc/intel/apollolake/acpi.c
index 68153f0..b84e454 100644
--- a/src/soc/intel/apollolake/acpi.c
+++ b/src/soc/intel/apollolake/acpi.c
@@ -103,14 +103,9 @@
 
 	fadt->pm_tmr_len = 4;
 
-	fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
+	fill_fadt_extended_pm_io(fadt);
 
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	fadt->x_pm_tmr_blk.bit_offset = 0;
-	fadt->x_pm_tmr_blk.addrh = 0x0;
-	fadt->x_pm_tmr_blk.addrl = fadt->pm_tmr_blk;
-	fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+	fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
 
 	if (cfg->lpss_s0ix_enable)
 		fadt->flags |= ACPI_FADT_LOW_PWR_IDLE_S0;
diff --git a/src/soc/intel/baytrail/fadt.c b/src/soc/intel/baytrail/fadt.c
index e4e225e..7f48253 100644
--- a/src/soc/intel/baytrail/fadt.c
+++ b/src/soc/intel/baytrail/fadt.c
@@ -20,6 +20,9 @@
 	fadt->pm2_cnt_len = 1;
 	fadt->pm_tmr_len = 4;
 	fadt->gpe0_blk_len = 2 * (GPE0_EN - GPE0_STS);
+
+	fill_fadt_extended_pm_io(fadt);
+
 	fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
 
 	fadt->flags |= ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
@@ -27,44 +30,4 @@
 			ACPI_FADT_SEALED_CASE | ACPI_FADT_S4_RTC_WAKE |
 			ACPI_FADT_PLATFORM_CLOCK;
 
-	fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
-	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 = fadt->pm1a_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 = fadt->pm1_cnt_len * 8;
-	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 = fadt->pm1a_cnt_blk;
-	fadt->x_pm1a_cnt_blk.addrh = 0x0;
-
-	fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
-	fadt->x_pm2_cnt_blk.bit_offset = 0;
-	fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
-	fadt->x_pm2_cnt_blk.addrh = 0x0;
-
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->pm_tmr_blk;
-	fadt->x_pm_tmr_blk.addrh = 0x0;
-
-	/*
-	 * Windows 10 requires x_gpe0_blk to be set starting with FADT revision 5.
-	 * The bit_width field intentionally overflows here.
-	 * The OSPM can instead use the values in `fadt->gpe0_blk{,_len}`, which
-	 * seems to work fine on Linux 5.0 and Windows 10.
-	 */
-	fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_gpe0_blk.bit_width = fadt->gpe0_blk_len * 8;
-	fadt->x_gpe0_blk.bit_offset = 0;
-	fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
-	fadt->x_gpe0_blk.addrh = 0x0;
 }
diff --git a/src/soc/intel/braswell/fadt.c b/src/soc/intel/braswell/fadt.c
index ac1653d..749d54b 100644
--- a/src/soc/intel/braswell/fadt.c
+++ b/src/soc/intel/braswell/fadt.c
@@ -21,51 +21,13 @@
 	fadt->pm2_cnt_len = 1;
 	fadt->pm_tmr_len = 4;
 	fadt->gpe0_blk_len = 2 * (GPE0_EN - GPE0_STS);
+
+	fill_fadt_extended_pm_io(fadt);
+
 	fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
 
 	fadt->flags |= ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
 			ACPI_FADT_SLEEP_BUTTON |
 			ACPI_FADT_SEALED_CASE | ACPI_FADT_S4_RTC_WAKE |
 			ACPI_FADT_PLATFORM_CLOCK;
-
-	fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
-	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 = fadt->pm1a_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 = fadt->pm1_cnt_len * 8;
-	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 = fadt->pm1a_cnt_blk;
-	fadt->x_pm1a_cnt_blk.addrh = 0x0;
-
-	fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
-	fadt->x_pm2_cnt_blk.bit_offset = 0;
-	fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
-	fadt->x_pm2_cnt_blk.addrh = 0x0;
-
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->pm_tmr_blk;
-	fadt->x_pm_tmr_blk.addrh = 0x0;
-
-	/*
-	 * Windows 10 requires x_gpe0_blk to be set starting with FADT revision 5.
-	 * The bit_width field intentionally overflows here.
-	 * The OSPM can instead use the values in `fadt->gpe0_blk{,_len}`, which
-	 * seems to work fine on Linux 5.0 and Windows 10.
-	 */
-	fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_gpe0_blk.bit_width = fadt->gpe0_blk_len * 8;
-	fadt->x_gpe0_blk.bit_offset = 0;
-	fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
-	fadt->x_gpe0_blk.addrh = 0x0;
 }
diff --git a/src/soc/intel/broadwell/pch/fadt.c b/src/soc/intel/broadwell/pch/fadt.c
index 4e74d58..2f02b0f 100644
--- a/src/soc/intel/broadwell/pch/fadt.c
+++ b/src/soc/intel/broadwell/pch/fadt.c
@@ -20,6 +20,9 @@
 	fadt->pm2_cnt_len = 1;
 	fadt->pm_tmr_len = 4;
 	fadt->gpe0_blk_len = 32;
+
+	fill_fadt_extended_pm_io(fadt);
+
 	fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
 
 	fadt->flags |= ACPI_FADT_WBINVD |
@@ -28,45 +31,4 @@
 		       ACPI_FADT_SEALED_CASE |
 		       ACPI_FADT_S4_RTC_WAKE |
 		       ACPI_FADT_PLATFORM_CLOCK;
-
-	fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
-	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 = fadt->pm1a_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 = fadt->pm1_cnt_len * 8;
-	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 = fadt->pm1a_cnt_blk;
-	fadt->x_pm1a_cnt_blk.addrh = 0x0;
-
-	fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
-	fadt->x_pm2_cnt_blk.bit_offset = 0;
-	fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
-	fadt->x_pm2_cnt_blk.addrh = 0x0;
-
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->pm_tmr_blk;
-	fadt->x_pm_tmr_blk.addrh = 0x0;
-
-	/*
-	 * Windows 10 requires x_gpe0_blk to be set starting with FADT revision 5.
-	 * The bit_width field intentionally overflows here.
-	 * The OSPM can instead use the values in `fadt->gpe0_blk{,_len}`, which
-	 * seems to work fine on Linux 5.0 and Windows 10.
-	 */
-	fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_gpe0_blk.bit_width = fadt->gpe0_blk_len * 8;
-	fadt->x_gpe0_blk.bit_offset = 0;
-	fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
-	fadt->x_gpe0_blk.addrh = 0x0;
 }
diff --git a/src/soc/intel/cannonlake/acpi.c b/src/soc/intel/cannonlake/acpi.c
index 4bd0063..62462a8 100644
--- a/src/soc/intel/cannonlake/acpi.c
+++ b/src/soc/intel/cannonlake/acpi.c
@@ -154,12 +154,8 @@
 
 	fadt->pm_tmr_blk = pmbase + PM1_TMR;
 	fadt->pm_tmr_len = 4;
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->pm_tmr_blk;
-	fadt->x_pm_tmr_blk.addrh = 0x0;
+
+	fill_fadt_extended_pm_io(fadt);
 
 	if (config->s0ix_enable)
 		fadt->flags |= ACPI_FADT_LOW_PWR_IDLE_S0;
diff --git a/src/soc/intel/common/block/acpi/acpi.c b/src/soc/intel/common/block/acpi/acpi.c
index 2c27b15..af439a8 100644
--- a/src/soc/intel/common/block/acpi/acpi.c
+++ b/src/soc/intel/common/block/acpi/acpi.c
@@ -105,6 +105,7 @@
 	/* GPE0 STS/EN pairs each 32 bits wide. */
 	fadt->gpe0_blk_len = 2 * GPE0_REG_MAX * sizeof(uint32_t);
 
+	fill_fadt_extended_pm_io(fadt);
 
 	fadt->flags |= ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
 			ACPI_FADT_SLEEP_BUTTON |
@@ -112,33 +113,6 @@
 
 	if (CONFIG(USE_PM_ACPI_TIMER))
 		fadt->flags |= ACPI_FADT_PLATFORM_CLOCK;
-
-	fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
-	fadt->x_pm1a_evt_blk.bit_offset = 0;
-	fadt->x_pm1a_evt_blk.addrh = 0x0;
-	fadt->x_pm1a_evt_blk.addrl = fadt->pm1a_evt_blk;
-	fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
-
-	fadt->x_pm1a_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm1a_cnt_blk.bit_width = fadt->pm1_cnt_len * 8;
-	fadt->x_pm1a_cnt_blk.bit_offset = 0;
-	fadt->x_pm1a_cnt_blk.addrh = 0x0;
-	fadt->x_pm1a_cnt_blk.addrl = fadt->pm1a_cnt_blk;
-	fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
-
-	/*
-	 * Windows 10 requires x_gpe0_blk to be set starting with FADT revision 5.
-	 * The bit_width field intentionally overflows here.
-	 * The OSPM can instead use the values in `fadt->gpe0_blk{,_len}`, which
-	 * seems to work fine on Linux 5.0 and Windows 10.
-	 */
-	fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_gpe0_blk.bit_width = fadt->gpe0_blk_len * 8;
-	fadt->x_gpe0_blk.bit_offset = 0;
-	fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
-	fadt->x_gpe0_blk.addrh = 0x0;
 }
 
 unsigned long southbridge_write_acpi_tables(const struct device *device,
diff --git a/src/soc/intel/denverton_ns/acpi.c b/src/soc/intel/denverton_ns/acpi.c
index 6ddcc08..d0fde3e 100644
--- a/src/soc/intel/denverton_ns/acpi.c
+++ b/src/soc/intel/denverton_ns/acpi.c
@@ -97,21 +97,8 @@
 
 	fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
 
-	/* PM2 Control Registers */
-	fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
-	fadt->x_pm2_cnt_blk.bit_offset = 0;
-	fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
-	fadt->x_pm2_cnt_blk.addrh = 0x0;
-
-	/* PM1 Timer Register */
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->pm_tmr_blk;
-	fadt->x_pm_tmr_blk.addrh = 0x0;
+	/* PM Extended Registers */
+	fill_fadt_extended_pm_io(fadt);
 }
 
 static acpi_tstate_t denverton_tss_table[] = {
diff --git a/src/soc/intel/elkhartlake/acpi.c b/src/soc/intel/elkhartlake/acpi.c
index 6deee1b..f566ce5 100644
--- a/src/soc/intel/elkhartlake/acpi.c
+++ b/src/soc/intel/elkhartlake/acpi.c
@@ -153,12 +153,9 @@
 
 	fadt->pm_tmr_blk = pmbase + PM1_TMR;
 	fadt->pm_tmr_len = 4;
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->pm_tmr_blk;
-	fadt->x_pm_tmr_blk.addrh = 0x0;
+
+	fill_fadt_extended_pm_io(fadt);
+
 	fadt->preferred_pm_profile = PM_MOBILE;
 
 	if (config->s0ix_enable)
diff --git a/src/soc/intel/jasperlake/acpi.c b/src/soc/intel/jasperlake/acpi.c
index 4680e4d..6cf7ef5 100644
--- a/src/soc/intel/jasperlake/acpi.c
+++ b/src/soc/intel/jasperlake/acpi.c
@@ -153,12 +153,8 @@
 
 	fadt->pm_tmr_blk = pmbase + PM1_TMR;
 	fadt->pm_tmr_len = 4;
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->pm_tmr_blk;
-	fadt->x_pm_tmr_blk.addrh = 0x0;
+
+	fill_fadt_extended_pm_io(fadt);
 
 	if (config->s0ix_enable)
 		fadt->flags |= ACPI_FADT_LOW_PWR_IDLE_S0;
diff --git a/src/soc/intel/meteorlake/acpi.c b/src/soc/intel/meteorlake/acpi.c
index c6e7cab..ca4e5e1 100644
--- a/src/soc/intel/meteorlake/acpi.c
+++ b/src/soc/intel/meteorlake/acpi.c
@@ -156,12 +156,8 @@
 
 	fadt->pm_tmr_blk = pmbase + PM1_TMR;
 	fadt->pm_tmr_len = 4;
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->pm_tmr_blk;
-	fadt->x_pm_tmr_blk.addrh = 0x0;
+
+	fill_fadt_extended_pm_io(fadt);
 
 	if (config->s0ix_enable)
 		fadt->flags |= ACPI_FADT_LOW_PWR_IDLE_S0;
diff --git a/src/soc/intel/skylake/fadt.c b/src/soc/intel/skylake/fadt.c
index 68aab47..5c97f4e 100644
--- a/src/soc/intel/skylake/fadt.c
+++ b/src/soc/intel/skylake/fadt.c
@@ -16,6 +16,8 @@
 	fadt->pm2_cnt_len = 1;
 	fadt->pm_tmr_len = 4;
 
+	fill_fadt_extended_pm_io(fadt);
+
 	fadt->iapc_boot_arch = ACPI_FADT_LEGACY_FREE;
 	if (!CONFIG(NO_FADT_8042))
 		fadt->iapc_boot_arch |= ACPI_FADT_8042;
@@ -23,17 +25,5 @@
 	if (config->s0ix_enable)
 		fadt->flags |= ACPI_FADT_LOW_PWR_IDLE_S0;
 
-	fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
-	fadt->x_pm2_cnt_blk.bit_offset = 0;
-	fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
-	fadt->x_pm2_cnt_blk.addrh = 0x0;
 
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->pm_tmr_blk;
-	fadt->x_pm_tmr_blk.addrh = 0x0;
 }
diff --git a/src/soc/intel/tigerlake/acpi.c b/src/soc/intel/tigerlake/acpi.c
index 305ba1b..9ff6e18 100644
--- a/src/soc/intel/tigerlake/acpi.c
+++ b/src/soc/intel/tigerlake/acpi.c
@@ -153,12 +153,8 @@
 
 	fadt->pm_tmr_blk = pmbase + PM1_TMR;
 	fadt->pm_tmr_len = 4;
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->pm_tmr_blk;
-	fadt->x_pm_tmr_blk.addrh = 0x0;
+
+	fill_fadt_extended_pm_io(fadt);
 
 	if (config->s0ix_enable)
 		fadt->flags |= ACPI_FADT_LOW_PWR_IDLE_S0;
diff --git a/src/soc/intel/xeon_sp/skx/soc_acpi.c b/src/soc/intel/xeon_sp/skx/soc_acpi.c
index eedf387..35e3ea1 100644
--- a/src/soc/intel/xeon_sp/skx/soc_acpi.c
+++ b/src/soc/intel/xeon_sp/skx/soc_acpi.c
@@ -50,22 +50,8 @@
 
 	fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
 
-	/* PM2 Control Registers */
-	fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
-	fadt->x_pm2_cnt_blk.bit_offset = 0;
-	fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
-	fadt->x_pm2_cnt_blk.addrh = 0x0;
-
-	/* PM1 Timer Register */
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->pm_tmr_blk;
-	fadt->x_pm_tmr_blk.addrh = 0x0;
-
+	/* PM Extended Registers */
+	fill_fadt_extended_pm_io(fadt);
 }
 
 void uncore_inject_dsdt(const struct device *device)
diff --git a/src/soc/intel/xeon_sp/spr/soc_acpi.c b/src/soc/intel/xeon_sp/spr/soc_acpi.c
index 933cb97..193b859 100644
--- a/src/soc/intel/xeon_sp/spr/soc_acpi.c
+++ b/src/soc/intel/xeon_sp/spr/soc_acpi.c
@@ -49,35 +49,8 @@
 	fadt->pm2_cnt_blk = pmbase + PM2_CNT;
 	fadt->pm2_cnt_len = 1;
 
-	/* PM2 Control Registers */
-	fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
-	fadt->x_pm2_cnt_blk.bit_offset = 0;
-	fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
-	fadt->x_pm2_cnt_blk.addrh = 0x0;
-
-	/* PM1 Timer Register */
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->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 = fadt->gpe0_blk_len * 8;
-	fadt->x_gpe0_blk.bit_offset = 0;
-	fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
-	fadt->x_gpe0_blk.addrh = 0x0;
-
-	fadt->x_gpe1_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_gpe1_blk.bit_width = fadt->gpe1_blk_len * 8;
-	fadt->x_gpe1_blk.bit_offset = 0;
-	fadt->x_gpe1_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_gpe1_blk.addrl = fadt->gpe1_blk;
-	fadt->x_gpe1_blk.addrh = 0x0;
+	/* PM Extended Registers */
+	fill_fadt_extended_pm_io(fadt);
 }
 
 static void create_dsdt_iou_pci_resource(uint8_t socket, uint8_t stack, const STACK_RES *ri,
diff --git a/src/southbridge/amd/pi/hudson/fadt.c b/src/southbridge/amd/pi/hudson/fadt.c
index 701ceed..34d67b4 100644
--- a/src/southbridge/amd/pi/hudson/fadt.c
+++ b/src/southbridge/amd/pi/hudson/fadt.c
@@ -36,6 +36,8 @@
 	fadt->pm_tmr_len = 4;	/* 32 bits */
 	fadt->gpe0_blk_len = 8;	/* 64 bits */
 
+	fill_fadt_extended_pm_io(fadt);
+
 	fadt->duty_offset = 1;	/* CLK_VAL bits 3:1 */
 	fadt->duty_width = 3;	/* CLK_VAL bits 3:1 */
 	fadt->iapc_boot_arch = FADT_BOOT_ARCH;	/* See table 5-10 */
@@ -52,32 +54,4 @@
 
 	fadt->x_firmware_ctl_l = 0;	/* set to 0 if firmware_ctrl is used */
 	fadt->x_firmware_ctl_h = 0;
-
-	fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
-	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 = fadt->pm1a_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 = fadt->pm1_cnt_len * 8;
-	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 = fadt->pm1a_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 = fadt->pm_tmr_len * 8;
-	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 = fadt->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 = fadt->gpe0_blk_len * 8;
-	fadt->x_gpe0_blk.bit_offset = 0;
-	fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
-	fadt->x_gpe0_blk.addrh = 0x0;
 }
diff --git a/src/southbridge/intel/bd82x6x/fadt.c b/src/southbridge/intel/bd82x6x/fadt.c
index c7d5428..98283ce 100644
--- a/src/southbridge/intel/bd82x6x/fadt.c
+++ b/src/southbridge/intel/bd82x6x/fadt.c
@@ -24,6 +24,8 @@
 	fadt->pm_tmr_len = 4;
 	fadt->gpe0_blk_len = 16;
 
+	fill_fadt_extended_pm_io(fadt);
+
 	fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
 
 	fadt->flags |= ACPI_FADT_WBINVD |
@@ -32,42 +34,8 @@
 			ACPI_FADT_SEALED_CASE |
 			ACPI_FADT_S4_RTC_WAKE |
 			ACPI_FADT_PLATFORM_CLOCK;
+
 	if (chip->docking_supported) {
 		fadt->flags |= ACPI_FADT_DOCKING_SUPPORTED;
 	}
-
-	fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
-	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 = fadt->pm1a_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 = fadt->pm1_cnt_len * 8;
-	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 = fadt->pm1a_cnt_blk;
-	fadt->x_pm1a_cnt_blk.addrh = 0x0;
-
-	fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
-	fadt->x_pm2_cnt_blk.bit_offset = 0;
-	fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
-	fadt->x_pm2_cnt_blk.addrh = 0x0;
-
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->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 = fadt->gpe0_blk_len * 8;
-	fadt->x_gpe0_blk.bit_offset = 0;
-	fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
-	fadt->x_gpe0_blk.addrh = 0x0;
 }
diff --git a/src/southbridge/intel/i82371eb/fadt.c b/src/southbridge/intel/i82371eb/fadt.c
index 551ec8f..e78ba42 100644
--- a/src/southbridge/intel/i82371eb/fadt.c
+++ b/src/southbridge/intel/i82371eb/fadt.c
@@ -29,6 +29,8 @@
 	fadt->pm_tmr_len = 4;
 	fadt->gpe0_blk_len = 4;
 
+	fill_fadt_extended_pm_io(fadt);
+
 	/*
 	 * bit  meaning
 	 * 0    1: We have user-visible legacy devices
@@ -90,32 +92,4 @@
 	 */
 	fadt->flags |= ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED | ACPI_FADT_SLEEP_BUTTON |
 		       ACPI_FADT_S4_RTC_WAKE;
-
-	fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
-	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 = fadt->pm1a_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 = fadt->pm1_cnt_len * 8;
-	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 = fadt->pm1a_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 = fadt->pm_tmr_len * 8;
-	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 = fadt->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 = fadt->gpe0_blk_len * 8;
-	fadt->x_gpe0_blk.bit_offset = 0;
-	fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
-	fadt->x_gpe0_blk.addrh = 0x0;
 }
diff --git a/src/southbridge/intel/i82801dx/fadt.c b/src/southbridge/intel/i82801dx/fadt.c
index aeb7d45..0b21f8b 100644
--- a/src/southbridge/intel/i82801dx/fadt.c
+++ b/src/southbridge/intel/i82801dx/fadt.c
@@ -18,36 +18,10 @@
 	fadt->pm_tmr_len = 4;
 	fadt->gpe0_blk_len = 8;
 
+	fill_fadt_extended_pm_io(fadt);
+
 	fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
 
 	fadt->flags |= ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED | ACPI_FADT_SLEEP_BUTTON |
 			ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK;
-
-	fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
-	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 = fadt->pm1a_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 = fadt->pm1_cnt_len * 8;
-	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 = fadt->pm1a_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 = fadt->pm_tmr_len * 8;
-	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 = fadt->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 = fadt->gpe0_blk_len * 8;
-	fadt->x_gpe0_blk.bit_offset = 0;
-	fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
-	fadt->x_gpe0_blk.addrh = 0x0;
 }
diff --git a/src/southbridge/intel/i82801gx/fadt.c b/src/southbridge/intel/i82801gx/fadt.c
index 98861c5..1eb095f 100644
--- a/src/southbridge/intel/i82801gx/fadt.c
+++ b/src/southbridge/intel/i82801gx/fadt.c
@@ -33,45 +33,13 @@
 	else
 		fadt->duty_width = 0;
 
+	fill_fadt_extended_pm_io(fadt);
+
 	fadt->iapc_boot_arch = ACPI_FADT_8042 | ACPI_FADT_LEGACY_DEVICES;
 	fadt->flags |= (ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED
 		       | ACPI_FADT_SLEEP_BUTTON | ACPI_FADT_S4_RTC_WAKE
 		       | ACPI_FADT_PLATFORM_CLOCK | ACPI_FADT_C2_MP_SUPPORTED);
+
 	if (chip->docking_supported)
 		fadt->flags |= ACPI_FADT_DOCKING_SUPPORTED;
-
-	fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
-	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 = fadt->pm1a_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 = fadt->pm1_cnt_len * 8;
-	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 = fadt->pm1a_cnt_blk;
-	fadt->x_pm1a_cnt_blk.addrh = 0x0;
-
-	fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
-	fadt->x_pm2_cnt_blk.bit_offset = 0;
-	fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
-	fadt->x_pm2_cnt_blk.addrh = 0x0;
-
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->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 = fadt->gpe0_blk_len * 8;
-	fadt->x_gpe0_blk.bit_offset = 0;
-	fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
-	fadt->x_gpe0_blk.addrh = 0x0;
 }
diff --git a/src/southbridge/intel/i82801ix/fadt.c b/src/southbridge/intel/i82801ix/fadt.c
index f8cca2d..795a4c4 100644
--- a/src/southbridge/intel/i82801ix/fadt.c
+++ b/src/southbridge/intel/i82801ix/fadt.c
@@ -26,43 +26,10 @@
 	fadt->duty_offset = 1;
 	fadt->duty_width = 3;
 
+	fill_fadt_extended_pm_io(fadt);
+
 	fadt->iapc_boot_arch = ACPI_FADT_LEGACY_FREE;
 	fadt->flags |= ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
 			ACPI_FADT_SLEEP_BUTTON | ACPI_FADT_S4_RTC_WAKE |
 			ACPI_FADT_DOCKING_SUPPORTED | ACPI_FADT_PLATFORM_CLOCK;
-
-	fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
-	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 = fadt->pm1a_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 = fadt->pm1_cnt_len * 8;
-	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 = fadt->pm1a_cnt_blk;
-	fadt->x_pm1a_cnt_blk.addrh = 0x0;
-
-	fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
-	fadt->x_pm2_cnt_blk.bit_offset = 0;
-	fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
-	fadt->x_pm2_cnt_blk.addrh = 0x0;
-
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->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 = fadt->gpe0_blk_len * 8;
-	fadt->x_gpe0_blk.bit_offset = 0;
-	fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
-	fadt->x_gpe0_blk.addrh = 0x0;
 }
diff --git a/src/southbridge/intel/i82801jx/fadt.c b/src/southbridge/intel/i82801jx/fadt.c
index e7a9104..0a64fa9 100644
--- a/src/southbridge/intel/i82801jx/fadt.c
+++ b/src/southbridge/intel/i82801jx/fadt.c
@@ -26,43 +26,10 @@
 	fadt->duty_offset = 1;
 	fadt->duty_width = 0;
 
+	fill_fadt_extended_pm_io(fadt);
+
 	fadt->iapc_boot_arch = ACPI_FADT_8042 | ACPI_FADT_LEGACY_DEVICES;
 	fadt->flags |= (ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED
 		       | ACPI_FADT_SLEEP_BUTTON | ACPI_FADT_S4_RTC_WAKE
 		       | ACPI_FADT_PLATFORM_CLOCK | ACPI_FADT_C2_MP_SUPPORTED);
-
-	fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
-	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 = fadt->pm1a_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 = fadt->pm1_cnt_len * 8;
-	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 = fadt->pm1a_cnt_blk;
-	fadt->x_pm1a_cnt_blk.addrh = 0x0;
-
-	fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
-	fadt->x_pm2_cnt_blk.bit_offset = 0;
-	fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
-	fadt->x_pm2_cnt_blk.addrh = 0x0;
-
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->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 = fadt->gpe0_blk_len * 8;
-	fadt->x_gpe0_blk.bit_offset = 0;
-	fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
-	fadt->x_gpe0_blk.addrh = 0x0;
 }
diff --git a/src/southbridge/intel/ibexpeak/fadt.c b/src/southbridge/intel/ibexpeak/fadt.c
index bae209d..b17e9f0 100644
--- a/src/southbridge/intel/ibexpeak/fadt.c
+++ b/src/southbridge/intel/ibexpeak/fadt.c
@@ -24,6 +24,8 @@
 	fadt->pm_tmr_len = 4;
 	fadt->gpe0_blk_len = 16;
 
+	fill_fadt_extended_pm_io(fadt);
+
 	fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
 
 	fadt->flags |= ACPI_FADT_WBINVD |
@@ -31,42 +33,8 @@
 			ACPI_FADT_SLEEP_BUTTON |
 			ACPI_FADT_S4_RTC_WAKE |
 			ACPI_FADT_PLATFORM_CLOCK;
+
 	if (chip->docking_supported) {
 		fadt->flags |= ACPI_FADT_DOCKING_SUPPORTED;
 	}
-
-	fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
-	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 = fadt->pm1a_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 = fadt->pm1_cnt_len * 8;
-	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 = fadt->pm1a_cnt_blk;
-	fadt->x_pm1a_cnt_blk.addrh = 0x0;
-
-	fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
-	fadt->x_pm2_cnt_blk.bit_offset = 0;
-	fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
-	fadt->x_pm2_cnt_blk.addrh = 0x0;
-
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->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 = fadt->gpe0_blk_len * 8;
-	fadt->x_gpe0_blk.bit_offset = 0;
-	fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
-	fadt->x_gpe0_blk.addrh = 0x0;
 }
diff --git a/src/southbridge/intel/lynxpoint/fadt.c b/src/southbridge/intel/lynxpoint/fadt.c
index dc7ee54..ea542ca 100644
--- a/src/southbridge/intel/lynxpoint/fadt.c
+++ b/src/southbridge/intel/lynxpoint/fadt.c
@@ -21,6 +21,8 @@
 	else
 		fadt->gpe0_blk = pmbase + GPE0_STS;
 
+	fill_fadt_extended_pm_io(fadt);
+
 	/*
 	 * Some of the lengths here are doubled. This is because they describe
 	 * blocks containing two registers, where the size of each register
@@ -47,45 +49,4 @@
 
 	if (cfg && cfg->docking_supported)
 		fadt->flags |= ACPI_FADT_DOCKING_SUPPORTED;
-
-	fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
-	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 = fadt->pm1a_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 = fadt->pm1_cnt_len * 8;
-	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 = fadt->pm1a_cnt_blk;
-	fadt->x_pm1a_cnt_blk.addrh = 0x0;
-
-	fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
-	fadt->x_pm2_cnt_blk.bit_offset = 0;
-	fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
-	fadt->x_pm2_cnt_blk.addrh = 0x0;
-
-	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
-	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 = fadt->pm_tmr_blk;
-	fadt->x_pm_tmr_blk.addrh = 0x0;
-
-	/*
-	 * Windows 10 requires x_gpe0_blk to be set starting with FADT revision 5.
-	 * The bit_width field intentionally overflows here.
-	 * The OSPM can instead use the values in `fadt->gpe0_blk{,_len}`, which
-	 * seems to work fine on Linux 5.0 and Windows 10.
-	 */
-	fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO;
-	fadt->x_gpe0_blk.bit_width = fadt->gpe0_blk_len * 8;
-	fadt->x_gpe0_blk.bit_offset = 0;
-	fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
-	fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
-	fadt->x_gpe0_blk.addrh = 0x0;
 }