1 /* 2 * Intel(R) Trace Hub pci driver 3 * 4 * Copyright (C) 2014-2015 Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 */ 15 16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 17 18 #include <linux/types.h> 19 #include <linux/module.h> 20 #include <linux/device.h> 21 #include <linux/sysfs.h> 22 #include <linux/pci.h> 23 24 #include "intel_th.h" 25 26 #define DRIVER_NAME "intel_th_pci" 27 28 #define BAR_MASK (BIT(TH_MMIO_CONFIG) | BIT(TH_MMIO_SW)) 29 30 #define PCI_REG_NPKDSC 0x80 31 #define NPKDSC_TSACT BIT(5) 32 33 static int intel_th_pci_activate(struct intel_th *th) 34 { 35 struct pci_dev *pdev = to_pci_dev(th->dev); 36 u32 npkdsc; 37 int err; 38 39 if (!INTEL_TH_CAP(th, tscu_enable)) 40 return 0; 41 42 err = pci_read_config_dword(pdev, PCI_REG_NPKDSC, &npkdsc); 43 if (!err) { 44 npkdsc |= NPKDSC_TSACT; 45 err = pci_write_config_dword(pdev, PCI_REG_NPKDSC, npkdsc); 46 } 47 48 if (err) 49 dev_err(&pdev->dev, "failed to read NPKDSC register\n"); 50 51 return err; 52 } 53 54 static void intel_th_pci_deactivate(struct intel_th *th) 55 { 56 struct pci_dev *pdev = to_pci_dev(th->dev); 57 u32 npkdsc; 58 int err; 59 60 if (!INTEL_TH_CAP(th, tscu_enable)) 61 return; 62 63 err = pci_read_config_dword(pdev, PCI_REG_NPKDSC, &npkdsc); 64 if (!err) { 65 npkdsc |= NPKDSC_TSACT; 66 err = pci_write_config_dword(pdev, PCI_REG_NPKDSC, npkdsc); 67 } 68 69 if (err) 70 dev_err(&pdev->dev, "failed to read NPKDSC register\n"); 71 } 72 73 static int intel_th_pci_probe(struct pci_dev *pdev, 74 const struct pci_device_id *id) 75 { 76 struct intel_th_drvdata *drvdata = (void *)id->driver_data; 77 struct intel_th *th; 78 int err; 79 80 err = pcim_enable_device(pdev); 81 if (err) 82 return err; 83 84 err = pcim_iomap_regions_request_all(pdev, BAR_MASK, DRIVER_NAME); 85 if (err) 86 return err; 87 88 th = intel_th_alloc(&pdev->dev, drvdata, pdev->resource, 89 DEVICE_COUNT_RESOURCE, pdev->irq); 90 if (IS_ERR(th)) 91 return PTR_ERR(th); 92 93 th->activate = intel_th_pci_activate; 94 th->deactivate = intel_th_pci_deactivate; 95 96 pci_set_master(pdev); 97 98 return 0; 99 } 100 101 static void intel_th_pci_remove(struct pci_dev *pdev) 102 { 103 struct intel_th *th = pci_get_drvdata(pdev); 104 105 intel_th_free(th); 106 } 107 108 static const struct intel_th_drvdata intel_th_2x = { 109 .tscu_enable = 1, 110 }; 111 112 static const struct pci_device_id intel_th_pci_id_table[] = { 113 { 114 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9d26), 115 .driver_data = (kernel_ulong_t)0, 116 }, 117 { 118 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa126), 119 .driver_data = (kernel_ulong_t)0, 120 }, 121 { 122 /* Apollo Lake */ 123 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a8e), 124 .driver_data = (kernel_ulong_t)0, 125 }, 126 { 127 /* Broxton */ 128 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0a80), 129 .driver_data = (kernel_ulong_t)0, 130 }, 131 { 132 /* Broxton B-step */ 133 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1a8e), 134 .driver_data = (kernel_ulong_t)0, 135 }, 136 { 137 /* Kaby Lake PCH-H */ 138 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa2a6), 139 .driver_data = (kernel_ulong_t)0, 140 }, 141 { 142 /* Denverton */ 143 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x19e1), 144 .driver_data = (kernel_ulong_t)0, 145 }, 146 { 147 /* Lewisburg PCH */ 148 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa1a6), 149 .driver_data = (kernel_ulong_t)0, 150 }, 151 { 152 /* Gemini Lake */ 153 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x318e), 154 .driver_data = (kernel_ulong_t)&intel_th_2x, 155 }, 156 { 157 /* Cannon Lake H */ 158 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa326), 159 .driver_data = (kernel_ulong_t)&intel_th_2x, 160 }, 161 { 162 /* Cannon Lake LP */ 163 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9da6), 164 .driver_data = (kernel_ulong_t)&intel_th_2x, 165 }, 166 { 167 /* Cedar Fork PCH */ 168 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x18e1), 169 .driver_data = (kernel_ulong_t)&intel_th_2x, 170 }, 171 { 0 }, 172 }; 173 174 MODULE_DEVICE_TABLE(pci, intel_th_pci_id_table); 175 176 static struct pci_driver intel_th_pci_driver = { 177 .name = DRIVER_NAME, 178 .id_table = intel_th_pci_id_table, 179 .probe = intel_th_pci_probe, 180 .remove = intel_th_pci_remove, 181 }; 182 183 module_pci_driver(intel_th_pci_driver); 184 185 MODULE_LICENSE("GPL v2"); 186 MODULE_DESCRIPTION("Intel(R) Trace Hub PCI controller driver"); 187 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@intel.com>"); 188