xref: /aosp_15_r20/external/coreboot/src/southbridge/intel/common/pciehp.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <string.h>
4 #include <acpi/acpigen.h>
5 #include <device/device.h>
6 #include <device/pci.h>
7 #include <stdbool.h>
8 
9 #include "pciehp.h"
10 
intel_acpi_pcie_hotplug_generator(bool * hotplug_map,int port_number)11 void intel_acpi_pcie_hotplug_generator(bool *hotplug_map, int port_number)
12 {
13 	int port;
14 	int have_hotplug = 0;
15 
16 	for (port = 0; port < port_number; port++) {
17 		if (hotplug_map[port]) {
18 			have_hotplug = 1;
19 		}
20 	}
21 
22 	if (!have_hotplug) {
23 		return;
24 	}
25 
26 	for (port = 0; port < port_number; port++) {
27 		if (hotplug_map[port]) {
28 			char scope_name[] = "\\_SB.PCI0.RP0x";
29 			scope_name[sizeof("\\_SB.PCI0.RP0x") - 2] = '1' + port;
30 			acpigen_write_scope(scope_name);
31 
32 			/*
33 			  Device (SLOT)
34 			  {
35 				Name (_ADR, 0x00)
36 				Method (_RMV, 0, NotSerialized)
37 				{
38 					Return (0x01)
39 				}
40 			  }
41 			*/
42 
43 			acpigen_write_device("SLOT");
44 
45 			acpigen_write_name_byte("_ADR", 0x00);
46 
47 			acpigen_write_method("_RMV", 0);
48 			/* ReturnOp  */
49 			acpigen_emit_byte(0xa4);
50 			/* One  */
51 			acpigen_emit_byte(0x01);
52 			acpigen_pop_len();
53 			acpigen_pop_len();
54 			acpigen_pop_len();
55 		}
56 	}
57 
58 	/* Method (_L01, 0, NotSerialized)
59 	{
60 		If (\_SB.PCI0.RP04.HPCS)
61 		{
62 			Sleep (100)
63 			Store (0x01, \_SB.PCI0.RP04.HPCS)
64 			If (\_SB.PCI0.RP04.PDC)
65 			{
66 				Store (0x01, \_SB.PCI0.RP04.PDC)
67 				Notify (\_SB.PCI0.RP04, 0x00)
68 			}
69 		}
70 	}
71 
72 	*/
73 	acpigen_write_scope("\\_GPE");
74 	acpigen_write_method("_L01", 0);
75 	for (port = 0; port < port_number; port++) {
76 		if (hotplug_map[port]) {
77 			char reg_name[] = "\\_SB.PCI0.RP0x.HPCS";
78 			reg_name[sizeof("\\_SB.PCI0.RP0x") - 2] = '1' + port;
79 			acpigen_emit_byte(0xa0); /* IfOp. */
80 			acpigen_write_len_f();
81 			acpigen_emit_namestring(reg_name);
82 
83 			/* Sleep (100) */
84 			acpigen_emit_byte(0x5b); /* SleepOp. */
85 			acpigen_emit_byte(0x22);
86 			acpigen_write_byte(100);
87 
88 			/* Store (0x01, \_SB.PCI0.RP04.HPCS) */
89 			acpigen_emit_byte(0x70);
90 			acpigen_emit_byte(0x01);
91 			acpigen_emit_namestring(reg_name);
92 
93 			memcpy(reg_name + sizeof("\\_SB.PCI0.RP0x.") - 1, "PDC", 4);
94 
95 			/* If (\_SB.PCI0.RP04.PDC) */
96 			acpigen_emit_byte(0xa0); /* IfOp. */
97 			acpigen_write_len_f();
98 			acpigen_emit_namestring(reg_name);
99 
100 			/* Store (0x01, \_SB.PCI0.RP04.PDC) */
101 			acpigen_emit_byte(0x70);
102 			acpigen_emit_byte(0x01);
103 			acpigen_emit_namestring(reg_name);
104 
105 			reg_name[sizeof("\\_SB.PCI0.RP0x") - 1] = '\0';
106 
107 			/* Notify(\_SB.PCI0.RP04, 0x00) */
108 			acpigen_emit_byte(0x86);
109 			acpigen_emit_namestring(reg_name);
110 			acpigen_emit_byte(0x00);
111 			acpigen_pop_len();
112 			acpigen_pop_len();
113 		}
114 	}
115 	acpigen_pop_len();
116 	acpigen_pop_len();
117 }
118