]> Git Repo - linux.git/blob - drivers/platform/x86/intel_telemetry_pltdrv.c
Merge tag 'platform-drivers-x86-v5.7-1' of git://git.infradead.org/linux-platform...
[linux.git] / drivers / platform / x86 / intel_telemetry_pltdrv.c
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_pmc_ipc.h>
19 #include <asm/intel_punit_ipc.h>
20 #include <asm/intel_telemetry.h>
21
22 #define DRIVER_NAME     "intel_telemetry"
23 #define DRIVER_VERSION  "1.0.0"
24
25 #define TELEM_TRC_VERBOSITY_MASK        0x3
26
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)
31
32 #define TELEM_SAMPLING_DEFAULT_PERIOD   0xD
33
34 #define TELEM_MAX_EVENTS_SRAM           28
35 #define TELEM_SSRAM_STARTTIME_OFFSET    8
36 #define TELEM_SSRAM_EVTLOG_OFFSET       16
37
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
49
50 #define TELEM_INFO_SRAMEVTS_MASK        0xFF00
51 #define TELEM_INFO_SRAMEVTS_SHIFT       0x8
52 #define TELEM_SSRAM_READ_TIMEOUT        10
53
54 #define TELEM_INFO_NENABLES_MASK        0xFF
55 #define TELEM_EVENT_ENABLE              0x8000
56
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
61
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))
69
70 enum telemetry_action {
71         TELEM_UPDATE = 0,
72         TELEM_ADD,
73         TELEM_RESET,
74         TELEM_ACTION_NONE
75 };
76
77 struct telem_ssram_region {
78         u64 timestamp;
79         u64 start_time;
80         u64 events[TELEM_MAX_EVENTS_SRAM];
81 };
82
83 static struct telemetry_plt_config *telm_conf;
84
85 /*
86  * The following counters are programmed by default during setup.
87  * Only 20 allocated to kernel driver
88  */
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},
111 };
112
113
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},
136 };
137
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},
160 };
161
162 /* APL specific Data */
163 static struct telemetry_plt_config telem_apl_config = {
164         .pss_config = {
165                 .telem_evts = telemetry_apl_pss_default_events,
166         },
167         .ioss_config = {
168                 .telem_evts = telemetry_apl_ioss_default_events,
169         },
170 };
171
172 /* GLK specific Data */
173 static struct telemetry_plt_config telem_glk_config = {
174         .pss_config = {
175                 .telem_evts = telemetry_glk_pss_default_events,
176         },
177         .ioss_config = {
178                 .telem_evts = telemetry_apl_ioss_default_events,
179         },
180 };
181
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),
185         {}
186 };
187
188 MODULE_DEVICE_TABLE(x86cpu, telemetry_cpu_ids);
189
190 static inline int telem_get_unitconfig(enum telemetry_unit telem_unit,
191                                      struct telemetry_unit_config **unit_config)
192 {
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;
199
200         return 0;
201
202 }
203
204 static int telemetry_check_evtid(enum telemetry_unit telem_unit,
205                                  u32 *evtmap, u8 len,
206                                  enum telemetry_action action)
207 {
208         struct telemetry_unit_config *unit_config;
209         int ret;
210
211         ret = telem_get_unitconfig(telem_unit, &unit_config);
212         if (ret < 0)
213                 return ret;
214
215         switch (action) {
216         case TELEM_RESET:
217                 if (len > TELEM_MAX_EVENTS_SRAM)
218                         return -EINVAL;
219
220                 break;
221
222         case TELEM_UPDATE:
223                 if (len > TELEM_MAX_EVENTS_SRAM)
224                         return -EINVAL;
225
226                 if ((len > 0) && (evtmap == NULL))
227                         return -EINVAL;
228
229                 break;
230
231         case TELEM_ADD:
232                 if ((len + unit_config->ssram_evts_used) >
233                     TELEM_MAX_EVENTS_SRAM)
234                         return -EINVAL;
235
236                 if ((len > 0) && (evtmap == NULL))
237                         return -EINVAL;
238
239                 break;
240
241         default:
242                 pr_err("Unknown Telemetry action specified %d\n", action);
243                 return -EINVAL;
244         }
245
246         return 0;
247 }
248
249
250 static inline int telemetry_plt_config_ioss_event(u32 evt_id, int index)
251 {
252         u32 write_buf;
253         int ret;
254
255         write_buf = evt_id | TELEM_EVENT_ENABLE;
256         write_buf <<= BITS_PER_BYTE;
257         write_buf |= index;
258
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);
262
263         return ret;
264 }
265
266 static inline int telemetry_plt_config_pss_event(u32 evt_id, int index)
267 {
268         u32 write_buf;
269         int ret;
270
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);
274
275         return ret;
276 }
277
278 static int telemetry_setup_iossevtconfig(struct telemetry_evtconfig evtconfig,
279                                          enum telemetry_action action)
280 {
281         u8 num_ioss_evts, ioss_period;
282         int ret, index, idx;
283         u32 *ioss_evtmap;
284         u32 telem_ctrl;
285
286         num_ioss_evts = evtconfig.num_evts;
287         ioss_period = evtconfig.period;
288         ioss_evtmap = evtconfig.evtmap;
289
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;
297         }
298
299         /* Disable Telemetry */
300         TELEM_DISABLE(telem_ctrl);
301
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;
310         }
311
312
313         /* Reset Everything */
314         if (action == TELEM_RESET) {
315                 /* Clear All Events */
316                 TELEM_CLEAR_EVENTS(telem_ctrl);
317
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;
326                 }
327                 telm_conf->ioss_config.ssram_evts_used = 0;
328
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;
337                         }
338                         telm_conf->ioss_config.ssram_evts_used++;
339                 }
340         }
341
342         /* Re-Configure Everything */
343         if (action == TELEM_UPDATE) {
344                 /* Clear All Events */
345                 TELEM_CLEAR_EVENTS(telem_ctrl);
346
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;
355                 }
356                 telm_conf->ioss_config.ssram_evts_used = 0;
357
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];
362
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;
369                         }
370                         telm_conf->ioss_config.ssram_evts_used++;
371                 }
372         }
373
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];
381
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;
388                         }
389                         telm_conf->ioss_config.ssram_evts_used++;
390                 }
391         }
392
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;
398
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;
406         }
407
408         telm_conf->ioss_config.curr_period = ioss_period;
409
410         return 0;
411 }
412
413
414 static int telemetry_setup_pssevtconfig(struct telemetry_evtconfig evtconfig,
415                                         enum telemetry_action action)
416 {
417         u8 num_pss_evts, pss_period;
418         int ret, index, idx;
419         u32 *pss_evtmap;
420         u32 telem_ctrl;
421
422         num_pss_evts = evtconfig.num_evts;
423         pss_period = evtconfig.period;
424         pss_evtmap = evtconfig.evtmap;
425
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;
433         }
434
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;
442         }
443
444         /* Reset Everything */
445         if (action == TELEM_RESET) {
446                 /* Clear All Events */
447                 TELEM_CLEAR_EVENTS(telem_ctrl);
448
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;
455                 }
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;
465                         }
466                         telm_conf->pss_config.ssram_evts_used++;
467                 }
468         }
469
470         /* Re-Configure Everything */
471         if (action == TELEM_UPDATE) {
472                 /* Clear All Events */
473                 TELEM_CLEAR_EVENTS(telem_ctrl);
474
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;
481                 }
482                 telm_conf->pss_config.ssram_evts_used = 0;
483
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];
488
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;
495                         }
496                         telm_conf->pss_config.ssram_evts_used++;
497                 }
498         }
499
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++) {
505
506                         telm_conf->pss_config.telem_evts[index].evt_id =
507                         pss_evtmap[idx];
508
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;
515                         }
516                         telm_conf->pss_config.ssram_evts_used++;
517                 }
518         }
519
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;
525
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;
531         }
532
533         telm_conf->pss_config.curr_period = pss_period;
534
535         return 0;
536 }
537
538 static int telemetry_setup_evtconfig(struct telemetry_evtconfig pss_evtconfig,
539                                      struct telemetry_evtconfig ioss_evtconfig,
540                                      enum telemetry_action action)
541 {
542         int ret;
543
544         mutex_lock(&(telm_conf->telem_lock));
545
546         if ((action == TELEM_UPDATE) && (telm_conf->telem_in_use)) {
547                 ret = -EBUSY;
548                 goto out;
549         }
550
551         ret = telemetry_check_evtid(TELEM_PSS, pss_evtconfig.evtmap,
552                                     pss_evtconfig.num_evts, action);
553         if (ret)
554                 goto out;
555
556         ret = telemetry_check_evtid(TELEM_IOSS, ioss_evtconfig.evtmap,
557                                     ioss_evtconfig.num_evts, action);
558         if (ret)
559                 goto out;
560
561         if (ioss_evtconfig.num_evts) {
562                 ret = telemetry_setup_iossevtconfig(ioss_evtconfig, action);
563                 if (ret)
564                         goto out;
565         }
566
567         if (pss_evtconfig.num_evts) {
568                 ret = telemetry_setup_pssevtconfig(pss_evtconfig, action);
569                 if (ret)
570                         goto out;
571         }
572
573         if ((action == TELEM_UPDATE) || (action == TELEM_ADD))
574                 telm_conf->telem_in_use = true;
575         else
576                 telm_conf->telem_in_use = false;
577
578 out:
579         mutex_unlock(&(telm_conf->telem_lock));
580         return ret;
581 }
582
583 static int telemetry_setup(struct platform_device *pdev)
584 {
585         struct telemetry_evtconfig pss_evtconfig, ioss_evtconfig;
586         u32 read_buf, events, event_regs;
587         int ret;
588
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;
594         }
595
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;
606         }
607
608         telm_conf->ioss_config.min_period = TELEM_MIN_PERIOD(read_buf);
609         telm_conf->ioss_config.max_period = TELEM_MAX_PERIOD(read_buf);
610
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;
617         }
618
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;
629         }
630
631         telm_conf->pss_config.min_period = TELEM_MIN_PERIOD(read_buf);
632         telm_conf->pss_config.max_period = TELEM_MAX_PERIOD(read_buf);
633
634         pss_evtconfig.evtmap = NULL;
635         pss_evtconfig.num_evts = TELEM_MAX_OS_ALLOCATED_EVENTS;
636         pss_evtconfig.period = TELEM_SAMPLING_DEFAULT_PERIOD;
637
638         ioss_evtconfig.evtmap = NULL;
639         ioss_evtconfig.num_evts = TELEM_MAX_OS_ALLOCATED_EVENTS;
640         ioss_evtconfig.period = TELEM_SAMPLING_DEFAULT_PERIOD;
641
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;
647         }
648         return 0;
649 }
650
651 static int telemetry_plt_update_events(struct telemetry_evtconfig pss_evtconfig,
652                                 struct telemetry_evtconfig ioss_evtconfig)
653 {
654         int ret;
655
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;
660         }
661
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;
666         }
667
668         ret = telemetry_setup_evtconfig(pss_evtconfig, ioss_evtconfig,
669                                         TELEM_UPDATE);
670         if (ret)
671                 pr_err("TELEMETRY Config Failed\n");
672
673         return ret;
674 }
675
676
677 static int telemetry_plt_set_sampling_period(u8 pss_period, u8 ioss_period)
678 {
679         u32 telem_ctrl = 0;
680         int ret = 0;
681
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;
688                 }
689
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;
697                 }
698
699                 /* Disable Telemetry */
700                 TELEM_DISABLE(telem_ctrl);
701
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;
710                 }
711
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;
717
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;
726                 }
727                 telm_conf->ioss_config.curr_period = ioss_period;
728         }
729
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;
735                 }
736
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;
744                 }
745
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;
754                 }
755
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;
761
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;
768                 }
769                 telm_conf->pss_config.curr_period = pss_period;
770         }
771
772 out:
773         mutex_unlock(&(telm_conf->telem_lock));
774         return ret;
775 }
776
777
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)
782 {
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;
787
788         return 0;
789 }
790
791
792 static int telemetry_plt_reset_events(void)
793 {
794         struct telemetry_evtconfig pss_evtconfig, ioss_evtconfig;
795         int ret;
796
797         pss_evtconfig.evtmap = NULL;
798         pss_evtconfig.num_evts = TELEM_MAX_OS_ALLOCATED_EVENTS;
799         pss_evtconfig.period = TELEM_SAMPLING_DEFAULT_PERIOD;
800
801         ioss_evtconfig.evtmap = NULL;
802         ioss_evtconfig.num_evts = TELEM_MAX_OS_ALLOCATED_EVENTS;
803         ioss_evtconfig.period = TELEM_SAMPLING_DEFAULT_PERIOD;
804
805         ret = telemetry_setup_evtconfig(pss_evtconfig, ioss_evtconfig,
806                                         TELEM_RESET);
807         if (ret)
808                 pr_err("TELEMETRY Reset Failed\n");
809
810         return ret;
811 }
812
813
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)
817 {
818         u32 *pss_evtmap, *ioss_evtmap;
819         u32 index;
820
821         pss_evtmap = pss_config->evtmap;
822         ioss_evtmap = ioss_config->evtmap;
823
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;
827
828         pss_config->period = telm_conf->pss_config.curr_period;
829         ioss_config->period = telm_conf->ioss_config.curr_period;
830
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;
835         }
836
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;
841         }
842
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;
847         }
848
849         mutex_unlock(&(telm_conf->telem_lock));
850         return 0;
851 }
852
853
854 static int telemetry_plt_add_events(u8 num_pss_evts, u8 num_ioss_evts,
855                                     u32 *pss_evtmap, u32 *ioss_evtmap)
856 {
857         struct telemetry_evtconfig pss_evtconfig, ioss_evtconfig;
858         int ret;
859
860         pss_evtconfig.evtmap = pss_evtmap;
861         pss_evtconfig.num_evts = num_pss_evts;
862         pss_evtconfig.period = telm_conf->pss_config.curr_period;
863
864         ioss_evtconfig.evtmap = ioss_evtmap;
865         ioss_evtconfig.num_evts = num_ioss_evts;
866         ioss_evtconfig.period = telm_conf->ioss_config.curr_period;
867
868         ret = telemetry_setup_evtconfig(pss_evtconfig, ioss_evtconfig,
869                                         TELEM_ADD);
870         if (ret)
871                 pr_err("TELEMETRY ADD Failed\n");
872
873         return ret;
874 }
875
876 static int telem_evtlog_read(enum telemetry_unit telem_unit,
877                              struct telem_ssram_region *ssram_region, u8 len)
878 {
879         struct telemetry_unit_config *unit_config;
880         u64 timestamp_prev, timestamp_next;
881         int ret, index, timeout = 0;
882
883         ret = telem_get_unitconfig(telem_unit, &unit_config);
884         if (ret < 0)
885                 return ret;
886
887         if (len > unit_config->ssram_evts_used)
888                 len = unit_config->ssram_evts_used;
889
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;
895                 }
896
897                 ssram_region->start_time = readq(unit_config->regmap +
898                                                  TELEM_SSRAM_STARTTIME_OFFSET);
899
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);
904                 }
905
906                 timestamp_next = readq(unit_config->regmap);
907                 if (!timestamp_next) {
908                         pr_err("Ssram under update. Please Try Later\n");
909                         return -EBUSY;
910                 }
911
912                 if (timeout++ > TELEM_SSRAM_READ_TIMEOUT) {
913                         pr_err("Timeout while reading Events\n");
914                         return -EBUSY;
915                 }
916
917         } while (timestamp_prev != timestamp_next);
918
919         ssram_region->timestamp = timestamp_next;
920
921         return len;
922 }
923
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)
927 {
928         int index, idx1, ret, readlen = len;
929         struct telem_ssram_region ssram_region;
930         struct telemetry_evtmap *evtmap;
931
932         switch (telem_unit)     {
933         case TELEM_PSS:
934                 evtmap = telm_conf->pss_config.telem_evts;
935                 break;
936
937         case TELEM_IOSS:
938                 evtmap = telm_conf->ioss_config.telem_evts;
939                 break;
940
941         default:
942                 pr_err("Unknown Telemetry Unit Specified %d\n", telem_unit);
943                 return -EINVAL;
944         }
945
946         if (!log_all_evts)
947                 readlen = TELEM_MAX_EVENTS_SRAM;
948
949         ret = telem_evtlog_read(telem_unit, &ssram_region, readlen);
950         if (ret < 0)
951                 return ret;
952
953         /* Invalid evt-id array specified via length mismatch */
954         if ((!log_all_evts) && (len > ret))
955                 return -EINVAL;
956
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;
961                 }
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++;
972
973                                         break;
974                                 }
975                         }
976                 }
977
978         return readlen;
979 }
980
981 static int telemetry_plt_read_eventlog(enum telemetry_unit telem_unit,
982                 struct telemetry_evtlog *evtlog, int len, int log_all_evts)
983 {
984         int ret;
985
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));
990
991         return ret;
992 }
993
994 static int telemetry_plt_get_trace_verbosity(enum telemetry_unit telem_unit,
995                                              u32 *verbosity)
996 {
997         u32 temp = 0;
998         int ret;
999
1000         if (verbosity == NULL)
1001                 return -EINVAL;
1002
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;
1012                 }
1013
1014                 break;
1015
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;
1023                 }
1024
1025                 break;
1026
1027         default:
1028                 pr_err("Unknown Telemetry Unit Specified %d\n", telem_unit);
1029                 ret = -EINVAL;
1030                 break;
1031         }
1032         TELEM_EXTRACT_VERBOSITY(temp, *verbosity);
1033
1034 out:
1035         mutex_unlock(&(telm_conf->telem_trace_lock));
1036         return ret;
1037 }
1038
1039 static int telemetry_plt_set_trace_verbosity(enum telemetry_unit telem_unit,
1040                                              u32 verbosity)
1041 {
1042         u32 temp = 0;
1043         int ret;
1044
1045         verbosity &= TELEM_TRC_VERBOSITY_MASK;
1046
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;
1056                 }
1057
1058                 TELEM_CLEAR_VERBOSITY_BITS(temp);
1059                 TELEM_SET_VERBOSITY_BITS(temp, verbosity);
1060
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;
1067                 }
1068                 break;
1069
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;
1077                 }
1078
1079                 TELEM_CLEAR_VERBOSITY_BITS(temp);
1080                 TELEM_SET_VERBOSITY_BITS(temp, verbosity);
1081
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;
1088                 }
1089                 break;
1090
1091         default:
1092                 pr_err("Unknown Telemetry Unit Specified %d\n", telem_unit);
1093                 ret = -EINVAL;
1094                 break;
1095         }
1096
1097 out:
1098         mutex_unlock(&(telm_conf->telem_trace_lock));
1099         return ret;
1100 }
1101
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,
1113 };
1114
1115 static int telemetry_pltdrv_probe(struct platform_device *pdev)
1116 {
1117         const struct x86_cpu_id *id;
1118         void __iomem *mem;
1119         int ret;
1120
1121         id = x86_match_cpu(telemetry_cpu_ids);
1122         if (!id)
1123                 return -ENODEV;
1124
1125         telm_conf = (struct telemetry_plt_config *)id->driver_data;
1126
1127         mem = devm_platform_ioremap_resource(pdev, 0);
1128         if (IS_ERR(mem))
1129                 return PTR_ERR(mem);
1130
1131         telm_conf->pss_config.regmap = mem;
1132
1133         mem = devm_platform_ioremap_resource(pdev, 1);
1134         if (IS_ERR(mem))
1135                 return PTR_ERR(mem);
1136
1137         telm_conf->ioss_config.regmap = mem;
1138
1139         mutex_init(&telm_conf->telem_lock);
1140         mutex_init(&telm_conf->telem_trace_lock);
1141
1142         ret = telemetry_setup(pdev);
1143         if (ret)
1144                 goto out;
1145
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;
1150         }
1151
1152         return 0;
1153
1154 out:
1155         dev_err(&pdev->dev, "TELEMETRY Setup Failed.\n");
1156
1157         return ret;
1158 }
1159
1160 static int telemetry_pltdrv_remove(struct platform_device *pdev)
1161 {
1162         telemetry_clear_pltdata();
1163         return 0;
1164 }
1165
1166 static struct platform_driver telemetry_soc_driver = {
1167         .probe          = telemetry_pltdrv_probe,
1168         .remove         = telemetry_pltdrv_remove,
1169         .driver         = {
1170                 .name   = DRIVER_NAME,
1171         },
1172 };
1173
1174 static int __init telemetry_module_init(void)
1175 {
1176         return platform_driver_register(&telemetry_soc_driver);
1177 }
1178
1179 static void __exit telemetry_module_exit(void)
1180 {
1181         platform_driver_unregister(&telemetry_soc_driver);
1182 }
1183
1184 device_initcall(telemetry_module_init);
1185 module_exit(telemetry_module_exit);
1186
1187 MODULE_AUTHOR("Souvik Kumar Chakravarty <[email protected]>");
1188 MODULE_DESCRIPTION("Intel SoC Telemetry Platform Driver");
1189 MODULE_VERSION(DRIVER_VERSION);
1190 MODULE_LICENSE("GPL v2");
This page took 0.104134 seconds and 4 git commands to generate.