162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * ACPI support 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2020, Intel Corporation 662306a36Sopenharmony_ci * Author: Mika Westerberg <mika.westerberg@linux.intel.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/acpi.h> 1062306a36Sopenharmony_ci#include <linux/pm_runtime.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "tb.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_cistatic acpi_status tb_acpi_add_link(acpi_handle handle, u32 level, void *data, 1562306a36Sopenharmony_ci void **ret) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci struct acpi_device *adev = acpi_fetch_acpi_dev(handle); 1862306a36Sopenharmony_ci struct fwnode_handle *fwnode; 1962306a36Sopenharmony_ci struct tb_nhi *nhi = data; 2062306a36Sopenharmony_ci struct pci_dev *pdev; 2162306a36Sopenharmony_ci struct device *dev; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci if (!adev) 2462306a36Sopenharmony_ci return AE_OK; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci fwnode = fwnode_find_reference(acpi_fwnode_handle(adev), "usb4-host-interface", 0); 2762306a36Sopenharmony_ci if (IS_ERR(fwnode)) 2862306a36Sopenharmony_ci return AE_OK; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci /* It needs to reference this NHI */ 3162306a36Sopenharmony_ci if (dev_fwnode(&nhi->pdev->dev) != fwnode) 3262306a36Sopenharmony_ci goto out_put; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci /* 3562306a36Sopenharmony_ci * Try to find physical device walking upwards to the hierarcy. 3662306a36Sopenharmony_ci * We need to do this because the xHCI driver might not yet be 3762306a36Sopenharmony_ci * bound so the USB3 SuperSpeed ports are not yet created. 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_ci do { 4062306a36Sopenharmony_ci dev = acpi_get_first_physical_node(adev); 4162306a36Sopenharmony_ci if (dev) 4262306a36Sopenharmony_ci break; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci adev = acpi_dev_parent(adev); 4562306a36Sopenharmony_ci } while (adev); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci /* 4862306a36Sopenharmony_ci * Check that the device is PCIe. This is because USB3 4962306a36Sopenharmony_ci * SuperSpeed ports have this property and they are not power 5062306a36Sopenharmony_ci * managed with the xHCI and the SuperSpeed hub so we create the 5162306a36Sopenharmony_ci * link from xHCI instead. 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_ci while (dev && !dev_is_pci(dev)) 5462306a36Sopenharmony_ci dev = dev->parent; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci if (!dev) 5762306a36Sopenharmony_ci goto out_put; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci /* 6062306a36Sopenharmony_ci * Check that this actually matches the type of device we 6162306a36Sopenharmony_ci * expect. It should either be xHCI or PCIe root/downstream 6262306a36Sopenharmony_ci * port. 6362306a36Sopenharmony_ci */ 6462306a36Sopenharmony_ci pdev = to_pci_dev(dev); 6562306a36Sopenharmony_ci if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI || 6662306a36Sopenharmony_ci (pci_is_pcie(pdev) && 6762306a36Sopenharmony_ci (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT || 6862306a36Sopenharmony_ci pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM))) { 6962306a36Sopenharmony_ci const struct device_link *link; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci /* 7262306a36Sopenharmony_ci * Make them both active first to make sure the NHI does 7362306a36Sopenharmony_ci * not runtime suspend before the consumer. The 7462306a36Sopenharmony_ci * pm_runtime_put() below then allows the consumer to 7562306a36Sopenharmony_ci * runtime suspend again (which then allows NHI runtime 7662306a36Sopenharmony_ci * suspend too now that the device link is established). 7762306a36Sopenharmony_ci */ 7862306a36Sopenharmony_ci pm_runtime_get_sync(&pdev->dev); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci link = device_link_add(&pdev->dev, &nhi->pdev->dev, 8162306a36Sopenharmony_ci DL_FLAG_AUTOREMOVE_SUPPLIER | 8262306a36Sopenharmony_ci DL_FLAG_RPM_ACTIVE | 8362306a36Sopenharmony_ci DL_FLAG_PM_RUNTIME); 8462306a36Sopenharmony_ci if (link) { 8562306a36Sopenharmony_ci dev_dbg(&nhi->pdev->dev, "created link from %s\n", 8662306a36Sopenharmony_ci dev_name(&pdev->dev)); 8762306a36Sopenharmony_ci *(bool *)ret = true; 8862306a36Sopenharmony_ci } else { 8962306a36Sopenharmony_ci dev_warn(&nhi->pdev->dev, "device link creation from %s failed\n", 9062306a36Sopenharmony_ci dev_name(&pdev->dev)); 9162306a36Sopenharmony_ci } 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci pm_runtime_put(&pdev->dev); 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ciout_put: 9762306a36Sopenharmony_ci fwnode_handle_put(fwnode); 9862306a36Sopenharmony_ci return AE_OK; 9962306a36Sopenharmony_ci} 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci/** 10262306a36Sopenharmony_ci * tb_acpi_add_links() - Add device links based on ACPI description 10362306a36Sopenharmony_ci * @nhi: Pointer to NHI 10462306a36Sopenharmony_ci * 10562306a36Sopenharmony_ci * Goes over ACPI namespace finding tunneled ports that reference to 10662306a36Sopenharmony_ci * @nhi ACPI node. For each reference a device link is added. The link 10762306a36Sopenharmony_ci * is automatically removed by the driver core. 10862306a36Sopenharmony_ci * 10962306a36Sopenharmony_ci * Returns %true if at least one link was created. 11062306a36Sopenharmony_ci */ 11162306a36Sopenharmony_cibool tb_acpi_add_links(struct tb_nhi *nhi) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci acpi_status status; 11462306a36Sopenharmony_ci bool ret = false; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci if (!has_acpi_companion(&nhi->pdev->dev)) 11762306a36Sopenharmony_ci return false; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci /* 12062306a36Sopenharmony_ci * Find all devices that have usb4-host-controller interface 12162306a36Sopenharmony_ci * property that references to this NHI. 12262306a36Sopenharmony_ci */ 12362306a36Sopenharmony_ci status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 32, 12462306a36Sopenharmony_ci tb_acpi_add_link, NULL, nhi, (void **)&ret); 12562306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 12662306a36Sopenharmony_ci dev_warn(&nhi->pdev->dev, "failed to enumerate tunneled ports\n"); 12762306a36Sopenharmony_ci return false; 12862306a36Sopenharmony_ci } 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci return ret; 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/** 13462306a36Sopenharmony_ci * tb_acpi_is_native() - Did the platform grant native TBT/USB4 control 13562306a36Sopenharmony_ci * 13662306a36Sopenharmony_ci * Returns %true if the platform granted OS native control over 13762306a36Sopenharmony_ci * TBT/USB4. In this case software based connection manager can be used, 13862306a36Sopenharmony_ci * otherwise there is firmware based connection manager running. 13962306a36Sopenharmony_ci */ 14062306a36Sopenharmony_cibool tb_acpi_is_native(void) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci return osc_sb_native_usb4_support_confirmed && 14362306a36Sopenharmony_ci osc_sb_native_usb4_control; 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci/** 14762306a36Sopenharmony_ci * tb_acpi_may_tunnel_usb3() - Is USB3 tunneling allowed by the platform 14862306a36Sopenharmony_ci * 14962306a36Sopenharmony_ci * When software based connection manager is used, this function 15062306a36Sopenharmony_ci * returns %true if platform allows native USB3 tunneling. 15162306a36Sopenharmony_ci */ 15262306a36Sopenharmony_cibool tb_acpi_may_tunnel_usb3(void) 15362306a36Sopenharmony_ci{ 15462306a36Sopenharmony_ci if (tb_acpi_is_native()) 15562306a36Sopenharmony_ci return osc_sb_native_usb4_control & OSC_USB_USB3_TUNNELING; 15662306a36Sopenharmony_ci return true; 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci/** 16062306a36Sopenharmony_ci * tb_acpi_may_tunnel_dp() - Is DisplayPort tunneling allowed by the platform 16162306a36Sopenharmony_ci * 16262306a36Sopenharmony_ci * When software based connection manager is used, this function 16362306a36Sopenharmony_ci * returns %true if platform allows native DP tunneling. 16462306a36Sopenharmony_ci */ 16562306a36Sopenharmony_cibool tb_acpi_may_tunnel_dp(void) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci if (tb_acpi_is_native()) 16862306a36Sopenharmony_ci return osc_sb_native_usb4_control & OSC_USB_DP_TUNNELING; 16962306a36Sopenharmony_ci return true; 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci/** 17362306a36Sopenharmony_ci * tb_acpi_may_tunnel_pcie() - Is PCIe tunneling allowed by the platform 17462306a36Sopenharmony_ci * 17562306a36Sopenharmony_ci * When software based connection manager is used, this function 17662306a36Sopenharmony_ci * returns %true if platform allows native PCIe tunneling. 17762306a36Sopenharmony_ci */ 17862306a36Sopenharmony_cibool tb_acpi_may_tunnel_pcie(void) 17962306a36Sopenharmony_ci{ 18062306a36Sopenharmony_ci if (tb_acpi_is_native()) 18162306a36Sopenharmony_ci return osc_sb_native_usb4_control & OSC_USB_PCIE_TUNNELING; 18262306a36Sopenharmony_ci return true; 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci/** 18662306a36Sopenharmony_ci * tb_acpi_is_xdomain_allowed() - Are XDomain connections allowed 18762306a36Sopenharmony_ci * 18862306a36Sopenharmony_ci * When software based connection manager is used, this function 18962306a36Sopenharmony_ci * returns %true if platform allows XDomain connections. 19062306a36Sopenharmony_ci */ 19162306a36Sopenharmony_cibool tb_acpi_is_xdomain_allowed(void) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci if (tb_acpi_is_native()) 19462306a36Sopenharmony_ci return osc_sb_native_usb4_control & OSC_USB_XDOMAIN; 19562306a36Sopenharmony_ci return true; 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci/* UUID for retimer _DSM: e0053122-795b-4122-8a5e-57be1d26acb3 */ 19962306a36Sopenharmony_cistatic const guid_t retimer_dsm_guid = 20062306a36Sopenharmony_ci GUID_INIT(0xe0053122, 0x795b, 0x4122, 20162306a36Sopenharmony_ci 0x8a, 0x5e, 0x57, 0xbe, 0x1d, 0x26, 0xac, 0xb3); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci#define RETIMER_DSM_QUERY_ONLINE_STATE 1 20462306a36Sopenharmony_ci#define RETIMER_DSM_SET_ONLINE_STATE 2 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_cistatic int tb_acpi_retimer_set_power(struct tb_port *port, bool power) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci struct usb4_port *usb4 = port->usb4; 20962306a36Sopenharmony_ci union acpi_object argv4[2]; 21062306a36Sopenharmony_ci struct acpi_device *adev; 21162306a36Sopenharmony_ci union acpi_object *obj; 21262306a36Sopenharmony_ci int ret; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci if (!usb4->can_offline) 21562306a36Sopenharmony_ci return 0; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci adev = ACPI_COMPANION(&usb4->dev); 21862306a36Sopenharmony_ci if (WARN_ON(!adev)) 21962306a36Sopenharmony_ci return 0; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci /* Check if we are already powered on (and in correct mode) */ 22262306a36Sopenharmony_ci obj = acpi_evaluate_dsm_typed(adev->handle, &retimer_dsm_guid, 1, 22362306a36Sopenharmony_ci RETIMER_DSM_QUERY_ONLINE_STATE, NULL, 22462306a36Sopenharmony_ci ACPI_TYPE_INTEGER); 22562306a36Sopenharmony_ci if (!obj) { 22662306a36Sopenharmony_ci tb_port_warn(port, "ACPI: query online _DSM failed\n"); 22762306a36Sopenharmony_ci return -EIO; 22862306a36Sopenharmony_ci } 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci ret = obj->integer.value; 23162306a36Sopenharmony_ci ACPI_FREE(obj); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci if (power == ret) 23462306a36Sopenharmony_ci return 0; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci tb_port_dbg(port, "ACPI: calling _DSM to power %s retimers\n", 23762306a36Sopenharmony_ci power ? "on" : "off"); 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci argv4[0].type = ACPI_TYPE_PACKAGE; 24062306a36Sopenharmony_ci argv4[0].package.count = 1; 24162306a36Sopenharmony_ci argv4[0].package.elements = &argv4[1]; 24262306a36Sopenharmony_ci argv4[1].integer.type = ACPI_TYPE_INTEGER; 24362306a36Sopenharmony_ci argv4[1].integer.value = power; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci obj = acpi_evaluate_dsm_typed(adev->handle, &retimer_dsm_guid, 1, 24662306a36Sopenharmony_ci RETIMER_DSM_SET_ONLINE_STATE, argv4, 24762306a36Sopenharmony_ci ACPI_TYPE_INTEGER); 24862306a36Sopenharmony_ci if (!obj) { 24962306a36Sopenharmony_ci tb_port_warn(port, 25062306a36Sopenharmony_ci "ACPI: set online state _DSM evaluation failed\n"); 25162306a36Sopenharmony_ci return -EIO; 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci ret = obj->integer.value; 25562306a36Sopenharmony_ci ACPI_FREE(obj); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci if (ret >= 0) { 25862306a36Sopenharmony_ci if (power) 25962306a36Sopenharmony_ci return ret == 1 ? 0 : -EBUSY; 26062306a36Sopenharmony_ci return 0; 26162306a36Sopenharmony_ci } 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci tb_port_warn(port, "ACPI: set online state _DSM failed with error %d\n", ret); 26462306a36Sopenharmony_ci return -EIO; 26562306a36Sopenharmony_ci} 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci/** 26862306a36Sopenharmony_ci * tb_acpi_power_on_retimers() - Call platform to power on retimers 26962306a36Sopenharmony_ci * @port: USB4 port 27062306a36Sopenharmony_ci * 27162306a36Sopenharmony_ci * Calls platform to turn on power to all retimers behind this USB4 27262306a36Sopenharmony_ci * port. After this function returns successfully the caller can 27362306a36Sopenharmony_ci * continue with the normal retimer flows (as specified in the USB4 27462306a36Sopenharmony_ci * spec). Note if this returns %-EBUSY it means the type-C port is in 27562306a36Sopenharmony_ci * non-USB4/TBT mode (there is non-USB4/TBT device connected). 27662306a36Sopenharmony_ci * 27762306a36Sopenharmony_ci * This should only be called if the USB4/TBT link is not up. 27862306a36Sopenharmony_ci * 27962306a36Sopenharmony_ci * Returns %0 on success. 28062306a36Sopenharmony_ci */ 28162306a36Sopenharmony_ciint tb_acpi_power_on_retimers(struct tb_port *port) 28262306a36Sopenharmony_ci{ 28362306a36Sopenharmony_ci return tb_acpi_retimer_set_power(port, true); 28462306a36Sopenharmony_ci} 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci/** 28762306a36Sopenharmony_ci * tb_acpi_power_off_retimers() - Call platform to power off retimers 28862306a36Sopenharmony_ci * @port: USB4 port 28962306a36Sopenharmony_ci * 29062306a36Sopenharmony_ci * This is the opposite of tb_acpi_power_on_retimers(). After returning 29162306a36Sopenharmony_ci * successfully the normal operations with the @port can continue. 29262306a36Sopenharmony_ci * 29362306a36Sopenharmony_ci * Returns %0 on success. 29462306a36Sopenharmony_ci */ 29562306a36Sopenharmony_ciint tb_acpi_power_off_retimers(struct tb_port *port) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci return tb_acpi_retimer_set_power(port, false); 29862306a36Sopenharmony_ci} 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_cistatic bool tb_acpi_bus_match(struct device *dev) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci return tb_is_switch(dev) || tb_is_usb4_port_device(dev); 30362306a36Sopenharmony_ci} 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_cistatic struct acpi_device *tb_acpi_switch_find_companion(struct tb_switch *sw) 30662306a36Sopenharmony_ci{ 30762306a36Sopenharmony_ci struct tb_switch *parent_sw = tb_switch_parent(sw); 30862306a36Sopenharmony_ci struct acpi_device *adev = NULL; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci /* 31162306a36Sopenharmony_ci * Device routers exists under the downstream facing USB4 port 31262306a36Sopenharmony_ci * of the parent router. Their _ADR is always 0. 31362306a36Sopenharmony_ci */ 31462306a36Sopenharmony_ci if (parent_sw) { 31562306a36Sopenharmony_ci struct tb_port *port = tb_switch_downstream_port(sw); 31662306a36Sopenharmony_ci struct acpi_device *port_adev; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci port_adev = acpi_find_child_by_adr(ACPI_COMPANION(&parent_sw->dev), 31962306a36Sopenharmony_ci port->port); 32062306a36Sopenharmony_ci if (port_adev) 32162306a36Sopenharmony_ci adev = acpi_find_child_device(port_adev, 0, false); 32262306a36Sopenharmony_ci } else { 32362306a36Sopenharmony_ci struct tb_nhi *nhi = sw->tb->nhi; 32462306a36Sopenharmony_ci struct acpi_device *parent_adev; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci parent_adev = ACPI_COMPANION(&nhi->pdev->dev); 32762306a36Sopenharmony_ci if (parent_adev) 32862306a36Sopenharmony_ci adev = acpi_find_child_device(parent_adev, 0, false); 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci return adev; 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_cistatic struct acpi_device *tb_acpi_find_companion(struct device *dev) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci /* 33762306a36Sopenharmony_ci * The Thunderbolt/USB4 hierarchy looks like following: 33862306a36Sopenharmony_ci * 33962306a36Sopenharmony_ci * Device (NHI) 34062306a36Sopenharmony_ci * Device (HR) // Host router _ADR == 0 34162306a36Sopenharmony_ci * Device (DFP0) // Downstream port _ADR == lane 0 adapter 34262306a36Sopenharmony_ci * Device (DR) // Device router _ADR == 0 34362306a36Sopenharmony_ci * Device (UFP) // Upstream port _ADR == lane 0 adapter 34462306a36Sopenharmony_ci * Device (DFP1) // Downstream port _ADR == lane 0 adapter number 34562306a36Sopenharmony_ci * 34662306a36Sopenharmony_ci * At the moment we bind the host router to the corresponding 34762306a36Sopenharmony_ci * Linux device. 34862306a36Sopenharmony_ci */ 34962306a36Sopenharmony_ci if (tb_is_switch(dev)) 35062306a36Sopenharmony_ci return tb_acpi_switch_find_companion(tb_to_switch(dev)); 35162306a36Sopenharmony_ci if (tb_is_usb4_port_device(dev)) 35262306a36Sopenharmony_ci return acpi_find_child_by_adr(ACPI_COMPANION(dev->parent), 35362306a36Sopenharmony_ci tb_to_usb4_port_device(dev)->port->port); 35462306a36Sopenharmony_ci return NULL; 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_cistatic void tb_acpi_setup(struct device *dev) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci struct acpi_device *adev = ACPI_COMPANION(dev); 36062306a36Sopenharmony_ci struct usb4_port *usb4 = tb_to_usb4_port_device(dev); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci if (!adev || !usb4) 36362306a36Sopenharmony_ci return; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci if (acpi_check_dsm(adev->handle, &retimer_dsm_guid, 1, 36662306a36Sopenharmony_ci BIT(RETIMER_DSM_QUERY_ONLINE_STATE) | 36762306a36Sopenharmony_ci BIT(RETIMER_DSM_SET_ONLINE_STATE))) 36862306a36Sopenharmony_ci usb4->can_offline = true; 36962306a36Sopenharmony_ci} 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_cistatic struct acpi_bus_type tb_acpi_bus = { 37262306a36Sopenharmony_ci .name = "thunderbolt", 37362306a36Sopenharmony_ci .match = tb_acpi_bus_match, 37462306a36Sopenharmony_ci .find_companion = tb_acpi_find_companion, 37562306a36Sopenharmony_ci .setup = tb_acpi_setup, 37662306a36Sopenharmony_ci}; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ciint tb_acpi_init(void) 37962306a36Sopenharmony_ci{ 38062306a36Sopenharmony_ci return register_acpi_bus_type(&tb_acpi_bus); 38162306a36Sopenharmony_ci} 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_civoid tb_acpi_exit(void) 38462306a36Sopenharmony_ci{ 38562306a36Sopenharmony_ci unregister_acpi_bus_type(&tb_acpi_bus); 38662306a36Sopenharmony_ci} 387