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_2x = { 124 .tscu_enable = 1, 125 .has_mintctl = 1, 126 }; 127 128 static const struct pci_device_id intel_th_pci_id_table[] = { 129 { 130 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9d26), 131 .driver_data = (kernel_ulong_t)0, 132 }, 133 { 134 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa126), 135 .driver_data = (kernel_ulong_t)0, 136 }, 137 { 138 /* Apollo Lake */ 139 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a8e), 140 .driver_data = (kernel_ulong_t)0, 141 }, 142 { 143 /* Broxton */ 144 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0a80), 145 .driver_data = (kernel_ulong_t)0, 146 }, 147 { 148 /* Broxton B-step */ 149 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1a8e), 150 .driver_data = (kernel_ulong_t)0, 151 }, 152 { 153 /* Kaby Lake PCH-H */ 154 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa2a6), 155 .driver_data = (kernel_ulong_t)0, 156 }, 157 { 158 /* Denverton */ 159 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x19e1), 160 .driver_data = (kernel_ulong_t)0, 161 }, 162 { 163 /* Lewisburg PCH */ 164 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa1a6), 165 .driver_data = (kernel_ulong_t)0, 166 }, 167 { 168 /* Gemini Lake */ 169 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x318e), 170 .driver_data = (kernel_ulong_t)&intel_th_2x, 171 }, 172 { 173 /* Cannon Lake H */ 174 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa326), 175 .driver_data = (kernel_ulong_t)&intel_th_2x, 176 }, 177 { 178 /* Cannon Lake LP */ 179 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9da6), 180 .driver_data = (kernel_ulong_t)&intel_th_2x, 181 }, 182 { 183 /* Cedar Fork PCH */ 184 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x18e1), 185 .driver_data = (kernel_ulong_t)&intel_th_2x, 186 }, 187 { 188 /* Ice Lake PCH */ 189 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x34a6), 190 .driver_data = (kernel_ulong_t)&intel_th_2x, 191 }, 192 { 193 /* Comet Lake */ 194 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x02a6), 195 .driver_data = (kernel_ulong_t)&intel_th_2x, 196 }, 197 { 0 }, 198 }; 199 200 MODULE_DEVICE_TABLE(pci, intel_th_pci_id_table); 201 202 static struct pci_driver intel_th_pci_driver = { 203 .name = DRIVER_NAME, 204 .id_table = intel_th_pci_id_table, 205 .probe = intel_th_pci_probe, 206 .remove = intel_th_pci_remove, 207 }; 208 209 module_pci_driver(intel_th_pci_driver); 210 211 MODULE_LICENSE("GPL v2"); 212 MODULE_DESCRIPTION("Intel(R) Trace Hub PCI controller driver"); 213 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@intel.com>"); 214