Commit | Line | Data |
---|---|---|
ad51f287 | 1 | // SPDX-License-Identifier: GPL-2.0 |
b740d2e9 RB |
2 | /* |
3 | * Intel Core SoC Power Management Controller Driver | |
4 | * | |
5 | * Copyright (c) 2016, Intel Corporation. | |
6 | * All Rights Reserved. | |
7 | * | |
8 | * Authors: Rajneesh Bhardwaj <rajneesh.bhardwaj@intel.com> | |
9 | * Vishwanath Somayaji <vishwanath.somayaji@intel.com> | |
b740d2e9 RB |
10 | */ |
11 | ||
21ae4357 SP |
12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
13 | ||
745698c3 | 14 | #include <linux/acpi.h> |
8122e7cd | 15 | #include <linux/bitfield.h> |
b740d2e9 | 16 | #include <linux/debugfs.h> |
9c2ee199 | 17 | #include <linux/delay.h> |
238f9c11 | 18 | #include <linux/dmi.h> |
b740d2e9 | 19 | #include <linux/io.h> |
2854a0aa | 20 | #include <linux/module.h> |
661405bd | 21 | #include <linux/pci.h> |
6c96a78c | 22 | #include <linux/platform_device.h> |
2ac8d46d | 23 | #include <linux/suspend.h> |
9c2ee199 | 24 | #include <linux/uaccess.h> |
b740d2e9 RB |
25 | |
26 | #include <asm/cpu_device_id.h> | |
70e0d117 | 27 | #include <asm/intel-family.h> |
8aba056a | 28 | #include <asm/msr.h> |
c09c6071 | 29 | #include <asm/tsc.h> |
b740d2e9 RB |
30 | |
31 | #include "intel_pmc_core.h" | |
32 | ||
33 | static struct pmc_dev pmc; | |
34 | ||
8aba056a RB |
35 | /* PKGC MSRs are common across Intel Core SoCs */ |
36 | static const struct pmc_bit_map msr_map[] = { | |
37 | {"Package C2", MSR_PKG_C2_RESIDENCY}, | |
38 | {"Package C3", MSR_PKG_C3_RESIDENCY}, | |
39 | {"Package C6", MSR_PKG_C6_RESIDENCY}, | |
40 | {"Package C7", MSR_PKG_C7_RESIDENCY}, | |
41 | {"Package C8", MSR_PKG_C8_RESIDENCY}, | |
42 | {"Package C9", MSR_PKG_C9_RESIDENCY}, | |
43 | {"Package C10", MSR_PKG_C10_RESIDENCY}, | |
44 | {} | |
45 | }; | |
46 | ||
fe748227 RB |
47 | static const struct pmc_bit_map spt_pll_map[] = { |
48 | {"MIPI PLL", SPT_PMC_BIT_MPHY_CMN_LANE0}, | |
49 | {"GEN2 USB2PCIE2 PLL", SPT_PMC_BIT_MPHY_CMN_LANE1}, | |
50 | {"DMIPCIE3 PLL", SPT_PMC_BIT_MPHY_CMN_LANE2}, | |
51 | {"SATA PLL", SPT_PMC_BIT_MPHY_CMN_LANE3}, | |
b1cb33da | 52 | {} |
fe748227 RB |
53 | }; |
54 | ||
173943b3 RB |
55 | static const struct pmc_bit_map spt_mphy_map[] = { |
56 | {"MPHY CORE LANE 0", SPT_PMC_BIT_MPHY_LANE0}, | |
57 | {"MPHY CORE LANE 1", SPT_PMC_BIT_MPHY_LANE1}, | |
58 | {"MPHY CORE LANE 2", SPT_PMC_BIT_MPHY_LANE2}, | |
59 | {"MPHY CORE LANE 3", SPT_PMC_BIT_MPHY_LANE3}, | |
60 | {"MPHY CORE LANE 4", SPT_PMC_BIT_MPHY_LANE4}, | |
61 | {"MPHY CORE LANE 5", SPT_PMC_BIT_MPHY_LANE5}, | |
62 | {"MPHY CORE LANE 6", SPT_PMC_BIT_MPHY_LANE6}, | |
63 | {"MPHY CORE LANE 7", SPT_PMC_BIT_MPHY_LANE7}, | |
64 | {"MPHY CORE LANE 8", SPT_PMC_BIT_MPHY_LANE8}, | |
65 | {"MPHY CORE LANE 9", SPT_PMC_BIT_MPHY_LANE9}, | |
66 | {"MPHY CORE LANE 10", SPT_PMC_BIT_MPHY_LANE10}, | |
67 | {"MPHY CORE LANE 11", SPT_PMC_BIT_MPHY_LANE11}, | |
68 | {"MPHY CORE LANE 12", SPT_PMC_BIT_MPHY_LANE12}, | |
69 | {"MPHY CORE LANE 13", SPT_PMC_BIT_MPHY_LANE13}, | |
70 | {"MPHY CORE LANE 14", SPT_PMC_BIT_MPHY_LANE14}, | |
71 | {"MPHY CORE LANE 15", SPT_PMC_BIT_MPHY_LANE15}, | |
b1cb33da | 72 | {} |
173943b3 RB |
73 | }; |
74 | ||
0bdfaf42 RB |
75 | static const struct pmc_bit_map spt_pfear_map[] = { |
76 | {"PMC", SPT_PMC_BIT_PMC}, | |
77 | {"OPI-DMI", SPT_PMC_BIT_OPI}, | |
78 | {"SPI / eSPI", SPT_PMC_BIT_SPI}, | |
79 | {"XHCI", SPT_PMC_BIT_XHCI}, | |
80 | {"SPA", SPT_PMC_BIT_SPA}, | |
81 | {"SPB", SPT_PMC_BIT_SPB}, | |
82 | {"SPC", SPT_PMC_BIT_SPC}, | |
83 | {"GBE", SPT_PMC_BIT_GBE}, | |
84 | {"SATA", SPT_PMC_BIT_SATA}, | |
85 | {"HDA-PGD0", SPT_PMC_BIT_HDA_PGD0}, | |
86 | {"HDA-PGD1", SPT_PMC_BIT_HDA_PGD1}, | |
87 | {"HDA-PGD2", SPT_PMC_BIT_HDA_PGD2}, | |
88 | {"HDA-PGD3", SPT_PMC_BIT_HDA_PGD3}, | |
89 | {"RSVD", SPT_PMC_BIT_RSVD_0B}, | |
90 | {"LPSS", SPT_PMC_BIT_LPSS}, | |
91 | {"LPC", SPT_PMC_BIT_LPC}, | |
92 | {"SMB", SPT_PMC_BIT_SMB}, | |
93 | {"ISH", SPT_PMC_BIT_ISH}, | |
94 | {"P2SB", SPT_PMC_BIT_P2SB}, | |
95 | {"DFX", SPT_PMC_BIT_DFX}, | |
96 | {"SCC", SPT_PMC_BIT_SCC}, | |
97 | {"RSVD", SPT_PMC_BIT_RSVD_0C}, | |
98 | {"FUSE", SPT_PMC_BIT_FUSE}, | |
99 | {"CAMERA", SPT_PMC_BIT_CAMREA}, | |
100 | {"RSVD", SPT_PMC_BIT_RSVD_0D}, | |
101 | {"USB3-OTG", SPT_PMC_BIT_USB3_OTG}, | |
102 | {"EXI", SPT_PMC_BIT_EXI}, | |
103 | {"CSE", SPT_PMC_BIT_CSE}, | |
104 | {"CSME_KVM", SPT_PMC_BIT_CSME_KVM}, | |
105 | {"CSME_PMT", SPT_PMC_BIT_CSME_PMT}, | |
106 | {"CSME_CLINK", SPT_PMC_BIT_CSME_CLINK}, | |
107 | {"CSME_PTIO", SPT_PMC_BIT_CSME_PTIO}, | |
108 | {"CSME_USBR", SPT_PMC_BIT_CSME_USBR}, | |
109 | {"CSME_SUSRAM", SPT_PMC_BIT_CSME_SUSRAM}, | |
110 | {"CSME_SMT", SPT_PMC_BIT_CSME_SMT}, | |
111 | {"RSVD", SPT_PMC_BIT_RSVD_1A}, | |
112 | {"CSME_SMS2", SPT_PMC_BIT_CSME_SMS2}, | |
113 | {"CSME_SMS1", SPT_PMC_BIT_CSME_SMS1}, | |
114 | {"CSME_RTC", SPT_PMC_BIT_CSME_RTC}, | |
115 | {"CSME_PSF", SPT_PMC_BIT_CSME_PSF}, | |
b1cb33da | 116 | {} |
0bdfaf42 RB |
117 | }; |
118 | ||
e3985478 GK |
119 | static const struct pmc_bit_map *ext_spt_pfear_map[] = { |
120 | spt_pfear_map, | |
121 | NULL | |
122 | }; | |
123 | ||
2eb15055 RB |
124 | static const struct pmc_bit_map spt_ltr_show_map[] = { |
125 | {"SOUTHPORT_A", SPT_PMC_LTR_SPA}, | |
126 | {"SOUTHPORT_B", SPT_PMC_LTR_SPB}, | |
127 | {"SATA", SPT_PMC_LTR_SATA}, | |
128 | {"GIGABIT_ETHERNET", SPT_PMC_LTR_GBE}, | |
129 | {"XHCI", SPT_PMC_LTR_XHCI}, | |
2a13096a | 130 | {"Reserved", SPT_PMC_LTR_RESERVED}, |
2eb15055 RB |
131 | {"ME", SPT_PMC_LTR_ME}, |
132 | /* EVA is Enterprise Value Add, doesn't really exist on PCH */ | |
133 | {"EVA", SPT_PMC_LTR_EVA}, | |
134 | {"SOUTHPORT_C", SPT_PMC_LTR_SPC}, | |
135 | {"HD_AUDIO", SPT_PMC_LTR_AZ}, | |
136 | {"LPSS", SPT_PMC_LTR_LPSS}, | |
137 | {"SOUTHPORT_D", SPT_PMC_LTR_SPD}, | |
138 | {"SOUTHPORT_E", SPT_PMC_LTR_SPE}, | |
139 | {"CAMERA", SPT_PMC_LTR_CAM}, | |
140 | {"ESPI", SPT_PMC_LTR_ESPI}, | |
141 | {"SCC", SPT_PMC_LTR_SCC}, | |
142 | {"ISH", SPT_PMC_LTR_ISH}, | |
143 | /* Below two cannot be used for LTR_IGNORE */ | |
144 | {"CURRENT_PLATFORM", SPT_PMC_LTR_CUR_PLT}, | |
145 | {"AGGREGATED_SYSTEM", SPT_PMC_LTR_CUR_ASLT}, | |
146 | {} | |
147 | }; | |
148 | ||
0bdfaf42 | 149 | static const struct pmc_reg_map spt_reg_map = { |
e3985478 | 150 | .pfear_sts = ext_spt_pfear_map, |
173943b3 | 151 | .mphy_sts = spt_mphy_map, |
fe748227 | 152 | .pll_sts = spt_pll_map, |
2eb15055 | 153 | .ltr_show_sts = spt_ltr_show_map, |
8aba056a | 154 | .msr_sts = msr_map, |
c977b98b SP |
155 | .slp_s0_offset = SPT_PMC_SLP_S0_RES_COUNTER_OFFSET, |
156 | .ltr_ignore_offset = SPT_PMC_LTR_IGNORE_OFFSET, | |
157 | .regmap_length = SPT_PMC_MMIO_REG_LEN, | |
158 | .ppfear0_offset = SPT_PMC_XRAM_PPFEAR0A, | |
159 | .ppfear_buckets = SPT_PPFEAR_NUM_ENTRIES, | |
160 | .pm_cfg_offset = SPT_PMC_PM_CFG_OFFSET, | |
161 | .pm_read_disable_bit = SPT_PMC_READ_DISABLE_BIT, | |
2d649d97 | 162 | .ltr_ignore_max = SPT_NUM_IP_IGN_ALLOWED, |
238f9c11 | 163 | .pm_vric1_offset = SPT_PMC_VRIC1_OFFSET, |
0bdfaf42 RB |
164 | }; |
165 | ||
43e82d8a | 166 | /* Cannon Lake: PGD PFET Enable Ack Status Register(s) bitmap */ |
291101f6 | 167 | static const struct pmc_bit_map cnp_pfear_map[] = { |
5406327d | 168 | /* Reserved for Cannon Lake but valid for Comet Lake */ |
291101f6 RB |
169 | {"PMC", BIT(0)}, |
170 | {"OPI-DMI", BIT(1)}, | |
171 | {"SPI/eSPI", BIT(2)}, | |
172 | {"XHCI", BIT(3)}, | |
173 | {"SPA", BIT(4)}, | |
174 | {"SPB", BIT(5)}, | |
175 | {"SPC", BIT(6)}, | |
176 | {"GBE", BIT(7)}, | |
177 | ||
178 | {"SATA", BIT(0)}, | |
179 | {"HDA_PGD0", BIT(1)}, | |
180 | {"HDA_PGD1", BIT(2)}, | |
181 | {"HDA_PGD2", BIT(3)}, | |
182 | {"HDA_PGD3", BIT(4)}, | |
183 | {"SPD", BIT(5)}, | |
184 | {"LPSS", BIT(6)}, | |
185 | {"LPC", BIT(7)}, | |
186 | ||
187 | {"SMB", BIT(0)}, | |
188 | {"ISH", BIT(1)}, | |
189 | {"P2SB", BIT(2)}, | |
190 | {"NPK_VNN", BIT(3)}, | |
191 | {"SDX", BIT(4)}, | |
192 | {"SPE", BIT(5)}, | |
193 | {"Fuse", BIT(6)}, | |
49a43794 | 194 | /* |
554f269f GK |
195 | * Reserved for Cannon Lake but valid for Ice Lake, Comet Lake, |
196 | * Tiger Lake and Elkhart Lake. | |
49a43794 | 197 | */ |
6769fdbe | 198 | {"SBR8", BIT(7)}, |
291101f6 RB |
199 | |
200 | {"CSME_FSC", BIT(0)}, | |
201 | {"USB3_OTG", BIT(1)}, | |
202 | {"EXI", BIT(2)}, | |
203 | {"CSE", BIT(3)}, | |
6769fdbe RB |
204 | {"CSME_KVM", BIT(4)}, |
205 | {"CSME_PMT", BIT(5)}, | |
206 | {"CSME_CLINK", BIT(6)}, | |
207 | {"CSME_PTIO", BIT(7)}, | |
208 | ||
209 | {"CSME_USBR", BIT(0)}, | |
210 | {"CSME_SUSRAM", BIT(1)}, | |
211 | {"CSME_SMT1", BIT(2)}, | |
291101f6 | 212 | {"CSME_SMT4", BIT(3)}, |
6769fdbe RB |
213 | {"CSME_SMS2", BIT(4)}, |
214 | {"CSME_SMS1", BIT(5)}, | |
215 | {"CSME_RTC", BIT(6)}, | |
216 | {"CSME_PSF", BIT(7)}, | |
291101f6 RB |
217 | |
218 | {"SBR0", BIT(0)}, | |
219 | {"SBR1", BIT(1)}, | |
220 | {"SBR2", BIT(2)}, | |
221 | {"SBR3", BIT(3)}, | |
222 | {"SBR4", BIT(4)}, | |
223 | {"SBR5", BIT(5)}, | |
224 | {"CSME_PECI", BIT(6)}, | |
225 | {"PSF1", BIT(7)}, | |
226 | ||
227 | {"PSF2", BIT(0)}, | |
228 | {"PSF3", BIT(1)}, | |
229 | {"PSF4", BIT(2)}, | |
230 | {"CNVI", BIT(3)}, | |
231 | {"UFS0", BIT(4)}, | |
232 | {"EMMC", BIT(5)}, | |
d6827015 | 233 | {"SPF", BIT(6)}, |
291101f6 RB |
234 | {"SBR6", BIT(7)}, |
235 | ||
236 | {"SBR7", BIT(0)}, | |
237 | {"NPK_AON", BIT(1)}, | |
238 | {"HDA_PGD4", BIT(2)}, | |
239 | {"HDA_PGD5", BIT(3)}, | |
240 | {"HDA_PGD6", BIT(4)}, | |
49a43794 | 241 | /* |
554f269f GK |
242 | * Reserved for Cannon Lake but valid for Ice Lake, Comet Lake, |
243 | * Tiger Lake and ELkhart Lake. | |
49a43794 | 244 | */ |
6769fdbe RB |
245 | {"PSF6", BIT(5)}, |
246 | {"PSF7", BIT(6)}, | |
247 | {"PSF8", BIT(7)}, | |
e3985478 GK |
248 | {} |
249 | }; | |
250 | ||
251 | static const struct pmc_bit_map *ext_cnp_pfear_map[] = { | |
252 | cnp_pfear_map, | |
253 | NULL | |
254 | }; | |
6769fdbe | 255 | |
e3985478 | 256 | static const struct pmc_bit_map icl_pfear_map[] = { |
43e82d8a | 257 | /* Ice Lake generation onwards only */ |
6769fdbe RB |
258 | {"RES_65", BIT(0)}, |
259 | {"RES_66", BIT(1)}, | |
260 | {"RES_67", BIT(2)}, | |
261 | {"TAM", BIT(3)}, | |
262 | {"GBETSN", BIT(4)}, | |
263 | {"TBTLSX", BIT(5)}, | |
264 | {"RES_71", BIT(6)}, | |
265 | {"RES_72", BIT(7)}, | |
291101f6 RB |
266 | {} |
267 | }; | |
268 | ||
e3985478 GK |
269 | static const struct pmc_bit_map *ext_icl_pfear_map[] = { |
270 | cnp_pfear_map, | |
271 | icl_pfear_map, | |
272 | NULL | |
273 | }; | |
274 | ||
49a43794 | 275 | static const struct pmc_bit_map tgl_pfear_map[] = { |
554f269f | 276 | /* Tiger Lake and Elkhart Lake generation onwards only */ |
49a43794 GK |
277 | {"PSF9", BIT(0)}, |
278 | {"RES_66", BIT(1)}, | |
279 | {"RES_67", BIT(2)}, | |
280 | {"RES_68", BIT(3)}, | |
281 | {"RES_69", BIT(4)}, | |
282 | {"RES_70", BIT(5)}, | |
283 | {"TBTLSX", BIT(6)}, | |
284 | {} | |
285 | }; | |
286 | ||
287 | static const struct pmc_bit_map *ext_tgl_pfear_map[] = { | |
288 | cnp_pfear_map, | |
289 | tgl_pfear_map, | |
290 | NULL | |
291 | }; | |
292 | ||
4cf2afd6 BD |
293 | static const struct pmc_bit_map cnp_slps0_dbg0_map[] = { |
294 | {"AUDIO_D3", BIT(0)}, | |
295 | {"OTG_D3", BIT(1)}, | |
296 | {"XHCI_D3", BIT(2)}, | |
297 | {"LPIO_D3", BIT(3)}, | |
298 | {"SDX_D3", BIT(4)}, | |
299 | {"SATA_D3", BIT(5)}, | |
300 | {"UFS0_D3", BIT(6)}, | |
301 | {"UFS1_D3", BIT(7)}, | |
302 | {"EMMC_D3", BIT(8)}, | |
303 | {} | |
304 | }; | |
305 | ||
306 | static const struct pmc_bit_map cnp_slps0_dbg1_map[] = { | |
307 | {"SDIO_PLL_OFF", BIT(0)}, | |
308 | {"USB2_PLL_OFF", BIT(1)}, | |
309 | {"AUDIO_PLL_OFF", BIT(2)}, | |
310 | {"OC_PLL_OFF", BIT(3)}, | |
311 | {"MAIN_PLL_OFF", BIT(4)}, | |
312 | {"XOSC_OFF", BIT(5)}, | |
313 | {"LPC_CLKS_GATED", BIT(6)}, | |
314 | {"PCIE_CLKREQS_IDLE", BIT(7)}, | |
315 | {"AUDIO_ROSC_OFF", BIT(8)}, | |
316 | {"HPET_XOSC_CLK_REQ", BIT(9)}, | |
317 | {"PMC_ROSC_SLOW_CLK", BIT(10)}, | |
318 | {"AON2_ROSC_GATED", BIT(11)}, | |
319 | {"CLKACKS_DEASSERTED", BIT(12)}, | |
320 | {} | |
321 | }; | |
322 | ||
323 | static const struct pmc_bit_map cnp_slps0_dbg2_map[] = { | |
324 | {"MPHY_CORE_GATED", BIT(0)}, | |
325 | {"CSME_GATED", BIT(1)}, | |
326 | {"USB2_SUS_GATED", BIT(2)}, | |
327 | {"DYN_FLEX_IO_IDLE", BIT(3)}, | |
328 | {"GBE_NO_LINK", BIT(4)}, | |
329 | {"THERM_SEN_DISABLED", BIT(5)}, | |
330 | {"PCIE_LOW_POWER", BIT(6)}, | |
331 | {"ISH_VNNAON_REQ_ACT", BIT(7)}, | |
332 | {"ISH_VNN_REQ_ACT", BIT(8)}, | |
333 | {"CNV_VNNAON_REQ_ACT", BIT(9)}, | |
334 | {"CNV_VNN_REQ_ACT", BIT(10)}, | |
335 | {"NPK_VNNON_REQ_ACT", BIT(11)}, | |
336 | {"PMSYNC_STATE_IDLE", BIT(12)}, | |
337 | {"ALST_GT_THRES", BIT(13)}, | |
338 | {"PMC_ARC_PG_READY", BIT(14)}, | |
339 | {} | |
340 | }; | |
341 | ||
342 | static const struct pmc_bit_map *cnp_slps0_dbg_maps[] = { | |
343 | cnp_slps0_dbg0_map, | |
344 | cnp_slps0_dbg1_map, | |
345 | cnp_slps0_dbg2_map, | |
b1cb33da | 346 | NULL |
4cf2afd6 BD |
347 | }; |
348 | ||
2eb15055 RB |
349 | static const struct pmc_bit_map cnp_ltr_show_map[] = { |
350 | {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, | |
351 | {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, | |
352 | {"SATA", CNP_PMC_LTR_SATA}, | |
353 | {"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE}, | |
354 | {"XHCI", CNP_PMC_LTR_XHCI}, | |
2a13096a | 355 | {"Reserved", CNP_PMC_LTR_RESERVED}, |
2eb15055 RB |
356 | {"ME", CNP_PMC_LTR_ME}, |
357 | /* EVA is Enterprise Value Add, doesn't really exist on PCH */ | |
358 | {"EVA", CNP_PMC_LTR_EVA}, | |
359 | {"SOUTHPORT_C", CNP_PMC_LTR_SPC}, | |
360 | {"HD_AUDIO", CNP_PMC_LTR_AZ}, | |
361 | {"CNV", CNP_PMC_LTR_CNV}, | |
362 | {"LPSS", CNP_PMC_LTR_LPSS}, | |
363 | {"SOUTHPORT_D", CNP_PMC_LTR_SPD}, | |
364 | {"SOUTHPORT_E", CNP_PMC_LTR_SPE}, | |
365 | {"CAMERA", CNP_PMC_LTR_CAM}, | |
366 | {"ESPI", CNP_PMC_LTR_ESPI}, | |
367 | {"SCC", CNP_PMC_LTR_SCC}, | |
368 | {"ISH", CNP_PMC_LTR_ISH}, | |
369 | {"UFSX2", CNP_PMC_LTR_UFSX2}, | |
370 | {"EMMC", CNP_PMC_LTR_EMMC}, | |
43e82d8a | 371 | /* Reserved for Cannon Lake but valid for Ice Lake */ |
6769fdbe | 372 | {"WIGIG", ICL_PMC_LTR_WIGIG}, |
2eb15055 RB |
373 | /* Below two cannot be used for LTR_IGNORE */ |
374 | {"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT}, | |
375 | {"AGGREGATED_SYSTEM", CNP_PMC_LTR_CUR_ASLT}, | |
376 | {} | |
377 | }; | |
378 | ||
291101f6 | 379 | static const struct pmc_reg_map cnp_reg_map = { |
e3985478 | 380 | .pfear_sts = ext_cnp_pfear_map, |
291101f6 | 381 | .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, |
4cf2afd6 | 382 | .slps0_dbg_maps = cnp_slps0_dbg_maps, |
2eb15055 | 383 | .ltr_show_sts = cnp_ltr_show_map, |
8aba056a | 384 | .msr_sts = msr_map, |
4cf2afd6 | 385 | .slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET, |
291101f6 RB |
386 | .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, |
387 | .regmap_length = CNP_PMC_MMIO_REG_LEN, | |
388 | .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, | |
389 | .ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES, | |
390 | .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, | |
391 | .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, | |
2d649d97 | 392 | .ltr_ignore_max = CNP_NUM_IP_IGN_ALLOWED, |
291101f6 RB |
393 | }; |
394 | ||
6769fdbe | 395 | static const struct pmc_reg_map icl_reg_map = { |
e3985478 | 396 | .pfear_sts = ext_icl_pfear_map, |
6769fdbe RB |
397 | .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, |
398 | .slps0_dbg_maps = cnp_slps0_dbg_maps, | |
399 | .ltr_show_sts = cnp_ltr_show_map, | |
8aba056a | 400 | .msr_sts = msr_map, |
6769fdbe RB |
401 | .slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET, |
402 | .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, | |
403 | .regmap_length = CNP_PMC_MMIO_REG_LEN, | |
404 | .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, | |
405 | .ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES, | |
406 | .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, | |
407 | .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, | |
408 | .ltr_ignore_max = ICL_NUM_IP_IGN_ALLOWED, | |
409 | }; | |
410 | ||
49a43794 GK |
411 | static const struct pmc_reg_map tgl_reg_map = { |
412 | .pfear_sts = ext_tgl_pfear_map, | |
413 | .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, | |
414 | .slps0_dbg_maps = cnp_slps0_dbg_maps, | |
415 | .ltr_show_sts = cnp_ltr_show_map, | |
416 | .msr_sts = msr_map, | |
417 | .slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET, | |
418 | .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, | |
419 | .regmap_length = CNP_PMC_MMIO_REG_LEN, | |
420 | .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, | |
421 | .ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES, | |
422 | .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, | |
423 | .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, | |
424 | .ltr_ignore_max = TGL_NUM_IP_IGN_ALLOWED, | |
425 | }; | |
426 | ||
b740d2e9 RB |
427 | static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset) |
428 | { | |
429 | return readl(pmcdev->regbase + reg_offset); | |
430 | } | |
431 | ||
e0e60abc AS |
432 | static inline void pmc_core_reg_write(struct pmc_dev *pmcdev, int reg_offset, |
433 | u32 val) | |
173943b3 RB |
434 | { |
435 | writel(val, pmcdev->regbase + reg_offset); | |
436 | } | |
437 | ||
4a5861f7 | 438 | static inline u64 pmc_core_adjust_slp_s0_step(u32 value) |
b740d2e9 | 439 | { |
4a5861f7 | 440 | return (u64)value * SPT_PMC_SLP_S0_RES_COUNTER_STEP; |
b740d2e9 RB |
441 | } |
442 | ||
df2294fb | 443 | static int pmc_core_dev_state_get(void *data, u64 *val) |
b740d2e9 | 444 | { |
df2294fb | 445 | struct pmc_dev *pmcdev = data; |
c977b98b | 446 | const struct pmc_reg_map *map = pmcdev->map; |
df2294fb | 447 | u32 value; |
b740d2e9 | 448 | |
c977b98b | 449 | value = pmc_core_reg_read(pmcdev, map->slp_s0_offset); |
df2294fb | 450 | *val = pmc_core_adjust_slp_s0_step(value); |
b740d2e9 RB |
451 | |
452 | return 0; | |
453 | } | |
454 | ||
df2294fb | 455 | DEFINE_DEBUGFS_ATTRIBUTE(pmc_core_dev_state, pmc_core_dev_state_get, NULL, "%llu\n"); |
b740d2e9 | 456 | |
173943b3 RB |
457 | static int pmc_core_check_read_lock_bit(void) |
458 | { | |
459 | struct pmc_dev *pmcdev = &pmc; | |
460 | u32 value; | |
461 | ||
c977b98b SP |
462 | value = pmc_core_reg_read(pmcdev, pmcdev->map->pm_cfg_offset); |
463 | return value & BIT(pmcdev->map->pm_read_disable_bit); | |
173943b3 RB |
464 | } |
465 | ||
0bdfaf42 | 466 | #if IS_ENABLED(CONFIG_DEBUG_FS) |
4cf2afd6 BD |
467 | static bool slps0_dbg_latch; |
468 | ||
90113f3e AS |
469 | static inline u8 pmc_core_reg_read_byte(struct pmc_dev *pmcdev, int offset) |
470 | { | |
471 | return readb(pmcdev->regbase + offset); | |
472 | } | |
473 | ||
e3985478 GK |
474 | static void pmc_core_display_map(struct seq_file *s, int index, int idx, int ip, |
475 | u8 pf_reg, const struct pmc_bit_map **pf_map) | |
0bdfaf42 RB |
476 | { |
477 | seq_printf(s, "PCH IP: %-2d - %-32s\tState: %s\n", | |
e3985478 GK |
478 | ip, pf_map[idx][index].name, |
479 | pf_map[idx][index].bit_mask & pf_reg ? "Off" : "On"); | |
0bdfaf42 RB |
480 | } |
481 | ||
3b1f9955 | 482 | static int pmc_core_ppfear_show(struct seq_file *s, void *unused) |
0bdfaf42 RB |
483 | { |
484 | struct pmc_dev *pmcdev = s->private; | |
e3985478 | 485 | const struct pmc_bit_map **maps = pmcdev->map->pfear_sts; |
c977b98b | 486 | u8 pf_regs[PPFEAR_MAX_NUM_ENTRIES]; |
e3985478 | 487 | int index, iter, idx, ip = 0; |
0bdfaf42 | 488 | |
c977b98b | 489 | iter = pmcdev->map->ppfear0_offset; |
0bdfaf42 | 490 | |
c977b98b SP |
491 | for (index = 0; index < pmcdev->map->ppfear_buckets && |
492 | index < PPFEAR_MAX_NUM_ENTRIES; index++, iter++) | |
0bdfaf42 RB |
493 | pf_regs[index] = pmc_core_reg_read_byte(pmcdev, iter); |
494 | ||
e3985478 GK |
495 | for (idx = 0; maps[idx]; idx++) { |
496 | for (index = 0; maps[idx][index].name && | |
497 | index < pmcdev->map->ppfear_buckets * 8; ip++, index++) | |
498 | pmc_core_display_map(s, index, idx, ip, | |
499 | pf_regs[index / 8], maps); | |
500 | } | |
0bdfaf42 RB |
501 | |
502 | return 0; | |
503 | } | |
3b1f9955 | 504 | DEFINE_SHOW_ATTRIBUTE(pmc_core_ppfear); |
0bdfaf42 | 505 | |
173943b3 RB |
506 | /* This function should return link status, 0 means ready */ |
507 | static int pmc_core_mtpmc_link_status(void) | |
508 | { | |
509 | struct pmc_dev *pmcdev = &pmc; | |
510 | u32 value; | |
511 | ||
512 | value = pmc_core_reg_read(pmcdev, SPT_PMC_PM_STS_OFFSET); | |
4f24ecff | 513 | return value & BIT(SPT_PMC_MSG_FULL_STS_BIT); |
173943b3 RB |
514 | } |
515 | ||
516 | static int pmc_core_send_msg(u32 *addr_xram) | |
517 | { | |
518 | struct pmc_dev *pmcdev = &pmc; | |
519 | u32 dest; | |
520 | int timeout; | |
521 | ||
522 | for (timeout = NUM_RETRIES; timeout > 0; timeout--) { | |
523 | if (pmc_core_mtpmc_link_status() == 0) | |
524 | break; | |
525 | msleep(5); | |
526 | } | |
527 | ||
528 | if (timeout <= 0 && pmc_core_mtpmc_link_status()) | |
529 | return -EBUSY; | |
530 | ||
531 | dest = (*addr_xram & MTPMC_MASK) | (1U << 1); | |
532 | pmc_core_reg_write(pmcdev, SPT_PMC_MTPMC_OFFSET, dest); | |
533 | return 0; | |
534 | } | |
535 | ||
3b1f9955 | 536 | static int pmc_core_mphy_pg_show(struct seq_file *s, void *unused) |
173943b3 RB |
537 | { |
538 | struct pmc_dev *pmcdev = s->private; | |
539 | const struct pmc_bit_map *map = pmcdev->map->mphy_sts; | |
540 | u32 mphy_core_reg_low, mphy_core_reg_high; | |
541 | u32 val_low, val_high; | |
542 | int index, err = 0; | |
543 | ||
544 | if (pmcdev->pmc_xram_read_bit) { | |
545 | seq_puts(s, "Access denied: please disable PMC_READ_DISABLE setting in BIOS."); | |
546 | return 0; | |
547 | } | |
548 | ||
549 | mphy_core_reg_low = (SPT_PMC_MPHY_CORE_STS_0 << 16); | |
550 | mphy_core_reg_high = (SPT_PMC_MPHY_CORE_STS_1 << 16); | |
551 | ||
552 | mutex_lock(&pmcdev->lock); | |
553 | ||
554 | if (pmc_core_send_msg(&mphy_core_reg_low) != 0) { | |
555 | err = -EBUSY; | |
556 | goto out_unlock; | |
557 | } | |
558 | ||
559 | msleep(10); | |
560 | val_low = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET); | |
561 | ||
562 | if (pmc_core_send_msg(&mphy_core_reg_high) != 0) { | |
563 | err = -EBUSY; | |
564 | goto out_unlock; | |
565 | } | |
566 | ||
567 | msleep(10); | |
568 | val_high = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET); | |
569 | ||
570 | for (index = 0; map[index].name && index < 8; index++) { | |
571 | seq_printf(s, "%-32s\tState: %s\n", | |
572 | map[index].name, | |
573 | map[index].bit_mask & val_low ? "Not power gated" : | |
574 | "Power gated"); | |
575 | } | |
576 | ||
577 | for (index = 8; map[index].name; index++) { | |
578 | seq_printf(s, "%-32s\tState: %s\n", | |
579 | map[index].name, | |
580 | map[index].bit_mask & val_high ? "Not power gated" : | |
581 | "Power gated"); | |
582 | } | |
583 | ||
584 | out_unlock: | |
585 | mutex_unlock(&pmcdev->lock); | |
586 | return err; | |
587 | } | |
3b1f9955 | 588 | DEFINE_SHOW_ATTRIBUTE(pmc_core_mphy_pg); |
173943b3 | 589 | |
fe748227 RB |
590 | static int pmc_core_pll_show(struct seq_file *s, void *unused) |
591 | { | |
592 | struct pmc_dev *pmcdev = s->private; | |
593 | const struct pmc_bit_map *map = pmcdev->map->pll_sts; | |
594 | u32 mphy_common_reg, val; | |
595 | int index, err = 0; | |
596 | ||
597 | if (pmcdev->pmc_xram_read_bit) { | |
598 | seq_puts(s, "Access denied: please disable PMC_READ_DISABLE setting in BIOS."); | |
599 | return 0; | |
600 | } | |
601 | ||
602 | mphy_common_reg = (SPT_PMC_MPHY_COM_STS_0 << 16); | |
603 | mutex_lock(&pmcdev->lock); | |
604 | ||
605 | if (pmc_core_send_msg(&mphy_common_reg) != 0) { | |
606 | err = -EBUSY; | |
607 | goto out_unlock; | |
608 | } | |
609 | ||
610 | /* Observed PMC HW response latency for MTPMC-MFPMC is ~10 ms */ | |
611 | msleep(10); | |
612 | val = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET); | |
613 | ||
614 | for (index = 0; map[index].name ; index++) { | |
615 | seq_printf(s, "%-32s\tState: %s\n", | |
616 | map[index].name, | |
617 | map[index].bit_mask & val ? "Active" : "Idle"); | |
618 | } | |
619 | ||
620 | out_unlock: | |
621 | mutex_unlock(&pmcdev->lock); | |
622 | return err; | |
623 | } | |
3b1f9955 | 624 | DEFINE_SHOW_ATTRIBUTE(pmc_core_pll); |
fe748227 | 625 | |
e0e60abc AS |
626 | static ssize_t pmc_core_ltr_ignore_write(struct file *file, |
627 | const char __user *userbuf, | |
628 | size_t count, loff_t *ppos) | |
9c2ee199 RB |
629 | { |
630 | struct pmc_dev *pmcdev = &pmc; | |
c977b98b | 631 | const struct pmc_reg_map *map = pmcdev->map; |
9c2ee199 | 632 | u32 val, buf_size, fd; |
95924388 | 633 | int err; |
9c2ee199 RB |
634 | |
635 | buf_size = count < 64 ? count : 64; | |
9c2ee199 | 636 | |
95924388 AS |
637 | err = kstrtou32_from_user(userbuf, buf_size, 10, &val); |
638 | if (err) | |
639 | return err; | |
640 | ||
641 | mutex_lock(&pmcdev->lock); | |
9c2ee199 | 642 | |
2d649d97 | 643 | if (val > map->ltr_ignore_max) { |
9c2ee199 RB |
644 | err = -EINVAL; |
645 | goto out_unlock; | |
646 | } | |
647 | ||
c977b98b | 648 | fd = pmc_core_reg_read(pmcdev, map->ltr_ignore_offset); |
9c2ee199 | 649 | fd |= (1U << val); |
c977b98b | 650 | pmc_core_reg_write(pmcdev, map->ltr_ignore_offset, fd); |
9c2ee199 RB |
651 | |
652 | out_unlock: | |
653 | mutex_unlock(&pmcdev->lock); | |
654 | return err == 0 ? count : err; | |
655 | } | |
656 | ||
657 | static int pmc_core_ltr_ignore_show(struct seq_file *s, void *unused) | |
658 | { | |
659 | return 0; | |
660 | } | |
661 | ||
662 | static int pmc_core_ltr_ignore_open(struct inode *inode, struct file *file) | |
663 | { | |
664 | return single_open(file, pmc_core_ltr_ignore_show, inode->i_private); | |
665 | } | |
666 | ||
667 | static const struct file_operations pmc_core_ltr_ignore_ops = { | |
668 | .open = pmc_core_ltr_ignore_open, | |
669 | .read = seq_read, | |
670 | .write = pmc_core_ltr_ignore_write, | |
671 | .llseek = seq_lseek, | |
672 | .release = single_release, | |
673 | }; | |
674 | ||
4cf2afd6 BD |
675 | static void pmc_core_slps0_dbg_latch(struct pmc_dev *pmcdev, bool reset) |
676 | { | |
677 | const struct pmc_reg_map *map = pmcdev->map; | |
678 | u32 fd; | |
679 | ||
680 | mutex_lock(&pmcdev->lock); | |
681 | ||
682 | if (!reset && !slps0_dbg_latch) | |
683 | goto out_unlock; | |
684 | ||
685 | fd = pmc_core_reg_read(pmcdev, map->slps0_dbg_offset); | |
686 | if (reset) | |
687 | fd &= ~CNP_PMC_LATCH_SLPS0_EVENTS; | |
688 | else | |
689 | fd |= CNP_PMC_LATCH_SLPS0_EVENTS; | |
690 | pmc_core_reg_write(pmcdev, map->slps0_dbg_offset, fd); | |
691 | ||
692 | slps0_dbg_latch = 0; | |
693 | ||
694 | out_unlock: | |
695 | mutex_unlock(&pmcdev->lock); | |
696 | } | |
697 | ||
698 | static int pmc_core_slps0_dbg_show(struct seq_file *s, void *unused) | |
699 | { | |
700 | struct pmc_dev *pmcdev = s->private; | |
701 | const struct pmc_bit_map **maps = pmcdev->map->slps0_dbg_maps; | |
702 | const struct pmc_bit_map *map; | |
703 | int offset; | |
704 | u32 data; | |
705 | ||
706 | pmc_core_slps0_dbg_latch(pmcdev, false); | |
707 | offset = pmcdev->map->slps0_dbg_offset; | |
708 | while (*maps) { | |
709 | map = *maps; | |
710 | data = pmc_core_reg_read(pmcdev, offset); | |
711 | offset += 4; | |
712 | while (map->name) { | |
713 | seq_printf(s, "SLP_S0_DBG: %-32s\tState: %s\n", | |
714 | map->name, | |
715 | data & map->bit_mask ? | |
716 | "Yes" : "No"); | |
717 | ++map; | |
718 | } | |
719 | ++maps; | |
720 | } | |
721 | pmc_core_slps0_dbg_latch(pmcdev, true); | |
722 | return 0; | |
723 | } | |
724 | DEFINE_SHOW_ATTRIBUTE(pmc_core_slps0_dbg); | |
725 | ||
8122e7cd RB |
726 | static u32 convert_ltr_scale(u32 val) |
727 | { | |
728 | /* | |
729 | * As per PCIE specification supporting document | |
730 | * ECN_LatencyTolnReporting_14Aug08.pdf the Latency | |
731 | * Tolerance Reporting data payload is encoded in a | |
732 | * 3 bit scale and 10 bit value fields. Values are | |
733 | * multiplied by the indicated scale to yield an absolute time | |
734 | * value, expressible in a range from 1 nanosecond to | |
735 | * 2^25*(2^10-1) = 34,326,183,936 nanoseconds. | |
736 | * | |
737 | * scale encoding is as follows: | |
738 | * | |
739 | * ---------------------------------------------- | |
740 | * |scale factor | Multiplier (ns) | | |
741 | * ---------------------------------------------- | |
742 | * | 0 | 1 | | |
743 | * | 1 | 32 | | |
744 | * | 2 | 1024 | | |
745 | * | 3 | 32768 | | |
746 | * | 4 | 1048576 | | |
747 | * | 5 | 33554432 | | |
748 | * | 6 | Invalid | | |
749 | * | 7 | Invalid | | |
750 | * ---------------------------------------------- | |
751 | */ | |
752 | if (val > 5) { | |
753 | pr_warn("Invalid LTR scale factor.\n"); | |
754 | return 0; | |
755 | } | |
756 | ||
757 | return 1U << (5 * val); | |
758 | } | |
759 | ||
2eb15055 RB |
760 | static int pmc_core_ltr_show(struct seq_file *s, void *unused) |
761 | { | |
762 | struct pmc_dev *pmcdev = s->private; | |
763 | const struct pmc_bit_map *map = pmcdev->map->ltr_show_sts; | |
8122e7cd RB |
764 | u64 decoded_snoop_ltr, decoded_non_snoop_ltr; |
765 | u32 ltr_raw_data, scale, val; | |
766 | u16 snoop_ltr, nonsnoop_ltr; | |
2eb15055 RB |
767 | int index; |
768 | ||
769 | for (index = 0; map[index].name ; index++) { | |
8122e7cd RB |
770 | decoded_snoop_ltr = decoded_non_snoop_ltr = 0; |
771 | ltr_raw_data = pmc_core_reg_read(pmcdev, | |
772 | map[index].bit_mask); | |
773 | snoop_ltr = ltr_raw_data & ~MTPMC_MASK; | |
774 | nonsnoop_ltr = (ltr_raw_data >> 0x10) & ~MTPMC_MASK; | |
775 | ||
776 | if (FIELD_GET(LTR_REQ_NONSNOOP, ltr_raw_data)) { | |
777 | scale = FIELD_GET(LTR_DECODED_SCALE, nonsnoop_ltr); | |
778 | val = FIELD_GET(LTR_DECODED_VAL, nonsnoop_ltr); | |
779 | decoded_non_snoop_ltr = val * convert_ltr_scale(scale); | |
780 | } | |
781 | ||
782 | if (FIELD_GET(LTR_REQ_SNOOP, ltr_raw_data)) { | |
783 | scale = FIELD_GET(LTR_DECODED_SCALE, snoop_ltr); | |
784 | val = FIELD_GET(LTR_DECODED_VAL, snoop_ltr); | |
785 | decoded_snoop_ltr = val * convert_ltr_scale(scale); | |
786 | } | |
787 | ||
788 | seq_printf(s, "%-32s\tLTR: RAW: 0x%-16x\tNon-Snoop(ns): %-16llu\tSnoop(ns): %-16llu\n", | |
789 | map[index].name, ltr_raw_data, | |
790 | decoded_non_snoop_ltr, | |
791 | decoded_snoop_ltr); | |
2eb15055 RB |
792 | } |
793 | return 0; | |
794 | } | |
795 | DEFINE_SHOW_ATTRIBUTE(pmc_core_ltr); | |
796 | ||
8aba056a RB |
797 | static int pmc_core_pkgc_show(struct seq_file *s, void *unused) |
798 | { | |
799 | struct pmc_dev *pmcdev = s->private; | |
800 | const struct pmc_bit_map *map = pmcdev->map->msr_sts; | |
801 | u64 pcstate_count; | |
802 | int index; | |
803 | ||
804 | for (index = 0; map[index].name ; index++) { | |
805 | if (rdmsrl_safe(map[index].bit_mask, &pcstate_count)) | |
806 | continue; | |
807 | ||
c09c6071 HP |
808 | pcstate_count *= 1000; |
809 | do_div(pcstate_count, tsc_khz); | |
810 | seq_printf(s, "%-8s : %llu\n", map[index].name, | |
8aba056a RB |
811 | pcstate_count); |
812 | } | |
813 | ||
814 | return 0; | |
815 | } | |
816 | DEFINE_SHOW_ATTRIBUTE(pmc_core_pkgc); | |
817 | ||
b740d2e9 RB |
818 | static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev) |
819 | { | |
820 | debugfs_remove_recursive(pmcdev->dbgfs_dir); | |
821 | } | |
822 | ||
15167554 | 823 | static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev) |
b740d2e9 | 824 | { |
750e0f57 | 825 | struct dentry *dir; |
b740d2e9 RB |
826 | |
827 | dir = debugfs_create_dir("pmc_core", NULL); | |
b740d2e9 | 828 | pmcdev->dbgfs_dir = dir; |
b740d2e9 | 829 | |
750e0f57 RB |
830 | debugfs_create_file("slp_s0_residency_usec", 0444, dir, pmcdev, |
831 | &pmc_core_dev_state); | |
b740d2e9 | 832 | |
6268c0b2 GK |
833 | if (pmcdev->map->pfear_sts) |
834 | debugfs_create_file("pch_ip_power_gating_status", 0444, dir, | |
835 | pmcdev, &pmc_core_ppfear_fops); | |
173943b3 | 836 | |
750e0f57 RB |
837 | debugfs_create_file("ltr_ignore", 0644, dir, pmcdev, |
838 | &pmc_core_ltr_ignore_ops); | |
9c2ee199 | 839 | |
cd89e92b | 840 | debugfs_create_file("ltr_show", 0444, dir, pmcdev, &pmc_core_ltr_fops); |
2eb15055 | 841 | |
8aba056a RB |
842 | debugfs_create_file("package_cstate_show", 0444, dir, pmcdev, |
843 | &pmc_core_pkgc_fops); | |
844 | ||
750e0f57 RB |
845 | if (pmcdev->map->pll_sts) |
846 | debugfs_create_file("pll_status", 0444, dir, pmcdev, | |
3b1f9955 | 847 | &pmc_core_pll_fops); |
9c2ee199 | 848 | |
750e0f57 RB |
849 | if (pmcdev->map->mphy_sts) |
850 | debugfs_create_file("mphy_core_lanes_power_gating_status", | |
851 | 0444, dir, pmcdev, | |
3b1f9955 | 852 | &pmc_core_mphy_pg_fops); |
0bdfaf42 | 853 | |
4cf2afd6 BD |
854 | if (pmcdev->map->slps0_dbg_maps) { |
855 | debugfs_create_file("slp_s0_debug_status", 0444, | |
856 | dir, pmcdev, | |
857 | &pmc_core_slps0_dbg_fops); | |
858 | ||
859 | debugfs_create_bool("slp_s0_dbg_latch", 0644, | |
860 | dir, &slps0_dbg_latch); | |
861 | } | |
0bdfaf42 RB |
862 | } |
863 | #else | |
15167554 | 864 | static inline void pmc_core_dbgfs_register(struct pmc_dev *pmcdev) |
0bdfaf42 | 865 | { |
0bdfaf42 RB |
866 | } |
867 | ||
868 | static inline void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev) | |
869 | { | |
b740d2e9 | 870 | } |
0bdfaf42 | 871 | #endif /* CONFIG_DEBUG_FS */ |
b740d2e9 RB |
872 | |
873 | static const struct x86_cpu_id intel_pmc_core_ids[] = { | |
af239c44 | 874 | INTEL_CPU_FAM6(SKYLAKE_L, spt_reg_map), |
c66f78a6 | 875 | INTEL_CPU_FAM6(SKYLAKE, spt_reg_map), |
af239c44 | 876 | INTEL_CPU_FAM6(KABYLAKE_L, spt_reg_map), |
c66f78a6 | 877 | INTEL_CPU_FAM6(KABYLAKE, spt_reg_map), |
af239c44 PZ |
878 | INTEL_CPU_FAM6(CANNONLAKE_L, cnp_reg_map), |
879 | INTEL_CPU_FAM6(ICELAKE_L, icl_reg_map), | |
66013e8e | 880 | INTEL_CPU_FAM6(ICELAKE_NNPI, icl_reg_map), |
5406327d GK |
881 | INTEL_CPU_FAM6(COMETLAKE, cnp_reg_map), |
882 | INTEL_CPU_FAM6(COMETLAKE_L, cnp_reg_map), | |
49a43794 GK |
883 | INTEL_CPU_FAM6(TIGERLAKE_L, tgl_reg_map), |
884 | INTEL_CPU_FAM6(TIGERLAKE, tgl_reg_map), | |
554f269f | 885 | INTEL_CPU_FAM6(ATOM_TREMONT, tgl_reg_map), |
b740d2e9 RB |
886 | {} |
887 | }; | |
888 | ||
21ae4357 SP |
889 | MODULE_DEVICE_TABLE(x86cpu, intel_pmc_core_ids); |
890 | ||
661405bd | 891 | static const struct pci_device_id pmc_pci_ids[] = { |
476bac56 AS |
892 | { PCI_VDEVICE(INTEL, SPT_PMC_PCI_DEVICE_ID) }, |
893 | { } | |
661405bd RB |
894 | }; |
895 | ||
238f9c11 RB |
896 | /* |
897 | * This quirk can be used on those platforms where | |
898 | * the platform BIOS enforces 24Mhx Crystal to shutdown | |
899 | * before PMC can assert SLP_S0#. | |
900 | */ | |
9ae11e23 | 901 | static int quirk_xtal_ignore(const struct dmi_system_id *id) |
238f9c11 RB |
902 | { |
903 | struct pmc_dev *pmcdev = &pmc; | |
904 | u32 value; | |
905 | ||
906 | value = pmc_core_reg_read(pmcdev, pmcdev->map->pm_vric1_offset); | |
907 | /* 24MHz Crystal Shutdown Qualification Disable */ | |
908 | value |= SPT_PMC_VRIC1_XTALSDQDIS; | |
909 | /* Low Voltage Mode Enable */ | |
910 | value &= ~SPT_PMC_VRIC1_SLPS0LVEN; | |
911 | pmc_core_reg_write(pmcdev, pmcdev->map->pm_vric1_offset, value); | |
912 | return 0; | |
913 | } | |
914 | ||
915 | static const struct dmi_system_id pmc_core_dmi_table[] = { | |
916 | { | |
917 | .callback = quirk_xtal_ignore, | |
918 | .ident = "HP Elite x2 1013 G3", | |
919 | .matches = { | |
920 | DMI_MATCH(DMI_SYS_VENDOR, "HP"), | |
921 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Elite x2 1013 G3"), | |
922 | }, | |
923 | }, | |
924 | {} | |
925 | }; | |
926 | ||
6c96a78c | 927 | static int pmc_core_probe(struct platform_device *pdev) |
b740d2e9 | 928 | { |
6c96a78c | 929 | static bool device_initialized; |
b740d2e9 RB |
930 | struct pmc_dev *pmcdev = &pmc; |
931 | const struct x86_cpu_id *cpu_id; | |
745698c3 | 932 | u64 slp_s0_addr; |
b740d2e9 | 933 | |
6c96a78c RJ |
934 | if (device_initialized) |
935 | return -ENODEV; | |
936 | ||
b740d2e9 | 937 | cpu_id = x86_match_cpu(intel_pmc_core_ids); |
21ae4357 SP |
938 | if (!cpu_id) |
939 | return -ENODEV; | |
940 | ||
941 | pmcdev->map = (struct pmc_reg_map *)cpu_id->driver_data; | |
745698c3 | 942 | |
661405bd | 943 | /* |
43e82d8a GK |
944 | * Coffee Lake has CPU ID of Kaby Lake and Cannon Lake PCH. So here |
945 | * Sunrisepoint PCH regmap can't be used. Use Cannon Lake PCH regmap | |
661405bd RB |
946 | * in this case. |
947 | */ | |
e50af833 | 948 | if (pmcdev->map == &spt_reg_map && !pci_dev_present(pmc_pci_ids)) |
661405bd RB |
949 | pmcdev->map = &cnp_reg_map; |
950 | ||
7d505758 | 951 | if (lpit_read_residency_count_address(&slp_s0_addr)) { |
745698c3 | 952 | pmcdev->base_addr = PMC_BASE_ADDR_DEFAULT; |
7d505758 VB |
953 | |
954 | if (page_is_ram(PHYS_PFN(pmcdev->base_addr))) | |
955 | return -ENODEV; | |
956 | } else { | |
745698c3 | 957 | pmcdev->base_addr = slp_s0_addr - pmcdev->map->slp_s0_offset; |
7d505758 | 958 | } |
745698c3 | 959 | |
21ae4357 SP |
960 | pmcdev->regbase = ioremap(pmcdev->base_addr, |
961 | pmcdev->map->regmap_length); | |
962 | if (!pmcdev->regbase) | |
b740d2e9 | 963 | return -ENOMEM; |
b740d2e9 | 964 | |
173943b3 | 965 | mutex_init(&pmcdev->lock); |
6c96a78c | 966 | platform_set_drvdata(pdev, pmcdev); |
c977b98b | 967 | pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(); |
6c96a78c | 968 | dmi_check_system(pmc_core_dmi_table); |
173943b3 | 969 | |
15167554 | 970 | pmc_core_dbgfs_register(pmcdev); |
b740d2e9 | 971 | |
6c96a78c RJ |
972 | device_initialized = true; |
973 | dev_info(&pdev->dev, " initialized\n"); | |
974 | ||
b740d2e9 RB |
975 | return 0; |
976 | } | |
977 | ||
6c96a78c | 978 | static int pmc_core_remove(struct platform_device *pdev) |
2854a0aa | 979 | { |
6c96a78c | 980 | struct pmc_dev *pmcdev = platform_get_drvdata(pdev); |
b740d2e9 | 981 | |
21ae4357 | 982 | pmc_core_dbgfs_unregister(pmcdev); |
6c96a78c | 983 | platform_set_drvdata(pdev, NULL); |
21ae4357 SP |
984 | mutex_destroy(&pmcdev->lock); |
985 | iounmap(pmcdev->regbase); | |
6c96a78c RJ |
986 | return 0; |
987 | } | |
988 | ||
2ac8d46d RJ |
989 | #ifdef CONFIG_PM_SLEEP |
990 | ||
991 | static bool warn_on_s0ix_failures; | |
992 | module_param(warn_on_s0ix_failures, bool, 0644); | |
993 | MODULE_PARM_DESC(warn_on_s0ix_failures, "Check and warn for S0ix failures"); | |
994 | ||
995 | static int pmc_core_suspend(struct device *dev) | |
996 | { | |
997 | struct pmc_dev *pmcdev = dev_get_drvdata(dev); | |
998 | ||
999 | pmcdev->check_counters = false; | |
1000 | ||
1001 | /* No warnings on S0ix failures */ | |
1002 | if (!warn_on_s0ix_failures) | |
1003 | return 0; | |
1004 | ||
1005 | /* Check if the syspend will actually use S0ix */ | |
1006 | if (pm_suspend_via_firmware()) | |
1007 | return 0; | |
1008 | ||
1009 | /* Save PC10 residency for checking later */ | |
1010 | if (rdmsrl_safe(MSR_PKG_C10_RESIDENCY, &pmcdev->pc10_counter)) | |
1011 | return -EIO; | |
1012 | ||
1013 | /* Save S0ix residency for checking later */ | |
1014 | if (pmc_core_dev_state_get(pmcdev, &pmcdev->s0ix_counter)) | |
1015 | return -EIO; | |
1016 | ||
1017 | pmcdev->check_counters = true; | |
1018 | return 0; | |
1019 | } | |
1020 | ||
1021 | static inline bool pmc_core_is_pc10_failed(struct pmc_dev *pmcdev) | |
1022 | { | |
1023 | u64 pc10_counter; | |
1024 | ||
1025 | if (rdmsrl_safe(MSR_PKG_C10_RESIDENCY, &pc10_counter)) | |
1026 | return false; | |
1027 | ||
1028 | if (pc10_counter == pmcdev->pc10_counter) | |
1029 | return true; | |
1030 | ||
1031 | return false; | |
1032 | } | |
1033 | ||
1034 | static inline bool pmc_core_is_s0ix_failed(struct pmc_dev *pmcdev) | |
1035 | { | |
1036 | u64 s0ix_counter; | |
1037 | ||
1038 | if (pmc_core_dev_state_get(pmcdev, &s0ix_counter)) | |
1039 | return false; | |
1040 | ||
1041 | if (s0ix_counter == pmcdev->s0ix_counter) | |
1042 | return true; | |
1043 | ||
1044 | return false; | |
1045 | } | |
1046 | ||
1047 | static int pmc_core_resume(struct device *dev) | |
1048 | { | |
1049 | struct pmc_dev *pmcdev = dev_get_drvdata(dev); | |
1050 | const struct pmc_bit_map **maps = pmcdev->map->slps0_dbg_maps; | |
1051 | int offset = pmcdev->map->slps0_dbg_offset; | |
1052 | const struct pmc_bit_map *map; | |
1053 | u32 data; | |
1054 | ||
1055 | if (!pmcdev->check_counters) | |
1056 | return 0; | |
1057 | ||
1058 | if (!pmc_core_is_s0ix_failed(pmcdev)) | |
1059 | return 0; | |
1060 | ||
1061 | if (pmc_core_is_pc10_failed(pmcdev)) { | |
1062 | /* S0ix failed because of PC10 entry failure */ | |
1063 | dev_info(dev, "CPU did not enter PC10!!! (PC10 cnt=0x%llx)\n", | |
1064 | pmcdev->pc10_counter); | |
1065 | return 0; | |
1066 | } | |
1067 | ||
1068 | /* The real interesting case - S0ix failed - lets ask PMC why. */ | |
1069 | dev_warn(dev, "CPU did not enter SLP_S0!!! (S0ix cnt=%llu)\n", | |
1070 | pmcdev->s0ix_counter); | |
1071 | while (*maps) { | |
1072 | map = *maps; | |
1073 | data = pmc_core_reg_read(pmcdev, offset); | |
1074 | offset += 4; | |
1075 | while (map->name) { | |
1076 | dev_dbg(dev, "SLP_S0_DBG: %-32s\tState: %s\n", | |
1077 | map->name, | |
1078 | data & map->bit_mask ? "Yes" : "No"); | |
1079 | map++; | |
1080 | } | |
1081 | maps++; | |
1082 | } | |
1083 | return 0; | |
1084 | } | |
1085 | ||
1086 | #endif | |
1087 | ||
1088 | static const struct dev_pm_ops pmc_core_pm_ops = { | |
1089 | SET_LATE_SYSTEM_SLEEP_PM_OPS(pmc_core_suspend, pmc_core_resume) | |
1090 | }; | |
1091 | ||
b02f6a2e RJ |
1092 | static const struct acpi_device_id pmc_core_acpi_ids[] = { |
1093 | {"INT33A1", 0}, /* _HID for Intel Power Engine, _CID PNP0D80*/ | |
1094 | { } | |
1095 | }; | |
1096 | MODULE_DEVICE_TABLE(acpi, pmc_core_acpi_ids); | |
1097 | ||
6c96a78c RJ |
1098 | static struct platform_driver pmc_core_driver = { |
1099 | .driver = { | |
1100 | .name = "intel_pmc_core", | |
b02f6a2e | 1101 | .acpi_match_table = ACPI_PTR(pmc_core_acpi_ids), |
2ac8d46d | 1102 | .pm = &pmc_core_pm_ops, |
6c96a78c RJ |
1103 | }, |
1104 | .probe = pmc_core_probe, | |
1105 | .remove = pmc_core_remove, | |
1106 | }; | |
1107 | ||
b02f6a2e | 1108 | module_platform_driver(pmc_core_driver); |
2854a0aa SP |
1109 | |
1110 | MODULE_LICENSE("GPL v2"); | |
1111 | MODULE_DESCRIPTION("Intel PMC Core Driver"); |