xref: /linux/drivers/hwtracing/intel_th/pci.c (revision a0e7df335afd2a8a8a688251ffee375b58b6517c)
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