xref: /linux/drivers/thunderbolt/pci.c (revision 3d5e48944e824bddc20d7b874e784f7b279636fe)
1*e241d98eSKonrad Dybcio // SPDX-License-Identifier: GPL-2.0-only
2*e241d98eSKonrad Dybcio /*
3*e241d98eSKonrad Dybcio  * Thunderbolt driver - PCI NHI driver
4*e241d98eSKonrad Dybcio  *
5*e241d98eSKonrad Dybcio  * Copyright (c) 2014 Andreas Noever <andreas.noever@gmail.com>
6*e241d98eSKonrad Dybcio  * Copyright (C) 2018, Intel Corporation
7*e241d98eSKonrad Dybcio  */
8*e241d98eSKonrad Dybcio 
9*e241d98eSKonrad Dybcio #include <linux/pm_runtime.h>
10*e241d98eSKonrad Dybcio #include <linux/slab.h>
11*e241d98eSKonrad Dybcio #include <linux/errno.h>
12*e241d98eSKonrad Dybcio #include <linux/pci.h>
13*e241d98eSKonrad Dybcio #include <linux/dma-mapping.h>
14*e241d98eSKonrad Dybcio #include <linux/interrupt.h>
15*e241d98eSKonrad Dybcio #include <linux/iommu.h>
16*e241d98eSKonrad Dybcio #include <linux/module.h>
17*e241d98eSKonrad Dybcio #include <linux/delay.h>
18*e241d98eSKonrad Dybcio #include <linux/property.h>
19*e241d98eSKonrad Dybcio #include <linux/string_helpers.h>
20*e241d98eSKonrad Dybcio #include <linux/suspend.h>
21*e241d98eSKonrad Dybcio 
22*e241d98eSKonrad Dybcio #include "nhi.h"
23*e241d98eSKonrad Dybcio #include "nhi_regs.h"
24*e241d98eSKonrad Dybcio #include "tb.h"
25*e241d98eSKonrad Dybcio 
26*e241d98eSKonrad Dybcio /**
27*e241d98eSKonrad Dybcio  * struct tb_nhi_pci - NHI device connected over PCIe
28*e241d98eSKonrad Dybcio  * @nhi: NHI device
29*e241d98eSKonrad Dybcio  * @msix_ida: Used to allocate MSI-X vectors for rings
30*e241d98eSKonrad Dybcio  */
31*e241d98eSKonrad Dybcio struct tb_nhi_pci {
32*e241d98eSKonrad Dybcio 	struct tb_nhi nhi;
33*e241d98eSKonrad Dybcio 	struct ida msix_ida;
34*e241d98eSKonrad Dybcio };
35*e241d98eSKonrad Dybcio 
36*e241d98eSKonrad Dybcio static inline struct tb_nhi_pci *nhi_to_pci(struct tb_nhi *nhi)
37*e241d98eSKonrad Dybcio {
38*e241d98eSKonrad Dybcio 	return container_of(nhi, struct tb_nhi_pci, nhi);
39*e241d98eSKonrad Dybcio }
40*e241d98eSKonrad Dybcio 
41*e241d98eSKonrad Dybcio static void nhi_pci_check_quirks(struct tb_nhi_pci *nhi_pci)
42*e241d98eSKonrad Dybcio {
43*e241d98eSKonrad Dybcio 	struct tb_nhi *nhi = &nhi_pci->nhi;
44*e241d98eSKonrad Dybcio 	struct pci_dev *pdev = to_pci_dev(nhi->dev);
45*e241d98eSKonrad Dybcio 
46*e241d98eSKonrad Dybcio 	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
47*e241d98eSKonrad Dybcio 		/*
48*e241d98eSKonrad Dybcio 		 * Intel hardware supports auto clear of the interrupt
49*e241d98eSKonrad Dybcio 		 * status register right after interrupt is being
50*e241d98eSKonrad Dybcio 		 * issued.
51*e241d98eSKonrad Dybcio 		 */
52*e241d98eSKonrad Dybcio 		nhi->quirks |= QUIRK_AUTO_CLEAR_INT;
53*e241d98eSKonrad Dybcio 
54*e241d98eSKonrad Dybcio 		switch (pdev->device) {
55*e241d98eSKonrad Dybcio 		case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI:
56*e241d98eSKonrad Dybcio 		case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI:
57*e241d98eSKonrad Dybcio 			/*
58*e241d98eSKonrad Dybcio 			 * Falcon Ridge controller needs the end-to-end
59*e241d98eSKonrad Dybcio 			 * flow control workaround to avoid losing Rx
60*e241d98eSKonrad Dybcio 			 * packets when RING_FLAG_E2E is set.
61*e241d98eSKonrad Dybcio 			 */
62*e241d98eSKonrad Dybcio 			nhi->quirks |= QUIRK_E2E;
63*e241d98eSKonrad Dybcio 			break;
64*e241d98eSKonrad Dybcio 		}
65*e241d98eSKonrad Dybcio 	}
66*e241d98eSKonrad Dybcio }
67*e241d98eSKonrad Dybcio 
68*e241d98eSKonrad Dybcio static int nhi_pci_check_iommu_pdev(struct pci_dev *pdev, void *data)
69*e241d98eSKonrad Dybcio {
70*e241d98eSKonrad Dybcio 	if (!pdev->external_facing ||
71*e241d98eSKonrad Dybcio 	    !device_iommu_capable(&pdev->dev, IOMMU_CAP_PRE_BOOT_PROTECTION))
72*e241d98eSKonrad Dybcio 		return 0;
73*e241d98eSKonrad Dybcio 	*(bool *)data = true;
74*e241d98eSKonrad Dybcio 	return 1; /* Stop walking */
75*e241d98eSKonrad Dybcio }
76*e241d98eSKonrad Dybcio 
77*e241d98eSKonrad Dybcio static void nhi_pci_check_iommu(struct tb_nhi_pci *nhi_pci)
78*e241d98eSKonrad Dybcio {
79*e241d98eSKonrad Dybcio 	struct tb_nhi *nhi = &nhi_pci->nhi;
80*e241d98eSKonrad Dybcio 	struct pci_dev *pdev = to_pci_dev(nhi->dev);
81*e241d98eSKonrad Dybcio 	struct pci_bus *bus = pdev->bus;
82*e241d98eSKonrad Dybcio 	bool port_ok = false;
83*e241d98eSKonrad Dybcio 
84*e241d98eSKonrad Dybcio 	/*
85*e241d98eSKonrad Dybcio 	 * Ideally what we'd do here is grab every PCI device that
86*e241d98eSKonrad Dybcio 	 * represents a tunnelling adapter for this NHI and check their
87*e241d98eSKonrad Dybcio 	 * status directly, but unfortunately USB4 seems to make it
88*e241d98eSKonrad Dybcio 	 * obnoxiously difficult to reliably make any correlation.
89*e241d98eSKonrad Dybcio 	 *
90*e241d98eSKonrad Dybcio 	 * So for now we'll have to bodge it... Hoping that the system
91*e241d98eSKonrad Dybcio 	 * is at least sane enough that an adapter is in the same PCI
92*e241d98eSKonrad Dybcio 	 * segment as its NHI, if we can find *something* on that segment
93*e241d98eSKonrad Dybcio 	 * which meets the requirements for Kernel DMA Protection, we'll
94*e241d98eSKonrad Dybcio 	 * take that to imply that firmware is aware and has (hopefully)
95*e241d98eSKonrad Dybcio 	 * done the right thing in general. We need to know that the PCI
96*e241d98eSKonrad Dybcio 	 * layer has seen the ExternalFacingPort property which will then
97*e241d98eSKonrad Dybcio 	 * inform the IOMMU layer to enforce the complete "untrusted DMA"
98*e241d98eSKonrad Dybcio 	 * flow, but also that the IOMMU driver itself can be trusted not
99*e241d98eSKonrad Dybcio 	 * to have been subverted by a pre-boot DMA attack.
100*e241d98eSKonrad Dybcio 	 */
101*e241d98eSKonrad Dybcio 	while (bus->parent)
102*e241d98eSKonrad Dybcio 		bus = bus->parent;
103*e241d98eSKonrad Dybcio 
104*e241d98eSKonrad Dybcio 	pci_walk_bus(bus, nhi_pci_check_iommu_pdev, &port_ok);
105*e241d98eSKonrad Dybcio 
106*e241d98eSKonrad Dybcio 	nhi->iommu_dma_protection = port_ok;
107*e241d98eSKonrad Dybcio 	dev_dbg(nhi->dev, "IOMMU DMA protection is %s\n",
108*e241d98eSKonrad Dybcio 		str_enabled_disabled(port_ok));
109*e241d98eSKonrad Dybcio }
110*e241d98eSKonrad Dybcio 
111*e241d98eSKonrad Dybcio static int nhi_pci_init_msi(struct tb_nhi *nhi)
112*e241d98eSKonrad Dybcio {
113*e241d98eSKonrad Dybcio 	struct tb_nhi_pci *nhi_pci = nhi_to_pci(nhi);
114*e241d98eSKonrad Dybcio 	struct pci_dev *pdev = to_pci_dev(nhi->dev);
115*e241d98eSKonrad Dybcio 	struct device *dev = &pdev->dev;
116*e241d98eSKonrad Dybcio 	int res, irq, nvec;
117*e241d98eSKonrad Dybcio 
118*e241d98eSKonrad Dybcio 	ida_init(&nhi_pci->msix_ida);
119*e241d98eSKonrad Dybcio 
120*e241d98eSKonrad Dybcio 	/*
121*e241d98eSKonrad Dybcio 	 * The NHI has 16 MSI-X vectors or a single MSI. We first try to
122*e241d98eSKonrad Dybcio 	 * get all MSI-X vectors and if we succeed, each ring will have
123*e241d98eSKonrad Dybcio 	 * one MSI-X. If for some reason that does not work out, we
124*e241d98eSKonrad Dybcio 	 * fallback to a single MSI.
125*e241d98eSKonrad Dybcio 	 */
126*e241d98eSKonrad Dybcio 	nvec = pci_alloc_irq_vectors(pdev, MSIX_MIN_VECS, MSIX_MAX_VECS,
127*e241d98eSKonrad Dybcio 				     PCI_IRQ_MSIX);
128*e241d98eSKonrad Dybcio 	if (nvec < 0) {
129*e241d98eSKonrad Dybcio 		nvec = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
130*e241d98eSKonrad Dybcio 		if (nvec < 0)
131*e241d98eSKonrad Dybcio 			return nvec;
132*e241d98eSKonrad Dybcio 
133*e241d98eSKonrad Dybcio 		INIT_WORK(&nhi->interrupt_work, nhi_interrupt_work);
134*e241d98eSKonrad Dybcio 
135*e241d98eSKonrad Dybcio 		irq = pci_irq_vector(pdev, 0);
136*e241d98eSKonrad Dybcio 		if (irq < 0)
137*e241d98eSKonrad Dybcio 			return irq;
138*e241d98eSKonrad Dybcio 
139*e241d98eSKonrad Dybcio 		res = devm_request_irq(&pdev->dev, irq, nhi_msi,
140*e241d98eSKonrad Dybcio 				       IRQF_NO_SUSPEND, "thunderbolt", nhi);
141*e241d98eSKonrad Dybcio 		if (res)
142*e241d98eSKonrad Dybcio 			return dev_err_probe(dev, res, "request_irq failed, aborting\n");
143*e241d98eSKonrad Dybcio 	}
144*e241d98eSKonrad Dybcio 
145*e241d98eSKonrad Dybcio 	return 0;
146*e241d98eSKonrad Dybcio }
147*e241d98eSKonrad Dybcio 
148*e241d98eSKonrad Dybcio static bool nhi_pci_imr_valid(struct pci_dev *pdev)
149*e241d98eSKonrad Dybcio {
150*e241d98eSKonrad Dybcio 	u8 val;
151*e241d98eSKonrad Dybcio 
152*e241d98eSKonrad Dybcio 	if (!device_property_read_u8(&pdev->dev, "IMR_VALID", &val))
153*e241d98eSKonrad Dybcio 		return !!val;
154*e241d98eSKonrad Dybcio 
155*e241d98eSKonrad Dybcio 	return true;
156*e241d98eSKonrad Dybcio }
157*e241d98eSKonrad Dybcio 
158*e241d98eSKonrad Dybcio static void nhi_pci_start_dma_port(struct tb_nhi *nhi)
159*e241d98eSKonrad Dybcio {
160*e241d98eSKonrad Dybcio 	struct pci_dev *pdev = to_pci_dev(nhi->dev);
161*e241d98eSKonrad Dybcio 	struct pci_dev *root_port;
162*e241d98eSKonrad Dybcio 
163*e241d98eSKonrad Dybcio 	/*
164*e241d98eSKonrad Dybcio 	 * During host router NVM upgrade we should not allow root port to
165*e241d98eSKonrad Dybcio 	 * go into D3cold because some root ports cannot trigger PME
166*e241d98eSKonrad Dybcio 	 * itself. To be on the safe side keep the root port in D0 during
167*e241d98eSKonrad Dybcio 	 * the whole upgrade process.
168*e241d98eSKonrad Dybcio 	 */
169*e241d98eSKonrad Dybcio 	root_port = pcie_find_root_port(pdev);
170*e241d98eSKonrad Dybcio 	if (root_port)
171*e241d98eSKonrad Dybcio 		pm_runtime_get_noresume(&root_port->dev);
172*e241d98eSKonrad Dybcio }
173*e241d98eSKonrad Dybcio 
174*e241d98eSKonrad Dybcio static void nhi_pci_complete_dma_port(struct tb_nhi *nhi)
175*e241d98eSKonrad Dybcio {
176*e241d98eSKonrad Dybcio 	struct pci_dev *pdev = to_pci_dev(nhi->dev);
177*e241d98eSKonrad Dybcio 	struct pci_dev *root_port;
178*e241d98eSKonrad Dybcio 
179*e241d98eSKonrad Dybcio 	root_port = pcie_find_root_port(pdev);
180*e241d98eSKonrad Dybcio 	if (root_port)
181*e241d98eSKonrad Dybcio 		pm_runtime_put(&root_port->dev);
182*e241d98eSKonrad Dybcio }
183*e241d98eSKonrad Dybcio 
184*e241d98eSKonrad Dybcio static int nhi_pci_ring_request_msix(struct tb_ring *ring, bool no_suspend)
185*e241d98eSKonrad Dybcio {
186*e241d98eSKonrad Dybcio 	struct tb_nhi *nhi = ring->nhi;
187*e241d98eSKonrad Dybcio 	struct tb_nhi_pci *nhi_pci = nhi_to_pci(nhi);
188*e241d98eSKonrad Dybcio 	struct pci_dev *pdev = to_pci_dev(nhi->dev);
189*e241d98eSKonrad Dybcio 	unsigned long irqflags;
190*e241d98eSKonrad Dybcio 	int ret;
191*e241d98eSKonrad Dybcio 
192*e241d98eSKonrad Dybcio 	if (!pdev->msix_enabled)
193*e241d98eSKonrad Dybcio 		return 0;
194*e241d98eSKonrad Dybcio 
195*e241d98eSKonrad Dybcio 	ret = ida_alloc_max(&nhi_pci->msix_ida, MSIX_MAX_VECS - 1, GFP_KERNEL);
196*e241d98eSKonrad Dybcio 	if (ret < 0)
197*e241d98eSKonrad Dybcio 		return ret;
198*e241d98eSKonrad Dybcio 
199*e241d98eSKonrad Dybcio 	ring->vector = ret;
200*e241d98eSKonrad Dybcio 
201*e241d98eSKonrad Dybcio 	ret = pci_irq_vector(pdev, ring->vector);
202*e241d98eSKonrad Dybcio 	if (ret < 0)
203*e241d98eSKonrad Dybcio 		goto err_ida_remove;
204*e241d98eSKonrad Dybcio 
205*e241d98eSKonrad Dybcio 	ring->irq = ret;
206*e241d98eSKonrad Dybcio 
207*e241d98eSKonrad Dybcio 	irqflags = no_suspend ? IRQF_NO_SUSPEND : 0;
208*e241d98eSKonrad Dybcio 	ret = request_irq(ring->irq, ring_msix, irqflags, "thunderbolt", ring);
209*e241d98eSKonrad Dybcio 	if (ret)
210*e241d98eSKonrad Dybcio 		goto err_ida_remove;
211*e241d98eSKonrad Dybcio 
212*e241d98eSKonrad Dybcio 	return 0;
213*e241d98eSKonrad Dybcio 
214*e241d98eSKonrad Dybcio err_ida_remove:
215*e241d98eSKonrad Dybcio 	ida_free(&nhi_pci->msix_ida, ring->vector);
216*e241d98eSKonrad Dybcio 
217*e241d98eSKonrad Dybcio 	return ret;
218*e241d98eSKonrad Dybcio }
219*e241d98eSKonrad Dybcio 
220*e241d98eSKonrad Dybcio static void nhi_pci_ring_release_msix(struct tb_ring *ring)
221*e241d98eSKonrad Dybcio {
222*e241d98eSKonrad Dybcio 	struct tb_nhi_pci *nhi_pci = nhi_to_pci(ring->nhi);
223*e241d98eSKonrad Dybcio 
224*e241d98eSKonrad Dybcio 	if (ring->irq <= 0)
225*e241d98eSKonrad Dybcio 		return;
226*e241d98eSKonrad Dybcio 
227*e241d98eSKonrad Dybcio 	free_irq(ring->irq, ring);
228*e241d98eSKonrad Dybcio 	ida_free(&nhi_pci->msix_ida, ring->vector);
229*e241d98eSKonrad Dybcio 	ring->vector = 0;
230*e241d98eSKonrad Dybcio 	ring->irq = 0;
231*e241d98eSKonrad Dybcio }
232*e241d98eSKonrad Dybcio 
233*e241d98eSKonrad Dybcio static void nhi_pci_shutdown(struct tb_nhi *nhi)
234*e241d98eSKonrad Dybcio {
235*e241d98eSKonrad Dybcio 	struct tb_nhi_pci *nhi_pci = nhi_to_pci(nhi);
236*e241d98eSKonrad Dybcio 	struct pci_dev *pdev = to_pci_dev(nhi->dev);
237*e241d98eSKonrad Dybcio 
238*e241d98eSKonrad Dybcio 	/*
239*e241d98eSKonrad Dybcio 	 * We have to release the irq before calling flush_work. Otherwise an
240*e241d98eSKonrad Dybcio 	 * already executing IRQ handler could call schedule_work again.
241*e241d98eSKonrad Dybcio 	 */
242*e241d98eSKonrad Dybcio 	if (!pdev->msix_enabled) {
243*e241d98eSKonrad Dybcio 		devm_free_irq(nhi->dev, pdev->irq, nhi);
244*e241d98eSKonrad Dybcio 		flush_work(&nhi->interrupt_work);
245*e241d98eSKonrad Dybcio 	}
246*e241d98eSKonrad Dybcio 	ida_destroy(&nhi_pci->msix_ida);
247*e241d98eSKonrad Dybcio }
248*e241d98eSKonrad Dybcio 
249*e241d98eSKonrad Dybcio static bool nhi_pci_is_present(struct tb_nhi *nhi)
250*e241d98eSKonrad Dybcio {
251*e241d98eSKonrad Dybcio 	return pci_device_is_present(to_pci_dev(nhi->dev));
252*e241d98eSKonrad Dybcio }
253*e241d98eSKonrad Dybcio 
254*e241d98eSKonrad Dybcio static const struct tb_nhi_ops pci_nhi_default_ops = {
255*e241d98eSKonrad Dybcio 	.pre_nvm_auth = nhi_pci_start_dma_port,
256*e241d98eSKonrad Dybcio 	.post_nvm_auth = nhi_pci_complete_dma_port,
257*e241d98eSKonrad Dybcio 	.request_ring_irq = nhi_pci_ring_request_msix,
258*e241d98eSKonrad Dybcio 	.release_ring_irq = nhi_pci_ring_release_msix,
259*e241d98eSKonrad Dybcio 	.shutdown = nhi_pci_shutdown,
260*e241d98eSKonrad Dybcio 	.is_present = nhi_pci_is_present,
261*e241d98eSKonrad Dybcio 	.init_interrupts = nhi_pci_init_msi,
262*e241d98eSKonrad Dybcio };
263*e241d98eSKonrad Dybcio 
264*e241d98eSKonrad Dybcio /* Ice Lake specific NHI operations */
265*e241d98eSKonrad Dybcio 
266*e241d98eSKonrad Dybcio #define ICL_LC_MAILBOX_TIMEOUT	500 /* ms */
267*e241d98eSKonrad Dybcio 
268*e241d98eSKonrad Dybcio static int check_for_device(struct device *dev, void *data)
269*e241d98eSKonrad Dybcio {
270*e241d98eSKonrad Dybcio 	return tb_is_switch(dev);
271*e241d98eSKonrad Dybcio }
272*e241d98eSKonrad Dybcio 
273*e241d98eSKonrad Dybcio static bool icl_nhi_is_device_connected(struct tb_nhi *nhi)
274*e241d98eSKonrad Dybcio {
275*e241d98eSKonrad Dybcio 	struct tb *tb = dev_get_drvdata(nhi->dev);
276*e241d98eSKonrad Dybcio 	int ret;
277*e241d98eSKonrad Dybcio 
278*e241d98eSKonrad Dybcio 	ret = device_for_each_child(&tb->root_switch->dev, NULL,
279*e241d98eSKonrad Dybcio 				    check_for_device);
280*e241d98eSKonrad Dybcio 	return ret > 0;
281*e241d98eSKonrad Dybcio }
282*e241d98eSKonrad Dybcio 
283*e241d98eSKonrad Dybcio static int icl_nhi_force_power(struct tb_nhi *nhi, bool power)
284*e241d98eSKonrad Dybcio {
285*e241d98eSKonrad Dybcio 	struct pci_dev *pdev = to_pci_dev(nhi->dev);
286*e241d98eSKonrad Dybcio 	u32 vs_cap;
287*e241d98eSKonrad Dybcio 
288*e241d98eSKonrad Dybcio 	/*
289*e241d98eSKonrad Dybcio 	 * The Thunderbolt host controller is present always in Ice Lake
290*e241d98eSKonrad Dybcio 	 * but the firmware may not be loaded and running (depending
291*e241d98eSKonrad Dybcio 	 * whether there is device connected and so on). Each time the
292*e241d98eSKonrad Dybcio 	 * controller is used we need to "Force Power" it first and wait
293*e241d98eSKonrad Dybcio 	 * for the firmware to indicate it is up and running. This "Force
294*e241d98eSKonrad Dybcio 	 * Power" is really not about actually powering on/off the
295*e241d98eSKonrad Dybcio 	 * controller so it is accessible even if "Force Power" is off.
296*e241d98eSKonrad Dybcio 	 *
297*e241d98eSKonrad Dybcio 	 * The actual power management happens inside shared ACPI power
298*e241d98eSKonrad Dybcio 	 * resources using standard ACPI methods.
299*e241d98eSKonrad Dybcio 	 */
300*e241d98eSKonrad Dybcio 	pci_read_config_dword(pdev, VS_CAP_22, &vs_cap);
301*e241d98eSKonrad Dybcio 	if (power) {
302*e241d98eSKonrad Dybcio 		vs_cap &= ~VS_CAP_22_DMA_DELAY_MASK;
303*e241d98eSKonrad Dybcio 		vs_cap |= 0x22 << VS_CAP_22_DMA_DELAY_SHIFT;
304*e241d98eSKonrad Dybcio 		vs_cap |= VS_CAP_22_FORCE_POWER;
305*e241d98eSKonrad Dybcio 	} else {
306*e241d98eSKonrad Dybcio 		vs_cap &= ~VS_CAP_22_FORCE_POWER;
307*e241d98eSKonrad Dybcio 	}
308*e241d98eSKonrad Dybcio 	pci_write_config_dword(pdev, VS_CAP_22, vs_cap);
309*e241d98eSKonrad Dybcio 
310*e241d98eSKonrad Dybcio 	if (power) {
311*e241d98eSKonrad Dybcio 		unsigned int retries = 350;
312*e241d98eSKonrad Dybcio 		u32 val;
313*e241d98eSKonrad Dybcio 
314*e241d98eSKonrad Dybcio 		/* Wait until the firmware tells it is up and running */
315*e241d98eSKonrad Dybcio 		do {
316*e241d98eSKonrad Dybcio 			pci_read_config_dword(pdev, VS_CAP_9, &val);
317*e241d98eSKonrad Dybcio 			if (val & VS_CAP_9_FW_READY)
318*e241d98eSKonrad Dybcio 				return 0;
319*e241d98eSKonrad Dybcio 			usleep_range(3000, 3100);
320*e241d98eSKonrad Dybcio 		} while (--retries);
321*e241d98eSKonrad Dybcio 
322*e241d98eSKonrad Dybcio 		return -ETIMEDOUT;
323*e241d98eSKonrad Dybcio 	}
324*e241d98eSKonrad Dybcio 
325*e241d98eSKonrad Dybcio 	return 0;
326*e241d98eSKonrad Dybcio }
327*e241d98eSKonrad Dybcio 
328*e241d98eSKonrad Dybcio static void icl_nhi_lc_mailbox_cmd(struct tb_nhi *nhi, enum icl_lc_mailbox_cmd cmd)
329*e241d98eSKonrad Dybcio {
330*e241d98eSKonrad Dybcio 	struct pci_dev *pdev = to_pci_dev(nhi->dev);
331*e241d98eSKonrad Dybcio 	u32 data;
332*e241d98eSKonrad Dybcio 
333*e241d98eSKonrad Dybcio 	data = (cmd << VS_CAP_19_CMD_SHIFT) & VS_CAP_19_CMD_MASK;
334*e241d98eSKonrad Dybcio 	pci_write_config_dword(pdev, VS_CAP_19, data | VS_CAP_19_VALID);
335*e241d98eSKonrad Dybcio }
336*e241d98eSKonrad Dybcio 
337*e241d98eSKonrad Dybcio static int icl_nhi_lc_mailbox_cmd_complete(struct tb_nhi *nhi, int timeout)
338*e241d98eSKonrad Dybcio {
339*e241d98eSKonrad Dybcio 	struct pci_dev *pdev = to_pci_dev(nhi->dev);
340*e241d98eSKonrad Dybcio 	unsigned long end;
341*e241d98eSKonrad Dybcio 	u32 data;
342*e241d98eSKonrad Dybcio 
343*e241d98eSKonrad Dybcio 	if (!timeout)
344*e241d98eSKonrad Dybcio 		goto clear;
345*e241d98eSKonrad Dybcio 
346*e241d98eSKonrad Dybcio 	end = jiffies + msecs_to_jiffies(timeout);
347*e241d98eSKonrad Dybcio 	do {
348*e241d98eSKonrad Dybcio 		pci_read_config_dword(pdev, VS_CAP_18, &data);
349*e241d98eSKonrad Dybcio 		if (data & VS_CAP_18_DONE)
350*e241d98eSKonrad Dybcio 			goto clear;
351*e241d98eSKonrad Dybcio 		usleep_range(1000, 1100);
352*e241d98eSKonrad Dybcio 	} while (time_before(jiffies, end));
353*e241d98eSKonrad Dybcio 
354*e241d98eSKonrad Dybcio 	return -ETIMEDOUT;
355*e241d98eSKonrad Dybcio 
356*e241d98eSKonrad Dybcio clear:
357*e241d98eSKonrad Dybcio 	/* Clear the valid bit */
358*e241d98eSKonrad Dybcio 	pci_write_config_dword(pdev, VS_CAP_19, 0);
359*e241d98eSKonrad Dybcio 	return 0;
360*e241d98eSKonrad Dybcio }
361*e241d98eSKonrad Dybcio 
362*e241d98eSKonrad Dybcio static void icl_nhi_set_ltr(struct tb_nhi *nhi)
363*e241d98eSKonrad Dybcio {
364*e241d98eSKonrad Dybcio 	struct pci_dev *pdev = to_pci_dev(nhi->dev);
365*e241d98eSKonrad Dybcio 	u32 max_ltr, ltr;
366*e241d98eSKonrad Dybcio 
367*e241d98eSKonrad Dybcio 	pci_read_config_dword(pdev, VS_CAP_16, &max_ltr);
368*e241d98eSKonrad Dybcio 	max_ltr &= 0xffff;
369*e241d98eSKonrad Dybcio 	/* Program the same value for both snoop and no-snoop */
370*e241d98eSKonrad Dybcio 	ltr = max_ltr << 16 | max_ltr;
371*e241d98eSKonrad Dybcio 	pci_write_config_dword(pdev, VS_CAP_15, ltr);
372*e241d98eSKonrad Dybcio }
373*e241d98eSKonrad Dybcio 
374*e241d98eSKonrad Dybcio static int icl_nhi_suspend(struct tb_nhi *nhi)
375*e241d98eSKonrad Dybcio {
376*e241d98eSKonrad Dybcio 	struct tb *tb = dev_get_drvdata(nhi->dev);
377*e241d98eSKonrad Dybcio 	int ret;
378*e241d98eSKonrad Dybcio 
379*e241d98eSKonrad Dybcio 	if (icl_nhi_is_device_connected(nhi))
380*e241d98eSKonrad Dybcio 		return 0;
381*e241d98eSKonrad Dybcio 
382*e241d98eSKonrad Dybcio 	if (tb_switch_is_icm(tb->root_switch)) {
383*e241d98eSKonrad Dybcio 		/*
384*e241d98eSKonrad Dybcio 		 * If there is no device connected we need to perform
385*e241d98eSKonrad Dybcio 		 * both: a handshake through LC mailbox and force power
386*e241d98eSKonrad Dybcio 		 * down before entering D3.
387*e241d98eSKonrad Dybcio 		 */
388*e241d98eSKonrad Dybcio 		icl_nhi_lc_mailbox_cmd(nhi, ICL_LC_PREPARE_FOR_RESET);
389*e241d98eSKonrad Dybcio 		ret = icl_nhi_lc_mailbox_cmd_complete(nhi, ICL_LC_MAILBOX_TIMEOUT);
390*e241d98eSKonrad Dybcio 		if (ret)
391*e241d98eSKonrad Dybcio 			return ret;
392*e241d98eSKonrad Dybcio 	}
393*e241d98eSKonrad Dybcio 
394*e241d98eSKonrad Dybcio 	return icl_nhi_force_power(nhi, false);
395*e241d98eSKonrad Dybcio }
396*e241d98eSKonrad Dybcio 
397*e241d98eSKonrad Dybcio static int icl_nhi_suspend_noirq(struct tb_nhi *nhi, bool wakeup)
398*e241d98eSKonrad Dybcio {
399*e241d98eSKonrad Dybcio 	struct tb *tb = dev_get_drvdata(nhi->dev);
400*e241d98eSKonrad Dybcio 	enum icl_lc_mailbox_cmd cmd;
401*e241d98eSKonrad Dybcio 
402*e241d98eSKonrad Dybcio 	if (!pm_suspend_via_firmware())
403*e241d98eSKonrad Dybcio 		return icl_nhi_suspend(nhi);
404*e241d98eSKonrad Dybcio 
405*e241d98eSKonrad Dybcio 	if (!tb_switch_is_icm(tb->root_switch))
406*e241d98eSKonrad Dybcio 		return 0;
407*e241d98eSKonrad Dybcio 
408*e241d98eSKonrad Dybcio 	cmd = wakeup ? ICL_LC_GO2SX : ICL_LC_GO2SX_NO_WAKE;
409*e241d98eSKonrad Dybcio 	icl_nhi_lc_mailbox_cmd(nhi, cmd);
410*e241d98eSKonrad Dybcio 	return icl_nhi_lc_mailbox_cmd_complete(nhi, ICL_LC_MAILBOX_TIMEOUT);
411*e241d98eSKonrad Dybcio }
412*e241d98eSKonrad Dybcio 
413*e241d98eSKonrad Dybcio static int icl_nhi_resume(struct tb_nhi *nhi)
414*e241d98eSKonrad Dybcio {
415*e241d98eSKonrad Dybcio 	int ret;
416*e241d98eSKonrad Dybcio 
417*e241d98eSKonrad Dybcio 	ret = icl_nhi_force_power(nhi, true);
418*e241d98eSKonrad Dybcio 	if (ret)
419*e241d98eSKonrad Dybcio 		return ret;
420*e241d98eSKonrad Dybcio 
421*e241d98eSKonrad Dybcio 	icl_nhi_set_ltr(nhi);
422*e241d98eSKonrad Dybcio 	return 0;
423*e241d98eSKonrad Dybcio }
424*e241d98eSKonrad Dybcio 
425*e241d98eSKonrad Dybcio static void icl_nhi_shutdown(struct tb_nhi *nhi)
426*e241d98eSKonrad Dybcio {
427*e241d98eSKonrad Dybcio 	nhi_pci_shutdown(nhi);
428*e241d98eSKonrad Dybcio 
429*e241d98eSKonrad Dybcio 	icl_nhi_force_power(nhi, false);
430*e241d98eSKonrad Dybcio }
431*e241d98eSKonrad Dybcio 
432*e241d98eSKonrad Dybcio static const struct tb_nhi_ops icl_nhi_ops = {
433*e241d98eSKonrad Dybcio 	.init = icl_nhi_resume,
434*e241d98eSKonrad Dybcio 	.suspend_noirq = icl_nhi_suspend_noirq,
435*e241d98eSKonrad Dybcio 	.resume_noirq = icl_nhi_resume,
436*e241d98eSKonrad Dybcio 	.runtime_suspend = icl_nhi_suspend,
437*e241d98eSKonrad Dybcio 	.runtime_resume = icl_nhi_resume,
438*e241d98eSKonrad Dybcio 	.shutdown = icl_nhi_shutdown,
439*e241d98eSKonrad Dybcio 	.pre_nvm_auth = nhi_pci_start_dma_port,
440*e241d98eSKonrad Dybcio 	.post_nvm_auth = nhi_pci_complete_dma_port,
441*e241d98eSKonrad Dybcio 	.request_ring_irq = nhi_pci_ring_request_msix,
442*e241d98eSKonrad Dybcio 	.release_ring_irq = nhi_pci_ring_release_msix,
443*e241d98eSKonrad Dybcio 	.is_present = nhi_pci_is_present,
444*e241d98eSKonrad Dybcio 	.init_interrupts = nhi_pci_init_msi,
445*e241d98eSKonrad Dybcio };
446*e241d98eSKonrad Dybcio 
447*e241d98eSKonrad Dybcio static int nhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
448*e241d98eSKonrad Dybcio {
449*e241d98eSKonrad Dybcio 	struct device *dev = &pdev->dev;
450*e241d98eSKonrad Dybcio 	struct tb_nhi_pci *nhi_pci;
451*e241d98eSKonrad Dybcio 	struct tb_nhi *nhi;
452*e241d98eSKonrad Dybcio 	int res;
453*e241d98eSKonrad Dybcio 
454*e241d98eSKonrad Dybcio 	if (!nhi_pci_imr_valid(pdev))
455*e241d98eSKonrad Dybcio 		return dev_err_probe(dev, -ENODEV, "firmware image not valid, aborting\n");
456*e241d98eSKonrad Dybcio 
457*e241d98eSKonrad Dybcio 	res = pcim_enable_device(pdev);
458*e241d98eSKonrad Dybcio 	if (res)
459*e241d98eSKonrad Dybcio 		return dev_err_probe(dev, res, "cannot enable PCI device, aborting\n");
460*e241d98eSKonrad Dybcio 
461*e241d98eSKonrad Dybcio 	nhi_pci = devm_kzalloc(dev, sizeof(*nhi_pci), GFP_KERNEL);
462*e241d98eSKonrad Dybcio 	if (!nhi_pci)
463*e241d98eSKonrad Dybcio 		return -ENOMEM;
464*e241d98eSKonrad Dybcio 
465*e241d98eSKonrad Dybcio 	nhi = &nhi_pci->nhi;
466*e241d98eSKonrad Dybcio 	nhi->dev = dev;
467*e241d98eSKonrad Dybcio 	nhi->ops = (const struct tb_nhi_ops *)id->driver_data ?: &pci_nhi_default_ops;
468*e241d98eSKonrad Dybcio 
469*e241d98eSKonrad Dybcio 	nhi->iobase = pcim_iomap_region(pdev, 0, "thunderbolt");
470*e241d98eSKonrad Dybcio 	res = PTR_ERR_OR_ZERO(nhi->iobase);
471*e241d98eSKonrad Dybcio 	if (res)
472*e241d98eSKonrad Dybcio 		return dev_err_probe(dev, res, "cannot obtain PCI resources, aborting\n");
473*e241d98eSKonrad Dybcio 
474*e241d98eSKonrad Dybcio 	nhi_pci_check_quirks(nhi_pci);
475*e241d98eSKonrad Dybcio 	nhi_pci_check_iommu(nhi_pci);
476*e241d98eSKonrad Dybcio 
477*e241d98eSKonrad Dybcio 	pci_set_master(pdev);
478*e241d98eSKonrad Dybcio 
479*e241d98eSKonrad Dybcio 	return nhi_probe(&nhi_pci->nhi);
480*e241d98eSKonrad Dybcio }
481*e241d98eSKonrad Dybcio 
482*e241d98eSKonrad Dybcio static void nhi_pci_remove(struct pci_dev *pdev)
483*e241d98eSKonrad Dybcio {
484*e241d98eSKonrad Dybcio 	struct tb *tb = pci_get_drvdata(pdev);
485*e241d98eSKonrad Dybcio 	struct tb_nhi *nhi = tb->nhi;
486*e241d98eSKonrad Dybcio 
487*e241d98eSKonrad Dybcio 	pm_runtime_get_sync(&pdev->dev);
488*e241d98eSKonrad Dybcio 	pm_runtime_dont_use_autosuspend(&pdev->dev);
489*e241d98eSKonrad Dybcio 	pm_runtime_forbid(&pdev->dev);
490*e241d98eSKonrad Dybcio 
491*e241d98eSKonrad Dybcio 	tb_domain_remove(tb);
492*e241d98eSKonrad Dybcio 	wait_for_completion(&nhi->domain_released);
493*e241d98eSKonrad Dybcio 	nhi_shutdown(nhi);
494*e241d98eSKonrad Dybcio }
495*e241d98eSKonrad Dybcio 
496*e241d98eSKonrad Dybcio static struct pci_device_id nhi_ids[] = {
497*e241d98eSKonrad Dybcio 	/*
498*e241d98eSKonrad Dybcio 	 * We have to specify class, the TB bridges use the same device and
499*e241d98eSKonrad Dybcio 	 * vendor (sub)id on gen 1 and gen 2 controllers.
500*e241d98eSKonrad Dybcio 	 */
501*e241d98eSKonrad Dybcio 	{
502*e241d98eSKonrad Dybcio 		.class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0,
503*e241d98eSKonrad Dybcio 		.vendor = PCI_VENDOR_ID_INTEL,
504*e241d98eSKonrad Dybcio 		.device = PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
505*e241d98eSKonrad Dybcio 		.subvendor = 0x2222, .subdevice = 0x1111,
506*e241d98eSKonrad Dybcio 	},
507*e241d98eSKonrad Dybcio 	{
508*e241d98eSKonrad Dybcio 		.class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0,
509*e241d98eSKonrad Dybcio 		.vendor = PCI_VENDOR_ID_INTEL,
510*e241d98eSKonrad Dybcio 		.device = PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
511*e241d98eSKonrad Dybcio 		.subvendor = 0x2222, .subdevice = 0x1111,
512*e241d98eSKonrad Dybcio 	},
513*e241d98eSKonrad Dybcio 	{
514*e241d98eSKonrad Dybcio 		.class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0,
515*e241d98eSKonrad Dybcio 		.vendor = PCI_VENDOR_ID_INTEL,
516*e241d98eSKonrad Dybcio 		.device = PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI,
517*e241d98eSKonrad Dybcio 		.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
518*e241d98eSKonrad Dybcio 	},
519*e241d98eSKonrad Dybcio 	{
520*e241d98eSKonrad Dybcio 		.class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0,
521*e241d98eSKonrad Dybcio 		.vendor = PCI_VENDOR_ID_INTEL,
522*e241d98eSKonrad Dybcio 		.device = PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI,
523*e241d98eSKonrad Dybcio 		.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
524*e241d98eSKonrad Dybcio 	},
525*e241d98eSKonrad Dybcio 
526*e241d98eSKonrad Dybcio 	/* Thunderbolt 3 */
527*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_NHI) },
528*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_NHI) },
529*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_USBONLY_NHI) },
530*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_LP_NHI) },
531*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_LP_USBONLY_NHI) },
532*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_2C_NHI) },
533*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_4C_NHI) },
534*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_USBONLY_NHI) },
535*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TITAN_RIDGE_2C_NHI) },
536*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_NHI) },
537*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICL_NHI0),
538*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
539*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICL_NHI1),
540*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
541*e241d98eSKonrad Dybcio 	/* Thunderbolt 4 */
542*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGL_NHI0),
543*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
544*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGL_NHI1),
545*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
546*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGL_H_NHI0),
547*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
548*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGL_H_NHI1),
549*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
550*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADL_NHI0),
551*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
552*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADL_NHI1),
553*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
554*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_RPL_NHI0),
555*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
556*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_RPL_NHI1),
557*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
558*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTL_M_NHI0),
559*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
560*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTL_P_NHI0),
561*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
562*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTL_P_NHI1),
563*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
564*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_LNL_NHI0),
565*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
566*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_LNL_NHI1),
567*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
568*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_M_NHI0),
569*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
570*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_M_NHI1),
571*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
572*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_P_NHI0),
573*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
574*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_P_NHI1),
575*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
576*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_WCL_NHI0),
577*e241d98eSKonrad Dybcio 	  .driver_data = (kernel_ulong_t)&icl_nhi_ops },
578*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_80G_NHI) },
579*e241d98eSKonrad Dybcio 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_40G_NHI) },
580*e241d98eSKonrad Dybcio 
581*e241d98eSKonrad Dybcio 	/* Any USB4 compliant host */
582*e241d98eSKonrad Dybcio 	{ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_USB4, ~0) },
583*e241d98eSKonrad Dybcio 
584*e241d98eSKonrad Dybcio 	{ 0,}
585*e241d98eSKonrad Dybcio };
586*e241d98eSKonrad Dybcio 
587*e241d98eSKonrad Dybcio MODULE_DEVICE_TABLE(pci, nhi_ids);
588*e241d98eSKonrad Dybcio MODULE_DESCRIPTION("Thunderbolt/USB4 core driver");
589*e241d98eSKonrad Dybcio MODULE_LICENSE("GPL");
590*e241d98eSKonrad Dybcio 
591*e241d98eSKonrad Dybcio static struct pci_driver nhi_driver = {
592*e241d98eSKonrad Dybcio 	.name = "thunderbolt",
593*e241d98eSKonrad Dybcio 	.id_table = nhi_ids,
594*e241d98eSKonrad Dybcio 	.probe = nhi_pci_probe,
595*e241d98eSKonrad Dybcio 	.remove = nhi_pci_remove,
596*e241d98eSKonrad Dybcio 	.shutdown = nhi_pci_remove,
597*e241d98eSKonrad Dybcio 	.driver.pm = &nhi_pm_ops,
598*e241d98eSKonrad Dybcio };
599*e241d98eSKonrad Dybcio 
600*e241d98eSKonrad Dybcio static int __init nhi_init(void)
601*e241d98eSKonrad Dybcio {
602*e241d98eSKonrad Dybcio 	int ret;
603*e241d98eSKonrad Dybcio 
604*e241d98eSKonrad Dybcio 	ret = tb_domain_init();
605*e241d98eSKonrad Dybcio 	if (ret)
606*e241d98eSKonrad Dybcio 		return ret;
607*e241d98eSKonrad Dybcio 
608*e241d98eSKonrad Dybcio 	ret = pci_register_driver(&nhi_driver);
609*e241d98eSKonrad Dybcio 	if (ret)
610*e241d98eSKonrad Dybcio 		tb_domain_exit();
611*e241d98eSKonrad Dybcio 
612*e241d98eSKonrad Dybcio 	return ret;
613*e241d98eSKonrad Dybcio }
614*e241d98eSKonrad Dybcio 
615*e241d98eSKonrad Dybcio static void __exit nhi_unload(void)
616*e241d98eSKonrad Dybcio {
617*e241d98eSKonrad Dybcio 	pci_unregister_driver(&nhi_driver);
618*e241d98eSKonrad Dybcio 	tb_domain_exit();
619*e241d98eSKonrad Dybcio }
620*e241d98eSKonrad Dybcio 
621*e241d98eSKonrad Dybcio rootfs_initcall(nhi_init);
622*e241d98eSKonrad Dybcio module_exit(nhi_unload);
623