brintos

brintos / linux-shallow public Read only

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