xref: /linux/drivers/thunderbolt/acpi.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
1  // SPDX-License-Identifier: GPL-2.0
2  /*
3   * ACPI support
4   *
5   * Copyright (C) 2020, Intel Corporation
6   * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
7   */
8  
9  #include <linux/acpi.h>
10  #include <linux/pm_runtime.h>
11  
12  #include "tb.h"
13  
tb_acpi_add_link(acpi_handle handle,u32 level,void * data,void ** ret)14  static acpi_status tb_acpi_add_link(acpi_handle handle, u32 level, void *data,
15  				    void **ret)
16  {
17  	struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
18  	struct fwnode_handle *fwnode;
19  	struct tb_nhi *nhi = data;
20  	struct pci_dev *pdev;
21  	struct device *dev;
22  
23  	if (!adev)
24  		return AE_OK;
25  
26  	fwnode = fwnode_find_reference(acpi_fwnode_handle(adev), "usb4-host-interface", 0);
27  	if (IS_ERR(fwnode))
28  		return AE_OK;
29  
30  	/* It needs to reference this NHI */
31  	if (dev_fwnode(&nhi->pdev->dev) != fwnode)
32  		goto out_put;
33  
34  	/*
35  	 * Ignore USB3 ports here as USB core will set up device links between
36  	 * tunneled USB3 devices and NHI host during USB device creation.
37  	 * USB3 ports might not even have a physical device yet if xHCI driver
38  	 * isn't bound yet.
39  	 */
40  	dev = acpi_get_first_physical_node(adev);
41  	if (!dev || !dev_is_pci(dev))
42  		goto out_put;
43  
44  	/* Check that this matches a PCIe root/downstream port. */
45  	pdev = to_pci_dev(dev);
46  	if (pci_is_pcie(pdev) &&
47  	    (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT ||
48  	     pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM)) {
49  		const struct device_link *link;
50  
51  		/*
52  		 * Make them both active first to make sure the NHI does
53  		 * not runtime suspend before the consumer. The
54  		 * pm_runtime_put() below then allows the consumer to
55  		 * runtime suspend again (which then allows NHI runtime
56  		 * suspend too now that the device link is established).
57  		 */
58  		pm_runtime_get_sync(&pdev->dev);
59  
60  		link = device_link_add(&pdev->dev, &nhi->pdev->dev,
61  				       DL_FLAG_AUTOREMOVE_SUPPLIER |
62  				       DL_FLAG_RPM_ACTIVE |
63  				       DL_FLAG_PM_RUNTIME);
64  		if (link) {
65  			dev_dbg(&nhi->pdev->dev, "created link from %s\n",
66  				dev_name(&pdev->dev));
67  			*(bool *)ret = true;
68  		} else {
69  			dev_warn(&nhi->pdev->dev, "device link creation from %s failed\n",
70  				 dev_name(&pdev->dev));
71  		}
72  
73  		pm_runtime_put(&pdev->dev);
74  	}
75  
76  out_put:
77  	fwnode_handle_put(fwnode);
78  	return AE_OK;
79  }
80  
81  /**
82   * tb_acpi_add_links() - Add device links based on ACPI description
83   * @nhi: Pointer to NHI
84   *
85   * Goes over ACPI namespace finding tunneled ports that reference to
86   * @nhi ACPI node. For each reference a device link is added. The link
87   * is automatically removed by the driver core.
88   *
89   * Returns %true if at least one link was created.
90   */
tb_acpi_add_links(struct tb_nhi * nhi)91  bool tb_acpi_add_links(struct tb_nhi *nhi)
92  {
93  	acpi_status status;
94  	bool ret = false;
95  
96  	if (!has_acpi_companion(&nhi->pdev->dev))
97  		return false;
98  
99  	/*
100  	 * Find all devices that have usb4-host-controller interface
101  	 * property that references to this NHI.
102  	 */
103  	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 32,
104  				     tb_acpi_add_link, NULL, nhi, (void **)&ret);
105  	if (ACPI_FAILURE(status)) {
106  		dev_warn(&nhi->pdev->dev, "failed to enumerate tunneled ports\n");
107  		return false;
108  	}
109  
110  	return ret;
111  }
112  
113  /**
114   * tb_acpi_is_native() - Did the platform grant native TBT/USB4 control
115   *
116   * Returns %true if the platform granted OS native control over
117   * TBT/USB4. In this case software based connection manager can be used,
118   * otherwise there is firmware based connection manager running.
119   */
tb_acpi_is_native(void)120  bool tb_acpi_is_native(void)
121  {
122  	return osc_sb_native_usb4_support_confirmed &&
123  	       osc_sb_native_usb4_control;
124  }
125  
126  /**
127   * tb_acpi_may_tunnel_usb3() - Is USB3 tunneling allowed by the platform
128   *
129   * When software based connection manager is used, this function
130   * returns %true if platform allows native USB3 tunneling.
131   */
tb_acpi_may_tunnel_usb3(void)132  bool tb_acpi_may_tunnel_usb3(void)
133  {
134  	if (tb_acpi_is_native())
135  		return osc_sb_native_usb4_control & OSC_USB_USB3_TUNNELING;
136  	return true;
137  }
138  
139  /**
140   * tb_acpi_may_tunnel_dp() - Is DisplayPort tunneling allowed by the platform
141   *
142   * When software based connection manager is used, this function
143   * returns %true if platform allows native DP tunneling.
144   */
tb_acpi_may_tunnel_dp(void)145  bool tb_acpi_may_tunnel_dp(void)
146  {
147  	if (tb_acpi_is_native())
148  		return osc_sb_native_usb4_control & OSC_USB_DP_TUNNELING;
149  	return true;
150  }
151  
152  /**
153   * tb_acpi_may_tunnel_pcie() - Is PCIe tunneling allowed by the platform
154   *
155   * When software based connection manager is used, this function
156   * returns %true if platform allows native PCIe tunneling.
157   */
tb_acpi_may_tunnel_pcie(void)158  bool tb_acpi_may_tunnel_pcie(void)
159  {
160  	if (tb_acpi_is_native())
161  		return osc_sb_native_usb4_control & OSC_USB_PCIE_TUNNELING;
162  	return true;
163  }
164  
165  /**
166   * tb_acpi_is_xdomain_allowed() - Are XDomain connections allowed
167   *
168   * When software based connection manager is used, this function
169   * returns %true if platform allows XDomain connections.
170   */
tb_acpi_is_xdomain_allowed(void)171  bool tb_acpi_is_xdomain_allowed(void)
172  {
173  	if (tb_acpi_is_native())
174  		return osc_sb_native_usb4_control & OSC_USB_XDOMAIN;
175  	return true;
176  }
177  
178  /* UUID for retimer _DSM: e0053122-795b-4122-8a5e-57be1d26acb3 */
179  static const guid_t retimer_dsm_guid =
180  	GUID_INIT(0xe0053122, 0x795b, 0x4122,
181  		  0x8a, 0x5e, 0x57, 0xbe, 0x1d, 0x26, 0xac, 0xb3);
182  
183  #define RETIMER_DSM_QUERY_ONLINE_STATE	1
184  #define RETIMER_DSM_SET_ONLINE_STATE	2
185  
tb_acpi_retimer_set_power(struct tb_port * port,bool power)186  static int tb_acpi_retimer_set_power(struct tb_port *port, bool power)
187  {
188  	struct usb4_port *usb4 = port->usb4;
189  	union acpi_object argv4[2];
190  	struct acpi_device *adev;
191  	union acpi_object *obj;
192  	int ret;
193  
194  	if (!usb4->can_offline)
195  		return 0;
196  
197  	adev = ACPI_COMPANION(&usb4->dev);
198  	if (WARN_ON(!adev))
199  		return 0;
200  
201  	/* Check if we are already powered on (and in correct mode) */
202  	obj = acpi_evaluate_dsm_typed(adev->handle, &retimer_dsm_guid, 1,
203  				      RETIMER_DSM_QUERY_ONLINE_STATE, NULL,
204  				      ACPI_TYPE_INTEGER);
205  	if (!obj) {
206  		tb_port_warn(port, "ACPI: query online _DSM failed\n");
207  		return -EIO;
208  	}
209  
210  	ret = obj->integer.value;
211  	ACPI_FREE(obj);
212  
213  	if (power == ret)
214  		return 0;
215  
216  	tb_port_dbg(port, "ACPI: calling _DSM to power %s retimers\n",
217  		    power ? "on" : "off");
218  
219  	argv4[0].type = ACPI_TYPE_PACKAGE;
220  	argv4[0].package.count = 1;
221  	argv4[0].package.elements = &argv4[1];
222  	argv4[1].integer.type = ACPI_TYPE_INTEGER;
223  	argv4[1].integer.value = power;
224  
225  	obj = acpi_evaluate_dsm_typed(adev->handle, &retimer_dsm_guid, 1,
226  				      RETIMER_DSM_SET_ONLINE_STATE, argv4,
227  				      ACPI_TYPE_INTEGER);
228  	if (!obj) {
229  		tb_port_warn(port,
230  			     "ACPI: set online state _DSM evaluation failed\n");
231  		return -EIO;
232  	}
233  
234  	ret = obj->integer.value;
235  	ACPI_FREE(obj);
236  
237  	if (ret >= 0) {
238  		if (power)
239  			return ret == 1 ? 0 : -EBUSY;
240  		return 0;
241  	}
242  
243  	tb_port_warn(port, "ACPI: set online state _DSM failed with error %d\n", ret);
244  	return -EIO;
245  }
246  
247  /**
248   * tb_acpi_power_on_retimers() - Call platform to power on retimers
249   * @port: USB4 port
250   *
251   * Calls platform to turn on power to all retimers behind this USB4
252   * port. After this function returns successfully the caller can
253   * continue with the normal retimer flows (as specified in the USB4
254   * spec). Note if this returns %-EBUSY it means the type-C port is in
255   * non-USB4/TBT mode (there is non-USB4/TBT device connected).
256   *
257   * This should only be called if the USB4/TBT link is not up.
258   *
259   * Returns %0 on success.
260   */
tb_acpi_power_on_retimers(struct tb_port * port)261  int tb_acpi_power_on_retimers(struct tb_port *port)
262  {
263  	return tb_acpi_retimer_set_power(port, true);
264  }
265  
266  /**
267   * tb_acpi_power_off_retimers() - Call platform to power off retimers
268   * @port: USB4 port
269   *
270   * This is the opposite of tb_acpi_power_on_retimers(). After returning
271   * successfully the normal operations with the @port can continue.
272   *
273   * Returns %0 on success.
274   */
tb_acpi_power_off_retimers(struct tb_port * port)275  int tb_acpi_power_off_retimers(struct tb_port *port)
276  {
277  	return tb_acpi_retimer_set_power(port, false);
278  }
279  
tb_acpi_bus_match(struct device * dev)280  static bool tb_acpi_bus_match(struct device *dev)
281  {
282  	return tb_is_switch(dev) || tb_is_usb4_port_device(dev);
283  }
284  
tb_acpi_switch_find_companion(struct tb_switch * sw)285  static struct acpi_device *tb_acpi_switch_find_companion(struct tb_switch *sw)
286  {
287  	struct tb_switch *parent_sw = tb_switch_parent(sw);
288  	struct acpi_device *adev = NULL;
289  
290  	/*
291  	 * Device routers exists under the downstream facing USB4 port
292  	 * of the parent router. Their _ADR is always 0.
293  	 */
294  	if (parent_sw) {
295  		struct tb_port *port = tb_switch_downstream_port(sw);
296  		struct acpi_device *port_adev;
297  
298  		port_adev = acpi_find_child_by_adr(ACPI_COMPANION(&parent_sw->dev),
299  						   port->port);
300  		if (port_adev)
301  			adev = acpi_find_child_device(port_adev, 0, false);
302  	} else {
303  		struct tb_nhi *nhi = sw->tb->nhi;
304  		struct acpi_device *parent_adev;
305  
306  		parent_adev = ACPI_COMPANION(&nhi->pdev->dev);
307  		if (parent_adev)
308  			adev = acpi_find_child_device(parent_adev, 0, false);
309  	}
310  
311  	return adev;
312  }
313  
tb_acpi_find_companion(struct device * dev)314  static struct acpi_device *tb_acpi_find_companion(struct device *dev)
315  {
316  	/*
317  	 * The Thunderbolt/USB4 hierarchy looks like following:
318  	 *
319  	 * Device (NHI)
320  	 *   Device (HR)		// Host router _ADR == 0
321  	 *      Device (DFP0)		// Downstream port _ADR == lane 0 adapter
322  	 *        Device (DR)		// Device router _ADR == 0
323  	 *          Device (UFP)	// Upstream port _ADR == lane 0 adapter
324  	 *      Device (DFP1)		// Downstream port _ADR == lane 0 adapter number
325  	 *
326  	 * At the moment we bind the host router to the corresponding
327  	 * Linux device.
328  	 */
329  	if (tb_is_switch(dev))
330  		return tb_acpi_switch_find_companion(tb_to_switch(dev));
331  	if (tb_is_usb4_port_device(dev))
332  		return acpi_find_child_by_adr(ACPI_COMPANION(dev->parent),
333  					      tb_to_usb4_port_device(dev)->port->port);
334  	return NULL;
335  }
336  
tb_acpi_setup(struct device * dev)337  static void tb_acpi_setup(struct device *dev)
338  {
339  	struct acpi_device *adev = ACPI_COMPANION(dev);
340  	struct usb4_port *usb4 = tb_to_usb4_port_device(dev);
341  
342  	if (!adev || !usb4)
343  		return;
344  
345  	if (acpi_check_dsm(adev->handle, &retimer_dsm_guid, 1,
346  			   BIT(RETIMER_DSM_QUERY_ONLINE_STATE) |
347  			   BIT(RETIMER_DSM_SET_ONLINE_STATE)))
348  		usb4->can_offline = true;
349  }
350  
351  static struct acpi_bus_type tb_acpi_bus = {
352  	.name = "thunderbolt",
353  	.match = tb_acpi_bus_match,
354  	.find_companion = tb_acpi_find_companion,
355  	.setup = tb_acpi_setup,
356  };
357  
tb_acpi_init(void)358  int tb_acpi_init(void)
359  {
360  	return register_acpi_bus_type(&tb_acpi_bus);
361  }
362  
tb_acpi_exit(void)363  void tb_acpi_exit(void)
364  {
365  	unregister_acpi_bus_type(&tb_acpi_bus);
366  }
367