blob: ebbe4b2cf52a6b965f704aeb8b8702e4517ec282 [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>
Karthikeyan Ramasubramanian0bb5b1c2022-05-02 13:16:15 -06005
6#include "chip.h"
7
8static const char *usb_hub_acpi_name(const struct device *dev)
9{
Karthikeyan Ramasubramanian0bb5b1c2022-05-02 13:16:15 -060010 const char *pattern;
Arthur Heymans5d8fe862022-05-13 17:30:47 +020011 struct drivers_usb_hub_config *config = dev->chip_info;
12
13 if (config->acpi_name[0] != 0)
14 return config->acpi_name;
Karthikeyan Ramasubramanian0bb5b1c2022-05-02 13:16:15 -060015
16 /* USB ACPI driver does not have acpi_name operation defined. Hence return
17 the ACPI name for both the hub and any downstream facing ports. */
18 switch (dev->path.usb.port_type) {
19 case 0:
20 return "EHUB";
21 case 2:
22 pattern = "HS%02d";
23 break;
24 case 3:
25 pattern = "SS%02d";
26 break;
27 default:
28 return NULL;
29 }
30
Arthur Heymans5d8fe862022-05-13 17:30:47 +020031 snprintf(config->acpi_name, sizeof(config->acpi_name), pattern,
32 dev->path.usb.port_id + 1);
Karthikeyan Ramasubramanian0bb5b1c2022-05-02 13:16:15 -060033
Arthur Heymans5d8fe862022-05-13 17:30:47 +020034 return config->acpi_name;
Karthikeyan Ramasubramanian0bb5b1c2022-05-02 13:16:15 -060035}
36
37static void usb_hub_add_ports(const struct device *dev)
38{
39 const struct drivers_usb_hub_config *config = config_of(dev);
40 struct device *port = NULL;
41 unsigned int child_count = 0;
42
Arthur Heymans7fcd4d52023-08-24 15:12:19 +020043 while ((port = dev_bus_each_child(dev->downstream, port)) != NULL) {
Karthikeyan Ramasubramanian0bb5b1c2022-05-02 13:16:15 -060044 if (child_count++ >= config->port_count) {
45 printk(BIOS_WARNING, "%s cannot be added. Port Count limit reached.\n",
46 dev_name(port));
47 continue;
48 }
49 acpigen_write_device(usb_hub_acpi_name(port));
50 acpigen_write_name_byte("_ADR", port->path.usb.port_id + 1);
51 acpigen_write_device_end();
52 }
53}
54
55static void usb_hub_acpi_fill_ssdt(const struct device *dev)
56{
57 const struct drivers_usb_hub_config *config = config_of(dev);
58 const char *scope = acpi_device_scope(dev);
59 const char *name = acpi_device_name(dev);
60
61 acpigen_write_scope(scope);
62 acpigen_write_device(name);
63 acpigen_write_ADR(0);
64 if (config->name)
65 acpigen_write_name_string("_DDN", config->name);
66 if (config->desc)
67 acpigen_write_name_unicode("_STR", config->desc);
68 usb_hub_add_ports(dev);
69 acpigen_write_device_end();
70 acpigen_write_scope_end();
71}
72
73static struct device_operations usb_hub_ops = {
74 .read_resources = noop_read_resources,
75 .set_resources = noop_set_resources,
76 .scan_bus = scan_static_bus,
77 .acpi_fill_ssdt = usb_hub_acpi_fill_ssdt,
78 .acpi_name = usb_hub_acpi_name
79};
80
81static void usb_hub_acpi_enable(struct device *dev)
82{
83 dev->ops = &usb_hub_ops;
84}
85
86struct chip_operations drivers_usb_hub_ops = {
Nicholas Sudsgaardbfb11be2024-01-30 09:53:46 +090087 .name = "USB Hub",
Karthikeyan Ramasubramanian0bb5b1c2022-05-02 13:16:15 -060088 .enable_dev = usb_hub_acpi_enable
89};