Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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 */
 16const 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
 91const 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
100const 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
113const 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
130const 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
149const 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
156const 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
191const 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
223static DEFINE_PER_CPU(u64, pkg_cst_config);
224
225static 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
238static 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
248static 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
256void 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
268int 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
277int 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}