linux/drivers/platform/x86/intel_telemetry_debugfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Intel SOC Telemetry debugfs Driver: Currently supports APL
   4 * Copyright (c) 2015, Intel Corporation.
   5 * All Rights Reserved.
   6 *
   7 * This file provides the debugfs interfaces for telemetry.
   8 * /sys/kernel/debug/telemetry/pss_info: Shows Primary Control Sub-Sys Counters
   9 * /sys/kernel/debug/telemetry/ioss_info: Shows IO Sub-System Counters
  10 * /sys/kernel/debug/telemetry/soc_states: Shows SoC State
  11 * /sys/kernel/debug/telemetry/pss_trace_verbosity: Read and Change Tracing
  12 *                              Verbosity via firmware
  13 * /sys/kernel/debug/telemetry/ioss_race_verbosity: Write and Change Tracing
  14 *                              Verbosity via firmware
  15 */
  16#include <linux/debugfs.h>
  17#include <linux/device.h>
  18#include <linux/module.h>
  19#include <linux/pci.h>
  20#include <linux/seq_file.h>
  21#include <linux/suspend.h>
  22
  23#include <asm/cpu_device_id.h>
  24#include <asm/intel-family.h>
  25#include <asm/intel_pmc_ipc.h>
  26#include <asm/intel_telemetry.h>
  27
  28#define DRIVER_NAME                     "telemetry_soc_debugfs"
  29#define DRIVER_VERSION                  "1.0.0"
  30
  31/* ApolloLake SoC Event-IDs */
  32#define TELEM_APL_PSS_PSTATES_ID        0x2802
  33#define TELEM_APL_PSS_IDLE_ID           0x2806
  34#define TELEM_APL_PCS_IDLE_BLOCKED_ID   0x2C00
  35#define TELEM_APL_PCS_S0IX_BLOCKED_ID   0x2C01
  36#define TELEM_APL_PSS_WAKEUP_ID         0x2C02
  37#define TELEM_APL_PSS_LTR_BLOCKING_ID   0x2C03
  38
  39#define TELEM_APL_S0IX_TOTAL_OCC_ID     0x4000
  40#define TELEM_APL_S0IX_SHLW_OCC_ID      0x4001
  41#define TELEM_APL_S0IX_DEEP_OCC_ID      0x4002
  42#define TELEM_APL_S0IX_TOTAL_RES_ID     0x4800
  43#define TELEM_APL_S0IX_SHLW_RES_ID      0x4801
  44#define TELEM_APL_S0IX_DEEP_RES_ID      0x4802
  45#define TELEM_APL_D0IX_ID               0x581A
  46#define TELEM_APL_D3_ID                 0x5819
  47#define TELEM_APL_PG_ID                 0x5818
  48
  49#define TELEM_INFO_SRAMEVTS_MASK        0xFF00
  50#define TELEM_INFO_SRAMEVTS_SHIFT       0x8
  51#define TELEM_SSRAM_READ_TIMEOUT        10
  52
  53#define TELEM_MASK_BIT                  1
  54#define TELEM_MASK_BYTE                 0xFF
  55#define BYTES_PER_LONG                  8
  56#define TELEM_APL_MASK_PCS_STATE        0xF
  57
  58/* Max events in bitmap to check for */
  59#define TELEM_PSS_IDLE_EVTS             25
  60#define TELEM_PSS_IDLE_BLOCKED_EVTS     20
  61#define TELEM_PSS_S0IX_BLOCKED_EVTS     20
  62#define TELEM_PSS_S0IX_WAKEUP_EVTS      20
  63#define TELEM_PSS_LTR_BLOCKING_EVTS     20
  64#define TELEM_IOSS_DX_D0IX_EVTS         25
  65#define TELEM_IOSS_PG_EVTS              30
  66
  67#define TELEM_CHECK_AND_PARSE_EVTS(EVTID, EVTNUM, BUF, EVTLOG, EVTDAT, MASK) { \
  68        if (evtlog[index].telem_evtid == (EVTID)) { \
  69                for (idx = 0; idx < (EVTNUM); idx++) \
  70                        (BUF)[idx] = ((EVTLOG) >> (EVTDAT)[idx].bit_pos) & \
  71                                     (MASK); \
  72        continue; \
  73        } \
  74}
  75
  76#define TELEM_CHECK_AND_PARSE_CTRS(EVTID, CTR) { \
  77        if (evtlog[index].telem_evtid == (EVTID)) { \
  78                (CTR) = evtlog[index].telem_evtlog; \
  79                continue; \
  80        } \
  81}
  82
  83static u8 suspend_prep_ok;
  84static u32 suspend_shlw_ctr_temp, suspend_deep_ctr_temp;
  85static u64 suspend_shlw_res_temp, suspend_deep_res_temp;
  86
  87struct telemetry_susp_stats {
  88        u32 shlw_ctr;
  89        u32 deep_ctr;
  90        u64 shlw_res;
  91        u64 deep_res;
  92};
  93
  94/* Bitmap definitions for default counters in APL */
  95struct telem_pss_idle_stateinfo {
  96        const char *name;
  97        u32 bit_pos;
  98};
  99
 100static struct telem_pss_idle_stateinfo telem_apl_pss_idle_data[] = {
 101        {"IA_CORE0_C1E",                0},
 102        {"IA_CORE1_C1E",                1},
 103        {"IA_CORE2_C1E",                2},
 104        {"IA_CORE3_C1E",                3},
 105        {"IA_CORE0_C6",                 16},
 106        {"IA_CORE1_C6",                 17},
 107        {"IA_CORE2_C6",                 18},
 108        {"IA_CORE3_C6",                 19},
 109        {"IA_MODULE0_C7",               32},
 110        {"IA_MODULE1_C7",               33},
 111        {"GT_RC6",                      40},
 112        {"IUNIT_PROCESSING_IDLE",       41},
 113        {"FAR_MEM_IDLE",                43},
 114        {"DISPLAY_IDLE",                44},
 115        {"IUNIT_INPUT_SYSTEM_IDLE",     45},
 116        {"PCS_STATUS",                  60},
 117};
 118
 119struct telem_pcs_blkd_info {
 120        const char *name;
 121        u32 bit_pos;
 122};
 123
 124static struct telem_pcs_blkd_info telem_apl_pcs_idle_blkd_data[] = {
 125        {"COMPUTE",                     0},
 126        {"MISC",                        8},
 127        {"MODULE_ACTIONS_PENDING",      16},
 128        {"LTR",                         24},
 129        {"DISPLAY_WAKE",                32},
 130        {"ISP_WAKE",                    40},
 131        {"PSF0_ACTIVE",                 48},
 132};
 133
 134static struct telem_pcs_blkd_info telem_apl_pcs_s0ix_blkd_data[] = {
 135        {"LTR",                         0},
 136        {"IRTL",                        8},
 137        {"WAKE_DEADLINE_PENDING",       16},
 138        {"DISPLAY",                     24},
 139        {"ISP",                         32},
 140        {"CORE",                        40},
 141        {"PMC",                         48},
 142        {"MISC",                        56},
 143};
 144
 145struct telem_pss_ltr_info {
 146        const char *name;
 147        u32 bit_pos;
 148};
 149
 150static struct telem_pss_ltr_info telem_apl_pss_ltr_data[] = {
 151        {"CORE_ACTIVE",         0},
 152        {"MEM_UP",              8},
 153        {"DFX",                 16},
 154        {"DFX_FORCE_LTR",       24},
 155        {"DISPLAY",             32},
 156        {"ISP",                 40},
 157        {"SOUTH",               48},
 158};
 159
 160struct telem_pss_wakeup_info {
 161        const char *name;
 162        u32 bit_pos;
 163};
 164
 165static struct telem_pss_wakeup_info telem_apl_pss_wakeup[] = {
 166        {"IP_IDLE",                     0},
 167        {"DISPLAY_WAKE",                8},
 168        {"VOLTAGE_REG_INT",             16},
 169        {"DROWSY_TIMER (HOTPLUG)",      24},
 170        {"CORE_WAKE",                   32},
 171        {"MISC_S0IX",                   40},
 172        {"MISC_ABORT",                  56},
 173};
 174
 175struct telem_ioss_d0ix_stateinfo {
 176        const char *name;
 177        u32 bit_pos;
 178};
 179
 180static struct telem_ioss_d0ix_stateinfo telem_apl_ioss_d0ix_data[] = {
 181        {"CSE",         0},
 182        {"SCC2",        1},
 183        {"GMM",         2},
 184        {"XDCI",        3},
 185        {"XHCI",        4},
 186        {"ISH",         5},
 187        {"AVS",         6},
 188        {"PCIE0P1",     7},
 189        {"PECI0P0",     8},
 190        {"LPSS",        9},
 191        {"SCC",         10},
 192        {"PWM",         11},
 193        {"PCIE1_P3",    12},
 194        {"PCIE1_P2",    13},
 195        {"PCIE1_P1",    14},
 196        {"PCIE1_P0",    15},
 197        {"CNV",         16},
 198        {"SATA",        17},
 199        {"PRTC",        18},
 200};
 201
 202struct telem_ioss_pg_info {
 203        const char *name;
 204        u32 bit_pos;
 205};
 206
 207static struct telem_ioss_pg_info telem_apl_ioss_pg_data[] = {
 208        {"LPSS",        0},
 209        {"SCC",         1},
 210        {"P2SB",        2},
 211        {"SCC2",        3},
 212        {"GMM",         4},
 213        {"PCIE0",       5},
 214        {"XDCI",        6},
 215        {"xHCI",        7},
 216        {"CSE",         8},
 217        {"SPI",         9},
 218        {"AVSPGD4",     10},
 219        {"AVSPGD3",     11},
 220        {"AVSPGD2",     12},
 221        {"AVSPGD1",     13},
 222        {"ISH",         14},
 223        {"EXI",         15},
 224        {"NPKVRC",      16},
 225        {"NPKVNN",      17},
 226        {"CUNIT",       18},
 227        {"FUSE_CTRL",   19},
 228        {"PCIE1",       20},
 229        {"CNV",         21},
 230        {"LPC",         22},
 231        {"SATA",        23},
 232        {"SMB",         24},
 233        {"PRTC",        25},
 234};
 235
 236struct telemetry_debugfs_conf {
 237        struct telemetry_susp_stats suspend_stats;
 238        struct dentry *telemetry_dbg_dir;
 239
 240        /* Bitmap Data */
 241        struct telem_ioss_d0ix_stateinfo *ioss_d0ix_data;
 242        struct telem_pss_idle_stateinfo *pss_idle_data;
 243        struct telem_pcs_blkd_info *pcs_idle_blkd_data;
 244        struct telem_pcs_blkd_info *pcs_s0ix_blkd_data;
 245        struct telem_pss_wakeup_info *pss_wakeup;
 246        struct telem_pss_ltr_info *pss_ltr_data;
 247        struct telem_ioss_pg_info *ioss_pg_data;
 248        u8 pcs_idle_blkd_evts;
 249        u8 pcs_s0ix_blkd_evts;
 250        u8 pss_wakeup_evts;
 251        u8 pss_idle_evts;
 252        u8 pss_ltr_evts;
 253        u8 ioss_d0ix_evts;
 254        u8 ioss_pg_evts;
 255
 256        /* IDs */
 257        u16  pss_ltr_blocking_id;
 258        u16  pcs_idle_blkd_id;
 259        u16  pcs_s0ix_blkd_id;
 260        u16  s0ix_total_occ_id;
 261        u16  s0ix_shlw_occ_id;
 262        u16  s0ix_deep_occ_id;
 263        u16  s0ix_total_res_id;
 264        u16  s0ix_shlw_res_id;
 265        u16  s0ix_deep_res_id;
 266        u16  pss_wakeup_id;
 267        u16  ioss_d0ix_id;
 268        u16  pstates_id;
 269        u16  pss_idle_id;
 270        u16  ioss_d3_id;
 271        u16  ioss_pg_id;
 272};
 273
 274static struct telemetry_debugfs_conf *debugfs_conf;
 275
 276static struct telemetry_debugfs_conf telem_apl_debugfs_conf = {
 277        .pss_idle_data = telem_apl_pss_idle_data,
 278        .pcs_idle_blkd_data = telem_apl_pcs_idle_blkd_data,
 279        .pcs_s0ix_blkd_data = telem_apl_pcs_s0ix_blkd_data,
 280        .pss_ltr_data = telem_apl_pss_ltr_data,
 281        .pss_wakeup = telem_apl_pss_wakeup,
 282        .ioss_d0ix_data = telem_apl_ioss_d0ix_data,
 283        .ioss_pg_data = telem_apl_ioss_pg_data,
 284
 285        .pss_idle_evts = ARRAY_SIZE(telem_apl_pss_idle_data),
 286        .pcs_idle_blkd_evts = ARRAY_SIZE(telem_apl_pcs_idle_blkd_data),
 287        .pcs_s0ix_blkd_evts = ARRAY_SIZE(telem_apl_pcs_s0ix_blkd_data),
 288        .pss_ltr_evts = ARRAY_SIZE(telem_apl_pss_ltr_data),
 289        .pss_wakeup_evts = ARRAY_SIZE(telem_apl_pss_wakeup),
 290        .ioss_d0ix_evts = ARRAY_SIZE(telem_apl_ioss_d0ix_data),
 291        .ioss_pg_evts = ARRAY_SIZE(telem_apl_ioss_pg_data),
 292
 293        .pstates_id = TELEM_APL_PSS_PSTATES_ID,
 294        .pss_idle_id = TELEM_APL_PSS_IDLE_ID,
 295        .pcs_idle_blkd_id = TELEM_APL_PCS_IDLE_BLOCKED_ID,
 296        .pcs_s0ix_blkd_id = TELEM_APL_PCS_S0IX_BLOCKED_ID,
 297        .pss_wakeup_id = TELEM_APL_PSS_WAKEUP_ID,
 298        .pss_ltr_blocking_id = TELEM_APL_PSS_LTR_BLOCKING_ID,
 299        .s0ix_total_occ_id = TELEM_APL_S0IX_TOTAL_OCC_ID,
 300        .s0ix_shlw_occ_id = TELEM_APL_S0IX_SHLW_OCC_ID,
 301        .s0ix_deep_occ_id = TELEM_APL_S0IX_DEEP_OCC_ID,
 302        .s0ix_total_res_id = TELEM_APL_S0IX_TOTAL_RES_ID,
 303        .s0ix_shlw_res_id = TELEM_APL_S0IX_SHLW_RES_ID,
 304        .s0ix_deep_res_id = TELEM_APL_S0IX_DEEP_RES_ID,
 305        .ioss_d0ix_id = TELEM_APL_D0IX_ID,
 306        .ioss_d3_id = TELEM_APL_D3_ID,
 307        .ioss_pg_id = TELEM_APL_PG_ID,
 308};
 309
 310static const struct x86_cpu_id telemetry_debugfs_cpu_ids[] = {
 311        INTEL_CPU_FAM6(ATOM_GOLDMONT, telem_apl_debugfs_conf),
 312        INTEL_CPU_FAM6(ATOM_GOLDMONT_PLUS, telem_apl_debugfs_conf),
 313        {}
 314};
 315
 316MODULE_DEVICE_TABLE(x86cpu, telemetry_debugfs_cpu_ids);
 317
 318static int telemetry_debugfs_check_evts(void)
 319{
 320        if ((debugfs_conf->pss_idle_evts > TELEM_PSS_IDLE_EVTS) ||
 321            (debugfs_conf->pcs_idle_blkd_evts > TELEM_PSS_IDLE_BLOCKED_EVTS) ||
 322            (debugfs_conf->pcs_s0ix_blkd_evts > TELEM_PSS_S0IX_BLOCKED_EVTS) ||
 323            (debugfs_conf->pss_ltr_evts > TELEM_PSS_LTR_BLOCKING_EVTS) ||
 324            (debugfs_conf->pss_wakeup_evts > TELEM_PSS_S0IX_WAKEUP_EVTS) ||
 325            (debugfs_conf->ioss_d0ix_evts > TELEM_IOSS_DX_D0IX_EVTS) ||
 326            (debugfs_conf->ioss_pg_evts > TELEM_IOSS_PG_EVTS))
 327                return -EINVAL;
 328
 329        return 0;
 330}
 331
 332static int telem_pss_states_show(struct seq_file *s, void *unused)
 333{
 334        struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];
 335        struct telemetry_debugfs_conf *conf = debugfs_conf;
 336        const char *name[TELEM_MAX_OS_ALLOCATED_EVENTS];
 337        u32 pcs_idle_blkd[TELEM_PSS_IDLE_BLOCKED_EVTS],
 338            pcs_s0ix_blkd[TELEM_PSS_S0IX_BLOCKED_EVTS],
 339            pss_s0ix_wakeup[TELEM_PSS_S0IX_WAKEUP_EVTS],
 340            pss_ltr_blkd[TELEM_PSS_LTR_BLOCKING_EVTS],
 341            pss_idle[TELEM_PSS_IDLE_EVTS];
 342        int index, idx, ret, err = 0;
 343        u64 pstates = 0;
 344
 345        ret = telemetry_read_eventlog(TELEM_PSS, evtlog,
 346                                      TELEM_MAX_OS_ALLOCATED_EVENTS);
 347        if (ret < 0)
 348                return ret;
 349
 350        err = telemetry_get_evtname(TELEM_PSS, name,
 351                                    TELEM_MAX_OS_ALLOCATED_EVENTS);
 352        if (err < 0)
 353                return err;
 354
 355        seq_puts(s, "\n----------------------------------------------------\n");
 356        seq_puts(s, "\tPSS TELEM EVENTLOG (Residency = field/19.2 us\n");
 357        seq_puts(s, "----------------------------------------------------\n");
 358        for (index = 0; index < ret; index++) {
 359                seq_printf(s, "%-32s %llu\n",
 360                           name[index], evtlog[index].telem_evtlog);
 361
 362                /* Fetch PSS IDLE State */
 363                if (evtlog[index].telem_evtid == conf->pss_idle_id) {
 364                        pss_idle[conf->pss_idle_evts - 1] =
 365                        (evtlog[index].telem_evtlog >>
 366                        conf->pss_idle_data[conf->pss_idle_evts - 1].bit_pos) &
 367                        TELEM_APL_MASK_PCS_STATE;
 368                }
 369
 370                TELEM_CHECK_AND_PARSE_EVTS(conf->pss_idle_id,
 371                                           conf->pss_idle_evts - 1,
 372                                           pss_idle, evtlog[index].telem_evtlog,
 373                                           conf->pss_idle_data, TELEM_MASK_BIT);
 374
 375                TELEM_CHECK_AND_PARSE_EVTS(conf->pcs_idle_blkd_id,
 376                                           conf->pcs_idle_blkd_evts,
 377                                           pcs_idle_blkd,
 378                                           evtlog[index].telem_evtlog,
 379                                           conf->pcs_idle_blkd_data,
 380                                           TELEM_MASK_BYTE);
 381
 382                TELEM_CHECK_AND_PARSE_EVTS(conf->pcs_s0ix_blkd_id,
 383                                           conf->pcs_s0ix_blkd_evts,
 384                                           pcs_s0ix_blkd,
 385                                           evtlog[index].telem_evtlog,
 386                                           conf->pcs_s0ix_blkd_data,
 387                                           TELEM_MASK_BYTE);
 388
 389                TELEM_CHECK_AND_PARSE_EVTS(conf->pss_wakeup_id,
 390                                           conf->pss_wakeup_evts,
 391                                           pss_s0ix_wakeup,
 392                                           evtlog[index].telem_evtlog,
 393                                           conf->pss_wakeup, TELEM_MASK_BYTE);
 394
 395                TELEM_CHECK_AND_PARSE_EVTS(conf->pss_ltr_blocking_id,
 396                                           conf->pss_ltr_evts, pss_ltr_blkd,
 397                                           evtlog[index].telem_evtlog,
 398                                           conf->pss_ltr_data, TELEM_MASK_BYTE);
 399
 400                if (evtlog[index].telem_evtid == debugfs_conf->pstates_id)
 401                        pstates = evtlog[index].telem_evtlog;
 402        }
 403
 404        seq_puts(s, "\n--------------------------------------\n");
 405        seq_puts(s, "PStates\n");
 406        seq_puts(s, "--------------------------------------\n");
 407        seq_puts(s, "Domain\t\t\t\tFreq(Mhz)\n");
 408        seq_printf(s, " IA\t\t\t\t %llu\n GT\t\t\t\t %llu\n",
 409                   (pstates & TELEM_MASK_BYTE)*100,
 410                   ((pstates >> 8) & TELEM_MASK_BYTE)*50/3);
 411
 412        seq_printf(s, " IUNIT\t\t\t\t %llu\n SA\t\t\t\t %llu\n",
 413                   ((pstates >> 16) & TELEM_MASK_BYTE)*25,
 414                   ((pstates >> 24) & TELEM_MASK_BYTE)*50/3);
 415
 416        seq_puts(s, "\n--------------------------------------\n");
 417        seq_puts(s, "PSS IDLE Status\n");
 418        seq_puts(s, "--------------------------------------\n");
 419        seq_puts(s, "Device\t\t\t\t\tIDLE\n");
 420        for (index = 0; index < debugfs_conf->pss_idle_evts; index++) {
 421                seq_printf(s, "%-32s\t%u\n",
 422                           debugfs_conf->pss_idle_data[index].name,
 423                           pss_idle[index]);
 424        }
 425
 426        seq_puts(s, "\n--------------------------------------\n");
 427        seq_puts(s, "PSS Idle blkd Status (~1ms saturating bucket)\n");
 428        seq_puts(s, "--------------------------------------\n");
 429        seq_puts(s, "Blocker\t\t\t\t\tCount\n");
 430        for (index = 0; index < debugfs_conf->pcs_idle_blkd_evts; index++) {
 431                seq_printf(s, "%-32s\t%u\n",
 432                           debugfs_conf->pcs_idle_blkd_data[index].name,
 433                           pcs_idle_blkd[index]);
 434        }
 435
 436        seq_puts(s, "\n--------------------------------------\n");
 437        seq_puts(s, "PSS S0ix blkd Status (~1ms saturating bucket)\n");
 438        seq_puts(s, "--------------------------------------\n");
 439        seq_puts(s, "Blocker\t\t\t\t\tCount\n");
 440        for (index = 0; index < debugfs_conf->pcs_s0ix_blkd_evts; index++) {
 441                seq_printf(s, "%-32s\t%u\n",
 442                           debugfs_conf->pcs_s0ix_blkd_data[index].name,
 443                           pcs_s0ix_blkd[index]);
 444        }
 445
 446        seq_puts(s, "\n--------------------------------------\n");
 447        seq_puts(s, "LTR Blocking Status (~1ms saturating bucket)\n");
 448        seq_puts(s, "--------------------------------------\n");
 449        seq_puts(s, "Blocker\t\t\t\t\tCount\n");
 450        for (index = 0; index < debugfs_conf->pss_ltr_evts; index++) {
 451                seq_printf(s, "%-32s\t%u\n",
 452                           debugfs_conf->pss_ltr_data[index].name,
 453                           pss_s0ix_wakeup[index]);
 454        }
 455
 456        seq_puts(s, "\n--------------------------------------\n");
 457        seq_puts(s, "Wakes Status (~1ms saturating bucket)\n");
 458        seq_puts(s, "--------------------------------------\n");
 459        seq_puts(s, "Wakes\t\t\t\t\tCount\n");
 460        for (index = 0; index < debugfs_conf->pss_wakeup_evts; index++) {
 461                seq_printf(s, "%-32s\t%u\n",
 462                           debugfs_conf->pss_wakeup[index].name,
 463                           pss_ltr_blkd[index]);
 464        }
 465
 466        return 0;
 467}
 468
 469DEFINE_SHOW_ATTRIBUTE(telem_pss_states);
 470
 471static int telem_ioss_states_show(struct seq_file *s, void *unused)
 472{
 473        struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];
 474        const char *name[TELEM_MAX_OS_ALLOCATED_EVENTS];
 475        int index, ret, err;
 476
 477        ret = telemetry_read_eventlog(TELEM_IOSS, evtlog,
 478                                      TELEM_MAX_OS_ALLOCATED_EVENTS);
 479        if (ret < 0)
 480                return ret;
 481
 482        err = telemetry_get_evtname(TELEM_IOSS, name,
 483                                    TELEM_MAX_OS_ALLOCATED_EVENTS);
 484        if (err < 0)
 485                return err;
 486
 487        seq_puts(s, "--------------------------------------\n");
 488        seq_puts(s, "\tI0SS TELEMETRY EVENTLOG\n");
 489        seq_puts(s, "--------------------------------------\n");
 490        for (index = 0; index < ret; index++) {
 491                seq_printf(s, "%-32s 0x%llx\n",
 492                           name[index], evtlog[index].telem_evtlog);
 493        }
 494
 495        return 0;
 496}
 497
 498DEFINE_SHOW_ATTRIBUTE(telem_ioss_states);
 499
 500static int telem_soc_states_show(struct seq_file *s, void *unused)
 501{
 502        u32 d3_sts[TELEM_IOSS_DX_D0IX_EVTS], d0ix_sts[TELEM_IOSS_DX_D0IX_EVTS];
 503        u32 pg_sts[TELEM_IOSS_PG_EVTS], pss_idle[TELEM_PSS_IDLE_EVTS];
 504        struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];
 505        u32 s0ix_total_ctr = 0, s0ix_shlw_ctr = 0, s0ix_deep_ctr = 0;
 506        u64 s0ix_total_res = 0, s0ix_shlw_res = 0, s0ix_deep_res = 0;
 507        struct telemetry_debugfs_conf *conf = debugfs_conf;
 508        struct pci_dev *dev = NULL;
 509        int index, idx, ret;
 510        u32 d3_state;
 511        u16 pmcsr;
 512
 513        ret = telemetry_read_eventlog(TELEM_IOSS, evtlog,
 514                                      TELEM_MAX_OS_ALLOCATED_EVENTS);
 515        if (ret < 0)
 516                return ret;
 517
 518        for (index = 0; index < ret; index++) {
 519                TELEM_CHECK_AND_PARSE_EVTS(conf->ioss_d3_id,
 520                                           conf->ioss_d0ix_evts,
 521                                           d3_sts, evtlog[index].telem_evtlog,
 522                                           conf->ioss_d0ix_data,
 523                                           TELEM_MASK_BIT);
 524
 525                TELEM_CHECK_AND_PARSE_EVTS(conf->ioss_pg_id, conf->ioss_pg_evts,
 526                                           pg_sts, evtlog[index].telem_evtlog,
 527                                           conf->ioss_pg_data, TELEM_MASK_BIT);
 528
 529                TELEM_CHECK_AND_PARSE_EVTS(conf->ioss_d0ix_id,
 530                                           conf->ioss_d0ix_evts,
 531                                           d0ix_sts, evtlog[index].telem_evtlog,
 532                                           conf->ioss_d0ix_data,
 533                                           TELEM_MASK_BIT);
 534
 535                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_total_occ_id,
 536                                           s0ix_total_ctr);
 537
 538                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_occ_id,
 539                                           s0ix_shlw_ctr);
 540
 541                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_occ_id,
 542                                           s0ix_deep_ctr);
 543
 544                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_total_res_id,
 545                                           s0ix_total_res);
 546
 547                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_res_id,
 548                                           s0ix_shlw_res);
 549
 550                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_res_id,
 551                                           s0ix_deep_res);
 552        }
 553
 554        seq_puts(s, "\n---------------------------------------------------\n");
 555        seq_puts(s, "S0IX Type\t\t\t Occurrence\t\t Residency(us)\n");
 556        seq_puts(s, "---------------------------------------------------\n");
 557
 558        seq_printf(s, "S0IX Shallow\t\t\t %10u\t %10llu\n",
 559                   s0ix_shlw_ctr -
 560                   conf->suspend_stats.shlw_ctr,
 561                   (u64)((s0ix_shlw_res -
 562                   conf->suspend_stats.shlw_res)*10/192));
 563
 564        seq_printf(s, "S0IX Deep\t\t\t %10u\t %10llu\n",
 565                   s0ix_deep_ctr -
 566                   conf->suspend_stats.deep_ctr,
 567                   (u64)((s0ix_deep_res -
 568                   conf->suspend_stats.deep_res)*10/192));
 569
 570        seq_printf(s, "Suspend(With S0ixShallow)\t %10u\t %10llu\n",
 571                   conf->suspend_stats.shlw_ctr,
 572                   (u64)(conf->suspend_stats.shlw_res*10)/192);
 573
 574        seq_printf(s, "Suspend(With S0ixDeep)\t\t %10u\t %10llu\n",
 575                   conf->suspend_stats.deep_ctr,
 576                   (u64)(conf->suspend_stats.deep_res*10)/192);
 577
 578        seq_printf(s, "TOTAL S0IX\t\t\t %10u\t %10llu\n", s0ix_total_ctr,
 579                   (u64)(s0ix_total_res*10/192));
 580        seq_puts(s, "\n-------------------------------------------------\n");
 581        seq_puts(s, "\t\tDEVICE STATES\n");
 582        seq_puts(s, "-------------------------------------------------\n");
 583
 584        for_each_pci_dev(dev) {
 585                pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
 586                d3_state = ((pmcsr & PCI_PM_CTRL_STATE_MASK) ==
 587                            (__force int)PCI_D3hot) ? 1 : 0;
 588
 589                seq_printf(s, "pci %04x %04X %s %20.20s: ",
 590                           dev->vendor, dev->device, dev_name(&dev->dev),
 591                           dev_driver_string(&dev->dev));
 592                seq_printf(s, " d3:%x\n", d3_state);
 593        }
 594
 595        seq_puts(s, "\n--------------------------------------\n");
 596        seq_puts(s, "D3/D0i3 Status\n");
 597        seq_puts(s, "--------------------------------------\n");
 598        seq_puts(s, "Block\t\t D3\t D0i3\n");
 599        for (index = 0; index < conf->ioss_d0ix_evts; index++) {
 600                seq_printf(s, "%-10s\t %u\t %u\n",
 601                           conf->ioss_d0ix_data[index].name,
 602                           d3_sts[index], d0ix_sts[index]);
 603        }
 604
 605        seq_puts(s, "\n--------------------------------------\n");
 606        seq_puts(s, "South Complex PowerGate Status\n");
 607        seq_puts(s, "--------------------------------------\n");
 608        seq_puts(s, "Device\t\t PG\n");
 609        for (index = 0; index < conf->ioss_pg_evts; index++) {
 610                seq_printf(s, "%-10s\t %u\n",
 611                           conf->ioss_pg_data[index].name,
 612                           pg_sts[index]);
 613        }
 614
 615        evtlog->telem_evtid = conf->pss_idle_id;
 616        ret = telemetry_read_events(TELEM_PSS, evtlog, 1);
 617        if (ret < 0)
 618                return ret;
 619
 620        seq_puts(s, "\n-----------------------------------------\n");
 621        seq_puts(s, "North Idle Status\n");
 622        seq_puts(s, "-----------------------------------------\n");
 623        for (idx = 0; idx < conf->pss_idle_evts - 1; idx++) {
 624                pss_idle[idx] = (evtlog->telem_evtlog >>
 625                                conf->pss_idle_data[idx].bit_pos) &
 626                                TELEM_MASK_BIT;
 627        }
 628
 629        pss_idle[idx] = (evtlog->telem_evtlog >>
 630                        conf->pss_idle_data[idx].bit_pos) &
 631                        TELEM_APL_MASK_PCS_STATE;
 632
 633        for (index = 0; index < conf->pss_idle_evts; index++) {
 634                seq_printf(s, "%-30s %u\n",
 635                           conf->pss_idle_data[index].name,
 636                           pss_idle[index]);
 637        }
 638
 639        seq_puts(s, "\nPCS_STATUS Code\n");
 640        seq_puts(s, "0:C0 1:C1 2:C1_DN_WT_DEV 3:C2 4:C2_WT_DE_MEM_UP\n");
 641        seq_puts(s, "5:C2_WT_DE_MEM_DOWN 6:C2_UP_WT_DEV 7:C2_DN 8:C2_VOA\n");
 642        seq_puts(s, "9:C2_VOA_UP 10:S0IX_PRE 11:S0IX\n");
 643
 644        return 0;
 645}
 646
 647DEFINE_SHOW_ATTRIBUTE(telem_soc_states);
 648
 649static int telem_s0ix_res_get(void *data, u64 *val)
 650{
 651        u64 s0ix_total_res;
 652        int ret;
 653
 654        ret = intel_pmc_s0ix_counter_read(&s0ix_total_res);
 655        if (ret) {
 656                pr_err("Failed to read S0ix residency");
 657                return ret;
 658        }
 659
 660        *val = s0ix_total_res;
 661
 662        return 0;
 663}
 664
 665DEFINE_DEBUGFS_ATTRIBUTE(telem_s0ix_fops, telem_s0ix_res_get, NULL, "%llu\n");
 666
 667static int telem_pss_trc_verb_show(struct seq_file *s, void *unused)
 668{
 669        u32 verbosity;
 670        int err;
 671
 672        err = telemetry_get_trace_verbosity(TELEM_PSS, &verbosity);
 673        if (err) {
 674                pr_err("Get PSS Trace Verbosity Failed with Error %d\n", err);
 675                return -EFAULT;
 676        }
 677
 678        seq_printf(s, "PSS Trace Verbosity %u\n", verbosity);
 679        return 0;
 680}
 681
 682static ssize_t telem_pss_trc_verb_write(struct file *file,
 683                                        const char __user *userbuf,
 684                                        size_t count, loff_t *ppos)
 685{
 686        u32 verbosity;
 687        int err;
 688
 689        if (kstrtou32_from_user(userbuf, count, 0, &verbosity))
 690                return -EFAULT;
 691
 692        err = telemetry_set_trace_verbosity(TELEM_PSS, verbosity);
 693        if (err) {
 694                pr_err("Changing PSS Trace Verbosity Failed. Error %d\n", err);
 695                count = err;
 696        }
 697
 698        return count;
 699}
 700
 701static int telem_pss_trc_verb_open(struct inode *inode, struct file *file)
 702{
 703        return single_open(file, telem_pss_trc_verb_show, inode->i_private);
 704}
 705
 706static const struct file_operations telem_pss_trc_verb_ops = {
 707        .open           = telem_pss_trc_verb_open,
 708        .read           = seq_read,
 709        .write          = telem_pss_trc_verb_write,
 710        .llseek         = seq_lseek,
 711        .release        = single_release,
 712};
 713
 714static int telem_ioss_trc_verb_show(struct seq_file *s, void *unused)
 715{
 716        u32 verbosity;
 717        int err;
 718
 719        err = telemetry_get_trace_verbosity(TELEM_IOSS, &verbosity);
 720        if (err) {
 721                pr_err("Get IOSS Trace Verbosity Failed with Error %d\n", err);
 722                return -EFAULT;
 723        }
 724
 725        seq_printf(s, "IOSS Trace Verbosity %u\n", verbosity);
 726        return 0;
 727}
 728
 729static ssize_t telem_ioss_trc_verb_write(struct file *file,
 730                                         const char __user *userbuf,
 731                                         size_t count, loff_t *ppos)
 732{
 733        u32 verbosity;
 734        int err;
 735
 736        if (kstrtou32_from_user(userbuf, count, 0, &verbosity))
 737                return -EFAULT;
 738
 739        err = telemetry_set_trace_verbosity(TELEM_IOSS, verbosity);
 740        if (err) {
 741                pr_err("Changing IOSS Trace Verbosity Failed. Error %d\n", err);
 742                count = err;
 743        }
 744
 745        return count;
 746}
 747
 748static int telem_ioss_trc_verb_open(struct inode *inode, struct file *file)
 749{
 750        return single_open(file, telem_ioss_trc_verb_show, inode->i_private);
 751}
 752
 753static const struct file_operations telem_ioss_trc_verb_ops = {
 754        .open           = telem_ioss_trc_verb_open,
 755        .read           = seq_read,
 756        .write          = telem_ioss_trc_verb_write,
 757        .llseek         = seq_lseek,
 758        .release        = single_release,
 759};
 760
 761static int pm_suspend_prep_cb(void)
 762{
 763        struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];
 764        struct telemetry_debugfs_conf *conf = debugfs_conf;
 765        int ret, index;
 766
 767        ret = telemetry_raw_read_eventlog(TELEM_IOSS, evtlog,
 768                        TELEM_MAX_OS_ALLOCATED_EVENTS);
 769        if (ret < 0) {
 770                suspend_prep_ok = 0;
 771                goto out;
 772        }
 773
 774        for (index = 0; index < ret; index++) {
 775
 776                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_occ_id,
 777                                           suspend_shlw_ctr_temp);
 778
 779                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_occ_id,
 780                                           suspend_deep_ctr_temp);
 781
 782                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_res_id,
 783                                           suspend_shlw_res_temp);
 784
 785                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_res_id,
 786                                           suspend_deep_res_temp);
 787        }
 788        suspend_prep_ok = 1;
 789out:
 790        return NOTIFY_OK;
 791}
 792
 793static int pm_suspend_exit_cb(void)
 794{
 795        struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];
 796        static u32 suspend_shlw_ctr_exit, suspend_deep_ctr_exit;
 797        static u64 suspend_shlw_res_exit, suspend_deep_res_exit;
 798        struct telemetry_debugfs_conf *conf = debugfs_conf;
 799        int ret, index;
 800
 801        if (!suspend_prep_ok)
 802                goto out;
 803
 804        ret = telemetry_raw_read_eventlog(TELEM_IOSS, evtlog,
 805                                          TELEM_MAX_OS_ALLOCATED_EVENTS);
 806        if (ret < 0)
 807                goto out;
 808
 809        for (index = 0; index < ret; index++) {
 810                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_occ_id,
 811                                           suspend_shlw_ctr_exit);
 812
 813                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_occ_id,
 814                                           suspend_deep_ctr_exit);
 815
 816                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_res_id,
 817                                           suspend_shlw_res_exit);
 818
 819                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_res_id,
 820                                           suspend_deep_res_exit);
 821        }
 822
 823        if ((suspend_shlw_ctr_exit < suspend_shlw_ctr_temp) ||
 824            (suspend_deep_ctr_exit < suspend_deep_ctr_temp) ||
 825            (suspend_shlw_res_exit < suspend_shlw_res_temp) ||
 826            (suspend_deep_res_exit < suspend_deep_res_temp)) {
 827                pr_err("Wrong s0ix counters detected\n");
 828                goto out;
 829        }
 830
 831        /*
 832         * Due to some design limitations in the firmware, sometimes the
 833         * counters do not get updated by the time we reach here. As a
 834         * workaround, we try to see if this was a genuine case of sleep
 835         * failure or not by cross-checking from PMC GCR registers directly.
 836         */
 837        if (suspend_shlw_ctr_exit == suspend_shlw_ctr_temp &&
 838            suspend_deep_ctr_exit == suspend_deep_ctr_temp) {
 839                ret = intel_pmc_gcr_read64(PMC_GCR_TELEM_SHLW_S0IX_REG,
 840                                          &suspend_shlw_res_exit);
 841                if (ret < 0)
 842                        goto out;
 843
 844                ret = intel_pmc_gcr_read64(PMC_GCR_TELEM_DEEP_S0IX_REG,
 845                                          &suspend_deep_res_exit);
 846                if (ret < 0)
 847                        goto out;
 848
 849                if (suspend_shlw_res_exit > suspend_shlw_res_temp)
 850                        suspend_shlw_ctr_exit++;
 851
 852                if (suspend_deep_res_exit > suspend_deep_res_temp)
 853                        suspend_deep_ctr_exit++;
 854        }
 855
 856        suspend_shlw_ctr_exit -= suspend_shlw_ctr_temp;
 857        suspend_deep_ctr_exit -= suspend_deep_ctr_temp;
 858        suspend_shlw_res_exit -= suspend_shlw_res_temp;
 859        suspend_deep_res_exit -= suspend_deep_res_temp;
 860
 861        if (suspend_shlw_ctr_exit != 0) {
 862                conf->suspend_stats.shlw_ctr +=
 863                suspend_shlw_ctr_exit;
 864
 865                conf->suspend_stats.shlw_res +=
 866                suspend_shlw_res_exit;
 867        }
 868
 869        if (suspend_deep_ctr_exit != 0) {
 870                conf->suspend_stats.deep_ctr +=
 871                suspend_deep_ctr_exit;
 872
 873                conf->suspend_stats.deep_res +=
 874                suspend_deep_res_exit;
 875        }
 876
 877out:
 878        suspend_prep_ok = 0;
 879        return NOTIFY_OK;
 880}
 881
 882static int pm_notification(struct notifier_block *this,
 883                           unsigned long event, void *ptr)
 884{
 885        switch (event) {
 886        case PM_SUSPEND_PREPARE:
 887                return pm_suspend_prep_cb();
 888        case PM_POST_SUSPEND:
 889                return pm_suspend_exit_cb();
 890        }
 891
 892        return NOTIFY_DONE;
 893}
 894
 895static struct notifier_block pm_notifier = {
 896        .notifier_call = pm_notification,
 897};
 898
 899static int __init telemetry_debugfs_init(void)
 900{
 901        const struct x86_cpu_id *id;
 902        int err;
 903        struct dentry *dir;
 904
 905        /* Only APL supported for now */
 906        id = x86_match_cpu(telemetry_debugfs_cpu_ids);
 907        if (!id)
 908                return -ENODEV;
 909
 910        debugfs_conf = (struct telemetry_debugfs_conf *)id->driver_data;
 911
 912        err = telemetry_pltconfig_valid();
 913        if (err < 0) {
 914                pr_info("Invalid pltconfig, ensure IPC1 device is enabled in BIOS\n");
 915                return -ENODEV;
 916        }
 917
 918        err = telemetry_debugfs_check_evts();
 919        if (err < 0) {
 920                pr_info("telemetry_debugfs_check_evts failed\n");
 921                return -EINVAL;
 922        }
 923
 924        register_pm_notifier(&pm_notifier);
 925
 926        dir = debugfs_create_dir("telemetry", NULL);
 927        debugfs_conf->telemetry_dbg_dir = dir;
 928
 929        debugfs_create_file("pss_info", S_IFREG | S_IRUGO, dir, NULL,
 930                            &telem_pss_states_fops);
 931        debugfs_create_file("ioss_info", S_IFREG | S_IRUGO, dir, NULL,
 932                            &telem_ioss_states_fops);
 933        debugfs_create_file("soc_states", S_IFREG | S_IRUGO, dir, NULL,
 934                            &telem_soc_states_fops);
 935        debugfs_create_file("s0ix_residency_usec", S_IFREG | S_IRUGO, dir, NULL,
 936                            &telem_s0ix_fops);
 937        debugfs_create_file("pss_trace_verbosity", S_IFREG | S_IRUGO, dir, NULL,
 938                            &telem_pss_trc_verb_ops);
 939        debugfs_create_file("ioss_trace_verbosity", S_IFREG | S_IRUGO, dir,
 940                            NULL, &telem_ioss_trc_verb_ops);
 941        return 0;
 942}
 943
 944static void __exit telemetry_debugfs_exit(void)
 945{
 946        debugfs_remove_recursive(debugfs_conf->telemetry_dbg_dir);
 947        debugfs_conf->telemetry_dbg_dir = NULL;
 948        unregister_pm_notifier(&pm_notifier);
 949}
 950
 951late_initcall(telemetry_debugfs_init);
 952module_exit(telemetry_debugfs_exit);
 953
 954MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>");
 955MODULE_DESCRIPTION("Intel SoC Telemetry debugfs Interface");
 956MODULE_VERSION(DRIVER_VERSION);
 957MODULE_LICENSE("GPL v2");
 958