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