blob: ea48d9e0504abf951ae1ace313e0de3f19d46c9b [file] [log] [blame]
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +01001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2014 Vladimir Serbinenko
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of
9 * the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +010015 */
16
17#include <string.h>
18#include <arch/acpi.h>
19#include <arch/acpigen.h>
20#include <device/device.h>
21#include <device/pci.h>
22#include <device/pciexp.h>
23#include "pciehp.h"
24
25void intel_acpi_pcie_hotplug_generator(u8 *hotplug_map, int port_number)
26{
27 int port;
28 int have_hotplug = 0;
29
30 for (port = 0; port < port_number; port++) {
31 if (hotplug_map[port]) {
32 have_hotplug = 1;
33 }
34 }
35
36 if (!have_hotplug) {
37 return;
38 }
39
40 for (port = 0; port < port_number; port++) {
41 if (hotplug_map[port]) {
42 char scope_name[] = "\\_SB.PCI0.RP0x";
43 scope_name[sizeof("\\_SB.PCI0.RP0x") - 2] = '1' + port;
44 acpigen_write_scope(scope_name);
45
46 /*
47 Device (SLOT)
48 {
Elyes HAOUASb0f19882018-06-09 11:59:00 +020049 Name (_ADR, 0x00)
50 Method (_RMV, 0, NotSerialized)
51 {
52 Return (0x01)
53 }
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +010054 }
55 */
56
57 acpigen_write_device("SLOT");
58
59 acpigen_write_name_byte("_ADR", 0x00);
60
61 acpigen_write_method("_RMV", 0);
62 /* ReturnOp */
63 acpigen_emit_byte (0xa4);
64 /* One */
65 acpigen_emit_byte (0x01);
66 acpigen_pop_len();
67 acpigen_pop_len();
68 acpigen_pop_len();
69 }
70 }
71
72 /* Method (_L01, 0, NotSerialized)
73 {
74 If (\_SB.PCI0.RP04.HPCS)
75 {
76 Sleep (100)
77 Store (0x01, \_SB.PCI0.RP04.HPCS)
78 If (\_SB.PCI0.RP04.PDC)
79 {
80 Store (0x01, \_SB.PCI0.RP04.PDC)
81 Notify (\_SB.PCI0.RP04, 0x00)
82 }
83 }
84 }
85
86 */
87 acpigen_write_scope("\\_GPE");
88 acpigen_write_method("_L01", 0);
89 for (port = 0; port < port_number; port++) {
90 if (hotplug_map[port]) {
91 char reg_name[] = "\\_SB.PCI0.RP0x.HPCS";
92 reg_name[sizeof("\\_SB.PCI0.RP0x") - 2] = '1' + port;
93 acpigen_emit_byte(0xa0); /* IfOp. */
94 acpigen_write_len_f();
95 acpigen_emit_namestring(reg_name);
96
97 /* Sleep (100) */
98 acpigen_emit_byte(0x5b); /* SleepOp. */
99 acpigen_emit_byte(0x22);
100 acpigen_write_byte(100);
101
102 /* Store (0x01, \_SB.PCI0.RP04.HPCS) */
103 acpigen_emit_byte(0x70);
104 acpigen_emit_byte(0x01);
105 acpigen_emit_namestring(reg_name);
106
107 memcpy(reg_name + sizeof("\\_SB.PCI0.RP0x.") - 1, "PDC", 4);
108
109 /* If (\_SB.PCI0.RP04.PDC) */
110 acpigen_emit_byte(0xa0); /* IfOp. */
111 acpigen_write_len_f();
112 acpigen_emit_namestring(reg_name);
113
114 /* Store (0x01, \_SB.PCI0.RP04.PDC) */
115 acpigen_emit_byte(0x70);
116 acpigen_emit_byte(0x01);
117 acpigen_emit_namestring(reg_name);
118
119 reg_name[sizeof("\\_SB.PCI0.RP0x") - 1] = '\0';
120
121 /* Notify(\_SB.PCI0.RP04, 0x00) */
122 acpigen_emit_byte(0x86);
123 acpigen_emit_namestring(reg_name);
124 acpigen_emit_byte(0x00);
125 acpigen_pop_len();
126 acpigen_pop_len();
127 }
128 }
129 acpigen_pop_len();
130 acpigen_pop_len();
131
132}
133
134static void slot_dev_read_resources(struct device *dev)
135{
136 struct resource *resource;
137
138 resource = new_resource(dev, 0x10);
139 resource->size = 1 << 23;
140 resource->align = 22;
141 resource->gran = 22;
142 resource->limit = 0xffffffff;
143 resource->flags |= IORESOURCE_MEM;
144
145 resource = new_resource(dev, 0x14);
146 resource->size = 1 << 23;
147 resource->align = 22;
148 resource->gran = 22;
149 resource->limit = 0xffffffff;
150 resource->flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
151
152 resource = new_resource(dev, 0x18);
153 resource->size = 1 << 12;
154 resource->align = 12;
155 resource->gran = 12;
156 resource->limit = 0xffff;
157 resource->flags |= IORESOURCE_IO;
158}
159
160static struct device_operations slot_dev_ops = {
161 .read_resources = slot_dev_read_resources,
162};
163
164/* Add a dummy device to reserve I/O space for hotpluggable devices. */
165void intel_acpi_pcie_hotplug_scan_slot(struct bus *bus)
166{
167 struct device *slot;
168 struct device_path slot_path = { .type = DEVICE_PATH_NONE };
169 slot = alloc_dev(bus, &slot_path);
170 slot->ops = &slot_dev_ops;
171}