xref: /aosp_15_r20/external/coreboot/src/soc/amd/common/block/data_fabric/data_fabric_helper.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <acpi/acpi_device.h>
4 #include <amdblocks/data_fabric.h>
5 #include <amdblocks/pci_devs.h>
6 #include <console/console.h>
7 #include <device/pci_ops.h>
8 #include <soc/data_fabric.h>
9 #include <soc/pci_devs.h>
10 #include <types.h>
11 
data_fabric_set_indirect_address(uint16_t fn_reg,uint8_t instance_id)12 static void data_fabric_set_indirect_address(uint16_t fn_reg, uint8_t instance_id)
13 {
14 	union df_ficaa ficaa = { .cfg_inst_acc_en = 1 }; /* target only specific instance */
15 	/* convert register address to 32-bit register number */
16 	ficaa.reg_num = DF_REG_OFFSET(fn_reg) >> 2;
17 	ficaa.func_num = DF_REG_FN(fn_reg);
18 	ficaa.inst_id = instance_id;
19 	data_fabric_broadcast_write32(DF_FICAA_BIOS, ficaa.raw);
20 }
21 
data_fabric_read32(uint16_t fn_reg,uint8_t instance_id)22 uint32_t data_fabric_read32(uint16_t fn_reg, uint8_t instance_id)
23 {
24 	/* Broadcast reads might return unexpected results when a register has different
25 	   contents in the different instances. */
26 	if (instance_id == BROADCAST_FABRIC_ID)
27 		return data_fabric_broadcast_read32(fn_reg);
28 
29 	/* non-broadcast data fabric accesses need to be done via indirect access */
30 	data_fabric_set_indirect_address(fn_reg, instance_id);
31 	return data_fabric_broadcast_read32(DF_FICAD_LO);
32 }
33 
data_fabric_write32(uint16_t fn_reg,uint8_t instance_id,uint32_t data)34 void data_fabric_write32(uint16_t fn_reg, uint8_t instance_id, uint32_t data)
35 {
36 	if (instance_id == BROADCAST_FABRIC_ID) {
37 		data_fabric_broadcast_write32(fn_reg, data);
38 		return;
39 	}
40 
41 	/* non-broadcast data fabric accesses need to be done via indirect access */
42 	data_fabric_set_indirect_address(fn_reg, instance_id);
43 	data_fabric_broadcast_write32(DF_FICAD_LO, data);
44 }
45 
data_fabric_print_mmio_conf(void)46 void data_fabric_print_mmio_conf(void)
47 {
48 	union df_mmio_control control;
49 	uint64_t base, limit;
50 	printk(BIOS_SPEW,
51 		"=== Data Fabric MMIO configuration registers ===\n"
52 		"idx             base            limit  control R W NP F-ID\n");
53 	for (unsigned int i = 0; i < DF_MMIO_REG_SET_COUNT; i++) {
54 		control.raw = data_fabric_broadcast_read32(DF_MMIO_CONTROL(i));
55 		data_fabric_get_mmio_base_size(i, &base, &limit);
56 		printk(BIOS_SPEW, " %2u %16llx %16llx %8x %s %s  %s %4x\n",
57 		       i, base, limit, control.raw,
58 		       control.re ? "x" : " ",
59 		       control.we ? "x" : " ",
60 		       control.np ? "x" : " ",
61 		       control.dst_fabric_id);
62 	}
63 }
64 
65 #if CONFIG(HAVE_ACPI_TABLES)
data_fabric_acpi_name(const struct device * dev)66 static const char *data_fabric_acpi_name(const struct device *dev)
67 {
68 	const char *df_acpi_names[8] = {
69 		"DFD0",
70 		"DFD1",
71 		"DFD2",
72 		"DFD3",
73 		"DFD4",
74 		"DFD5",
75 		"DFD6",
76 		"DFD7"
77 	};
78 
79 	if (dev->path.type == DEVICE_PATH_PCI &&
80 	    PCI_SLOT(dev->path.pci.devfn) == DF_DEV)
81 		return df_acpi_names[PCI_FUNC(dev->path.pci.devfn)];
82 
83 	printk(BIOS_ERR, "%s: Unhandled device id 0x%x\n", __func__, dev->device);
84 	return NULL;
85 }
86 #endif
87 
88 struct device_operations amd_data_fabric_ops = {
89 	.read_resources		= noop_read_resources,
90 	.set_resources		= noop_set_resources,
91 #if CONFIG(HAVE_ACPI_TABLES)
92 	.acpi_name		= data_fabric_acpi_name,
93 	.acpi_fill_ssdt		= acpi_device_write_pci_dev,
94 #endif
95 };
96