1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * This file contains platform specific structure definitions
4 * and init function used by Cannon Lake Point PCH.
5 *
6 * Copyright (c) 2022, Intel Corporation.
7 * All Rights Reserved.
8 *
9 */
10
11 #include <linux/smp.h>
12 #include <linux/suspend.h>
13 #include "core.h"
14
15 /* Cannon Lake: PGD PFET Enable Ack Status Register(s) bitmap */
16 const struct pmc_bit_map cnp_pfear_map[] = {
17 {"PMC", BIT(0)},
18 {"OPI-DMI", BIT(1)},
19 {"SPI/eSPI", BIT(2)},
20 {"XHCI", BIT(3)},
21 {"SPA", BIT(4)},
22 {"SPB", BIT(5)},
23 {"SPC", BIT(6)},
24 {"GBE", BIT(7)},
25
26 {"SATA", BIT(0)},
27 {"HDA_PGD0", BIT(1)},
28 {"HDA_PGD1", BIT(2)},
29 {"HDA_PGD2", BIT(3)},
30 {"HDA_PGD3", BIT(4)},
31 {"SPD", BIT(5)},
32 {"LPSS", BIT(6)},
33 {"LPC", BIT(7)},
34
35 {"SMB", BIT(0)},
36 {"ISH", BIT(1)},
37 {"P2SB", BIT(2)},
38 {"NPK_VNN", BIT(3)},
39 {"SDX", BIT(4)},
40 {"SPE", BIT(5)},
41 {"Fuse", BIT(6)},
42 {"SBR8", BIT(7)},
43
44 {"CSME_FSC", BIT(0)},
45 {"USB3_OTG", BIT(1)},
46 {"EXI", BIT(2)},
47 {"CSE", BIT(3)},
48 {"CSME_KVM", BIT(4)},
49 {"CSME_PMT", BIT(5)},
50 {"CSME_CLINK", BIT(6)},
51 {"CSME_PTIO", BIT(7)},
52
53 {"CSME_USBR", BIT(0)},
54 {"CSME_SUSRAM", BIT(1)},
55 {"CSME_SMT1", BIT(2)},
56 {"CSME_SMT4", BIT(3)},
57 {"CSME_SMS2", BIT(4)},
58 {"CSME_SMS1", BIT(5)},
59 {"CSME_RTC", BIT(6)},
60 {"CSME_PSF", BIT(7)},
61
62 {"SBR0", BIT(0)},
63 {"SBR1", BIT(1)},
64 {"SBR2", BIT(2)},
65 {"SBR3", BIT(3)},
66 {"SBR4", BIT(4)},
67 {"SBR5", BIT(5)},
68 {"CSME_PECI", BIT(6)},
69 {"PSF1", BIT(7)},
70
71 {"PSF2", BIT(0)},
72 {"PSF3", BIT(1)},
73 {"PSF4", BIT(2)},
74 {"CNVI", BIT(3)},
75 {"UFS0", BIT(4)},
76 {"EMMC", BIT(5)},
77 {"SPF", BIT(6)},
78 {"SBR6", BIT(7)},
79
80 {"SBR7", BIT(0)},
81 {"NPK_AON", BIT(1)},
82 {"HDA_PGD4", BIT(2)},
83 {"HDA_PGD5", BIT(3)},
84 {"HDA_PGD6", BIT(4)},
85 {"PSF6", BIT(5)},
86 {"PSF7", BIT(6)},
87 {"PSF8", BIT(7)},
88 {}
89 };
90
91 const struct pmc_bit_map *ext_cnp_pfear_map[] = {
92 /*
93 * Check intel_pmc_core_ids[] users of cnp_reg_map for
94 * a list of core SoCs using this.
95 */
96 cnp_pfear_map,
97 NULL
98 };
99
100 const struct pmc_bit_map cnp_slps0_dbg0_map[] = {
101 {"AUDIO_D3", BIT(0)},
102 {"OTG_D3", BIT(1)},
103 {"XHCI_D3", BIT(2)},
104 {"LPIO_D3", BIT(3)},
105 {"SDX_D3", BIT(4)},
106 {"SATA_D3", BIT(5)},
107 {"UFS0_D3", BIT(6)},
108 {"UFS1_D3", BIT(7)},
109 {"EMMC_D3", BIT(8)},
110 {}
111 };
112
113 const struct pmc_bit_map cnp_slps0_dbg1_map[] = {
114 {"SDIO_PLL_OFF", BIT(0)},
115 {"USB2_PLL_OFF", BIT(1)},
116 {"AUDIO_PLL_OFF", BIT(2)},
117 {"OC_PLL_OFF", BIT(3)},
118 {"MAIN_PLL_OFF", BIT(4)},
119 {"XOSC_OFF", BIT(5)},
120 {"LPC_CLKS_GATED", BIT(6)},
121 {"PCIE_CLKREQS_IDLE", BIT(7)},
122 {"AUDIO_ROSC_OFF", BIT(8)},
123 {"HPET_XOSC_CLK_REQ", BIT(9)},
124 {"PMC_ROSC_SLOW_CLK", BIT(10)},
125 {"AON2_ROSC_GATED", BIT(11)},
126 {"CLKACKS_DEASSERTED", BIT(12)},
127 {}
128 };
129
130 const struct pmc_bit_map cnp_slps0_dbg2_map[] = {
131 {"MPHY_CORE_GATED", BIT(0)},
132 {"CSME_GATED", BIT(1)},
133 {"USB2_SUS_GATED", BIT(2)},
134 {"DYN_FLEX_IO_IDLE", BIT(3)},
135 {"GBE_NO_LINK", BIT(4)},
136 {"THERM_SEN_DISABLED", BIT(5)},
137 {"PCIE_LOW_POWER", BIT(6)},
138 {"ISH_VNNAON_REQ_ACT", BIT(7)},
139 {"ISH_VNN_REQ_ACT", BIT(8)},
140 {"CNV_VNNAON_REQ_ACT", BIT(9)},
141 {"CNV_VNN_REQ_ACT", BIT(10)},
142 {"NPK_VNNON_REQ_ACT", BIT(11)},
143 {"PMSYNC_STATE_IDLE", BIT(12)},
144 {"ALST_GT_THRES", BIT(13)},
145 {"PMC_ARC_PG_READY", BIT(14)},
146 {}
147 };
148
149 const struct pmc_bit_map *cnp_slps0_dbg_maps[] = {
150 cnp_slps0_dbg0_map,
151 cnp_slps0_dbg1_map,
152 cnp_slps0_dbg2_map,
153 NULL
154 };
155
156 const struct pmc_bit_map cnp_ltr_show_map[] = {
157 {"SOUTHPORT_A", CNP_PMC_LTR_SPA},
158 {"SOUTHPORT_B", CNP_PMC_LTR_SPB},
159 {"SATA", CNP_PMC_LTR_SATA},
160 {"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE},
161 {"XHCI", CNP_PMC_LTR_XHCI},
162 {"Reserved", CNP_PMC_LTR_RESERVED},
163 {"ME", CNP_PMC_LTR_ME},
164 /* EVA is Enterprise Value Add, doesn't really exist on PCH */
165 {"EVA", CNP_PMC_LTR_EVA},
166 {"SOUTHPORT_C", CNP_PMC_LTR_SPC},
167 {"HD_AUDIO", CNP_PMC_LTR_AZ},
168 {"CNV", CNP_PMC_LTR_CNV},
169 {"LPSS", CNP_PMC_LTR_LPSS},
170 {"SOUTHPORT_D", CNP_PMC_LTR_SPD},
171 {"SOUTHPORT_E", CNP_PMC_LTR_SPE},
172 {"CAMERA", CNP_PMC_LTR_CAM},
173 {"ESPI", CNP_PMC_LTR_ESPI},
174 {"SCC", CNP_PMC_LTR_SCC},
175 {"ISH", CNP_PMC_LTR_ISH},
176 {"UFSX2", CNP_PMC_LTR_UFSX2},
177 {"EMMC", CNP_PMC_LTR_EMMC},
178 /*
179 * Check intel_pmc_core_ids[] users of cnp_reg_map for
180 * a list of core SoCs using this.
181 */
182 {"WIGIG", ICL_PMC_LTR_WIGIG},
183 {"THC0", TGL_PMC_LTR_THC0},
184 {"THC1", TGL_PMC_LTR_THC1},
185 /* Below two cannot be used for LTR_IGNORE */
186 {"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT},
187 {"AGGREGATED_SYSTEM", CNP_PMC_LTR_CUR_ASLT},
188 {}
189 };
190
191 const struct pmc_reg_map cnp_reg_map = {
192 .pfear_sts = ext_cnp_pfear_map,
193 .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET,
194 .slp_s0_res_counter_step = SPT_PMC_SLP_S0_RES_COUNTER_STEP,
195 .slps0_dbg_maps = cnp_slps0_dbg_maps,
196 .ltr_show_sts = cnp_ltr_show_map,
197 .msr_sts = msr_map,
198 .slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET,
199 .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET,
200 .regmap_length = CNP_PMC_MMIO_REG_LEN,
201 .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A,
202 .ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES,
203 .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
204 .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT,
205 .ltr_ignore_max = CNP_NUM_IP_IGN_ALLOWED,
206 .etr3_offset = ETR3_OFFSET,
207 };
208
209
210 /*
211 * Disable C1 auto-demotion
212 *
213 * Aggressive C1 auto-demotion may lead to failure to enter the deepest C-state
214 * during suspend-to-idle, causing high power consumption. To prevent this, we
215 * disable C1 auto-demotion during suspend and re-enable on resume.
216 *
217 * Note that, although MSR_PKG_CST_CONFIG_CONTROL has 'package' in its name, it
218 * is actually a per-core MSR on client platforms, affecting only a single CPU.
219 * Therefore, it must be configured on all online CPUs. The online cpu mask is
220 * unchanged during the phase of suspend/resume as user space is frozen.
221 */
222
223 static DEFINE_PER_CPU(u64, pkg_cst_config);
224
disable_c1_auto_demote(void * unused)225 static void disable_c1_auto_demote(void *unused)
226 {
227 int cpunum = smp_processor_id();
228 u64 val;
229
230 rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, val);
231 per_cpu(pkg_cst_config, cpunum) = val;
232 val &= ~NHM_C1_AUTO_DEMOTE;
233 wrmsrl(MSR_PKG_CST_CONFIG_CONTROL, val);
234
235 pr_debug("%s: cpu:%d cst %llx\n", __func__, cpunum, val);
236 }
237
restore_c1_auto_demote(void * unused)238 static void restore_c1_auto_demote(void *unused)
239 {
240 int cpunum = smp_processor_id();
241
242 wrmsrl(MSR_PKG_CST_CONFIG_CONTROL, per_cpu(pkg_cst_config, cpunum));
243
244 pr_debug("%s: cpu:%d cst %llx\n", __func__, cpunum,
245 per_cpu(pkg_cst_config, cpunum));
246 }
247
s2idle_cpu_quirk(smp_call_func_t func)248 static void s2idle_cpu_quirk(smp_call_func_t func)
249 {
250 if (pm_suspend_via_firmware())
251 return;
252
253 on_each_cpu(func, NULL, true);
254 }
255
cnl_suspend(struct pmc_dev * pmcdev)256 void cnl_suspend(struct pmc_dev *pmcdev)
257 {
258 s2idle_cpu_quirk(disable_c1_auto_demote);
259
260 /*
261 * Due to a hardware limitation, the GBE LTR blocks PC10
262 * when a cable is attached. To unblock PC10 during suspend,
263 * tell the PMC to ignore it.
264 */
265 pmc_core_send_ltr_ignore(pmcdev, 3, 1);
266 }
267
cnl_resume(struct pmc_dev * pmcdev)268 int cnl_resume(struct pmc_dev *pmcdev)
269 {
270 s2idle_cpu_quirk(restore_c1_auto_demote);
271
272 pmc_core_send_ltr_ignore(pmcdev, 3, 0);
273
274 return pmc_core_resume_common(pmcdev);
275 }
276
cnp_core_init(struct pmc_dev * pmcdev)277 int cnp_core_init(struct pmc_dev *pmcdev)
278 {
279 struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
280 int ret;
281
282 pmcdev->suspend = cnl_suspend;
283 pmcdev->resume = cnl_resume;
284
285 pmc->map = &cnp_reg_map;
286 ret = get_primary_reg_base(pmc);
287 if (ret)
288 return ret;
289
290 pmc_core_get_low_power_modes(pmcdev);
291
292 return 0;
293 }
294