blob: 7a6e615df3cbab9568eb6347ab8ff796eca75676 [file] [log] [blame]
Felix Helddba3fe72021-02-13 01:05:56 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
Fred Reitberger1a9ac342022-11-03 15:19:51 -04003#include <acpi/acpi_device.h>
Felix Helddba3fe72021-02-13 01:05:56 +01004#include <amdblocks/data_fabric.h>
5#include <amdblocks/pci_devs.h>
Felix Held906f9be2021-02-13 20:38:08 +01006#include <console/console.h>
Felix Helddba3fe72021-02-13 01:05:56 +01007#include <device/pci_ops.h>
Felix Held602f93e2021-02-13 21:10:08 +01008#include <soc/data_fabric.h>
Felix Helddba3fe72021-02-13 01:05:56 +01009#include <soc/pci_devs.h>
10#include <types.h>
Felix Helddba3fe72021-02-13 01:05:56 +010011
Felix Held18a3c232023-08-03 00:10:03 +020012static void data_fabric_set_indirect_address(uint16_t fn_reg, uint8_t instance_id)
Felix Helddba3fe72021-02-13 01:05:56 +010013{
Felix Held6b324d92023-08-02 18:48:25 +020014 union df_ficaa ficaa = { .cfg_inst_acc_en = 1 }; /* target only specific instance */
Fred Reitberger437d0112022-11-01 08:42:41 -040015 /* convert register address to 32-bit register number */
Felix Held18a3c232023-08-03 00:10:03 +020016 ficaa.reg_num = DF_REG_OFFSET(fn_reg) >> 2;
17 ficaa.func_num = DF_REG_FN(fn_reg);
Fred Reitberger437d0112022-11-01 08:42:41 -040018 ficaa.inst_id = instance_id;
Felix Held4078d142023-08-03 00:20:55 +020019 data_fabric_broadcast_write32(DF_FICAA_BIOS, ficaa.raw);
Felix Helddba3fe72021-02-13 01:05:56 +010020}
21
Felix Held18a3c232023-08-03 00:10:03 +020022uint32_t data_fabric_read32(uint16_t fn_reg, uint8_t instance_id)
Felix Helddba3fe72021-02-13 01:05:56 +010023{
Felix Heldf1eaa672021-02-18 20:34:21 +010024 /* Broadcast reads might return unexpected results when a register has different
25 contents in the different instances. */
Felix Helddba3fe72021-02-13 01:05:56 +010026 if (instance_id == BROADCAST_FABRIC_ID)
Felix Held18a3c232023-08-03 00:10:03 +020027 return data_fabric_broadcast_read32(fn_reg);
Felix Helddba3fe72021-02-13 01:05:56 +010028
29 /* non-broadcast data fabric accesses need to be done via indirect access */
Felix Held18a3c232023-08-03 00:10:03 +020030 data_fabric_set_indirect_address(fn_reg, instance_id);
Felix Held4078d142023-08-03 00:20:55 +020031 return data_fabric_broadcast_read32(DF_FICAD_LO);
Felix Helddba3fe72021-02-13 01:05:56 +010032}
Felix Held45df9c12021-02-13 01:08:14 +010033
Felix Held18a3c232023-08-03 00:10:03 +020034void data_fabric_write32(uint16_t fn_reg, uint8_t instance_id, uint32_t data)
Felix Held45df9c12021-02-13 01:08:14 +010035{
36 if (instance_id == BROADCAST_FABRIC_ID) {
Felix Held18a3c232023-08-03 00:10:03 +020037 data_fabric_broadcast_write32(fn_reg, data);
Felix Held45df9c12021-02-13 01:08:14 +010038 return;
39 }
40
41 /* non-broadcast data fabric accesses need to be done via indirect access */
Felix Held18a3c232023-08-03 00:10:03 +020042 data_fabric_set_indirect_address(fn_reg, instance_id);
Felix Held4078d142023-08-03 00:20:55 +020043 data_fabric_broadcast_write32(DF_FICAD_LO, data);
Felix Held45df9c12021-02-13 01:08:14 +010044}
Felix Held602f93e2021-02-13 21:10:08 +010045
Felix Held906f9be2021-02-13 20:38:08 +010046void data_fabric_print_mmio_conf(void)
47{
Felix Held965a45f2023-02-07 14:31:16 +010048 union df_mmio_control control;
Felix Held77128a82023-02-02 16:13:05 +010049 uint64_t base, limit;
Felix Held906f9be2021-02-13 20:38:08 +010050 printk(BIOS_SPEW,
51 "=== Data Fabric MMIO configuration registers ===\n"
Felix Held965a45f2023-02-07 14:31:16 +010052 "idx base limit control R W NP F-ID\n");
Felix Heldb307ed62023-02-07 12:06:41 +010053 for (unsigned int i = 0; i < DF_MMIO_REG_SET_COUNT; i++) {
Felix Held18a3c232023-08-03 00:10:03 +020054 control.raw = data_fabric_broadcast_read32(DF_MMIO_CONTROL(i));
Felix Held58c2efc2023-09-15 21:33:13 +020055 data_fabric_get_mmio_base_size(i, &base, &limit);
Felix Held965a45f2023-02-07 14:31:16 +010056 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" : " ",
Felix Held84a60fb2023-08-04 18:45:36 +020061 control.dst_fabric_id);
Felix Held906f9be2021-02-13 20:38:08 +010062 }
63}
64
Felix Held045251e2023-10-13 21:33:55 +020065#if CONFIG(HAVE_ACPI_TABLES)
Fred Reitberger1a9ac342022-11-03 15:19:51 -040066static 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}
Felix Held045251e2023-10-13 21:33:55 +020086#endif
Fred Reitberger1a9ac342022-11-03 15:19:51 -040087
88struct device_operations amd_data_fabric_ops = {
89 .read_resources = noop_read_resources,
90 .set_resources = noop_set_resources,
Felix Held045251e2023-10-13 21:33:55 +020091#if CONFIG(HAVE_ACPI_TABLES)
Fred Reitberger1a9ac342022-11-03 15:19:51 -040092 .acpi_name = data_fabric_acpi_name,
93 .acpi_fill_ssdt = acpi_device_write_pci_dev,
Felix Held045251e2023-10-13 21:33:55 +020094#endif
Fred Reitberger1a9ac342022-11-03 15:19:51 -040095};