gpio: rcar: Fix runtime PM imbalance on error
[linux/fpc-iii.git] / drivers / platform / x86 / intel_telemetry_pltdrv.c
blob987a24e3344e920413437436e7e0a26080ce3053
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.
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.
12 #include <linux/io.h>
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
16 #include <asm/cpu_device_id.h>
17 #include <asm/intel-family.h>
18 #include <asm/intel_pmc_ipc.h>
19 #include <asm/intel_punit_ipc.h>
20 #include <asm/intel_telemetry.h>
22 #define DRIVER_NAME "intel_telemetry"
23 #define DRIVER_VERSION "1.0.0"
25 #define TELEM_TRC_VERBOSITY_MASK 0x3
27 #define TELEM_MIN_PERIOD(x) ((x) & 0x7F0000)
28 #define TELEM_MAX_PERIOD(x) ((x) & 0x7F000000)
29 #define TELEM_SAMPLE_PERIOD_INVALID(x) ((x) & (BIT(7)))
30 #define TELEM_CLEAR_SAMPLE_PERIOD(x) ((x) &= ~0x7F)
32 #define TELEM_SAMPLING_DEFAULT_PERIOD 0xD
34 #define TELEM_MAX_EVENTS_SRAM 28
35 #define TELEM_SSRAM_STARTTIME_OFFSET 8
36 #define TELEM_SSRAM_EVTLOG_OFFSET 16
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_CTRL_WRITE_SIZE 0x4
46 #define IOSS_TELEM_READ_WORD 0x1
47 #define IOSS_TELEM_WRITE_FOURBYTES 0x4
48 #define IOSS_TELEM_EVT_WRITE_SIZE 0x3
50 #define TELEM_INFO_SRAMEVTS_MASK 0xFF00
51 #define TELEM_INFO_SRAMEVTS_SHIFT 0x8
52 #define TELEM_SSRAM_READ_TIMEOUT 10
54 #define TELEM_INFO_NENABLES_MASK 0xFF
55 #define TELEM_EVENT_ENABLE 0x8000
57 #define TELEM_MASK_BIT 1
58 #define TELEM_MASK_BYTE 0xFF
59 #define BYTES_PER_LONG 8
60 #define TELEM_MASK_PCS_STATE 0xF
62 #define TELEM_DISABLE(x) ((x) &= ~(BIT(31)))
63 #define TELEM_CLEAR_EVENTS(x) ((x) |= (BIT(30)))
64 #define TELEM_ENABLE_SRAM_EVT_TRACE(x) ((x) &= ~(BIT(30) | BIT(24)))
65 #define TELEM_ENABLE_PERIODIC(x) ((x) |= (BIT(23) | BIT(31) | BIT(7)))
66 #define TELEM_EXTRACT_VERBOSITY(x, y) ((y) = (((x) >> 27) & 0x3))
67 #define TELEM_CLEAR_VERBOSITY_BITS(x) ((x) &= ~(BIT(27) | BIT(28)))
68 #define TELEM_SET_VERBOSITY_BITS(x, y) ((x) |= ((y) << 27))
70 enum telemetry_action {
71 TELEM_UPDATE = 0,
72 TELEM_ADD,
73 TELEM_RESET,
74 TELEM_ACTION_NONE
77 struct telem_ssram_region {
78 u64 timestamp;
79 u64 start_time;
80 u64 events[TELEM_MAX_EVENTS_SRAM];
83 static struct telemetry_plt_config *telm_conf;
86 * The following counters are programmed by default during setup.
87 * Only 20 allocated to kernel driver
89 static struct telemetry_evtmap
90 telemetry_apl_ioss_default_events[TELEM_MAX_OS_ALLOCATED_EVENTS] = {
91 {"SOC_S0IX_TOTAL_RES", 0x4800},
92 {"SOC_S0IX_TOTAL_OCC", 0x4000},
93 {"SOC_S0IX_SHALLOW_RES", 0x4801},
94 {"SOC_S0IX_SHALLOW_OCC", 0x4001},
95 {"SOC_S0IX_DEEP_RES", 0x4802},
96 {"SOC_S0IX_DEEP_OCC", 0x4002},
97 {"PMC_POWER_GATE", 0x5818},
98 {"PMC_D3_STATES", 0x5819},
99 {"PMC_D0I3_STATES", 0x581A},
100 {"PMC_S0IX_WAKE_REASON_GPIO", 0x6000},
101 {"PMC_S0IX_WAKE_REASON_TIMER", 0x6001},
102 {"PMC_S0IX_WAKE_REASON_VNNREQ", 0x6002},
103 {"PMC_S0IX_WAKE_REASON_LOWPOWER", 0x6003},
104 {"PMC_S0IX_WAKE_REASON_EXTERNAL", 0x6004},
105 {"PMC_S0IX_WAKE_REASON_MISC", 0x6005},
106 {"PMC_S0IX_BLOCKING_IPS_D3_D0I3", 0x6006},
107 {"PMC_S0IX_BLOCKING_IPS_PG", 0x6007},
108 {"PMC_S0IX_BLOCKING_MISC_IPS_PG", 0x6008},
109 {"PMC_S0IX_BLOCK_IPS_VNN_REQ", 0x6009},
110 {"PMC_S0IX_BLOCK_IPS_CLOCKS", 0x600B},
114 static struct telemetry_evtmap
115 telemetry_apl_pss_default_events[TELEM_MAX_OS_ALLOCATED_EVENTS] = {
116 {"IA_CORE0_C6_RES", 0x0400},
117 {"IA_CORE0_C6_CTR", 0x0000},
118 {"IA_MODULE0_C7_RES", 0x0410},
119 {"IA_MODULE0_C7_CTR", 0x000E},
120 {"IA_C0_RES", 0x0805},
121 {"PCS_LTR", 0x2801},
122 {"PSTATES", 0x2802},
123 {"SOC_S0I3_RES", 0x0409},
124 {"SOC_S0I3_CTR", 0x000A},
125 {"PCS_S0I3_CTR", 0x0009},
126 {"PCS_C1E_RES", 0x041A},
127 {"PCS_IDLE_STATUS", 0x2806},
128 {"IA_PERF_LIMITS", 0x280B},
129 {"GT_PERF_LIMITS", 0x280C},
130 {"PCS_WAKEUP_S0IX_CTR", 0x0030},
131 {"PCS_IDLE_BLOCKED", 0x2C00},
132 {"PCS_S0IX_BLOCKED", 0x2C01},
133 {"PCS_S0IX_WAKE_REASONS", 0x2C02},
134 {"PCS_LTR_BLOCKING", 0x2C03},
135 {"PC2_AND_MEM_SHALLOW_IDLE_RES", 0x1D40},
138 static struct telemetry_evtmap
139 telemetry_glk_pss_default_events[TELEM_MAX_OS_ALLOCATED_EVENTS] = {
140 {"IA_CORE0_C6_RES", 0x0400},
141 {"IA_CORE0_C6_CTR", 0x0000},
142 {"IA_MODULE0_C7_RES", 0x0410},
143 {"IA_MODULE0_C7_CTR", 0x000C},
144 {"IA_C0_RES", 0x0805},
145 {"PCS_LTR", 0x2801},
146 {"PSTATES", 0x2802},
147 {"SOC_S0I3_RES", 0x0407},
148 {"SOC_S0I3_CTR", 0x0008},
149 {"PCS_S0I3_CTR", 0x0007},
150 {"PCS_C1E_RES", 0x0414},
151 {"PCS_IDLE_STATUS", 0x2806},
152 {"IA_PERF_LIMITS", 0x280B},
153 {"GT_PERF_LIMITS", 0x280C},
154 {"PCS_WAKEUP_S0IX_CTR", 0x0025},
155 {"PCS_IDLE_BLOCKED", 0x2C00},
156 {"PCS_S0IX_BLOCKED", 0x2C01},
157 {"PCS_S0IX_WAKE_REASONS", 0x2C02},
158 {"PCS_LTR_BLOCKING", 0x2C03},
159 {"PC2_AND_MEM_SHALLOW_IDLE_RES", 0x1D40},
162 /* APL specific Data */
163 static struct telemetry_plt_config telem_apl_config = {
164 .pss_config = {
165 .telem_evts = telemetry_apl_pss_default_events,
167 .ioss_config = {
168 .telem_evts = telemetry_apl_ioss_default_events,
172 /* GLK specific Data */
173 static struct telemetry_plt_config telem_glk_config = {
174 .pss_config = {
175 .telem_evts = telemetry_glk_pss_default_events,
177 .ioss_config = {
178 .telem_evts = telemetry_apl_ioss_default_events,
182 static const struct x86_cpu_id telemetry_cpu_ids[] = {
183 X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, &telem_apl_config),
184 X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_PLUS, &telem_glk_config),
188 MODULE_DEVICE_TABLE(x86cpu, telemetry_cpu_ids);
190 static inline int telem_get_unitconfig(enum telemetry_unit telem_unit,
191 struct telemetry_unit_config **unit_config)
193 if (telem_unit == TELEM_PSS)
194 *unit_config = &(telm_conf->pss_config);
195 else if (telem_unit == TELEM_IOSS)
196 *unit_config = &(telm_conf->ioss_config);
197 else
198 return -EINVAL;
200 return 0;
204 static int telemetry_check_evtid(enum telemetry_unit telem_unit,
205 u32 *evtmap, u8 len,
206 enum telemetry_action action)
208 struct telemetry_unit_config *unit_config;
209 int ret;
211 ret = telem_get_unitconfig(telem_unit, &unit_config);
212 if (ret < 0)
213 return ret;
215 switch (action) {
216 case TELEM_RESET:
217 if (len > TELEM_MAX_EVENTS_SRAM)
218 return -EINVAL;
220 break;
222 case TELEM_UPDATE:
223 if (len > TELEM_MAX_EVENTS_SRAM)
224 return -EINVAL;
226 if ((len > 0) && (evtmap == NULL))
227 return -EINVAL;
229 break;
231 case TELEM_ADD:
232 if ((len + unit_config->ssram_evts_used) >
233 TELEM_MAX_EVENTS_SRAM)
234 return -EINVAL;
236 if ((len > 0) && (evtmap == NULL))
237 return -EINVAL;
239 break;
241 default:
242 pr_err("Unknown Telemetry action specified %d\n", action);
243 return -EINVAL;
246 return 0;
250 static inline int telemetry_plt_config_ioss_event(u32 evt_id, int index)
252 u32 write_buf;
253 int ret;
255 write_buf = evt_id | TELEM_EVENT_ENABLE;
256 write_buf <<= BITS_PER_BYTE;
257 write_buf |= index;
259 ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
260 IOSS_TELEM_EVENT_WRITE, (u8 *)&write_buf,
261 IOSS_TELEM_EVT_WRITE_SIZE, NULL, 0);
263 return ret;
266 static inline int telemetry_plt_config_pss_event(u32 evt_id, int index)
268 u32 write_buf;
269 int ret;
271 write_buf = evt_id | TELEM_EVENT_ENABLE;
272 ret = intel_punit_ipc_command(IPC_PUNIT_BIOS_WRITE_TELE_EVENT,
273 index, 0, &write_buf, NULL);
275 return ret;
278 static int telemetry_setup_iossevtconfig(struct telemetry_evtconfig evtconfig,
279 enum telemetry_action action)
281 u8 num_ioss_evts, ioss_period;
282 int ret, index, idx;
283 u32 *ioss_evtmap;
284 u32 telem_ctrl;
286 num_ioss_evts = evtconfig.num_evts;
287 ioss_period = evtconfig.period;
288 ioss_evtmap = evtconfig.evtmap;
290 /* Get telemetry EVENT CTL */
291 ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
292 IOSS_TELEM_EVENT_CTL_READ, NULL, 0,
293 &telem_ctrl, IOSS_TELEM_READ_WORD);
294 if (ret) {
295 pr_err("IOSS TELEM_CTRL Read Failed\n");
296 return ret;
299 /* Disable Telemetry */
300 TELEM_DISABLE(telem_ctrl);
302 ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
303 IOSS_TELEM_EVENT_CTL_WRITE,
304 (u8 *)&telem_ctrl,
305 IOSS_TELEM_EVT_CTRL_WRITE_SIZE,
306 NULL, 0);
307 if (ret) {
308 pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n");
309 return ret;
313 /* Reset Everything */
314 if (action == TELEM_RESET) {
315 /* Clear All Events */
316 TELEM_CLEAR_EVENTS(telem_ctrl);
318 ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
319 IOSS_TELEM_EVENT_CTL_WRITE,
320 (u8 *)&telem_ctrl,
321 IOSS_TELEM_EVT_CTRL_WRITE_SIZE,
322 NULL, 0);
323 if (ret) {
324 pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n");
325 return ret;
327 telm_conf->ioss_config.ssram_evts_used = 0;
329 /* Configure Events */
330 for (idx = 0; idx < num_ioss_evts; idx++) {
331 if (telemetry_plt_config_ioss_event(
332 telm_conf->ioss_config.telem_evts[idx].evt_id,
333 idx)) {
334 pr_err("IOSS TELEM_RESET Fail for data: %x\n",
335 telm_conf->ioss_config.telem_evts[idx].evt_id);
336 continue;
338 telm_conf->ioss_config.ssram_evts_used++;
342 /* Re-Configure Everything */
343 if (action == TELEM_UPDATE) {
344 /* Clear All Events */
345 TELEM_CLEAR_EVENTS(telem_ctrl);
347 ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
348 IOSS_TELEM_EVENT_CTL_WRITE,
349 (u8 *)&telem_ctrl,
350 IOSS_TELEM_EVT_CTRL_WRITE_SIZE,
351 NULL, 0);
352 if (ret) {
353 pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n");
354 return ret;
356 telm_conf->ioss_config.ssram_evts_used = 0;
358 /* Configure Events */
359 for (index = 0; index < num_ioss_evts; index++) {
360 telm_conf->ioss_config.telem_evts[index].evt_id =
361 ioss_evtmap[index];
363 if (telemetry_plt_config_ioss_event(
364 telm_conf->ioss_config.telem_evts[index].evt_id,
365 index)) {
366 pr_err("IOSS TELEM_UPDATE Fail for Evt%x\n",
367 ioss_evtmap[index]);
368 continue;
370 telm_conf->ioss_config.ssram_evts_used++;
374 /* Add some Events */
375 if (action == TELEM_ADD) {
376 /* Configure Events */
377 for (index = telm_conf->ioss_config.ssram_evts_used, idx = 0;
378 idx < num_ioss_evts; index++, idx++) {
379 telm_conf->ioss_config.telem_evts[index].evt_id =
380 ioss_evtmap[idx];
382 if (telemetry_plt_config_ioss_event(
383 telm_conf->ioss_config.telem_evts[index].evt_id,
384 index)) {
385 pr_err("IOSS TELEM_ADD Fail for Event %x\n",
386 ioss_evtmap[idx]);
387 continue;
389 telm_conf->ioss_config.ssram_evts_used++;
393 /* Enable Periodic Telemetry Events and enable SRAM trace */
394 TELEM_CLEAR_SAMPLE_PERIOD(telem_ctrl);
395 TELEM_ENABLE_SRAM_EVT_TRACE(telem_ctrl);
396 TELEM_ENABLE_PERIODIC(telem_ctrl);
397 telem_ctrl |= ioss_period;
399 ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
400 IOSS_TELEM_EVENT_CTL_WRITE,
401 (u8 *)&telem_ctrl,
402 IOSS_TELEM_EVT_CTRL_WRITE_SIZE, NULL, 0);
403 if (ret) {
404 pr_err("IOSS TELEM_CTRL Event Enable Write Failed\n");
405 return ret;
408 telm_conf->ioss_config.curr_period = ioss_period;
410 return 0;
414 static int telemetry_setup_pssevtconfig(struct telemetry_evtconfig evtconfig,
415 enum telemetry_action action)
417 u8 num_pss_evts, pss_period;
418 int ret, index, idx;
419 u32 *pss_evtmap;
420 u32 telem_ctrl;
422 num_pss_evts = evtconfig.num_evts;
423 pss_period = evtconfig.period;
424 pss_evtmap = evtconfig.evtmap;
426 /* PSS Config */
427 /* Get telemetry EVENT CTL */
428 ret = intel_punit_ipc_command(IPC_PUNIT_BIOS_READ_TELE_EVENT_CTRL,
429 0, 0, NULL, &telem_ctrl);
430 if (ret) {
431 pr_err("PSS TELEM_CTRL Read Failed\n");
432 return ret;
435 /* Disable Telemetry */
436 TELEM_DISABLE(telem_ctrl);
437 ret = intel_punit_ipc_command(IPC_PUNIT_BIOS_WRITE_TELE_EVENT_CTRL,
438 0, 0, &telem_ctrl, NULL);
439 if (ret) {
440 pr_err("PSS TELEM_CTRL Event Disable Write Failed\n");
441 return ret;
444 /* Reset Everything */
445 if (action == TELEM_RESET) {
446 /* Clear All Events */
447 TELEM_CLEAR_EVENTS(telem_ctrl);
449 ret = intel_punit_ipc_command(
450 IPC_PUNIT_BIOS_WRITE_TELE_EVENT_CTRL,
451 0, 0, &telem_ctrl, NULL);
452 if (ret) {
453 pr_err("PSS TELEM_CTRL Event Disable Write Failed\n");
454 return ret;
456 telm_conf->pss_config.ssram_evts_used = 0;
457 /* Configure Events */
458 for (idx = 0; idx < num_pss_evts; idx++) {
459 if (telemetry_plt_config_pss_event(
460 telm_conf->pss_config.telem_evts[idx].evt_id,
461 idx)) {
462 pr_err("PSS TELEM_RESET Fail for Event %x\n",
463 telm_conf->pss_config.telem_evts[idx].evt_id);
464 continue;
466 telm_conf->pss_config.ssram_evts_used++;
470 /* Re-Configure Everything */
471 if (action == TELEM_UPDATE) {
472 /* Clear All Events */
473 TELEM_CLEAR_EVENTS(telem_ctrl);
475 ret = intel_punit_ipc_command(
476 IPC_PUNIT_BIOS_WRITE_TELE_EVENT_CTRL,
477 0, 0, &telem_ctrl, NULL);
478 if (ret) {
479 pr_err("PSS TELEM_CTRL Event Disable Write Failed\n");
480 return ret;
482 telm_conf->pss_config.ssram_evts_used = 0;
484 /* Configure Events */
485 for (index = 0; index < num_pss_evts; index++) {
486 telm_conf->pss_config.telem_evts[index].evt_id =
487 pss_evtmap[index];
489 if (telemetry_plt_config_pss_event(
490 telm_conf->pss_config.telem_evts[index].evt_id,
491 index)) {
492 pr_err("PSS TELEM_UPDATE Fail for Event %x\n",
493 pss_evtmap[index]);
494 continue;
496 telm_conf->pss_config.ssram_evts_used++;
500 /* Add some Events */
501 if (action == TELEM_ADD) {
502 /* Configure Events */
503 for (index = telm_conf->pss_config.ssram_evts_used, idx = 0;
504 idx < num_pss_evts; index++, idx++) {
506 telm_conf->pss_config.telem_evts[index].evt_id =
507 pss_evtmap[idx];
509 if (telemetry_plt_config_pss_event(
510 telm_conf->pss_config.telem_evts[index].evt_id,
511 index)) {
512 pr_err("PSS TELEM_ADD Fail for Event %x\n",
513 pss_evtmap[idx]);
514 continue;
516 telm_conf->pss_config.ssram_evts_used++;
520 /* Enable Periodic Telemetry Events and enable SRAM trace */
521 TELEM_CLEAR_SAMPLE_PERIOD(telem_ctrl);
522 TELEM_ENABLE_SRAM_EVT_TRACE(telem_ctrl);
523 TELEM_ENABLE_PERIODIC(telem_ctrl);
524 telem_ctrl |= pss_period;
526 ret = intel_punit_ipc_command(IPC_PUNIT_BIOS_WRITE_TELE_EVENT_CTRL,
527 0, 0, &telem_ctrl, NULL);
528 if (ret) {
529 pr_err("PSS TELEM_CTRL Event Enable Write Failed\n");
530 return ret;
533 telm_conf->pss_config.curr_period = pss_period;
535 return 0;
538 static int telemetry_setup_evtconfig(struct telemetry_evtconfig pss_evtconfig,
539 struct telemetry_evtconfig ioss_evtconfig,
540 enum telemetry_action action)
542 int ret;
544 mutex_lock(&(telm_conf->telem_lock));
546 if ((action == TELEM_UPDATE) && (telm_conf->telem_in_use)) {
547 ret = -EBUSY;
548 goto out;
551 ret = telemetry_check_evtid(TELEM_PSS, pss_evtconfig.evtmap,
552 pss_evtconfig.num_evts, action);
553 if (ret)
554 goto out;
556 ret = telemetry_check_evtid(TELEM_IOSS, ioss_evtconfig.evtmap,
557 ioss_evtconfig.num_evts, action);
558 if (ret)
559 goto out;
561 if (ioss_evtconfig.num_evts) {
562 ret = telemetry_setup_iossevtconfig(ioss_evtconfig, action);
563 if (ret)
564 goto out;
567 if (pss_evtconfig.num_evts) {
568 ret = telemetry_setup_pssevtconfig(pss_evtconfig, action);
569 if (ret)
570 goto out;
573 if ((action == TELEM_UPDATE) || (action == TELEM_ADD))
574 telm_conf->telem_in_use = true;
575 else
576 telm_conf->telem_in_use = false;
578 out:
579 mutex_unlock(&(telm_conf->telem_lock));
580 return ret;
583 static int telemetry_setup(struct platform_device *pdev)
585 struct telemetry_evtconfig pss_evtconfig, ioss_evtconfig;
586 u32 read_buf, events, event_regs;
587 int ret;
589 ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY, IOSS_TELEM_INFO_READ,
590 NULL, 0, &read_buf, IOSS_TELEM_READ_WORD);
591 if (ret) {
592 dev_err(&pdev->dev, "IOSS TELEM_INFO Read Failed\n");
593 return ret;
596 /* Get telemetry Info */
597 events = (read_buf & TELEM_INFO_SRAMEVTS_MASK) >>
598 TELEM_INFO_SRAMEVTS_SHIFT;
599 event_regs = read_buf & TELEM_INFO_NENABLES_MASK;
600 if ((events < TELEM_MAX_EVENTS_SRAM) ||
601 (event_regs < TELEM_MAX_EVENTS_SRAM)) {
602 dev_err(&pdev->dev, "IOSS:Insufficient Space for SRAM Trace\n");
603 dev_err(&pdev->dev, "SRAM Events %d; Event Regs %d\n",
604 events, event_regs);
605 return -ENOMEM;
608 telm_conf->ioss_config.min_period = TELEM_MIN_PERIOD(read_buf);
609 telm_conf->ioss_config.max_period = TELEM_MAX_PERIOD(read_buf);
611 /* PUNIT Mailbox Setup */
612 ret = intel_punit_ipc_command(IPC_PUNIT_BIOS_READ_TELE_INFO, 0, 0,
613 NULL, &read_buf);
614 if (ret) {
615 dev_err(&pdev->dev, "PSS TELEM_INFO Read Failed\n");
616 return ret;
619 /* Get telemetry Info */
620 events = (read_buf & TELEM_INFO_SRAMEVTS_MASK) >>
621 TELEM_INFO_SRAMEVTS_SHIFT;
622 event_regs = read_buf & TELEM_INFO_SRAMEVTS_MASK;
623 if ((events < TELEM_MAX_EVENTS_SRAM) ||
624 (event_regs < TELEM_MAX_EVENTS_SRAM)) {
625 dev_err(&pdev->dev, "PSS:Insufficient Space for SRAM Trace\n");
626 dev_err(&pdev->dev, "SRAM Events %d; Event Regs %d\n",
627 events, event_regs);
628 return -ENOMEM;
631 telm_conf->pss_config.min_period = TELEM_MIN_PERIOD(read_buf);
632 telm_conf->pss_config.max_period = TELEM_MAX_PERIOD(read_buf);
634 pss_evtconfig.evtmap = NULL;
635 pss_evtconfig.num_evts = TELEM_MAX_OS_ALLOCATED_EVENTS;
636 pss_evtconfig.period = TELEM_SAMPLING_DEFAULT_PERIOD;
638 ioss_evtconfig.evtmap = NULL;
639 ioss_evtconfig.num_evts = TELEM_MAX_OS_ALLOCATED_EVENTS;
640 ioss_evtconfig.period = TELEM_SAMPLING_DEFAULT_PERIOD;
642 ret = telemetry_setup_evtconfig(pss_evtconfig, ioss_evtconfig,
643 TELEM_RESET);
644 if (ret) {
645 dev_err(&pdev->dev, "TELEMETRY Setup Failed\n");
646 return ret;
648 return 0;
651 static int telemetry_plt_update_events(struct telemetry_evtconfig pss_evtconfig,
652 struct telemetry_evtconfig ioss_evtconfig)
654 int ret;
656 if ((pss_evtconfig.num_evts > 0) &&
657 (TELEM_SAMPLE_PERIOD_INVALID(pss_evtconfig.period))) {
658 pr_err("PSS Sampling Period Out of Range\n");
659 return -EINVAL;
662 if ((ioss_evtconfig.num_evts > 0) &&
663 (TELEM_SAMPLE_PERIOD_INVALID(ioss_evtconfig.period))) {
664 pr_err("IOSS Sampling Period Out of Range\n");
665 return -EINVAL;
668 ret = telemetry_setup_evtconfig(pss_evtconfig, ioss_evtconfig,
669 TELEM_UPDATE);
670 if (ret)
671 pr_err("TELEMETRY Config Failed\n");
673 return ret;
677 static int telemetry_plt_set_sampling_period(u8 pss_period, u8 ioss_period)
679 u32 telem_ctrl = 0;
680 int ret = 0;
682 mutex_lock(&(telm_conf->telem_lock));
683 if (ioss_period) {
684 if (TELEM_SAMPLE_PERIOD_INVALID(ioss_period)) {
685 pr_err("IOSS Sampling Period Out of Range\n");
686 ret = -EINVAL;
687 goto out;
690 /* Get telemetry EVENT CTL */
691 ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
692 IOSS_TELEM_EVENT_CTL_READ, NULL, 0,
693 &telem_ctrl, IOSS_TELEM_READ_WORD);
694 if (ret) {
695 pr_err("IOSS TELEM_CTRL Read Failed\n");
696 goto out;
699 /* Disable Telemetry */
700 TELEM_DISABLE(telem_ctrl);
702 ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
703 IOSS_TELEM_EVENT_CTL_WRITE,
704 (u8 *)&telem_ctrl,
705 IOSS_TELEM_EVT_CTRL_WRITE_SIZE,
706 NULL, 0);
707 if (ret) {
708 pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n");
709 goto out;
712 /* Enable Periodic Telemetry Events and enable SRAM trace */
713 TELEM_CLEAR_SAMPLE_PERIOD(telem_ctrl);
714 TELEM_ENABLE_SRAM_EVT_TRACE(telem_ctrl);
715 TELEM_ENABLE_PERIODIC(telem_ctrl);
716 telem_ctrl |= ioss_period;
718 ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
719 IOSS_TELEM_EVENT_CTL_WRITE,
720 (u8 *)&telem_ctrl,
721 IOSS_TELEM_EVT_CTRL_WRITE_SIZE,
722 NULL, 0);
723 if (ret) {
724 pr_err("IOSS TELEM_CTRL Event Enable Write Failed\n");
725 goto out;
727 telm_conf->ioss_config.curr_period = ioss_period;
730 if (pss_period) {
731 if (TELEM_SAMPLE_PERIOD_INVALID(pss_period)) {
732 pr_err("PSS Sampling Period Out of Range\n");
733 ret = -EINVAL;
734 goto out;
737 /* Get telemetry EVENT CTL */
738 ret = intel_punit_ipc_command(
739 IPC_PUNIT_BIOS_READ_TELE_EVENT_CTRL,
740 0, 0, NULL, &telem_ctrl);
741 if (ret) {
742 pr_err("PSS TELEM_CTRL Read Failed\n");
743 goto out;
746 /* Disable Telemetry */
747 TELEM_DISABLE(telem_ctrl);
748 ret = intel_punit_ipc_command(
749 IPC_PUNIT_BIOS_WRITE_TELE_EVENT_CTRL,
750 0, 0, &telem_ctrl, NULL);
751 if (ret) {
752 pr_err("PSS TELEM_CTRL Event Disable Write Failed\n");
753 goto out;
756 /* Enable Periodic Telemetry Events and enable SRAM trace */
757 TELEM_CLEAR_SAMPLE_PERIOD(telem_ctrl);
758 TELEM_ENABLE_SRAM_EVT_TRACE(telem_ctrl);
759 TELEM_ENABLE_PERIODIC(telem_ctrl);
760 telem_ctrl |= pss_period;
762 ret = intel_punit_ipc_command(
763 IPC_PUNIT_BIOS_WRITE_TELE_EVENT_CTRL,
764 0, 0, &telem_ctrl, NULL);
765 if (ret) {
766 pr_err("PSS TELEM_CTRL Event Enable Write Failed\n");
767 goto out;
769 telm_conf->pss_config.curr_period = pss_period;
772 out:
773 mutex_unlock(&(telm_conf->telem_lock));
774 return ret;
778 static int telemetry_plt_get_sampling_period(u8 *pss_min_period,
779 u8 *pss_max_period,
780 u8 *ioss_min_period,
781 u8 *ioss_max_period)
783 *pss_min_period = telm_conf->pss_config.min_period;
784 *pss_max_period = telm_conf->pss_config.max_period;
785 *ioss_min_period = telm_conf->ioss_config.min_period;
786 *ioss_max_period = telm_conf->ioss_config.max_period;
788 return 0;
792 static int telemetry_plt_reset_events(void)
794 struct telemetry_evtconfig pss_evtconfig, ioss_evtconfig;
795 int ret;
797 pss_evtconfig.evtmap = NULL;
798 pss_evtconfig.num_evts = TELEM_MAX_OS_ALLOCATED_EVENTS;
799 pss_evtconfig.period = TELEM_SAMPLING_DEFAULT_PERIOD;
801 ioss_evtconfig.evtmap = NULL;
802 ioss_evtconfig.num_evts = TELEM_MAX_OS_ALLOCATED_EVENTS;
803 ioss_evtconfig.period = TELEM_SAMPLING_DEFAULT_PERIOD;
805 ret = telemetry_setup_evtconfig(pss_evtconfig, ioss_evtconfig,
806 TELEM_RESET);
807 if (ret)
808 pr_err("TELEMETRY Reset Failed\n");
810 return ret;
814 static int telemetry_plt_get_eventconfig(struct telemetry_evtconfig *pss_config,
815 struct telemetry_evtconfig *ioss_config,
816 int pss_len, int ioss_len)
818 u32 *pss_evtmap, *ioss_evtmap;
819 u32 index;
821 pss_evtmap = pss_config->evtmap;
822 ioss_evtmap = ioss_config->evtmap;
824 mutex_lock(&(telm_conf->telem_lock));
825 pss_config->num_evts = telm_conf->pss_config.ssram_evts_used;
826 ioss_config->num_evts = telm_conf->ioss_config.ssram_evts_used;
828 pss_config->period = telm_conf->pss_config.curr_period;
829 ioss_config->period = telm_conf->ioss_config.curr_period;
831 if ((pss_len < telm_conf->pss_config.ssram_evts_used) ||
832 (ioss_len < telm_conf->ioss_config.ssram_evts_used)) {
833 mutex_unlock(&(telm_conf->telem_lock));
834 return -EINVAL;
837 for (index = 0; index < telm_conf->pss_config.ssram_evts_used;
838 index++) {
839 pss_evtmap[index] =
840 telm_conf->pss_config.telem_evts[index].evt_id;
843 for (index = 0; index < telm_conf->ioss_config.ssram_evts_used;
844 index++) {
845 ioss_evtmap[index] =
846 telm_conf->ioss_config.telem_evts[index].evt_id;
849 mutex_unlock(&(telm_conf->telem_lock));
850 return 0;
854 static int telemetry_plt_add_events(u8 num_pss_evts, u8 num_ioss_evts,
855 u32 *pss_evtmap, u32 *ioss_evtmap)
857 struct telemetry_evtconfig pss_evtconfig, ioss_evtconfig;
858 int ret;
860 pss_evtconfig.evtmap = pss_evtmap;
861 pss_evtconfig.num_evts = num_pss_evts;
862 pss_evtconfig.period = telm_conf->pss_config.curr_period;
864 ioss_evtconfig.evtmap = ioss_evtmap;
865 ioss_evtconfig.num_evts = num_ioss_evts;
866 ioss_evtconfig.period = telm_conf->ioss_config.curr_period;
868 ret = telemetry_setup_evtconfig(pss_evtconfig, ioss_evtconfig,
869 TELEM_ADD);
870 if (ret)
871 pr_err("TELEMETRY ADD Failed\n");
873 return ret;
876 static int telem_evtlog_read(enum telemetry_unit telem_unit,
877 struct telem_ssram_region *ssram_region, u8 len)
879 struct telemetry_unit_config *unit_config;
880 u64 timestamp_prev, timestamp_next;
881 int ret, index, timeout = 0;
883 ret = telem_get_unitconfig(telem_unit, &unit_config);
884 if (ret < 0)
885 return ret;
887 if (len > unit_config->ssram_evts_used)
888 len = unit_config->ssram_evts_used;
890 do {
891 timestamp_prev = readq(unit_config->regmap);
892 if (!timestamp_prev) {
893 pr_err("Ssram under update. Please Try Later\n");
894 return -EBUSY;
897 ssram_region->start_time = readq(unit_config->regmap +
898 TELEM_SSRAM_STARTTIME_OFFSET);
900 for (index = 0; index < len; index++) {
901 ssram_region->events[index] =
902 readq(unit_config->regmap + TELEM_SSRAM_EVTLOG_OFFSET +
903 BYTES_PER_LONG*index);
906 timestamp_next = readq(unit_config->regmap);
907 if (!timestamp_next) {
908 pr_err("Ssram under update. Please Try Later\n");
909 return -EBUSY;
912 if (timeout++ > TELEM_SSRAM_READ_TIMEOUT) {
913 pr_err("Timeout while reading Events\n");
914 return -EBUSY;
917 } while (timestamp_prev != timestamp_next);
919 ssram_region->timestamp = timestamp_next;
921 return len;
924 static int telemetry_plt_raw_read_eventlog(enum telemetry_unit telem_unit,
925 struct telemetry_evtlog *evtlog,
926 int len, int log_all_evts)
928 int index, idx1, ret, readlen = len;
929 struct telem_ssram_region ssram_region;
930 struct telemetry_evtmap *evtmap;
932 switch (telem_unit) {
933 case TELEM_PSS:
934 evtmap = telm_conf->pss_config.telem_evts;
935 break;
937 case TELEM_IOSS:
938 evtmap = telm_conf->ioss_config.telem_evts;
939 break;
941 default:
942 pr_err("Unknown Telemetry Unit Specified %d\n", telem_unit);
943 return -EINVAL;
946 if (!log_all_evts)
947 readlen = TELEM_MAX_EVENTS_SRAM;
949 ret = telem_evtlog_read(telem_unit, &ssram_region, readlen);
950 if (ret < 0)
951 return ret;
953 /* Invalid evt-id array specified via length mismatch */
954 if ((!log_all_evts) && (len > ret))
955 return -EINVAL;
957 if (log_all_evts)
958 for (index = 0; index < ret; index++) {
959 evtlog[index].telem_evtlog = ssram_region.events[index];
960 evtlog[index].telem_evtid = evtmap[index].evt_id;
962 else
963 for (index = 0, readlen = 0; (index < ret) && (readlen < len);
964 index++) {
965 for (idx1 = 0; idx1 < len; idx1++) {
966 /* Elements matched */
967 if (evtmap[index].evt_id ==
968 evtlog[idx1].telem_evtid) {
969 evtlog[idx1].telem_evtlog =
970 ssram_region.events[index];
971 readlen++;
973 break;
978 return readlen;
981 static int telemetry_plt_read_eventlog(enum telemetry_unit telem_unit,
982 struct telemetry_evtlog *evtlog, int len, int log_all_evts)
984 int ret;
986 mutex_lock(&(telm_conf->telem_lock));
987 ret = telemetry_plt_raw_read_eventlog(telem_unit, evtlog,
988 len, log_all_evts);
989 mutex_unlock(&(telm_conf->telem_lock));
991 return ret;
994 static int telemetry_plt_get_trace_verbosity(enum telemetry_unit telem_unit,
995 u32 *verbosity)
997 u32 temp = 0;
998 int ret;
1000 if (verbosity == NULL)
1001 return -EINVAL;
1003 mutex_lock(&(telm_conf->telem_trace_lock));
1004 switch (telem_unit) {
1005 case TELEM_PSS:
1006 ret = intel_punit_ipc_command(
1007 IPC_PUNIT_BIOS_READ_TELE_TRACE_CTRL,
1008 0, 0, NULL, &temp);
1009 if (ret) {
1010 pr_err("PSS TRACE_CTRL Read Failed\n");
1011 goto out;
1014 break;
1016 case TELEM_IOSS:
1017 ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
1018 IOSS_TELEM_TRACE_CTL_READ, NULL, 0, &temp,
1019 IOSS_TELEM_READ_WORD);
1020 if (ret) {
1021 pr_err("IOSS TRACE_CTL Read Failed\n");
1022 goto out;
1025 break;
1027 default:
1028 pr_err("Unknown Telemetry Unit Specified %d\n", telem_unit);
1029 ret = -EINVAL;
1030 break;
1032 TELEM_EXTRACT_VERBOSITY(temp, *verbosity);
1034 out:
1035 mutex_unlock(&(telm_conf->telem_trace_lock));
1036 return ret;
1039 static int telemetry_plt_set_trace_verbosity(enum telemetry_unit telem_unit,
1040 u32 verbosity)
1042 u32 temp = 0;
1043 int ret;
1045 verbosity &= TELEM_TRC_VERBOSITY_MASK;
1047 mutex_lock(&(telm_conf->telem_trace_lock));
1048 switch (telem_unit) {
1049 case TELEM_PSS:
1050 ret = intel_punit_ipc_command(
1051 IPC_PUNIT_BIOS_READ_TELE_TRACE_CTRL,
1052 0, 0, NULL, &temp);
1053 if (ret) {
1054 pr_err("PSS TRACE_CTRL Read Failed\n");
1055 goto out;
1058 TELEM_CLEAR_VERBOSITY_BITS(temp);
1059 TELEM_SET_VERBOSITY_BITS(temp, verbosity);
1061 ret = intel_punit_ipc_command(
1062 IPC_PUNIT_BIOS_WRITE_TELE_TRACE_CTRL,
1063 0, 0, &temp, NULL);
1064 if (ret) {
1065 pr_err("PSS TRACE_CTRL Verbosity Set Failed\n");
1066 goto out;
1068 break;
1070 case TELEM_IOSS:
1071 ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
1072 IOSS_TELEM_TRACE_CTL_READ, NULL, 0, &temp,
1073 IOSS_TELEM_READ_WORD);
1074 if (ret) {
1075 pr_err("IOSS TRACE_CTL Read Failed\n");
1076 goto out;
1079 TELEM_CLEAR_VERBOSITY_BITS(temp);
1080 TELEM_SET_VERBOSITY_BITS(temp, verbosity);
1082 ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
1083 IOSS_TELEM_TRACE_CTL_WRITE, (u8 *)&temp,
1084 IOSS_TELEM_WRITE_FOURBYTES, NULL, 0);
1085 if (ret) {
1086 pr_err("IOSS TRACE_CTL Verbosity Set Failed\n");
1087 goto out;
1089 break;
1091 default:
1092 pr_err("Unknown Telemetry Unit Specified %d\n", telem_unit);
1093 ret = -EINVAL;
1094 break;
1097 out:
1098 mutex_unlock(&(telm_conf->telem_trace_lock));
1099 return ret;
1102 static const struct telemetry_core_ops telm_pltops = {
1103 .get_trace_verbosity = telemetry_plt_get_trace_verbosity,
1104 .set_trace_verbosity = telemetry_plt_set_trace_verbosity,
1105 .set_sampling_period = telemetry_plt_set_sampling_period,
1106 .get_sampling_period = telemetry_plt_get_sampling_period,
1107 .raw_read_eventlog = telemetry_plt_raw_read_eventlog,
1108 .get_eventconfig = telemetry_plt_get_eventconfig,
1109 .update_events = telemetry_plt_update_events,
1110 .read_eventlog = telemetry_plt_read_eventlog,
1111 .reset_events = telemetry_plt_reset_events,
1112 .add_events = telemetry_plt_add_events,
1115 static int telemetry_pltdrv_probe(struct platform_device *pdev)
1117 const struct x86_cpu_id *id;
1118 void __iomem *mem;
1119 int ret;
1121 id = x86_match_cpu(telemetry_cpu_ids);
1122 if (!id)
1123 return -ENODEV;
1125 telm_conf = (struct telemetry_plt_config *)id->driver_data;
1127 mem = devm_platform_ioremap_resource(pdev, 0);
1128 if (IS_ERR(mem))
1129 return PTR_ERR(mem);
1131 telm_conf->pss_config.regmap = mem;
1133 mem = devm_platform_ioremap_resource(pdev, 1);
1134 if (IS_ERR(mem))
1135 return PTR_ERR(mem);
1137 telm_conf->ioss_config.regmap = mem;
1139 mutex_init(&telm_conf->telem_lock);
1140 mutex_init(&telm_conf->telem_trace_lock);
1142 ret = telemetry_setup(pdev);
1143 if (ret)
1144 goto out;
1146 ret = telemetry_set_pltdata(&telm_pltops, telm_conf);
1147 if (ret) {
1148 dev_err(&pdev->dev, "TELEMETRY Set Pltops Failed.\n");
1149 goto out;
1152 return 0;
1154 out:
1155 dev_err(&pdev->dev, "TELEMETRY Setup Failed.\n");
1157 return ret;
1160 static int telemetry_pltdrv_remove(struct platform_device *pdev)
1162 telemetry_clear_pltdata();
1163 return 0;
1166 static struct platform_driver telemetry_soc_driver = {
1167 .probe = telemetry_pltdrv_probe,
1168 .remove = telemetry_pltdrv_remove,
1169 .driver = {
1170 .name = DRIVER_NAME,
1174 static int __init telemetry_module_init(void)
1176 return platform_driver_register(&telemetry_soc_driver);
1179 static void __exit telemetry_module_exit(void)
1181 platform_driver_unregister(&telemetry_soc_driver);
1184 device_initcall(telemetry_module_init);
1185 module_exit(telemetry_module_exit);
1187 MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>");
1188 MODULE_DESCRIPTION("Intel SoC Telemetry Platform Driver");
1189 MODULE_VERSION(DRIVER_VERSION);
1190 MODULE_LICENSE("GPL v2");