soc/amd/common/include/data_fabric_defs: introduce & use DF_REG_* macros

To have both the PCI function number and the register offset into the
config space of that function of the data fabric device in the data
fabric register definitions, introduce and use the DF_REG_ID, DF_REG_FN
and DF_REG_REG macros. The DF_REG_ID macro is used for register
definitions where both the function number and the register offset are
specified, and the DF_REG_FN and DF_REG_REG macros are used to extract
the function number and the register offset from the register defines.
This will allow having one define for accessing an indexed group of
registers that are on different functions of the data fabric device.

TEST=MMIO resources read from the data fabric's MMIO decode registers
don't change on Mandolin and the ACPI CRAT table is also identical.

Signed-off-by: Felix Held <felix-coreboot@felixheld.de>
Change-Id: I63a284b26081c170a217b082b100c482f6158e7e
Reviewed-on: https://review.coreboot.org/c/coreboot/+/76886
Reviewed-by: Martin L Roth <gaumless@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Eric Lai <eric_lai@quanta.corp-partner.google.com>
diff --git a/src/soc/amd/common/block/data_fabric/data_fabric_helper.c b/src/soc/amd/common/block/data_fabric/data_fabric_helper.c
index 1f0e2cf..acfbf6c 100644
--- a/src/soc/amd/common/block/data_fabric/data_fabric_helper.c
+++ b/src/soc/amd/common/block/data_fabric/data_fabric_helper.c
@@ -11,38 +11,41 @@
 #include <soc/pci_devs.h>
 #include <types.h>
 
-static void data_fabric_set_indirect_address(uint8_t func, uint16_t reg, uint8_t instance_id)
+static void data_fabric_set_indirect_address(uint16_t fn_reg, uint8_t instance_id)
 {
 	union df_ficaa ficaa = { .cfg_inst_acc_en = 1 }; /* target only specific instance */
 	/* convert register address to 32-bit register number */
-	ficaa.reg_num = reg >> 2;
-	ficaa.func_num = func;
+	ficaa.reg_num = DF_REG_OFFSET(fn_reg) >> 2;
+	ficaa.func_num = DF_REG_FN(fn_reg);
 	ficaa.inst_id = instance_id;
-	pci_write_config32(SOC_DF_F4_DEV, DF_FICAA_BIOS, ficaa.raw);
+	pci_write_config32(_SOC_DEV(DF_DEV, DF_REG_FN(DF_FICAA_BIOS)),
+			   DF_REG_OFFSET(DF_FICAA_BIOS), ficaa.raw);
 }
 
-uint32_t data_fabric_read32(uint8_t function, uint16_t reg, uint8_t instance_id)
+uint32_t data_fabric_read32(uint16_t fn_reg, uint8_t instance_id)
 {
 	/* Broadcast reads might return unexpected results when a register has different
 	   contents in the different instances. */
 	if (instance_id == BROADCAST_FABRIC_ID)
-		return data_fabric_broadcast_read32(function, reg);
+		return data_fabric_broadcast_read32(fn_reg);
 
 	/* non-broadcast data fabric accesses need to be done via indirect access */
-	data_fabric_set_indirect_address(function, reg, instance_id);
-	return pci_read_config32(SOC_DF_F4_DEV, DF_FICAD_LO);
+	data_fabric_set_indirect_address(fn_reg, instance_id);
+	return pci_read_config32(_SOC_DEV(DF_DEV, DF_REG_FN(DF_FICAD_LO)),
+				 DF_REG_OFFSET(DF_FICAD_LO));
 }
 
-void data_fabric_write32(uint8_t function, uint16_t reg, uint8_t instance_id, uint32_t data)
+void data_fabric_write32(uint16_t fn_reg, uint8_t instance_id, uint32_t data)
 {
 	if (instance_id == BROADCAST_FABRIC_ID) {
-		data_fabric_broadcast_write32(function, reg, data);
+		data_fabric_broadcast_write32(fn_reg, data);
 		return;
 	}
 
 	/* non-broadcast data fabric accesses need to be done via indirect access */
-	data_fabric_set_indirect_address(function, reg, instance_id);
-	pci_write_config32(SOC_DF_F4_DEV, DF_FICAD_LO, data);
+	data_fabric_set_indirect_address(fn_reg, instance_id);
+	pci_write_config32(_SOC_DEV(DF_DEV, DF_REG_FN(DF_FICAD_LO)),
+			   DF_REG_OFFSET(DF_FICAD_LO), data);
 }
 
 void data_fabric_print_mmio_conf(void)
@@ -53,12 +56,12 @@
 		"=== Data Fabric MMIO configuration registers ===\n"
 		"idx             base            limit  control R W NP F-ID\n");
 	for (unsigned int i = 0; i < DF_MMIO_REG_SET_COUNT; i++) {
-		control.raw = data_fabric_broadcast_read32(0, DF_MMIO_CONTROL(i));
+		control.raw = data_fabric_broadcast_read32(DF_MMIO_CONTROL(i));
 		/* Base and limit address registers don't contain the lower address bits, but
 		   are shifted by D18F0_MMIO_SHIFT bits */
-		base = (uint64_t)data_fabric_broadcast_read32(0, DF_MMIO_BASE(i))
+		base = (uint64_t)data_fabric_broadcast_read32(DF_MMIO_BASE(i))
 			<< D18F0_MMIO_SHIFT;
-		limit = (uint64_t)data_fabric_broadcast_read32(0, DF_MMIO_LIMIT(i))
+		limit = (uint64_t)data_fabric_broadcast_read32(DF_MMIO_LIMIT(i))
 			<< D18F0_MMIO_SHIFT;
 		/* Lower D18F0_MMIO_SHIFT address limit bits are all 1 */
 		limit += (1 << D18F0_MMIO_SHIFT) - 1;
@@ -74,15 +77,15 @@
 void data_fabric_disable_mmio_reg(unsigned int reg)
 {
 	union df_mmio_control ctrl = { .fabric_id = IOMS0_FABRIC_ID };
-	data_fabric_broadcast_write32(0, DF_MMIO_CONTROL(reg), ctrl.raw);
-	data_fabric_broadcast_write32(0, DF_MMIO_BASE(reg), 0);
-	data_fabric_broadcast_write32(0, DF_MMIO_LIMIT(reg), 0);
+	data_fabric_broadcast_write32(DF_MMIO_CONTROL(reg), ctrl.raw);
+	data_fabric_broadcast_write32(DF_MMIO_BASE(reg), 0);
+	data_fabric_broadcast_write32(DF_MMIO_LIMIT(reg), 0);
 }
 
 static bool is_mmio_reg_disabled(unsigned int reg)
 {
 	union df_mmio_control ctrl;
-	ctrl.raw = data_fabric_broadcast_read32(0, DF_MMIO_CONTROL(reg));
+	ctrl.raw = data_fabric_broadcast_read32(DF_MMIO_CONTROL(reg));
 	return !(ctrl.we || ctrl.re);
 }
 
@@ -128,12 +131,12 @@
 
 	for (i = 0; i < DF_MMIO_REG_SET_COUNT; i++) {
 		/* Adjust all registers that overlap */
-		ctrl.raw = data_fabric_broadcast_read32(0, DF_MMIO_CONTROL(i));
+		ctrl.raw = data_fabric_broadcast_read32(DF_MMIO_CONTROL(i));
 		if (!(ctrl.we || ctrl.re))
 			continue; /* not enabled */
 
-		base = data_fabric_broadcast_read32(0, DF_MMIO_BASE(i));
-		limit = data_fabric_broadcast_read32(0, DF_MMIO_LIMIT(i));
+		base = data_fabric_broadcast_read32(DF_MMIO_BASE(i));
+		limit = data_fabric_broadcast_read32(DF_MMIO_LIMIT(i));
 
 		if (base > np_top || limit < np_bot)
 			continue; /* no overlap at all */
@@ -145,7 +148,7 @@
 
 		if (base < np_bot && limit > np_top) {
 			/* Split the configured region */
-			data_fabric_broadcast_write32(0, DF_MMIO_LIMIT(i), np_bot - 1);
+			data_fabric_broadcast_write32(DF_MMIO_LIMIT(i), np_bot - 1);
 			reg = data_fabric_find_unused_mmio_reg();
 			if (reg < 0) {
 				/* Although a pair could be freed later, this condition is
@@ -154,17 +157,17 @@
 				printk(BIOS_ERR, "Not enough NB MMIO routing registers\n");
 				continue;
 			}
-			data_fabric_broadcast_write32(0, DF_MMIO_BASE(reg), np_top + 1);
-			data_fabric_broadcast_write32(0, DF_MMIO_LIMIT(reg), limit);
-			data_fabric_broadcast_write32(0, DF_MMIO_CONTROL(reg), ctrl.raw);
+			data_fabric_broadcast_write32(DF_MMIO_BASE(reg), np_top + 1);
+			data_fabric_broadcast_write32(DF_MMIO_LIMIT(reg), limit);
+			data_fabric_broadcast_write32(DF_MMIO_CONTROL(reg), ctrl.raw);
 			continue;
 		}
 
 		/* If still here, adjust only the base or limit */
 		if (base <= np_bot)
-			data_fabric_broadcast_write32(0, DF_MMIO_LIMIT(i), np_bot - 1);
+			data_fabric_broadcast_write32(DF_MMIO_LIMIT(i), np_bot - 1);
 		else
-			data_fabric_broadcast_write32(0, DF_MMIO_BASE(i), np_top + 1);
+			data_fabric_broadcast_write32(DF_MMIO_BASE(i), np_top + 1);
 	}
 
 	reg = data_fabric_find_unused_mmio_reg();
@@ -175,9 +178,9 @@
 
 	union df_mmio_control np_ctrl = { .fabric_id = IOMS0_FABRIC_ID,
 					  .np = 1, .we = 1, .re = 1 };
-	data_fabric_broadcast_write32(0, DF_MMIO_BASE(reg), np_bot);
-	data_fabric_broadcast_write32(0, DF_MMIO_LIMIT(reg), np_top);
-	data_fabric_broadcast_write32(0, DF_MMIO_CONTROL(reg), np_ctrl.raw);
+	data_fabric_broadcast_write32(DF_MMIO_BASE(reg), np_bot);
+	data_fabric_broadcast_write32(DF_MMIO_LIMIT(reg), np_top);
+	data_fabric_broadcast_write32(DF_MMIO_CONTROL(reg), np_ctrl.raw);
 
 	data_fabric_print_mmio_conf();
 }
diff --git a/src/soc/amd/common/block/data_fabric/domain.c b/src/soc/amd/common/block/data_fabric/domain.c
index 1b33f31..f28bb12 100644
--- a/src/soc/amd/common/block/data_fabric/domain.c
+++ b/src/soc/amd/common/block/data_fabric/domain.c
@@ -38,8 +38,8 @@
 static void data_fabric_get_mmio_base_size(unsigned int reg,
 					   resource_t *mmio_base, resource_t *mmio_limit)
 {
-	const uint32_t base_reg = data_fabric_broadcast_read32(0, DF_MMIO_BASE(reg));
-	const uint32_t limit_reg = data_fabric_broadcast_read32(0, DF_MMIO_LIMIT(reg));
+	const uint32_t base_reg = data_fabric_broadcast_read32(DF_MMIO_BASE(reg));
+	const uint32_t limit_reg = data_fabric_broadcast_read32(DF_MMIO_LIMIT(reg));
 	/* The raw register values are bits 47..16  of the actual address */
 	*mmio_base = (resource_t)base_reg << D18F0_MMIO_SHIFT;
 	*mmio_limit = (((resource_t)limit_reg + 1) << D18F0_MMIO_SHIFT) - 1;
@@ -101,7 +101,7 @@
 		(1ULL << get_usable_physical_address_bits()) - DF_RESERVED_TOP_12GB_MMIO_SIZE;
 
 	for (unsigned int i = 0; i < DF_MMIO_REG_SET_COUNT; i++) {
-		ctrl.raw = data_fabric_broadcast_read32(0, DF_MMIO_CONTROL(i));
+		ctrl.raw = data_fabric_broadcast_read32(DF_MMIO_CONTROL(i));
 
 		/* Relevant MMIO regions need to have both reads and writes enabled */
 		if (!ctrl.we || !ctrl.re)
diff --git a/src/soc/amd/common/block/include/amdblocks/data_fabric.h b/src/soc/amd/common/block/include/amdblocks/data_fabric.h
index 4fb28fc..ad1f97b 100644
--- a/src/soc/amd/common/block/include/amdblocks/data_fabric.h
+++ b/src/soc/amd/common/block/include/amdblocks/data_fabric.h
@@ -3,6 +3,7 @@
 #ifndef AMD_BLOCK_DATA_FABRIC_H
 #define AMD_BLOCK_DATA_FABRIC_H
 
+#include <amdblocks/data_fabric_defs.h>
 #include <amdblocks/pci_devs.h>
 #include <device/pci_ops.h>
 #include <soc/data_fabric.h>
@@ -24,21 +25,21 @@
 /* Last 12GB of the usable address space are reserved */
 #define DF_RESERVED_TOP_12GB_MMIO_SIZE		(12ULL * GiB)
 
-uint32_t data_fabric_read32(uint8_t function, uint16_t reg, uint8_t instance_id);
-void data_fabric_write32(uint8_t function, uint16_t reg, uint8_t instance_id, uint32_t data);
+uint32_t data_fabric_read32(uint16_t fn_reg, uint8_t instance_id);
+void data_fabric_write32(uint16_t fn_reg, uint8_t instance_id, uint32_t data);
 
 static __always_inline
-uint32_t data_fabric_broadcast_read32(uint8_t function, uint16_t reg)
+uint32_t data_fabric_broadcast_read32(uint16_t fn_reg)
 {
 	/* No bit masking required. Macros will apply mask to values. */
-	return pci_read_config32(_SOC_DEV(DF_DEV, function), reg);
+	return pci_read_config32(_SOC_DEV(DF_DEV, DF_REG_FN(fn_reg)), DF_REG_OFFSET(fn_reg));
 }
 
 static __always_inline
-void data_fabric_broadcast_write32(uint8_t function, uint16_t reg, uint32_t data)
+void data_fabric_broadcast_write32(uint16_t fn_reg, uint32_t data)
 {
 	/* No bit masking required. Macros will apply mask to values. */
-	pci_write_config32(_SOC_DEV(DF_DEV, function), reg, data);
+	pci_write_config32(_SOC_DEV(DF_DEV, DF_REG_FN(fn_reg)), DF_REG_OFFSET(fn_reg), data);
 }
 
 void data_fabric_print_mmio_conf(void);
diff --git a/src/soc/amd/common/block/include/amdblocks/data_fabric_defs.h b/src/soc/amd/common/block/include/amdblocks/data_fabric_defs.h
new file mode 100644
index 0000000..3508715
--- /dev/null
+++ b/src/soc/amd/common/block/include/amdblocks/data_fabric_defs.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef AMD_BLOCK_DATA_FABRIC_DEFS_H
+#define AMD_BLOCK_DATA_FABRIC_DEFS_H
+
+#define DF_REG_ID(fn, reg)	(((fn) & 0x7) << 12 | ((reg) & 0xfff))
+#define DF_REG_FN(id)		((id) >> 12)
+#define DF_REG_OFFSET(id)	((id) & 0xfff)
+
+#endif /* AMD_BLOCK_DATA_FABRIC_DEFS_H */