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 #include "pci_ids.h" 18 19 #define DRIVER_NAME "intel_th_pci" 20 21 enum { 22 TH_PCI_CONFIG_BAR = 0, 23 TH_PCI_STH_SW_BAR = 2, 24 TH_PCI_RTIT_BAR = 4, 25 }; 26 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_request_all_regions(pdev, DRIVER_NAME); 87 if (err) 88 return err; 89 90 if (!pcim_iomap(pdev, TH_PCI_CONFIG_BAR, 0)) 91 return -ENOMEM; 92 93 if (!pcim_iomap(pdev, TH_PCI_STH_SW_BAR, 0)) 94 return -ENOMEM; 95 96 if (pdev->resource[TH_PCI_RTIT_BAR].start) { 97 resource[TH_MMIO_RTIT] = pdev->resource[TH_PCI_RTIT_BAR]; 98 r++; 99 } 100 101 err = pci_alloc_irq_vectors(pdev, 1, 8, PCI_IRQ_ALL_TYPES); 102 if (err > 0) 103 for (i = 0; i < err; i++, r++) { 104 resource[r].flags = IORESOURCE_IRQ; 105 resource[r].start = pci_irq_vector(pdev, i); 106 } 107 108 th = intel_th_alloc(&pdev->dev, drvdata, resource, r); 109 if (IS_ERR(th)) { 110 err = PTR_ERR(th); 111 goto err_free_irq; 112 } 113 114 th->activate = intel_th_pci_activate; 115 th->deactivate = intel_th_pci_deactivate; 116 117 pci_set_master(pdev); 118 119 return 0; 120 121 err_free_irq: 122 pci_free_irq_vectors(pdev); 123 return err; 124 } 125 126 static void intel_th_pci_remove(struct pci_dev *pdev) 127 { 128 struct intel_th *th = pci_get_drvdata(pdev); 129 130 intel_th_free(th); 131 132 pci_free_irq_vectors(pdev); 133 } 134 135 static const struct intel_th_drvdata intel_th_1x_multi_is_broken = { 136 .multi_is_broken = 1, 137 }; 138 139 static const struct intel_th_drvdata intel_th_2x = { 140 .tscu_enable = 1, 141 .has_mintctl = 1, 142 }; 143 144 static const struct pci_device_id intel_th_pci_id_table[] = { 145 { PCI_DEVICE_DATA(INTEL, NPK_CML, &intel_th_2x) }, /* Comet Lake */ 146 { PCI_DEVICE_DATA(INTEL, NPK_CML_PCH, &intel_th_2x) }, /* Comet Lake PCH */ 147 { PCI_DEVICE_DATA(INTEL, NPK_GNR, &intel_th_2x) }, /* Granite Rapids */ 148 { PCI_DEVICE_DATA(INTEL, NPK_BXT, NULL) }, /* Broxton */ 149 { PCI_DEVICE_DATA(INTEL, NPK_CDF, &intel_th_2x) }, /* Cedar Fork PCH */ 150 { PCI_DEVICE_DATA(INTEL, NPK_DNV, NULL) }, /* Denverton */ 151 { PCI_DEVICE_DATA(INTEL, NPK_BXT_B, NULL) }, /* Broxton B-step */ 152 { PCI_DEVICE_DATA(INTEL, NPK_EBG, &intel_th_2x) }, /* Emmitsburg PCH */ 153 { PCI_DEVICE_DATA(INTEL, NPK_GLK, &intel_th_2x) }, /* Gemini Lake */ 154 { PCI_DEVICE_DATA(INTEL, NPK_GNR_SOC, &intel_th_2x) }, /* Granite Rapids SOC */ 155 { PCI_DEVICE_DATA(INTEL, NPK_SPR, &intel_th_2x) }, /* Sapphire Rapids SOC */ 156 { PCI_DEVICE_DATA(INTEL, NPK_ICL_PCH, &intel_th_2x) }, /* Ice Lake PCH */ 157 { PCI_DEVICE_DATA(INTEL, NPK_TGL_PCH_H, &intel_th_2x) }, /* Tiger Lake PCH-H */ 158 { PCI_DEVICE_DATA(INTEL, NPK_EHL_CPU, &intel_th_2x) }, /* Elkhart Lake CPU */ 159 { PCI_DEVICE_DATA(INTEL, NPK_ICL_NNPI, &intel_th_2x) }, /* Ice Lake NNPI */ 160 { PCI_DEVICE_DATA(INTEL, NPK_ADL_CPU, &intel_th_2x) }, /* Alder Lake CPU */ 161 { PCI_DEVICE_DATA(INTEL, NPK_EHL, &intel_th_2x) }, /* Elkhart Lake */ 162 { PCI_DEVICE_DATA(INTEL, NPK_RKL, &intel_th_2x) }, /* Rocket Lake CPU */ 163 { PCI_DEVICE_DATA(INTEL, NPK_JSL_PCH, &intel_th_2x) }, /* Jasper Lake PCH */ 164 { PCI_DEVICE_DATA(INTEL, NPK_JSL_CPU, &intel_th_2x) }, /* Jasper Lake CPU */ 165 { PCI_DEVICE_DATA(INTEL, NPK_ADL_P, &intel_th_2x) }, /* Alder Lake-P */ 166 { PCI_DEVICE_DATA(INTEL, NPK_ADL_M, &intel_th_2x) }, /* Alder Lake-M */ 167 { PCI_DEVICE_DATA(INTEL, NPK_APL, NULL) }, /* Apollo Lake */ 168 { PCI_DEVICE_DATA(INTEL, NPK_NVL_PCH, &intel_th_2x) }, /* Nova Lake-PCH */ 169 { PCI_DEVICE_DATA(INTEL, NPK_ARL, &intel_th_2x) }, /* Arrow Lake */ 170 { PCI_DEVICE_DATA(INTEL, NPK_RPL_S, &intel_th_2x) }, /* Raptor Lake-S */ 171 { PCI_DEVICE_DATA(INTEL, NPK_ADL, &intel_th_2x) }, /* Alder Lake */ 172 { PCI_DEVICE_DATA(INTEL, NPK_MTL_P, &intel_th_2x) }, /* Meteor Lake-P */ 173 { PCI_DEVICE_DATA(INTEL, NPK_MTL_S, &intel_th_2x) }, /* Meteor Lake-S */ 174 { PCI_DEVICE_DATA(INTEL, NPK_ICL_CPU, &intel_th_2x) }, /* Ice Lake CPU */ 175 { PCI_DEVICE_DATA(INTEL, NPK_TGL_CPU, &intel_th_2x) }, /* Tiger Lake CPU */ 176 { PCI_DEVICE_DATA(INTEL, NPK_0, NULL) }, 177 { PCI_DEVICE_DATA(INTEL, NPK_CNL_LP, &intel_th_2x) }, /* Cannon Lake LP */ 178 { PCI_DEVICE_DATA(INTEL, NPK_TGL_PCH, &intel_th_2x) }, /* Tiger Lake PCH */ 179 { PCI_DEVICE_DATA(INTEL, NPK_1, NULL) }, 180 { PCI_DEVICE_DATA(INTEL, NPK_LBG_PCH, NULL) }, /* Lewisburg PCH */ 181 { PCI_DEVICE_DATA(INTEL, NPK_LBG_PCH_2, NULL) }, /* Lewisburg PCH */ 182 { PCI_DEVICE_DATA(INTEL, NPK_KBL_PCH, &intel_th_1x_multi_is_broken) }, /* Kaby Lake PCH-H */ 183 { PCI_DEVICE_DATA(INTEL, NPK_CNL_H, &intel_th_2x) }, /* Cannon Lake H */ 184 { PCI_DEVICE_DATA(INTEL, NPK_CML_PCH_V, &intel_th_1x_multi_is_broken) }, /* Comet Lake PCH-V */ 185 { PCI_DEVICE_DATA(INTEL, NPK_RPL_S_CPU, &intel_th_2x) }, /* Raptor Lake-S CPU */ 186 { PCI_DEVICE_DATA(INTEL, NPK_LNL, &intel_th_2x) }, /* Lunar Lake */ 187 { PCI_DEVICE_DATA(INTEL, NPK_MTL_S_CPU, &intel_th_2x) }, /* Meteor Lake-S CPU */ 188 { PCI_DEVICE_DATA(INTEL, NPK_NVL_P, &intel_th_2x) }, /* Nova Lake-P */ 189 { PCI_DEVICE_DATA(INTEL, NPK_NVL_H, &intel_th_2x) }, /* Nova Lake-H */ 190 { PCI_DEVICE_DATA(INTEL, NPK_NVL_S, &intel_th_2x) }, /* Nova Lake-S */ 191 { PCI_DEVICE_DATA(INTEL, NPK_PTL_H, &intel_th_2x) }, /* Panther Lake-H */ 192 { PCI_DEVICE_DATA(INTEL, NPK_PTL_PU, &intel_th_2x) }, /* Panther Lake-P/U */ 193 { } 194 }; 195 196 MODULE_DEVICE_TABLE(pci, intel_th_pci_id_table); 197 198 static struct pci_driver intel_th_pci_driver = { 199 .name = DRIVER_NAME, 200 .id_table = intel_th_pci_id_table, 201 .probe = intel_th_pci_probe, 202 .remove = intel_th_pci_remove, 203 }; 204 205 module_pci_driver(intel_th_pci_driver); 206 207 MODULE_LICENSE("GPL v2"); 208 MODULE_DESCRIPTION("Intel(R) Trace Hub PCI controller driver"); 209 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@intel.com>"); 210