xref: /aosp_15_r20/external/coreboot/src/southbridge/intel/common/acpi_pirq_gen.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <acpi/acpigen.h>
4 #include <acpi/acpigen_pci.h>
5 #include <device/pci_def.h>
6 #include <device/pci_ops.h>
7 
8 #include "acpi_pirq_gen.h"
9 
gen_apic_route(const struct slot_pin_irq_map * pin_irq_map,unsigned int map_count)10 static void gen_apic_route(const struct slot_pin_irq_map *pin_irq_map,
11 			   unsigned int map_count)
12 {
13 	for (unsigned int i = 0; i < map_count; i++)
14 		/*
15 		 * The reason for subtracting PCI_INT_A from the pin given is
16 		 * that PCI defines pins as 1-4, and _PRT uses 0-3.
17 		 */
18 		acpigen_write_PRT_GSI_entry(pin_irq_map[i].slot,
19 					    pin_irq_map[i].pin - PCI_INT_A,
20 					    pin_irq_map[i].apic_gsi);
21 }
22 
gen_pic_route(const struct slot_pin_irq_map * pin_irq_map,unsigned int map_count,const struct pic_pirq_map * pirq_map)23 static void gen_pic_route(const struct slot_pin_irq_map *pin_irq_map,
24 			  unsigned int map_count,
25 			  const struct pic_pirq_map *pirq_map)
26 {
27 	for (unsigned int i = 0; i < map_count; i++) {
28 		const enum pirq pirq = pin_irq_map[i].pic_pirq;
29 		const unsigned int pin = pin_irq_map[i].pin - PCI_INT_A;
30 		if (pirq == PIRQ_INVALID)
31 			continue;
32 
33 		const size_t pirq_index = pirq_idx(pirq);
34 		if (pirq_map->type == PIRQ_GSI)
35 			acpigen_write_PRT_GSI_entry(pin_irq_map[i].slot,
36 						    pin,
37 						    pirq_map->gsi[pirq_index]);
38 		else
39 			acpigen_write_PRT_source_entry(pin_irq_map[i].slot,
40 						       pin,
41 						       pirq_map->source_path[pirq_index],
42 						       0);
43 	}
44 }
45 
intel_write_pci0_PRT(const struct slot_pin_irq_map * pin_irq_map,unsigned int map_count,const struct pic_pirq_map * pirq_map)46 void intel_write_pci0_PRT(const struct slot_pin_irq_map *pin_irq_map,
47 			  unsigned int map_count,
48 			  const struct pic_pirq_map *pirq_map)
49 {
50 	/* \_SB.PCI0._PRT */
51 	acpigen_write_scope("\\_SB.PCI0");
52 	acpigen_write_method("_PRT", 0);
53 	acpigen_write_if();
54 	acpigen_emit_namestring("PICM");
55 	acpigen_emit_byte(RETURN_OP);
56 	acpigen_write_package(map_count);
57 	gen_apic_route(pin_irq_map, map_count);
58 	acpigen_pop_len(); /* package */
59 	acpigen_write_else();
60 	acpigen_emit_byte(RETURN_OP);
61 	acpigen_write_package(map_count);
62 	gen_pic_route(pin_irq_map, map_count, pirq_map);
63 	acpigen_pop_len(); /* package */
64 	acpigen_pop_len(); /* else PICM */
65 	acpigen_pop_len(); /* _PRT */
66 	acpigen_pop_len(); /* \_SB */
67 }
68 
is_slot_pin_assigned(const struct slot_pin_irq_map * pin_irq_map,unsigned int map_count,unsigned int slot,enum pci_pin pin)69 bool is_slot_pin_assigned(const struct slot_pin_irq_map *pin_irq_map,
70 			  unsigned int map_count, unsigned int slot,
71 			  enum pci_pin pin)
72 {
73 	for (size_t i = 0; i < map_count; i++) {
74 		if (pin_irq_map[i].slot == slot && pin_irq_map[i].pin == pin)
75 			return true;
76 	}
77 
78 	return false;
79 }
80