blob: 3944952eabcfd001ea4db1ff4935480c4c74234c [file] [log] [blame]
Karthikeyan Ramasubramanian0bb5b1c2022-05-02 13:16:15 -06001/* SPDX-License-Identifier: GPL-2.0-or-later */
2
3#include <acpi/acpigen.h>
4#include <acpi/acpi_device.h>
5#include <stdlib.h>
6
7#include "chip.h"
8
9static const char *usb_hub_acpi_name(const struct device *dev)
10{
Karthikeyan Ramasubramanian0bb5b1c2022-05-02 13:16:15 -060011 const char *pattern;
Arthur Heymans5d8fe862022-05-13 17:30:47 +020012 struct drivers_usb_hub_config *config = dev->chip_info;
13
14 if (config->acpi_name[0] != 0)
15 return config->acpi_name;
Karthikeyan Ramasubramanian0bb5b1c2022-05-02 13:16:15 -060016
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
Arthur Heymans5d8fe862022-05-13 17:30:47 +020032 snprintf(config->acpi_name, sizeof(config->acpi_name), pattern,
33 dev->path.usb.port_id + 1);
Karthikeyan Ramasubramanian0bb5b1c2022-05-02 13:16:15 -060034
Arthur Heymans5d8fe862022-05-13 17:30:47 +020035 return config->acpi_name;
Karthikeyan Ramasubramanian0bb5b1c2022-05-02 13:16:15 -060036}
37
38static 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
Arthur Heymans7fcd4d52023-08-24 15:12:19 +020044 while ((port = dev_bus_each_child(dev->downstream, port)) != NULL) {
Karthikeyan Ramasubramanian0bb5b1c2022-05-02 13:16:15 -060045 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
56static 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
74static 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
82static void usb_hub_acpi_enable(struct device *dev)
83{
84 dev->ops = &usb_hub_ops;
85}
86
87struct chip_operations drivers_usb_hub_ops = {
Nicholas Sudsgaardbfb11be2024-01-30 09:53:46 +090088 .name = "USB Hub",
Karthikeyan Ramasubramanian0bb5b1c2022-05-02 13:16:15 -060089 .enable_dev = usb_hub_acpi_enable
90};