pltdrv.c (30508B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Intel SOC Telemetry Platform Driver: Currently supports APL 4 * Copyright (c) 2015, Intel Corporation. 5 * All Rights Reserved. 6 * 7 * This file provides the platform specific telemetry implementation for APL. 8 * It used the PUNIT and PMC IPC interfaces for configuring the counters. 9 * The accumulated results are fetched from SRAM. 10 */ 11 12#include <linux/io.h> 13#include <linux/module.h> 14#include <linux/platform_device.h> 15 16#include <asm/cpu_device_id.h> 17#include <asm/intel-family.h> 18#include <asm/intel_punit_ipc.h> 19#include <asm/intel_telemetry.h> 20 21#define DRIVER_NAME "intel_telemetry" 22#define DRIVER_VERSION "1.0.0" 23 24#define TELEM_TRC_VERBOSITY_MASK 0x3 25 26#define TELEM_MIN_PERIOD(x) ((x) & 0x7F0000) 27#define TELEM_MAX_PERIOD(x) ((x) & 0x7F000000) 28#define TELEM_SAMPLE_PERIOD_INVALID(x) ((x) & (BIT(7))) 29#define TELEM_CLEAR_SAMPLE_PERIOD(x) ((x) &= ~0x7F) 30 31#define TELEM_SAMPLING_DEFAULT_PERIOD 0xD 32 33#define TELEM_MAX_EVENTS_SRAM 28 34#define TELEM_SSRAM_STARTTIME_OFFSET 8 35#define TELEM_SSRAM_EVTLOG_OFFSET 16 36 37#define IOSS_TELEM 0xeb 38#define IOSS_TELEM_EVENT_READ 0x0 39#define IOSS_TELEM_EVENT_WRITE 0x1 40#define IOSS_TELEM_INFO_READ 0x2 41#define IOSS_TELEM_TRACE_CTL_READ 0x5 42#define IOSS_TELEM_TRACE_CTL_WRITE 0x6 43#define IOSS_TELEM_EVENT_CTL_READ 0x7 44#define IOSS_TELEM_EVENT_CTL_WRITE 0x8 45#define IOSS_TELEM_EVT_WRITE_SIZE 0x3 46 47#define TELEM_INFO_SRAMEVTS_MASK 0xFF00 48#define TELEM_INFO_SRAMEVTS_SHIFT 0x8 49#define TELEM_SSRAM_READ_TIMEOUT 10 50 51#define TELEM_INFO_NENABLES_MASK 0xFF 52#define TELEM_EVENT_ENABLE 0x8000 53 54#define TELEM_MASK_BIT 1 55#define TELEM_MASK_BYTE 0xFF 56#define BYTES_PER_LONG 8 57#define TELEM_MASK_PCS_STATE 0xF 58 59#define TELEM_DISABLE(x) ((x) &= ~(BIT(31))) 60#define TELEM_CLEAR_EVENTS(x) ((x) |= (BIT(30))) 61#define TELEM_ENABLE_SRAM_EVT_TRACE(x) ((x) &= ~(BIT(30) | BIT(24))) 62#define TELEM_ENABLE_PERIODIC(x) ((x) |= (BIT(23) | BIT(31) | BIT(7))) 63#define TELEM_EXTRACT_VERBOSITY(x, y) ((y) = (((x) >> 27) & 0x3)) 64#define TELEM_CLEAR_VERBOSITY_BITS(x) ((x) &= ~(BIT(27) | BIT(28))) 65#define TELEM_SET_VERBOSITY_BITS(x, y) ((x) |= ((y) << 27)) 66 67enum telemetry_action { 68 TELEM_UPDATE = 0, 69 TELEM_ADD, 70 TELEM_RESET, 71 TELEM_ACTION_NONE 72}; 73 74struct telem_ssram_region { 75 u64 timestamp; 76 u64 start_time; 77 u64 events[TELEM_MAX_EVENTS_SRAM]; 78}; 79 80static struct telemetry_plt_config *telm_conf; 81 82/* 83 * The following counters are programmed by default during setup. 84 * Only 20 allocated to kernel driver 85 */ 86static struct telemetry_evtmap 87 telemetry_apl_ioss_default_events[TELEM_MAX_OS_ALLOCATED_EVENTS] = { 88 {"SOC_S0IX_TOTAL_RES", 0x4800}, 89 {"SOC_S0IX_TOTAL_OCC", 0x4000}, 90 {"SOC_S0IX_SHALLOW_RES", 0x4801}, 91 {"SOC_S0IX_SHALLOW_OCC", 0x4001}, 92 {"SOC_S0IX_DEEP_RES", 0x4802}, 93 {"SOC_S0IX_DEEP_OCC", 0x4002}, 94 {"PMC_POWER_GATE", 0x5818}, 95 {"PMC_D3_STATES", 0x5819}, 96 {"PMC_D0I3_STATES", 0x581A}, 97 {"PMC_S0IX_WAKE_REASON_GPIO", 0x6000}, 98 {"PMC_S0IX_WAKE_REASON_TIMER", 0x6001}, 99 {"PMC_S0IX_WAKE_REASON_VNNREQ", 0x6002}, 100 {"PMC_S0IX_WAKE_REASON_LOWPOWER", 0x6003}, 101 {"PMC_S0IX_WAKE_REASON_EXTERNAL", 0x6004}, 102 {"PMC_S0IX_WAKE_REASON_MISC", 0x6005}, 103 {"PMC_S0IX_BLOCKING_IPS_D3_D0I3", 0x6006}, 104 {"PMC_S0IX_BLOCKING_IPS_PG", 0x6007}, 105 {"PMC_S0IX_BLOCKING_MISC_IPS_PG", 0x6008}, 106 {"PMC_S0IX_BLOCK_IPS_VNN_REQ", 0x6009}, 107 {"PMC_S0IX_BLOCK_IPS_CLOCKS", 0x600B}, 108}; 109 110 111static struct telemetry_evtmap 112 telemetry_apl_pss_default_events[TELEM_MAX_OS_ALLOCATED_EVENTS] = { 113 {"IA_CORE0_C6_RES", 0x0400}, 114 {"IA_CORE0_C6_CTR", 0x0000}, 115 {"IA_MODULE0_C7_RES", 0x0410}, 116 {"IA_MODULE0_C7_CTR", 0x000E}, 117 {"IA_C0_RES", 0x0805}, 118 {"PCS_LTR", 0x2801}, 119 {"PSTATES", 0x2802}, 120 {"SOC_S0I3_RES", 0x0409}, 121 {"SOC_S0I3_CTR", 0x000A}, 122 {"PCS_S0I3_CTR", 0x0009}, 123 {"PCS_C1E_RES", 0x041A}, 124 {"PCS_IDLE_STATUS", 0x2806}, 125 {"IA_PERF_LIMITS", 0x280B}, 126 {"GT_PERF_LIMITS", 0x280C}, 127 {"PCS_WAKEUP_S0IX_CTR", 0x0030}, 128 {"PCS_IDLE_BLOCKED", 0x2C00}, 129 {"PCS_S0IX_BLOCKED", 0x2C01}, 130 {"PCS_S0IX_WAKE_REASONS", 0x2C02}, 131 {"PCS_LTR_BLOCKING", 0x2C03}, 132 {"PC2_AND_MEM_SHALLOW_IDLE_RES", 0x1D40}, 133}; 134 135static struct telemetry_evtmap 136 telemetry_glk_pss_default_events[TELEM_MAX_OS_ALLOCATED_EVENTS] = { 137 {"IA_CORE0_C6_RES", 0x0400}, 138 {"IA_CORE0_C6_CTR", 0x0000}, 139 {"IA_MODULE0_C7_RES", 0x0410}, 140 {"IA_MODULE0_C7_CTR", 0x000C}, 141 {"IA_C0_RES", 0x0805}, 142 {"PCS_LTR", 0x2801}, 143 {"PSTATES", 0x2802}, 144 {"SOC_S0I3_RES", 0x0407}, 145 {"SOC_S0I3_CTR", 0x0008}, 146 {"PCS_S0I3_CTR", 0x0007}, 147 {"PCS_C1E_RES", 0x0414}, 148 {"PCS_IDLE_STATUS", 0x2806}, 149 {"IA_PERF_LIMITS", 0x280B}, 150 {"GT_PERF_LIMITS", 0x280C}, 151 {"PCS_WAKEUP_S0IX_CTR", 0x0025}, 152 {"PCS_IDLE_BLOCKED", 0x2C00}, 153 {"PCS_S0IX_BLOCKED", 0x2C01}, 154 {"PCS_S0IX_WAKE_REASONS", 0x2C02}, 155 {"PCS_LTR_BLOCKING", 0x2C03}, 156 {"PC2_AND_MEM_SHALLOW_IDLE_RES", 0x1D40}, 157}; 158 159/* APL specific Data */ 160static struct telemetry_plt_config telem_apl_config = { 161 .pss_config = { 162 .telem_evts = telemetry_apl_pss_default_events, 163 }, 164 .ioss_config = { 165 .telem_evts = telemetry_apl_ioss_default_events, 166 }, 167}; 168 169/* GLK specific Data */ 170static struct telemetry_plt_config telem_glk_config = { 171 .pss_config = { 172 .telem_evts = telemetry_glk_pss_default_events, 173 }, 174 .ioss_config = { 175 .telem_evts = telemetry_apl_ioss_default_events, 176 }, 177}; 178 179static const struct x86_cpu_id telemetry_cpu_ids[] = { 180 X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, &telem_apl_config), 181 X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_PLUS, &telem_glk_config), 182 {} 183}; 184 185MODULE_DEVICE_TABLE(x86cpu, telemetry_cpu_ids); 186 187static inline int telem_get_unitconfig(enum telemetry_unit telem_unit, 188 struct telemetry_unit_config **unit_config) 189{ 190 if (telem_unit == TELEM_PSS) 191 *unit_config = &(telm_conf->pss_config); 192 else if (telem_unit == TELEM_IOSS) 193 *unit_config = &(telm_conf->ioss_config); 194 else 195 return -EINVAL; 196 197 return 0; 198 199} 200 201static int telemetry_check_evtid(enum telemetry_unit telem_unit, 202 u32 *evtmap, u8 len, 203 enum telemetry_action action) 204{ 205 struct telemetry_unit_config *unit_config; 206 int ret; 207 208 ret = telem_get_unitconfig(telem_unit, &unit_config); 209 if (ret < 0) 210 return ret; 211 212 switch (action) { 213 case TELEM_RESET: 214 if (len > TELEM_MAX_EVENTS_SRAM) 215 return -EINVAL; 216 217 break; 218 219 case TELEM_UPDATE: 220 if (len > TELEM_MAX_EVENTS_SRAM) 221 return -EINVAL; 222 223 if ((len > 0) && (evtmap == NULL)) 224 return -EINVAL; 225 226 break; 227 228 case TELEM_ADD: 229 if ((len + unit_config->ssram_evts_used) > 230 TELEM_MAX_EVENTS_SRAM) 231 return -EINVAL; 232 233 if ((len > 0) && (evtmap == NULL)) 234 return -EINVAL; 235 236 break; 237 238 default: 239 pr_err("Unknown Telemetry action specified %d\n", action); 240 return -EINVAL; 241 } 242 243 return 0; 244} 245 246 247static inline int telemetry_plt_config_ioss_event(u32 evt_id, int index) 248{ 249 u32 write_buf; 250 251 write_buf = evt_id | TELEM_EVENT_ENABLE; 252 write_buf <<= BITS_PER_BYTE; 253 write_buf |= index; 254 255 return intel_scu_ipc_dev_command(telm_conf->scu, IOSS_TELEM, 256 IOSS_TELEM_EVENT_WRITE, &write_buf, 257 IOSS_TELEM_EVT_WRITE_SIZE, NULL, 0); 258} 259 260static inline int telemetry_plt_config_pss_event(u32 evt_id, int index) 261{ 262 u32 write_buf; 263 int ret; 264 265 write_buf = evt_id | TELEM_EVENT_ENABLE; 266 ret = intel_punit_ipc_command(IPC_PUNIT_BIOS_WRITE_TELE_EVENT, 267 index, 0, &write_buf, NULL); 268 269 return ret; 270} 271 272static int telemetry_setup_iossevtconfig(struct telemetry_evtconfig evtconfig, 273 enum telemetry_action action) 274{ 275 struct intel_scu_ipc_dev *scu = telm_conf->scu; 276 u8 num_ioss_evts, ioss_period; 277 int ret, index, idx; 278 u32 *ioss_evtmap; 279 u32 telem_ctrl; 280 281 num_ioss_evts = evtconfig.num_evts; 282 ioss_period = evtconfig.period; 283 ioss_evtmap = evtconfig.evtmap; 284 285 /* Get telemetry EVENT CTL */ 286 ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM, 287 IOSS_TELEM_EVENT_CTL_READ, NULL, 0, 288 &telem_ctrl, sizeof(telem_ctrl)); 289 if (ret) { 290 pr_err("IOSS TELEM_CTRL Read Failed\n"); 291 return ret; 292 } 293 294 /* Disable Telemetry */ 295 TELEM_DISABLE(telem_ctrl); 296 297 ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM, 298 IOSS_TELEM_EVENT_CTL_WRITE, &telem_ctrl, 299 sizeof(telem_ctrl), NULL, 0); 300 if (ret) { 301 pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n"); 302 return ret; 303 } 304 305 306 /* Reset Everything */ 307 if (action == TELEM_RESET) { 308 /* Clear All Events */ 309 TELEM_CLEAR_EVENTS(telem_ctrl); 310 311 ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM, 312 IOSS_TELEM_EVENT_CTL_WRITE, 313 &telem_ctrl, sizeof(telem_ctrl), 314 NULL, 0); 315 if (ret) { 316 pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n"); 317 return ret; 318 } 319 telm_conf->ioss_config.ssram_evts_used = 0; 320 321 /* Configure Events */ 322 for (idx = 0; idx < num_ioss_evts; idx++) { 323 if (telemetry_plt_config_ioss_event( 324 telm_conf->ioss_config.telem_evts[idx].evt_id, 325 idx)) { 326 pr_err("IOSS TELEM_RESET Fail for data: %x\n", 327 telm_conf->ioss_config.telem_evts[idx].evt_id); 328 continue; 329 } 330 telm_conf->ioss_config.ssram_evts_used++; 331 } 332 } 333 334 /* Re-Configure Everything */ 335 if (action == TELEM_UPDATE) { 336 /* Clear All Events */ 337 TELEM_CLEAR_EVENTS(telem_ctrl); 338 339 ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM, 340 IOSS_TELEM_EVENT_CTL_WRITE, 341 &telem_ctrl, sizeof(telem_ctrl), 342 NULL, 0); 343 if (ret) { 344 pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n"); 345 return ret; 346 } 347 telm_conf->ioss_config.ssram_evts_used = 0; 348 349 /* Configure Events */ 350 for (index = 0; index < num_ioss_evts; index++) { 351 telm_conf->ioss_config.telem_evts[index].evt_id = 352 ioss_evtmap[index]; 353 354 if (telemetry_plt_config_ioss_event( 355 telm_conf->ioss_config.telem_evts[index].evt_id, 356 index)) { 357 pr_err("IOSS TELEM_UPDATE Fail for Evt%x\n", 358 ioss_evtmap[index]); 359 continue; 360 } 361 telm_conf->ioss_config.ssram_evts_used++; 362 } 363 } 364 365 /* Add some Events */ 366 if (action == TELEM_ADD) { 367 /* Configure Events */ 368 for (index = telm_conf->ioss_config.ssram_evts_used, idx = 0; 369 idx < num_ioss_evts; index++, idx++) { 370 telm_conf->ioss_config.telem_evts[index].evt_id = 371 ioss_evtmap[idx]; 372 373 if (telemetry_plt_config_ioss_event( 374 telm_conf->ioss_config.telem_evts[index].evt_id, 375 index)) { 376 pr_err("IOSS TELEM_ADD Fail for Event %x\n", 377 ioss_evtmap[idx]); 378 continue; 379 } 380 telm_conf->ioss_config.ssram_evts_used++; 381 } 382 } 383 384 /* Enable Periodic Telemetry Events and enable SRAM trace */ 385 TELEM_CLEAR_SAMPLE_PERIOD(telem_ctrl); 386 TELEM_ENABLE_SRAM_EVT_TRACE(telem_ctrl); 387 TELEM_ENABLE_PERIODIC(telem_ctrl); 388 telem_ctrl |= ioss_period; 389 390 ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM, 391 IOSS_TELEM_EVENT_CTL_WRITE, 392 &telem_ctrl, sizeof(telem_ctrl), NULL, 0); 393 if (ret) { 394 pr_err("IOSS TELEM_CTRL Event Enable Write Failed\n"); 395 return ret; 396 } 397 398 telm_conf->ioss_config.curr_period = ioss_period; 399 400 return 0; 401} 402 403 404static int telemetry_setup_pssevtconfig(struct telemetry_evtconfig evtconfig, 405 enum telemetry_action action) 406{ 407 u8 num_pss_evts, pss_period; 408 int ret, index, idx; 409 u32 *pss_evtmap; 410 u32 telem_ctrl; 411 412 num_pss_evts = evtconfig.num_evts; 413 pss_period = evtconfig.period; 414 pss_evtmap = evtconfig.evtmap; 415 416 /* PSS Config */ 417 /* Get telemetry EVENT CTL */ 418 ret = intel_punit_ipc_command(IPC_PUNIT_BIOS_READ_TELE_EVENT_CTRL, 419 0, 0, NULL, &telem_ctrl); 420 if (ret) { 421 pr_err("PSS TELEM_CTRL Read Failed\n"); 422 return ret; 423 } 424 425 /* Disable Telemetry */ 426 TELEM_DISABLE(telem_ctrl); 427 ret = intel_punit_ipc_command(IPC_PUNIT_BIOS_WRITE_TELE_EVENT_CTRL, 428 0, 0, &telem_ctrl, NULL); 429 if (ret) { 430 pr_err("PSS TELEM_CTRL Event Disable Write Failed\n"); 431 return ret; 432 } 433 434 /* Reset Everything */ 435 if (action == TELEM_RESET) { 436 /* Clear All Events */ 437 TELEM_CLEAR_EVENTS(telem_ctrl); 438 439 ret = intel_punit_ipc_command( 440 IPC_PUNIT_BIOS_WRITE_TELE_EVENT_CTRL, 441 0, 0, &telem_ctrl, NULL); 442 if (ret) { 443 pr_err("PSS TELEM_CTRL Event Disable Write Failed\n"); 444 return ret; 445 } 446 telm_conf->pss_config.ssram_evts_used = 0; 447 /* Configure Events */ 448 for (idx = 0; idx < num_pss_evts; idx++) { 449 if (telemetry_plt_config_pss_event( 450 telm_conf->pss_config.telem_evts[idx].evt_id, 451 idx)) { 452 pr_err("PSS TELEM_RESET Fail for Event %x\n", 453 telm_conf->pss_config.telem_evts[idx].evt_id); 454 continue; 455 } 456 telm_conf->pss_config.ssram_evts_used++; 457 } 458 } 459 460 /* Re-Configure Everything */ 461 if (action == TELEM_UPDATE) { 462 /* Clear All Events */ 463 TELEM_CLEAR_EVENTS(telem_ctrl); 464 465 ret = intel_punit_ipc_command( 466 IPC_PUNIT_BIOS_WRITE_TELE_EVENT_CTRL, 467 0, 0, &telem_ctrl, NULL); 468 if (ret) { 469 pr_err("PSS TELEM_CTRL Event Disable Write Failed\n"); 470 return ret; 471 } 472 telm_conf->pss_config.ssram_evts_used = 0; 473 474 /* Configure Events */ 475 for (index = 0; index < num_pss_evts; index++) { 476 telm_conf->pss_config.telem_evts[index].evt_id = 477 pss_evtmap[index]; 478 479 if (telemetry_plt_config_pss_event( 480 telm_conf->pss_config.telem_evts[index].evt_id, 481 index)) { 482 pr_err("PSS TELEM_UPDATE Fail for Event %x\n", 483 pss_evtmap[index]); 484 continue; 485 } 486 telm_conf->pss_config.ssram_evts_used++; 487 } 488 } 489 490 /* Add some Events */ 491 if (action == TELEM_ADD) { 492 /* Configure Events */ 493 for (index = telm_conf->pss_config.ssram_evts_used, idx = 0; 494 idx < num_pss_evts; index++, idx++) { 495 496 telm_conf->pss_config.telem_evts[index].evt_id = 497 pss_evtmap[idx]; 498 499 if (telemetry_plt_config_pss_event( 500 telm_conf->pss_config.telem_evts[index].evt_id, 501 index)) { 502 pr_err("PSS TELEM_ADD Fail for Event %x\n", 503 pss_evtmap[idx]); 504 continue; 505 } 506 telm_conf->pss_config.ssram_evts_used++; 507 } 508 } 509 510 /* Enable Periodic Telemetry Events and enable SRAM trace */ 511 TELEM_CLEAR_SAMPLE_PERIOD(telem_ctrl); 512 TELEM_ENABLE_SRAM_EVT_TRACE(telem_ctrl); 513 TELEM_ENABLE_PERIODIC(telem_ctrl); 514 telem_ctrl |= pss_period; 515 516 ret = intel_punit_ipc_command(IPC_PUNIT_BIOS_WRITE_TELE_EVENT_CTRL, 517 0, 0, &telem_ctrl, NULL); 518 if (ret) { 519 pr_err("PSS TELEM_CTRL Event Enable Write Failed\n"); 520 return ret; 521 } 522 523 telm_conf->pss_config.curr_period = pss_period; 524 525 return 0; 526} 527 528static int telemetry_setup_evtconfig(struct telemetry_evtconfig pss_evtconfig, 529 struct telemetry_evtconfig ioss_evtconfig, 530 enum telemetry_action action) 531{ 532 int ret; 533 534 mutex_lock(&(telm_conf->telem_lock)); 535 536 if ((action == TELEM_UPDATE) && (telm_conf->telem_in_use)) { 537 ret = -EBUSY; 538 goto out; 539 } 540 541 ret = telemetry_check_evtid(TELEM_PSS, pss_evtconfig.evtmap, 542 pss_evtconfig.num_evts, action); 543 if (ret) 544 goto out; 545 546 ret = telemetry_check_evtid(TELEM_IOSS, ioss_evtconfig.evtmap, 547 ioss_evtconfig.num_evts, action); 548 if (ret) 549 goto out; 550 551 if (ioss_evtconfig.num_evts) { 552 ret = telemetry_setup_iossevtconfig(ioss_evtconfig, action); 553 if (ret) 554 goto out; 555 } 556 557 if (pss_evtconfig.num_evts) { 558 ret = telemetry_setup_pssevtconfig(pss_evtconfig, action); 559 if (ret) 560 goto out; 561 } 562 563 if ((action == TELEM_UPDATE) || (action == TELEM_ADD)) 564 telm_conf->telem_in_use = true; 565 else 566 telm_conf->telem_in_use = false; 567 568out: 569 mutex_unlock(&(telm_conf->telem_lock)); 570 return ret; 571} 572 573static int telemetry_setup(struct platform_device *pdev) 574{ 575 struct telemetry_evtconfig pss_evtconfig, ioss_evtconfig; 576 u32 read_buf, events, event_regs; 577 int ret; 578 579 ret = intel_scu_ipc_dev_command(telm_conf->scu, IOSS_TELEM, 580 IOSS_TELEM_INFO_READ, NULL, 0, 581 &read_buf, sizeof(read_buf)); 582 if (ret) { 583 dev_err(&pdev->dev, "IOSS TELEM_INFO Read Failed\n"); 584 return ret; 585 } 586 587 /* Get telemetry Info */ 588 events = (read_buf & TELEM_INFO_SRAMEVTS_MASK) >> 589 TELEM_INFO_SRAMEVTS_SHIFT; 590 event_regs = read_buf & TELEM_INFO_NENABLES_MASK; 591 if ((events < TELEM_MAX_EVENTS_SRAM) || 592 (event_regs < TELEM_MAX_EVENTS_SRAM)) { 593 dev_err(&pdev->dev, "IOSS:Insufficient Space for SRAM Trace\n"); 594 dev_err(&pdev->dev, "SRAM Events %d; Event Regs %d\n", 595 events, event_regs); 596 return -ENOMEM; 597 } 598 599 telm_conf->ioss_config.min_period = TELEM_MIN_PERIOD(read_buf); 600 telm_conf->ioss_config.max_period = TELEM_MAX_PERIOD(read_buf); 601 602 /* PUNIT Mailbox Setup */ 603 ret = intel_punit_ipc_command(IPC_PUNIT_BIOS_READ_TELE_INFO, 0, 0, 604 NULL, &read_buf); 605 if (ret) { 606 dev_err(&pdev->dev, "PSS TELEM_INFO Read Failed\n"); 607 return ret; 608 } 609 610 /* Get telemetry Info */ 611 events = (read_buf & TELEM_INFO_SRAMEVTS_MASK) >> 612 TELEM_INFO_SRAMEVTS_SHIFT; 613 event_regs = read_buf & TELEM_INFO_SRAMEVTS_MASK; 614 if ((events < TELEM_MAX_EVENTS_SRAM) || 615 (event_regs < TELEM_MAX_EVENTS_SRAM)) { 616 dev_err(&pdev->dev, "PSS:Insufficient Space for SRAM Trace\n"); 617 dev_err(&pdev->dev, "SRAM Events %d; Event Regs %d\n", 618 events, event_regs); 619 return -ENOMEM; 620 } 621 622 telm_conf->pss_config.min_period = TELEM_MIN_PERIOD(read_buf); 623 telm_conf->pss_config.max_period = TELEM_MAX_PERIOD(read_buf); 624 625 pss_evtconfig.evtmap = NULL; 626 pss_evtconfig.num_evts = TELEM_MAX_OS_ALLOCATED_EVENTS; 627 pss_evtconfig.period = TELEM_SAMPLING_DEFAULT_PERIOD; 628 629 ioss_evtconfig.evtmap = NULL; 630 ioss_evtconfig.num_evts = TELEM_MAX_OS_ALLOCATED_EVENTS; 631 ioss_evtconfig.period = TELEM_SAMPLING_DEFAULT_PERIOD; 632 633 ret = telemetry_setup_evtconfig(pss_evtconfig, ioss_evtconfig, 634 TELEM_RESET); 635 if (ret) { 636 dev_err(&pdev->dev, "TELEMETRY Setup Failed\n"); 637 return ret; 638 } 639 return 0; 640} 641 642static int telemetry_plt_update_events(struct telemetry_evtconfig pss_evtconfig, 643 struct telemetry_evtconfig ioss_evtconfig) 644{ 645 int ret; 646 647 if ((pss_evtconfig.num_evts > 0) && 648 (TELEM_SAMPLE_PERIOD_INVALID(pss_evtconfig.period))) { 649 pr_err("PSS Sampling Period Out of Range\n"); 650 return -EINVAL; 651 } 652 653 if ((ioss_evtconfig.num_evts > 0) && 654 (TELEM_SAMPLE_PERIOD_INVALID(ioss_evtconfig.period))) { 655 pr_err("IOSS Sampling Period Out of Range\n"); 656 return -EINVAL; 657 } 658 659 ret = telemetry_setup_evtconfig(pss_evtconfig, ioss_evtconfig, 660 TELEM_UPDATE); 661 if (ret) 662 pr_err("TELEMETRY Config Failed\n"); 663 664 return ret; 665} 666 667 668static int telemetry_plt_set_sampling_period(u8 pss_period, u8 ioss_period) 669{ 670 u32 telem_ctrl = 0; 671 int ret = 0; 672 673 mutex_lock(&(telm_conf->telem_lock)); 674 if (ioss_period) { 675 struct intel_scu_ipc_dev *scu = telm_conf->scu; 676 677 if (TELEM_SAMPLE_PERIOD_INVALID(ioss_period)) { 678 pr_err("IOSS Sampling Period Out of Range\n"); 679 ret = -EINVAL; 680 goto out; 681 } 682 683 /* Get telemetry EVENT CTL */ 684 ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM, 685 IOSS_TELEM_EVENT_CTL_READ, NULL, 0, 686 &telem_ctrl, sizeof(telem_ctrl)); 687 if (ret) { 688 pr_err("IOSS TELEM_CTRL Read Failed\n"); 689 goto out; 690 } 691 692 /* Disable Telemetry */ 693 TELEM_DISABLE(telem_ctrl); 694 695 ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM, 696 IOSS_TELEM_EVENT_CTL_WRITE, 697 &telem_ctrl, sizeof(telem_ctrl), 698 NULL, 0); 699 if (ret) { 700 pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n"); 701 goto out; 702 } 703 704 /* Enable Periodic Telemetry Events and enable SRAM trace */ 705 TELEM_CLEAR_SAMPLE_PERIOD(telem_ctrl); 706 TELEM_ENABLE_SRAM_EVT_TRACE(telem_ctrl); 707 TELEM_ENABLE_PERIODIC(telem_ctrl); 708 telem_ctrl |= ioss_period; 709 710 ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM, 711 IOSS_TELEM_EVENT_CTL_WRITE, 712 &telem_ctrl, sizeof(telem_ctrl), 713 NULL, 0); 714 if (ret) { 715 pr_err("IOSS TELEM_CTRL Event Enable Write Failed\n"); 716 goto out; 717 } 718 telm_conf->ioss_config.curr_period = ioss_period; 719 } 720 721 if (pss_period) { 722 if (TELEM_SAMPLE_PERIOD_INVALID(pss_period)) { 723 pr_err("PSS Sampling Period Out of Range\n"); 724 ret = -EINVAL; 725 goto out; 726 } 727 728 /* Get telemetry EVENT CTL */ 729 ret = intel_punit_ipc_command( 730 IPC_PUNIT_BIOS_READ_TELE_EVENT_CTRL, 731 0, 0, NULL, &telem_ctrl); 732 if (ret) { 733 pr_err("PSS TELEM_CTRL Read Failed\n"); 734 goto out; 735 } 736 737 /* Disable Telemetry */ 738 TELEM_DISABLE(telem_ctrl); 739 ret = intel_punit_ipc_command( 740 IPC_PUNIT_BIOS_WRITE_TELE_EVENT_CTRL, 741 0, 0, &telem_ctrl, NULL); 742 if (ret) { 743 pr_err("PSS TELEM_CTRL Event Disable Write Failed\n"); 744 goto out; 745 } 746 747 /* Enable Periodic Telemetry Events and enable SRAM trace */ 748 TELEM_CLEAR_SAMPLE_PERIOD(telem_ctrl); 749 TELEM_ENABLE_SRAM_EVT_TRACE(telem_ctrl); 750 TELEM_ENABLE_PERIODIC(telem_ctrl); 751 telem_ctrl |= pss_period; 752 753 ret = intel_punit_ipc_command( 754 IPC_PUNIT_BIOS_WRITE_TELE_EVENT_CTRL, 755 0, 0, &telem_ctrl, NULL); 756 if (ret) { 757 pr_err("PSS TELEM_CTRL Event Enable Write Failed\n"); 758 goto out; 759 } 760 telm_conf->pss_config.curr_period = pss_period; 761 } 762 763out: 764 mutex_unlock(&(telm_conf->telem_lock)); 765 return ret; 766} 767 768 769static int telemetry_plt_get_sampling_period(u8 *pss_min_period, 770 u8 *pss_max_period, 771 u8 *ioss_min_period, 772 u8 *ioss_max_period) 773{ 774 *pss_min_period = telm_conf->pss_config.min_period; 775 *pss_max_period = telm_conf->pss_config.max_period; 776 *ioss_min_period = telm_conf->ioss_config.min_period; 777 *ioss_max_period = telm_conf->ioss_config.max_period; 778 779 return 0; 780} 781 782 783static int telemetry_plt_reset_events(void) 784{ 785 struct telemetry_evtconfig pss_evtconfig, ioss_evtconfig; 786 int ret; 787 788 pss_evtconfig.evtmap = NULL; 789 pss_evtconfig.num_evts = TELEM_MAX_OS_ALLOCATED_EVENTS; 790 pss_evtconfig.period = TELEM_SAMPLING_DEFAULT_PERIOD; 791 792 ioss_evtconfig.evtmap = NULL; 793 ioss_evtconfig.num_evts = TELEM_MAX_OS_ALLOCATED_EVENTS; 794 ioss_evtconfig.period = TELEM_SAMPLING_DEFAULT_PERIOD; 795 796 ret = telemetry_setup_evtconfig(pss_evtconfig, ioss_evtconfig, 797 TELEM_RESET); 798 if (ret) 799 pr_err("TELEMETRY Reset Failed\n"); 800 801 return ret; 802} 803 804 805static int telemetry_plt_get_eventconfig(struct telemetry_evtconfig *pss_config, 806 struct telemetry_evtconfig *ioss_config, 807 int pss_len, int ioss_len) 808{ 809 u32 *pss_evtmap, *ioss_evtmap; 810 u32 index; 811 812 pss_evtmap = pss_config->evtmap; 813 ioss_evtmap = ioss_config->evtmap; 814 815 mutex_lock(&(telm_conf->telem_lock)); 816 pss_config->num_evts = telm_conf->pss_config.ssram_evts_used; 817 ioss_config->num_evts = telm_conf->ioss_config.ssram_evts_used; 818 819 pss_config->period = telm_conf->pss_config.curr_period; 820 ioss_config->period = telm_conf->ioss_config.curr_period; 821 822 if ((pss_len < telm_conf->pss_config.ssram_evts_used) || 823 (ioss_len < telm_conf->ioss_config.ssram_evts_used)) { 824 mutex_unlock(&(telm_conf->telem_lock)); 825 return -EINVAL; 826 } 827 828 for (index = 0; index < telm_conf->pss_config.ssram_evts_used; 829 index++) { 830 pss_evtmap[index] = 831 telm_conf->pss_config.telem_evts[index].evt_id; 832 } 833 834 for (index = 0; index < telm_conf->ioss_config.ssram_evts_used; 835 index++) { 836 ioss_evtmap[index] = 837 telm_conf->ioss_config.telem_evts[index].evt_id; 838 } 839 840 mutex_unlock(&(telm_conf->telem_lock)); 841 return 0; 842} 843 844 845static int telemetry_plt_add_events(u8 num_pss_evts, u8 num_ioss_evts, 846 u32 *pss_evtmap, u32 *ioss_evtmap) 847{ 848 struct telemetry_evtconfig pss_evtconfig, ioss_evtconfig; 849 int ret; 850 851 pss_evtconfig.evtmap = pss_evtmap; 852 pss_evtconfig.num_evts = num_pss_evts; 853 pss_evtconfig.period = telm_conf->pss_config.curr_period; 854 855 ioss_evtconfig.evtmap = ioss_evtmap; 856 ioss_evtconfig.num_evts = num_ioss_evts; 857 ioss_evtconfig.period = telm_conf->ioss_config.curr_period; 858 859 ret = telemetry_setup_evtconfig(pss_evtconfig, ioss_evtconfig, 860 TELEM_ADD); 861 if (ret) 862 pr_err("TELEMETRY ADD Failed\n"); 863 864 return ret; 865} 866 867static int telem_evtlog_read(enum telemetry_unit telem_unit, 868 struct telem_ssram_region *ssram_region, u8 len) 869{ 870 struct telemetry_unit_config *unit_config; 871 u64 timestamp_prev, timestamp_next; 872 int ret, index, timeout = 0; 873 874 ret = telem_get_unitconfig(telem_unit, &unit_config); 875 if (ret < 0) 876 return ret; 877 878 if (len > unit_config->ssram_evts_used) 879 len = unit_config->ssram_evts_used; 880 881 do { 882 timestamp_prev = readq(unit_config->regmap); 883 if (!timestamp_prev) { 884 pr_err("Ssram under update. Please Try Later\n"); 885 return -EBUSY; 886 } 887 888 ssram_region->start_time = readq(unit_config->regmap + 889 TELEM_SSRAM_STARTTIME_OFFSET); 890 891 for (index = 0; index < len; index++) { 892 ssram_region->events[index] = 893 readq(unit_config->regmap + TELEM_SSRAM_EVTLOG_OFFSET + 894 BYTES_PER_LONG*index); 895 } 896 897 timestamp_next = readq(unit_config->regmap); 898 if (!timestamp_next) { 899 pr_err("Ssram under update. Please Try Later\n"); 900 return -EBUSY; 901 } 902 903 if (timeout++ > TELEM_SSRAM_READ_TIMEOUT) { 904 pr_err("Timeout while reading Events\n"); 905 return -EBUSY; 906 } 907 908 } while (timestamp_prev != timestamp_next); 909 910 ssram_region->timestamp = timestamp_next; 911 912 return len; 913} 914 915static int telemetry_plt_raw_read_eventlog(enum telemetry_unit telem_unit, 916 struct telemetry_evtlog *evtlog, 917 int len, int log_all_evts) 918{ 919 int index, idx1, ret, readlen = len; 920 struct telem_ssram_region ssram_region; 921 struct telemetry_evtmap *evtmap; 922 923 switch (telem_unit) { 924 case TELEM_PSS: 925 evtmap = telm_conf->pss_config.telem_evts; 926 break; 927 928 case TELEM_IOSS: 929 evtmap = telm_conf->ioss_config.telem_evts; 930 break; 931 932 default: 933 pr_err("Unknown Telemetry Unit Specified %d\n", telem_unit); 934 return -EINVAL; 935 } 936 937 if (!log_all_evts) 938 readlen = TELEM_MAX_EVENTS_SRAM; 939 940 ret = telem_evtlog_read(telem_unit, &ssram_region, readlen); 941 if (ret < 0) 942 return ret; 943 944 /* Invalid evt-id array specified via length mismatch */ 945 if ((!log_all_evts) && (len > ret)) 946 return -EINVAL; 947 948 if (log_all_evts) 949 for (index = 0; index < ret; index++) { 950 evtlog[index].telem_evtlog = ssram_region.events[index]; 951 evtlog[index].telem_evtid = evtmap[index].evt_id; 952 } 953 else 954 for (index = 0, readlen = 0; (index < ret) && (readlen < len); 955 index++) { 956 for (idx1 = 0; idx1 < len; idx1++) { 957 /* Elements matched */ 958 if (evtmap[index].evt_id == 959 evtlog[idx1].telem_evtid) { 960 evtlog[idx1].telem_evtlog = 961 ssram_region.events[index]; 962 readlen++; 963 964 break; 965 } 966 } 967 } 968 969 return readlen; 970} 971 972static int telemetry_plt_read_eventlog(enum telemetry_unit telem_unit, 973 struct telemetry_evtlog *evtlog, int len, int log_all_evts) 974{ 975 int ret; 976 977 mutex_lock(&(telm_conf->telem_lock)); 978 ret = telemetry_plt_raw_read_eventlog(telem_unit, evtlog, 979 len, log_all_evts); 980 mutex_unlock(&(telm_conf->telem_lock)); 981 982 return ret; 983} 984 985static int telemetry_plt_get_trace_verbosity(enum telemetry_unit telem_unit, 986 u32 *verbosity) 987{ 988 u32 temp = 0; 989 int ret; 990 991 if (verbosity == NULL) 992 return -EINVAL; 993 994 mutex_lock(&(telm_conf->telem_trace_lock)); 995 switch (telem_unit) { 996 case TELEM_PSS: 997 ret = intel_punit_ipc_command( 998 IPC_PUNIT_BIOS_READ_TELE_TRACE_CTRL, 999 0, 0, NULL, &temp); 1000 if (ret) { 1001 pr_err("PSS TRACE_CTRL Read Failed\n"); 1002 goto out; 1003 } 1004 1005 break; 1006 1007 case TELEM_IOSS: 1008 ret = intel_scu_ipc_dev_command(telm_conf->scu, 1009 IOSS_TELEM, IOSS_TELEM_TRACE_CTL_READ, 1010 NULL, 0, &temp, sizeof(temp)); 1011 if (ret) { 1012 pr_err("IOSS TRACE_CTL Read Failed\n"); 1013 goto out; 1014 } 1015 1016 break; 1017 1018 default: 1019 pr_err("Unknown Telemetry Unit Specified %d\n", telem_unit); 1020 ret = -EINVAL; 1021 break; 1022 } 1023 TELEM_EXTRACT_VERBOSITY(temp, *verbosity); 1024 1025out: 1026 mutex_unlock(&(telm_conf->telem_trace_lock)); 1027 return ret; 1028} 1029 1030static int telemetry_plt_set_trace_verbosity(enum telemetry_unit telem_unit, 1031 u32 verbosity) 1032{ 1033 u32 temp = 0; 1034 int ret; 1035 1036 verbosity &= TELEM_TRC_VERBOSITY_MASK; 1037 1038 mutex_lock(&(telm_conf->telem_trace_lock)); 1039 switch (telem_unit) { 1040 case TELEM_PSS: 1041 ret = intel_punit_ipc_command( 1042 IPC_PUNIT_BIOS_READ_TELE_TRACE_CTRL, 1043 0, 0, NULL, &temp); 1044 if (ret) { 1045 pr_err("PSS TRACE_CTRL Read Failed\n"); 1046 goto out; 1047 } 1048 1049 TELEM_CLEAR_VERBOSITY_BITS(temp); 1050 TELEM_SET_VERBOSITY_BITS(temp, verbosity); 1051 1052 ret = intel_punit_ipc_command( 1053 IPC_PUNIT_BIOS_WRITE_TELE_TRACE_CTRL, 1054 0, 0, &temp, NULL); 1055 if (ret) { 1056 pr_err("PSS TRACE_CTRL Verbosity Set Failed\n"); 1057 goto out; 1058 } 1059 break; 1060 1061 case TELEM_IOSS: 1062 ret = intel_scu_ipc_dev_command(telm_conf->scu, IOSS_TELEM, 1063 IOSS_TELEM_TRACE_CTL_READ, 1064 NULL, 0, &temp, sizeof(temp)); 1065 if (ret) { 1066 pr_err("IOSS TRACE_CTL Read Failed\n"); 1067 goto out; 1068 } 1069 1070 TELEM_CLEAR_VERBOSITY_BITS(temp); 1071 TELEM_SET_VERBOSITY_BITS(temp, verbosity); 1072 1073 ret = intel_scu_ipc_dev_command(telm_conf->scu, IOSS_TELEM, 1074 IOSS_TELEM_TRACE_CTL_WRITE, 1075 &temp, sizeof(temp), NULL, 0); 1076 if (ret) { 1077 pr_err("IOSS TRACE_CTL Verbosity Set Failed\n"); 1078 goto out; 1079 } 1080 break; 1081 1082 default: 1083 pr_err("Unknown Telemetry Unit Specified %d\n", telem_unit); 1084 ret = -EINVAL; 1085 break; 1086 } 1087 1088out: 1089 mutex_unlock(&(telm_conf->telem_trace_lock)); 1090 return ret; 1091} 1092 1093static const struct telemetry_core_ops telm_pltops = { 1094 .get_trace_verbosity = telemetry_plt_get_trace_verbosity, 1095 .set_trace_verbosity = telemetry_plt_set_trace_verbosity, 1096 .set_sampling_period = telemetry_plt_set_sampling_period, 1097 .get_sampling_period = telemetry_plt_get_sampling_period, 1098 .raw_read_eventlog = telemetry_plt_raw_read_eventlog, 1099 .get_eventconfig = telemetry_plt_get_eventconfig, 1100 .update_events = telemetry_plt_update_events, 1101 .read_eventlog = telemetry_plt_read_eventlog, 1102 .reset_events = telemetry_plt_reset_events, 1103 .add_events = telemetry_plt_add_events, 1104}; 1105 1106static int telemetry_pltdrv_probe(struct platform_device *pdev) 1107{ 1108 const struct x86_cpu_id *id; 1109 void __iomem *mem; 1110 int ret; 1111 1112 id = x86_match_cpu(telemetry_cpu_ids); 1113 if (!id) 1114 return -ENODEV; 1115 1116 telm_conf = (struct telemetry_plt_config *)id->driver_data; 1117 1118 telm_conf->pmc = dev_get_drvdata(pdev->dev.parent); 1119 1120 mem = devm_platform_ioremap_resource(pdev, 0); 1121 if (IS_ERR(mem)) 1122 return PTR_ERR(mem); 1123 1124 telm_conf->pss_config.regmap = mem; 1125 1126 mem = devm_platform_ioremap_resource(pdev, 1); 1127 if (IS_ERR(mem)) 1128 return PTR_ERR(mem); 1129 1130 telm_conf->ioss_config.regmap = mem; 1131 1132 telm_conf->scu = devm_intel_scu_ipc_dev_get(&pdev->dev); 1133 if (!telm_conf->scu) { 1134 ret = -EPROBE_DEFER; 1135 goto out; 1136 } 1137 1138 mutex_init(&telm_conf->telem_lock); 1139 mutex_init(&telm_conf->telem_trace_lock); 1140 1141 ret = telemetry_setup(pdev); 1142 if (ret) 1143 goto out; 1144 1145 ret = telemetry_set_pltdata(&telm_pltops, telm_conf); 1146 if (ret) { 1147 dev_err(&pdev->dev, "TELEMETRY Set Pltops Failed.\n"); 1148 goto out; 1149 } 1150 1151 return 0; 1152 1153out: 1154 dev_err(&pdev->dev, "TELEMETRY Setup Failed.\n"); 1155 1156 return ret; 1157} 1158 1159static int telemetry_pltdrv_remove(struct platform_device *pdev) 1160{ 1161 telemetry_clear_pltdata(); 1162 return 0; 1163} 1164 1165static struct platform_driver telemetry_soc_driver = { 1166 .probe = telemetry_pltdrv_probe, 1167 .remove = telemetry_pltdrv_remove, 1168 .driver = { 1169 .name = DRIVER_NAME, 1170 }, 1171}; 1172 1173static int __init telemetry_module_init(void) 1174{ 1175 return platform_driver_register(&telemetry_soc_driver); 1176} 1177 1178static void __exit telemetry_module_exit(void) 1179{ 1180 platform_driver_unregister(&telemetry_soc_driver); 1181} 1182 1183device_initcall(telemetry_module_init); 1184module_exit(telemetry_module_exit); 1185 1186MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>"); 1187MODULE_DESCRIPTION("Intel SoC Telemetry Platform Driver"); 1188MODULE_VERSION(DRIVER_VERSION); 1189MODULE_LICENSE("GPL v2");