150352fa7SAlexander Shishkin // SPDX-License-Identifier: GPL-2.0 22b0b16d3SAlexander Shishkin /* 32b0b16d3SAlexander Shishkin * Intel(R) Trace Hub pci driver 42b0b16d3SAlexander Shishkin * 52b0b16d3SAlexander Shishkin * Copyright (C) 2014-2015 Intel Corporation. 62b0b16d3SAlexander Shishkin */ 72b0b16d3SAlexander Shishkin 82b0b16d3SAlexander Shishkin #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 92b0b16d3SAlexander Shishkin 102b0b16d3SAlexander Shishkin #include <linux/types.h> 112b0b16d3SAlexander Shishkin #include <linux/module.h> 122b0b16d3SAlexander Shishkin #include <linux/device.h> 132b0b16d3SAlexander Shishkin #include <linux/sysfs.h> 142b0b16d3SAlexander Shishkin #include <linux/pci.h> 152b0b16d3SAlexander Shishkin 162b0b16d3SAlexander Shishkin #include "intel_th.h" 172b0b16d3SAlexander Shishkin 182b0b16d3SAlexander Shishkin #define DRIVER_NAME "intel_th_pci" 192b0b16d3SAlexander Shishkin 202b0b16d3SAlexander Shishkin #define BAR_MASK (BIT(TH_MMIO_CONFIG) | BIT(TH_MMIO_SW)) 212b0b16d3SAlexander Shishkin 22a0e7df33SAlexander Shishkin #define PCI_REG_NPKDSC 0x80 23a0e7df33SAlexander Shishkin #define NPKDSC_TSACT BIT(5) 24a0e7df33SAlexander Shishkin 25a0e7df33SAlexander Shishkin static int intel_th_pci_activate(struct intel_th *th) 26a0e7df33SAlexander Shishkin { 27a0e7df33SAlexander Shishkin struct pci_dev *pdev = to_pci_dev(th->dev); 28a0e7df33SAlexander Shishkin u32 npkdsc; 29a0e7df33SAlexander Shishkin int err; 30a0e7df33SAlexander Shishkin 31a0e7df33SAlexander Shishkin if (!INTEL_TH_CAP(th, tscu_enable)) 32a0e7df33SAlexander Shishkin return 0; 33a0e7df33SAlexander Shishkin 34a0e7df33SAlexander Shishkin err = pci_read_config_dword(pdev, PCI_REG_NPKDSC, &npkdsc); 35a0e7df33SAlexander Shishkin if (!err) { 36a0e7df33SAlexander Shishkin npkdsc |= NPKDSC_TSACT; 37a0e7df33SAlexander Shishkin err = pci_write_config_dword(pdev, PCI_REG_NPKDSC, npkdsc); 38a0e7df33SAlexander Shishkin } 39a0e7df33SAlexander Shishkin 40a0e7df33SAlexander Shishkin if (err) 41a0e7df33SAlexander Shishkin dev_err(&pdev->dev, "failed to read NPKDSC register\n"); 42a0e7df33SAlexander Shishkin 43a0e7df33SAlexander Shishkin return err; 44a0e7df33SAlexander Shishkin } 45a0e7df33SAlexander Shishkin 46a0e7df33SAlexander Shishkin static void intel_th_pci_deactivate(struct intel_th *th) 47a0e7df33SAlexander Shishkin { 48a0e7df33SAlexander Shishkin struct pci_dev *pdev = to_pci_dev(th->dev); 49a0e7df33SAlexander Shishkin u32 npkdsc; 50a0e7df33SAlexander Shishkin int err; 51a0e7df33SAlexander Shishkin 52a0e7df33SAlexander Shishkin if (!INTEL_TH_CAP(th, tscu_enable)) 53a0e7df33SAlexander Shishkin return; 54a0e7df33SAlexander Shishkin 55a0e7df33SAlexander Shishkin err = pci_read_config_dword(pdev, PCI_REG_NPKDSC, &npkdsc); 56a0e7df33SAlexander Shishkin if (!err) { 57a0e7df33SAlexander Shishkin npkdsc |= NPKDSC_TSACT; 58a0e7df33SAlexander Shishkin err = pci_write_config_dword(pdev, PCI_REG_NPKDSC, npkdsc); 59a0e7df33SAlexander Shishkin } 60a0e7df33SAlexander Shishkin 61a0e7df33SAlexander Shishkin if (err) 62a0e7df33SAlexander Shishkin dev_err(&pdev->dev, "failed to read NPKDSC register\n"); 63a0e7df33SAlexander Shishkin } 64a0e7df33SAlexander Shishkin 652b0b16d3SAlexander Shishkin static int intel_th_pci_probe(struct pci_dev *pdev, 662b0b16d3SAlexander Shishkin const struct pci_device_id *id) 672b0b16d3SAlexander Shishkin { 683321371bSAlexander Shishkin struct intel_th_drvdata *drvdata = (void *)id->driver_data; 692b0b16d3SAlexander Shishkin struct intel_th *th; 702b0b16d3SAlexander Shishkin int err; 712b0b16d3SAlexander Shishkin 722b0b16d3SAlexander Shishkin err = pcim_enable_device(pdev); 732b0b16d3SAlexander Shishkin if (err) 742b0b16d3SAlexander Shishkin return err; 752b0b16d3SAlexander Shishkin 762b0b16d3SAlexander Shishkin err = pcim_iomap_regions_request_all(pdev, BAR_MASK, DRIVER_NAME); 772b0b16d3SAlexander Shishkin if (err) 782b0b16d3SAlexander Shishkin return err; 792b0b16d3SAlexander Shishkin 803321371bSAlexander Shishkin th = intel_th_alloc(&pdev->dev, drvdata, pdev->resource, 812b0b16d3SAlexander Shishkin DEVICE_COUNT_RESOURCE, pdev->irq); 822b0b16d3SAlexander Shishkin if (IS_ERR(th)) 832b0b16d3SAlexander Shishkin return PTR_ERR(th); 842b0b16d3SAlexander Shishkin 85a0e7df33SAlexander Shishkin th->activate = intel_th_pci_activate; 86a0e7df33SAlexander Shishkin th->deactivate = intel_th_pci_deactivate; 87a0e7df33SAlexander Shishkin 88e9b2b3e7SAlexander Shishkin pci_set_master(pdev); 89e9b2b3e7SAlexander Shishkin 902b0b16d3SAlexander Shishkin return 0; 912b0b16d3SAlexander Shishkin } 922b0b16d3SAlexander Shishkin 932b0b16d3SAlexander Shishkin static void intel_th_pci_remove(struct pci_dev *pdev) 942b0b16d3SAlexander Shishkin { 952b0b16d3SAlexander Shishkin struct intel_th *th = pci_get_drvdata(pdev); 962b0b16d3SAlexander Shishkin 972b0b16d3SAlexander Shishkin intel_th_free(th); 982b0b16d3SAlexander Shishkin } 992b0b16d3SAlexander Shishkin 100a0e7df33SAlexander Shishkin static const struct intel_th_drvdata intel_th_2x = { 101a0e7df33SAlexander Shishkin .tscu_enable = 1, 102a0e7df33SAlexander Shishkin }; 103a0e7df33SAlexander Shishkin 1042b0b16d3SAlexander Shishkin static const struct pci_device_id intel_th_pci_id_table[] = { 1052b0b16d3SAlexander Shishkin { 1062b0b16d3SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9d26), 1072b0b16d3SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 1082b0b16d3SAlexander Shishkin }, 1092b0b16d3SAlexander Shishkin { 1102b0b16d3SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa126), 1112b0b16d3SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 1122b0b16d3SAlexander Shishkin }, 1136396b912SAlexander Shishkin { 1146396b912SAlexander Shishkin /* Apollo Lake */ 1156396b912SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a8e), 1166396b912SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 1176396b912SAlexander Shishkin }, 1183f040887SAlexander Shishkin { 1193f040887SAlexander Shishkin /* Broxton */ 1203f040887SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0a80), 1213f040887SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 1223f040887SAlexander Shishkin }, 123aaa3ca82SAlexander Shishkin { 124aaa3ca82SAlexander Shishkin /* Broxton B-step */ 125aaa3ca82SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1a8e), 126aaa3ca82SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 127aaa3ca82SAlexander Shishkin }, 1287a1a47ceSAlexander Shishkin { 1297a1a47ceSAlexander Shishkin /* Kaby Lake PCH-H */ 1307a1a47ceSAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa2a6), 1317a1a47ceSAlexander Shishkin .driver_data = (kernel_ulong_t)0, 1327a1a47ceSAlexander Shishkin }, 1335118ccd3SAlexander Shishkin { 1345118ccd3SAlexander Shishkin /* Denverton */ 1355118ccd3SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x19e1), 1365118ccd3SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 1375118ccd3SAlexander Shishkin }, 138340837f9SAlexander Shishkin { 13924600840SAlexander Shishkin /* Lewisburg PCH */ 14024600840SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa1a6), 14124600840SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 14224600840SAlexander Shishkin }, 14324600840SAlexander Shishkin { 144340837f9SAlexander Shishkin /* Gemini Lake */ 145340837f9SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x318e), 146a0e7df33SAlexander Shishkin .driver_data = (kernel_ulong_t)&intel_th_2x, 147340837f9SAlexander Shishkin }, 14884331e13SAlexander Shishkin { 14984331e13SAlexander Shishkin /* Cannon Lake H */ 15084331e13SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa326), 151a0e7df33SAlexander Shishkin .driver_data = (kernel_ulong_t)&intel_th_2x, 15284331e13SAlexander Shishkin }, 153efb3669eSAlexander Shishkin { 154efb3669eSAlexander Shishkin /* Cannon Lake LP */ 155efb3669eSAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9da6), 156a0e7df33SAlexander Shishkin .driver_data = (kernel_ulong_t)&intel_th_2x, 157efb3669eSAlexander Shishkin }, 158920ce7c3SAlexander Shishkin { 159920ce7c3SAlexander Shishkin /* Cedar Fork PCH */ 160920ce7c3SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x18e1), 161920ce7c3SAlexander Shishkin .driver_data = (kernel_ulong_t)&intel_th_2x, 162920ce7c3SAlexander Shishkin }, 163*59d08d00SAlexander Shishkin { 164*59d08d00SAlexander Shishkin /* Ice Lake PCH */ 165*59d08d00SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x34a6), 166*59d08d00SAlexander Shishkin .driver_data = (kernel_ulong_t)&intel_th_2x, 167*59d08d00SAlexander Shishkin }, 1682b0b16d3SAlexander Shishkin { 0 }, 1692b0b16d3SAlexander Shishkin }; 1702b0b16d3SAlexander Shishkin 1712b0b16d3SAlexander Shishkin MODULE_DEVICE_TABLE(pci, intel_th_pci_id_table); 1722b0b16d3SAlexander Shishkin 1732b0b16d3SAlexander Shishkin static struct pci_driver intel_th_pci_driver = { 1742b0b16d3SAlexander Shishkin .name = DRIVER_NAME, 1752b0b16d3SAlexander Shishkin .id_table = intel_th_pci_id_table, 1762b0b16d3SAlexander Shishkin .probe = intel_th_pci_probe, 1772b0b16d3SAlexander Shishkin .remove = intel_th_pci_remove, 1782b0b16d3SAlexander Shishkin }; 1792b0b16d3SAlexander Shishkin 1802b0b16d3SAlexander Shishkin module_pci_driver(intel_th_pci_driver); 1812b0b16d3SAlexander Shishkin 1822b0b16d3SAlexander Shishkin MODULE_LICENSE("GPL v2"); 1832b0b16d3SAlexander Shishkin MODULE_DESCRIPTION("Intel(R) Trace Hub PCI controller driver"); 1842b0b16d3SAlexander Shishkin MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@intel.com>"); 185