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> |
b740d2e9 | 18 | #include <linux/io.h> |
2854a0aa | 19 | #include <linux/module.h> |
661405bd | 20 | #include <linux/pci.h> |
9c2ee199 | 21 | #include <linux/uaccess.h> |
b740d2e9 RB |
22 | |
23 | #include <asm/cpu_device_id.h> | |
70e0d117 | 24 | #include <asm/intel-family.h> |
b740d2e9 RB |
25 | |
26 | #include "intel_pmc_core.h" | |
27 | ||
00f8b2fc RB |
28 | #define ICPU(model, data) \ |
29 | { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (kernel_ulong_t)data } | |
30 | ||
b740d2e9 RB |
31 | static struct pmc_dev pmc; |
32 | ||
fe748227 RB |
33 | static const struct pmc_bit_map spt_pll_map[] = { |
34 | {"MIPI PLL", SPT_PMC_BIT_MPHY_CMN_LANE0}, | |
35 | {"GEN2 USB2PCIE2 PLL", SPT_PMC_BIT_MPHY_CMN_LANE1}, | |
36 | {"DMIPCIE3 PLL", SPT_PMC_BIT_MPHY_CMN_LANE2}, | |
37 | {"SATA PLL", SPT_PMC_BIT_MPHY_CMN_LANE3}, | |
38 | {}, | |
39 | }; | |
40 | ||
173943b3 RB |
41 | static const struct pmc_bit_map spt_mphy_map[] = { |
42 | {"MPHY CORE LANE 0", SPT_PMC_BIT_MPHY_LANE0}, | |
43 | {"MPHY CORE LANE 1", SPT_PMC_BIT_MPHY_LANE1}, | |
44 | {"MPHY CORE LANE 2", SPT_PMC_BIT_MPHY_LANE2}, | |
45 | {"MPHY CORE LANE 3", SPT_PMC_BIT_MPHY_LANE3}, | |
46 | {"MPHY CORE LANE 4", SPT_PMC_BIT_MPHY_LANE4}, | |
47 | {"MPHY CORE LANE 5", SPT_PMC_BIT_MPHY_LANE5}, | |
48 | {"MPHY CORE LANE 6", SPT_PMC_BIT_MPHY_LANE6}, | |
49 | {"MPHY CORE LANE 7", SPT_PMC_BIT_MPHY_LANE7}, | |
50 | {"MPHY CORE LANE 8", SPT_PMC_BIT_MPHY_LANE8}, | |
51 | {"MPHY CORE LANE 9", SPT_PMC_BIT_MPHY_LANE9}, | |
52 | {"MPHY CORE LANE 10", SPT_PMC_BIT_MPHY_LANE10}, | |
53 | {"MPHY CORE LANE 11", SPT_PMC_BIT_MPHY_LANE11}, | |
54 | {"MPHY CORE LANE 12", SPT_PMC_BIT_MPHY_LANE12}, | |
55 | {"MPHY CORE LANE 13", SPT_PMC_BIT_MPHY_LANE13}, | |
56 | {"MPHY CORE LANE 14", SPT_PMC_BIT_MPHY_LANE14}, | |
57 | {"MPHY CORE LANE 15", SPT_PMC_BIT_MPHY_LANE15}, | |
58 | {}, | |
59 | }; | |
60 | ||
0bdfaf42 RB |
61 | static const struct pmc_bit_map spt_pfear_map[] = { |
62 | {"PMC", SPT_PMC_BIT_PMC}, | |
63 | {"OPI-DMI", SPT_PMC_BIT_OPI}, | |
64 | {"SPI / eSPI", SPT_PMC_BIT_SPI}, | |
65 | {"XHCI", SPT_PMC_BIT_XHCI}, | |
66 | {"SPA", SPT_PMC_BIT_SPA}, | |
67 | {"SPB", SPT_PMC_BIT_SPB}, | |
68 | {"SPC", SPT_PMC_BIT_SPC}, | |
69 | {"GBE", SPT_PMC_BIT_GBE}, | |
70 | {"SATA", SPT_PMC_BIT_SATA}, | |
71 | {"HDA-PGD0", SPT_PMC_BIT_HDA_PGD0}, | |
72 | {"HDA-PGD1", SPT_PMC_BIT_HDA_PGD1}, | |
73 | {"HDA-PGD2", SPT_PMC_BIT_HDA_PGD2}, | |
74 | {"HDA-PGD3", SPT_PMC_BIT_HDA_PGD3}, | |
75 | {"RSVD", SPT_PMC_BIT_RSVD_0B}, | |
76 | {"LPSS", SPT_PMC_BIT_LPSS}, | |
77 | {"LPC", SPT_PMC_BIT_LPC}, | |
78 | {"SMB", SPT_PMC_BIT_SMB}, | |
79 | {"ISH", SPT_PMC_BIT_ISH}, | |
80 | {"P2SB", SPT_PMC_BIT_P2SB}, | |
81 | {"DFX", SPT_PMC_BIT_DFX}, | |
82 | {"SCC", SPT_PMC_BIT_SCC}, | |
83 | {"RSVD", SPT_PMC_BIT_RSVD_0C}, | |
84 | {"FUSE", SPT_PMC_BIT_FUSE}, | |
85 | {"CAMERA", SPT_PMC_BIT_CAMREA}, | |
86 | {"RSVD", SPT_PMC_BIT_RSVD_0D}, | |
87 | {"USB3-OTG", SPT_PMC_BIT_USB3_OTG}, | |
88 | {"EXI", SPT_PMC_BIT_EXI}, | |
89 | {"CSE", SPT_PMC_BIT_CSE}, | |
90 | {"CSME_KVM", SPT_PMC_BIT_CSME_KVM}, | |
91 | {"CSME_PMT", SPT_PMC_BIT_CSME_PMT}, | |
92 | {"CSME_CLINK", SPT_PMC_BIT_CSME_CLINK}, | |
93 | {"CSME_PTIO", SPT_PMC_BIT_CSME_PTIO}, | |
94 | {"CSME_USBR", SPT_PMC_BIT_CSME_USBR}, | |
95 | {"CSME_SUSRAM", SPT_PMC_BIT_CSME_SUSRAM}, | |
96 | {"CSME_SMT", SPT_PMC_BIT_CSME_SMT}, | |
97 | {"RSVD", SPT_PMC_BIT_RSVD_1A}, | |
98 | {"CSME_SMS2", SPT_PMC_BIT_CSME_SMS2}, | |
99 | {"CSME_SMS1", SPT_PMC_BIT_CSME_SMS1}, | |
100 | {"CSME_RTC", SPT_PMC_BIT_CSME_RTC}, | |
101 | {"CSME_PSF", SPT_PMC_BIT_CSME_PSF}, | |
102 | {}, | |
103 | }; | |
104 | ||
2eb15055 RB |
105 | static const struct pmc_bit_map spt_ltr_show_map[] = { |
106 | {"SOUTHPORT_A", SPT_PMC_LTR_SPA}, | |
107 | {"SOUTHPORT_B", SPT_PMC_LTR_SPB}, | |
108 | {"SATA", SPT_PMC_LTR_SATA}, | |
109 | {"GIGABIT_ETHERNET", SPT_PMC_LTR_GBE}, | |
110 | {"XHCI", SPT_PMC_LTR_XHCI}, | |
111 | {"ME", SPT_PMC_LTR_ME}, | |
112 | /* EVA is Enterprise Value Add, doesn't really exist on PCH */ | |
113 | {"EVA", SPT_PMC_LTR_EVA}, | |
114 | {"SOUTHPORT_C", SPT_PMC_LTR_SPC}, | |
115 | {"HD_AUDIO", SPT_PMC_LTR_AZ}, | |
116 | {"LPSS", SPT_PMC_LTR_LPSS}, | |
117 | {"SOUTHPORT_D", SPT_PMC_LTR_SPD}, | |
118 | {"SOUTHPORT_E", SPT_PMC_LTR_SPE}, | |
119 | {"CAMERA", SPT_PMC_LTR_CAM}, | |
120 | {"ESPI", SPT_PMC_LTR_ESPI}, | |
121 | {"SCC", SPT_PMC_LTR_SCC}, | |
122 | {"ISH", SPT_PMC_LTR_ISH}, | |
123 | /* Below two cannot be used for LTR_IGNORE */ | |
124 | {"CURRENT_PLATFORM", SPT_PMC_LTR_CUR_PLT}, | |
125 | {"AGGREGATED_SYSTEM", SPT_PMC_LTR_CUR_ASLT}, | |
126 | {} | |
127 | }; | |
128 | ||
0bdfaf42 RB |
129 | static const struct pmc_reg_map spt_reg_map = { |
130 | .pfear_sts = spt_pfear_map, | |
173943b3 | 131 | .mphy_sts = spt_mphy_map, |
fe748227 | 132 | .pll_sts = spt_pll_map, |
2eb15055 | 133 | .ltr_show_sts = spt_ltr_show_map, |
c977b98b SP |
134 | .slp_s0_offset = SPT_PMC_SLP_S0_RES_COUNTER_OFFSET, |
135 | .ltr_ignore_offset = SPT_PMC_LTR_IGNORE_OFFSET, | |
136 | .regmap_length = SPT_PMC_MMIO_REG_LEN, | |
137 | .ppfear0_offset = SPT_PMC_XRAM_PPFEAR0A, | |
138 | .ppfear_buckets = SPT_PPFEAR_NUM_ENTRIES, | |
139 | .pm_cfg_offset = SPT_PMC_PM_CFG_OFFSET, | |
140 | .pm_read_disable_bit = SPT_PMC_READ_DISABLE_BIT, | |
2d649d97 | 141 | .ltr_ignore_max = SPT_NUM_IP_IGN_ALLOWED, |
0bdfaf42 RB |
142 | }; |
143 | ||
291101f6 RB |
144 | /* Cannonlake: PGD PFET Enable Ack Status Register(s) bitmap */ |
145 | static const struct pmc_bit_map cnp_pfear_map[] = { | |
146 | {"PMC", BIT(0)}, | |
147 | {"OPI-DMI", BIT(1)}, | |
148 | {"SPI/eSPI", BIT(2)}, | |
149 | {"XHCI", BIT(3)}, | |
150 | {"SPA", BIT(4)}, | |
151 | {"SPB", BIT(5)}, | |
152 | {"SPC", BIT(6)}, | |
153 | {"GBE", BIT(7)}, | |
154 | ||
155 | {"SATA", BIT(0)}, | |
156 | {"HDA_PGD0", BIT(1)}, | |
157 | {"HDA_PGD1", BIT(2)}, | |
158 | {"HDA_PGD2", BIT(3)}, | |
159 | {"HDA_PGD3", BIT(4)}, | |
160 | {"SPD", BIT(5)}, | |
161 | {"LPSS", BIT(6)}, | |
162 | {"LPC", BIT(7)}, | |
163 | ||
164 | {"SMB", BIT(0)}, | |
165 | {"ISH", BIT(1)}, | |
166 | {"P2SB", BIT(2)}, | |
167 | {"NPK_VNN", BIT(3)}, | |
168 | {"SDX", BIT(4)}, | |
169 | {"SPE", BIT(5)}, | |
170 | {"Fuse", BIT(6)}, | |
171 | {"Res_23", BIT(7)}, | |
172 | ||
173 | {"CSME_FSC", BIT(0)}, | |
174 | {"USB3_OTG", BIT(1)}, | |
175 | {"EXI", BIT(2)}, | |
176 | {"CSE", BIT(3)}, | |
177 | {"csme_kvm", BIT(4)}, | |
178 | {"csme_pmt", BIT(5)}, | |
179 | {"csme_clink", BIT(6)}, | |
180 | {"csme_ptio", BIT(7)}, | |
181 | ||
182 | {"csme_usbr", BIT(0)}, | |
183 | {"csme_susram", BIT(1)}, | |
184 | {"csme_smt1", BIT(2)}, | |
185 | {"CSME_SMT4", BIT(3)}, | |
186 | {"csme_sms2", BIT(4)}, | |
187 | {"csme_sms1", BIT(5)}, | |
188 | {"csme_rtc", BIT(6)}, | |
189 | {"csme_psf", BIT(7)}, | |
190 | ||
191 | {"SBR0", BIT(0)}, | |
192 | {"SBR1", BIT(1)}, | |
193 | {"SBR2", BIT(2)}, | |
194 | {"SBR3", BIT(3)}, | |
195 | {"SBR4", BIT(4)}, | |
196 | {"SBR5", BIT(5)}, | |
197 | {"CSME_PECI", BIT(6)}, | |
198 | {"PSF1", BIT(7)}, | |
199 | ||
200 | {"PSF2", BIT(0)}, | |
201 | {"PSF3", BIT(1)}, | |
202 | {"PSF4", BIT(2)}, | |
203 | {"CNVI", BIT(3)}, | |
204 | {"UFS0", BIT(4)}, | |
205 | {"EMMC", BIT(5)}, | |
d6827015 | 206 | {"SPF", BIT(6)}, |
291101f6 RB |
207 | {"SBR6", BIT(7)}, |
208 | ||
209 | {"SBR7", BIT(0)}, | |
210 | {"NPK_AON", BIT(1)}, | |
211 | {"HDA_PGD4", BIT(2)}, | |
212 | {"HDA_PGD5", BIT(3)}, | |
213 | {"HDA_PGD6", BIT(4)}, | |
214 | {} | |
215 | }; | |
216 | ||
4cf2afd6 BD |
217 | static const struct pmc_bit_map cnp_slps0_dbg0_map[] = { |
218 | {"AUDIO_D3", BIT(0)}, | |
219 | {"OTG_D3", BIT(1)}, | |
220 | {"XHCI_D3", BIT(2)}, | |
221 | {"LPIO_D3", BIT(3)}, | |
222 | {"SDX_D3", BIT(4)}, | |
223 | {"SATA_D3", BIT(5)}, | |
224 | {"UFS0_D3", BIT(6)}, | |
225 | {"UFS1_D3", BIT(7)}, | |
226 | {"EMMC_D3", BIT(8)}, | |
227 | {} | |
228 | }; | |
229 | ||
230 | static const struct pmc_bit_map cnp_slps0_dbg1_map[] = { | |
231 | {"SDIO_PLL_OFF", BIT(0)}, | |
232 | {"USB2_PLL_OFF", BIT(1)}, | |
233 | {"AUDIO_PLL_OFF", BIT(2)}, | |
234 | {"OC_PLL_OFF", BIT(3)}, | |
235 | {"MAIN_PLL_OFF", BIT(4)}, | |
236 | {"XOSC_OFF", BIT(5)}, | |
237 | {"LPC_CLKS_GATED", BIT(6)}, | |
238 | {"PCIE_CLKREQS_IDLE", BIT(7)}, | |
239 | {"AUDIO_ROSC_OFF", BIT(8)}, | |
240 | {"HPET_XOSC_CLK_REQ", BIT(9)}, | |
241 | {"PMC_ROSC_SLOW_CLK", BIT(10)}, | |
242 | {"AON2_ROSC_GATED", BIT(11)}, | |
243 | {"CLKACKS_DEASSERTED", BIT(12)}, | |
244 | {} | |
245 | }; | |
246 | ||
247 | static const struct pmc_bit_map cnp_slps0_dbg2_map[] = { | |
248 | {"MPHY_CORE_GATED", BIT(0)}, | |
249 | {"CSME_GATED", BIT(1)}, | |
250 | {"USB2_SUS_GATED", BIT(2)}, | |
251 | {"DYN_FLEX_IO_IDLE", BIT(3)}, | |
252 | {"GBE_NO_LINK", BIT(4)}, | |
253 | {"THERM_SEN_DISABLED", BIT(5)}, | |
254 | {"PCIE_LOW_POWER", BIT(6)}, | |
255 | {"ISH_VNNAON_REQ_ACT", BIT(7)}, | |
256 | {"ISH_VNN_REQ_ACT", BIT(8)}, | |
257 | {"CNV_VNNAON_REQ_ACT", BIT(9)}, | |
258 | {"CNV_VNN_REQ_ACT", BIT(10)}, | |
259 | {"NPK_VNNON_REQ_ACT", BIT(11)}, | |
260 | {"PMSYNC_STATE_IDLE", BIT(12)}, | |
261 | {"ALST_GT_THRES", BIT(13)}, | |
262 | {"PMC_ARC_PG_READY", BIT(14)}, | |
263 | {} | |
264 | }; | |
265 | ||
266 | static const struct pmc_bit_map *cnp_slps0_dbg_maps[] = { | |
267 | cnp_slps0_dbg0_map, | |
268 | cnp_slps0_dbg1_map, | |
269 | cnp_slps0_dbg2_map, | |
270 | NULL, | |
271 | }; | |
272 | ||
2eb15055 RB |
273 | static const struct pmc_bit_map cnp_ltr_show_map[] = { |
274 | {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, | |
275 | {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, | |
276 | {"SATA", CNP_PMC_LTR_SATA}, | |
277 | {"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE}, | |
278 | {"XHCI", CNP_PMC_LTR_XHCI}, | |
279 | {"ME", CNP_PMC_LTR_ME}, | |
280 | /* EVA is Enterprise Value Add, doesn't really exist on PCH */ | |
281 | {"EVA", CNP_PMC_LTR_EVA}, | |
282 | {"SOUTHPORT_C", CNP_PMC_LTR_SPC}, | |
283 | {"HD_AUDIO", CNP_PMC_LTR_AZ}, | |
284 | {"CNV", CNP_PMC_LTR_CNV}, | |
285 | {"LPSS", CNP_PMC_LTR_LPSS}, | |
286 | {"SOUTHPORT_D", CNP_PMC_LTR_SPD}, | |
287 | {"SOUTHPORT_E", CNP_PMC_LTR_SPE}, | |
288 | {"CAMERA", CNP_PMC_LTR_CAM}, | |
289 | {"ESPI", CNP_PMC_LTR_ESPI}, | |
290 | {"SCC", CNP_PMC_LTR_SCC}, | |
291 | {"ISH", CNP_PMC_LTR_ISH}, | |
292 | {"UFSX2", CNP_PMC_LTR_UFSX2}, | |
293 | {"EMMC", CNP_PMC_LTR_EMMC}, | |
294 | /* Below two cannot be used for LTR_IGNORE */ | |
295 | {"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT}, | |
296 | {"AGGREGATED_SYSTEM", CNP_PMC_LTR_CUR_ASLT}, | |
297 | {} | |
298 | }; | |
299 | ||
291101f6 RB |
300 | static const struct pmc_reg_map cnp_reg_map = { |
301 | .pfear_sts = cnp_pfear_map, | |
302 | .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, | |
4cf2afd6 | 303 | .slps0_dbg_maps = cnp_slps0_dbg_maps, |
2eb15055 | 304 | .ltr_show_sts = cnp_ltr_show_map, |
4cf2afd6 | 305 | .slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET, |
291101f6 RB |
306 | .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, |
307 | .regmap_length = CNP_PMC_MMIO_REG_LEN, | |
308 | .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, | |
309 | .ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES, | |
310 | .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, | |
311 | .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, | |
2d649d97 | 312 | .ltr_ignore_max = CNP_NUM_IP_IGN_ALLOWED, |
291101f6 RB |
313 | }; |
314 | ||
0bdfaf42 RB |
315 | static inline u8 pmc_core_reg_read_byte(struct pmc_dev *pmcdev, int offset) |
316 | { | |
317 | return readb(pmcdev->regbase + offset); | |
318 | } | |
319 | ||
b740d2e9 RB |
320 | static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset) |
321 | { | |
322 | return readl(pmcdev->regbase + reg_offset); | |
323 | } | |
324 | ||
173943b3 RB |
325 | static inline void pmc_core_reg_write(struct pmc_dev *pmcdev, int |
326 | reg_offset, u32 val) | |
327 | { | |
328 | writel(val, pmcdev->regbase + reg_offset); | |
329 | } | |
330 | ||
b740d2e9 RB |
331 | static inline u32 pmc_core_adjust_slp_s0_step(u32 value) |
332 | { | |
333 | return value * SPT_PMC_SLP_S0_RES_COUNTER_STEP; | |
334 | } | |
335 | ||
df2294fb | 336 | static int pmc_core_dev_state_get(void *data, u64 *val) |
b740d2e9 | 337 | { |
df2294fb | 338 | struct pmc_dev *pmcdev = data; |
c977b98b | 339 | const struct pmc_reg_map *map = pmcdev->map; |
df2294fb | 340 | u32 value; |
b740d2e9 | 341 | |
c977b98b | 342 | value = pmc_core_reg_read(pmcdev, map->slp_s0_offset); |
df2294fb | 343 | *val = pmc_core_adjust_slp_s0_step(value); |
b740d2e9 RB |
344 | |
345 | return 0; | |
346 | } | |
347 | ||
df2294fb | 348 | DEFINE_DEBUGFS_ATTRIBUTE(pmc_core_dev_state, pmc_core_dev_state_get, NULL, "%llu\n"); |
b740d2e9 | 349 | |
173943b3 RB |
350 | static int pmc_core_check_read_lock_bit(void) |
351 | { | |
352 | struct pmc_dev *pmcdev = &pmc; | |
353 | u32 value; | |
354 | ||
c977b98b SP |
355 | value = pmc_core_reg_read(pmcdev, pmcdev->map->pm_cfg_offset); |
356 | return value & BIT(pmcdev->map->pm_read_disable_bit); | |
173943b3 RB |
357 | } |
358 | ||
0bdfaf42 | 359 | #if IS_ENABLED(CONFIG_DEBUG_FS) |
4cf2afd6 BD |
360 | static bool slps0_dbg_latch; |
361 | ||
0bdfaf42 RB |
362 | static void pmc_core_display_map(struct seq_file *s, int index, |
363 | u8 pf_reg, const struct pmc_bit_map *pf_map) | |
364 | { | |
365 | seq_printf(s, "PCH IP: %-2d - %-32s\tState: %s\n", | |
366 | index, pf_map[index].name, | |
367 | pf_map[index].bit_mask & pf_reg ? "Off" : "On"); | |
368 | } | |
369 | ||
3b1f9955 | 370 | static int pmc_core_ppfear_show(struct seq_file *s, void *unused) |
0bdfaf42 RB |
371 | { |
372 | struct pmc_dev *pmcdev = s->private; | |
373 | const struct pmc_bit_map *map = pmcdev->map->pfear_sts; | |
c977b98b | 374 | u8 pf_regs[PPFEAR_MAX_NUM_ENTRIES]; |
0bdfaf42 RB |
375 | int index, iter; |
376 | ||
c977b98b | 377 | iter = pmcdev->map->ppfear0_offset; |
0bdfaf42 | 378 | |
c977b98b SP |
379 | for (index = 0; index < pmcdev->map->ppfear_buckets && |
380 | index < PPFEAR_MAX_NUM_ENTRIES; index++, iter++) | |
0bdfaf42 RB |
381 | pf_regs[index] = pmc_core_reg_read_byte(pmcdev, iter); |
382 | ||
0e68eeea RB |
383 | for (index = 0; map[index].name && |
384 | index < pmcdev->map->ppfear_buckets * 8; index++) | |
0bdfaf42 RB |
385 | pmc_core_display_map(s, index, pf_regs[index / 8], map); |
386 | ||
387 | return 0; | |
388 | } | |
3b1f9955 | 389 | DEFINE_SHOW_ATTRIBUTE(pmc_core_ppfear); |
0bdfaf42 | 390 | |
173943b3 RB |
391 | /* This function should return link status, 0 means ready */ |
392 | static int pmc_core_mtpmc_link_status(void) | |
393 | { | |
394 | struct pmc_dev *pmcdev = &pmc; | |
395 | u32 value; | |
396 | ||
397 | value = pmc_core_reg_read(pmcdev, SPT_PMC_PM_STS_OFFSET); | |
4f24ecff | 398 | return value & BIT(SPT_PMC_MSG_FULL_STS_BIT); |
173943b3 RB |
399 | } |
400 | ||
401 | static int pmc_core_send_msg(u32 *addr_xram) | |
402 | { | |
403 | struct pmc_dev *pmcdev = &pmc; | |
404 | u32 dest; | |
405 | int timeout; | |
406 | ||
407 | for (timeout = NUM_RETRIES; timeout > 0; timeout--) { | |
408 | if (pmc_core_mtpmc_link_status() == 0) | |
409 | break; | |
410 | msleep(5); | |
411 | } | |
412 | ||
413 | if (timeout <= 0 && pmc_core_mtpmc_link_status()) | |
414 | return -EBUSY; | |
415 | ||
416 | dest = (*addr_xram & MTPMC_MASK) | (1U << 1); | |
417 | pmc_core_reg_write(pmcdev, SPT_PMC_MTPMC_OFFSET, dest); | |
418 | return 0; | |
419 | } | |
420 | ||
3b1f9955 | 421 | static int pmc_core_mphy_pg_show(struct seq_file *s, void *unused) |
173943b3 RB |
422 | { |
423 | struct pmc_dev *pmcdev = s->private; | |
424 | const struct pmc_bit_map *map = pmcdev->map->mphy_sts; | |
425 | u32 mphy_core_reg_low, mphy_core_reg_high; | |
426 | u32 val_low, val_high; | |
427 | int index, err = 0; | |
428 | ||
429 | if (pmcdev->pmc_xram_read_bit) { | |
430 | seq_puts(s, "Access denied: please disable PMC_READ_DISABLE setting in BIOS."); | |
431 | return 0; | |
432 | } | |
433 | ||
434 | mphy_core_reg_low = (SPT_PMC_MPHY_CORE_STS_0 << 16); | |
435 | mphy_core_reg_high = (SPT_PMC_MPHY_CORE_STS_1 << 16); | |
436 | ||
437 | mutex_lock(&pmcdev->lock); | |
438 | ||
439 | if (pmc_core_send_msg(&mphy_core_reg_low) != 0) { | |
440 | err = -EBUSY; | |
441 | goto out_unlock; | |
442 | } | |
443 | ||
444 | msleep(10); | |
445 | val_low = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET); | |
446 | ||
447 | if (pmc_core_send_msg(&mphy_core_reg_high) != 0) { | |
448 | err = -EBUSY; | |
449 | goto out_unlock; | |
450 | } | |
451 | ||
452 | msleep(10); | |
453 | val_high = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET); | |
454 | ||
455 | for (index = 0; map[index].name && index < 8; index++) { | |
456 | seq_printf(s, "%-32s\tState: %s\n", | |
457 | map[index].name, | |
458 | map[index].bit_mask & val_low ? "Not power gated" : | |
459 | "Power gated"); | |
460 | } | |
461 | ||
462 | for (index = 8; map[index].name; index++) { | |
463 | seq_printf(s, "%-32s\tState: %s\n", | |
464 | map[index].name, | |
465 | map[index].bit_mask & val_high ? "Not power gated" : | |
466 | "Power gated"); | |
467 | } | |
468 | ||
469 | out_unlock: | |
470 | mutex_unlock(&pmcdev->lock); | |
471 | return err; | |
472 | } | |
3b1f9955 | 473 | DEFINE_SHOW_ATTRIBUTE(pmc_core_mphy_pg); |
173943b3 | 474 | |
fe748227 RB |
475 | static int pmc_core_pll_show(struct seq_file *s, void *unused) |
476 | { | |
477 | struct pmc_dev *pmcdev = s->private; | |
478 | const struct pmc_bit_map *map = pmcdev->map->pll_sts; | |
479 | u32 mphy_common_reg, val; | |
480 | int index, err = 0; | |
481 | ||
482 | if (pmcdev->pmc_xram_read_bit) { | |
483 | seq_puts(s, "Access denied: please disable PMC_READ_DISABLE setting in BIOS."); | |
484 | return 0; | |
485 | } | |
486 | ||
487 | mphy_common_reg = (SPT_PMC_MPHY_COM_STS_0 << 16); | |
488 | mutex_lock(&pmcdev->lock); | |
489 | ||
490 | if (pmc_core_send_msg(&mphy_common_reg) != 0) { | |
491 | err = -EBUSY; | |
492 | goto out_unlock; | |
493 | } | |
494 | ||
495 | /* Observed PMC HW response latency for MTPMC-MFPMC is ~10 ms */ | |
496 | msleep(10); | |
497 | val = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET); | |
498 | ||
499 | for (index = 0; map[index].name ; index++) { | |
500 | seq_printf(s, "%-32s\tState: %s\n", | |
501 | map[index].name, | |
502 | map[index].bit_mask & val ? "Active" : "Idle"); | |
503 | } | |
504 | ||
505 | out_unlock: | |
506 | mutex_unlock(&pmcdev->lock); | |
507 | return err; | |
508 | } | |
3b1f9955 | 509 | DEFINE_SHOW_ATTRIBUTE(pmc_core_pll); |
fe748227 | 510 | |
9c2ee199 RB |
511 | static ssize_t pmc_core_ltr_ignore_write(struct file *file, const char __user |
512 | *userbuf, size_t count, loff_t *ppos) | |
513 | { | |
514 | struct pmc_dev *pmcdev = &pmc; | |
c977b98b | 515 | const struct pmc_reg_map *map = pmcdev->map; |
9c2ee199 RB |
516 | u32 val, buf_size, fd; |
517 | int err = 0; | |
518 | ||
519 | buf_size = count < 64 ? count : 64; | |
520 | mutex_lock(&pmcdev->lock); | |
521 | ||
522 | if (kstrtou32_from_user(userbuf, buf_size, 10, &val)) { | |
523 | err = -EFAULT; | |
524 | goto out_unlock; | |
525 | } | |
526 | ||
2d649d97 | 527 | if (val > map->ltr_ignore_max) { |
9c2ee199 RB |
528 | err = -EINVAL; |
529 | goto out_unlock; | |
530 | } | |
531 | ||
c977b98b | 532 | fd = pmc_core_reg_read(pmcdev, map->ltr_ignore_offset); |
9c2ee199 | 533 | fd |= (1U << val); |
c977b98b | 534 | pmc_core_reg_write(pmcdev, map->ltr_ignore_offset, fd); |
9c2ee199 RB |
535 | |
536 | out_unlock: | |
537 | mutex_unlock(&pmcdev->lock); | |
538 | return err == 0 ? count : err; | |
539 | } | |
540 | ||
541 | static int pmc_core_ltr_ignore_show(struct seq_file *s, void *unused) | |
542 | { | |
543 | return 0; | |
544 | } | |
545 | ||
546 | static int pmc_core_ltr_ignore_open(struct inode *inode, struct file *file) | |
547 | { | |
548 | return single_open(file, pmc_core_ltr_ignore_show, inode->i_private); | |
549 | } | |
550 | ||
551 | static const struct file_operations pmc_core_ltr_ignore_ops = { | |
552 | .open = pmc_core_ltr_ignore_open, | |
553 | .read = seq_read, | |
554 | .write = pmc_core_ltr_ignore_write, | |
555 | .llseek = seq_lseek, | |
556 | .release = single_release, | |
557 | }; | |
558 | ||
4cf2afd6 BD |
559 | static void pmc_core_slps0_dbg_latch(struct pmc_dev *pmcdev, bool reset) |
560 | { | |
561 | const struct pmc_reg_map *map = pmcdev->map; | |
562 | u32 fd; | |
563 | ||
564 | mutex_lock(&pmcdev->lock); | |
565 | ||
566 | if (!reset && !slps0_dbg_latch) | |
567 | goto out_unlock; | |
568 | ||
569 | fd = pmc_core_reg_read(pmcdev, map->slps0_dbg_offset); | |
570 | if (reset) | |
571 | fd &= ~CNP_PMC_LATCH_SLPS0_EVENTS; | |
572 | else | |
573 | fd |= CNP_PMC_LATCH_SLPS0_EVENTS; | |
574 | pmc_core_reg_write(pmcdev, map->slps0_dbg_offset, fd); | |
575 | ||
576 | slps0_dbg_latch = 0; | |
577 | ||
578 | out_unlock: | |
579 | mutex_unlock(&pmcdev->lock); | |
580 | } | |
581 | ||
582 | static int pmc_core_slps0_dbg_show(struct seq_file *s, void *unused) | |
583 | { | |
584 | struct pmc_dev *pmcdev = s->private; | |
585 | const struct pmc_bit_map **maps = pmcdev->map->slps0_dbg_maps; | |
586 | const struct pmc_bit_map *map; | |
587 | int offset; | |
588 | u32 data; | |
589 | ||
590 | pmc_core_slps0_dbg_latch(pmcdev, false); | |
591 | offset = pmcdev->map->slps0_dbg_offset; | |
592 | while (*maps) { | |
593 | map = *maps; | |
594 | data = pmc_core_reg_read(pmcdev, offset); | |
595 | offset += 4; | |
596 | while (map->name) { | |
597 | seq_printf(s, "SLP_S0_DBG: %-32s\tState: %s\n", | |
598 | map->name, | |
599 | data & map->bit_mask ? | |
600 | "Yes" : "No"); | |
601 | ++map; | |
602 | } | |
603 | ++maps; | |
604 | } | |
605 | pmc_core_slps0_dbg_latch(pmcdev, true); | |
606 | return 0; | |
607 | } | |
608 | DEFINE_SHOW_ATTRIBUTE(pmc_core_slps0_dbg); | |
609 | ||
8122e7cd RB |
610 | static u32 convert_ltr_scale(u32 val) |
611 | { | |
612 | /* | |
613 | * As per PCIE specification supporting document | |
614 | * ECN_LatencyTolnReporting_14Aug08.pdf the Latency | |
615 | * Tolerance Reporting data payload is encoded in a | |
616 | * 3 bit scale and 10 bit value fields. Values are | |
617 | * multiplied by the indicated scale to yield an absolute time | |
618 | * value, expressible in a range from 1 nanosecond to | |
619 | * 2^25*(2^10-1) = 34,326,183,936 nanoseconds. | |
620 | * | |
621 | * scale encoding is as follows: | |
622 | * | |
623 | * ---------------------------------------------- | |
624 | * |scale factor | Multiplier (ns) | | |
625 | * ---------------------------------------------- | |
626 | * | 0 | 1 | | |
627 | * | 1 | 32 | | |
628 | * | 2 | 1024 | | |
629 | * | 3 | 32768 | | |
630 | * | 4 | 1048576 | | |
631 | * | 5 | 33554432 | | |
632 | * | 6 | Invalid | | |
633 | * | 7 | Invalid | | |
634 | * ---------------------------------------------- | |
635 | */ | |
636 | if (val > 5) { | |
637 | pr_warn("Invalid LTR scale factor.\n"); | |
638 | return 0; | |
639 | } | |
640 | ||
641 | return 1U << (5 * val); | |
642 | } | |
643 | ||
2eb15055 RB |
644 | static int pmc_core_ltr_show(struct seq_file *s, void *unused) |
645 | { | |
646 | struct pmc_dev *pmcdev = s->private; | |
647 | const struct pmc_bit_map *map = pmcdev->map->ltr_show_sts; | |
8122e7cd RB |
648 | u64 decoded_snoop_ltr, decoded_non_snoop_ltr; |
649 | u32 ltr_raw_data, scale, val; | |
650 | u16 snoop_ltr, nonsnoop_ltr; | |
2eb15055 RB |
651 | int index; |
652 | ||
653 | for (index = 0; map[index].name ; index++) { | |
8122e7cd RB |
654 | decoded_snoop_ltr = decoded_non_snoop_ltr = 0; |
655 | ltr_raw_data = pmc_core_reg_read(pmcdev, | |
656 | map[index].bit_mask); | |
657 | snoop_ltr = ltr_raw_data & ~MTPMC_MASK; | |
658 | nonsnoop_ltr = (ltr_raw_data >> 0x10) & ~MTPMC_MASK; | |
659 | ||
660 | if (FIELD_GET(LTR_REQ_NONSNOOP, ltr_raw_data)) { | |
661 | scale = FIELD_GET(LTR_DECODED_SCALE, nonsnoop_ltr); | |
662 | val = FIELD_GET(LTR_DECODED_VAL, nonsnoop_ltr); | |
663 | decoded_non_snoop_ltr = val * convert_ltr_scale(scale); | |
664 | } | |
665 | ||
666 | if (FIELD_GET(LTR_REQ_SNOOP, ltr_raw_data)) { | |
667 | scale = FIELD_GET(LTR_DECODED_SCALE, snoop_ltr); | |
668 | val = FIELD_GET(LTR_DECODED_VAL, snoop_ltr); | |
669 | decoded_snoop_ltr = val * convert_ltr_scale(scale); | |
670 | } | |
671 | ||
672 | seq_printf(s, "%-32s\tLTR: RAW: 0x%-16x\tNon-Snoop(ns): %-16llu\tSnoop(ns): %-16llu\n", | |
673 | map[index].name, ltr_raw_data, | |
674 | decoded_non_snoop_ltr, | |
675 | decoded_snoop_ltr); | |
2eb15055 RB |
676 | } |
677 | return 0; | |
678 | } | |
679 | DEFINE_SHOW_ATTRIBUTE(pmc_core_ltr); | |
680 | ||
b740d2e9 RB |
681 | static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev) |
682 | { | |
683 | debugfs_remove_recursive(pmcdev->dbgfs_dir); | |
684 | } | |
685 | ||
686 | static int pmc_core_dbgfs_register(struct pmc_dev *pmcdev) | |
687 | { | |
750e0f57 | 688 | struct dentry *dir; |
b740d2e9 RB |
689 | |
690 | dir = debugfs_create_dir("pmc_core", NULL); | |
127595ed | 691 | if (!dir) |
b740d2e9 RB |
692 | return -ENOMEM; |
693 | ||
694 | pmcdev->dbgfs_dir = dir; | |
b740d2e9 | 695 | |
750e0f57 RB |
696 | debugfs_create_file("slp_s0_residency_usec", 0444, dir, pmcdev, |
697 | &pmc_core_dev_state); | |
b740d2e9 | 698 | |
750e0f57 | 699 | debugfs_create_file("pch_ip_power_gating_status", 0444, dir, pmcdev, |
3b1f9955 | 700 | &pmc_core_ppfear_fops); |
173943b3 | 701 | |
750e0f57 RB |
702 | debugfs_create_file("ltr_ignore", 0644, dir, pmcdev, |
703 | &pmc_core_ltr_ignore_ops); | |
9c2ee199 | 704 | |
2eb15055 RB |
705 | debugfs_create_file("ltr_show", 0644, dir, pmcdev, &pmc_core_ltr_fops); |
706 | ||
750e0f57 RB |
707 | if (pmcdev->map->pll_sts) |
708 | debugfs_create_file("pll_status", 0444, dir, pmcdev, | |
3b1f9955 | 709 | &pmc_core_pll_fops); |
9c2ee199 | 710 | |
750e0f57 RB |
711 | if (pmcdev->map->mphy_sts) |
712 | debugfs_create_file("mphy_core_lanes_power_gating_status", | |
713 | 0444, dir, pmcdev, | |
3b1f9955 | 714 | &pmc_core_mphy_pg_fops); |
0bdfaf42 | 715 | |
4cf2afd6 BD |
716 | if (pmcdev->map->slps0_dbg_maps) { |
717 | debugfs_create_file("slp_s0_debug_status", 0444, | |
718 | dir, pmcdev, | |
719 | &pmc_core_slps0_dbg_fops); | |
720 | ||
721 | debugfs_create_bool("slp_s0_dbg_latch", 0644, | |
722 | dir, &slps0_dbg_latch); | |
723 | } | |
724 | ||
fe748227 | 725 | return 0; |
0bdfaf42 RB |
726 | } |
727 | #else | |
728 | static inline int pmc_core_dbgfs_register(struct pmc_dev *pmcdev) | |
729 | { | |
730 | return 0; | |
731 | } | |
732 | ||
733 | static inline void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev) | |
734 | { | |
b740d2e9 | 735 | } |
0bdfaf42 | 736 | #endif /* CONFIG_DEBUG_FS */ |
b740d2e9 RB |
737 | |
738 | static const struct x86_cpu_id intel_pmc_core_ids[] = { | |
00f8b2fc RB |
739 | ICPU(INTEL_FAM6_SKYLAKE_MOBILE, &spt_reg_map), |
740 | ICPU(INTEL_FAM6_SKYLAKE_DESKTOP, &spt_reg_map), | |
741 | ICPU(INTEL_FAM6_KABYLAKE_MOBILE, &spt_reg_map), | |
742 | ICPU(INTEL_FAM6_KABYLAKE_DESKTOP, &spt_reg_map), | |
291101f6 | 743 | ICPU(INTEL_FAM6_CANNONLAKE_MOBILE, &cnp_reg_map), |
b740d2e9 RB |
744 | {} |
745 | }; | |
746 | ||
21ae4357 SP |
747 | MODULE_DEVICE_TABLE(x86cpu, intel_pmc_core_ids); |
748 | ||
661405bd RB |
749 | static const struct pci_device_id pmc_pci_ids[] = { |
750 | { PCI_VDEVICE(INTEL, SPT_PMC_PCI_DEVICE_ID), 0}, | |
751 | { 0, }, | |
752 | }; | |
753 | ||
21ae4357 | 754 | static int __init pmc_core_probe(void) |
b740d2e9 | 755 | { |
b740d2e9 RB |
756 | struct pmc_dev *pmcdev = &pmc; |
757 | const struct x86_cpu_id *cpu_id; | |
745698c3 | 758 | u64 slp_s0_addr; |
b740d2e9 RB |
759 | int err; |
760 | ||
761 | cpu_id = x86_match_cpu(intel_pmc_core_ids); | |
21ae4357 SP |
762 | if (!cpu_id) |
763 | return -ENODEV; | |
764 | ||
765 | pmcdev->map = (struct pmc_reg_map *)cpu_id->driver_data; | |
745698c3 | 766 | |
661405bd RB |
767 | /* |
768 | * Coffeelake has CPU ID of Kabylake and Cannonlake PCH. So here | |
769 | * Sunrisepoint PCH regmap can't be used. Use Cannonlake PCH regmap | |
770 | * in this case. | |
771 | */ | |
e50af833 | 772 | if (pmcdev->map == &spt_reg_map && !pci_dev_present(pmc_pci_ids)) |
661405bd RB |
773 | pmcdev->map = &cnp_reg_map; |
774 | ||
745698c3 SP |
775 | if (lpit_read_residency_count_address(&slp_s0_addr)) |
776 | pmcdev->base_addr = PMC_BASE_ADDR_DEFAULT; | |
777 | else | |
778 | pmcdev->base_addr = slp_s0_addr - pmcdev->map->slp_s0_offset; | |
779 | ||
21ae4357 SP |
780 | pmcdev->regbase = ioremap(pmcdev->base_addr, |
781 | pmcdev->map->regmap_length); | |
782 | if (!pmcdev->regbase) | |
b740d2e9 | 783 | return -ENOMEM; |
b740d2e9 | 784 | |
173943b3 | 785 | mutex_init(&pmcdev->lock); |
c977b98b | 786 | pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(); |
173943b3 | 787 | |
b740d2e9 | 788 | err = pmc_core_dbgfs_register(pmcdev); |
21ae4357 SP |
789 | if (err < 0) { |
790 | pr_warn(" debugfs register failed.\n"); | |
791 | iounmap(pmcdev->regbase); | |
792 | return err; | |
793 | } | |
b740d2e9 | 794 | |
21ae4357 | 795 | pr_info(" initialized\n"); |
b740d2e9 RB |
796 | return 0; |
797 | } | |
21ae4357 | 798 | module_init(pmc_core_probe) |
b740d2e9 | 799 | |
21ae4357 | 800 | static void __exit pmc_core_remove(void) |
2854a0aa | 801 | { |
21ae4357 | 802 | struct pmc_dev *pmcdev = &pmc; |
b740d2e9 | 803 | |
21ae4357 SP |
804 | pmc_core_dbgfs_unregister(pmcdev); |
805 | mutex_destroy(&pmcdev->lock); | |
806 | iounmap(pmcdev->regbase); | |
807 | } | |
808 | module_exit(pmc_core_remove) | |
2854a0aa SP |
809 | |
810 | MODULE_LICENSE("GPL v2"); | |
811 | MODULE_DESCRIPTION("Intel PMC Core Driver"); |