0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0009
0010 #include <linux/types.h>
0011 #include <linux/module.h>
0012 #include <linux/device.h>
0013 #include <linux/sysfs.h>
0014 #include <linux/pci.h>
0015
0016 #include "intel_th.h"
0017
0018 #define DRIVER_NAME "intel_th_pci"
0019
0020 enum {
0021 TH_PCI_CONFIG_BAR = 0,
0022 TH_PCI_STH_SW_BAR = 2,
0023 TH_PCI_RTIT_BAR = 4,
0024 };
0025
0026 #define BAR_MASK (BIT(TH_PCI_CONFIG_BAR) | BIT(TH_PCI_STH_SW_BAR))
0027
0028 #define PCI_REG_NPKDSC 0x80
0029 #define NPKDSC_TSACT BIT(5)
0030
0031 static int intel_th_pci_activate(struct intel_th *th)
0032 {
0033 struct pci_dev *pdev = to_pci_dev(th->dev);
0034 u32 npkdsc;
0035 int err;
0036
0037 if (!INTEL_TH_CAP(th, tscu_enable))
0038 return 0;
0039
0040 err = pci_read_config_dword(pdev, PCI_REG_NPKDSC, &npkdsc);
0041 if (!err) {
0042 npkdsc |= NPKDSC_TSACT;
0043 err = pci_write_config_dword(pdev, PCI_REG_NPKDSC, npkdsc);
0044 }
0045
0046 if (err)
0047 dev_err(&pdev->dev, "failed to read NPKDSC register\n");
0048
0049 return err;
0050 }
0051
0052 static void intel_th_pci_deactivate(struct intel_th *th)
0053 {
0054 struct pci_dev *pdev = to_pci_dev(th->dev);
0055 u32 npkdsc;
0056 int err;
0057
0058 if (!INTEL_TH_CAP(th, tscu_enable))
0059 return;
0060
0061 err = pci_read_config_dword(pdev, PCI_REG_NPKDSC, &npkdsc);
0062 if (!err) {
0063 npkdsc |= NPKDSC_TSACT;
0064 err = pci_write_config_dword(pdev, PCI_REG_NPKDSC, npkdsc);
0065 }
0066
0067 if (err)
0068 dev_err(&pdev->dev, "failed to read NPKDSC register\n");
0069 }
0070
0071 static int intel_th_pci_probe(struct pci_dev *pdev,
0072 const struct pci_device_id *id)
0073 {
0074 const struct intel_th_drvdata *drvdata = (void *)id->driver_data;
0075 struct resource resource[TH_MMIO_END + TH_NVEC_MAX] = {
0076 [TH_MMIO_CONFIG] = pdev->resource[TH_PCI_CONFIG_BAR],
0077 [TH_MMIO_SW] = pdev->resource[TH_PCI_STH_SW_BAR],
0078 };
0079 int err, r = TH_MMIO_SW + 1, i;
0080 struct intel_th *th;
0081
0082 err = pcim_enable_device(pdev);
0083 if (err)
0084 return err;
0085
0086 err = pcim_iomap_regions_request_all(pdev, BAR_MASK, DRIVER_NAME);
0087 if (err)
0088 return err;
0089
0090 if (pdev->resource[TH_PCI_RTIT_BAR].start) {
0091 resource[TH_MMIO_RTIT] = pdev->resource[TH_PCI_RTIT_BAR];
0092 r++;
0093 }
0094
0095 err = pci_alloc_irq_vectors(pdev, 1, 8, PCI_IRQ_ALL_TYPES);
0096 if (err > 0)
0097 for (i = 0; i < err; i++, r++) {
0098 resource[r].flags = IORESOURCE_IRQ;
0099 resource[r].start = pci_irq_vector(pdev, i);
0100 }
0101
0102 th = intel_th_alloc(&pdev->dev, drvdata, resource, r);
0103 if (IS_ERR(th)) {
0104 err = PTR_ERR(th);
0105 goto err_free_irq;
0106 }
0107
0108 th->activate = intel_th_pci_activate;
0109 th->deactivate = intel_th_pci_deactivate;
0110
0111 pci_set_master(pdev);
0112
0113 return 0;
0114
0115 err_free_irq:
0116 pci_free_irq_vectors(pdev);
0117 return err;
0118 }
0119
0120 static void intel_th_pci_remove(struct pci_dev *pdev)
0121 {
0122 struct intel_th *th = pci_get_drvdata(pdev);
0123
0124 intel_th_free(th);
0125
0126 pci_free_irq_vectors(pdev);
0127 }
0128
0129 static const struct intel_th_drvdata intel_th_1x_multi_is_broken = {
0130 .multi_is_broken = 1,
0131 };
0132
0133 static const struct intel_th_drvdata intel_th_2x = {
0134 .tscu_enable = 1,
0135 .has_mintctl = 1,
0136 };
0137
0138 static const struct pci_device_id intel_th_pci_id_table[] = {
0139 {
0140 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9d26),
0141 .driver_data = (kernel_ulong_t)0,
0142 },
0143 {
0144 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa126),
0145 .driver_data = (kernel_ulong_t)0,
0146 },
0147 {
0148
0149 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a8e),
0150 .driver_data = (kernel_ulong_t)0,
0151 },
0152 {
0153
0154 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0a80),
0155 .driver_data = (kernel_ulong_t)0,
0156 },
0157 {
0158
0159 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1a8e),
0160 .driver_data = (kernel_ulong_t)0,
0161 },
0162 {
0163
0164 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa2a6),
0165 .driver_data = (kernel_ulong_t)&intel_th_1x_multi_is_broken,
0166 },
0167 {
0168
0169 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x19e1),
0170 .driver_data = (kernel_ulong_t)0,
0171 },
0172 {
0173
0174 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa1a6),
0175 .driver_data = (kernel_ulong_t)0,
0176 },
0177 {
0178
0179 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa226),
0180 .driver_data = (kernel_ulong_t)0,
0181 },
0182 {
0183
0184 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x318e),
0185 .driver_data = (kernel_ulong_t)&intel_th_2x,
0186 },
0187 {
0188
0189 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa326),
0190 .driver_data = (kernel_ulong_t)&intel_th_2x,
0191 },
0192 {
0193
0194 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9da6),
0195 .driver_data = (kernel_ulong_t)&intel_th_2x,
0196 },
0197 {
0198
0199 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x18e1),
0200 .driver_data = (kernel_ulong_t)&intel_th_2x,
0201 },
0202 {
0203
0204 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x34a6),
0205 .driver_data = (kernel_ulong_t)&intel_th_2x,
0206 },
0207 {
0208
0209 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x02a6),
0210 .driver_data = (kernel_ulong_t)&intel_th_2x,
0211 },
0212 {
0213
0214 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x06a6),
0215 .driver_data = (kernel_ulong_t)&intel_th_2x,
0216 },
0217 {
0218
0219 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa3a6),
0220 .driver_data = (kernel_ulong_t)&intel_th_1x_multi_is_broken,
0221 },
0222 {
0223
0224 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x45c5),
0225 .driver_data = (kernel_ulong_t)&intel_th_2x,
0226 },
0227 {
0228
0229 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8a29),
0230 .driver_data = (kernel_ulong_t)&intel_th_2x,
0231 },
0232 {
0233
0234 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9a33),
0235 .driver_data = (kernel_ulong_t)&intel_th_2x,
0236 },
0237 {
0238
0239 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa0a6),
0240 .driver_data = (kernel_ulong_t)&intel_th_2x,
0241 },
0242 {
0243
0244 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x43a6),
0245 .driver_data = (kernel_ulong_t)&intel_th_2x,
0246 },
0247 {
0248
0249 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4da6),
0250 .driver_data = (kernel_ulong_t)&intel_th_2x,
0251 },
0252 {
0253
0254 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4e29),
0255 .driver_data = (kernel_ulong_t)&intel_th_2x,
0256 },
0257 {
0258
0259 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4529),
0260 .driver_data = (kernel_ulong_t)&intel_th_2x,
0261 },
0262 {
0263
0264 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4b26),
0265 .driver_data = (kernel_ulong_t)&intel_th_2x,
0266 },
0267 {
0268
0269 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1bcc),
0270 .driver_data = (kernel_ulong_t)&intel_th_2x,
0271 },
0272 {
0273
0274 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7aa6),
0275 .driver_data = (kernel_ulong_t)&intel_th_2x,
0276 },
0277 {
0278
0279 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x51a6),
0280 .driver_data = (kernel_ulong_t)&intel_th_2x,
0281 },
0282 {
0283
0284 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x54a6),
0285 .driver_data = (kernel_ulong_t)&intel_th_2x,
0286 },
0287 {
0288
0289 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7e24),
0290 .driver_data = (kernel_ulong_t)&intel_th_2x,
0291 },
0292 {
0293
0294 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7a26),
0295 .driver_data = (kernel_ulong_t)&intel_th_2x,
0296 },
0297 {
0298
0299 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa76f),
0300 .driver_data = (kernel_ulong_t)&intel_th_2x,
0301 },
0302 {
0303
0304 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x466f),
0305 .driver_data = (kernel_ulong_t)&intel_th_2x,
0306 },
0307 {
0308
0309 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4c19),
0310 .driver_data = (kernel_ulong_t)&intel_th_2x,
0311 },
0312 { 0 },
0313 };
0314
0315 MODULE_DEVICE_TABLE(pci, intel_th_pci_id_table);
0316
0317 static struct pci_driver intel_th_pci_driver = {
0318 .name = DRIVER_NAME,
0319 .id_table = intel_th_pci_id_table,
0320 .probe = intel_th_pci_probe,
0321 .remove = intel_th_pci_remove,
0322 };
0323
0324 module_pci_driver(intel_th_pci_driver);
0325
0326 MODULE_LICENSE("GPL v2");
0327 MODULE_DESCRIPTION("Intel(R) Trace Hub PCI controller driver");
0328 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@intel.com>");