• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <acpi/acpigen.h>
4 #include <acpi/acpi_device.h>
5 #include <stdio.h>
6 
7 #include "chip.h"
8 
usb_hub_acpi_name(const struct device * dev)9 static const char *usb_hub_acpi_name(const struct device *dev)
10 {
11 	const char *pattern;
12 	struct drivers_usb_hub_config *config = dev->chip_info;
13 
14 	if (config->acpi_name[0] != 0)
15 		return config->acpi_name;
16 
17 	/* USB ACPI driver does not have acpi_name operation defined. Hence return
18 	   the ACPI name for both the hub and any downstream facing ports. */
19 	switch (dev->path.usb.port_type) {
20 	case 0:
21 		return "EHUB";
22 	case 2:
23 		pattern = "HS%02d";
24 		break;
25 	case 3:
26 		pattern = "SS%02d";
27 		break;
28 	default:
29 		return NULL;
30 	}
31 
32 	snprintf(config->acpi_name, sizeof(config->acpi_name), pattern,
33 		 dev->path.usb.port_id + 1);
34 
35 	return config->acpi_name;
36 }
37 
usb_hub_add_ports(const struct device * dev)38 static void usb_hub_add_ports(const struct device *dev)
39 {
40 	const struct drivers_usb_hub_config *config = config_of(dev);
41 	struct device *port = NULL;
42 	unsigned int child_count = 0;
43 
44 	while ((port = dev_bus_each_child(dev->downstream, port)) != NULL) {
45 		if (child_count++ >= config->port_count) {
46 			printk(BIOS_WARNING, "%s cannot be added. Port Count limit reached.\n",
47 			       dev_name(port));
48 			continue;
49 		}
50 		acpigen_write_device(usb_hub_acpi_name(port));
51 		acpigen_write_name_byte("_ADR", port->path.usb.port_id + 1);
52 		acpigen_write_device_end();
53 	}
54 }
55 
usb_hub_acpi_fill_ssdt(const struct device * dev)56 static void usb_hub_acpi_fill_ssdt(const struct device *dev)
57 {
58 	const struct drivers_usb_hub_config *config = config_of(dev);
59 	const char *scope = acpi_device_scope(dev);
60 	const char *name = acpi_device_name(dev);
61 
62 	acpigen_write_scope(scope);
63 	acpigen_write_device(name);
64 	acpigen_write_ADR(0);
65 	if (config->name)
66 		acpigen_write_name_string("_DDN", config->name);
67 	if (config->desc)
68 		acpigen_write_name_unicode("_STR", config->desc);
69 	usb_hub_add_ports(dev);
70 	acpigen_write_device_end();
71 	acpigen_write_scope_end();
72 }
73 
74 static struct device_operations usb_hub_ops = {
75 	.read_resources	= noop_read_resources,
76 	.set_resources	= noop_set_resources,
77 	.scan_bus	= scan_static_bus,
78 	.acpi_fill_ssdt	= usb_hub_acpi_fill_ssdt,
79 	.acpi_name	= usb_hub_acpi_name
80 };
81 
usb_hub_acpi_enable(struct device * dev)82 static void usb_hub_acpi_enable(struct device *dev)
83 {
84 	dev->ops = &usb_hub_ops;
85 }
86 
87 struct chip_operations drivers_usb_hub_ops = {
88 	 .name = "USB Hub",
89 	.enable_dev = usb_hub_acpi_enable
90 };
91