File Index
Files and directories
Sign in
FILE

pltdrv.c

File preview with syntax highlighting.

linux-6.19.14/drivers/platform/x86/intel/telemetry/pltdrv.c 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_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_VFM(INTEL_ATOM_GOLDMONT,	&telem_apl_config),
181	X86_MATCH_VFM(INTEL_ATOM_GOLDMONT_PLUS,	&telem_glk_config),
182	{}
183};
184
185MODULE_DEVICE_TABLE(x86cpu, telemetry_cpu_ids);
186
187static inline int telem_get_unitconfig(enum telemetry_unit telem_unit,
188				     struct telemetry_unit_config **unit_config)
189{
190	if (telem_unit == TELEM_PSS)
191		*unit_config = &(telm_conf->pss_config);
192	else if (telem_unit == TELEM_IOSS)
193		*unit_config = &(telm_conf->ioss_config);
194	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_NENABLES_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 telem_evtlog_read(enum telemetry_unit telem_unit,
643			     struct telem_ssram_region *ssram_region, u8 len)
644{
645	struct telemetry_unit_config *unit_config;
646	u64 timestamp_prev, timestamp_next;
647	int ret, index, timeout = 0;
648
649	ret = telem_get_unitconfig(telem_unit, &unit_config);
650	if (ret < 0)
651		return ret;
652
653	if (len > unit_config->ssram_evts_used)
654		len = unit_config->ssram_evts_used;
655
656	do {
657		timestamp_prev = readq(unit_config->regmap);
658		if (!timestamp_prev) {
659			pr_err("Ssram under update. Please Try Later\n");
660			return -EBUSY;
661		}
662
663		ssram_region->start_time = readq(unit_config->regmap +
664						 TELEM_SSRAM_STARTTIME_OFFSET);
665
666		for (index = 0; index < len; index++) {
667			ssram_region->events[index] =
668			readq(unit_config->regmap + TELEM_SSRAM_EVTLOG_OFFSET +
669			      BYTES_PER_LONG*index);
670		}
671
672		timestamp_next = readq(unit_config->regmap);
673		if (!timestamp_next) {
674			pr_err("Ssram under update. Please Try Later\n");
675			return -EBUSY;
676		}
677
678		if (timeout++ > TELEM_SSRAM_READ_TIMEOUT) {
679			pr_err("Timeout while reading Events\n");
680			return -EBUSY;
681		}
682
683	} while (timestamp_prev != timestamp_next);
684
685	ssram_region->timestamp = timestamp_next;
686
687	return len;
688}
689
690static int telemetry_plt_raw_read_eventlog(enum telemetry_unit telem_unit,
691					   struct telemetry_evtlog *evtlog,
692					   int len, int log_all_evts)
693{
694	int index, idx1, ret, readlen = len;
695	struct telem_ssram_region ssram_region;
696	struct telemetry_evtmap *evtmap;
697
698	switch (telem_unit)	{
699	case TELEM_PSS:
700		evtmap = telm_conf->pss_config.telem_evts;
701		break;
702
703	case TELEM_IOSS:
704		evtmap = telm_conf->ioss_config.telem_evts;
705		break;
706
707	default:
708		pr_err("Unknown Telemetry Unit Specified %d\n", telem_unit);
709		return -EINVAL;
710	}
711
712	if (!log_all_evts)
713		readlen = TELEM_MAX_EVENTS_SRAM;
714
715	ret = telem_evtlog_read(telem_unit, &ssram_region, readlen);
716	if (ret < 0)
717		return ret;
718
719	/* Invalid evt-id array specified via length mismatch */
720	if ((!log_all_evts) && (len > ret))
721		return -EINVAL;
722
723	if (log_all_evts)
724		for (index = 0; index < ret; index++) {
725			evtlog[index].telem_evtlog = ssram_region.events[index];
726			evtlog[index].telem_evtid = evtmap[index].evt_id;
727		}
728	else
729		for (index = 0, readlen = 0; (index < ret) && (readlen < len);
730		     index++) {
731			for (idx1 = 0; idx1 < len; idx1++) {
732				/* Elements matched */
733				if (evtmap[index].evt_id ==
734				    evtlog[idx1].telem_evtid) {
735					evtlog[idx1].telem_evtlog =
736					ssram_region.events[index];
737					readlen++;
738
739					break;
740				}
741			}
742		}
743
744	return readlen;
745}
746
747static int telemetry_plt_read_eventlog(enum telemetry_unit telem_unit,
748		struct telemetry_evtlog *evtlog, int len, int log_all_evts)
749{
750	int ret;
751
752	mutex_lock(&(telm_conf->telem_lock));
753	ret = telemetry_plt_raw_read_eventlog(telem_unit, evtlog,
754					      len, log_all_evts);
755	mutex_unlock(&(telm_conf->telem_lock));
756
757	return ret;
758}
759
760static int telemetry_plt_get_trace_verbosity(enum telemetry_unit telem_unit,
761					     u32 *verbosity)
762{
763	u32 temp = 0;
764	int ret;
765
766	if (verbosity == NULL)
767		return -EINVAL;
768
769	mutex_lock(&(telm_conf->telem_trace_lock));
770	switch (telem_unit) {
771	case TELEM_PSS:
772		ret = intel_punit_ipc_command(
773				IPC_PUNIT_BIOS_READ_TELE_TRACE_CTRL,
774				0, 0, NULL, &temp);
775		if (ret) {
776			pr_err("PSS TRACE_CTRL Read Failed\n");
777			goto out;
778		}
779
780		break;
781
782	case TELEM_IOSS:
783		ret = intel_scu_ipc_dev_command(telm_conf->scu,
784				IOSS_TELEM, IOSS_TELEM_TRACE_CTL_READ,
785				NULL, 0, &temp, sizeof(temp));
786		if (ret) {
787			pr_err("IOSS TRACE_CTL Read Failed\n");
788			goto out;
789		}
790
791		break;
792
793	default:
794		pr_err("Unknown Telemetry Unit Specified %d\n", telem_unit);
795		ret = -EINVAL;
796		break;
797	}
798	TELEM_EXTRACT_VERBOSITY(temp, *verbosity);
799
800out:
801	mutex_unlock(&(telm_conf->telem_trace_lock));
802	return ret;
803}
804
805static int telemetry_plt_set_trace_verbosity(enum telemetry_unit telem_unit,
806					     u32 verbosity)
807{
808	u32 temp = 0;
809	int ret;
810
811	verbosity &= TELEM_TRC_VERBOSITY_MASK;
812
813	mutex_lock(&(telm_conf->telem_trace_lock));
814	switch (telem_unit) {
815	case TELEM_PSS:
816		ret = intel_punit_ipc_command(
817				IPC_PUNIT_BIOS_READ_TELE_TRACE_CTRL,
818				0, 0, NULL, &temp);
819		if (ret) {
820			pr_err("PSS TRACE_CTRL Read Failed\n");
821			goto out;
822		}
823
824		TELEM_CLEAR_VERBOSITY_BITS(temp);
825		TELEM_SET_VERBOSITY_BITS(temp, verbosity);
826
827		ret = intel_punit_ipc_command(
828				IPC_PUNIT_BIOS_WRITE_TELE_TRACE_CTRL,
829				0, 0, &temp, NULL);
830		if (ret) {
831			pr_err("PSS TRACE_CTRL Verbosity Set Failed\n");
832			goto out;
833		}
834		break;
835
836	case TELEM_IOSS:
837		ret = intel_scu_ipc_dev_command(telm_conf->scu, IOSS_TELEM,
838						IOSS_TELEM_TRACE_CTL_READ,
839						NULL, 0, &temp, sizeof(temp));
840		if (ret) {
841			pr_err("IOSS TRACE_CTL Read Failed\n");
842			goto out;
843		}
844
845		TELEM_CLEAR_VERBOSITY_BITS(temp);
846		TELEM_SET_VERBOSITY_BITS(temp, verbosity);
847
848		ret = intel_scu_ipc_dev_command(telm_conf->scu, IOSS_TELEM,
849						IOSS_TELEM_TRACE_CTL_WRITE,
850						&temp, sizeof(temp), NULL, 0);
851		if (ret) {
852			pr_err("IOSS TRACE_CTL Verbosity Set Failed\n");
853			goto out;
854		}
855		break;
856
857	default:
858		pr_err("Unknown Telemetry Unit Specified %d\n", telem_unit);
859		ret = -EINVAL;
860		break;
861	}
862
863out:
864	mutex_unlock(&(telm_conf->telem_trace_lock));
865	return ret;
866}
867
868static const struct telemetry_core_ops telm_pltops = {
869	.get_trace_verbosity = telemetry_plt_get_trace_verbosity,
870	.set_trace_verbosity = telemetry_plt_set_trace_verbosity,
871	.raw_read_eventlog = telemetry_plt_raw_read_eventlog,
872	.read_eventlog = telemetry_plt_read_eventlog,
873};
874
875static int telemetry_pltdrv_probe(struct platform_device *pdev)
876{
877	const struct x86_cpu_id *id;
878	void __iomem *mem;
879	int ret;
880
881	id = x86_match_cpu(telemetry_cpu_ids);
882	if (!id)
883		return -ENODEV;
884
885	telm_conf = (struct telemetry_plt_config *)id->driver_data;
886
887	telm_conf->pmc = dev_get_drvdata(pdev->dev.parent);
888
889	mem = devm_platform_ioremap_resource(pdev, 0);
890	if (IS_ERR(mem))
891		return PTR_ERR(mem);
892
893	telm_conf->pss_config.regmap = mem;
894
895	mem = devm_platform_ioremap_resource(pdev, 1);
896	if (IS_ERR(mem))
897		return PTR_ERR(mem);
898
899	telm_conf->ioss_config.regmap = mem;
900
901	telm_conf->scu = devm_intel_scu_ipc_dev_get(&pdev->dev);
902	if (!telm_conf->scu) {
903		ret = -EPROBE_DEFER;
904		goto out;
905	}
906
907	mutex_init(&telm_conf->telem_lock);
908	mutex_init(&telm_conf->telem_trace_lock);
909
910	ret = telemetry_setup(pdev);
911	if (ret)
912		goto out;
913
914	ret = telemetry_set_pltdata(&telm_pltops, telm_conf);
915	if (ret) {
916		dev_err(&pdev->dev, "TELEMETRY Set Pltops Failed.\n");
917		goto out;
918	}
919
920	return 0;
921
922out:
923	dev_err(&pdev->dev, "TELEMETRY Setup Failed.\n");
924
925	return ret;
926}
927
928static void telemetry_pltdrv_remove(struct platform_device *pdev)
929{
930	telemetry_clear_pltdata();
931}
932
933static struct platform_driver telemetry_soc_driver = {
934	.probe		= telemetry_pltdrv_probe,
935	.remove		= telemetry_pltdrv_remove,
936	.driver		= {
937		.name	= DRIVER_NAME,
938	},
939};
940
941static int __init telemetry_module_init(void)
942{
943	return platform_driver_register(&telemetry_soc_driver);
944}
945
946static void __exit telemetry_module_exit(void)
947{
948	platform_driver_unregister(&telemetry_soc_driver);
949}
950
951device_initcall(telemetry_module_init);
952module_exit(telemetry_module_exit);
953
954MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>");
955MODULE_DESCRIPTION("Intel SoC Telemetry Platform Driver");
956MODULE_VERSION(DRIVER_VERSION);
957MODULE_LICENSE("GPL v2");
~/ Read-only file preview.