1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Intel(R) Trace Hub pci driver |
4 | * |
5 | * Copyright (C) 2014-2015 Intel Corporation. |
6 | */ |
7 | |
8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
9 | |
10 | #include <linux/types.h> |
11 | #include <linux/module.h> |
12 | #include <linux/device.h> |
13 | #include <linux/sysfs.h> |
14 | #include <linux/pci.h> |
15 | |
16 | #include "intel_th.h" |
17 | |
18 | #define DRIVER_NAME "intel_th_pci" |
19 | |
20 | enum { |
21 | TH_PCI_CONFIG_BAR = 0, |
22 | TH_PCI_STH_SW_BAR = 2, |
23 | TH_PCI_RTIT_BAR = 4, |
24 | }; |
25 | |
26 | #define BAR_MASK (BIT(TH_PCI_CONFIG_BAR) | BIT(TH_PCI_STH_SW_BAR)) |
27 | |
28 | #define PCI_REG_NPKDSC 0x80 |
29 | #define NPKDSC_TSACT BIT(5) |
30 | |
31 | static int intel_th_pci_activate(struct intel_th *th) |
32 | { |
33 | struct pci_dev *pdev = to_pci_dev(th->dev); |
34 | u32 npkdsc; |
35 | int err; |
36 | |
37 | if (!INTEL_TH_CAP(th, tscu_enable)) |
38 | return 0; |
39 | |
40 | err = pci_read_config_dword(dev: pdev, PCI_REG_NPKDSC, val: &npkdsc); |
41 | if (!err) { |
42 | npkdsc |= NPKDSC_TSACT; |
43 | err = pci_write_config_dword(dev: pdev, PCI_REG_NPKDSC, val: npkdsc); |
44 | } |
45 | |
46 | if (err) |
47 | dev_err(&pdev->dev, "failed to read NPKDSC register\n" ); |
48 | |
49 | return err; |
50 | } |
51 | |
52 | static void intel_th_pci_deactivate(struct intel_th *th) |
53 | { |
54 | struct pci_dev *pdev = to_pci_dev(th->dev); |
55 | u32 npkdsc; |
56 | int err; |
57 | |
58 | if (!INTEL_TH_CAP(th, tscu_enable)) |
59 | return; |
60 | |
61 | err = pci_read_config_dword(dev: pdev, PCI_REG_NPKDSC, val: &npkdsc); |
62 | if (!err) { |
63 | npkdsc |= NPKDSC_TSACT; |
64 | err = pci_write_config_dword(dev: pdev, PCI_REG_NPKDSC, val: npkdsc); |
65 | } |
66 | |
67 | if (err) |
68 | dev_err(&pdev->dev, "failed to read NPKDSC register\n" ); |
69 | } |
70 | |
71 | static int intel_th_pci_probe(struct pci_dev *pdev, |
72 | const struct pci_device_id *id) |
73 | { |
74 | const struct intel_th_drvdata *drvdata = (void *)id->driver_data; |
75 | struct resource resource[TH_MMIO_END + TH_NVEC_MAX] = { |
76 | [TH_MMIO_CONFIG] = pdev->resource[TH_PCI_CONFIG_BAR], |
77 | [TH_MMIO_SW] = pdev->resource[TH_PCI_STH_SW_BAR], |
78 | }; |
79 | int err, r = TH_MMIO_SW + 1, i; |
80 | struct intel_th *th; |
81 | |
82 | err = pcim_enable_device(pdev); |
83 | if (err) |
84 | return err; |
85 | |
86 | err = pcim_iomap_regions_request_all(pdev, BAR_MASK, DRIVER_NAME); |
87 | if (err) |
88 | return err; |
89 | |
90 | if (pdev->resource[TH_PCI_RTIT_BAR].start) { |
91 | resource[TH_MMIO_RTIT] = pdev->resource[TH_PCI_RTIT_BAR]; |
92 | r++; |
93 | } |
94 | |
95 | err = pci_alloc_irq_vectors(dev: pdev, min_vecs: 1, max_vecs: 8, PCI_IRQ_ALL_TYPES); |
96 | if (err > 0) |
97 | for (i = 0; i < err; i++, r++) { |
98 | resource[r].flags = IORESOURCE_IRQ; |
99 | resource[r].start = pci_irq_vector(dev: pdev, nr: i); |
100 | } |
101 | |
102 | th = intel_th_alloc(dev: &pdev->dev, drvdata, devres: resource, ndevres: r); |
103 | if (IS_ERR(ptr: th)) { |
104 | err = PTR_ERR(ptr: th); |
105 | goto err_free_irq; |
106 | } |
107 | |
108 | th->activate = intel_th_pci_activate; |
109 | th->deactivate = intel_th_pci_deactivate; |
110 | |
111 | pci_set_master(dev: pdev); |
112 | |
113 | return 0; |
114 | |
115 | err_free_irq: |
116 | pci_free_irq_vectors(dev: pdev); |
117 | return err; |
118 | } |
119 | |
120 | static void intel_th_pci_remove(struct pci_dev *pdev) |
121 | { |
122 | struct intel_th *th = pci_get_drvdata(pdev); |
123 | |
124 | intel_th_free(th); |
125 | |
126 | pci_free_irq_vectors(dev: pdev); |
127 | } |
128 | |
129 | static const struct intel_th_drvdata intel_th_1x_multi_is_broken = { |
130 | .multi_is_broken = 1, |
131 | }; |
132 | |
133 | static const struct intel_th_drvdata intel_th_2x = { |
134 | .tscu_enable = 1, |
135 | .has_mintctl = 1, |
136 | }; |
137 | |
138 | static const struct pci_device_id intel_th_pci_id_table[] = { |
139 | { |
140 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9d26), |
141 | .driver_data = (kernel_ulong_t)0, |
142 | }, |
143 | { |
144 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa126), |
145 | .driver_data = (kernel_ulong_t)0, |
146 | }, |
147 | { |
148 | /* Apollo Lake */ |
149 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a8e), |
150 | .driver_data = (kernel_ulong_t)0, |
151 | }, |
152 | { |
153 | /* Broxton */ |
154 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0a80), |
155 | .driver_data = (kernel_ulong_t)0, |
156 | }, |
157 | { |
158 | /* Broxton B-step */ |
159 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1a8e), |
160 | .driver_data = (kernel_ulong_t)0, |
161 | }, |
162 | { |
163 | /* Kaby Lake PCH-H */ |
164 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa2a6), |
165 | .driver_data = (kernel_ulong_t)&intel_th_1x_multi_is_broken, |
166 | }, |
167 | { |
168 | /* Denverton */ |
169 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x19e1), |
170 | .driver_data = (kernel_ulong_t)0, |
171 | }, |
172 | { |
173 | /* Lewisburg PCH */ |
174 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa1a6), |
175 | .driver_data = (kernel_ulong_t)0, |
176 | }, |
177 | { |
178 | /* Lewisburg PCH */ |
179 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa226), |
180 | .driver_data = (kernel_ulong_t)0, |
181 | }, |
182 | { |
183 | /* Gemini Lake */ |
184 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x318e), |
185 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
186 | }, |
187 | { |
188 | /* Cannon Lake H */ |
189 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa326), |
190 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
191 | }, |
192 | { |
193 | /* Cannon Lake LP */ |
194 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9da6), |
195 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
196 | }, |
197 | { |
198 | /* Cedar Fork PCH */ |
199 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x18e1), |
200 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
201 | }, |
202 | { |
203 | /* Ice Lake PCH */ |
204 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x34a6), |
205 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
206 | }, |
207 | { |
208 | /* Comet Lake */ |
209 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x02a6), |
210 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
211 | }, |
212 | { |
213 | /* Comet Lake PCH */ |
214 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x06a6), |
215 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
216 | }, |
217 | { |
218 | /* Comet Lake PCH-V */ |
219 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa3a6), |
220 | .driver_data = (kernel_ulong_t)&intel_th_1x_multi_is_broken, |
221 | }, |
222 | { |
223 | /* Ice Lake NNPI */ |
224 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x45c5), |
225 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
226 | }, |
227 | { |
228 | /* Ice Lake CPU */ |
229 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8a29), |
230 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
231 | }, |
232 | { |
233 | /* Tiger Lake CPU */ |
234 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9a33), |
235 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
236 | }, |
237 | { |
238 | /* Tiger Lake PCH */ |
239 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa0a6), |
240 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
241 | }, |
242 | { |
243 | /* Tiger Lake PCH-H */ |
244 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x43a6), |
245 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
246 | }, |
247 | { |
248 | /* Jasper Lake PCH */ |
249 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4da6), |
250 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
251 | }, |
252 | { |
253 | /* Jasper Lake CPU */ |
254 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4e29), |
255 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
256 | }, |
257 | { |
258 | /* Elkhart Lake CPU */ |
259 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4529), |
260 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
261 | }, |
262 | { |
263 | /* Elkhart Lake */ |
264 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4b26), |
265 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
266 | }, |
267 | { |
268 | /* Emmitsburg PCH */ |
269 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1bcc), |
270 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
271 | }, |
272 | { |
273 | /* Alder Lake */ |
274 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7aa6), |
275 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
276 | }, |
277 | { |
278 | /* Alder Lake-P */ |
279 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x51a6), |
280 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
281 | }, |
282 | { |
283 | /* Alder Lake-M */ |
284 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x54a6), |
285 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
286 | }, |
287 | { |
288 | /* Meteor Lake-P */ |
289 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7e24), |
290 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
291 | }, |
292 | { |
293 | /* Raptor Lake-S */ |
294 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7a26), |
295 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
296 | }, |
297 | { |
298 | /* Raptor Lake-S CPU */ |
299 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa76f), |
300 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
301 | }, |
302 | { |
303 | /* Alder Lake CPU */ |
304 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x466f), |
305 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
306 | }, |
307 | { |
308 | /* Rocket Lake CPU */ |
309 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4c19), |
310 | .driver_data = (kernel_ulong_t)&intel_th_2x, |
311 | }, |
312 | { 0 }, |
313 | }; |
314 | |
315 | MODULE_DEVICE_TABLE(pci, intel_th_pci_id_table); |
316 | |
317 | static struct pci_driver intel_th_pci_driver = { |
318 | .name = DRIVER_NAME, |
319 | .id_table = intel_th_pci_id_table, |
320 | .probe = intel_th_pci_probe, |
321 | .remove = intel_th_pci_remove, |
322 | }; |
323 | |
324 | module_pci_driver(intel_th_pci_driver); |
325 | |
326 | MODULE_LICENSE("GPL v2" ); |
327 | MODULE_DESCRIPTION("Intel(R) Trace Hub PCI controller driver" ); |
328 | MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@intel.com>" ); |
329 | |