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