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 20db73a059SAlexander Shishkin enum { 21db73a059SAlexander Shishkin TH_PCI_CONFIG_BAR = 0, 22db73a059SAlexander Shishkin TH_PCI_STH_SW_BAR = 2, 23fc027f4cSAlexander Shishkin TH_PCI_RTIT_BAR = 4, 24db73a059SAlexander Shishkin }; 25db73a059SAlexander Shishkin 26db73a059SAlexander Shishkin #define BAR_MASK (BIT(TH_PCI_CONFIG_BAR) | BIT(TH_PCI_STH_SW_BAR)) 272b0b16d3SAlexander Shishkin 28a0e7df33SAlexander Shishkin #define PCI_REG_NPKDSC 0x80 29a0e7df33SAlexander Shishkin #define NPKDSC_TSACT BIT(5) 30a0e7df33SAlexander Shishkin 31a0e7df33SAlexander Shishkin static int intel_th_pci_activate(struct intel_th *th) 32a0e7df33SAlexander Shishkin { 33a0e7df33SAlexander Shishkin struct pci_dev *pdev = to_pci_dev(th->dev); 34a0e7df33SAlexander Shishkin u32 npkdsc; 35a0e7df33SAlexander Shishkin int err; 36a0e7df33SAlexander Shishkin 37a0e7df33SAlexander Shishkin if (!INTEL_TH_CAP(th, tscu_enable)) 38a0e7df33SAlexander Shishkin return 0; 39a0e7df33SAlexander Shishkin 40a0e7df33SAlexander Shishkin err = pci_read_config_dword(pdev, PCI_REG_NPKDSC, &npkdsc); 41a0e7df33SAlexander Shishkin if (!err) { 42a0e7df33SAlexander Shishkin npkdsc |= NPKDSC_TSACT; 43a0e7df33SAlexander Shishkin err = pci_write_config_dword(pdev, PCI_REG_NPKDSC, npkdsc); 44a0e7df33SAlexander Shishkin } 45a0e7df33SAlexander Shishkin 46a0e7df33SAlexander Shishkin if (err) 47a0e7df33SAlexander Shishkin dev_err(&pdev->dev, "failed to read NPKDSC register\n"); 48a0e7df33SAlexander Shishkin 49a0e7df33SAlexander Shishkin return err; 50a0e7df33SAlexander Shishkin } 51a0e7df33SAlexander Shishkin 52a0e7df33SAlexander Shishkin static void intel_th_pci_deactivate(struct intel_th *th) 53a0e7df33SAlexander Shishkin { 54a0e7df33SAlexander Shishkin struct pci_dev *pdev = to_pci_dev(th->dev); 55a0e7df33SAlexander Shishkin u32 npkdsc; 56a0e7df33SAlexander Shishkin int err; 57a0e7df33SAlexander Shishkin 58a0e7df33SAlexander Shishkin if (!INTEL_TH_CAP(th, tscu_enable)) 59a0e7df33SAlexander Shishkin return; 60a0e7df33SAlexander Shishkin 61a0e7df33SAlexander Shishkin err = pci_read_config_dword(pdev, PCI_REG_NPKDSC, &npkdsc); 62a0e7df33SAlexander Shishkin if (!err) { 63a0e7df33SAlexander Shishkin npkdsc |= NPKDSC_TSACT; 64a0e7df33SAlexander Shishkin err = pci_write_config_dword(pdev, PCI_REG_NPKDSC, npkdsc); 65a0e7df33SAlexander Shishkin } 66a0e7df33SAlexander Shishkin 67a0e7df33SAlexander Shishkin if (err) 68a0e7df33SAlexander Shishkin dev_err(&pdev->dev, "failed to read NPKDSC register\n"); 69a0e7df33SAlexander Shishkin } 70a0e7df33SAlexander Shishkin 712b0b16d3SAlexander Shishkin static int intel_th_pci_probe(struct pci_dev *pdev, 722b0b16d3SAlexander Shishkin const struct pci_device_id *id) 732b0b16d3SAlexander Shishkin { 743321371bSAlexander Shishkin struct intel_th_drvdata *drvdata = (void *)id->driver_data; 75*62a59302SAlexander Shishkin struct resource resource[TH_MMIO_END + 1] = { 76db73a059SAlexander Shishkin [TH_MMIO_CONFIG] = pdev->resource[TH_PCI_CONFIG_BAR], 77db73a059SAlexander Shishkin [TH_MMIO_SW] = pdev->resource[TH_PCI_STH_SW_BAR], 78db73a059SAlexander Shishkin }; 79fc027f4cSAlexander Shishkin int err, r = TH_MMIO_SW + 1; 802b0b16d3SAlexander Shishkin struct intel_th *th; 812b0b16d3SAlexander Shishkin 822b0b16d3SAlexander Shishkin err = pcim_enable_device(pdev); 832b0b16d3SAlexander Shishkin if (err) 842b0b16d3SAlexander Shishkin return err; 852b0b16d3SAlexander Shishkin 862b0b16d3SAlexander Shishkin err = pcim_iomap_regions_request_all(pdev, BAR_MASK, DRIVER_NAME); 872b0b16d3SAlexander Shishkin if (err) 882b0b16d3SAlexander Shishkin return err; 892b0b16d3SAlexander Shishkin 90fc027f4cSAlexander Shishkin if (pdev->resource[TH_PCI_RTIT_BAR].start) { 91fc027f4cSAlexander Shishkin resource[TH_MMIO_RTIT] = pdev->resource[TH_PCI_RTIT_BAR]; 92fc027f4cSAlexander Shishkin r++; 93fc027f4cSAlexander Shishkin } 94fc027f4cSAlexander Shishkin 95*62a59302SAlexander Shishkin if (pdev->irq > 0) { 96*62a59302SAlexander Shishkin resource[r].flags = IORESOURCE_IRQ; 97*62a59302SAlexander Shishkin resource[r++].start = pdev->irq; 98*62a59302SAlexander Shishkin } 99*62a59302SAlexander Shishkin 100*62a59302SAlexander Shishkin th = intel_th_alloc(&pdev->dev, drvdata, resource, r); 1012b0b16d3SAlexander Shishkin if (IS_ERR(th)) 1022b0b16d3SAlexander Shishkin return PTR_ERR(th); 1032b0b16d3SAlexander Shishkin 104a0e7df33SAlexander Shishkin th->activate = intel_th_pci_activate; 105a0e7df33SAlexander Shishkin th->deactivate = intel_th_pci_deactivate; 106a0e7df33SAlexander Shishkin 107e9b2b3e7SAlexander Shishkin pci_set_master(pdev); 108e9b2b3e7SAlexander Shishkin 1092b0b16d3SAlexander Shishkin return 0; 1102b0b16d3SAlexander Shishkin } 1112b0b16d3SAlexander Shishkin 1122b0b16d3SAlexander Shishkin static void intel_th_pci_remove(struct pci_dev *pdev) 1132b0b16d3SAlexander Shishkin { 1142b0b16d3SAlexander Shishkin struct intel_th *th = pci_get_drvdata(pdev); 1152b0b16d3SAlexander Shishkin 1162b0b16d3SAlexander Shishkin intel_th_free(th); 1172b0b16d3SAlexander Shishkin } 1182b0b16d3SAlexander Shishkin 119a0e7df33SAlexander Shishkin static const struct intel_th_drvdata intel_th_2x = { 120a0e7df33SAlexander Shishkin .tscu_enable = 1, 121a0e7df33SAlexander Shishkin }; 122a0e7df33SAlexander Shishkin 1232b0b16d3SAlexander Shishkin static const struct pci_device_id intel_th_pci_id_table[] = { 1242b0b16d3SAlexander Shishkin { 1252b0b16d3SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9d26), 1262b0b16d3SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 1272b0b16d3SAlexander Shishkin }, 1282b0b16d3SAlexander Shishkin { 1292b0b16d3SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa126), 1302b0b16d3SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 1312b0b16d3SAlexander Shishkin }, 1326396b912SAlexander Shishkin { 1336396b912SAlexander Shishkin /* Apollo Lake */ 1346396b912SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a8e), 1356396b912SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 1366396b912SAlexander Shishkin }, 1373f040887SAlexander Shishkin { 1383f040887SAlexander Shishkin /* Broxton */ 1393f040887SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0a80), 1403f040887SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 1413f040887SAlexander Shishkin }, 142aaa3ca82SAlexander Shishkin { 143aaa3ca82SAlexander Shishkin /* Broxton B-step */ 144aaa3ca82SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1a8e), 145aaa3ca82SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 146aaa3ca82SAlexander Shishkin }, 1477a1a47ceSAlexander Shishkin { 1487a1a47ceSAlexander Shishkin /* Kaby Lake PCH-H */ 1497a1a47ceSAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa2a6), 1507a1a47ceSAlexander Shishkin .driver_data = (kernel_ulong_t)0, 1517a1a47ceSAlexander Shishkin }, 1525118ccd3SAlexander Shishkin { 1535118ccd3SAlexander Shishkin /* Denverton */ 1545118ccd3SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x19e1), 1555118ccd3SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 1565118ccd3SAlexander Shishkin }, 157340837f9SAlexander Shishkin { 15824600840SAlexander Shishkin /* Lewisburg PCH */ 15924600840SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa1a6), 16024600840SAlexander Shishkin .driver_data = (kernel_ulong_t)0, 16124600840SAlexander Shishkin }, 16224600840SAlexander Shishkin { 163340837f9SAlexander Shishkin /* Gemini Lake */ 164340837f9SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x318e), 165a0e7df33SAlexander Shishkin .driver_data = (kernel_ulong_t)&intel_th_2x, 166340837f9SAlexander Shishkin }, 16784331e13SAlexander Shishkin { 16884331e13SAlexander Shishkin /* Cannon Lake H */ 16984331e13SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa326), 170a0e7df33SAlexander Shishkin .driver_data = (kernel_ulong_t)&intel_th_2x, 17184331e13SAlexander Shishkin }, 172efb3669eSAlexander Shishkin { 173efb3669eSAlexander Shishkin /* Cannon Lake LP */ 174efb3669eSAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9da6), 175a0e7df33SAlexander Shishkin .driver_data = (kernel_ulong_t)&intel_th_2x, 176efb3669eSAlexander Shishkin }, 177920ce7c3SAlexander Shishkin { 178920ce7c3SAlexander Shishkin /* Cedar Fork PCH */ 179920ce7c3SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x18e1), 180920ce7c3SAlexander Shishkin .driver_data = (kernel_ulong_t)&intel_th_2x, 181920ce7c3SAlexander Shishkin }, 18259d08d00SAlexander Shishkin { 18359d08d00SAlexander Shishkin /* Ice Lake PCH */ 18459d08d00SAlexander Shishkin PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x34a6), 18559d08d00SAlexander Shishkin .driver_data = (kernel_ulong_t)&intel_th_2x, 18659d08d00SAlexander Shishkin }, 1872b0b16d3SAlexander Shishkin { 0 }, 1882b0b16d3SAlexander Shishkin }; 1892b0b16d3SAlexander Shishkin 1902b0b16d3SAlexander Shishkin MODULE_DEVICE_TABLE(pci, intel_th_pci_id_table); 1912b0b16d3SAlexander Shishkin 1922b0b16d3SAlexander Shishkin static struct pci_driver intel_th_pci_driver = { 1932b0b16d3SAlexander Shishkin .name = DRIVER_NAME, 1942b0b16d3SAlexander Shishkin .id_table = intel_th_pci_id_table, 1952b0b16d3SAlexander Shishkin .probe = intel_th_pci_probe, 1962b0b16d3SAlexander Shishkin .remove = intel_th_pci_remove, 1972b0b16d3SAlexander Shishkin }; 1982b0b16d3SAlexander Shishkin 1992b0b16d3SAlexander Shishkin module_pci_driver(intel_th_pci_driver); 2002b0b16d3SAlexander Shishkin 2012b0b16d3SAlexander Shishkin MODULE_LICENSE("GPL v2"); 2022b0b16d3SAlexander Shishkin MODULE_DESCRIPTION("Intel(R) Trace Hub PCI controller driver"); 2032b0b16d3SAlexander Shishkin MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@intel.com>"); 204