coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
pci_xhci.c
Go to the documentation of this file.
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 <stdlib.h>
11 
12 #define PCI_XHCI_CLASSCODE 0x0c0330 /* USB3.0 xHCI controller */
13 
14 static unsigned int controller_count;
15 static const struct device_operations xhci_pci_ops;
16 
17 struct port_counts {
18  unsigned int high_speed;
19  unsigned int super_speed;
20 };
21 
22 __weak enum cb_err pci_xhci_get_wake_gpe(const struct device *dev, int *gpe)
23 {
24  *gpe = -1;
25  return CB_SUCCESS;
26 }
27 
28 static void xhci_count_ports(void *context, const struct xhci_supported_protocol *data)
29 {
30  struct port_counts *counts = context;
31 
32  switch (data->major_rev) {
33  case 3:
34  counts->super_speed += data->port_count;
35  return;
36  case 2:
37  counts->high_speed += data->port_count;
38  return;
39  default:
40  printk(BIOS_INFO, "%s: Unknown USB Version: %#x\n", __func__, data->major_rev);
41  return;
42  }
43 }
44 
45 static bool xhci_port_exists(const struct device *dev, const struct usb_path *path)
46 {
47  /* Cache the counts so we don't have to iterate on each invocation. */
48  static struct {
49  const struct device *dev;
50  struct port_counts counts;
51  } cache;
52 
53  if (cache.dev != dev) {
54  cache.counts.high_speed = 0;
55  cache.counts.super_speed = 0;
56  cache.dev = dev;
57 
59  }
60 
61  /* port_ids are 0 based */
62  switch (path->port_type) {
63  case 3:
64  return path->port_id < cache.counts.super_speed;
65  case 2:
66  return path->port_id < cache.counts.high_speed;
67  default:
68  printk(BIOS_INFO, "%s: Unknown USB Version: %#x\n", __func__, path->port_type);
69  return false;
70  }
71 }
72 
73 static const struct device *get_xhci_dev(const struct device *dev)
74 {
75  while (dev && dev->ops != &xhci_pci_ops) {
76  if (dev->path.type == DEVICE_PATH_ROOT)
77  return NULL;
78 
79  dev = dev->bus->dev;
80  }
81 
82  return dev;
83 }
84 
85 static const char *xhci_acpi_name(const struct device *dev)
86 {
87  char *name;
88  unsigned int port_id;
89  const char *pattern;
90  const struct device *xhci_dev;
91 
92  /* Generate ACPI names for the usb_acpi driver */
93  if (dev->path.type == DEVICE_PATH_USB) {
94  /* Ports index start at 1 */
95  port_id = dev->path.usb.port_id + 1;
96 
97  switch (dev->path.usb.port_type) {
98  case 0:
99  return "RHUB";
100  case 2:
101  pattern = "HS%02d";
102  break;
103  case 3:
104  pattern = "SS%02d";
105  break;
106  default:
107  printk(BIOS_INFO, "%s: Unknown USB Version: %#x\n", __func__,
108  dev->path.usb.port_type);
109  return NULL;
110  }
111 
112  xhci_dev = get_xhci_dev(dev);
113  if (!xhci_dev)
114  die("%s: xHCI controller not found for %s\n", __func__, dev_path(dev));
115 
116  /*
117  * We only want to return an ACPI name for a USB port if the controller
118  * physically has the port. This has the desired side effect of making the
119  * usb_acpi driver skip generating an ACPI node for a device which has
120  * no port. This prevents writing an invalid SSDT table which the OS then
121  * complains about.
122  */
123  if (!xhci_port_exists(xhci_dev, &dev->path.usb)) {
124  printk(BIOS_WARNING, "%s: %s does not exist on xHC ", __func__,
125  dev_path(dev));
126  /* dev_path uses a static buffer :( */
127  printk(BIOS_WARNING, "%s\n", dev_path(xhci_dev));
128 
129  return NULL;
130  }
131 
134  name[4] = '\0';
135 
136  return name;
137  } else if (dev->ops == &xhci_pci_ops) {
138  return dev->name;
139  }
140 
141  printk(BIOS_ERR, "%s: Unknown device %s\n", __func__, dev_path(dev));
142 
143  return NULL;
144 }
145 
146 static void xhci_generate_port_acpi(void *context, const struct xhci_supported_protocol *data)
147 {
148  const char *format;
149  char buf[16];
150  struct port_counts *counts = context;
151  unsigned int *dev_num;
152 
154 
155  if (data->major_rev == 3) {
156  format = "SS%02d";
157  dev_num = &counts->super_speed;
158  } else if (data->major_rev == 2) {
159  format = "HS%02d";
160  dev_num = &counts->high_speed;
161  } else {
162  printk(BIOS_INFO, "%s: Unknown USB Version: %#x\n", __func__, data->major_rev);
163  return;
164  }
165 
166  for (unsigned int i = 0; i < data->port_count; ++i) {
167  snprintf(buf, sizeof(buf), format, ++(*dev_num));
169  acpigen_write_name_byte("_ADR", data->port_offset + i);
170  acpigen_pop_len();
171  }
172 }
173 
174 static void xhci_add_devices(const struct device *dev)
175 {
176  /* Used by the callback to track how many ports have been seen. */
177  struct port_counts counts = {0, 0};
178 
179  acpigen_write_device("RHUB");
180  acpigen_write_name_integer("_ADR", 0x00000000);
181 
183 
184  acpigen_pop_len();
185 }
186 
187 static void xhci_fill_ssdt(const struct device *dev)
188 {
189  int gpe;
190  const char *scope = acpi_device_scope(dev);
191  const char *name = acpi_device_name(dev);
192 
193  if (!scope || !name)
194  return;
195 
196  printk(BIOS_DEBUG, "xHCI SSDT generation\n");
197 
198  acpigen_write_scope(scope);
200 
202  acpigen_write_name_string("_DDN", "xHC - Extensible Host Controller");
204 
205  if (pci_xhci_get_wake_gpe(dev, &gpe) == CB_SUCCESS) {
206  printk(BIOS_DEBUG, "%s: Got GPE %d for %s\n", __func__, gpe, dev_path(dev));
207  } else {
208  printk(BIOS_ERR, "%s: Error getting GPE for : %s\n", __func__, dev_path(dev));
209  gpe = -1;
210  }
211 
212  if (gpe > 0) {
217  }
218 
219  xhci_add_devices(dev);
220 
221  acpigen_pop_len();
222  acpigen_pop_len();
223 }
224 
225 static void xhci_enable(struct device *dev)
226 {
227  char *name;
229  /* Class code, the upper 3 bytes of PCI_CLASS_REVISION. */
230  class >>= 8;
231 
232  if (class != PCI_XHCI_CLASSCODE) {
233  printk(BIOS_ERR, "Incorrect xHCI class code: %#x\n", class);
234  dev->enabled = 0;
235  return;
236  }
237 
240  dev->name = name;
241 }
242 
243 static const struct device_operations xhci_pci_ops = {
245  .set_resources = pci_dev_set_resources,
246  .enable_resources = pci_dev_enable_resources,
247  .init = pci_dev_init,
248  .scan_bus = scan_static_bus,
249  .enable = xhci_enable,
250  .ops_pci = &pci_dev_ops_pci,
251  .acpi_fill_ssdt = xhci_fill_ssdt,
252  .acpi_name = xhci_acpi_name,
253 };
254 
255 static const unsigned short amd_pci_device_ids[] = {
263  0
264 };
265 
266 static const struct pci_driver xhci_pci_driver __pci_driver = {
267  .ops = &xhci_pci_ops,
268  .vendor = PCI_VID_AMD,
269  .devices = amd_pci_device_ids,
270 };
int acpi_device_status(const struct device *dev)
Definition: device.c:193
const char * acpi_device_name(const struct device *dev)
Definition: device.c:49
const char * acpi_device_scope(const struct device *dev)
Definition: device.c:158
void acpigen_write_PRW(u32 wake, u32 level)
Definition: acpigen.c:929
void acpigen_pop_len(void)
Definition: acpigen.c:37
void acpigen_write_name_byte(const char *name, uint8_t val)
Definition: acpigen.c:152
void acpigen_write_scope(const char *name)
Definition: acpigen.c:326
void acpigen_write_name_integer(const char *name, uint64_t val)
Definition: acpigen.c:170
void acpigen_write_STA(uint8_t status)
Definition: acpigen.c:783
void acpigen_write_device(const char *name)
Definition: acpigen.c:769
void acpigen_write_name_string(const char *name, const char *string)
Definition: acpigen.c:176
void acpigen_write_ADR_pci_device(const struct device *dev)
Definition: acpigen_pci.c:22
const char * name
Definition: mmu.c:92
static const u32 pattern[8]
Definition: ast_post.c:428
cb_err
coreboot error codes
Definition: cb_err.h:15
@ CB_SUCCESS
Call completed successfully.
Definition: cb_err.h:16
#define printk(level,...)
Definition: stdlib.h:16
void __noreturn die(const char *fmt,...)
Definition: die.c:17
void xhci_print_supported_protocol(const struct xhci_supported_protocol *supported_protocol)
Definition: xhci.c:115
enum cb_err xhci_for_each_supported_usb_cap(const struct device *device, void *context, void(*callback)(void *context, const struct xhci_supported_protocol *data))
Helper method that iterates over only the USB supported capabilities structures in the xHCI Extended ...
Definition: xhci.c:103
const char * dev_path(const struct device *dev)
Definition: device_util.c:149
@ ACPI_DEVICE_SLEEP_D0
Definition: acpi.h:48
@ ACPI_DEVICE_SLEEP_D3_COLD
Definition: acpi.h:53
#define ACPI_NAME_BUFFER_SIZE
Definition: acpi.h:59
static __always_inline u32 pci_read_config32(const struct device *dev, u16 reg)
Definition: pci_ops.h:58
void * malloc(size_t size)
Definition: malloc.c:53
#define SLP_TYP_S3
Definition: pmc.h:67
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define BIOS_WARNING
BIOS_WARNING - Bad configuration.
Definition: loglevel.h:86
static uint8_t * buf
Definition: uart.c:7
@ DEVICE_PATH_ROOT
Definition: path.h:8
@ DEVICE_PATH_USB
Definition: path.h:20
#define PCI_CLASS_REVISION
Definition: pci_def.h:40
void pci_dev_init(struct device *dev)
Default handler: only runs the relevant PCI BIOS.
Definition: pci_device.c:873
void pci_dev_enable_resources(struct device *dev)
Definition: pci_device.c:721
void pci_dev_read_resources(struct device *dev)
Definition: pci_device.c:534
struct pci_operations pci_dev_ops_pci
Default device operation for PCI devices.
Definition: pci_device.c:911
void pci_dev_set_resources(struct device *dev)
Definition: pci_device.c:691
#define PCI_DID_AMD_FAM17H_MODELA0H_XHCI2
Definition: pci_ids.h:602
#define PCI_VID_AMD
Definition: pci_ids.h:496
#define PCI_DID_AMD_FAM17H_MODELA0H_XHCI0
Definition: pci_ids.h:600
#define PCI_DID_AMD_FAM17H_MODELA0H_XHCI1
Definition: pci_ids.h:601
#define PCI_DID_AMD_FAM17H_MODEL20H_XHCI0
Definition: pci_ids.h:598
#define PCI_DID_AMD_FAM17H_MODEL60H_XHCI
Definition: pci_ids.h:599
#define PCI_DID_AMD_FAM17H_MODEL18H_XHCI0
Definition: pci_ids.h:596
#define PCI_DID_AMD_FAM17H_MODEL18H_XHCI1
Definition: pci_ids.h:597
static const char * xhci_acpi_name(const struct device *dev)
Definition: pci_xhci.c:85
static bool xhci_port_exists(const struct device *dev, const struct usb_path *path)
Definition: pci_xhci.c:45
static const struct device * get_xhci_dev(const struct device *dev)
Definition: pci_xhci.c:73
static void xhci_fill_ssdt(const struct device *dev)
Definition: pci_xhci.c:187
static unsigned int controller_count
Definition: pci_xhci.c:14
static void xhci_enable(struct device *dev)
Definition: pci_xhci.c:225
static const struct pci_driver xhci_pci_driver __pci_driver
Definition: pci_xhci.c:266
static void xhci_add_devices(const struct device *dev)
Definition: pci_xhci.c:174
static void xhci_generate_port_acpi(void *context, const struct xhci_supported_protocol *data)
Definition: pci_xhci.c:146
static const struct device_operations xhci_pci_ops
Definition: pci_xhci.c:15
static const unsigned short amd_pci_device_ids[]
Definition: pci_xhci.c:255
static void xhci_count_ports(void *context, const struct xhci_supported_protocol *data)
Definition: pci_xhci.c:28
__weak enum cb_err pci_xhci_get_wake_gpe(const struct device *dev, int *gpe)
Definition: pci_xhci.c:22
#define PCI_XHCI_CLASSCODE
Definition: pci_xhci.c:12
void scan_static_bus(struct device *bus)
Definition: root_device.c:89
const struct smm_save_state_ops *legacy_ops __weak
Definition: save_state.c:8
#define NULL
Definition: stddef.h:19
unsigned int uint32_t
Definition: stdint.h:14
DEVTREE_CONST struct device * dev
Definition: device.h:78
void(* read_resources)(struct device *dev)
Definition: device.h:39
struct usb_path usb
Definition: path.h:127
enum device_path_type type
Definition: path.h:114
Definition: device.h:107
const char * name
Definition: device.h:145
struct device_path path
Definition: device.h:115
struct device_operations * ops
Definition: device.h:143
DEVTREE_CONST struct bus * bus
Definition: device.h:108
unsigned int enabled
Definition: device.h:122
unsigned int high_speed
Definition: pci_xhci.c:18
unsigned int super_speed
Definition: pci_xhci.c:19
Definition: path.h:100
unsigned int port_type
Definition: path.h:101
unsigned int port_id
Definition: path.h:102
uint32_t port_count
Definition: xhci.h:33
uint32_t port_offset
Definition: xhci.h:32
uint32_t major_rev
Definition: xhci.h:22
int snprintf(char *buf, size_t size, const char *fmt,...)
Note: This file is only for POSIX compatibility, and is meant to be chain-included via string....
Definition: vsprintf.c:35