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(pdev, PCI_REG_NPKDSC, &npkdsc); 41 if (!err) { 42 npkdsc |= NPKDSC_TSACT; 43 err = pci_write_config_dword(pdev, PCI_REG_NPKDSC, 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(pdev, PCI_REG_NPKDSC, &npkdsc); 62 if (!err) { 63 npkdsc |= NPKDSC_TSACT; 64 err = pci_write_config_dword(pdev, PCI_REG_NPKDSC, 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(pdev, 1, 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(pdev, i); 100 } 101 102 th = intel_th_alloc(&pdev->dev, drvdata, resource, r); 103 if (IS_ERR(th)) { 104 err = PTR_ERR(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(pdev); 112 113 return 0; 114 115 err_free_irq: 116 pci_free_irq_vectors(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(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