File Index
Files and directories
Sign in
FILE

cnp.c

File preview with syntax highlighting.

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