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