^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * ACPI support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2020, Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "tb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) static acpi_status tb_acpi_add_link(acpi_handle handle, u32 level, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) void **return_value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct fwnode_reference_args args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct fwnode_handle *fwnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct tb_nhi *nhi = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct acpi_device *adev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct pci_dev *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) if (acpi_bus_get_device(handle, &adev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) fwnode = acpi_fwnode_handle(adev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) ret = fwnode_property_get_reference_args(fwnode, "usb4-host-interface",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) NULL, 0, 0, &args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* It needs to reference this NHI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) if (nhi->pdev->dev.fwnode != args.fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) goto out_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * Try to find physical device walking upwards to the hierarcy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * We need to do this because the xHCI driver might not yet be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * bound so the USB3 SuperSpeed ports are not yet created.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) dev = acpi_get_first_physical_node(adev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) while (!dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) adev = adev->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (!adev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) dev = acpi_get_first_physical_node(adev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) goto out_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * Check that the device is PCIe. This is because USB3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * SuperSpeed ports have this property and they are not power
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * managed with the xHCI and the SuperSpeed hub so we create the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * link from xHCI instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) while (dev && !dev_is_pci(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) dev = dev->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) goto out_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * Check that this actually matches the type of device we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * expect. It should either be xHCI or PCIe root/downstream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) pdev = to_pci_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) (pci_is_pcie(pdev) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) const struct device_link *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * Make them both active first to make sure the NHI does
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * not runtime suspend before the consumer. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * pm_runtime_put() below then allows the consumer to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * runtime suspend again (which then allows NHI runtime
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * suspend too now that the device link is established).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) pm_runtime_get_sync(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) link = device_link_add(&pdev->dev, &nhi->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) DL_FLAG_AUTOREMOVE_SUPPLIER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) DL_FLAG_RPM_ACTIVE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) DL_FLAG_PM_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) dev_dbg(&nhi->pdev->dev, "created link from %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) dev_name(&pdev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) dev_warn(&nhi->pdev->dev, "device link creation from %s failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) dev_name(&pdev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) pm_runtime_put(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) out_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) fwnode_handle_put(args.fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * tb_acpi_add_links() - Add device links based on ACPI description
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * @nhi: Pointer to NHI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * Goes over ACPI namespace finding tunneled ports that reference to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * @nhi ACPI node. For each reference a device link is added. The link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * is automatically removed by the driver core.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) void tb_acpi_add_links(struct tb_nhi *nhi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (!has_acpi_companion(&nhi->pdev->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * Find all devices that have usb4-host-controller interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * property that references to this NHI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) tb_acpi_add_link, NULL, nhi, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (ACPI_FAILURE(status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) dev_warn(&nhi->pdev->dev, "failed to enumerate tunneled ports\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }