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