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