Felix Held | dba3fe7 | 2021-02-13 01:05:56 +0100 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | |
Fred Reitberger | 1a9ac34 | 2022-11-03 15:19:51 -0400 | [diff] [blame] | 3 | #include <acpi/acpi_device.h> |
Felix Held | dba3fe7 | 2021-02-13 01:05:56 +0100 | [diff] [blame] | 4 | #include <amdblocks/data_fabric.h> |
| 5 | #include <amdblocks/pci_devs.h> |
Felix Held | 906f9be | 2021-02-13 20:38:08 +0100 | [diff] [blame] | 6 | #include <console/console.h> |
Felix Held | dba3fe7 | 2021-02-13 01:05:56 +0100 | [diff] [blame] | 7 | #include <device/pci_ops.h> |
Felix Held | 602f93e | 2021-02-13 21:10:08 +0100 | [diff] [blame] | 8 | #include <soc/data_fabric.h> |
Felix Held | dba3fe7 | 2021-02-13 01:05:56 +0100 | [diff] [blame] | 9 | #include <soc/pci_devs.h> |
| 10 | #include <types.h> |
Felix Held | dba3fe7 | 2021-02-13 01:05:56 +0100 | [diff] [blame] | 11 | |
Felix Held | 18a3c23 | 2023-08-03 00:10:03 +0200 | [diff] [blame] | 12 | static void data_fabric_set_indirect_address(uint16_t fn_reg, uint8_t instance_id) |
Felix Held | dba3fe7 | 2021-02-13 01:05:56 +0100 | [diff] [blame] | 13 | { |
Felix Held | 6b324d9 | 2023-08-02 18:48:25 +0200 | [diff] [blame] | 14 | union df_ficaa ficaa = { .cfg_inst_acc_en = 1 }; /* target only specific instance */ |
Fred Reitberger | 437d011 | 2022-11-01 08:42:41 -0400 | [diff] [blame] | 15 | /* convert register address to 32-bit register number */ |
Felix Held | 18a3c23 | 2023-08-03 00:10:03 +0200 | [diff] [blame] | 16 | ficaa.reg_num = DF_REG_OFFSET(fn_reg) >> 2; |
| 17 | ficaa.func_num = DF_REG_FN(fn_reg); |
Fred Reitberger | 437d011 | 2022-11-01 08:42:41 -0400 | [diff] [blame] | 18 | ficaa.inst_id = instance_id; |
Felix Held | 4078d14 | 2023-08-03 00:20:55 +0200 | [diff] [blame] | 19 | data_fabric_broadcast_write32(DF_FICAA_BIOS, ficaa.raw); |
Felix Held | dba3fe7 | 2021-02-13 01:05:56 +0100 | [diff] [blame] | 20 | } |
| 21 | |
Felix Held | 18a3c23 | 2023-08-03 00:10:03 +0200 | [diff] [blame] | 22 | uint32_t data_fabric_read32(uint16_t fn_reg, uint8_t instance_id) |
Felix Held | dba3fe7 | 2021-02-13 01:05:56 +0100 | [diff] [blame] | 23 | { |
Felix Held | f1eaa67 | 2021-02-18 20:34:21 +0100 | [diff] [blame] | 24 | /* Broadcast reads might return unexpected results when a register has different |
| 25 | contents in the different instances. */ |
Felix Held | dba3fe7 | 2021-02-13 01:05:56 +0100 | [diff] [blame] | 26 | if (instance_id == BROADCAST_FABRIC_ID) |
Felix Held | 18a3c23 | 2023-08-03 00:10:03 +0200 | [diff] [blame] | 27 | return data_fabric_broadcast_read32(fn_reg); |
Felix Held | dba3fe7 | 2021-02-13 01:05:56 +0100 | [diff] [blame] | 28 | |
| 29 | /* non-broadcast data fabric accesses need to be done via indirect access */ |
Felix Held | 18a3c23 | 2023-08-03 00:10:03 +0200 | [diff] [blame] | 30 | data_fabric_set_indirect_address(fn_reg, instance_id); |
Felix Held | 4078d14 | 2023-08-03 00:20:55 +0200 | [diff] [blame] | 31 | return data_fabric_broadcast_read32(DF_FICAD_LO); |
Felix Held | dba3fe7 | 2021-02-13 01:05:56 +0100 | [diff] [blame] | 32 | } |
Felix Held | 45df9c1 | 2021-02-13 01:08:14 +0100 | [diff] [blame] | 33 | |
Felix Held | 18a3c23 | 2023-08-03 00:10:03 +0200 | [diff] [blame] | 34 | void data_fabric_write32(uint16_t fn_reg, uint8_t instance_id, uint32_t data) |
Felix Held | 45df9c1 | 2021-02-13 01:08:14 +0100 | [diff] [blame] | 35 | { |
| 36 | if (instance_id == BROADCAST_FABRIC_ID) { |
Felix Held | 18a3c23 | 2023-08-03 00:10:03 +0200 | [diff] [blame] | 37 | data_fabric_broadcast_write32(fn_reg, data); |
Felix Held | 45df9c1 | 2021-02-13 01:08:14 +0100 | [diff] [blame] | 38 | return; |
| 39 | } |
| 40 | |
| 41 | /* non-broadcast data fabric accesses need to be done via indirect access */ |
Felix Held | 18a3c23 | 2023-08-03 00:10:03 +0200 | [diff] [blame] | 42 | data_fabric_set_indirect_address(fn_reg, instance_id); |
Felix Held | 4078d14 | 2023-08-03 00:20:55 +0200 | [diff] [blame] | 43 | data_fabric_broadcast_write32(DF_FICAD_LO, data); |
Felix Held | 45df9c1 | 2021-02-13 01:08:14 +0100 | [diff] [blame] | 44 | } |
Felix Held | 602f93e | 2021-02-13 21:10:08 +0100 | [diff] [blame] | 45 | |
Felix Held | 906f9be | 2021-02-13 20:38:08 +0100 | [diff] [blame] | 46 | void data_fabric_print_mmio_conf(void) |
| 47 | { |
Felix Held | 965a45f | 2023-02-07 14:31:16 +0100 | [diff] [blame] | 48 | union df_mmio_control control; |
Felix Held | 77128a8 | 2023-02-02 16:13:05 +0100 | [diff] [blame] | 49 | uint64_t base, limit; |
Felix Held | 906f9be | 2021-02-13 20:38:08 +0100 | [diff] [blame] | 50 | printk(BIOS_SPEW, |
| 51 | "=== Data Fabric MMIO configuration registers ===\n" |
Felix Held | 965a45f | 2023-02-07 14:31:16 +0100 | [diff] [blame] | 52 | "idx base limit control R W NP F-ID\n"); |
Felix Held | b307ed6 | 2023-02-07 12:06:41 +0100 | [diff] [blame] | 53 | for (unsigned int i = 0; i < DF_MMIO_REG_SET_COUNT; i++) { |
Felix Held | 18a3c23 | 2023-08-03 00:10:03 +0200 | [diff] [blame] | 54 | control.raw = data_fabric_broadcast_read32(DF_MMIO_CONTROL(i)); |
Felix Held | 58c2efc | 2023-09-15 21:33:13 +0200 | [diff] [blame] | 55 | data_fabric_get_mmio_base_size(i, &base, &limit); |
Felix Held | 965a45f | 2023-02-07 14:31:16 +0100 | [diff] [blame] | 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" : " ", |
Felix Held | 84a60fb | 2023-08-04 18:45:36 +0200 | [diff] [blame] | 61 | control.dst_fabric_id); |
Felix Held | 906f9be | 2021-02-13 20:38:08 +0100 | [diff] [blame] | 62 | } |
| 63 | } |
| 64 | |
Felix Held | 045251e | 2023-10-13 21:33:55 +0200 | [diff] [blame] | 65 | #if CONFIG(HAVE_ACPI_TABLES) |
Fred Reitberger | 1a9ac34 | 2022-11-03 15:19:51 -0400 | [diff] [blame] | 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 | } |
Felix Held | 045251e | 2023-10-13 21:33:55 +0200 | [diff] [blame] | 86 | #endif |
Fred Reitberger | 1a9ac34 | 2022-11-03 15:19:51 -0400 | [diff] [blame] | 87 | |
| 88 | struct device_operations amd_data_fabric_ops = { |
| 89 | .read_resources = noop_read_resources, |
| 90 | .set_resources = noop_set_resources, |
Felix Held | 045251e | 2023-10-13 21:33:55 +0200 | [diff] [blame] | 91 | #if CONFIG(HAVE_ACPI_TABLES) |
Fred Reitberger | 1a9ac34 | 2022-11-03 15:19:51 -0400 | [diff] [blame] | 92 | .acpi_name = data_fabric_acpi_name, |
| 93 | .acpi_fill_ssdt = acpi_device_write_pci_dev, |
Felix Held | 045251e | 2023-10-13 21:33:55 +0200 | [diff] [blame] | 94 | #endif |
Fred Reitberger | 1a9ac34 | 2022-11-03 15:19:51 -0400 | [diff] [blame] | 95 | }; |