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