blob: 355e9df32fda1eeac1e77860a7df0d593fbe9a2c [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +01002
3#include <string.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -07004#include <acpi/acpigen.h>
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +01005#include <device/device.h>
6#include <device/pci.h>
Felix Singerf4842bb2024-01-12 21:21:06 +01007#include <stdbool.h>
Elyes HAOUAS4b7202e2019-03-16 10:02:31 +01008
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +01009#include "pciehp.h"
10
Felix Singerf4842bb2024-01-12 21:21:06 +010011void intel_acpi_pcie_hotplug_generator(bool *hotplug_map, int port_number)
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +010012{
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 {
Elyes HAOUASb0f19882018-06-09 11:59:00 +020035 Name (_ADR, 0x00)
36 Method (_RMV, 0, NotSerialized)
37 {
38 Return (0x01)
39 }
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +010040 }
41 */
42
43 acpigen_write_device("SLOT");
44
45 acpigen_write_name_byte("_ADR", 0x00);
46
47 acpigen_write_method("_RMV", 0);
48 /* ReturnOp */
Elyes Haouas0f3075e2023-09-10 10:37:15 +020049 acpigen_emit_byte(0xa4);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +010050 /* One */
Elyes Haouas0f3075e2023-09-10 10:37:15 +020051 acpigen_emit_byte(0x01);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +010052 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();
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100117}