12b0b16d3SAlexander Shishkin /* 22b0b16d3SAlexander Shishkin * Intel(R) Trace Hub pci driver 32b0b16d3SAlexander Shishkin * 42b0b16d3SAlexander Shishkin * Copyright (C) 2014-2015 Intel Corporation. 52b0b16d3SAlexander Shishkin * 62b0b16d3SAlexander Shishkin * This program is free software; you can redistribute it and/or modify it 72b0b16d3SAlexander Shishkin * under the terms and conditions of the GNU General Public License, 82b0b16d3SAlexander Shishkin * version 2, as published by the Free Software Foundation. 92b0b16d3SAlexander Shishkin * 102b0b16d3SAlexander Shishkin * This program is distributed in the hope it will be useful, but WITHOUT 112b0b16d3SAlexander Shishkin * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 122b0b16d3SAlexander Shishkin * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 132b0b16d3SAlexander Shishkin * more details. 142b0b16d3SAlexander Shishkin */ 152b0b16d3SAlexander Shishkin 162b0b16d3SAlexander Shishkin #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 172b0b16d3SAlexander Shishkin 182b0b16d3SAlexander Shishkin #include <linux/types.h> 192b0b16d3SAlexander Shishkin #include <linux/module.h> 202b0b16d3SAlexander Shishkin #include <linux/device.h> 212b0b16d3SAlexander Shishkin #include <linux/sysfs.h> 222b0b16d3SAlexander Shishkin #include <linux/pci.h> 232b0b16d3SAlexander Shishkin 242b0b16d3SAlexander Shishkin #include "intel_th.h" 252b0b16d3SAlexander Shishkin 262b0b16d3SAlexander Shishkin #define DRIVER_NAME "intel_th_pci" 272b0b16d3SAlexander Shishkin 282b0b16d3SAlexander Shishkin #define BAR_MASK (BIT(TH_MMIO_CONFIG) | BIT(TH_MMIO_SW)) 292b0b16d3SAlexander Shishkin 30*a0e7df33SAlexander Shishkin #define PCI_REG_NPKDSC 0x80 31*a0e7df33SAlexander Shishkin #define NPKDSC_TSACT BIT(5) 32*a0e7df33SAlexander Shishkin 33*a0e7df33SAlexander Shishkin static int intel_th_pci_activate(struct intel_th *th) 34*a0e7df33SAlexander Shishkin { 35*a0e7df33SAlexander Shishkin struct pci_dev *pdev = to_pci_dev(th->dev); 36*a0e7df33SAlexander Shishkin u32 npkdsc; 37*a0e7df33SAlexander Shishkin int err; 38*a0e7df33SAlexander Shishkin 39*a0e7df33SAlexander Shishkin if (!INTEL_TH_CAP(th, tscu_enable)) 40*a0e7df33SAlexander Shishkin return 0; 41*a0e7df33SAlexander Shishkin 42*a0e7df33SAlexander Shishkin err = pci_read_config_dword(pdev, PCI_REG_NPKDSC, &npkdsc); 43*a0e7df33SAlexander Shishkin if (!err) { 44*a0e7df33SAlexander Shishkin npkdsc |= NPKDSC_TSACT; 45*a0e7df33SAlexander Shishkin err = pci_write_config_dword(pdev, PCI_REG_NPKDSC, npkdsc); 46*a0e7df33SAlexander Shishkin } 47*a0e7df33SAlexander Shishkin 48*a0e7df33SAlexander Shishkin if (err) 49*a0e7df33SAlexander Shishkin dev_err(&pdev->dev, "failed to read NPKDSC register\n"); 50*a0e7df33SAlexander Shishkin 51*a0e7df33SAlexander Shishkin return err; 52*a0e7df33SAlexander Shishkin } 53*a0e7df33SAlexander Shishkin 54*a0e7df33SAlexander Shishkin static void intel_th_pci_deactivate(struct intel_th *th) 55*a0e7df33SAlexander Shishkin { 56*a0e7df33SAlexander Shishkin struct pci_dev *pdev = to_pci_dev(th->dev); 57*a0e7df33SAlexander Shishkin u32 npkdsc; 58*a0e7df33SAlexander Shishkin int err; 59*a0e7df33SAlexander Shishkin 60*a0e7df33SAlexander Shishkin if (!INTEL_TH_CAP(th, tscu_enable)) 61*a0e7df33SAlexander Shishkin return; 62*a0e7df33SAlexander Shishkin 63*a0e7df33SAlexander Shishkin err = pci_read_config_dword(pdev, PCI_REG_NPKDSC, &npkdsc); 64*a0e7df33SAlexander Shishkin if (!err) { 65*a0e7df33SAlexander Shishkin npkdsc |= NPKDSC_TSACT; 66*a0e7df33SAlexander Shishkin err = pci_write_config_dword(pdev, PCI_REG_NPKDSC, npkdsc); 67*a0e7df33SAlexander Shishkin } 68*a0e7df33SAlexander Shishkin 69*a0e7df33SAlexander Shishkin if (err) 70*a0e7df33SAlexander Shishkin dev_err(&pdev->dev, "failed to read NPKDSC register\n"); 71*a0e7df33SAlexander Shishkin } 72*a0e7df33SAlexander Shishkin 732b0b16d3SAlexander Shishkin static int intel_th_pci_probe(struct pci_dev *pdev, 742b0b16d3SAlexander Shishkin const struct pci_device_id *id) 752b0b16d3SAlexander Shishkin { 763321371bSAlexander Shishkin struct intel_th_drvdata *drvdata = (void *)id->driver_data; 772b0b16d3SAlexander Shishkin struct intel_th *th; 782b0b16d3SAlexander Shishkin int err; 792b0b16d3SAlexander Shishkin 802b0b16d3SAlexander Shishkin err = pcim_enable_device(pdev); 812b0b16d3SAlexander Shishkin if (err) 822b0b16d3SAlexander Shishkin return err; 832b0b16d3SAlexander Shishkin 842b0b16d3SAlexander Shishkin err = pcim_iomap_regions_request_all(pdev, BAR_MASK, DRIVER_NAME); 852b0b16d3SAlexander Shishkin if (err) 862b0b16d3SAlexander Shishkin return err; 872b0b16d3SAlexander Shishkin 883321371bSAlexander Shishkin th = intel_th_alloc(&pdev->dev, drvdata, pdev->resource, 892b0b16d3SAlexander Shishkin DEVICE_COUNT_RESOURCE, pdev->irq); 902b0b16d3SAlexander Shishkin if (IS_ERR(th)) 912b0b16d3SAlexander Shishkin return PTR_ERR(th); 922b0b16d3SAlexander Shishkin 93*a0e7df33SAlexander Shishkin th->activate = intel_th_pci_activate; 94*a0e7df33SAlexander Shishkin th->deactivate = intel_th_pci_deactivate; 95*a0e7df33SAlexander Shishkin 96e9b2b3e7SAlexander Shishkin pci_set_master(pdev); 97e9b2b3e7SAlexander Shishkin 982b0b16d3SAlexander Shishkin return 0; 992b0b16d3SAlexander Shishkin } 1002b0b16d3SAlexander Shishkin 1012b0b16d3SAlexander Shishkin static void intel_th_pci_remove(struct pci_dev *pdev) 1022b0b16d3SAlexander Shishkin { 1032b0b16d3SAlexander Shishkin struct intel_th *th = pci_get_drvdata(pdev); 1042b0b16d3SAlexander Shishkin 1052b0b16d3SAlexander Shishkin intel_th_free(th); 1062b0b16d3SAlexander Shishkin } 1072b0b16d3SAlexander Shishkin 108*a0e7df33SAlexander Shishkin static const struct intel_th_drvdata intel_th_2x = { 109*a0e7df33SAlexander Shishkin .tscu_enable = 1, 110*a0e7df33SAlexander Shishkin }; 111*a0e7df33SAlexander Shishkin 1122b0b16d3SAlexander Shishkin static const struct pci_device_id intel_th_pci_id_table[] = { 1132b0b16d3SAlexander Shishkin { 1142b0b16d3SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9d26), 1152b0b16d3SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 1162b0b16d3SAlexander Shishkin }, 1172b0b16d3SAlexander Shishkin { 1182b0b16d3SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa126), 1192b0b16d3SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 1202b0b16d3SAlexander Shishkin }, 1216396b912SAlexander Shishkin { 1226396b912SAlexander Shishkin /* Apollo Lake */ 1236396b912SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a8e), 1246396b912SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 1256396b912SAlexander Shishkin }, 1263f040887SAlexander Shishkin { 1273f040887SAlexander Shishkin /* Broxton */ 1283f040887SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0a80), 1293f040887SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 1303f040887SAlexander Shishkin }, 131aaa3ca82SAlexander Shishkin { 132aaa3ca82SAlexander Shishkin /* Broxton B-step */ 133aaa3ca82SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1a8e), 134aaa3ca82SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 135aaa3ca82SAlexander Shishkin }, 1367a1a47ceSAlexander Shishkin { 1377a1a47ceSAlexander Shishkin /* Kaby Lake PCH-H */ 1387a1a47ceSAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa2a6), 1397a1a47ceSAlexander Shishkin .driver_data = (kernel_ulong_t)0, 1407a1a47ceSAlexander Shishkin }, 1415118ccd3SAlexander Shishkin { 1425118ccd3SAlexander Shishkin /* Denverton */ 1435118ccd3SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x19e1), 1445118ccd3SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 1455118ccd3SAlexander Shishkin }, 146340837f9SAlexander Shishkin { 147340837f9SAlexander Shishkin /* Gemini Lake */ 148340837f9SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x318e), 149*a0e7df33SAlexander Shishkin .driver_data = (kernel_ulong_t)&intel_th_2x, 150340837f9SAlexander Shishkin }, 15184331e13SAlexander Shishkin { 15284331e13SAlexander Shishkin /* Cannon Lake H */ 15384331e13SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa326), 154*a0e7df33SAlexander Shishkin .driver_data = (kernel_ulong_t)&intel_th_2x, 15584331e13SAlexander Shishkin }, 156efb3669eSAlexander Shishkin { 157efb3669eSAlexander Shishkin /* Cannon Lake LP */ 158efb3669eSAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9da6), 159*a0e7df33SAlexander Shishkin .driver_data = (kernel_ulong_t)&intel_th_2x, 160efb3669eSAlexander Shishkin }, 1612b0b16d3SAlexander Shishkin { 0 }, 1622b0b16d3SAlexander Shishkin }; 1632b0b16d3SAlexander Shishkin 1642b0b16d3SAlexander Shishkin MODULE_DEVICE_TABLE(pci, intel_th_pci_id_table); 1652b0b16d3SAlexander Shishkin 1662b0b16d3SAlexander Shishkin static struct pci_driver intel_th_pci_driver = { 1672b0b16d3SAlexander Shishkin .name = DRIVER_NAME, 1682b0b16d3SAlexander Shishkin .id_table = intel_th_pci_id_table, 1692b0b16d3SAlexander Shishkin .probe = intel_th_pci_probe, 1702b0b16d3SAlexander Shishkin .remove = intel_th_pci_remove, 1712b0b16d3SAlexander Shishkin }; 1722b0b16d3SAlexander Shishkin 1732b0b16d3SAlexander Shishkin module_pci_driver(intel_th_pci_driver); 1742b0b16d3SAlexander Shishkin 1752b0b16d3SAlexander Shishkin MODULE_LICENSE("GPL v2"); 1762b0b16d3SAlexander Shishkin MODULE_DESCRIPTION("Intel(R) Trace Hub PCI controller driver"); 1772b0b16d3SAlexander Shishkin MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@intel.com>"); 178