1189 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Intel SOC Telemetry Platform Driver: Currently supports APL4 * 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 0x325 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 0xD32 33#define TELEM_MAX_EVENTS_SRAM 2834#define TELEM_SSRAM_STARTTIME_OFFSET 835#define TELEM_SSRAM_EVTLOG_OFFSET 1636 37#define IOSS_TELEM 0xeb38#define IOSS_TELEM_EVENT_READ 0x039#define IOSS_TELEM_EVENT_WRITE 0x140#define IOSS_TELEM_INFO_READ 0x241#define IOSS_TELEM_TRACE_CTL_READ 0x542#define IOSS_TELEM_TRACE_CTL_WRITE 0x643#define IOSS_TELEM_EVENT_CTL_READ 0x744#define IOSS_TELEM_EVENT_CTL_WRITE 0x845#define IOSS_TELEM_EVT_WRITE_SIZE 0x346 47#define TELEM_INFO_SRAMEVTS_MASK 0xFF0048#define TELEM_INFO_SRAMEVTS_SHIFT 0x849#define TELEM_SSRAM_READ_TIMEOUT 1050 51#define TELEM_INFO_NENABLES_MASK 0xFF52#define TELEM_EVENT_ENABLE 0x800053 54#define TELEM_MASK_BIT 155#define TELEM_MASK_BYTE 0xFF56#define BYTES_PER_LONG 857#define TELEM_MASK_PCS_STATE 0xF58 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_NONE72};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 driver85 */86static struct telemetry_evtmap87 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_evtmap112 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_evtmap136 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_VFM(INTEL_ATOM_GOLDMONT, &telem_apl_config),181 X86_MATCH_VFM(INTEL_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 else195 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 else566 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 else954 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 void telemetry_pltdrv_remove(struct platform_device *pdev)1160{1161 telemetry_clear_pltdata();1162}1163 1164static struct platform_driver telemetry_soc_driver = {1165 .probe = telemetry_pltdrv_probe,1166 .remove_new = telemetry_pltdrv_remove,1167 .driver = {1168 .name = DRIVER_NAME,1169 },1170};1171 1172static int __init telemetry_module_init(void)1173{1174 return platform_driver_register(&telemetry_soc_driver);1175}1176 1177static void __exit telemetry_module_exit(void)1178{1179 platform_driver_unregister(&telemetry_soc_driver);1180}1181 1182device_initcall(telemetry_module_init);1183module_exit(telemetry_module_exit);1184 1185MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>");1186MODULE_DESCRIPTION("Intel SoC Telemetry Platform Driver");1187MODULE_VERSION(DRIVER_VERSION);1188MODULE_LICENSE("GPL v2");1189