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 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 return PTR_ERR(th); 105 106 th->activate = intel_th_pci_activate; 107 th->deactivate = intel_th_pci_deactivate; 108 109 pci_set_master(pdev); 110 111 return 0; 112 } 113 114 static void intel_th_pci_remove(struct pci_dev *pdev) 115 { 116 struct intel_th *th = pci_get_drvdata(pdev); 117 118 intel_th_free(th); 119 120 pci_free_irq_vectors(pdev); 121 } 122 123 static const struct intel_th_drvdata intel_th_1x_multi_is_broken = { 124 .multi_is_broken = 1, 125 }; 126 127 static const struct intel_th_drvdata intel_th_2x = { 128 .tscu_enable = 1, 129 .has_mintctl = 1, 130 }; 131 132 static const struct pci_device_id intel_th_pci_id_table[] = { 133 { 134 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9d26), 135 .driver_data = (kernel_ulong_t)0, 136 }, 137 { 138 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa126), 139 .driver_data = (kernel_ulong_t)0, 140 }, 141 { 142 /* Apollo Lake */ 143 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a8e), 144 .driver_data = (kernel_ulong_t)0, 145 }, 146 { 147 /* Broxton */ 148 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0a80), 149 .driver_data = (kernel_ulong_t)0, 150 }, 151 { 152 /* Broxton B-step */ 153 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1a8e), 154 .driver_data = (kernel_ulong_t)0, 155 }, 156 { 157 /* Kaby Lake PCH-H */ 158 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa2a6), 159 .driver_data = (kernel_ulong_t)&intel_th_1x_multi_is_broken, 160 }, 161 { 162 /* Denverton */ 163 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x19e1), 164 .driver_data = (kernel_ulong_t)0, 165 }, 166 { 167 /* Lewisburg PCH */ 168 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa1a6), 169 .driver_data = (kernel_ulong_t)0, 170 }, 171 { 172 /* Lewisburg PCH */ 173 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa226), 174 .driver_data = (kernel_ulong_t)0, 175 }, 176 { 177 /* Gemini Lake */ 178 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x318e), 179 .driver_data = (kernel_ulong_t)&intel_th_2x, 180 }, 181 { 182 /* Cannon Lake H */ 183 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa326), 184 .driver_data = (kernel_ulong_t)&intel_th_2x, 185 }, 186 { 187 /* Cannon Lake LP */ 188 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9da6), 189 .driver_data = (kernel_ulong_t)&intel_th_2x, 190 }, 191 { 192 /* Cedar Fork PCH */ 193 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x18e1), 194 .driver_data = (kernel_ulong_t)&intel_th_2x, 195 }, 196 { 197 /* Ice Lake PCH */ 198 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x34a6), 199 .driver_data = (kernel_ulong_t)&intel_th_2x, 200 }, 201 { 202 /* Comet Lake */ 203 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x02a6), 204 .driver_data = (kernel_ulong_t)&intel_th_2x, 205 }, 206 { 207 /* Comet Lake PCH */ 208 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x06a6), 209 .driver_data = (kernel_ulong_t)&intel_th_2x, 210 }, 211 { 212 /* Comet Lake PCH-V */ 213 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa3a6), 214 .driver_data = (kernel_ulong_t)&intel_th_1x_multi_is_broken, 215 }, 216 { 217 /* Ice Lake NNPI */ 218 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x45c5), 219 .driver_data = (kernel_ulong_t)&intel_th_2x, 220 }, 221 { 222 /* Ice Lake CPU */ 223 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8a29), 224 .driver_data = (kernel_ulong_t)&intel_th_2x, 225 }, 226 { 227 /* Tiger Lake CPU */ 228 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9a33), 229 .driver_data = (kernel_ulong_t)&intel_th_2x, 230 }, 231 { 232 /* Tiger Lake PCH */ 233 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa0a6), 234 .driver_data = (kernel_ulong_t)&intel_th_2x, 235 }, 236 { 237 /* Tiger Lake PCH-H */ 238 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x43a6), 239 .driver_data = (kernel_ulong_t)&intel_th_2x, 240 }, 241 { 242 /* Jasper Lake PCH */ 243 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4da6), 244 .driver_data = (kernel_ulong_t)&intel_th_2x, 245 }, 246 { 247 /* Jasper Lake CPU */ 248 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4e29), 249 .driver_data = (kernel_ulong_t)&intel_th_2x, 250 }, 251 { 252 /* Elkhart Lake CPU */ 253 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4529), 254 .driver_data = (kernel_ulong_t)&intel_th_2x, 255 }, 256 { 257 /* Elkhart Lake */ 258 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4b26), 259 .driver_data = (kernel_ulong_t)&intel_th_2x, 260 }, 261 { 262 /* Emmitsburg PCH */ 263 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1bcc), 264 .driver_data = (kernel_ulong_t)&intel_th_2x, 265 }, 266 { 0 }, 267 }; 268 269 MODULE_DEVICE_TABLE(pci, intel_th_pci_id_table); 270 271 static struct pci_driver intel_th_pci_driver = { 272 .name = DRIVER_NAME, 273 .id_table = intel_th_pci_id_table, 274 .probe = intel_th_pci_probe, 275 .remove = intel_th_pci_remove, 276 }; 277 278 module_pci_driver(intel_th_pci_driver); 279 280 MODULE_LICENSE("GPL v2"); 281 MODULE_DESCRIPTION("Intel(R) Trace Hub PCI controller driver"); 282 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@intel.com>"); 283