xref: /aosp_15_r20/external/coreboot/src/soc/amd/common/block/pci/pci_routing_info.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <amdblocks/amd_pci_util.h>
4 #include <console/console.h>
5 #include <device/pci_def.h>
6 #include <stdlib.h>
7 #include <types.h>
8 
9 enum pcie_swizzle_pin {
10 	PIN_A = 0,
11 	PIN_B,
12 	PIN_C,
13 	PIN_D,
14 };
15 
16 static const uint8_t pcie_swizzle_table[][4] = {
17 	{PIN_A, PIN_B, PIN_C, PIN_D},
18 	{PIN_B, PIN_C, PIN_D, PIN_A},
19 	{PIN_C, PIN_D, PIN_A, PIN_B},
20 	{PIN_D, PIN_A, PIN_B, PIN_C},
21 };
22 
get_pci_routing_info(unsigned int devfn)23 const struct pci_routing_info *get_pci_routing_info(unsigned int devfn)
24 {
25 	const struct pci_routing_info *routing_info;
26 	size_t entries = 0;
27 
28 	routing_info = get_pci_routing_table(&entries);
29 
30 	if (!routing_info || !entries)
31 		return NULL;
32 
33 	for (size_t i = 0; i < entries; ++i, ++routing_info)
34 		if (routing_info->devfn == devfn)
35 			return routing_info;
36 
37 	printk(BIOS_ERR, "Failed to find PCIe routing info for dev: %#x, fn: %#x\n",
38 	       PCI_SLOT(devfn), PCI_FUNC(devfn));
39 
40 	return NULL;
41 }
42 
pci_calculate_irq(const struct pci_routing_info * routing_info,unsigned int pin)43 unsigned int pci_calculate_irq(const struct pci_routing_info *routing_info,
44 					      unsigned int pin)
45 {
46 	unsigned int irq;
47 
48 	if (routing_info->swizzle >= ARRAY_SIZE(pcie_swizzle_table))
49 		die("%s: swizzle %u out of bounds\n", __func__, routing_info->swizzle);
50 
51 	if (pin >= ARRAY_SIZE(pcie_swizzle_table[routing_info->swizzle]))
52 		die("%s: pin %u out of bounds\n", __func__, pin);
53 
54 	irq = routing_info->group * 4;
55 	irq += pcie_swizzle_table[routing_info->swizzle][pin];
56 
57 	return irq;
58 }
59 
populate_pirq_data(void)60 void populate_pirq_data(void)
61 {
62 	const struct pci_routing_info *routing_table, *routing_entry;
63 	size_t entries = 0;
64 	struct pirq_struct *pirq;
65 	unsigned int irq;
66 
67 	routing_table = get_pci_routing_table(&entries);
68 
69 	if (!routing_table || !entries)
70 		return;
71 
72 	pirq = calloc(entries, sizeof(*pirq));
73 
74 	if (!pirq) {
75 		printk(BIOS_ERR, "%s: Allocation failed\n", __func__);
76 		return;
77 	}
78 
79 	for (size_t i = 0; i < entries; ++i) {
80 		routing_entry = &routing_table[i];
81 
82 		pirq[i].devfn = routing_entry->devfn;
83 		for (size_t j = 0; j < 4; ++j) {
84 			irq = pci_calculate_irq(routing_entry, j);
85 
86 			pirq[i].PIN[j] = irq % 8;
87 		}
88 	}
89 
90 	pirq_data_ptr = pirq;
91 	pirq_data_size = entries;
92 }
93