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/mfd/intel_pmc_bxt.h>
  19#include <linux/module.h>
  20#include <linux/pci.h>
  21#include <linux/seq_file.h>
  22#include <linux/suspend.h>
  23
  24#include <asm/cpu_device_id.h>
  25#include <asm/intel-family.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        X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT,       &telem_apl_debugfs_conf),
 312        X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_PLUS,  &telem_apl_debugfs_conf),
 313        {}
 314};
 315MODULE_DEVICE_TABLE(x86cpu, telemetry_debugfs_cpu_ids);
 316
 317static int telemetry_debugfs_check_evts(void)
 318{
 319        if ((debugfs_conf->pss_idle_evts > TELEM_PSS_IDLE_EVTS) ||
 320            (debugfs_conf->pcs_idle_blkd_evts > TELEM_PSS_IDLE_BLOCKED_EVTS) ||
 321            (debugfs_conf->pcs_s0ix_blkd_evts > TELEM_PSS_S0IX_BLOCKED_EVTS) ||
 322            (debugfs_conf->pss_ltr_evts > TELEM_PSS_LTR_BLOCKING_EVTS) ||
 323            (debugfs_conf->pss_wakeup_evts > TELEM_PSS_S0IX_WAKEUP_EVTS) ||
 324            (debugfs_conf->ioss_d0ix_evts > TELEM_IOSS_DX_D0IX_EVTS) ||
 325            (debugfs_conf->ioss_pg_evts > TELEM_IOSS_PG_EVTS))
 326                return -EINVAL;
 327
 328        return 0;
 329}
 330
 331static int telem_pss_states_show(struct seq_file *s, void *unused)
 332{
 333        struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];
 334        struct telemetry_debugfs_conf *conf = debugfs_conf;
 335        const char *name[TELEM_MAX_OS_ALLOCATED_EVENTS];
 336        u32 pcs_idle_blkd[TELEM_PSS_IDLE_BLOCKED_EVTS],
 337            pcs_s0ix_blkd[TELEM_PSS_S0IX_BLOCKED_EVTS],
 338            pss_s0ix_wakeup[TELEM_PSS_S0IX_WAKEUP_EVTS],
 339            pss_ltr_blkd[TELEM_PSS_LTR_BLOCKING_EVTS],
 340            pss_idle[TELEM_PSS_IDLE_EVTS];
 341        int index, idx, ret, err = 0;
 342        u64 pstates = 0;
 343
 344        ret = telemetry_read_eventlog(TELEM_PSS, evtlog,
 345                                      TELEM_MAX_OS_ALLOCATED_EVENTS);
 346        if (ret < 0)
 347                return ret;
 348
 349        err = telemetry_get_evtname(TELEM_PSS, name,
 350                                    TELEM_MAX_OS_ALLOCATED_EVENTS);
 351        if (err < 0)
 352                return err;
 353
 354        seq_puts(s, "\n----------------------------------------------------\n");
 355        seq_puts(s, "\tPSS TELEM EVENTLOG (Residency = field/19.2 us\n");
 356        seq_puts(s, "----------------------------------------------------\n");
 357        for (index = 0; index < ret; index++) {
 358                seq_printf(s, "%-32s %llu\n",
 359                           name[index], evtlog[index].telem_evtlog);
 360
 361                /* Fetch PSS IDLE State */
 362                if (evtlog[index].telem_evtid == conf->pss_idle_id) {
 363                        pss_idle[conf->pss_idle_evts - 1] =
 364                        (evtlog[index].telem_evtlog >>
 365                        conf->pss_idle_data[conf->pss_idle_evts - 1].bit_pos) &
 366                        TELEM_APL_MASK_PCS_STATE;
 367                }
 368
 369                TELEM_CHECK_AND_PARSE_EVTS(conf->pss_idle_id,
 370                                           conf->pss_idle_evts - 1,
 371                                           pss_idle, evtlog[index].telem_evtlog,
 372                                           conf->pss_idle_data, TELEM_MASK_BIT);
 373
 374                TELEM_CHECK_AND_PARSE_EVTS(conf->pcs_idle_blkd_id,
 375                                           conf->pcs_idle_blkd_evts,
 376                                           pcs_idle_blkd,
 377                                           evtlog[index].telem_evtlog,
 378                                           conf->pcs_idle_blkd_data,
 379                                           TELEM_MASK_BYTE);
 380
 381                TELEM_CHECK_AND_PARSE_EVTS(conf->pcs_s0ix_blkd_id,
 382                                           conf->pcs_s0ix_blkd_evts,
 383                                           pcs_s0ix_blkd,
 384                                           evtlog[index].telem_evtlog,
 385                                           conf->pcs_s0ix_blkd_data,
 386                                           TELEM_MASK_BYTE);
 387
 388                TELEM_CHECK_AND_PARSE_EVTS(conf->pss_wakeup_id,
 389                                           conf->pss_wakeup_evts,
 390                                           pss_s0ix_wakeup,
 391                                           evtlog[index].telem_evtlog,
 392                                           conf->pss_wakeup, TELEM_MASK_BYTE);
 393
 394                TELEM_CHECK_AND_PARSE_EVTS(conf->pss_ltr_blocking_id,
 395                                           conf->pss_ltr_evts, pss_ltr_blkd,
 396                                           evtlog[index].telem_evtlog,
 397                                           conf->pss_ltr_data, TELEM_MASK_BYTE);
 398
 399                if (evtlog[index].telem_evtid == debugfs_conf->pstates_id)
 400                        pstates = evtlog[index].telem_evtlog;
 401        }
 402
 403        seq_puts(s, "\n--------------------------------------\n");
 404        seq_puts(s, "PStates\n");
 405        seq_puts(s, "--------------------------------------\n");
 406        seq_puts(s, "Domain\t\t\t\tFreq(Mhz)\n");
 407        seq_printf(s, " IA\t\t\t\t %llu\n GT\t\t\t\t %llu\n",
 408                   (pstates & TELEM_MASK_BYTE)*100,
 409                   ((pstates >> 8) & TELEM_MASK_BYTE)*50/3);
 410
 411        seq_printf(s, " IUNIT\t\t\t\t %llu\n SA\t\t\t\t %llu\n",
 412                   ((pstates >> 16) & TELEM_MASK_BYTE)*25,
 413                   ((pstates >> 24) & TELEM_MASK_BYTE)*50/3);
 414
 415        seq_puts(s, "\n--------------------------------------\n");
 416        seq_puts(s, "PSS IDLE Status\n");
 417        seq_puts(s, "--------------------------------------\n");
 418        seq_puts(s, "Device\t\t\t\t\tIDLE\n");
 419        for (index = 0; index < debugfs_conf->pss_idle_evts; index++) {
 420                seq_printf(s, "%-32s\t%u\n",
 421                           debugfs_conf->pss_idle_data[index].name,
 422                           pss_idle[index]);
 423        }
 424
 425        seq_puts(s, "\n--------------------------------------\n");
 426        seq_puts(s, "PSS Idle blkd Status (~1ms saturating bucket)\n");
 427        seq_puts(s, "--------------------------------------\n");
 428        seq_puts(s, "Blocker\t\t\t\t\tCount\n");
 429        for (index = 0; index < debugfs_conf->pcs_idle_blkd_evts; index++) {
 430                seq_printf(s, "%-32s\t%u\n",
 431                           debugfs_conf->pcs_idle_blkd_data[index].name,
 432                           pcs_idle_blkd[index]);
 433        }
 434
 435        seq_puts(s, "\n--------------------------------------\n");
 436        seq_puts(s, "PSS S0ix blkd Status (~1ms saturating bucket)\n");
 437        seq_puts(s, "--------------------------------------\n");
 438        seq_puts(s, "Blocker\t\t\t\t\tCount\n");
 439        for (index = 0; index < debugfs_conf->pcs_s0ix_blkd_evts; index++) {
 440                seq_printf(s, "%-32s\t%u\n",
 441                           debugfs_conf->pcs_s0ix_blkd_data[index].name,
 442                           pcs_s0ix_blkd[index]);
 443        }
 444
 445        seq_puts(s, "\n--------------------------------------\n");
 446        seq_puts(s, "LTR Blocking Status (~1ms saturating bucket)\n");
 447        seq_puts(s, "--------------------------------------\n");
 448        seq_puts(s, "Blocker\t\t\t\t\tCount\n");
 449        for (index = 0; index < debugfs_conf->pss_ltr_evts; index++) {
 450                seq_printf(s, "%-32s\t%u\n",
 451                           debugfs_conf->pss_ltr_data[index].name,
 452                           pss_s0ix_wakeup[index]);
 453        }
 454
 455        seq_puts(s, "\n--------------------------------------\n");
 456        seq_puts(s, "Wakes Status (~1ms saturating bucket)\n");
 457        seq_puts(s, "--------------------------------------\n");
 458        seq_puts(s, "Wakes\t\t\t\t\tCount\n");
 459        for (index = 0; index < debugfs_conf->pss_wakeup_evts; index++) {
 460                seq_printf(s, "%-32s\t%u\n",
 461                           debugfs_conf->pss_wakeup[index].name,
 462                           pss_ltr_blkd[index]);
 463        }
 464
 465        return 0;
 466}
 467
 468DEFINE_SHOW_ATTRIBUTE(telem_pss_states);
 469
 470static int telem_ioss_states_show(struct seq_file *s, void *unused)
 471{
 472        struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];
 473        const char *name[TELEM_MAX_OS_ALLOCATED_EVENTS];
 474        int index, ret, err;
 475
 476        ret = telemetry_read_eventlog(TELEM_IOSS, evtlog,
 477                                      TELEM_MAX_OS_ALLOCATED_EVENTS);
 478        if (ret < 0)
 479                return ret;
 480
 481        err = telemetry_get_evtname(TELEM_IOSS, name,
 482                                    TELEM_MAX_OS_ALLOCATED_EVENTS);
 483        if (err < 0)
 484                return err;
 485
 486        seq_puts(s, "--------------------------------------\n");
 487        seq_puts(s, "\tI0SS TELEMETRY EVENTLOG\n");
 488        seq_puts(s, "--------------------------------------\n");
 489        for (index = 0; index < ret; index++) {
 490                seq_printf(s, "%-32s 0x%llx\n",
 491                           name[index], evtlog[index].telem_evtlog);
 492        }
 493
 494        return 0;
 495}
 496
 497DEFINE_SHOW_ATTRIBUTE(telem_ioss_states);
 498
 499static int telem_soc_states_show(struct seq_file *s, void *unused)
 500{
 501        u32 d3_sts[TELEM_IOSS_DX_D0IX_EVTS], d0ix_sts[TELEM_IOSS_DX_D0IX_EVTS];
 502        u32 pg_sts[TELEM_IOSS_PG_EVTS], pss_idle[TELEM_PSS_IDLE_EVTS];
 503        struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];
 504        u32 s0ix_total_ctr = 0, s0ix_shlw_ctr = 0, s0ix_deep_ctr = 0;
 505        u64 s0ix_total_res = 0, s0ix_shlw_res = 0, s0ix_deep_res = 0;
 506        struct telemetry_debugfs_conf *conf = debugfs_conf;
 507        struct pci_dev *dev = NULL;
 508        int index, idx, ret;
 509        u32 d3_state;
 510        u16 pmcsr;
 511
 512        ret = telemetry_read_eventlog(TELEM_IOSS, evtlog,
 513                                      TELEM_MAX_OS_ALLOCATED_EVENTS);
 514        if (ret < 0)
 515                return ret;
 516
 517        for (index = 0; index < ret; index++) {
 518                TELEM_CHECK_AND_PARSE_EVTS(conf->ioss_d3_id,
 519                                           conf->ioss_d0ix_evts,
 520                                           d3_sts, evtlog[index].telem_evtlog,
 521                                           conf->ioss_d0ix_data,
 522                                           TELEM_MASK_BIT);
 523
 524                TELEM_CHECK_AND_PARSE_EVTS(conf->ioss_pg_id, conf->ioss_pg_evts,
 525                                           pg_sts, evtlog[index].telem_evtlog,
 526                                           conf->ioss_pg_data, TELEM_MASK_BIT);
 527
 528                TELEM_CHECK_AND_PARSE_EVTS(conf->ioss_d0ix_id,
 529                                           conf->ioss_d0ix_evts,
 530                                           d0ix_sts, evtlog[index].telem_evtlog,
 531                                           conf->ioss_d0ix_data,
 532                                           TELEM_MASK_BIT);
 533
 534                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_total_occ_id,
 535                                           s0ix_total_ctr);
 536
 537                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_occ_id,
 538                                           s0ix_shlw_ctr);
 539
 540                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_occ_id,
 541                                           s0ix_deep_ctr);
 542
 543                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_total_res_id,
 544                                           s0ix_total_res);
 545
 546                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_res_id,
 547                                           s0ix_shlw_res);
 548
 549                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_res_id,
 550                                           s0ix_deep_res);
 551        }
 552
 553        seq_puts(s, "\n---------------------------------------------------\n");
 554        seq_puts(s, "S0IX Type\t\t\t Occurrence\t\t Residency(us)\n");
 555        seq_puts(s, "---------------------------------------------------\n");
 556
 557        seq_printf(s, "S0IX Shallow\t\t\t %10u\t %10llu\n",
 558                   s0ix_shlw_ctr -
 559                   conf->suspend_stats.shlw_ctr,
 560                   (u64)((s0ix_shlw_res -
 561                   conf->suspend_stats.shlw_res)*10/192));
 562
 563        seq_printf(s, "S0IX Deep\t\t\t %10u\t %10llu\n",
 564                   s0ix_deep_ctr -
 565                   conf->suspend_stats.deep_ctr,
 566                   (u64)((s0ix_deep_res -
 567                   conf->suspend_stats.deep_res)*10/192));
 568
 569        seq_printf(s, "Suspend(With S0ixShallow)\t %10u\t %10llu\n",
 570                   conf->suspend_stats.shlw_ctr,
 571                   (u64)(conf->suspend_stats.shlw_res*10)/192);
 572
 573        seq_printf(s, "Suspend(With S0ixDeep)\t\t %10u\t %10llu\n",
 574                   conf->suspend_stats.deep_ctr,
 575                   (u64)(conf->suspend_stats.deep_res*10)/192);
 576
 577        seq_printf(s, "TOTAL S0IX\t\t\t %10u\t %10llu\n", s0ix_total_ctr,
 578                   (u64)(s0ix_total_res*10/192));
 579        seq_puts(s, "\n-------------------------------------------------\n");
 580        seq_puts(s, "\t\tDEVICE STATES\n");
 581        seq_puts(s, "-------------------------------------------------\n");
 582
 583        for_each_pci_dev(dev) {
 584                pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
 585                d3_state = ((pmcsr & PCI_PM_CTRL_STATE_MASK) ==
 586                            (__force int)PCI_D3hot) ? 1 : 0;
 587
 588                seq_printf(s, "pci %04x %04X %s %20.20s: ",
 589                           dev->vendor, dev->device, dev_name(&dev->dev),
 590                           dev_driver_string(&dev->dev));
 591                seq_printf(s, " d3:%x\n", d3_state);
 592        }
 593
 594        seq_puts(s, "\n--------------------------------------\n");
 595        seq_puts(s, "D3/D0i3 Status\n");
 596        seq_puts(s, "--------------------------------------\n");
 597        seq_puts(s, "Block\t\t D3\t D0i3\n");
 598        for (index = 0; index < conf->ioss_d0ix_evts; index++) {
 599                seq_printf(s, "%-10s\t %u\t %u\n",
 600                           conf->ioss_d0ix_data[index].name,
 601                           d3_sts[index], d0ix_sts[index]);
 602        }
 603
 604        seq_puts(s, "\n--------------------------------------\n");
 605        seq_puts(s, "South Complex PowerGate Status\n");
 606        seq_puts(s, "--------------------------------------\n");
 607        seq_puts(s, "Device\t\t PG\n");
 608        for (index = 0; index < conf->ioss_pg_evts; index++) {
 609                seq_printf(s, "%-10s\t %u\n",
 610                           conf->ioss_pg_data[index].name,
 611                           pg_sts[index]);
 612        }
 613
 614        evtlog->telem_evtid = conf->pss_idle_id;
 615        ret = telemetry_read_events(TELEM_PSS, evtlog, 1);
 616        if (ret < 0)
 617                return ret;
 618
 619        seq_puts(s, "\n-----------------------------------------\n");
 620        seq_puts(s, "North Idle Status\n");
 621        seq_puts(s, "-----------------------------------------\n");
 622        for (idx = 0; idx < conf->pss_idle_evts - 1; idx++) {
 623                pss_idle[idx] = (evtlog->telem_evtlog >>
 624                                conf->pss_idle_data[idx].bit_pos) &
 625                                TELEM_MASK_BIT;
 626        }
 627
 628        pss_idle[idx] = (evtlog->telem_evtlog >>
 629                        conf->pss_idle_data[idx].bit_pos) &
 630                        TELEM_APL_MASK_PCS_STATE;
 631
 632        for (index = 0; index < conf->pss_idle_evts; index++) {
 633                seq_printf(s, "%-30s %u\n",
 634                           conf->pss_idle_data[index].name,
 635                           pss_idle[index]);
 636        }
 637
 638        seq_puts(s, "\nPCS_STATUS Code\n");
 639        seq_puts(s, "0:C0 1:C1 2:C1_DN_WT_DEV 3:C2 4:C2_WT_DE_MEM_UP\n");
 640        seq_puts(s, "5:C2_WT_DE_MEM_DOWN 6:C2_UP_WT_DEV 7:C2_DN 8:C2_VOA\n");
 641        seq_puts(s, "9:C2_VOA_UP 10:S0IX_PRE 11:S0IX\n");
 642
 643        return 0;
 644}
 645
 646DEFINE_SHOW_ATTRIBUTE(telem_soc_states);
 647
 648static int telem_s0ix_res_get(void *data, u64 *val)
 649{
 650        struct telemetry_plt_config *plt_config = telemetry_get_pltdata();
 651        u64 s0ix_total_res;
 652        int ret;
 653
 654        ret = intel_pmc_s0ix_counter_read(plt_config->pmc, &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        err = kstrtou32_from_user(userbuf, count, 0, &verbosity);
 690        if (err)
 691                return err;
 692
 693        err = telemetry_set_trace_verbosity(TELEM_PSS, verbosity);
 694        if (err) {
 695                pr_err("Changing PSS Trace Verbosity Failed. Error %d\n", err);
 696                return err;
 697        }
 698
 699        return count;
 700}
 701
 702static int telem_pss_trc_verb_open(struct inode *inode, struct file *file)
 703{
 704        return single_open(file, telem_pss_trc_verb_show, inode->i_private);
 705}
 706
 707static const struct file_operations telem_pss_trc_verb_ops = {
 708        .open           = telem_pss_trc_verb_open,
 709        .read           = seq_read,
 710        .write          = telem_pss_trc_verb_write,
 711        .llseek         = seq_lseek,
 712        .release        = single_release,
 713};
 714
 715static int telem_ioss_trc_verb_show(struct seq_file *s, void *unused)
 716{
 717        u32 verbosity;
 718        int err;
 719
 720        err = telemetry_get_trace_verbosity(TELEM_IOSS, &verbosity);
 721        if (err) {
 722                pr_err("Get IOSS Trace Verbosity Failed with Error %d\n", err);
 723                return -EFAULT;
 724        }
 725
 726        seq_printf(s, "IOSS Trace Verbosity %u\n", verbosity);
 727        return 0;
 728}
 729
 730static ssize_t telem_ioss_trc_verb_write(struct file *file,
 731                                         const char __user *userbuf,
 732                                         size_t count, loff_t *ppos)
 733{
 734        u32 verbosity;
 735        int err;
 736
 737        err = kstrtou32_from_user(userbuf, count, 0, &verbosity);
 738        if (err)
 739                return err;
 740
 741        err = telemetry_set_trace_verbosity(TELEM_IOSS, verbosity);
 742        if (err) {
 743                pr_err("Changing IOSS Trace Verbosity Failed. Error %d\n", err);
 744                return err;
 745        }
 746
 747        return count;
 748}
 749
 750static int telem_ioss_trc_verb_open(struct inode *inode, struct file *file)
 751{
 752        return single_open(file, telem_ioss_trc_verb_show, inode->i_private);
 753}
 754
 755static const struct file_operations telem_ioss_trc_verb_ops = {
 756        .open           = telem_ioss_trc_verb_open,
 757        .read           = seq_read,
 758        .write          = telem_ioss_trc_verb_write,
 759        .llseek         = seq_lseek,
 760        .release        = single_release,
 761};
 762
 763static int pm_suspend_prep_cb(void)
 764{
 765        struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];
 766        struct telemetry_debugfs_conf *conf = debugfs_conf;
 767        int ret, index;
 768
 769        ret = telemetry_raw_read_eventlog(TELEM_IOSS, evtlog,
 770                        TELEM_MAX_OS_ALLOCATED_EVENTS);
 771        if (ret < 0) {
 772                suspend_prep_ok = 0;
 773                goto out;
 774        }
 775
 776        for (index = 0; index < ret; index++) {
 777
 778                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_occ_id,
 779                                           suspend_shlw_ctr_temp);
 780
 781                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_occ_id,
 782                                           suspend_deep_ctr_temp);
 783
 784                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_res_id,
 785                                           suspend_shlw_res_temp);
 786
 787                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_res_id,
 788                                           suspend_deep_res_temp);
 789        }
 790        suspend_prep_ok = 1;
 791out:
 792        return NOTIFY_OK;
 793}
 794
 795static int pm_suspend_exit_cb(void)
 796{
 797        struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];
 798        static u32 suspend_shlw_ctr_exit, suspend_deep_ctr_exit;
 799        static u64 suspend_shlw_res_exit, suspend_deep_res_exit;
 800        struct telemetry_debugfs_conf *conf = debugfs_conf;
 801        int ret, index;
 802
 803        if (!suspend_prep_ok)
 804                goto out;
 805
 806        ret = telemetry_raw_read_eventlog(TELEM_IOSS, evtlog,
 807                                          TELEM_MAX_OS_ALLOCATED_EVENTS);
 808        if (ret < 0)
 809                goto out;
 810
 811        for (index = 0; index < ret; index++) {
 812                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_occ_id,
 813                                           suspend_shlw_ctr_exit);
 814
 815                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_occ_id,
 816                                           suspend_deep_ctr_exit);
 817
 818                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_shlw_res_id,
 819                                           suspend_shlw_res_exit);
 820
 821                TELEM_CHECK_AND_PARSE_CTRS(conf->s0ix_deep_res_id,
 822                                           suspend_deep_res_exit);
 823        }
 824
 825        if ((suspend_shlw_ctr_exit < suspend_shlw_ctr_temp) ||
 826            (suspend_deep_ctr_exit < suspend_deep_ctr_temp) ||
 827            (suspend_shlw_res_exit < suspend_shlw_res_temp) ||
 828            (suspend_deep_res_exit < suspend_deep_res_temp)) {
 829                pr_err("Wrong s0ix counters detected\n");
 830                goto out;
 831        }
 832
 833        /*
 834         * Due to some design limitations in the firmware, sometimes the
 835         * counters do not get updated by the time we reach here. As a
 836         * workaround, we try to see if this was a genuine case of sleep
 837         * failure or not by cross-checking from PMC GCR registers directly.
 838         */
 839        if (suspend_shlw_ctr_exit == suspend_shlw_ctr_temp &&
 840            suspend_deep_ctr_exit == suspend_deep_ctr_temp) {
 841                struct telemetry_plt_config *plt_config = telemetry_get_pltdata();
 842                struct intel_pmc_dev *pmc = plt_config->pmc;
 843
 844                ret = intel_pmc_gcr_read64(pmc, PMC_GCR_TELEM_SHLW_S0IX_REG,
 845                                          &suspend_shlw_res_exit);
 846                if (ret < 0)
 847                        goto out;
 848
 849                ret = intel_pmc_gcr_read64(pmc, PMC_GCR_TELEM_DEEP_S0IX_REG,
 850                                          &suspend_deep_res_exit);
 851                if (ret < 0)
 852                        goto out;
 853
 854                if (suspend_shlw_res_exit > suspend_shlw_res_temp)
 855                        suspend_shlw_ctr_exit++;
 856
 857                if (suspend_deep_res_exit > suspend_deep_res_temp)
 858                        suspend_deep_ctr_exit++;
 859        }
 860
 861        suspend_shlw_ctr_exit -= suspend_shlw_ctr_temp;
 862        suspend_deep_ctr_exit -= suspend_deep_ctr_temp;
 863        suspend_shlw_res_exit -= suspend_shlw_res_temp;
 864        suspend_deep_res_exit -= suspend_deep_res_temp;
 865
 866        if (suspend_shlw_ctr_exit != 0) {
 867                conf->suspend_stats.shlw_ctr +=
 868                suspend_shlw_ctr_exit;
 869
 870                conf->suspend_stats.shlw_res +=
 871                suspend_shlw_res_exit;
 872        }
 873
 874        if (suspend_deep_ctr_exit != 0) {
 875                conf->suspend_stats.deep_ctr +=
 876                suspend_deep_ctr_exit;
 877
 878                conf->suspend_stats.deep_res +=
 879                suspend_deep_res_exit;
 880        }
 881
 882out:
 883        suspend_prep_ok = 0;
 884        return NOTIFY_OK;
 885}
 886
 887static int pm_notification(struct notifier_block *this,
 888                           unsigned long event, void *ptr)
 889{
 890        switch (event) {
 891        case PM_SUSPEND_PREPARE:
 892                return pm_suspend_prep_cb();
 893        case PM_POST_SUSPEND:
 894                return pm_suspend_exit_cb();
 895        }
 896
 897        return NOTIFY_DONE;
 898}
 899
 900static struct notifier_block pm_notifier = {
 901        .notifier_call = pm_notification,
 902};
 903
 904static int __init telemetry_debugfs_init(void)
 905{
 906        const struct x86_cpu_id *id;
 907        int err;
 908        struct dentry *dir;
 909
 910        /* Only APL supported for now */
 911        id = x86_match_cpu(telemetry_debugfs_cpu_ids);
 912        if (!id)
 913                return -ENODEV;
 914
 915        debugfs_conf = (struct telemetry_debugfs_conf *)id->driver_data;
 916
 917        if (!telemetry_get_pltdata()) {
 918                pr_info("Invalid pltconfig, ensure IPC1 device is enabled in BIOS\n");
 919                return -ENODEV;
 920        }
 921
 922        err = telemetry_debugfs_check_evts();
 923        if (err < 0) {
 924                pr_info("telemetry_debugfs_check_evts failed\n");
 925                return -EINVAL;
 926        }
 927
 928        register_pm_notifier(&pm_notifier);
 929
 930        dir = debugfs_create_dir("telemetry", NULL);
 931        debugfs_conf->telemetry_dbg_dir = dir;
 932
 933        debugfs_create_file("pss_info", S_IFREG | S_IRUGO, dir, NULL,
 934                            &telem_pss_states_fops);
 935        debugfs_create_file("ioss_info", S_IFREG | S_IRUGO, dir, NULL,
 936                            &telem_ioss_states_fops);
 937        debugfs_create_file("soc_states", S_IFREG | S_IRUGO, dir, NULL,
 938                            &telem_soc_states_fops);
 939        debugfs_create_file("s0ix_residency_usec", S_IFREG | S_IRUGO, dir, NULL,
 940                            &telem_s0ix_fops);
 941        debugfs_create_file("pss_trace_verbosity", S_IFREG | S_IRUGO, dir, NULL,
 942                            &telem_pss_trc_verb_ops);
 943        debugfs_create_file("ioss_trace_verbosity", S_IFREG | S_IRUGO, dir,
 944                            NULL, &telem_ioss_trc_verb_ops);
 945        return 0;
 946}
 947
 948static void __exit telemetry_debugfs_exit(void)
 949{
 950        debugfs_remove_recursive(debugfs_conf->telemetry_dbg_dir);
 951        debugfs_conf->telemetry_dbg_dir = NULL;
 952        unregister_pm_notifier(&pm_notifier);
 953}
 954
 955late_initcall(telemetry_debugfs_init);
 956module_exit(telemetry_debugfs_exit);
 957
 958MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>");
 959MODULE_DESCRIPTION("Intel SoC Telemetry debugfs Interface");
 960MODULE_VERSION(DRIVER_VERSION);
 961MODULE_LICENSE("GPL v2");
 962