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 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 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 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 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 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 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