xref: /aosp_15_r20/external/coreboot/src/drivers/usb/pci_xhci/pci_xhci.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include "pci_xhci.h"
4 #include <acpi/acpigen.h>
5 #include <acpi/acpigen_pci.h>
6 #include <console/console.h>
7 #include <device/pci.h>
8 #include <device/pci_ids.h>
9 #include <device/xhci.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 
13 #define PCI_XHCI_CLASSCODE	0x0c0330 /* USB3.0 xHCI controller */
14 
15 static unsigned int controller_count;
16 const struct device_operations xhci_pci_ops;
17 
18 struct port_counts {
19 	unsigned int high_speed;
20 	unsigned int super_speed;
21 };
22 
pci_xhci_get_wake_gpe(const struct device * dev,int * gpe)23 __weak enum cb_err pci_xhci_get_wake_gpe(const struct device *dev, int *gpe)
24 {
25 	*gpe = -1;
26 	return CB_SUCCESS;
27 }
28 
xhci_count_ports(void * context,const struct xhci_supported_protocol * data)29 static void xhci_count_ports(void *context, const struct xhci_supported_protocol *data)
30 {
31 	struct port_counts *counts = context;
32 
33 	switch (data->major_rev) {
34 	case 3:
35 		counts->super_speed += data->port_count;
36 		return;
37 	case 2:
38 		counts->high_speed += data->port_count;
39 		return;
40 	default:
41 		printk(BIOS_INFO, "%s: Unknown USB Version: %#x\n", __func__, data->major_rev);
42 		return;
43 	}
44 }
45 
xhci_port_exists(const struct device * dev,const struct usb_path * path)46 static bool xhci_port_exists(const struct device *dev, const struct usb_path *path)
47 {
48 	/* Cache the counts so we don't have to iterate on each invocation. */
49 	static struct {
50 		const struct device *dev;
51 		struct port_counts counts;
52 	} cache;
53 
54 	if (cache.dev != dev) {
55 		cache.counts.high_speed = 0;
56 		cache.counts.super_speed = 0;
57 		cache.dev = dev;
58 
59 		xhci_for_each_supported_usb_cap(dev, &cache.counts, xhci_count_ports);
60 	}
61 
62 	/* port_ids are 0 based */
63 	switch (path->port_type) {
64 	case 3:
65 		return path->port_id < cache.counts.super_speed;
66 	case 2:
67 		return path->port_id < cache.counts.high_speed;
68 	default:
69 		printk(BIOS_INFO, "%s: Unknown USB Version: %#x\n", __func__, path->port_type);
70 		return false;
71 	}
72 }
73 
get_xhci_dev(const struct device * dev)74 static const struct device *get_xhci_dev(const struct device *dev)
75 {
76 	while (dev && dev->ops != &xhci_pci_ops) {
77 		if (is_root_device(dev))
78 			return NULL;
79 
80 		dev = dev->upstream->dev;
81 	}
82 
83 	return dev;
84 }
85 
xhci_acpi_name(const struct device * dev)86 static const char *xhci_acpi_name(const struct device *dev)
87 {
88 	char *name;
89 	unsigned int port_id;
90 	const char *pattern;
91 	const struct device *xhci_dev;
92 
93 	/* Generate ACPI names for the usb_acpi driver */
94 	if (dev->path.type == DEVICE_PATH_USB) {
95 		/* Ports index start at 1 */
96 		port_id = dev->path.usb.port_id + 1;
97 
98 		switch (dev->path.usb.port_type) {
99 		case 0:
100 			return "RHUB";
101 		case 2:
102 			pattern = "HS%02d";
103 			break;
104 		case 3:
105 			pattern = "SS%02d";
106 			break;
107 		default:
108 			printk(BIOS_INFO, "%s: Unknown USB Version: %#x\n", __func__,
109 			       dev->path.usb.port_type);
110 			return NULL;
111 		}
112 
113 		xhci_dev = get_xhci_dev(dev);
114 		if (!xhci_dev)
115 			die("%s: xHCI controller not found for %s\n", __func__, dev_path(dev));
116 
117 		/*
118 		 * We only want to return an ACPI name for a USB port if the controller
119 		 * physically has the port. This has the desired side effect of making the
120 		 * usb_acpi driver skip generating an ACPI node for a device which has
121 		 * no port. This prevents writing an invalid SSDT table which the OS then
122 		 * complains about.
123 		 */
124 		if (!xhci_port_exists(xhci_dev, &dev->path.usb)) {
125 			printk(BIOS_WARNING, "%s: %s does not exist on xHC ", __func__,
126 			       dev_path(dev));
127 			/* dev_path uses a static buffer :( */
128 			printk(BIOS_WARNING, "%s\n", dev_path(xhci_dev));
129 
130 			return NULL;
131 		}
132 
133 		name = malloc(ACPI_NAME_BUFFER_SIZE);
134 		snprintf(name, ACPI_NAME_BUFFER_SIZE, pattern, port_id);
135 		name[4] = '\0';
136 
137 		return name;
138 	} else if (dev->ops == &xhci_pci_ops) {
139 		return dev->name;
140 	}
141 
142 	printk(BIOS_ERR, "%s: Unknown device %s\n", __func__, dev_path(dev));
143 
144 	return NULL;
145 }
146 
xhci_generate_port_acpi(void * context,const struct xhci_supported_protocol * data)147 static void xhci_generate_port_acpi(void *context, const struct xhci_supported_protocol *data)
148 {
149 	const char *format;
150 	char buf[16];
151 	struct port_counts *counts = context;
152 	unsigned int *dev_num;
153 
154 	xhci_print_supported_protocol(data);
155 
156 	if (data->major_rev == 3) {
157 		format = "SS%02d";
158 		dev_num = &counts->super_speed;
159 	} else if (data->major_rev == 2) {
160 		format = "HS%02d";
161 		dev_num = &counts->high_speed;
162 	} else {
163 		printk(BIOS_INFO, "%s: Unknown USB Version: %#x\n", __func__, data->major_rev);
164 		return;
165 	}
166 
167 	for (unsigned int i = 0; i < data->port_count; ++i) {
168 		snprintf(buf, sizeof(buf), format, ++(*dev_num));
169 		acpigen_write_device(buf);
170 		acpigen_write_name_byte("_ADR", data->port_offset + i);
171 		acpigen_pop_len();
172 	}
173 }
174 
xhci_add_devices(const struct device * dev)175 static void xhci_add_devices(const struct device *dev)
176 {
177 	/* Used by the callback to track how many ports have been seen. */
178 	struct port_counts counts = {0, 0};
179 
180 	acpigen_write_device("RHUB");
181 	acpigen_write_name_integer("_ADR", 0x00000000);
182 
183 	xhci_for_each_supported_usb_cap(dev, &counts, xhci_generate_port_acpi);
184 
185 	acpigen_pop_len();
186 }
187 
xhci_fill_ssdt(const struct device * dev)188 static void xhci_fill_ssdt(const struct device *dev)
189 {
190 	int gpe;
191 	const char *scope = acpi_device_scope(dev);
192 	const char *name = acpi_device_name(dev);
193 
194 	if (!scope || !name)
195 		return;
196 
197 	printk(BIOS_DEBUG, "xHCI SSDT generation\n");
198 
199 	acpigen_write_scope(scope);
200 	acpigen_write_device(name);
201 
202 	acpigen_write_ADR_pci_device(dev);
203 	acpigen_write_name_string("_DDN", "xHC - Extensible Host Controller");
204 	acpigen_write_STA(acpi_device_status(dev));
205 
206 	if (pci_xhci_get_wake_gpe(dev, &gpe) == CB_SUCCESS) {
207 		printk(BIOS_DEBUG, "%s: Got GPE %d for %s\n", __func__, gpe, dev_path(dev));
208 	} else {
209 		printk(BIOS_ERR, "%s: Error getting GPE for : %s\n", __func__, dev_path(dev));
210 		gpe = -1;
211 	}
212 
213 	if (gpe > 0) {
214 		acpigen_write_PRW(gpe, SLP_TYP_S3);
215 		acpigen_write_name_integer("_S0W", ACPI_DEVICE_SLEEP_D0);
216 		acpigen_write_name_integer("_S3W", ACPI_DEVICE_SLEEP_D3_COLD);
217 		acpigen_write_name_integer("_S4W", ACPI_DEVICE_SLEEP_D3_COLD);
218 	}
219 
220 	xhci_add_devices(dev);
221 
222 	acpigen_pop_len();
223 	acpigen_pop_len();
224 }
225 
xhci_enable(struct device * dev)226 static void xhci_enable(struct device *dev)
227 {
228 	char *name;
229 	uint32_t class = pci_read_config32(dev, PCI_CLASS_REVISION);
230 	/* Class code, the upper 3 bytes of PCI_CLASS_REVISION. */
231 	class >>= 8;
232 
233 	if (class != PCI_XHCI_CLASSCODE) {
234 		printk(BIOS_ERR, "Incorrect xHCI class code: %#x\n", class);
235 		dev->enabled = 0;
236 		return;
237 	}
238 
239 	name = malloc(ACPI_NAME_BUFFER_SIZE);
240 	snprintf(name, ACPI_NAME_BUFFER_SIZE, "XHC%d", controller_count++);
241 	dev->name = name;
242 }
243 
244 const struct device_operations xhci_pci_ops = {
245 	.read_resources		= pci_dev_read_resources,
246 	.set_resources		= pci_dev_set_resources,
247 	.enable_resources	= pci_dev_enable_resources,
248 	.init			= pci_dev_init,
249 	.scan_bus		= scan_static_bus,
250 	.enable			= xhci_enable,
251 	.ops_pci		= &pci_dev_ops_pci,
252 	.acpi_fill_ssdt		= xhci_fill_ssdt,
253 	.acpi_name		= xhci_acpi_name,
254 };
255