xref: /linux/drivers/platform/x86/intel/telemetry/debugfs.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
12b6cb8f2SKate Hsuan // SPDX-License-Identifier: GPL-2.0
22b6cb8f2SKate Hsuan /*
32b6cb8f2SKate Hsuan  * Intel SOC Telemetry debugfs Driver: Currently supports APL
42b6cb8f2SKate Hsuan  * Copyright (c) 2015, Intel Corporation.
52b6cb8f2SKate Hsuan  * All Rights Reserved.
62b6cb8f2SKate Hsuan  *
72b6cb8f2SKate Hsuan  * This file provides the debugfs interfaces for telemetry.
82b6cb8f2SKate Hsuan  * /sys/kernel/debug/telemetry/pss_info: Shows Primary Control Sub-Sys Counters
92b6cb8f2SKate Hsuan  * /sys/kernel/debug/telemetry/ioss_info: Shows IO Sub-System Counters
102b6cb8f2SKate Hsuan  * /sys/kernel/debug/telemetry/soc_states: Shows SoC State
112b6cb8f2SKate Hsuan  * /sys/kernel/debug/telemetry/pss_trace_verbosity: Read and Change Tracing
122b6cb8f2SKate Hsuan  *				Verbosity via firmware
132b6cb8f2SKate Hsuan  * /sys/kernel/debug/telemetry/ioss_race_verbosity: Write and Change Tracing
142b6cb8f2SKate Hsuan  *				Verbosity via firmware
152b6cb8f2SKate Hsuan  */
162b6cb8f2SKate Hsuan #include <linux/debugfs.h>
172b6cb8f2SKate Hsuan #include <linux/device.h>
182b6cb8f2SKate Hsuan #include <linux/mfd/intel_pmc_bxt.h>
192b6cb8f2SKate Hsuan #include <linux/module.h>
202b6cb8f2SKate Hsuan #include <linux/pci.h>
212b6cb8f2SKate Hsuan #include <linux/seq_file.h>
222b6cb8f2SKate Hsuan #include <linux/suspend.h>
232b6cb8f2SKate Hsuan 
242b6cb8f2SKate Hsuan #include <asm/cpu_device_id.h>
252b6cb8f2SKate Hsuan #include <asm/intel-family.h>
262b6cb8f2SKate Hsuan #include <asm/intel_telemetry.h>
272b6cb8f2SKate Hsuan 
282b6cb8f2SKate Hsuan #define DRIVER_NAME			"telemetry_soc_debugfs"
292b6cb8f2SKate Hsuan #define DRIVER_VERSION			"1.0.0"
302b6cb8f2SKate Hsuan 
312b6cb8f2SKate Hsuan /* ApolloLake SoC Event-IDs */
322b6cb8f2SKate Hsuan #define TELEM_APL_PSS_PSTATES_ID	0x2802
332b6cb8f2SKate Hsuan #define TELEM_APL_PSS_IDLE_ID		0x2806
342b6cb8f2SKate Hsuan #define TELEM_APL_PCS_IDLE_BLOCKED_ID	0x2C00
352b6cb8f2SKate Hsuan #define TELEM_APL_PCS_S0IX_BLOCKED_ID	0x2C01
362b6cb8f2SKate Hsuan #define TELEM_APL_PSS_WAKEUP_ID		0x2C02
372b6cb8f2SKate Hsuan #define TELEM_APL_PSS_LTR_BLOCKING_ID	0x2C03
382b6cb8f2SKate Hsuan 
392b6cb8f2SKate Hsuan #define TELEM_APL_S0IX_TOTAL_OCC_ID	0x4000
402b6cb8f2SKate Hsuan #define TELEM_APL_S0IX_SHLW_OCC_ID	0x4001
412b6cb8f2SKate Hsuan #define TELEM_APL_S0IX_DEEP_OCC_ID	0x4002
422b6cb8f2SKate Hsuan #define TELEM_APL_S0IX_TOTAL_RES_ID	0x4800
432b6cb8f2SKate Hsuan #define TELEM_APL_S0IX_SHLW_RES_ID	0x4801
442b6cb8f2SKate Hsuan #define TELEM_APL_S0IX_DEEP_RES_ID	0x4802
452b6cb8f2SKate Hsuan #define TELEM_APL_D0IX_ID		0x581A
462b6cb8f2SKate Hsuan #define TELEM_APL_D3_ID			0x5819
472b6cb8f2SKate Hsuan #define TELEM_APL_PG_ID			0x5818
482b6cb8f2SKate Hsuan 
492b6cb8f2SKate Hsuan #define TELEM_INFO_SRAMEVTS_MASK	0xFF00
502b6cb8f2SKate Hsuan #define TELEM_INFO_SRAMEVTS_SHIFT	0x8
512b6cb8f2SKate Hsuan #define TELEM_SSRAM_READ_TIMEOUT	10
522b6cb8f2SKate Hsuan 
532b6cb8f2SKate Hsuan #define TELEM_MASK_BIT			1
542b6cb8f2SKate Hsuan #define TELEM_MASK_BYTE			0xFF
552b6cb8f2SKate Hsuan #define BYTES_PER_LONG			8
562b6cb8f2SKate Hsuan #define TELEM_APL_MASK_PCS_STATE	0xF
572b6cb8f2SKate Hsuan 
582b6cb8f2SKate Hsuan /* Max events in bitmap to check for */
592b6cb8f2SKate Hsuan #define TELEM_PSS_IDLE_EVTS		25
602b6cb8f2SKate Hsuan #define TELEM_PSS_IDLE_BLOCKED_EVTS	20
612b6cb8f2SKate Hsuan #define TELEM_PSS_S0IX_BLOCKED_EVTS	20
622b6cb8f2SKate Hsuan #define TELEM_PSS_S0IX_WAKEUP_EVTS	20
632b6cb8f2SKate Hsuan #define TELEM_PSS_LTR_BLOCKING_EVTS	20
642b6cb8f2SKate Hsuan #define TELEM_IOSS_DX_D0IX_EVTS		25
652b6cb8f2SKate Hsuan #define TELEM_IOSS_PG_EVTS		30
662b6cb8f2SKate Hsuan 
672b6cb8f2SKate Hsuan #define TELEM_CHECK_AND_PARSE_EVTS(EVTID, EVTNUM, BUF, EVTLOG, EVTDAT, MASK) { \
682b6cb8f2SKate Hsuan 	if (evtlog[index].telem_evtid == (EVTID)) { \
692b6cb8f2SKate Hsuan 		for (idx = 0; idx < (EVTNUM); idx++) \
702b6cb8f2SKate Hsuan 			(BUF)[idx] = ((EVTLOG) >> (EVTDAT)[idx].bit_pos) & \
712b6cb8f2SKate Hsuan 				     (MASK); \
722b6cb8f2SKate Hsuan 	continue; \
732b6cb8f2SKate Hsuan 	} \
742b6cb8f2SKate Hsuan }
752b6cb8f2SKate Hsuan 
762b6cb8f2SKate Hsuan #define TELEM_CHECK_AND_PARSE_CTRS(EVTID, CTR) { \
772b6cb8f2SKate Hsuan 	if (evtlog[index].telem_evtid == (EVTID)) { \
782b6cb8f2SKate Hsuan 		(CTR) = evtlog[index].telem_evtlog; \
792b6cb8f2SKate Hsuan 		continue; \
802b6cb8f2SKate Hsuan 	} \
812b6cb8f2SKate Hsuan }
822b6cb8f2SKate Hsuan 
832b6cb8f2SKate Hsuan static u8 suspend_prep_ok;
842b6cb8f2SKate Hsuan static u32 suspend_shlw_ctr_temp, suspend_deep_ctr_temp;
852b6cb8f2SKate Hsuan static u64 suspend_shlw_res_temp, suspend_deep_res_temp;
862b6cb8f2SKate Hsuan 
872b6cb8f2SKate Hsuan struct telemetry_susp_stats {
882b6cb8f2SKate Hsuan 	u32 shlw_ctr;
892b6cb8f2SKate Hsuan 	u32 deep_ctr;
902b6cb8f2SKate Hsuan 	u64 shlw_res;
912b6cb8f2SKate Hsuan 	u64 deep_res;
922b6cb8f2SKate Hsuan };
932b6cb8f2SKate Hsuan 
942b6cb8f2SKate Hsuan /* Bitmap definitions for default counters in APL */
952b6cb8f2SKate Hsuan struct telem_pss_idle_stateinfo {
962b6cb8f2SKate Hsuan 	const char *name;
972b6cb8f2SKate Hsuan 	u32 bit_pos;
982b6cb8f2SKate Hsuan };
992b6cb8f2SKate Hsuan 
1002b6cb8f2SKate Hsuan static struct telem_pss_idle_stateinfo telem_apl_pss_idle_data[] = {
1012b6cb8f2SKate Hsuan 	{"IA_CORE0_C1E",		0},
1022b6cb8f2SKate Hsuan 	{"IA_CORE1_C1E",		1},
1032b6cb8f2SKate Hsuan 	{"IA_CORE2_C1E",		2},
1042b6cb8f2SKate Hsuan 	{"IA_CORE3_C1E",		3},
1052b6cb8f2SKate Hsuan 	{"IA_CORE0_C6",			16},
1062b6cb8f2SKate Hsuan 	{"IA_CORE1_C6",			17},
1072b6cb8f2SKate Hsuan 	{"IA_CORE2_C6",			18},
1082b6cb8f2SKate Hsuan 	{"IA_CORE3_C6",			19},
1092b6cb8f2SKate Hsuan 	{"IA_MODULE0_C7",		32},
1102b6cb8f2SKate Hsuan 	{"IA_MODULE1_C7",		33},
1112b6cb8f2SKate Hsuan 	{"GT_RC6",			40},
1122b6cb8f2SKate Hsuan 	{"IUNIT_PROCESSING_IDLE",	41},
1132b6cb8f2SKate Hsuan 	{"FAR_MEM_IDLE",		43},
1142b6cb8f2SKate Hsuan 	{"DISPLAY_IDLE",		44},
1152b6cb8f2SKate Hsuan 	{"IUNIT_INPUT_SYSTEM_IDLE",	45},
1162b6cb8f2SKate Hsuan 	{"PCS_STATUS",			60},
1172b6cb8f2SKate Hsuan };
1182b6cb8f2SKate Hsuan 
1192b6cb8f2SKate Hsuan struct telem_pcs_blkd_info {
1202b6cb8f2SKate Hsuan 	const char *name;
1212b6cb8f2SKate Hsuan 	u32 bit_pos;
1222b6cb8f2SKate Hsuan };
1232b6cb8f2SKate Hsuan 
1242b6cb8f2SKate Hsuan static struct telem_pcs_blkd_info telem_apl_pcs_idle_blkd_data[] = {
1252b6cb8f2SKate Hsuan 	{"COMPUTE",			0},
1262b6cb8f2SKate Hsuan 	{"MISC",			8},
1272b6cb8f2SKate Hsuan 	{"MODULE_ACTIONS_PENDING",	16},
1282b6cb8f2SKate Hsuan 	{"LTR",				24},
1292b6cb8f2SKate Hsuan 	{"DISPLAY_WAKE",		32},
1302b6cb8f2SKate Hsuan 	{"ISP_WAKE",			40},
1312b6cb8f2SKate Hsuan 	{"PSF0_ACTIVE",			48},
1322b6cb8f2SKate Hsuan };
1332b6cb8f2SKate Hsuan 
1342b6cb8f2SKate Hsuan static struct telem_pcs_blkd_info telem_apl_pcs_s0ix_blkd_data[] = {
1352b6cb8f2SKate Hsuan 	{"LTR",				0},
1362b6cb8f2SKate Hsuan 	{"IRTL",			8},
1372b6cb8f2SKate Hsuan 	{"WAKE_DEADLINE_PENDING",	16},
1382b6cb8f2SKate Hsuan 	{"DISPLAY",			24},
1392b6cb8f2SKate Hsuan 	{"ISP",				32},
1402b6cb8f2SKate Hsuan 	{"CORE",			40},
1412b6cb8f2SKate Hsuan 	{"PMC",				48},
1422b6cb8f2SKate Hsuan 	{"MISC",			56},
1432b6cb8f2SKate Hsuan };
1442b6cb8f2SKate Hsuan 
1452b6cb8f2SKate Hsuan struct telem_pss_ltr_info {
1462b6cb8f2SKate Hsuan 	const char *name;
1472b6cb8f2SKate Hsuan 	u32 bit_pos;
1482b6cb8f2SKate Hsuan };
1492b6cb8f2SKate Hsuan 
1502b6cb8f2SKate Hsuan static struct telem_pss_ltr_info telem_apl_pss_ltr_data[] = {
1512b6cb8f2SKate Hsuan 	{"CORE_ACTIVE",		0},
1522b6cb8f2SKate Hsuan 	{"MEM_UP",		8},
1532b6cb8f2SKate Hsuan 	{"DFX",			16},
1542b6cb8f2SKate Hsuan 	{"DFX_FORCE_LTR",	24},
1552b6cb8f2SKate Hsuan 	{"DISPLAY",		32},
1562b6cb8f2SKate Hsuan 	{"ISP",			40},
1572b6cb8f2SKate Hsuan 	{"SOUTH",		48},
1582b6cb8f2SKate Hsuan };
1592b6cb8f2SKate Hsuan 
1602b6cb8f2SKate Hsuan struct telem_pss_wakeup_info {
1612b6cb8f2SKate Hsuan 	const char *name;
1622b6cb8f2SKate Hsuan 	u32 bit_pos;
1632b6cb8f2SKate Hsuan };
1642b6cb8f2SKate Hsuan 
1652b6cb8f2SKate Hsuan static struct telem_pss_wakeup_info telem_apl_pss_wakeup[] = {
1662b6cb8f2SKate Hsuan 	{"IP_IDLE",			0},
1672b6cb8f2SKate Hsuan 	{"DISPLAY_WAKE",		8},
1682b6cb8f2SKate Hsuan 	{"VOLTAGE_REG_INT",		16},
1692b6cb8f2SKate Hsuan 	{"DROWSY_TIMER (HOTPLUG)",	24},
1702b6cb8f2SKate Hsuan 	{"CORE_WAKE",			32},
1712b6cb8f2SKate Hsuan 	{"MISC_S0IX",			40},
1722b6cb8f2SKate Hsuan 	{"MISC_ABORT",			56},
1732b6cb8f2SKate Hsuan };
1742b6cb8f2SKate Hsuan 
1752b6cb8f2SKate Hsuan struct telem_ioss_d0ix_stateinfo {
1762b6cb8f2SKate Hsuan 	const char *name;
1772b6cb8f2SKate Hsuan 	u32 bit_pos;
1782b6cb8f2SKate Hsuan };
1792b6cb8f2SKate Hsuan 
1802b6cb8f2SKate Hsuan static struct telem_ioss_d0ix_stateinfo telem_apl_ioss_d0ix_data[] = {
1812b6cb8f2SKate Hsuan 	{"CSE",		0},
1822b6cb8f2SKate Hsuan 	{"SCC2",	1},
1832b6cb8f2SKate Hsuan 	{"GMM",		2},
1842b6cb8f2SKate Hsuan 	{"XDCI",	3},
1852b6cb8f2SKate Hsuan 	{"XHCI",	4},
1862b6cb8f2SKate Hsuan 	{"ISH",		5},
1872b6cb8f2SKate Hsuan 	{"AVS",		6},
1882b6cb8f2SKate Hsuan 	{"PCIE0P1",	7},
1892b6cb8f2SKate Hsuan 	{"PECI0P0",	8},
1902b6cb8f2SKate Hsuan 	{"LPSS",	9},
1912b6cb8f2SKate Hsuan 	{"SCC",		10},
1922b6cb8f2SKate Hsuan 	{"PWM",		11},
1932b6cb8f2SKate Hsuan 	{"PCIE1_P3",    12},
1942b6cb8f2SKate Hsuan 	{"PCIE1_P2",    13},
1952b6cb8f2SKate Hsuan 	{"PCIE1_P1",    14},
1962b6cb8f2SKate Hsuan 	{"PCIE1_P0",    15},
1972b6cb8f2SKate Hsuan 	{"CNV",		16},
1982b6cb8f2SKate Hsuan 	{"SATA",	17},
1992b6cb8f2SKate Hsuan 	{"PRTC",	18},
2002b6cb8f2SKate Hsuan };
2012b6cb8f2SKate Hsuan 
2022b6cb8f2SKate Hsuan struct telem_ioss_pg_info {
2032b6cb8f2SKate Hsuan 	const char *name;
2042b6cb8f2SKate Hsuan 	u32 bit_pos;
2052b6cb8f2SKate Hsuan };
2062b6cb8f2SKate Hsuan 
2072b6cb8f2SKate Hsuan static struct telem_ioss_pg_info telem_apl_ioss_pg_data[] = {
2082b6cb8f2SKate Hsuan 	{"LPSS",	0},
2092b6cb8f2SKate Hsuan 	{"SCC",		1},
2102b6cb8f2SKate Hsuan 	{"P2SB",	2},
2112b6cb8f2SKate Hsuan 	{"SCC2",	3},
2122b6cb8f2SKate Hsuan 	{"GMM",		4},
2132b6cb8f2SKate Hsuan 	{"PCIE0",	5},
2142b6cb8f2SKate Hsuan 	{"XDCI",	6},
2152b6cb8f2SKate Hsuan 	{"xHCI",	7},
2162b6cb8f2SKate Hsuan 	{"CSE",		8},
2172b6cb8f2SKate Hsuan 	{"SPI",		9},
2182b6cb8f2SKate Hsuan 	{"AVSPGD4",	10},
2192b6cb8f2SKate Hsuan 	{"AVSPGD3",	11},
2202b6cb8f2SKate Hsuan 	{"AVSPGD2",	12},
2212b6cb8f2SKate Hsuan 	{"AVSPGD1",	13},
2222b6cb8f2SKate Hsuan 	{"ISH",		14},
2232b6cb8f2SKate Hsuan 	{"EXI",		15},
2242b6cb8f2SKate Hsuan 	{"NPKVRC",	16},
2252b6cb8f2SKate Hsuan 	{"NPKVNN",	17},
2262b6cb8f2SKate Hsuan 	{"CUNIT",	18},
2272b6cb8f2SKate Hsuan 	{"FUSE_CTRL",	19},
2282b6cb8f2SKate Hsuan 	{"PCIE1",	20},
2292b6cb8f2SKate Hsuan 	{"CNV",		21},
2302b6cb8f2SKate Hsuan 	{"LPC",		22},
2312b6cb8f2SKate Hsuan 	{"SATA",	23},
2322b6cb8f2SKate Hsuan 	{"SMB",		24},
2332b6cb8f2SKate Hsuan 	{"PRTC",	25},
2342b6cb8f2SKate Hsuan };
2352b6cb8f2SKate Hsuan 
2362b6cb8f2SKate Hsuan struct telemetry_debugfs_conf {
2372b6cb8f2SKate Hsuan 	struct telemetry_susp_stats suspend_stats;
2382b6cb8f2SKate Hsuan 	struct dentry *telemetry_dbg_dir;
2392b6cb8f2SKate Hsuan 
2402b6cb8f2SKate Hsuan 	/* Bitmap Data */
2412b6cb8f2SKate Hsuan 	struct telem_ioss_d0ix_stateinfo *ioss_d0ix_data;
2422b6cb8f2SKate Hsuan 	struct telem_pss_idle_stateinfo *pss_idle_data;
2432b6cb8f2SKate Hsuan 	struct telem_pcs_blkd_info *pcs_idle_blkd_data;
2442b6cb8f2SKate Hsuan 	struct telem_pcs_blkd_info *pcs_s0ix_blkd_data;
2452b6cb8f2SKate Hsuan 	struct telem_pss_wakeup_info *pss_wakeup;
2462b6cb8f2SKate Hsuan 	struct telem_pss_ltr_info *pss_ltr_data;
2472b6cb8f2SKate Hsuan 	struct telem_ioss_pg_info *ioss_pg_data;
2482b6cb8f2SKate Hsuan 	u8 pcs_idle_blkd_evts;
2492b6cb8f2SKate Hsuan 	u8 pcs_s0ix_blkd_evts;
2502b6cb8f2SKate Hsuan 	u8 pss_wakeup_evts;
2512b6cb8f2SKate Hsuan 	u8 pss_idle_evts;
2522b6cb8f2SKate Hsuan 	u8 pss_ltr_evts;
2532b6cb8f2SKate Hsuan 	u8 ioss_d0ix_evts;
2542b6cb8f2SKate Hsuan 	u8 ioss_pg_evts;
2552b6cb8f2SKate Hsuan 
2562b6cb8f2SKate Hsuan 	/* IDs */
2572b6cb8f2SKate Hsuan 	u16  pss_ltr_blocking_id;
2582b6cb8f2SKate Hsuan 	u16  pcs_idle_blkd_id;
2592b6cb8f2SKate Hsuan 	u16  pcs_s0ix_blkd_id;
2602b6cb8f2SKate Hsuan 	u16  s0ix_total_occ_id;
2612b6cb8f2SKate Hsuan 	u16  s0ix_shlw_occ_id;
2622b6cb8f2SKate Hsuan 	u16  s0ix_deep_occ_id;
2632b6cb8f2SKate Hsuan 	u16  s0ix_total_res_id;
2642b6cb8f2SKate Hsuan 	u16  s0ix_shlw_res_id;
2652b6cb8f2SKate Hsuan 	u16  s0ix_deep_res_id;
2662b6cb8f2SKate Hsuan 	u16  pss_wakeup_id;
2672b6cb8f2SKate Hsuan 	u16  ioss_d0ix_id;
2682b6cb8f2SKate Hsuan 	u16  pstates_id;
2692b6cb8f2SKate Hsuan 	u16  pss_idle_id;
2702b6cb8f2SKate Hsuan 	u16  ioss_d3_id;
2712b6cb8f2SKate Hsuan 	u16  ioss_pg_id;
2722b6cb8f2SKate Hsuan };
2732b6cb8f2SKate Hsuan 
2742b6cb8f2SKate Hsuan static struct telemetry_debugfs_conf *debugfs_conf;
2752b6cb8f2SKate Hsuan 
2762b6cb8f2SKate Hsuan static struct telemetry_debugfs_conf telem_apl_debugfs_conf = {
2772b6cb8f2SKate Hsuan 	.pss_idle_data = telem_apl_pss_idle_data,
2782b6cb8f2SKate Hsuan 	.pcs_idle_blkd_data = telem_apl_pcs_idle_blkd_data,
2792b6cb8f2SKate Hsuan 	.pcs_s0ix_blkd_data = telem_apl_pcs_s0ix_blkd_data,
2802b6cb8f2SKate Hsuan 	.pss_ltr_data = telem_apl_pss_ltr_data,
2812b6cb8f2SKate Hsuan 	.pss_wakeup = telem_apl_pss_wakeup,
2822b6cb8f2SKate Hsuan 	.ioss_d0ix_data = telem_apl_ioss_d0ix_data,
2832b6cb8f2SKate Hsuan 	.ioss_pg_data = telem_apl_ioss_pg_data,
2842b6cb8f2SKate Hsuan 
2852b6cb8f2SKate Hsuan 	.pss_idle_evts = ARRAY_SIZE(telem_apl_pss_idle_data),
2862b6cb8f2SKate Hsuan 	.pcs_idle_blkd_evts = ARRAY_SIZE(telem_apl_pcs_idle_blkd_data),
2872b6cb8f2SKate Hsuan 	.pcs_s0ix_blkd_evts = ARRAY_SIZE(telem_apl_pcs_s0ix_blkd_data),
2882b6cb8f2SKate Hsuan 	.pss_ltr_evts = ARRAY_SIZE(telem_apl_pss_ltr_data),
2892b6cb8f2SKate Hsuan 	.pss_wakeup_evts = ARRAY_SIZE(telem_apl_pss_wakeup),
2902b6cb8f2SKate Hsuan 	.ioss_d0ix_evts = ARRAY_SIZE(telem_apl_ioss_d0ix_data),
2912b6cb8f2SKate Hsuan 	.ioss_pg_evts = ARRAY_SIZE(telem_apl_ioss_pg_data),
2922b6cb8f2SKate Hsuan 
2932b6cb8f2SKate Hsuan 	.pstates_id = TELEM_APL_PSS_PSTATES_ID,
2942b6cb8f2SKate Hsuan 	.pss_idle_id = TELEM_APL_PSS_IDLE_ID,
2952b6cb8f2SKate Hsuan 	.pcs_idle_blkd_id = TELEM_APL_PCS_IDLE_BLOCKED_ID,
2962b6cb8f2SKate Hsuan 	.pcs_s0ix_blkd_id = TELEM_APL_PCS_S0IX_BLOCKED_ID,
2972b6cb8f2SKate Hsuan 	.pss_wakeup_id = TELEM_APL_PSS_WAKEUP_ID,
2982b6cb8f2SKate Hsuan 	.pss_ltr_blocking_id = TELEM_APL_PSS_LTR_BLOCKING_ID,
2992b6cb8f2SKate Hsuan 	.s0ix_total_occ_id = TELEM_APL_S0IX_TOTAL_OCC_ID,
3002b6cb8f2SKate Hsuan 	.s0ix_shlw_occ_id = TELEM_APL_S0IX_SHLW_OCC_ID,
3012b6cb8f2SKate Hsuan 	.s0ix_deep_occ_id = TELEM_APL_S0IX_DEEP_OCC_ID,
3022b6cb8f2SKate Hsuan 	.s0ix_total_res_id = TELEM_APL_S0IX_TOTAL_RES_ID,
3032b6cb8f2SKate Hsuan 	.s0ix_shlw_res_id = TELEM_APL_S0IX_SHLW_RES_ID,
3042b6cb8f2SKate Hsuan 	.s0ix_deep_res_id = TELEM_APL_S0IX_DEEP_RES_ID,
3052b6cb8f2SKate Hsuan 	.ioss_d0ix_id = TELEM_APL_D0IX_ID,
3062b6cb8f2SKate Hsuan 	.ioss_d3_id = TELEM_APL_D3_ID,
3072b6cb8f2SKate Hsuan 	.ioss_pg_id = TELEM_APL_PG_ID,
3082b6cb8f2SKate Hsuan };
3092b6cb8f2SKate Hsuan 
3102b6cb8f2SKate Hsuan static const struct x86_cpu_id telemetry_debugfs_cpu_ids[] = {
311*0ff9c76fSTony Luck 	X86_MATCH_VFM(INTEL_ATOM_GOLDMONT,	&telem_apl_debugfs_conf),
312*0ff9c76fSTony Luck 	X86_MATCH_VFM(INTEL_ATOM_GOLDMONT_PLUS,	&telem_apl_debugfs_conf),
3132b6cb8f2SKate Hsuan 	{}
3142b6cb8f2SKate Hsuan };
3152b6cb8f2SKate Hsuan MODULE_DEVICE_TABLE(x86cpu, telemetry_debugfs_cpu_ids);
3162b6cb8f2SKate Hsuan 
telemetry_debugfs_check_evts(void)3172b6cb8f2SKate Hsuan static int telemetry_debugfs_check_evts(void)
3182b6cb8f2SKate Hsuan {
3192b6cb8f2SKate Hsuan 	if ((debugfs_conf->pss_idle_evts > TELEM_PSS_IDLE_EVTS) ||
3202b6cb8f2SKate Hsuan 	    (debugfs_conf->pcs_idle_blkd_evts > TELEM_PSS_IDLE_BLOCKED_EVTS) ||
3212b6cb8f2SKate Hsuan 	    (debugfs_conf->pcs_s0ix_blkd_evts > TELEM_PSS_S0IX_BLOCKED_EVTS) ||
3222b6cb8f2SKate Hsuan 	    (debugfs_conf->pss_ltr_evts > TELEM_PSS_LTR_BLOCKING_EVTS) ||
3232b6cb8f2SKate Hsuan 	    (debugfs_conf->pss_wakeup_evts > TELEM_PSS_S0IX_WAKEUP_EVTS) ||
3242b6cb8f2SKate Hsuan 	    (debugfs_conf->ioss_d0ix_evts > TELEM_IOSS_DX_D0IX_EVTS) ||
3252b6cb8f2SKate Hsuan 	    (debugfs_conf->ioss_pg_evts > TELEM_IOSS_PG_EVTS))
3262b6cb8f2SKate Hsuan 		return -EINVAL;
3272b6cb8f2SKate Hsuan 
3282b6cb8f2SKate Hsuan 	return 0;
3292b6cb8f2SKate Hsuan }
3302b6cb8f2SKate Hsuan 
telem_pss_states_show(struct seq_file * s,void * unused)3312b6cb8f2SKate Hsuan static int telem_pss_states_show(struct seq_file *s, void *unused)
3322b6cb8f2SKate Hsuan {
3332b6cb8f2SKate Hsuan 	struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];
3342b6cb8f2SKate Hsuan 	struct telemetry_debugfs_conf *conf = debugfs_conf;
3352b6cb8f2SKate Hsuan 	const char *name[TELEM_MAX_OS_ALLOCATED_EVENTS];
3362b6cb8f2SKate Hsuan 	u32 pcs_idle_blkd[TELEM_PSS_IDLE_BLOCKED_EVTS],
3372b6cb8f2SKate Hsuan 	    pcs_s0ix_blkd[TELEM_PSS_S0IX_BLOCKED_EVTS],
3382b6cb8f2SKate Hsuan 	    pss_s0ix_wakeup[TELEM_PSS_S0IX_WAKEUP_EVTS],
3392b6cb8f2SKate Hsuan 	    pss_ltr_blkd[TELEM_PSS_LTR_BLOCKING_EVTS],
3402b6cb8f2SKate Hsuan 	    pss_idle[TELEM_PSS_IDLE_EVTS];
3412b6cb8f2SKate Hsuan 	int index, idx, ret, err = 0;
3422b6cb8f2SKate Hsuan 	u64 pstates = 0;
3432b6cb8f2SKate Hsuan 
3442b6cb8f2SKate Hsuan 	ret = telemetry_read_eventlog(TELEM_PSS, evtlog,
3452b6cb8f2SKate Hsuan 				      TELEM_MAX_OS_ALLOCATED_EVENTS);
3462b6cb8f2SKate Hsuan 	if (ret < 0)
3472b6cb8f2SKate Hsuan 		return ret;
3482b6cb8f2SKate Hsuan 
3492b6cb8f2SKate Hsuan 	err = telemetry_get_evtname(TELEM_PSS, name,
3502b6cb8f2SKate Hsuan 				    TELEM_MAX_OS_ALLOCATED_EVENTS);
3512b6cb8f2SKate Hsuan 	if (err < 0)
3522b6cb8f2SKate Hsuan 		return err;
3532b6cb8f2SKate Hsuan 
3542b6cb8f2SKate Hsuan 	seq_puts(s, "\n----------------------------------------------------\n");
3552b6cb8f2SKate Hsuan 	seq_puts(s, "\tPSS TELEM EVENTLOG (Residency = field/19.2 us\n");
3562b6cb8f2SKate Hsuan 	seq_puts(s, "----------------------------------------------------\n");
3572b6cb8f2SKate Hsuan 	for (index = 0; index < ret; index++) {
3582b6cb8f2SKate Hsuan 		seq_printf(s, "%-32s %llu\n",
3592b6cb8f2SKate Hsuan 			   name[index], evtlog[index].telem_evtlog);
3602b6cb8f2SKate Hsuan 
3612b6cb8f2SKate Hsuan 		/* Fetch PSS IDLE State */
3622b6cb8f2SKate Hsuan 		if (evtlog[index].telem_evtid == conf->pss_idle_id) {
3632b6cb8f2SKate Hsuan 			pss_idle[conf->pss_idle_evts - 1] =
3642b6cb8f2SKate Hsuan 			(evtlog[index].telem_evtlog >>
3652b6cb8f2SKate Hsuan 			conf->pss_idle_data[conf->pss_idle_evts - 1].bit_pos) &
3662b6cb8f2SKate Hsuan 			TELEM_APL_MASK_PCS_STATE;
3672b6cb8f2SKate Hsuan 		}
3682b6cb8f2SKate Hsuan 
3692b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_EVTS(conf->pss_idle_id,
3702b6cb8f2SKate Hsuan 					   conf->pss_idle_evts - 1,
3712b6cb8f2SKate Hsuan 					   pss_idle, evtlog[index].telem_evtlog,
3722b6cb8f2SKate Hsuan 					   conf->pss_idle_data, TELEM_MASK_BIT);
3732b6cb8f2SKate Hsuan 
3742b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_EVTS(conf->pcs_idle_blkd_id,
3752b6cb8f2SKate Hsuan 					   conf->pcs_idle_blkd_evts,
3762b6cb8f2SKate Hsuan 					   pcs_idle_blkd,
3772b6cb8f2SKate Hsuan 					   evtlog[index].telem_evtlog,
3782b6cb8f2SKate Hsuan 					   conf->pcs_idle_blkd_data,
3792b6cb8f2SKate Hsuan 					   TELEM_MASK_BYTE);
3802b6cb8f2SKate Hsuan 
3812b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_EVTS(conf->pcs_s0ix_blkd_id,
3822b6cb8f2SKate Hsuan 					   conf->pcs_s0ix_blkd_evts,
3832b6cb8f2SKate Hsuan 					   pcs_s0ix_blkd,
3842b6cb8f2SKate Hsuan 					   evtlog[index].telem_evtlog,
3852b6cb8f2SKate Hsuan 					   conf->pcs_s0ix_blkd_data,
3862b6cb8f2SKate Hsuan 					   TELEM_MASK_BYTE);
3872b6cb8f2SKate Hsuan 
3882b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_EVTS(conf->pss_wakeup_id,
3892b6cb8f2SKate Hsuan 					   conf->pss_wakeup_evts,
3902b6cb8f2SKate Hsuan 					   pss_s0ix_wakeup,
3912b6cb8f2SKate Hsuan 					   evtlog[index].telem_evtlog,
3922b6cb8f2SKate Hsuan 					   conf->pss_wakeup, TELEM_MASK_BYTE);
3932b6cb8f2SKate Hsuan 
3942b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_EVTS(conf->pss_ltr_blocking_id,
3952b6cb8f2SKate Hsuan 					   conf->pss_ltr_evts, pss_ltr_blkd,
3962b6cb8f2SKate Hsuan 					   evtlog[index].telem_evtlog,
3972b6cb8f2SKate Hsuan 					   conf->pss_ltr_data, TELEM_MASK_BYTE);
3982b6cb8f2SKate Hsuan 
3992b6cb8f2SKate Hsuan 		if (evtlog[index].telem_evtid == debugfs_conf->pstates_id)
4002b6cb8f2SKate Hsuan 			pstates = evtlog[index].telem_evtlog;
4012b6cb8f2SKate Hsuan 	}
4022b6cb8f2SKate Hsuan 
4032b6cb8f2SKate Hsuan 	seq_puts(s, "\n--------------------------------------\n");
4042b6cb8f2SKate Hsuan 	seq_puts(s, "PStates\n");
4052b6cb8f2SKate Hsuan 	seq_puts(s, "--------------------------------------\n");
4062b6cb8f2SKate Hsuan 	seq_puts(s, "Domain\t\t\t\tFreq(Mhz)\n");
4072b6cb8f2SKate Hsuan 	seq_printf(s, " IA\t\t\t\t %llu\n GT\t\t\t\t %llu\n",
4082b6cb8f2SKate Hsuan 		   (pstates & TELEM_MASK_BYTE)*100,
4092b6cb8f2SKate Hsuan 		   ((pstates >> 8) & TELEM_MASK_BYTE)*50/3);
4102b6cb8f2SKate Hsuan 
4112b6cb8f2SKate Hsuan 	seq_printf(s, " IUNIT\t\t\t\t %llu\n SA\t\t\t\t %llu\n",
4122b6cb8f2SKate Hsuan 		   ((pstates >> 16) & TELEM_MASK_BYTE)*25,
4132b6cb8f2SKate Hsuan 		   ((pstates >> 24) & TELEM_MASK_BYTE)*50/3);
4142b6cb8f2SKate Hsuan 
4152b6cb8f2SKate Hsuan 	seq_puts(s, "\n--------------------------------------\n");
4162b6cb8f2SKate Hsuan 	seq_puts(s, "PSS IDLE Status\n");
4172b6cb8f2SKate Hsuan 	seq_puts(s, "--------------------------------------\n");
4182b6cb8f2SKate Hsuan 	seq_puts(s, "Device\t\t\t\t\tIDLE\n");
4192b6cb8f2SKate Hsuan 	for (index = 0; index < debugfs_conf->pss_idle_evts; index++) {
4202b6cb8f2SKate Hsuan 		seq_printf(s, "%-32s\t%u\n",
4212b6cb8f2SKate Hsuan 			   debugfs_conf->pss_idle_data[index].name,
4222b6cb8f2SKate Hsuan 			   pss_idle[index]);
4232b6cb8f2SKate Hsuan 	}
4242b6cb8f2SKate Hsuan 
4252b6cb8f2SKate Hsuan 	seq_puts(s, "\n--------------------------------------\n");
4262b6cb8f2SKate Hsuan 	seq_puts(s, "PSS Idle blkd Status (~1ms saturating bucket)\n");
4272b6cb8f2SKate Hsuan 	seq_puts(s, "--------------------------------------\n");
4282b6cb8f2SKate Hsuan 	seq_puts(s, "Blocker\t\t\t\t\tCount\n");
4292b6cb8f2SKate Hsuan 	for (index = 0; index < debugfs_conf->pcs_idle_blkd_evts; index++) {
4302b6cb8f2SKate Hsuan 		seq_printf(s, "%-32s\t%u\n",
4312b6cb8f2SKate Hsuan 			   debugfs_conf->pcs_idle_blkd_data[index].name,
4322b6cb8f2SKate Hsuan 			   pcs_idle_blkd[index]);
4332b6cb8f2SKate Hsuan 	}
4342b6cb8f2SKate Hsuan 
4352b6cb8f2SKate Hsuan 	seq_puts(s, "\n--------------------------------------\n");
4362b6cb8f2SKate Hsuan 	seq_puts(s, "PSS S0ix blkd Status (~1ms saturating bucket)\n");
4372b6cb8f2SKate Hsuan 	seq_puts(s, "--------------------------------------\n");
4382b6cb8f2SKate Hsuan 	seq_puts(s, "Blocker\t\t\t\t\tCount\n");
4392b6cb8f2SKate Hsuan 	for (index = 0; index < debugfs_conf->pcs_s0ix_blkd_evts; index++) {
4402b6cb8f2SKate Hsuan 		seq_printf(s, "%-32s\t%u\n",
4412b6cb8f2SKate Hsuan 			   debugfs_conf->pcs_s0ix_blkd_data[index].name,
4422b6cb8f2SKate Hsuan 			   pcs_s0ix_blkd[index]);
4432b6cb8f2SKate Hsuan 	}
4442b6cb8f2SKate Hsuan 
4452b6cb8f2SKate Hsuan 	seq_puts(s, "\n--------------------------------------\n");
4462b6cb8f2SKate Hsuan 	seq_puts(s, "LTR Blocking Status (~1ms saturating bucket)\n");
4472b6cb8f2SKate Hsuan 	seq_puts(s, "--------------------------------------\n");
4482b6cb8f2SKate Hsuan 	seq_puts(s, "Blocker\t\t\t\t\tCount\n");
4492b6cb8f2SKate Hsuan 	for (index = 0; index < debugfs_conf->pss_ltr_evts; index++) {
4502b6cb8f2SKate Hsuan 		seq_printf(s, "%-32s\t%u\n",
4512b6cb8f2SKate Hsuan 			   debugfs_conf->pss_ltr_data[index].name,
4522b6cb8f2SKate Hsuan 			   pss_s0ix_wakeup[index]);
4532b6cb8f2SKate Hsuan 	}
4542b6cb8f2SKate Hsuan 
4552b6cb8f2SKate Hsuan 	seq_puts(s, "\n--------------------------------------\n");
4562b6cb8f2SKate Hsuan 	seq_puts(s, "Wakes Status (~1ms saturating bucket)\n");
4572b6cb8f2SKate Hsuan 	seq_puts(s, "--------------------------------------\n");
4582b6cb8f2SKate Hsuan 	seq_puts(s, "Wakes\t\t\t\t\tCount\n");
4592b6cb8f2SKate Hsuan 	for (index = 0; index < debugfs_conf->pss_wakeup_evts; index++) {
4602b6cb8f2SKate Hsuan 		seq_printf(s, "%-32s\t%u\n",
4612b6cb8f2SKate Hsuan 			   debugfs_conf->pss_wakeup[index].name,
4622b6cb8f2SKate Hsuan 			   pss_ltr_blkd[index]);
4632b6cb8f2SKate Hsuan 	}
4642b6cb8f2SKate Hsuan 
4652b6cb8f2SKate Hsuan 	return 0;
4662b6cb8f2SKate Hsuan }
4672b6cb8f2SKate Hsuan 
4682b6cb8f2SKate Hsuan DEFINE_SHOW_ATTRIBUTE(telem_pss_states);
4692b6cb8f2SKate Hsuan 
telem_ioss_states_show(struct seq_file * s,void * unused)4702b6cb8f2SKate Hsuan static int telem_ioss_states_show(struct seq_file *s, void *unused)
4712b6cb8f2SKate Hsuan {
4722b6cb8f2SKate Hsuan 	struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];
4732b6cb8f2SKate Hsuan 	const char *name[TELEM_MAX_OS_ALLOCATED_EVENTS];
4742b6cb8f2SKate Hsuan 	int index, ret, err;
4752b6cb8f2SKate Hsuan 
4762b6cb8f2SKate Hsuan 	ret = telemetry_read_eventlog(TELEM_IOSS, evtlog,
4772b6cb8f2SKate Hsuan 				      TELEM_MAX_OS_ALLOCATED_EVENTS);
4782b6cb8f2SKate Hsuan 	if (ret < 0)
4792b6cb8f2SKate Hsuan 		return ret;
4802b6cb8f2SKate Hsuan 
4812b6cb8f2SKate Hsuan 	err = telemetry_get_evtname(TELEM_IOSS, name,
4822b6cb8f2SKate Hsuan 				    TELEM_MAX_OS_ALLOCATED_EVENTS);
4832b6cb8f2SKate Hsuan 	if (err < 0)
4842b6cb8f2SKate Hsuan 		return err;
4852b6cb8f2SKate Hsuan 
4862b6cb8f2SKate Hsuan 	seq_puts(s, "--------------------------------------\n");
4872b6cb8f2SKate Hsuan 	seq_puts(s, "\tI0SS TELEMETRY EVENTLOG\n");
4882b6cb8f2SKate Hsuan 	seq_puts(s, "--------------------------------------\n");
4892b6cb8f2SKate Hsuan 	for (index = 0; index < ret; index++) {
4902b6cb8f2SKate Hsuan 		seq_printf(s, "%-32s 0x%llx\n",
4912b6cb8f2SKate Hsuan 			   name[index], evtlog[index].telem_evtlog);
4922b6cb8f2SKate Hsuan 	}
4932b6cb8f2SKate Hsuan 
4942b6cb8f2SKate Hsuan 	return 0;
4952b6cb8f2SKate Hsuan }
4962b6cb8f2SKate Hsuan 
4972b6cb8f2SKate Hsuan DEFINE_SHOW_ATTRIBUTE(telem_ioss_states);
4982b6cb8f2SKate Hsuan 
telem_soc_states_show(struct seq_file * s,void * unused)4992b6cb8f2SKate Hsuan static int telem_soc_states_show(struct seq_file *s, void *unused)
5002b6cb8f2SKate Hsuan {
5012b6cb8f2SKate Hsuan 	u32 d3_sts[TELEM_IOSS_DX_D0IX_EVTS], d0ix_sts[TELEM_IOSS_DX_D0IX_EVTS];
5022b6cb8f2SKate Hsuan 	u32 pg_sts[TELEM_IOSS_PG_EVTS], pss_idle[TELEM_PSS_IDLE_EVTS];
5032b6cb8f2SKate Hsuan 	struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];
5042b6cb8f2SKate Hsuan 	u32 s0ix_total_ctr = 0, s0ix_shlw_ctr = 0, s0ix_deep_ctr = 0;
5052b6cb8f2SKate Hsuan 	u64 s0ix_total_res = 0, s0ix_shlw_res = 0, s0ix_deep_res = 0;
5062b6cb8f2SKate Hsuan 	struct telemetry_debugfs_conf *conf = debugfs_conf;
5072b6cb8f2SKate Hsuan 	struct pci_dev *dev = NULL;
5082b6cb8f2SKate Hsuan 	int index, idx, ret;
5092b6cb8f2SKate Hsuan 	u32 d3_state;
5102b6cb8f2SKate Hsuan 	u16 pmcsr;
5112b6cb8f2SKate Hsuan 
5122b6cb8f2SKate Hsuan 	ret = telemetry_read_eventlog(TELEM_IOSS, evtlog,
5132b6cb8f2SKate Hsuan 				      TELEM_MAX_OS_ALLOCATED_EVENTS);
5142b6cb8f2SKate Hsuan 	if (ret < 0)
5152b6cb8f2SKate Hsuan 		return ret;
5162b6cb8f2SKate Hsuan 
5172b6cb8f2SKate Hsuan 	for (index = 0; index < ret; index++) {
5182b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_EVTS(conf->ioss_d3_id,
5192b6cb8f2SKate Hsuan 					   conf->ioss_d0ix_evts,
5202b6cb8f2SKate Hsuan 					   d3_sts, evtlog[index].telem_evtlog,
5212b6cb8f2SKate Hsuan 					   conf->ioss_d0ix_data,
5222b6cb8f2SKate Hsuan 					   TELEM_MASK_BIT);
5232b6cb8f2SKate Hsuan 
5242b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_EVTS(conf->ioss_pg_id, conf->ioss_pg_evts,
5252b6cb8f2SKate Hsuan 					   pg_sts, evtlog[index].telem_evtlog,
5262b6cb8f2SKate Hsuan 					   conf->ioss_pg_data, TELEM_MASK_BIT);
5272b6cb8f2SKate Hsuan 
5282b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_EVTS(conf->ioss_d0ix_id,
5292b6cb8f2SKate Hsuan 					   conf->ioss_d0ix_evts,
5302b6cb8f2SKate Hsuan 					   d0ix_sts, evtlog[index].telem_evtlog,
5312b6cb8f2SKate Hsuan 					   conf->ioss_d0ix_data,
5322b6cb8f2SKate Hsuan 					   TELEM_MASK_BIT);
5332b6cb8f2SKate Hsuan 
5342b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_total_occ_id,
5352b6cb8f2SKate Hsuan 					   s0ix_total_ctr);
5362b6cb8f2SKate Hsuan 
5372b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_occ_id,
5382b6cb8f2SKate Hsuan 					   s0ix_shlw_ctr);
5392b6cb8f2SKate Hsuan 
5402b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_occ_id,
5412b6cb8f2SKate Hsuan 					   s0ix_deep_ctr);
5422b6cb8f2SKate Hsuan 
5432b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_total_res_id,
5442b6cb8f2SKate Hsuan 					   s0ix_total_res);
5452b6cb8f2SKate Hsuan 
5462b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_res_id,
5472b6cb8f2SKate Hsuan 					   s0ix_shlw_res);
5482b6cb8f2SKate Hsuan 
5492b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_res_id,
5502b6cb8f2SKate Hsuan 					   s0ix_deep_res);
5512b6cb8f2SKate Hsuan 	}
5522b6cb8f2SKate Hsuan 
5532b6cb8f2SKate Hsuan 	seq_puts(s, "\n---------------------------------------------------\n");
5542b6cb8f2SKate Hsuan 	seq_puts(s, "S0IX Type\t\t\t Occurrence\t\t Residency(us)\n");
5552b6cb8f2SKate Hsuan 	seq_puts(s, "---------------------------------------------------\n");
5562b6cb8f2SKate Hsuan 
5572b6cb8f2SKate Hsuan 	seq_printf(s, "S0IX Shallow\t\t\t %10u\t %10llu\n",
5582b6cb8f2SKate Hsuan 		   s0ix_shlw_ctr -
5592b6cb8f2SKate Hsuan 		   conf->suspend_stats.shlw_ctr,
5602b6cb8f2SKate Hsuan 		   (u64)((s0ix_shlw_res -
5612b6cb8f2SKate Hsuan 		   conf->suspend_stats.shlw_res)*10/192));
5622b6cb8f2SKate Hsuan 
5632b6cb8f2SKate Hsuan 	seq_printf(s, "S0IX Deep\t\t\t %10u\t %10llu\n",
5642b6cb8f2SKate Hsuan 		   s0ix_deep_ctr -
5652b6cb8f2SKate Hsuan 		   conf->suspend_stats.deep_ctr,
5662b6cb8f2SKate Hsuan 		   (u64)((s0ix_deep_res -
5672b6cb8f2SKate Hsuan 		   conf->suspend_stats.deep_res)*10/192));
5682b6cb8f2SKate Hsuan 
5692b6cb8f2SKate Hsuan 	seq_printf(s, "Suspend(With S0ixShallow)\t %10u\t %10llu\n",
5702b6cb8f2SKate Hsuan 		   conf->suspend_stats.shlw_ctr,
5712b6cb8f2SKate Hsuan 		   (u64)(conf->suspend_stats.shlw_res*10)/192);
5722b6cb8f2SKate Hsuan 
5732b6cb8f2SKate Hsuan 	seq_printf(s, "Suspend(With S0ixDeep)\t\t %10u\t %10llu\n",
5742b6cb8f2SKate Hsuan 		   conf->suspend_stats.deep_ctr,
5752b6cb8f2SKate Hsuan 		   (u64)(conf->suspend_stats.deep_res*10)/192);
5762b6cb8f2SKate Hsuan 
5772b6cb8f2SKate Hsuan 	seq_printf(s, "TOTAL S0IX\t\t\t %10u\t %10llu\n", s0ix_total_ctr,
5782b6cb8f2SKate Hsuan 		   (u64)(s0ix_total_res*10/192));
5792b6cb8f2SKate Hsuan 	seq_puts(s, "\n-------------------------------------------------\n");
5802b6cb8f2SKate Hsuan 	seq_puts(s, "\t\tDEVICE STATES\n");
5812b6cb8f2SKate Hsuan 	seq_puts(s, "-------------------------------------------------\n");
5822b6cb8f2SKate Hsuan 
5832b6cb8f2SKate Hsuan 	for_each_pci_dev(dev) {
5842b6cb8f2SKate Hsuan 		pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
5852b6cb8f2SKate Hsuan 		d3_state = ((pmcsr & PCI_PM_CTRL_STATE_MASK) ==
5862b6cb8f2SKate Hsuan 			    (__force int)PCI_D3hot) ? 1 : 0;
5872b6cb8f2SKate Hsuan 
5882b6cb8f2SKate Hsuan 		seq_printf(s, "pci %04x %04X %s %20.20s: ",
5892b6cb8f2SKate Hsuan 			   dev->vendor, dev->device, dev_name(&dev->dev),
5902b6cb8f2SKate Hsuan 			   dev_driver_string(&dev->dev));
5912b6cb8f2SKate Hsuan 		seq_printf(s, " d3:%x\n", d3_state);
5922b6cb8f2SKate Hsuan 	}
5932b6cb8f2SKate Hsuan 
5942b6cb8f2SKate Hsuan 	seq_puts(s, "\n--------------------------------------\n");
5952b6cb8f2SKate Hsuan 	seq_puts(s, "D3/D0i3 Status\n");
5962b6cb8f2SKate Hsuan 	seq_puts(s, "--------------------------------------\n");
5972b6cb8f2SKate Hsuan 	seq_puts(s, "Block\t\t D3\t D0i3\n");
5982b6cb8f2SKate Hsuan 	for (index = 0; index < conf->ioss_d0ix_evts; index++) {
5992b6cb8f2SKate Hsuan 		seq_printf(s, "%-10s\t %u\t %u\n",
6002b6cb8f2SKate Hsuan 			   conf->ioss_d0ix_data[index].name,
6012b6cb8f2SKate Hsuan 			   d3_sts[index], d0ix_sts[index]);
6022b6cb8f2SKate Hsuan 	}
6032b6cb8f2SKate Hsuan 
6042b6cb8f2SKate Hsuan 	seq_puts(s, "\n--------------------------------------\n");
6052b6cb8f2SKate Hsuan 	seq_puts(s, "South Complex PowerGate Status\n");
6062b6cb8f2SKate Hsuan 	seq_puts(s, "--------------------------------------\n");
6072b6cb8f2SKate Hsuan 	seq_puts(s, "Device\t\t PG\n");
6082b6cb8f2SKate Hsuan 	for (index = 0; index < conf->ioss_pg_evts; index++) {
6092b6cb8f2SKate Hsuan 		seq_printf(s, "%-10s\t %u\n",
6102b6cb8f2SKate Hsuan 			   conf->ioss_pg_data[index].name,
6112b6cb8f2SKate Hsuan 			   pg_sts[index]);
6122b6cb8f2SKate Hsuan 	}
6132b6cb8f2SKate Hsuan 
6142b6cb8f2SKate Hsuan 	evtlog->telem_evtid = conf->pss_idle_id;
6152b6cb8f2SKate Hsuan 	ret = telemetry_read_events(TELEM_PSS, evtlog, 1);
6162b6cb8f2SKate Hsuan 	if (ret < 0)
6172b6cb8f2SKate Hsuan 		return ret;
6182b6cb8f2SKate Hsuan 
6192b6cb8f2SKate Hsuan 	seq_puts(s, "\n-----------------------------------------\n");
6202b6cb8f2SKate Hsuan 	seq_puts(s, "North Idle Status\n");
6212b6cb8f2SKate Hsuan 	seq_puts(s, "-----------------------------------------\n");
6222b6cb8f2SKate Hsuan 	for (idx = 0; idx < conf->pss_idle_evts - 1; idx++) {
6232b6cb8f2SKate Hsuan 		pss_idle[idx] =	(evtlog->telem_evtlog >>
6242b6cb8f2SKate Hsuan 				conf->pss_idle_data[idx].bit_pos) &
6252b6cb8f2SKate Hsuan 				TELEM_MASK_BIT;
6262b6cb8f2SKate Hsuan 	}
6272b6cb8f2SKate Hsuan 
6282b6cb8f2SKate Hsuan 	pss_idle[idx] = (evtlog->telem_evtlog >>
6292b6cb8f2SKate Hsuan 			conf->pss_idle_data[idx].bit_pos) &
6302b6cb8f2SKate Hsuan 			TELEM_APL_MASK_PCS_STATE;
6312b6cb8f2SKate Hsuan 
6322b6cb8f2SKate Hsuan 	for (index = 0; index < conf->pss_idle_evts; index++) {
6332b6cb8f2SKate Hsuan 		seq_printf(s, "%-30s %u\n",
6342b6cb8f2SKate Hsuan 			   conf->pss_idle_data[index].name,
6352b6cb8f2SKate Hsuan 			   pss_idle[index]);
6362b6cb8f2SKate Hsuan 	}
6372b6cb8f2SKate Hsuan 
6382b6cb8f2SKate Hsuan 	seq_puts(s, "\nPCS_STATUS Code\n");
6392b6cb8f2SKate Hsuan 	seq_puts(s, "0:C0 1:C1 2:C1_DN_WT_DEV 3:C2 4:C2_WT_DE_MEM_UP\n");
6402b6cb8f2SKate Hsuan 	seq_puts(s, "5:C2_WT_DE_MEM_DOWN 6:C2_UP_WT_DEV 7:C2_DN 8:C2_VOA\n");
6412b6cb8f2SKate Hsuan 	seq_puts(s, "9:C2_VOA_UP 10:S0IX_PRE 11:S0IX\n");
6422b6cb8f2SKate Hsuan 
6432b6cb8f2SKate Hsuan 	return 0;
6442b6cb8f2SKate Hsuan }
6452b6cb8f2SKate Hsuan 
6462b6cb8f2SKate Hsuan DEFINE_SHOW_ATTRIBUTE(telem_soc_states);
6472b6cb8f2SKate Hsuan 
telem_s0ix_res_get(void * data,u64 * val)6482b6cb8f2SKate Hsuan static int telem_s0ix_res_get(void *data, u64 *val)
6492b6cb8f2SKate Hsuan {
6502b6cb8f2SKate Hsuan 	struct telemetry_plt_config *plt_config = telemetry_get_pltdata();
6512b6cb8f2SKate Hsuan 	u64 s0ix_total_res;
6522b6cb8f2SKate Hsuan 	int ret;
6532b6cb8f2SKate Hsuan 
6542b6cb8f2SKate Hsuan 	ret = intel_pmc_s0ix_counter_read(plt_config->pmc, &s0ix_total_res);
6552b6cb8f2SKate Hsuan 	if (ret) {
6562b6cb8f2SKate Hsuan 		pr_err("Failed to read S0ix residency");
6572b6cb8f2SKate Hsuan 		return ret;
6582b6cb8f2SKate Hsuan 	}
6592b6cb8f2SKate Hsuan 
6602b6cb8f2SKate Hsuan 	*val = s0ix_total_res;
6612b6cb8f2SKate Hsuan 
6622b6cb8f2SKate Hsuan 	return 0;
6632b6cb8f2SKate Hsuan }
6642b6cb8f2SKate Hsuan 
6652b6cb8f2SKate Hsuan DEFINE_DEBUGFS_ATTRIBUTE(telem_s0ix_fops, telem_s0ix_res_get, NULL, "%llu\n");
6662b6cb8f2SKate Hsuan 
telem_pss_trc_verb_show(struct seq_file * s,void * unused)6672b6cb8f2SKate Hsuan static int telem_pss_trc_verb_show(struct seq_file *s, void *unused)
6682b6cb8f2SKate Hsuan {
6692b6cb8f2SKate Hsuan 	u32 verbosity;
6702b6cb8f2SKate Hsuan 	int err;
6712b6cb8f2SKate Hsuan 
6722b6cb8f2SKate Hsuan 	err = telemetry_get_trace_verbosity(TELEM_PSS, &verbosity);
6732b6cb8f2SKate Hsuan 	if (err) {
6742b6cb8f2SKate Hsuan 		pr_err("Get PSS Trace Verbosity Failed with Error %d\n", err);
6752b6cb8f2SKate Hsuan 		return -EFAULT;
6762b6cb8f2SKate Hsuan 	}
6772b6cb8f2SKate Hsuan 
6782b6cb8f2SKate Hsuan 	seq_printf(s, "PSS Trace Verbosity %u\n", verbosity);
6792b6cb8f2SKate Hsuan 	return 0;
6802b6cb8f2SKate Hsuan }
6812b6cb8f2SKate Hsuan 
telem_pss_trc_verb_write(struct file * file,const char __user * userbuf,size_t count,loff_t * ppos)6822b6cb8f2SKate Hsuan static ssize_t telem_pss_trc_verb_write(struct file *file,
6832b6cb8f2SKate Hsuan 					const char __user *userbuf,
6842b6cb8f2SKate Hsuan 					size_t count, loff_t *ppos)
6852b6cb8f2SKate Hsuan {
6862b6cb8f2SKate Hsuan 	u32 verbosity;
6872b6cb8f2SKate Hsuan 	int err;
6882b6cb8f2SKate Hsuan 
6892b6cb8f2SKate Hsuan 	err = kstrtou32_from_user(userbuf, count, 0, &verbosity);
6902b6cb8f2SKate Hsuan 	if (err)
6912b6cb8f2SKate Hsuan 		return err;
6922b6cb8f2SKate Hsuan 
6932b6cb8f2SKate Hsuan 	err = telemetry_set_trace_verbosity(TELEM_PSS, verbosity);
6942b6cb8f2SKate Hsuan 	if (err) {
6952b6cb8f2SKate Hsuan 		pr_err("Changing PSS Trace Verbosity Failed. Error %d\n", err);
6962b6cb8f2SKate Hsuan 		return err;
6972b6cb8f2SKate Hsuan 	}
6982b6cb8f2SKate Hsuan 
6992b6cb8f2SKate Hsuan 	return count;
7002b6cb8f2SKate Hsuan }
7012b6cb8f2SKate Hsuan 
telem_pss_trc_verb_open(struct inode * inode,struct file * file)7022b6cb8f2SKate Hsuan static int telem_pss_trc_verb_open(struct inode *inode, struct file *file)
7032b6cb8f2SKate Hsuan {
7042b6cb8f2SKate Hsuan 	return single_open(file, telem_pss_trc_verb_show, inode->i_private);
7052b6cb8f2SKate Hsuan }
7062b6cb8f2SKate Hsuan 
7072b6cb8f2SKate Hsuan static const struct file_operations telem_pss_trc_verb_ops = {
7082b6cb8f2SKate Hsuan 	.open		= telem_pss_trc_verb_open,
7092b6cb8f2SKate Hsuan 	.read		= seq_read,
7102b6cb8f2SKate Hsuan 	.write		= telem_pss_trc_verb_write,
7112b6cb8f2SKate Hsuan 	.llseek		= seq_lseek,
7122b6cb8f2SKate Hsuan 	.release	= single_release,
7132b6cb8f2SKate Hsuan };
7142b6cb8f2SKate Hsuan 
telem_ioss_trc_verb_show(struct seq_file * s,void * unused)7152b6cb8f2SKate Hsuan static int telem_ioss_trc_verb_show(struct seq_file *s, void *unused)
7162b6cb8f2SKate Hsuan {
7172b6cb8f2SKate Hsuan 	u32 verbosity;
7182b6cb8f2SKate Hsuan 	int err;
7192b6cb8f2SKate Hsuan 
7202b6cb8f2SKate Hsuan 	err = telemetry_get_trace_verbosity(TELEM_IOSS, &verbosity);
7212b6cb8f2SKate Hsuan 	if (err) {
7222b6cb8f2SKate Hsuan 		pr_err("Get IOSS Trace Verbosity Failed with Error %d\n", err);
7232b6cb8f2SKate Hsuan 		return -EFAULT;
7242b6cb8f2SKate Hsuan 	}
7252b6cb8f2SKate Hsuan 
7262b6cb8f2SKate Hsuan 	seq_printf(s, "IOSS Trace Verbosity %u\n", verbosity);
7272b6cb8f2SKate Hsuan 	return 0;
7282b6cb8f2SKate Hsuan }
7292b6cb8f2SKate Hsuan 
telem_ioss_trc_verb_write(struct file * file,const char __user * userbuf,size_t count,loff_t * ppos)7302b6cb8f2SKate Hsuan static ssize_t telem_ioss_trc_verb_write(struct file *file,
7312b6cb8f2SKate Hsuan 					 const char __user *userbuf,
7322b6cb8f2SKate Hsuan 					 size_t count, loff_t *ppos)
7332b6cb8f2SKate Hsuan {
7342b6cb8f2SKate Hsuan 	u32 verbosity;
7352b6cb8f2SKate Hsuan 	int err;
7362b6cb8f2SKate Hsuan 
7372b6cb8f2SKate Hsuan 	err = kstrtou32_from_user(userbuf, count, 0, &verbosity);
7382b6cb8f2SKate Hsuan 	if (err)
7392b6cb8f2SKate Hsuan 		return err;
7402b6cb8f2SKate Hsuan 
7412b6cb8f2SKate Hsuan 	err = telemetry_set_trace_verbosity(TELEM_IOSS, verbosity);
7422b6cb8f2SKate Hsuan 	if (err) {
7432b6cb8f2SKate Hsuan 		pr_err("Changing IOSS Trace Verbosity Failed. Error %d\n", err);
7442b6cb8f2SKate Hsuan 		return err;
7452b6cb8f2SKate Hsuan 	}
7462b6cb8f2SKate Hsuan 
7472b6cb8f2SKate Hsuan 	return count;
7482b6cb8f2SKate Hsuan }
7492b6cb8f2SKate Hsuan 
telem_ioss_trc_verb_open(struct inode * inode,struct file * file)7502b6cb8f2SKate Hsuan static int telem_ioss_trc_verb_open(struct inode *inode, struct file *file)
7512b6cb8f2SKate Hsuan {
7522b6cb8f2SKate Hsuan 	return single_open(file, telem_ioss_trc_verb_show, inode->i_private);
7532b6cb8f2SKate Hsuan }
7542b6cb8f2SKate Hsuan 
7552b6cb8f2SKate Hsuan static const struct file_operations telem_ioss_trc_verb_ops = {
7562b6cb8f2SKate Hsuan 	.open		= telem_ioss_trc_verb_open,
7572b6cb8f2SKate Hsuan 	.read		= seq_read,
7582b6cb8f2SKate Hsuan 	.write		= telem_ioss_trc_verb_write,
7592b6cb8f2SKate Hsuan 	.llseek		= seq_lseek,
7602b6cb8f2SKate Hsuan 	.release	= single_release,
7612b6cb8f2SKate Hsuan };
7622b6cb8f2SKate Hsuan 
pm_suspend_prep_cb(void)7632b6cb8f2SKate Hsuan static int pm_suspend_prep_cb(void)
7642b6cb8f2SKate Hsuan {
7652b6cb8f2SKate Hsuan 	struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];
7662b6cb8f2SKate Hsuan 	struct telemetry_debugfs_conf *conf = debugfs_conf;
7672b6cb8f2SKate Hsuan 	int ret, index;
7682b6cb8f2SKate Hsuan 
7692b6cb8f2SKate Hsuan 	ret = telemetry_raw_read_eventlog(TELEM_IOSS, evtlog,
7702b6cb8f2SKate Hsuan 			TELEM_MAX_OS_ALLOCATED_EVENTS);
7712b6cb8f2SKate Hsuan 	if (ret < 0) {
7722b6cb8f2SKate Hsuan 		suspend_prep_ok = 0;
7732b6cb8f2SKate Hsuan 		goto out;
7742b6cb8f2SKate Hsuan 	}
7752b6cb8f2SKate Hsuan 
7762b6cb8f2SKate Hsuan 	for (index = 0; index < ret; index++) {
7772b6cb8f2SKate Hsuan 
7782b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_occ_id,
7792b6cb8f2SKate Hsuan 					   suspend_shlw_ctr_temp);
7802b6cb8f2SKate Hsuan 
7812b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_occ_id,
7822b6cb8f2SKate Hsuan 					   suspend_deep_ctr_temp);
7832b6cb8f2SKate Hsuan 
7842b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_res_id,
7852b6cb8f2SKate Hsuan 					   suspend_shlw_res_temp);
7862b6cb8f2SKate Hsuan 
7872b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_res_id,
7882b6cb8f2SKate Hsuan 					   suspend_deep_res_temp);
7892b6cb8f2SKate Hsuan 	}
7902b6cb8f2SKate Hsuan 	suspend_prep_ok = 1;
7912b6cb8f2SKate Hsuan out:
7922b6cb8f2SKate Hsuan 	return NOTIFY_OK;
7932b6cb8f2SKate Hsuan }
7942b6cb8f2SKate Hsuan 
pm_suspend_exit_cb(void)7952b6cb8f2SKate Hsuan static int pm_suspend_exit_cb(void)
7962b6cb8f2SKate Hsuan {
7972b6cb8f2SKate Hsuan 	struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];
7982b6cb8f2SKate Hsuan 	static u32 suspend_shlw_ctr_exit, suspend_deep_ctr_exit;
7992b6cb8f2SKate Hsuan 	static u64 suspend_shlw_res_exit, suspend_deep_res_exit;
8002b6cb8f2SKate Hsuan 	struct telemetry_debugfs_conf *conf = debugfs_conf;
8012b6cb8f2SKate Hsuan 	int ret, index;
8022b6cb8f2SKate Hsuan 
8032b6cb8f2SKate Hsuan 	if (!suspend_prep_ok)
8042b6cb8f2SKate Hsuan 		goto out;
8052b6cb8f2SKate Hsuan 
8062b6cb8f2SKate Hsuan 	ret = telemetry_raw_read_eventlog(TELEM_IOSS, evtlog,
8072b6cb8f2SKate Hsuan 					  TELEM_MAX_OS_ALLOCATED_EVENTS);
8082b6cb8f2SKate Hsuan 	if (ret < 0)
8092b6cb8f2SKate Hsuan 		goto out;
8102b6cb8f2SKate Hsuan 
8112b6cb8f2SKate Hsuan 	for (index = 0; index < ret; index++) {
8122b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_occ_id,
8132b6cb8f2SKate Hsuan 					   suspend_shlw_ctr_exit);
8142b6cb8f2SKate Hsuan 
8152b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_occ_id,
8162b6cb8f2SKate Hsuan 					   suspend_deep_ctr_exit);
8172b6cb8f2SKate Hsuan 
8182b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_res_id,
8192b6cb8f2SKate Hsuan 					   suspend_shlw_res_exit);
8202b6cb8f2SKate Hsuan 
8212b6cb8f2SKate Hsuan 		TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_res_id,
8222b6cb8f2SKate Hsuan 					   suspend_deep_res_exit);
8232b6cb8f2SKate Hsuan 	}
8242b6cb8f2SKate Hsuan 
8252b6cb8f2SKate Hsuan 	if ((suspend_shlw_ctr_exit < suspend_shlw_ctr_temp) ||
8262b6cb8f2SKate Hsuan 	    (suspend_deep_ctr_exit < suspend_deep_ctr_temp) ||
8272b6cb8f2SKate Hsuan 	    (suspend_shlw_res_exit < suspend_shlw_res_temp) ||
8282b6cb8f2SKate Hsuan 	    (suspend_deep_res_exit < suspend_deep_res_temp)) {
8292b6cb8f2SKate Hsuan 		pr_err("Wrong s0ix counters detected\n");
8302b6cb8f2SKate Hsuan 		goto out;
8312b6cb8f2SKate Hsuan 	}
8322b6cb8f2SKate Hsuan 
8332b6cb8f2SKate Hsuan 	/*
8342b6cb8f2SKate Hsuan 	 * Due to some design limitations in the firmware, sometimes the
8352b6cb8f2SKate Hsuan 	 * counters do not get updated by the time we reach here. As a
8362b6cb8f2SKate Hsuan 	 * workaround, we try to see if this was a genuine case of sleep
8372b6cb8f2SKate Hsuan 	 * failure or not by cross-checking from PMC GCR registers directly.
8382b6cb8f2SKate Hsuan 	 */
8392b6cb8f2SKate Hsuan 	if (suspend_shlw_ctr_exit == suspend_shlw_ctr_temp &&
8402b6cb8f2SKate Hsuan 	    suspend_deep_ctr_exit == suspend_deep_ctr_temp) {
8412b6cb8f2SKate Hsuan 		struct telemetry_plt_config *plt_config = telemetry_get_pltdata();
8422b6cb8f2SKate Hsuan 		struct intel_pmc_dev *pmc = plt_config->pmc;
8432b6cb8f2SKate Hsuan 
8442b6cb8f2SKate Hsuan 		ret = intel_pmc_gcr_read64(pmc, PMC_GCR_TELEM_SHLW_S0IX_REG,
8452b6cb8f2SKate Hsuan 					  &suspend_shlw_res_exit);
8462b6cb8f2SKate Hsuan 		if (ret < 0)
8472b6cb8f2SKate Hsuan 			goto out;
8482b6cb8f2SKate Hsuan 
8492b6cb8f2SKate Hsuan 		ret = intel_pmc_gcr_read64(pmc, PMC_GCR_TELEM_DEEP_S0IX_REG,
8502b6cb8f2SKate Hsuan 					  &suspend_deep_res_exit);
8512b6cb8f2SKate Hsuan 		if (ret < 0)
8522b6cb8f2SKate Hsuan 			goto out;
8532b6cb8f2SKate Hsuan 
8542b6cb8f2SKate Hsuan 		if (suspend_shlw_res_exit > suspend_shlw_res_temp)
8552b6cb8f2SKate Hsuan 			suspend_shlw_ctr_exit++;
8562b6cb8f2SKate Hsuan 
8572b6cb8f2SKate Hsuan 		if (suspend_deep_res_exit > suspend_deep_res_temp)
8582b6cb8f2SKate Hsuan 			suspend_deep_ctr_exit++;
8592b6cb8f2SKate Hsuan 	}
8602b6cb8f2SKate Hsuan 
8612b6cb8f2SKate Hsuan 	suspend_shlw_ctr_exit -= suspend_shlw_ctr_temp;
8622b6cb8f2SKate Hsuan 	suspend_deep_ctr_exit -= suspend_deep_ctr_temp;
8632b6cb8f2SKate Hsuan 	suspend_shlw_res_exit -= suspend_shlw_res_temp;
8642b6cb8f2SKate Hsuan 	suspend_deep_res_exit -= suspend_deep_res_temp;
8652b6cb8f2SKate Hsuan 
8662b6cb8f2SKate Hsuan 	if (suspend_shlw_ctr_exit != 0) {
8672b6cb8f2SKate Hsuan 		conf->suspend_stats.shlw_ctr +=
8682b6cb8f2SKate Hsuan 		suspend_shlw_ctr_exit;
8692b6cb8f2SKate Hsuan 
8702b6cb8f2SKate Hsuan 		conf->suspend_stats.shlw_res +=
8712b6cb8f2SKate Hsuan 		suspend_shlw_res_exit;
8722b6cb8f2SKate Hsuan 	}
8732b6cb8f2SKate Hsuan 
8742b6cb8f2SKate Hsuan 	if (suspend_deep_ctr_exit != 0) {
8752b6cb8f2SKate Hsuan 		conf->suspend_stats.deep_ctr +=
8762b6cb8f2SKate Hsuan 		suspend_deep_ctr_exit;
8772b6cb8f2SKate Hsuan 
8782b6cb8f2SKate Hsuan 		conf->suspend_stats.deep_res +=
8792b6cb8f2SKate Hsuan 		suspend_deep_res_exit;
8802b6cb8f2SKate Hsuan 	}
8812b6cb8f2SKate Hsuan 
8822b6cb8f2SKate Hsuan out:
8832b6cb8f2SKate Hsuan 	suspend_prep_ok = 0;
8842b6cb8f2SKate Hsuan 	return NOTIFY_OK;
8852b6cb8f2SKate Hsuan }
8862b6cb8f2SKate Hsuan 
pm_notification(struct notifier_block * this,unsigned long event,void * ptr)8872b6cb8f2SKate Hsuan static int pm_notification(struct notifier_block *this,
8882b6cb8f2SKate Hsuan 			   unsigned long event, void *ptr)
8892b6cb8f2SKate Hsuan {
8902b6cb8f2SKate Hsuan 	switch (event) {
8912b6cb8f2SKate Hsuan 	case PM_SUSPEND_PREPARE:
8922b6cb8f2SKate Hsuan 		return pm_suspend_prep_cb();
8932b6cb8f2SKate Hsuan 	case PM_POST_SUSPEND:
8942b6cb8f2SKate Hsuan 		return pm_suspend_exit_cb();
8952b6cb8f2SKate Hsuan 	}
8962b6cb8f2SKate Hsuan 
8972b6cb8f2SKate Hsuan 	return NOTIFY_DONE;
8982b6cb8f2SKate Hsuan }
8992b6cb8f2SKate Hsuan 
9002b6cb8f2SKate Hsuan static struct notifier_block pm_notifier = {
9012b6cb8f2SKate Hsuan 	.notifier_call = pm_notification,
9022b6cb8f2SKate Hsuan };
9032b6cb8f2SKate Hsuan 
telemetry_debugfs_init(void)9042b6cb8f2SKate Hsuan static int __init telemetry_debugfs_init(void)
9052b6cb8f2SKate Hsuan {
9062b6cb8f2SKate Hsuan 	const struct x86_cpu_id *id;
9072b6cb8f2SKate Hsuan 	int err;
9082b6cb8f2SKate Hsuan 	struct dentry *dir;
9092b6cb8f2SKate Hsuan 
9102b6cb8f2SKate Hsuan 	/* Only APL supported for now */
9112b6cb8f2SKate Hsuan 	id = x86_match_cpu(telemetry_debugfs_cpu_ids);
9122b6cb8f2SKate Hsuan 	if (!id)
9132b6cb8f2SKate Hsuan 		return -ENODEV;
9142b6cb8f2SKate Hsuan 
9152b6cb8f2SKate Hsuan 	debugfs_conf = (struct telemetry_debugfs_conf *)id->driver_data;
9162b6cb8f2SKate Hsuan 
9172b6cb8f2SKate Hsuan 	if (!telemetry_get_pltdata()) {
9182b6cb8f2SKate Hsuan 		pr_info("Invalid pltconfig, ensure IPC1 device is enabled in BIOS\n");
9192b6cb8f2SKate Hsuan 		return -ENODEV;
9202b6cb8f2SKate Hsuan 	}
9212b6cb8f2SKate Hsuan 
9222b6cb8f2SKate Hsuan 	err = telemetry_debugfs_check_evts();
9232b6cb8f2SKate Hsuan 	if (err < 0) {
9242b6cb8f2SKate Hsuan 		pr_info("telemetry_debugfs_check_evts failed\n");
9252b6cb8f2SKate Hsuan 		return -EINVAL;
9262b6cb8f2SKate Hsuan 	}
9272b6cb8f2SKate Hsuan 
9282b6cb8f2SKate Hsuan 	register_pm_notifier(&pm_notifier);
9292b6cb8f2SKate Hsuan 
9302b6cb8f2SKate Hsuan 	dir = debugfs_create_dir("telemetry", NULL);
9312b6cb8f2SKate Hsuan 	debugfs_conf->telemetry_dbg_dir = dir;
9322b6cb8f2SKate Hsuan 
9332b6cb8f2SKate Hsuan 	debugfs_create_file("pss_info", S_IFREG | S_IRUGO, dir, NULL,
9342b6cb8f2SKate Hsuan 			    &telem_pss_states_fops);
9352b6cb8f2SKate Hsuan 	debugfs_create_file("ioss_info", S_IFREG | S_IRUGO, dir, NULL,
9362b6cb8f2SKate Hsuan 			    &telem_ioss_states_fops);
9372b6cb8f2SKate Hsuan 	debugfs_create_file("soc_states", S_IFREG | S_IRUGO, dir, NULL,
9382b6cb8f2SKate Hsuan 			    &telem_soc_states_fops);
9392b6cb8f2SKate Hsuan 	debugfs_create_file("s0ix_residency_usec", S_IFREG | S_IRUGO, dir, NULL,
9402b6cb8f2SKate Hsuan 			    &telem_s0ix_fops);
9412b6cb8f2SKate Hsuan 	debugfs_create_file("pss_trace_verbosity", S_IFREG | S_IRUGO, dir, NULL,
9422b6cb8f2SKate Hsuan 			    &telem_pss_trc_verb_ops);
9432b6cb8f2SKate Hsuan 	debugfs_create_file("ioss_trace_verbosity", S_IFREG | S_IRUGO, dir,
9442b6cb8f2SKate Hsuan 			    NULL, &telem_ioss_trc_verb_ops);
9452b6cb8f2SKate Hsuan 	return 0;
9462b6cb8f2SKate Hsuan }
9472b6cb8f2SKate Hsuan 
telemetry_debugfs_exit(void)9482b6cb8f2SKate Hsuan static void __exit telemetry_debugfs_exit(void)
9492b6cb8f2SKate Hsuan {
9502b6cb8f2SKate Hsuan 	debugfs_remove_recursive(debugfs_conf->telemetry_dbg_dir);
9512b6cb8f2SKate Hsuan 	debugfs_conf->telemetry_dbg_dir = NULL;
9522b6cb8f2SKate Hsuan 	unregister_pm_notifier(&pm_notifier);
9532b6cb8f2SKate Hsuan }
9542b6cb8f2SKate Hsuan 
9552b6cb8f2SKate Hsuan late_initcall(telemetry_debugfs_init);
9562b6cb8f2SKate Hsuan module_exit(telemetry_debugfs_exit);
9572b6cb8f2SKate Hsuan 
9582b6cb8f2SKate Hsuan MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>");
9592b6cb8f2SKate Hsuan MODULE_DESCRIPTION("Intel SoC Telemetry debugfs Interface");
9602b6cb8f2SKate Hsuan MODULE_VERSION(DRIVER_VERSION);
9612b6cb8f2SKate Hsuan MODULE_LICENSE("GPL v2");
962