Duncan Laurie | ce3a974 | 2020-08-13 16:17:57 -0700 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
| 2 | |
| 3 | #include <acpi/acpigen.h> |
| 4 | #include <console/console.h> |
| 5 | #include <device/device.h> |
| 6 | #include <device/path.h> |
Duncan Laurie | ce3a974 | 2020-08-13 16:17:57 -0700 | [diff] [blame] | 7 | #include <string.h> |
Duncan Laurie | ce3a974 | 2020-08-13 16:17:57 -0700 | [diff] [blame] | 8 | #include "chip.h" |
| 9 | |
| 10 | #define PCI_HOTPLUG_IN_D3_UUID "6211E2C0-58A3-4AF3-90E1-927A4E0C55A4" |
| 11 | #define PCI_EXTERNAL_PORT_UUID "EFCC06CC-73AC-4BC3-BFF0-76143807C389" |
| 12 | |
| 13 | #if CONFIG(HAVE_ACPI_TABLES) |
Duncan Laurie | 389cb30 | 2020-10-18 15:01:22 -0700 | [diff] [blame^] | 14 | static void usb4_pcie_acpi_fill_ssdt(const struct device *dev) |
Duncan Laurie | ce3a974 | 2020-08-13 16:17:57 -0700 | [diff] [blame] | 15 | { |
| 16 | const struct soc_intel_common_block_usb4_config *config; |
| 17 | const struct device *parent; |
| 18 | struct acpi_dp *dsd, *pkg; |
| 19 | const char *usb4_path; |
| 20 | int port_id; |
| 21 | |
| 22 | /* Get parent PCI device */ |
| 23 | parent = dev->bus->dev; |
| 24 | if (!parent) { |
| 25 | printk(BIOS_ERR, "%s: Unable to find parent device\n", __func__); |
| 26 | return; |
| 27 | } |
| 28 | |
| 29 | if (!dev->enabled || !parent->enabled) |
| 30 | return; |
| 31 | |
| 32 | config = config_of(dev); |
| 33 | if (!config->usb4_port) { |
| 34 | printk(BIOS_ERR, "%s: Unable to find reference to usb4_port\n", __func__); |
| 35 | return; |
| 36 | } |
| 37 | |
| 38 | /* Get ACPI path to USB4 device. */ |
| 39 | usb4_path = acpi_device_path(config->usb4_port); |
| 40 | if (!usb4_path) { |
Duncan Laurie | 389cb30 | 2020-10-18 15:01:22 -0700 | [diff] [blame^] | 41 | printk(BIOS_ERR, "%s: Unable to find ACPI path for usb4_port %s\n", |
| 42 | __func__, dev_path(config->usb4_port)); |
Duncan Laurie | ce3a974 | 2020-08-13 16:17:57 -0700 | [diff] [blame] | 43 | return; |
| 44 | } |
| 45 | |
| 46 | usb4_path = strdup(usb4_path); |
| 47 | port_id = dev->path.generic.id; |
| 48 | |
Duncan Laurie | 389cb30 | 2020-10-18 15:01:22 -0700 | [diff] [blame^] | 49 | acpigen_write_scope(acpi_device_path(parent)); |
Duncan Laurie | ce3a974 | 2020-08-13 16:17:57 -0700 | [diff] [blame] | 50 | |
| 51 | /* Add pointer to USB4 port controller. */ |
| 52 | dsd = acpi_dp_new_table("_DSD"); |
| 53 | acpi_dp_add_reference(dsd, "usb4-host-interface", usb4_path); |
| 54 | acpi_dp_add_integer(dsd, "usb4-port-number", port_id); |
| 55 | |
| 56 | /* Indicate that device supports hotplug in D3. */ |
| 57 | pkg = acpi_dp_new_table(PCI_HOTPLUG_IN_D3_UUID); |
| 58 | acpi_dp_add_integer(pkg, "HotPlugSupportInD3", 1); |
| 59 | acpi_dp_add_package(dsd, pkg); |
| 60 | |
| 61 | /* Indicate that port is external. */ |
| 62 | pkg = acpi_dp_new_table(PCI_EXTERNAL_PORT_UUID); |
| 63 | acpi_dp_add_integer(pkg, "ExternalFacingPort", 1); |
Duncan Laurie | ce3a974 | 2020-08-13 16:17:57 -0700 | [diff] [blame] | 64 | |
| 65 | acpi_dp_add_package(dsd, pkg); |
| 66 | acpi_dp_write(dsd); |
| 67 | |
| 68 | acpigen_pop_len(); /* Scope */ |
| 69 | |
Duncan Laurie | 389cb30 | 2020-10-18 15:01:22 -0700 | [diff] [blame^] | 70 | printk(BIOS_INFO, "%s: %s at %s\n", acpi_device_path(parent), |
| 71 | config->desc ? : dev->chip_ops->name, dev_path(parent)); |
Duncan Laurie | ce3a974 | 2020-08-13 16:17:57 -0700 | [diff] [blame] | 72 | } |
| 73 | #endif |
| 74 | |
Duncan Laurie | 389cb30 | 2020-10-18 15:01:22 -0700 | [diff] [blame^] | 75 | static struct device_operations usb4_pcie_acpi_dev_ops = { |
| 76 | .read_resources = noop_read_resources, |
| 77 | .set_resources = noop_set_resources, |
Duncan Laurie | ce3a974 | 2020-08-13 16:17:57 -0700 | [diff] [blame] | 78 | #if CONFIG(HAVE_ACPI_TABLES) |
Duncan Laurie | 389cb30 | 2020-10-18 15:01:22 -0700 | [diff] [blame^] | 79 | .acpi_fill_ssdt = usb4_pcie_acpi_fill_ssdt, |
Duncan Laurie | ce3a974 | 2020-08-13 16:17:57 -0700 | [diff] [blame] | 80 | #endif |
| 81 | }; |
| 82 | |
Duncan Laurie | 389cb30 | 2020-10-18 15:01:22 -0700 | [diff] [blame^] | 83 | static void usb4_pcie_acpi_enable(struct device *dev) |
Duncan Laurie | ce3a974 | 2020-08-13 16:17:57 -0700 | [diff] [blame] | 84 | { |
Duncan Laurie | 389cb30 | 2020-10-18 15:01:22 -0700 | [diff] [blame^] | 85 | dev->ops = &usb4_pcie_acpi_dev_ops; |
Duncan Laurie | ce3a974 | 2020-08-13 16:17:57 -0700 | [diff] [blame] | 86 | } |
| 87 | |
| 88 | struct chip_operations soc_intel_common_block_usb4_ops = { |
Duncan Laurie | 389cb30 | 2020-10-18 15:01:22 -0700 | [diff] [blame^] | 89 | CHIP_NAME("Intel USB4 PCIe Root Port") |
| 90 | .enable_dev = usb4_pcie_acpi_enable |
Duncan Laurie | ce3a974 | 2020-08-13 16:17:57 -0700 | [diff] [blame] | 91 | }; |