brintos

brintos / linux-shallow public Read only

0
0
Text · 60.5 KiB · 9d18dfc Raw
2118 lines · c
1// SPDX-License-Identifier: GPL-2.0-only OR Linux-OpenIB2/*3 * Mellanox BlueField Performance Monitoring Counters driver4 *5 * This driver provides a sysfs interface for monitoring6 * performance statistics in BlueField SoC.7 *8 * Copyright (c) 2020, NVIDIA CORPORATION.  All rights reserved.9 */10 11#include <linux/acpi.h>12#include <linux/arm-smccc.h>13#include <linux/bitfield.h>14#include <linux/errno.h>15#include <linux/hwmon.h>16#include <linux/platform_device.h>17#include <linux/string.h>18#include <uapi/linux/psci.h>19 20#define MLXBF_PMC_WRITE_REG_32 0x8200000921#define MLXBF_PMC_READ_REG_32 0x8200000A22#define MLXBF_PMC_WRITE_REG_64 0x8200000B23#define MLXBF_PMC_READ_REG_64 0x8200000C24#define MLXBF_PMC_SIP_SVC_UID 0x8200ff0125#define MLXBF_PMC_SIP_SVC_VERSION 0x8200ff0326#define MLXBF_PMC_SVC_REQ_MAJOR 027#define MLXBF_PMC_SVC_MIN_MINOR 328 29#define MLXBF_PMC_SMCCC_ACCESS_VIOLATION -430 31#define MLXBF_PMC_EVENT_SET_BF1 032#define MLXBF_PMC_EVENT_SET_BF2 133#define MLXBF_PMC_EVENT_SET_BF3 234#define MLXBF_PMC_EVENT_INFO_LEN 10035 36#define MLXBF_PMC_MAX_BLOCKS 3037#define MLXBF_PMC_MAX_ATTRS 7038#define MLXBF_PMC_INFO_SZ 439#define MLXBF_PMC_REG_SIZE 840#define MLXBF_PMC_L3C_REG_SIZE 441 42#define MLXBF_PMC_TYPE_CRSPACE 243#define MLXBF_PMC_TYPE_COUNTER 144#define MLXBF_PMC_TYPE_REGISTER 045 46#define MLXBF_PMC_PERFCTL 047#define MLXBF_PMC_PERFEVT 148#define MLXBF_PMC_PERFACC0 449 50#define MLXBF_PMC_PERFMON_CONFIG_WR_R_B BIT(0)51#define MLXBF_PMC_PERFMON_CONFIG_STROBE BIT(1)52#define MLXBF_PMC_PERFMON_CONFIG_ADDR GENMASK_ULL(4, 2)53#define MLXBF_PMC_PERFMON_CONFIG_WDATA GENMASK_ULL(60, 5)54 55#define MLXBF_PMC_PERFCTL_FM0 GENMASK_ULL(18, 16)56#define MLXBF_PMC_PERFCTL_MS0 GENMASK_ULL(21, 20)57#define MLXBF_PMC_PERFCTL_ACCM0 GENMASK_ULL(26, 24)58#define MLXBF_PMC_PERFCTL_AD0 BIT(27)59#define MLXBF_PMC_PERFCTL_ETRIG0 GENMASK_ULL(29, 28)60#define MLXBF_PMC_PERFCTL_EB0 BIT(30)61#define MLXBF_PMC_PERFCTL_EN0 BIT(31)62 63#define MLXBF_PMC_PERFEVT_EVTSEL GENMASK_ULL(31, 24)64 65#define MLXBF_PMC_L3C_PERF_CNT_CFG 0x066#define MLXBF_PMC_L3C_PERF_CNT_SEL 0x1067#define MLXBF_PMC_L3C_PERF_CNT_SEL_1 0x1468#define MLXBF_PMC_L3C_PERF_CNT_LOW 0x4069#define MLXBF_PMC_L3C_PERF_CNT_HIGH 0x6070 71#define MLXBF_PMC_L3C_PERF_CNT_CFG_EN BIT(0)72#define MLXBF_PMC_L3C_PERF_CNT_CFG_RST BIT(1)73#define MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_0 GENMASK(5, 0)74#define MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_1 GENMASK(13, 8)75#define MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_2 GENMASK(21, 16)76#define MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_3 GENMASK(29, 24)77 78#define MLXBF_PMC_L3C_PERF_CNT_SEL_1_CNT_4 GENMASK(5, 0)79 80#define MLXBF_PMC_L3C_PERF_CNT_LOW_VAL GENMASK(31, 0)81#define MLXBF_PMC_L3C_PERF_CNT_HIGH_VAL GENMASK(24, 0)82 83#define MLXBF_PMC_CRSPACE_PERFMON_REG0 0x084#define MLXBF_PMC_CRSPACE_PERFSEL_SZ 485#define MLXBF_PMC_CRSPACE_PERFSEL0 GENMASK(23, 16)86#define MLXBF_PMC_CRSPACE_PERFSEL1 GENMASK(7, 0)87#define MLXBF_PMC_CRSPACE_PERFMON_REG0_SZ 0x288#define MLXBF_PMC_CRSPACE_PERFMON_CTL(n) (n * MLXBF_PMC_CRSPACE_PERFMON_REG0_SZ)89#define MLXBF_PMC_CRSPACE_PERFMON_EN BIT(30)90#define MLXBF_PMC_CRSPACE_PERFMON_CLR BIT(28)91#define MLXBF_PMC_CRSPACE_PERFMON_VAL0(n) (MLXBF_PMC_CRSPACE_PERFMON_CTL(n) + 0xc)92 93/**94 * struct mlxbf_pmc_attribute - Structure to hold attribute and block info95 * for each sysfs entry96 * @dev_attr: Device attribute struct97 * @index: index to identify counter number within a block98 * @nr: block number to which the sysfs belongs99 */100struct mlxbf_pmc_attribute {101	struct device_attribute dev_attr;102	unsigned int index;103	unsigned int nr;104};105 106/**107 * struct mlxbf_pmc_block_info - Structure to hold info for each HW block108 *109 * @mmio_base: The VA at which the PMC block is mapped110 * @blk_size: Size of each mapped region111 * @counters: Number of counters in the block112 * @type: Type of counters in the block113 * @attr_counter: Attributes for "counter" sysfs files114 * @attr_event: Attributes for "event" sysfs files115 * @attr_event_list: Attributes for "event_list" sysfs files116 * @attr_enable: Attributes for "enable" sysfs files117 * @block_attr: All attributes needed for the block118 * @block_attr_grp: Attribute group for the block119 */120struct mlxbf_pmc_block_info {121	void __iomem *mmio_base;122	size_t blk_size;123	size_t counters;124	unsigned int type;125	struct mlxbf_pmc_attribute *attr_counter;126	struct mlxbf_pmc_attribute *attr_event;127	struct mlxbf_pmc_attribute attr_event_list;128	struct mlxbf_pmc_attribute attr_enable;129	struct attribute *block_attr[MLXBF_PMC_MAX_ATTRS];130	struct attribute_group block_attr_grp;131};132 133/**134 * struct mlxbf_pmc_context - Structure to hold PMC context info135 *136 * @pdev: The kernel structure representing the device137 * @total_blocks: Total number of blocks138 * @tile_count: Number of tiles in the system139 * @llt_enable: Info on enabled LLTs140 * @mss_enable: Info on enabled MSSs141 * @group_num: Group number assigned to each valid block142 * @hwmon_dev: Hwmon device for bfperf143 * @block_name: Block name144 * @block:  Block info145 * @groups:  Attribute groups from each block146 * @svc_sreg_support: Whether SMCs are used to access performance registers147 * @sreg_tbl_perf: Secure register access table number148 * @event_set: Event set to use149 */150struct mlxbf_pmc_context {151	struct platform_device *pdev;152	u32 total_blocks;153	u32 tile_count;154	u8 llt_enable;155	u8 mss_enable;156	u32 group_num;157	struct device *hwmon_dev;158	const char *block_name[MLXBF_PMC_MAX_BLOCKS];159	struct mlxbf_pmc_block_info block[MLXBF_PMC_MAX_BLOCKS];160	const struct attribute_group *groups[MLXBF_PMC_MAX_BLOCKS];161	bool svc_sreg_support;162	u32 sreg_tbl_perf;163	unsigned int event_set;164};165 166/**167 * struct mlxbf_pmc_events - Structure to hold supported events for each block168 * @evt_num: Event number used to program counters169 * @evt_name: Name of the event170 */171struct mlxbf_pmc_events {172	u32 evt_num;173	char *evt_name;174};175 176static const struct mlxbf_pmc_events mlxbf_pmc_pcie_events[] = {177	{ 0x0, "IN_P_PKT_CNT" },178	{ 0x10, "IN_NP_PKT_CNT" },179	{ 0x18, "IN_C_PKT_CNT" },180	{ 0x20, "OUT_P_PKT_CNT" },181	{ 0x28, "OUT_NP_PKT_CNT" },182	{ 0x30, "OUT_C_PKT_CNT" },183	{ 0x38, "IN_P_BYTE_CNT" },184	{ 0x40, "IN_NP_BYTE_CNT" },185	{ 0x48, "IN_C_BYTE_CNT" },186	{ 0x50, "OUT_P_BYTE_CNT" },187	{ 0x58, "OUT_NP_BYTE_CNT" },188	{ 0x60, "OUT_C_BYTE_CNT" },189};190 191static const struct mlxbf_pmc_events mlxbf_pmc_smgen_events[] = {192	{ 0x0, "AW_REQ" },193	{ 0x1, "AW_BEATS" },194	{ 0x2, "AW_TRANS" },195	{ 0x3, "AW_RESP" },196	{ 0x4, "AW_STL" },197	{ 0x5, "AW_LAT" },198	{ 0x6, "AW_REQ_TBU" },199	{ 0x8, "AR_REQ" },200	{ 0x9, "AR_BEATS" },201	{ 0xa, "AR_TRANS" },202	{ 0xb, "AR_STL" },203	{ 0xc, "AR_LAT" },204	{ 0xd, "AR_REQ_TBU" },205	{ 0xe, "TBU_MISS" },206	{ 0xf, "TX_DAT_AF" },207	{ 0x10, "RX_DAT_AF" },208	{ 0x11, "RETRYQ_CRED" },209};210 211static const struct mlxbf_pmc_events mlxbf_pmc_trio_events_1[] = {212	{ 0x0, "DISABLE" },213	{ 0xa0, "TPIO_DATA_BEAT" },214	{ 0xa1, "TDMA_DATA_BEAT" },215	{ 0xa2, "MAP_DATA_BEAT" },216	{ 0xa3, "TXMSG_DATA_BEAT" },217	{ 0xa4, "TPIO_DATA_PACKET" },218	{ 0xa5, "TDMA_DATA_PACKET" },219	{ 0xa6, "MAP_DATA_PACKET" },220	{ 0xa7, "TXMSG_DATA_PACKET" },221	{ 0xa8, "TDMA_RT_AF" },222	{ 0xa9, "TDMA_PBUF_MAC_AF" },223	{ 0xaa, "TRIO_MAP_WRQ_BUF_EMPTY" },224	{ 0xab, "TRIO_MAP_CPL_BUF_EMPTY" },225	{ 0xac, "TRIO_MAP_RDQ0_BUF_EMPTY" },226	{ 0xad, "TRIO_MAP_RDQ1_BUF_EMPTY" },227	{ 0xae, "TRIO_MAP_RDQ2_BUF_EMPTY" },228	{ 0xaf, "TRIO_MAP_RDQ3_BUF_EMPTY" },229	{ 0xb0, "TRIO_MAP_RDQ4_BUF_EMPTY" },230	{ 0xb1, "TRIO_MAP_RDQ5_BUF_EMPTY" },231	{ 0xb2, "TRIO_MAP_RDQ6_BUF_EMPTY" },232	{ 0xb3, "TRIO_MAP_RDQ7_BUF_EMPTY" },233};234 235static const struct mlxbf_pmc_events mlxbf_pmc_trio_events_2[] = {236	{ 0x0, "DISABLE" },237	{ 0xa0, "TPIO_DATA_BEAT" },238	{ 0xa1, "TDMA_DATA_BEAT" },239	{ 0xa2, "MAP_DATA_BEAT" },240	{ 0xa3, "TXMSG_DATA_BEAT" },241	{ 0xa4, "TPIO_DATA_PACKET" },242	{ 0xa5, "TDMA_DATA_PACKET" },243	{ 0xa6, "MAP_DATA_PACKET" },244	{ 0xa7, "TXMSG_DATA_PACKET" },245	{ 0xa8, "TDMA_RT_AF" },246	{ 0xa9, "TDMA_PBUF_MAC_AF" },247	{ 0xaa, "TRIO_MAP_WRQ_BUF_EMPTY" },248	{ 0xab, "TRIO_MAP_CPL_BUF_EMPTY" },249	{ 0xac, "TRIO_MAP_RDQ0_BUF_EMPTY" },250	{ 0xad, "TRIO_MAP_RDQ1_BUF_EMPTY" },251	{ 0xae, "TRIO_MAP_RDQ2_BUF_EMPTY" },252	{ 0xaf, "TRIO_MAP_RDQ3_BUF_EMPTY" },253	{ 0xb0, "TRIO_MAP_RDQ4_BUF_EMPTY" },254	{ 0xb1, "TRIO_MAP_RDQ5_BUF_EMPTY" },255	{ 0xb2, "TRIO_MAP_RDQ6_BUF_EMPTY" },256	{ 0xb3, "TRIO_MAP_RDQ7_BUF_EMPTY" },257	{ 0xb4, "TRIO_RING_TX_FLIT_CH0" },258	{ 0xb5, "TRIO_RING_TX_FLIT_CH1" },259	{ 0xb6, "TRIO_RING_TX_FLIT_CH2" },260	{ 0xb7, "TRIO_RING_TX_FLIT_CH3" },261	{ 0xb8, "TRIO_RING_TX_FLIT_CH4" },262	{ 0xb9, "TRIO_RING_RX_FLIT_CH0" },263	{ 0xba, "TRIO_RING_RX_FLIT_CH1" },264	{ 0xbb, "TRIO_RING_RX_FLIT_CH2" },265	{ 0xbc, "TRIO_RING_RX_FLIT_CH3" },266};267 268static const struct mlxbf_pmc_events mlxbf_pmc_ecc_events[] = {269	{ 0x0, "DISABLE" },270	{ 0x100, "ECC_SINGLE_ERROR_CNT" },271	{ 0x104, "ECC_DOUBLE_ERROR_CNT" },272	{ 0x114, "SERR_INJ" },273	{ 0x118, "DERR_INJ" },274	{ 0x124, "ECC_SINGLE_ERROR_0" },275	{ 0x164, "ECC_DOUBLE_ERROR_0" },276	{ 0x340, "DRAM_ECC_COUNT" },277	{ 0x344, "DRAM_ECC_INJECT" },278	{ 0x348, "DRAM_ECC_ERROR" },279};280 281static const struct mlxbf_pmc_events mlxbf_pmc_mss_events_1[] = {282	{ 0x0, "DISABLE" },283	{ 0xc0, "RXREQ_MSS" },284	{ 0xc1, "RXDAT_MSS" },285	{ 0xc2, "TXRSP_MSS" },286	{ 0xc3, "TXDAT_MSS" },287};288 289static const struct mlxbf_pmc_events mlxbf_pmc_mss_events_3[] = {290	{0, "SKYLIB_CDN_TX_FLITS"},291	{1, "SKYLIB_DDN_TX_FLITS"},292	{2, "SKYLIB_NDN_TX_FLITS"},293	{3, "SKYLIB_SDN_TX_FLITS"},294	{4, "SKYLIB_UDN_TX_FLITS"},295	{5, "SKYLIB_CDN_RX_FLITS"},296	{6, "SKYLIB_DDN_RX_FLITS"},297	{7, "SKYLIB_NDN_RX_FLITS"},298	{8, "SKYLIB_SDN_RX_FLITS"},299	{9, "SKYLIB_UDN_RX_FLITS"},300	{10, "SKYLIB_CDN_TX_STALL"},301	{11, "SKYLIB_DDN_TX_STALL"},302	{12, "SKYLIB_NDN_TX_STALL"},303	{13, "SKYLIB_SDN_TX_STALL"},304	{14, "SKYLIB_UDN_TX_STALL"},305	{15, "SKYLIB_CDN_RX_STALL"},306	{16, "SKYLIB_DDN_RX_STALL"},307	{17, "SKYLIB_NDN_RX_STALL"},308	{18, "SKYLIB_SDN_RX_STALL"},309	{19, "SKYLIB_UDN_RX_STALL"},310	{20, "SKYLIB_CHI_REQ0_TX_FLITS"},311	{21, "SKYLIB_CHI_DATA0_TX_FLITS"},312	{22, "SKYLIB_CHI_RESP0_TX_FLITS"},313	{23, "SKYLIB_CHI_SNP0_TX_FLITS"},314	{24, "SKYLIB_CHI_REQ1_TX_FLITS"},315	{25, "SKYLIB_CHI_DATA1_TX_FLITS"},316	{26, "SKYLIB_CHI_RESP1_TX_FLITS"},317	{27, "SKYLIB_CHI_SNP1_TX_FLITS"},318	{28, "SKYLIB_CHI_REQ2_TX_FLITS"},319	{29, "SKYLIB_CHI_DATA2_TX_FLITS"},320	{30, "SKYLIB_CHI_RESP2_TX_FLITS"},321	{31, "SKYLIB_CHI_SNP2_TX_FLITS"},322	{32, "SKYLIB_CHI_REQ3_TX_FLITS"},323	{33, "SKYLIB_CHI_DATA3_TX_FLITS"},324	{34, "SKYLIB_CHI_RESP3_TX_FLITS"},325	{35, "SKYLIB_CHI_SNP3_TX_FLITS"},326	{36, "SKYLIB_TLP_REQ_TX_FLITS"},327	{37, "SKYLIB_TLP_RESP_TX_FLITS"},328	{38, "SKYLIB_TLP_META_TX_FLITS"},329	{39, "SKYLIB_AXIS_DATA_TX_FLITS"},330	{40, "SKYLIB_AXIS_CRED_TX_FLITS"},331	{41, "SKYLIB_APB_TX_FLITS"},332	{42, "SKYLIB_VW_TX_FLITS"},333	{43, "SKYLIB_GGA_MSN_W_TX_FLITS"},334	{44, "SKYLIB_GGA_MSN_N_TX_FLITS"},335	{45, "SKYLIB_CR_REQ_TX_FLITS"},336	{46, "SKYLIB_CR_RESP_TX_FLITS"},337	{47, "SKYLIB_MSN_PRNF_TX_FLITS"},338	{48, "SKYLIB_DBG_DATA_TX_FLITS"},339	{49, "SKYLIB_DBG_CRED_TX_FLITS"},340	{50, "SKYLIB_CHI_REQ0_RX_FLITS"},341	{51, "SKYLIB_CHI_DATA0_RX_FLITS"},342	{52, "SKYLIB_CHI_RESP0_RX_FLITS"},343	{53, "SKYLIB_CHI_SNP0_RX_FLITS"},344	{54, "SKYLIB_CHI_REQ1_RX_FLITS"},345	{55, "SKYLIB_CHI_DATA1_RX_FLITS"},346	{56, "SKYLIB_CHI_RESP1_RX_FLITS"},347	{57, "SKYLIB_CHI_SNP1_RX_FLITS"},348	{58, "SKYLIB_CHI_REQ2_RX_FLITS"},349	{59, "SKYLIB_CHI_DATA2_RX_FLITS"},350	{60, "SKYLIB_CHI_RESP2_RX_FLITS"},351	{61, "SKYLIB_CHI_SNP2_RX_FLITS"},352	{62, "SKYLIB_CHI_REQ3_RX_FLITS"},353	{63, "SKYLIB_CHI_DATA3_RX_FLITS"},354	{64, "SKYLIB_CHI_RESP3_RX_FLITS"},355	{65, "SKYLIB_CHI_SNP3_RX_FLITS"},356	{66, "SKYLIB_TLP_REQ_RX_FLITS"},357	{67, "SKYLIB_TLP_RESP_RX_FLITS"},358	{68, "SKYLIB_TLP_META_RX_FLITS"},359	{69, "SKYLIB_AXIS_DATA_RX_FLITS"},360	{70, "SKYLIB_AXIS_CRED_RX_FLITS"},361	{71, "SKYLIB_APB_RX_FLITS"},362	{72, "SKYLIB_VW_RX_FLITS"},363	{73, "SKYLIB_GGA_MSN_W_RX_FLITS"},364	{74, "SKYLIB_GGA_MSN_N_RX_FLITS"},365	{75, "SKYLIB_CR_REQ_RX_FLITS"},366	{76, "SKYLIB_CR_RESP_RX_FLITS"},367	{77, "SKYLIB_MSN_PRNF_RX_FLITS"},368	{78, "SKYLIB_DBG_DATA_RX_FLITS"},369	{79, "SKYLIB_DBG_CRED_RX_FLITS"},370	{80, "SKYLIB_CHI_REQ0_TX_STALL"},371	{81, "SKYLIB_CHI_DATA0_TX_STALL"},372	{82, "SKYLIB_CHI_RESP0_TX_STALL"},373	{83, "SKYLIB_CHI_SNP0_TX_STALL"},374	{84, "SKYLIB_CHI_REQ1_TX_STALL"},375	{85, "SKYLIB_CHI_DATA1_TX_STALL"},376	{86, "SKYLIB_CHI_RESP1_TX_STALL"},377	{87, "SKYLIB_CHI_SNP1_TX_STALL"},378	{88, "SKYLIB_CHI_REQ2_TX_STALL"},379	{89, "SKYLIB_CHI_DATA2_TX_STALL"},380	{90, "SKYLIB_CHI_RESP2_TX_STALL"},381	{91, "SKYLIB_CHI_SNP2_TX_STALL"},382	{92, "SKYLIB_CHI_REQ3_TX_STALL"},383	{93, "SKYLIB_CHI_DATA3_TX_STALL"},384	{94, "SKYLIB_CHI_RESP3_TX_STALL"},385	{95, "SKYLIB_CHI_SNP3_TX_STALL"},386	{96, "SKYLIB_TLP_REQ_TX_STALL"},387	{97, "SKYLIB_TLP_RESP_TX_STALL"},388	{98, "SKYLIB_TLP_META_TX_STALL"},389	{99, "SKYLIB_AXIS_DATA_TX_STALL"},390	{100, "SKYLIB_AXIS_CRED_TX_STALL"},391	{101, "SKYLIB_APB_TX_STALL"},392	{102, "SKYLIB_VW_TX_STALL"},393	{103, "SKYLIB_GGA_MSN_W_TX_STALL"},394	{104, "SKYLIB_GGA_MSN_N_TX_STALL"},395	{105, "SKYLIB_CR_REQ_TX_STALL"},396	{106, "SKYLIB_CR_RESP_TX_STALL"},397	{107, "SKYLIB_MSN_PRNF_TX_STALL"},398	{108, "SKYLIB_DBG_DATA_TX_STALL"},399	{109, "SKYLIB_DBG_CRED_TX_STALL"},400	{110, "SKYLIB_CHI_REQ0_RX_STALL"},401	{111, "SKYLIB_CHI_DATA0_RX_STALL"},402	{112, "SKYLIB_CHI_RESP0_RX_STALL"},403	{113, "SKYLIB_CHI_SNP0_RX_STALL"},404	{114, "SKYLIB_CHI_REQ1_RX_STALL"},405	{115, "SKYLIB_CHI_DATA1_RX_STALL"},406	{116, "SKYLIB_CHI_RESP1_RX_STALL"},407	{117, "SKYLIB_CHI_SNP1_RX_STALL"},408	{118, "SKYLIB_CHI_REQ2_RX_STALL"},409	{119, "SKYLIB_CHI_DATA2_RX_STALL"},410	{120, "SKYLIB_CHI_RESP2_RX_STALL"},411	{121, "SKYLIB_CHI_SNP2_RX_STALL"},412	{122, "SKYLIB_CHI_REQ3_RX_STALL"},413	{123, "SKYLIB_CHI_DATA3_RX_STALL"},414	{124, "SKYLIB_CHI_RESP3_RX_STALL"},415	{125, "SKYLIB_CHI_SNP3_RX_STALL"},416	{126, "SKYLIB_TLP_REQ_RX_STALL"},417	{127, "SKYLIB_TLP_RESP_RX_STALL"},418	{128, "SKYLIB_TLP_META_RX_STALL"},419	{129, "SKYLIB_AXIS_DATA_RX_STALL"},420	{130, "SKYLIB_AXIS_CRED_RX_STALL"},421	{131, "SKYLIB_APB_RX_STALL"},422	{132, "SKYLIB_VW_RX_STALL"},423	{133, "SKYLIB_GGA_MSN_W_RX_STALL"},424	{134, "SKYLIB_GGA_MSN_N_RX_STALL"},425	{135, "SKYLIB_CR_REQ_RX_STALL"},426	{136, "SKYLIB_CR_RESP_RX_STALL"},427	{137, "SKYLIB_MSN_PRNF_RX_STALL"},428	{138, "SKYLIB_DBG_DATA_RX_STALL"},429	{139, "SKYLIB_DBG_CRED_RX_STALL"},430	{140, "SKYLIB_CDN_LOOPBACK_FLITS"},431	{141, "SKYLIB_DDN_LOOPBACK_FLITS"},432	{142, "SKYLIB_NDN_LOOPBACK_FLITS"},433	{143, "SKYLIB_SDN_LOOPBACK_FLITS"},434	{144, "SKYLIB_UDN_LOOPBACK_FLITS"},435	{145, "HISTOGRAM_HISTOGRAM_BIN0"},436	{146, "HISTOGRAM_HISTOGRAM_BIN1"},437	{147, "HISTOGRAM_HISTOGRAM_BIN2"},438	{148, "HISTOGRAM_HISTOGRAM_BIN3"},439	{149, "HISTOGRAM_HISTOGRAM_BIN4"},440	{150, "HISTOGRAM_HISTOGRAM_BIN5"},441	{151, "HISTOGRAM_HISTOGRAM_BIN6"},442	{152, "HISTOGRAM_HISTOGRAM_BIN7"},443	{153, "HISTOGRAM_HISTOGRAM_BIN8"},444	{154, "HISTOGRAM_HISTOGRAM_BIN9"},445};446 447static const struct mlxbf_pmc_events mlxbf_pmc_hnf_events[] = {448	{ 0x0, "DISABLE" },449	{ 0x45, "HNF_REQUESTS" },450	{ 0x46, "HNF_REJECTS" },451	{ 0x47, "ALL_BUSY" },452	{ 0x48, "MAF_BUSY" },453	{ 0x49, "MAF_REQUESTS" },454	{ 0x4a, "RNF_REQUESTS" },455	{ 0x4b, "REQUEST_TYPE" },456	{ 0x4c, "MEMORY_READS" },457	{ 0x4d, "MEMORY_WRITES" },458	{ 0x4e, "VICTIM_WRITE" },459	{ 0x4f, "POC_FULL" },460	{ 0x50, "POC_FAIL" },461	{ 0x51, "POC_SUCCESS" },462	{ 0x52, "POC_WRITES" },463	{ 0x53, "POC_READS" },464	{ 0x54, "FORWARD" },465	{ 0x55, "RXREQ_HNF" },466	{ 0x56, "RXRSP_HNF" },467	{ 0x57, "RXDAT_HNF" },468	{ 0x58, "TXREQ_HNF" },469	{ 0x59, "TXRSP_HNF" },470	{ 0x5a, "TXDAT_HNF" },471	{ 0x5b, "TXSNP_HNF" },472	{ 0x5c, "INDEX_MATCH" },473	{ 0x5d, "A72_ACCESS" },474	{ 0x5e, "IO_ACCESS" },475	{ 0x5f, "TSO_WRITE" },476	{ 0x60, "TSO_CONFLICT" },477	{ 0x61, "DIR_HIT" },478	{ 0x62, "HNF_ACCEPTS" },479	{ 0x63, "REQ_BUF_EMPTY" },480	{ 0x64, "REQ_BUF_IDLE_MAF" },481	{ 0x65, "TSO_NOARB" },482	{ 0x66, "TSO_NOARB_CYCLES" },483	{ 0x67, "MSS_NO_CREDIT" },484	{ 0x68, "TXDAT_NO_LCRD" },485	{ 0x69, "TXSNP_NO_LCRD" },486	{ 0x6a, "TXRSP_NO_LCRD" },487	{ 0x6b, "TXREQ_NO_LCRD" },488	{ 0x6c, "TSO_CL_MATCH" },489	{ 0x6d, "MEMORY_READS_BYPASS" },490	{ 0x6e, "TSO_NOARB_TIMEOUT" },491	{ 0x6f, "ALLOCATE" },492	{ 0x70, "VICTIM" },493	{ 0x71, "A72_WRITE" },494	{ 0x72, "A72_READ" },495	{ 0x73, "IO_WRITE" },496	{ 0x74, "IO_READ" },497	{ 0x75, "TSO_REJECT" },498	{ 0x80, "TXREQ_RN" },499	{ 0x81, "TXRSP_RN" },500	{ 0x82, "TXDAT_RN" },501	{ 0x83, "RXSNP_RN" },502	{ 0x84, "RXRSP_RN" },503	{ 0x85, "RXDAT_RN" },504};505 506static const struct mlxbf_pmc_events mlxbf_pmc_hnfnet_events[] = {507	{ 0x0, "DISABLE" },508	{ 0x12, "CDN_REQ" },509	{ 0x13, "DDN_REQ" },510	{ 0x14, "NDN_REQ" },511	{ 0x15, "CDN_DIAG_N_OUT_OF_CRED" },512	{ 0x16, "CDN_DIAG_S_OUT_OF_CRED" },513	{ 0x17, "CDN_DIAG_E_OUT_OF_CRED" },514	{ 0x18, "CDN_DIAG_W_OUT_OF_CRED" },515	{ 0x19, "CDN_DIAG_C_OUT_OF_CRED" },516	{ 0x1a, "CDN_DIAG_N_EGRESS" },517	{ 0x1b, "CDN_DIAG_S_EGRESS" },518	{ 0x1c, "CDN_DIAG_E_EGRESS" },519	{ 0x1d, "CDN_DIAG_W_EGRESS" },520	{ 0x1e, "CDN_DIAG_C_EGRESS" },521	{ 0x1f, "CDN_DIAG_N_INGRESS" },522	{ 0x20, "CDN_DIAG_S_INGRESS" },523	{ 0x21, "CDN_DIAG_E_INGRESS" },524	{ 0x22, "CDN_DIAG_W_INGRESS" },525	{ 0x23, "CDN_DIAG_C_INGRESS" },526	{ 0x24, "CDN_DIAG_CORE_SENT" },527	{ 0x25, "DDN_DIAG_N_OUT_OF_CRED" },528	{ 0x26, "DDN_DIAG_S_OUT_OF_CRED" },529	{ 0x27, "DDN_DIAG_E_OUT_OF_CRED" },530	{ 0x28, "DDN_DIAG_W_OUT_OF_CRED" },531	{ 0x29, "DDN_DIAG_C_OUT_OF_CRED" },532	{ 0x2a, "DDN_DIAG_N_EGRESS" },533	{ 0x2b, "DDN_DIAG_S_EGRESS" },534	{ 0x2c, "DDN_DIAG_E_EGRESS" },535	{ 0x2d, "DDN_DIAG_W_EGRESS" },536	{ 0x2e, "DDN_DIAG_C_EGRESS" },537	{ 0x2f, "DDN_DIAG_N_INGRESS" },538	{ 0x30, "DDN_DIAG_S_INGRESS" },539	{ 0x31, "DDN_DIAG_E_INGRESS" },540	{ 0x32, "DDN_DIAG_W_INGRESS" },541	{ 0x33, "DDN_DIAG_C_INGRESS" },542	{ 0x34, "DDN_DIAG_CORE_SENT" },543	{ 0x35, "NDN_DIAG_N_OUT_OF_CRED" },544	{ 0x36, "NDN_DIAG_S_OUT_OF_CRED" },545	{ 0x37, "NDN_DIAG_E_OUT_OF_CRED" },546	{ 0x38, "NDN_DIAG_W_OUT_OF_CRED" },547	{ 0x39, "NDN_DIAG_C_OUT_OF_CRED" },548	{ 0x3a, "NDN_DIAG_N_EGRESS" },549	{ 0x3b, "NDN_DIAG_S_EGRESS" },550	{ 0x3c, "NDN_DIAG_E_EGRESS" },551	{ 0x3d, "NDN_DIAG_W_EGRESS" },552	{ 0x3e, "NDN_DIAG_C_EGRESS" },553	{ 0x3f, "NDN_DIAG_N_INGRESS" },554	{ 0x40, "NDN_DIAG_S_INGRESS" },555	{ 0x41, "NDN_DIAG_E_INGRESS" },556	{ 0x42, "NDN_DIAG_W_INGRESS" },557	{ 0x43, "NDN_DIAG_C_INGRESS" },558	{ 0x44, "NDN_DIAG_CORE_SENT" },559};560 561static const struct mlxbf_pmc_events mlxbf_pmc_l3c_events[] = {562	{ 0x00, "DISABLE" },563	{ 0x01, "CYCLES" },564	{ 0x02, "TOTAL_RD_REQ_IN" },565	{ 0x03, "TOTAL_WR_REQ_IN" },566	{ 0x04, "TOTAL_WR_DBID_ACK" },567	{ 0x05, "TOTAL_WR_DATA_IN" },568	{ 0x06, "TOTAL_WR_COMP" },569	{ 0x07, "TOTAL_RD_DATA_OUT" },570	{ 0x08, "TOTAL_CDN_REQ_IN_BANK0" },571	{ 0x09, "TOTAL_CDN_REQ_IN_BANK1" },572	{ 0x0a, "TOTAL_DDN_REQ_IN_BANK0" },573	{ 0x0b, "TOTAL_DDN_REQ_IN_BANK1" },574	{ 0x0c, "TOTAL_EMEM_RD_RES_IN_BANK0" },575	{ 0x0d, "TOTAL_EMEM_RD_RES_IN_BANK1" },576	{ 0x0e, "TOTAL_CACHE_RD_RES_IN_BANK0" },577	{ 0x0f, "TOTAL_CACHE_RD_RES_IN_BANK1" },578	{ 0x10, "TOTAL_EMEM_RD_REQ_BANK0" },579	{ 0x11, "TOTAL_EMEM_RD_REQ_BANK1" },580	{ 0x12, "TOTAL_EMEM_WR_REQ_BANK0" },581	{ 0x13, "TOTAL_EMEM_WR_REQ_BANK1" },582	{ 0x14, "TOTAL_RD_REQ_OUT" },583	{ 0x15, "TOTAL_WR_REQ_OUT" },584	{ 0x16, "TOTAL_RD_RES_IN" },585	{ 0x17, "HITS_BANK0" },586	{ 0x18, "HITS_BANK1" },587	{ 0x19, "MISSES_BANK0" },588	{ 0x1a, "MISSES_BANK1" },589	{ 0x1b, "ALLOCATIONS_BANK0" },590	{ 0x1c, "ALLOCATIONS_BANK1" },591	{ 0x1d, "EVICTIONS_BANK0" },592	{ 0x1e, "EVICTIONS_BANK1" },593	{ 0x1f, "DBID_REJECT" },594	{ 0x20, "WRDB_REJECT_BANK0" },595	{ 0x21, "WRDB_REJECT_BANK1" },596	{ 0x22, "CMDQ_REJECT_BANK0" },597	{ 0x23, "CMDQ_REJECT_BANK1" },598	{ 0x24, "COB_REJECT_BANK0" },599	{ 0x25, "COB_REJECT_BANK1" },600	{ 0x26, "TRB_REJECT_BANK0" },601	{ 0x27, "TRB_REJECT_BANK1" },602	{ 0x28, "TAG_REJECT_BANK0" },603	{ 0x29, "TAG_REJECT_BANK1" },604	{ 0x2a, "ANY_REJECT_BANK0" },605	{ 0x2b, "ANY_REJECT_BANK1" },606};607 608static const struct mlxbf_pmc_events mlxbf_pmc_llt_events[] = {609	{0, "HNF0_CYCLES"},610	{1, "HNF0_REQS_RECEIVED"},611	{2, "HNF0_REQS_PROCESSED"},612	{3, "HNF0_DIR_HIT"},613	{4, "HNF0_DIR_MISS"},614	{5, "HNF0_DIR_RD_ALLOC"},615	{6, "HNF0_DIR_WR_ALLOC"},616	{7, "HNF0_DIR_VICTIM"},617	{8, "HNF0_CL_HAZARD"},618	{9, "HNF0_ALL_HAZARD"},619	{10, "HNF0_PIPE_STALLS"},620	{11, "HNF0_MEM_READS"},621	{12, "HNF0_MEM_WRITES"},622	{13, "HNF0_MEM_ACCESS"},623	{14, "HNF0_DCL_READ"},624	{15, "HNF0_DCL_INVAL"},625	{16, "HNF0_CHI_RXDAT"},626	{17, "HNF0_CHI_RXRSP"},627	{18, "HNF0_CHI_TXDAT"},628	{19, "HNF0_CHI_TXRSP"},629	{20, "HNF0_CHI_TXSNP"},630	{21, "HNF0_DCT_SNP"},631	{22, "HNF0_SNP_FWD_DATA"},632	{23, "HNF0_SNP_FWD_RSP"},633	{24, "HNF0_SNP_RSP"},634	{25, "HNF0_EXCL_FULL"},635	{26, "HNF0_EXCL_WRITE_F"},636	{27, "HNF0_EXCL_WRITE_S"},637	{28, "HNF0_EXCL_WRITE"},638	{29, "HNF0_EXCL_READ"},639	{30, "HNF0_REQ_BUF_EMPTY"},640	{31, "HNF0_ALL_MAFS_BUSY"},641	{32, "HNF0_TXDAT_NO_LCRD"},642	{33, "HNF0_TXSNP_NO_LCRD"},643	{34, "HNF0_TXRSP_NO_LCRD"},644	{35, "HNF0_TXREQ_NO_LCRD"},645	{36, "HNF0_WRITE"},646	{37, "HNF0_READ"},647	{38, "HNF0_ACCESS"},648	{39, "HNF0_MAF_N_BUSY"},649	{40, "HNF0_MAF_N_REQS"},650	{41, "HNF0_SEL_OPCODE"},651	{42, "HNF1_CYCLES"},652	{43, "HNF1_REQS_RECEIVED"},653	{44, "HNF1_REQS_PROCESSED"},654	{45, "HNF1_DIR_HIT"},655	{46, "HNF1_DIR_MISS"},656	{47, "HNF1_DIR_RD_ALLOC"},657	{48, "HNF1_DIR_WR_ALLOC"},658	{49, "HNF1_DIR_VICTIM"},659	{50, "HNF1_CL_HAZARD"},660	{51, "HNF1_ALL_HAZARD"},661	{52, "HNF1_PIPE_STALLS"},662	{53, "HNF1_MEM_READS"},663	{54, "HNF1_MEM_WRITES"},664	{55, "HNF1_MEM_ACCESS"},665	{56, "HNF1_DCL_READ"},666	{57, "HNF1_DCL_INVAL"},667	{58, "HNF1_CHI_RXDAT"},668	{59, "HNF1_CHI_RXRSP"},669	{60, "HNF1_CHI_TXDAT"},670	{61, "HNF1_CHI_TXRSP"},671	{62, "HNF1_CHI_TXSNP"},672	{63, "HNF1_DCT_SNP"},673	{64, "HNF1_SNP_FWD_DATA"},674	{65, "HNF1_SNP_FWD_RSP"},675	{66, "HNF1_SNP_RSP"},676	{67, "HNF1_EXCL_FULL"},677	{68, "HNF1_EXCL_WRITE_F"},678	{69, "HNF1_EXCL_WRITE_S"},679	{70, "HNF1_EXCL_WRITE"},680	{71, "HNF1_EXCL_READ"},681	{72, "HNF1_REQ_BUF_EMPTY"},682	{73, "HNF1_ALL_MAFS_BUSY"},683	{74, "HNF1_TXDAT_NO_LCRD"},684	{75, "HNF1_TXSNP_NO_LCRD"},685	{76, "HNF1_TXRSP_NO_LCRD"},686	{77, "HNF1_TXREQ_NO_LCRD"},687	{78, "HNF1_WRITE"},688	{79, "HNF1_READ"},689	{80, "HNF1_ACCESS"},690	{81, "HNF1_MAF_N_BUSY"},691	{82, "HNF1_MAF_N_REQS"},692	{83, "HNF1_SEL_OPCODE"},693	{84, "GDC_BANK0_RD_REQ"},694	{85, "GDC_BANK0_WR_REQ"},695	{86, "GDC_BANK0_ALLOCATE"},696	{87, "GDC_BANK0_HIT"},697	{88, "GDC_BANK0_MISS"},698	{89, "GDC_BANK0_INVALIDATE"},699	{90, "GDC_BANK0_EVICT"},700	{91, "GDC_BANK0_RD_RESP"},701	{92, "GDC_BANK0_WR_ACK"},702	{93, "GDC_BANK0_SNOOP"},703	{94, "GDC_BANK0_SNOOP_NORMAL"},704	{95, "GDC_BANK0_SNOOP_FWD"},705	{96, "GDC_BANK0_SNOOP_STASH"},706	{97, "GDC_BANK0_SNOOP_STASH_INDPND_RD"},707	{98, "GDC_BANK0_FOLLOWER"},708	{99, "GDC_BANK0_FW"},709	{100, "GDC_BANK0_HIT_DCL_BOTH"},710	{101, "GDC_BANK0_HIT_DCL_PARTIAL"},711	{102, "GDC_BANK0_EVICT_DCL"},712	{103, "GDC_BANK0_G_RSE_PIPE_CACHE_DATA0"},713	{103, "GDC_BANK0_G_RSE_PIPE_CACHE_DATA1"},714	{105, "GDC_BANK0_ARB_STRB"},715	{106, "GDC_BANK0_ARB_WAIT"},716	{107, "GDC_BANK0_GGA_STRB"},717	{108, "GDC_BANK0_GGA_WAIT"},718	{109, "GDC_BANK0_FW_STRB"},719	{110, "GDC_BANK0_FW_WAIT"},720	{111, "GDC_BANK0_SNP_STRB"},721	{112, "GDC_BANK0_SNP_WAIT"},722	{113, "GDC_BANK0_MISS_INARB_STRB"},723	{114, "GDC_BANK0_MISS_INARB_WAIT"},724	{115, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD0"},725	{116, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD1"},726	{117, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD2"},727	{118, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD3"},728	{119, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR0"},729	{120, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR1"},730	{121, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR2"},731	{122, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR3"},732	{123, "GDC_BANK1_RD_REQ"},733	{124, "GDC_BANK1_WR_REQ"},734	{125, "GDC_BANK1_ALLOCATE"},735	{126, "GDC_BANK1_HIT"},736	{127, "GDC_BANK1_MISS"},737	{128, "GDC_BANK1_INVALIDATE"},738	{129, "GDC_BANK1_EVICT"},739	{130, "GDC_BANK1_RD_RESP"},740	{131, "GDC_BANK1_WR_ACK"},741	{132, "GDC_BANK1_SNOOP"},742	{133, "GDC_BANK1_SNOOP_NORMAL"},743	{134, "GDC_BANK1_SNOOP_FWD"},744	{135, "GDC_BANK1_SNOOP_STASH"},745	{136, "GDC_BANK1_SNOOP_STASH_INDPND_RD"},746	{137, "GDC_BANK1_FOLLOWER"},747	{138, "GDC_BANK1_FW"},748	{139, "GDC_BANK1_HIT_DCL_BOTH"},749	{140, "GDC_BANK1_HIT_DCL_PARTIAL"},750	{141, "GDC_BANK1_EVICT_DCL"},751	{142, "GDC_BANK1_G_RSE_PIPE_CACHE_DATA0"},752	{143, "GDC_BANK1_G_RSE_PIPE_CACHE_DATA1"},753	{144, "GDC_BANK1_ARB_STRB"},754	{145, "GDC_BANK1_ARB_WAIT"},755	{146, "GDC_BANK1_GGA_STRB"},756	{147, "GDC_BANK1_GGA_WAIT"},757	{148, "GDC_BANK1_FW_STRB"},758	{149, "GDC_BANK1_FW_WAIT"},759	{150, "GDC_BANK1_SNP_STRB"},760	{151, "GDC_BANK1_SNP_WAIT"},761	{152, "GDC_BANK1_MISS_INARB_STRB"},762	{153, "GDC_BANK1_MISS_INARB_WAIT"},763	{154, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD0"},764	{155, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD1"},765	{156, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD2"},766	{157, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD3"},767	{158, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR0"},768	{159, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR1"},769	{160, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR2"},770	{161, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR3"},771	{162, "HISTOGRAM_HISTOGRAM_BIN0"},772	{163, "HISTOGRAM_HISTOGRAM_BIN1"},773	{164, "HISTOGRAM_HISTOGRAM_BIN2"},774	{165, "HISTOGRAM_HISTOGRAM_BIN3"},775	{166, "HISTOGRAM_HISTOGRAM_BIN4"},776	{167, "HISTOGRAM_HISTOGRAM_BIN5"},777	{168, "HISTOGRAM_HISTOGRAM_BIN6"},778	{169, "HISTOGRAM_HISTOGRAM_BIN7"},779	{170, "HISTOGRAM_HISTOGRAM_BIN8"},780	{171, "HISTOGRAM_HISTOGRAM_BIN9"},781};782 783static const struct mlxbf_pmc_events mlxbf_pmc_llt_miss_events[] = {784	{0, "GDC_MISS_MACHINE_RD_REQ"},785	{1, "GDC_MISS_MACHINE_WR_REQ"},786	{2, "GDC_MISS_MACHINE_SNP_REQ"},787	{3, "GDC_MISS_MACHINE_EVICT_REQ"},788	{4, "GDC_MISS_MACHINE_FW_REQ"},789	{5, "GDC_MISS_MACHINE_RD_RESP"},790	{6, "GDC_MISS_MACHINE_WR_RESP"},791	{7, "GDC_MISS_MACHINE_SNP_STASH_DATAPULL_DROP"},792	{8, "GDC_MISS_MACHINE_SNP_STASH_DATAPULL_DROP_TXDAT"},793	{9, "GDC_MISS_MACHINE_CHI_TXREQ"},794	{10, "GDC_MISS_MACHINE_CHI_RXRSP"},795	{11, "GDC_MISS_MACHINE_CHI_TXDAT"},796	{12, "GDC_MISS_MACHINE_CHI_RXDAT"},797	{13, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_0"},798	{14, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_1 "},799	{15, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_2"},800	{16, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_3 "},801	{17, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_0 "},802	{18, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_1 "},803	{19, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_2 "},804	{20, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_3 "},805	{21, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_0"},806	{22, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_1"},807	{23, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_2"},808	{24, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_3"},809	{25, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_0 "},810	{26, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_1"},811	{27, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_2"},812	{28, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_3"},813	{29, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_0"},814	{30, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_1"},815	{31, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_2"},816	{32, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_3"},817	{33, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_4"},818	{34, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_5"},819	{35, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_6"},820	{36, "GDC_MISS_MACHINE_G_RSE_PIPE_TXREQ_0"},821	{37, "GDC_MISS_MACHINE_G_RSE_PIPE_TXREQ_1"},822	{38, "GDC_MISS_MACHINE_G_CREDIT_TXREQ_0"},823	{39, "GDC_MISS_MACHINE_G_CREDIT_TXREQ_1"},824	{40, "GDC_MISS_MACHINE_G_RSE_PIPE_TXDAT_0"},825	{41, "GDC_MISS_MACHINE_G_RSE_PIPE_TXDAT_1"},826	{42, "GDC_MISS_MACHINE_G_CREDIT_TXDAT_0"},827	{43, "GDC_MISS_MACHINE_G_CREDIT_TXDAT_1"},828	{44, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_0"},829	{45, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_1"},830	{46, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_2"},831	{47, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_3"},832	{48, "GDC_MISS_MACHINE_G_RSE_PIPE_TXRSP_0"},833	{49, "GDC_MISS_MACHINE_G_RSE_PIPE_TXRSP_1"},834	{50, "GDC_MISS_MACHINE_G_CREDIT_TXRSP_0"},835	{51, "GDC_MISS_MACHINE_G_CREDIT_TXRSP_1"},836	{52, "GDC_MISS_MACHINE_G_RSE_PIPE_INARB_0"},837	{53, "GDC_MISS_MACHINE_G_RSE_PIPE_INARB_1"},838	{54, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_0"},839	{55, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_1"},840	{56, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_2"},841	{57, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_3"},842	{58, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_0"},843	{59, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_1"},844	{60, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_2"},845	{61, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_3"},846	{62, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_4"},847	{63, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_5"},848	{64, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_6"},849	{65, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_7"},850	{66, "HISTOGRAM_HISTOGRAM_BIN0"},851	{67, "HISTOGRAM_HISTOGRAM_BIN1"},852	{68, "HISTOGRAM_HISTOGRAM_BIN2"},853	{69, "HISTOGRAM_HISTOGRAM_BIN3"},854	{70, "HISTOGRAM_HISTOGRAM_BIN4"},855	{71, "HISTOGRAM_HISTOGRAM_BIN5"},856	{72, "HISTOGRAM_HISTOGRAM_BIN6"},857	{73, "HISTOGRAM_HISTOGRAM_BIN7"},858	{74, "HISTOGRAM_HISTOGRAM_BIN8"},859	{75, "HISTOGRAM_HISTOGRAM_BIN9"},860};861 862static struct mlxbf_pmc_context *pmc;863 864/* UUID used to probe ATF service. */865static const char *mlxbf_pmc_svc_uuid_str = "89c036b4-e7d7-11e6-8797-001aca00bfc4";866 867/* Calls an SMC to access a performance register */868static int mlxbf_pmc_secure_read(void __iomem *addr, u32 command, u64 *result)869{870	struct arm_smccc_res res;871	int status, err = 0;872 873	arm_smccc_smc(command, pmc->sreg_tbl_perf, (uintptr_t)addr, 0, 0, 0, 0,874		      0, &res);875 876	status = res.a0;877 878	switch (status) {879	case PSCI_RET_NOT_SUPPORTED:880		err = -EINVAL;881		break;882	case MLXBF_PMC_SMCCC_ACCESS_VIOLATION:883		err = -EACCES;884		break;885	default:886		*result = res.a1;887		break;888	}889 890	return err;891}892 893/* Read from a performance counter */894static int mlxbf_pmc_read(void __iomem *addr, u32 command, u64 *result)895{896	if (pmc->svc_sreg_support)897		return mlxbf_pmc_secure_read(addr, command, result);898 899	if (command == MLXBF_PMC_READ_REG_32)900		*result = readl(addr);901	else902		*result = readq(addr);903 904	return 0;905}906 907/* Convenience function for 32-bit reads */908static int mlxbf_pmc_readl(void __iomem *addr, u32 *result)909{910	u64 read_out;911	int status;912 913	status = mlxbf_pmc_read(addr, MLXBF_PMC_READ_REG_32, &read_out);914	if (status)915		return status;916	*result = (u32)read_out;917 918	return 0;919}920 921/* Calls an SMC to access a performance register */922static int mlxbf_pmc_secure_write(void __iomem *addr, u32 command, u64 value)923{924	struct arm_smccc_res res;925	int status, err = 0;926 927	arm_smccc_smc(command, pmc->sreg_tbl_perf, value, (uintptr_t)addr, 0, 0,928		      0, 0, &res);929 930	status = res.a0;931 932	switch (status) {933	case PSCI_RET_NOT_SUPPORTED:934		err = -EINVAL;935		break;936	case MLXBF_PMC_SMCCC_ACCESS_VIOLATION:937		err = -EACCES;938		break;939	}940 941	return err;942}943 944/* Write to a performance counter */945static int mlxbf_pmc_write(void __iomem *addr, int command, u64 value)946{947	if (pmc->svc_sreg_support)948		return mlxbf_pmc_secure_write(addr, command, value);949 950	if (command == MLXBF_PMC_WRITE_REG_32)951		writel(value, addr);952	else953		writeq(value, addr);954 955	return 0;956}957 958/* Check if the register offset is within the mapped region for the block */959static bool mlxbf_pmc_valid_range(unsigned int blk_num, u32 offset)960{961	if ((offset >= 0) && !(offset % MLXBF_PMC_REG_SIZE) &&962	    (offset + MLXBF_PMC_REG_SIZE <= pmc->block[blk_num].blk_size))963		return true; /* inside the mapped PMC space */964 965	return false;966}967 968/* Get the event list corresponding to a certain block */969static const struct mlxbf_pmc_events *mlxbf_pmc_event_list(const char *blk, size_t *psize)970{971	const struct mlxbf_pmc_events *events;972	size_t size;973 974	if (strstr(blk, "tilenet")) {975		events = mlxbf_pmc_hnfnet_events;976		size = ARRAY_SIZE(mlxbf_pmc_hnfnet_events);977	} else if (strstr(blk, "tile")) {978		events = mlxbf_pmc_hnf_events;979		size = ARRAY_SIZE(mlxbf_pmc_hnf_events);980	} else if (strstr(blk, "triogen")) {981		events = mlxbf_pmc_smgen_events;982		size = ARRAY_SIZE(mlxbf_pmc_smgen_events);983	} else if (strstr(blk, "trio")) {984		switch (pmc->event_set) {985		case MLXBF_PMC_EVENT_SET_BF1:986			events = mlxbf_pmc_trio_events_1;987			size = ARRAY_SIZE(mlxbf_pmc_trio_events_1);988			break;989		case MLXBF_PMC_EVENT_SET_BF2:990			events = mlxbf_pmc_trio_events_2;991			size = ARRAY_SIZE(mlxbf_pmc_trio_events_2);992			break;993		default:994			events = NULL;995			size = 0;996			break;997		}998	} else if (strstr(blk, "mss")) {999		switch (pmc->event_set) {1000		case MLXBF_PMC_EVENT_SET_BF1:1001		case MLXBF_PMC_EVENT_SET_BF2:1002			events = mlxbf_pmc_mss_events_1;1003			size = ARRAY_SIZE(mlxbf_pmc_mss_events_1);1004			break;1005		case MLXBF_PMC_EVENT_SET_BF3:1006			events = mlxbf_pmc_mss_events_3;1007			size = ARRAY_SIZE(mlxbf_pmc_mss_events_3);1008			break;1009		default:1010			events = NULL;1011			size = 0;1012			break;1013		}1014	} else if (strstr(blk, "ecc")) {1015		events = mlxbf_pmc_ecc_events;1016		size = ARRAY_SIZE(mlxbf_pmc_ecc_events);1017	} else if (strstr(blk, "pcie")) {1018		events = mlxbf_pmc_pcie_events;1019		size = ARRAY_SIZE(mlxbf_pmc_pcie_events);1020	} else if (strstr(blk, "l3cache")) {1021		events = mlxbf_pmc_l3c_events;1022		size = ARRAY_SIZE(mlxbf_pmc_l3c_events);1023	} else if (strstr(blk, "gic")) {1024		events = mlxbf_pmc_smgen_events;1025		size = ARRAY_SIZE(mlxbf_pmc_smgen_events);1026	} else if (strstr(blk, "smmu")) {1027		events = mlxbf_pmc_smgen_events;1028		size = ARRAY_SIZE(mlxbf_pmc_smgen_events);1029	} else if (strstr(blk, "llt_miss")) {1030		events = mlxbf_pmc_llt_miss_events;1031		size = ARRAY_SIZE(mlxbf_pmc_llt_miss_events);1032	} else if (strstr(blk, "llt")) {1033		events = mlxbf_pmc_llt_events;1034		size = ARRAY_SIZE(mlxbf_pmc_llt_events);1035	} else {1036		events = NULL;1037		size = 0;1038	}1039 1040	if (psize)1041		*psize = size;1042 1043	return events;1044}1045 1046static bool mlxbf_pmc_event_supported(const char *blk)1047{1048	return !!mlxbf_pmc_event_list(blk, NULL);1049}1050 1051/* Get the event number given the name */1052static int mlxbf_pmc_get_event_num(const char *blk, const char *evt)1053{1054	const struct mlxbf_pmc_events *events;1055	unsigned int i;1056	size_t size;1057 1058	events = mlxbf_pmc_event_list(blk, &size);1059	if (!events)1060		return -EINVAL;1061 1062	for (i = 0; i < size; ++i) {1063		if (!strcmp(evt, events[i].evt_name))1064			return events[i].evt_num;1065	}1066 1067	return -ENODEV;1068}1069 1070/* Get the event number given the name */1071static char *mlxbf_pmc_get_event_name(const char *blk, u32 evt)1072{1073	const struct mlxbf_pmc_events *events;1074	unsigned int i;1075	size_t size;1076 1077	events = mlxbf_pmc_event_list(blk, &size);1078	if (!events)1079		return NULL;1080 1081	for (i = 0; i < size; ++i) {1082		if (evt == events[i].evt_num)1083			return events[i].evt_name;1084	}1085 1086	return NULL;1087}1088 1089/* Method to enable/disable/reset l3cache counters */1090static int mlxbf_pmc_config_l3_counters(unsigned int blk_num, bool enable, bool reset)1091{1092	u32 perfcnt_cfg = 0;1093 1094	if (enable)1095		perfcnt_cfg |= MLXBF_PMC_L3C_PERF_CNT_CFG_EN;1096	if (reset)1097		perfcnt_cfg |= MLXBF_PMC_L3C_PERF_CNT_CFG_RST;1098 1099	return mlxbf_pmc_write(pmc->block[blk_num].mmio_base +1100				       MLXBF_PMC_L3C_PERF_CNT_CFG,1101			       MLXBF_PMC_WRITE_REG_32, perfcnt_cfg);1102}1103 1104/* Method to handle l3cache counter programming */1105static int mlxbf_pmc_program_l3_counter(unsigned int blk_num, u32 cnt_num, u32 evt)1106{1107	u32 perfcnt_sel_1 = 0, perfcnt_sel = 0, *wordaddr;1108	void __iomem *pmcaddr;1109	int ret;1110 1111	/* Disable all counters before programming them */1112	if (mlxbf_pmc_config_l3_counters(blk_num, false, false))1113		return -EINVAL;1114 1115	/* Select appropriate register information */1116	switch (cnt_num) {1117	case 0 ... 3:1118		pmcaddr = pmc->block[blk_num].mmio_base +1119			  MLXBF_PMC_L3C_PERF_CNT_SEL;1120		wordaddr = &perfcnt_sel;1121		break;1122	case 4:1123		pmcaddr = pmc->block[blk_num].mmio_base +1124			  MLXBF_PMC_L3C_PERF_CNT_SEL_1;1125		wordaddr = &perfcnt_sel_1;1126		break;1127	default:1128		return -EINVAL;1129	}1130 1131	ret = mlxbf_pmc_readl(pmcaddr, wordaddr);1132	if (ret)1133		return ret;1134 1135	switch (cnt_num) {1136	case 0:1137		perfcnt_sel &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_0;1138		perfcnt_sel |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_0,1139					  evt);1140		break;1141	case 1:1142		perfcnt_sel &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_1;1143		perfcnt_sel |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_1,1144					  evt);1145		break;1146	case 2:1147		perfcnt_sel &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_2;1148		perfcnt_sel |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_2,1149					  evt);1150		break;1151	case 3:1152		perfcnt_sel &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_3;1153		perfcnt_sel |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_3,1154					  evt);1155		break;1156	case 4:1157		perfcnt_sel_1 &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_1_CNT_4;1158		perfcnt_sel_1 |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_1_CNT_4,1159					    evt);1160		break;1161	default:1162		return -EINVAL;1163	}1164 1165	return mlxbf_pmc_write(pmcaddr, MLXBF_PMC_WRITE_REG_32, *wordaddr);1166}1167 1168/* Method to handle crspace counter programming */1169static int mlxbf_pmc_program_crspace_counter(unsigned int blk_num, u32 cnt_num, u32 evt)1170{1171	void *addr;1172	u32 word;1173	int ret;1174 1175	addr = pmc->block[blk_num].mmio_base +1176		((cnt_num / 2) * MLXBF_PMC_CRSPACE_PERFSEL_SZ);1177	ret = mlxbf_pmc_readl(addr, &word);1178	if (ret)1179		return ret;1180 1181	if (cnt_num % 2) {1182		word &= ~MLXBF_PMC_CRSPACE_PERFSEL1;1183		word |= FIELD_PREP(MLXBF_PMC_CRSPACE_PERFSEL1, evt);1184	} else {1185		word &= ~MLXBF_PMC_CRSPACE_PERFSEL0;1186		word |= FIELD_PREP(MLXBF_PMC_CRSPACE_PERFSEL0, evt);1187	}1188 1189	return mlxbf_pmc_write(addr, MLXBF_PMC_WRITE_REG_32, word);1190}1191 1192/* Method to clear crspace counter value */1193static int mlxbf_pmc_clear_crspace_counter(unsigned int blk_num, u32 cnt_num)1194{1195	void *addr;1196 1197	addr = pmc->block[blk_num].mmio_base +1198		MLXBF_PMC_CRSPACE_PERFMON_VAL0(pmc->block[blk_num].counters) +1199		(cnt_num * 4);1200 1201	return mlxbf_pmc_write(addr, MLXBF_PMC_WRITE_REG_32, 0x0);1202}1203 1204/* Method to program a counter to monitor an event */1205static int mlxbf_pmc_program_counter(unsigned int blk_num, u32 cnt_num, u32 evt, bool is_l3)1206{1207	u64 perfctl, perfevt, perfmon_cfg;1208 1209	if (cnt_num >= pmc->block[blk_num].counters)1210		return -ENODEV;1211 1212	if (is_l3)1213		return mlxbf_pmc_program_l3_counter(blk_num, cnt_num, evt);1214 1215	if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE)1216		return mlxbf_pmc_program_crspace_counter(blk_num, cnt_num,1217							 evt);1218 1219	/* Configure the counter */1220	perfctl = FIELD_PREP(MLXBF_PMC_PERFCTL_EN0, 1);1221	perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_EB0, 0);1222	perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_ETRIG0, 1);1223	perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_AD0, 0);1224	perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_ACCM0, 0);1225	perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_MS0, 0);1226	perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_FM0, 0);1227 1228	perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WDATA, perfctl);1229	perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR,1230				  MLXBF_PMC_PERFCTL);1231	perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1);1232	perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 1);1233 1234	if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base +1235				    cnt_num * MLXBF_PMC_REG_SIZE,1236			    MLXBF_PMC_WRITE_REG_64, perfmon_cfg))1237		return -EFAULT;1238 1239	/* Select the event */1240	perfevt = FIELD_PREP(MLXBF_PMC_PERFEVT_EVTSEL, evt);1241 1242	perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WDATA, perfevt);1243	perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR,1244				  MLXBF_PMC_PERFEVT);1245	perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1);1246	perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 1);1247 1248	if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base +1249				    cnt_num * MLXBF_PMC_REG_SIZE,1250			    MLXBF_PMC_WRITE_REG_64, perfmon_cfg))1251		return -EFAULT;1252 1253	/* Clear the accumulator */1254	perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR,1255				 MLXBF_PMC_PERFACC0);1256	perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1);1257	perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 1);1258 1259	if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base +1260				    cnt_num * MLXBF_PMC_REG_SIZE,1261			    MLXBF_PMC_WRITE_REG_64, perfmon_cfg))1262		return -EFAULT;1263 1264	return 0;1265}1266 1267/* Method to handle l3 counter reads */1268static int mlxbf_pmc_read_l3_counter(unsigned int blk_num, u32 cnt_num, u64 *result)1269{1270	u32 perfcnt_low = 0, perfcnt_high = 0;1271	int status;1272	u64 value;1273 1274	status = mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +1275					 MLXBF_PMC_L3C_PERF_CNT_LOW +1276					 cnt_num * MLXBF_PMC_L3C_REG_SIZE,1277				 &perfcnt_low);1278 1279	if (status)1280		return status;1281 1282	status = mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +1283					 MLXBF_PMC_L3C_PERF_CNT_HIGH +1284					 cnt_num * MLXBF_PMC_L3C_REG_SIZE,1285				 &perfcnt_high);1286 1287	if (status)1288		return status;1289 1290	value = perfcnt_high;1291	value = value << 32;1292	value |= perfcnt_low;1293	*result = value;1294 1295	return 0;1296}1297 1298/* Method to handle crspace counter reads */1299static int mlxbf_pmc_read_crspace_counter(unsigned int blk_num, u32 cnt_num, u64 *result)1300{1301	int status = 0;1302	u32 value;1303 1304	status = mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +1305		MLXBF_PMC_CRSPACE_PERFMON_VAL0(pmc->block[blk_num].counters) +1306		(cnt_num * 4), &value);1307	if (status)1308		return status;1309 1310	*result = value;1311 1312	return 0;1313}1314 1315/* Method to read the counter value */1316static int mlxbf_pmc_read_counter(unsigned int blk_num, u32 cnt_num, bool is_l3, u64 *result)1317{1318	u32 perfcfg_offset, perfval_offset;1319	u64 perfmon_cfg;1320	int status;1321 1322	if (cnt_num >= pmc->block[blk_num].counters)1323		return -EINVAL;1324 1325	if (is_l3)1326		return mlxbf_pmc_read_l3_counter(blk_num, cnt_num, result);1327 1328	if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE)1329		return mlxbf_pmc_read_crspace_counter(blk_num, cnt_num, result);1330 1331	perfcfg_offset = cnt_num * MLXBF_PMC_REG_SIZE;1332	perfval_offset = perfcfg_offset +1333			 pmc->block[blk_num].counters * MLXBF_PMC_REG_SIZE;1334 1335	/* Set counter in "read" mode */1336	perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR,1337				 MLXBF_PMC_PERFACC0);1338	perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1);1339	perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 0);1340 1341	status = mlxbf_pmc_write(pmc->block[blk_num].mmio_base + perfcfg_offset,1342				 MLXBF_PMC_WRITE_REG_64, perfmon_cfg);1343 1344	if (status)1345		return status;1346 1347	/* Get the counter value */1348	return mlxbf_pmc_read(pmc->block[blk_num].mmio_base + perfval_offset,1349			      MLXBF_PMC_READ_REG_64, result);1350}1351 1352/* Method to read L3 block event */1353static int mlxbf_pmc_read_l3_event(unsigned int blk_num, u32 cnt_num, u64 *result)1354{1355	u32 perfcnt_sel = 0, perfcnt_sel_1 = 0, *wordaddr;1356	void __iomem *pmcaddr;1357	u64 evt;1358 1359	/* Select appropriate register information */1360	switch (cnt_num) {1361	case 0 ... 3:1362		pmcaddr = pmc->block[blk_num].mmio_base +1363			  MLXBF_PMC_L3C_PERF_CNT_SEL;1364		wordaddr = &perfcnt_sel;1365		break;1366	case 4:1367		pmcaddr = pmc->block[blk_num].mmio_base +1368			  MLXBF_PMC_L3C_PERF_CNT_SEL_1;1369		wordaddr = &perfcnt_sel_1;1370		break;1371	default:1372		return -EINVAL;1373	}1374 1375	if (mlxbf_pmc_readl(pmcaddr, wordaddr))1376		return -EINVAL;1377 1378	/* Read from appropriate register field for the counter */1379	switch (cnt_num) {1380	case 0:1381		evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_0, perfcnt_sel);1382		break;1383	case 1:1384		evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_1, perfcnt_sel);1385		break;1386	case 2:1387		evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_2, perfcnt_sel);1388		break;1389	case 3:1390		evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_3, perfcnt_sel);1391		break;1392	case 4:1393		evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_1_CNT_4,1394				perfcnt_sel_1);1395		break;1396	default:1397		return -EINVAL;1398	}1399	*result = evt;1400 1401	return 0;1402}1403 1404/* Method to read crspace block event */1405static int mlxbf_pmc_read_crspace_event(unsigned int blk_num, u32 cnt_num, u64 *result)1406{1407	u32 word, evt;1408	void *addr;1409	int ret;1410 1411	addr = pmc->block[blk_num].mmio_base +1412		((cnt_num / 2) * MLXBF_PMC_CRSPACE_PERFSEL_SZ);1413	ret = mlxbf_pmc_readl(addr, &word);1414	if (ret)1415		return ret;1416 1417	if (cnt_num % 2)1418		evt = FIELD_GET(MLXBF_PMC_CRSPACE_PERFSEL1, word);1419	else1420		evt = FIELD_GET(MLXBF_PMC_CRSPACE_PERFSEL0, word);1421 1422	*result = evt;1423 1424	return 0;1425}1426 1427/* Method to find the event currently being monitored by a counter */1428static int mlxbf_pmc_read_event(unsigned int blk_num, u32 cnt_num, bool is_l3, u64 *result)1429{1430	u32 perfcfg_offset, perfval_offset;1431	u64 perfmon_cfg, perfevt;1432 1433	if (cnt_num >= pmc->block[blk_num].counters)1434		return -EINVAL;1435 1436	if (is_l3)1437		return mlxbf_pmc_read_l3_event(blk_num, cnt_num, result);1438 1439	if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE)1440		return mlxbf_pmc_read_crspace_event(blk_num, cnt_num, result);1441 1442	perfcfg_offset = cnt_num * MLXBF_PMC_REG_SIZE;1443	perfval_offset = perfcfg_offset +1444			 pmc->block[blk_num].counters * MLXBF_PMC_REG_SIZE;1445 1446	/* Set counter in "read" mode */1447	perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR,1448				 MLXBF_PMC_PERFEVT);1449	perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1);1450	perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 0);1451 1452	if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base + perfcfg_offset,1453			    MLXBF_PMC_WRITE_REG_64, perfmon_cfg))1454		return -EFAULT;1455 1456	/* Get the event number */1457	if (mlxbf_pmc_read(pmc->block[blk_num].mmio_base + perfval_offset,1458			   MLXBF_PMC_READ_REG_64, &perfevt))1459		return -EFAULT;1460 1461	*result = FIELD_GET(MLXBF_PMC_PERFEVT_EVTSEL, perfevt);1462 1463	return 0;1464}1465 1466/* Method to read a register */1467static int mlxbf_pmc_read_reg(unsigned int blk_num, u32 offset, u64 *result)1468{1469	u32 ecc_out;1470 1471	if (strstr(pmc->block_name[blk_num], "ecc")) {1472		if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + offset,1473				    &ecc_out))1474			return -EFAULT;1475 1476		*result = ecc_out;1477		return 0;1478	}1479 1480	if (mlxbf_pmc_valid_range(blk_num, offset))1481		return mlxbf_pmc_read(pmc->block[blk_num].mmio_base + offset,1482				      MLXBF_PMC_READ_REG_64, result);1483 1484	return -EINVAL;1485}1486 1487/* Method to write to a register */1488static int mlxbf_pmc_write_reg(unsigned int blk_num, u32 offset, u64 data)1489{1490	if (strstr(pmc->block_name[blk_num], "ecc")) {1491		return mlxbf_pmc_write(pmc->block[blk_num].mmio_base + offset,1492				       MLXBF_PMC_WRITE_REG_32, data);1493	}1494 1495	if (mlxbf_pmc_valid_range(blk_num, offset))1496		return mlxbf_pmc_write(pmc->block[blk_num].mmio_base + offset,1497				       MLXBF_PMC_WRITE_REG_64, data);1498 1499	return -EINVAL;1500}1501 1502/* Show function for "counter" sysfs files */1503static ssize_t mlxbf_pmc_counter_show(struct device *dev,1504				      struct device_attribute *attr, char *buf)1505{1506	struct mlxbf_pmc_attribute *attr_counter = container_of(1507		attr, struct mlxbf_pmc_attribute, dev_attr);1508	unsigned int blk_num, cnt_num;1509	bool is_l3 = false;1510	int offset;1511	u64 value;1512 1513	blk_num = attr_counter->nr;1514	cnt_num = attr_counter->index;1515 1516	if (strstr(pmc->block_name[blk_num], "l3cache"))1517		is_l3 = true;1518 1519	if ((pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER) ||1520	    (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE)) {1521		if (mlxbf_pmc_read_counter(blk_num, cnt_num, is_l3, &value))1522			return -EINVAL;1523	} else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_REGISTER) {1524		offset = mlxbf_pmc_get_event_num(pmc->block_name[blk_num],1525						 attr->attr.name);1526		if (offset < 0)1527			return -EINVAL;1528		if (mlxbf_pmc_read_reg(blk_num, offset, &value))1529			return -EINVAL;1530	} else1531		return -EINVAL;1532 1533	return sysfs_emit(buf, "0x%llx\n", value);1534}1535 1536/* Store function for "counter" sysfs files */1537static ssize_t mlxbf_pmc_counter_store(struct device *dev,1538				       struct device_attribute *attr,1539				       const char *buf, size_t count)1540{1541	struct mlxbf_pmc_attribute *attr_counter = container_of(1542		attr, struct mlxbf_pmc_attribute, dev_attr);1543	unsigned int blk_num, cnt_num, data;1544	bool is_l3 = false;1545	u64 evt_num;1546	int offset;1547	int err;1548 1549	blk_num = attr_counter->nr;1550	cnt_num = attr_counter->index;1551 1552	err = kstrtouint(buf, 0, &data);1553	if (err < 0)1554		return err;1555 1556	/* Allow non-zero writes only to the ecc regs */1557	if (!(strstr(pmc->block_name[blk_num], "ecc")) && data)1558		return -EINVAL;1559 1560	/* Do not allow writes to the L3C regs */1561	if (strstr(pmc->block_name[blk_num], "l3cache"))1562		return -EINVAL;1563 1564	if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER) {1565		err = mlxbf_pmc_read_event(blk_num, cnt_num, is_l3, &evt_num);1566		if (err)1567			return err;1568		err = mlxbf_pmc_program_counter(blk_num, cnt_num, evt_num,1569						is_l3);1570		if (err)1571			return err;1572	} else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_REGISTER) {1573		offset = mlxbf_pmc_get_event_num(pmc->block_name[blk_num],1574						 attr->attr.name);1575		if (offset < 0)1576			return -EINVAL;1577		err = mlxbf_pmc_write_reg(blk_num, offset, data);1578		if (err)1579			return err;1580	} else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) {1581		if (sscanf(attr->attr.name, "counter%u", &cnt_num) != 1)1582			return -EINVAL;1583		err = mlxbf_pmc_clear_crspace_counter(blk_num, cnt_num);1584	} else1585		return -EINVAL;1586 1587	return count;1588}1589 1590/* Show function for "event" sysfs files */1591static ssize_t mlxbf_pmc_event_show(struct device *dev,1592				    struct device_attribute *attr, char *buf)1593{1594	struct mlxbf_pmc_attribute *attr_event = container_of(1595		attr, struct mlxbf_pmc_attribute, dev_attr);1596	unsigned int blk_num, cnt_num;1597	bool is_l3 = false;1598	char *evt_name;1599	u64 evt_num;1600	int err;1601 1602	blk_num = attr_event->nr;1603	cnt_num = attr_event->index;1604 1605	if (strstr(pmc->block_name[blk_num], "l3cache"))1606		is_l3 = true;1607 1608	err = mlxbf_pmc_read_event(blk_num, cnt_num, is_l3, &evt_num);1609	if (err)1610		return sysfs_emit(buf, "No event being monitored\n");1611 1612	evt_name = mlxbf_pmc_get_event_name(pmc->block_name[blk_num], evt_num);1613	if (!evt_name)1614		return -EINVAL;1615 1616	return sysfs_emit(buf, "0x%llx: %s\n", evt_num, evt_name);1617}1618 1619/* Store function for "event" sysfs files */1620static ssize_t mlxbf_pmc_event_store(struct device *dev,1621				     struct device_attribute *attr,1622				     const char *buf, size_t count)1623{1624	struct mlxbf_pmc_attribute *attr_event = container_of(1625		attr, struct mlxbf_pmc_attribute, dev_attr);1626	unsigned int blk_num, cnt_num;1627	bool is_l3 = false;1628	int evt_num;1629	int err;1630 1631	blk_num = attr_event->nr;1632	cnt_num = attr_event->index;1633 1634	if (isalpha(buf[0])) {1635		evt_num = mlxbf_pmc_get_event_num(pmc->block_name[blk_num],1636						  buf);1637		if (evt_num < 0)1638			return -EINVAL;1639	} else {1640		err = kstrtouint(buf, 0, &evt_num);1641		if (err < 0)1642			return err;1643	}1644 1645	if (strstr(pmc->block_name[blk_num], "l3cache"))1646		is_l3 = true;1647 1648	err = mlxbf_pmc_program_counter(blk_num, cnt_num, evt_num, is_l3);1649	if (err)1650		return err;1651 1652	return count;1653}1654 1655/* Show function for "event_list" sysfs files */1656static ssize_t mlxbf_pmc_event_list_show(struct device *dev,1657					 struct device_attribute *attr,1658					 char *buf)1659{1660	struct mlxbf_pmc_attribute *attr_event_list = container_of(1661		attr, struct mlxbf_pmc_attribute, dev_attr);1662	const struct mlxbf_pmc_events *events;1663	char e_info[MLXBF_PMC_EVENT_INFO_LEN];1664	unsigned int blk_num, i, len = 0;1665	size_t size;1666	int ret = 0;1667 1668	blk_num = attr_event_list->nr;1669 1670	events = mlxbf_pmc_event_list(pmc->block_name[blk_num], &size);1671	if (!events)1672		return -EINVAL;1673 1674	for (i = 0, buf[0] = '\0'; i < size; ++i) {1675		len += snprintf(e_info, sizeof(e_info), "0x%x: %s\n",1676				events[i].evt_num, events[i].evt_name);1677		if (len >= PAGE_SIZE)1678			break;1679		strcat(buf, e_info);1680		ret = len;1681	}1682 1683	return ret;1684}1685 1686/* Show function for "enable" sysfs files - only for l3cache & crspace */1687static ssize_t mlxbf_pmc_enable_show(struct device *dev,1688				     struct device_attribute *attr, char *buf)1689{1690	struct mlxbf_pmc_attribute *attr_enable = container_of(1691		attr, struct mlxbf_pmc_attribute, dev_attr);1692	unsigned int blk_num, value;1693	u32 perfcnt_cfg, word;1694 1695	blk_num = attr_enable->nr;1696 1697	if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) {1698		if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +1699				MLXBF_PMC_CRSPACE_PERFMON_CTL(pmc->block[blk_num].counters),1700				&word))1701			return -EINVAL;1702 1703		value = FIELD_GET(MLXBF_PMC_CRSPACE_PERFMON_EN, word);1704	} else {1705		if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +1706					    MLXBF_PMC_L3C_PERF_CNT_CFG,1707				    &perfcnt_cfg))1708			return -EINVAL;1709 1710		value = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_CFG_EN, perfcnt_cfg);1711	}1712 1713	return sysfs_emit(buf, "%u\n", value);1714}1715 1716/* Store function for "enable" sysfs files - only for l3cache & crspace */1717static ssize_t mlxbf_pmc_enable_store(struct device *dev,1718				      struct device_attribute *attr,1719				      const char *buf, size_t count)1720{1721	struct mlxbf_pmc_attribute *attr_enable = container_of(1722		attr, struct mlxbf_pmc_attribute, dev_attr);1723	unsigned int en, blk_num;1724	u32 word;1725	int err;1726 1727	blk_num = attr_enable->nr;1728 1729	err = kstrtouint(buf, 0, &en);1730	if (err < 0)1731		return err;1732 1733	if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) {1734		err = mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +1735			MLXBF_PMC_CRSPACE_PERFMON_CTL(pmc->block[blk_num].counters),1736			&word);1737		if (err)1738			return -EINVAL;1739 1740		word &= ~MLXBF_PMC_CRSPACE_PERFMON_EN;1741		word |= FIELD_PREP(MLXBF_PMC_CRSPACE_PERFMON_EN, en);1742		if (en)1743			word |= FIELD_PREP(MLXBF_PMC_CRSPACE_PERFMON_CLR, 1);1744 1745		mlxbf_pmc_write(pmc->block[blk_num].mmio_base +1746			MLXBF_PMC_CRSPACE_PERFMON_CTL(pmc->block[blk_num].counters),1747			MLXBF_PMC_WRITE_REG_32, word);1748	} else {1749		if (en && en != 1)1750			return -EINVAL;1751 1752		err = mlxbf_pmc_config_l3_counters(blk_num, false, !!en);1753		if (err)1754			return err;1755 1756		if (en == 1) {1757			err = mlxbf_pmc_config_l3_counters(blk_num, true, false);1758			if (err)1759				return err;1760		}1761	}1762 1763	return count;1764}1765 1766/* Populate attributes for blocks with counters to monitor performance */1767static int mlxbf_pmc_init_perftype_counter(struct device *dev, unsigned int blk_num)1768{1769	struct mlxbf_pmc_attribute *attr;1770	unsigned int i = 0, j = 0;1771 1772	if (!mlxbf_pmc_event_supported(pmc->block_name[blk_num]))1773		return -ENOENT;1774 1775	/* "event_list" sysfs to list events supported by the block */1776	attr = &pmc->block[blk_num].attr_event_list;1777	sysfs_attr_init(&attr->dev_attr.attr);1778	attr->dev_attr.attr.mode = 0444;1779	attr->dev_attr.show = mlxbf_pmc_event_list_show;1780	attr->nr = blk_num;1781	attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, "event_list");1782	if (!attr->dev_attr.attr.name)1783		return -ENOMEM;1784	pmc->block[blk_num].block_attr[i] = &attr->dev_attr.attr;1785	attr = NULL;1786 1787	/* "enable" sysfs to start/stop the counters. Only in L3C blocks */1788	if (strstr(pmc->block_name[blk_num], "l3cache") ||1789	    ((pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE))) {1790		attr = &pmc->block[blk_num].attr_enable;1791		sysfs_attr_init(&attr->dev_attr.attr);1792		attr->dev_attr.attr.mode = 0644;1793		attr->dev_attr.show = mlxbf_pmc_enable_show;1794		attr->dev_attr.store = mlxbf_pmc_enable_store;1795		attr->nr = blk_num;1796		attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,1797							  "enable");1798		if (!attr->dev_attr.attr.name)1799			return -ENOMEM;1800		pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr;1801		attr = NULL;1802	}1803 1804	pmc->block[blk_num].attr_counter = devm_kcalloc(1805		dev, pmc->block[blk_num].counters,1806		sizeof(struct mlxbf_pmc_attribute), GFP_KERNEL);1807	if (!pmc->block[blk_num].attr_counter)1808		return -ENOMEM;1809 1810	pmc->block[blk_num].attr_event = devm_kcalloc(1811		dev, pmc->block[blk_num].counters,1812		sizeof(struct mlxbf_pmc_attribute), GFP_KERNEL);1813	if (!pmc->block[blk_num].attr_event)1814		return -ENOMEM;1815 1816	/* "eventX" and "counterX" sysfs to program and read counter values */1817	for (j = 0; j < pmc->block[blk_num].counters; ++j) {1818		attr = &pmc->block[blk_num].attr_counter[j];1819		sysfs_attr_init(&attr->dev_attr.attr);1820		attr->dev_attr.attr.mode = 0644;1821		attr->dev_attr.show = mlxbf_pmc_counter_show;1822		attr->dev_attr.store = mlxbf_pmc_counter_store;1823		attr->index = j;1824		attr->nr = blk_num;1825		attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, "counter%u", j);1826		if (!attr->dev_attr.attr.name)1827			return -ENOMEM;1828		pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr;1829		attr = NULL;1830 1831		attr = &pmc->block[blk_num].attr_event[j];1832		sysfs_attr_init(&attr->dev_attr.attr);1833		attr->dev_attr.attr.mode = 0644;1834		attr->dev_attr.show = mlxbf_pmc_event_show;1835		attr->dev_attr.store = mlxbf_pmc_event_store;1836		attr->index = j;1837		attr->nr = blk_num;1838		attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, "event%u", j);1839		if (!attr->dev_attr.attr.name)1840			return -ENOMEM;1841		pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr;1842		attr = NULL;1843	}1844 1845	return 0;1846}1847 1848/* Populate attributes for blocks with registers to monitor performance */1849static int mlxbf_pmc_init_perftype_reg(struct device *dev, unsigned int blk_num)1850{1851	const struct mlxbf_pmc_events *events;1852	struct mlxbf_pmc_attribute *attr;1853	unsigned int i = 0;1854	size_t count = 0;1855 1856	events = mlxbf_pmc_event_list(pmc->block_name[blk_num], &count);1857	if (!events)1858		return -ENOENT;1859 1860	pmc->block[blk_num].attr_event = devm_kcalloc(1861		dev, count, sizeof(struct mlxbf_pmc_attribute), GFP_KERNEL);1862	if (!pmc->block[blk_num].attr_event)1863		return -ENOMEM;1864 1865	while (count > 0) {1866		--count;1867		attr = &pmc->block[blk_num].attr_event[count];1868		sysfs_attr_init(&attr->dev_attr.attr);1869		attr->dev_attr.attr.mode = 0644;1870		attr->dev_attr.show = mlxbf_pmc_counter_show;1871		attr->dev_attr.store = mlxbf_pmc_counter_store;1872		attr->nr = blk_num;1873		attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,1874							  events[count].evt_name);1875		if (!attr->dev_attr.attr.name)1876			return -ENOMEM;1877		pmc->block[blk_num].block_attr[i] = &attr->dev_attr.attr;1878		attr = NULL;1879		i++;1880	}1881 1882	return 0;1883}1884 1885/* Helper to create the bfperf sysfs sub-directories and files */1886static int mlxbf_pmc_create_groups(struct device *dev, unsigned int blk_num)1887{1888	int err;1889 1890	/* Populate attributes based on counter type */1891	if ((pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER) ||1892	    (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE))1893		err = mlxbf_pmc_init_perftype_counter(dev, blk_num);1894	else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_REGISTER)1895		err = mlxbf_pmc_init_perftype_reg(dev, blk_num);1896	else1897		err = -ENOENT;1898 1899	if (err)1900		return err;1901 1902	/* Add a new attribute_group for the block */1903	pmc->block[blk_num].block_attr_grp.attrs = pmc->block[blk_num].block_attr;1904	pmc->block[blk_num].block_attr_grp.name = devm_kasprintf(1905		dev, GFP_KERNEL, pmc->block_name[blk_num]);1906	if (!pmc->block[blk_num].block_attr_grp.name)1907		return -ENOMEM;1908	pmc->groups[pmc->group_num] = &pmc->block[blk_num].block_attr_grp;1909	pmc->group_num++;1910 1911	return 0;1912}1913 1914static bool mlxbf_pmc_guid_match(const guid_t *guid,1915				 const struct arm_smccc_res *res)1916{1917	guid_t id = GUID_INIT(res->a0, res->a1, res->a1 >> 16, res->a2,1918			      res->a2 >> 8, res->a2 >> 16, res->a2 >> 24,1919			      res->a3, res->a3 >> 8, res->a3 >> 16,1920			      res->a3 >> 24);1921 1922	return guid_equal(guid, &id);1923}1924 1925/* Helper to map the Performance Counters from the varios blocks */1926static int mlxbf_pmc_map_counters(struct device *dev)1927{1928	u64 info[MLXBF_PMC_INFO_SZ];1929	unsigned int tile_num, i;1930	int ret;1931 1932	for (i = 0; i < pmc->total_blocks; ++i) {1933		/* Create sysfs for tiles only if block number <  tile_count */1934		if (strstr(pmc->block_name[i], "tilenet")) {1935			if (sscanf(pmc->block_name[i], "tilenet%u", &tile_num) != 1)1936				continue;1937 1938			if (tile_num >= pmc->tile_count)1939				continue;1940		} else if (strstr(pmc->block_name[i], "tile")) {1941			if (sscanf(pmc->block_name[i], "tile%u", &tile_num) != 1)1942				continue;1943 1944			if (tile_num >= pmc->tile_count)1945				continue;1946		}1947 1948		/* Create sysfs only for enabled MSS blocks */1949		if (strstr(pmc->block_name[i], "mss") &&1950		    pmc->event_set == MLXBF_PMC_EVENT_SET_BF3) {1951			unsigned int mss_num;1952 1953			if (sscanf(pmc->block_name[i], "mss%u", &mss_num) != 1)1954				continue;1955 1956			if (!((pmc->mss_enable >> mss_num) & 0x1))1957				continue;1958		}1959 1960		/* Create sysfs only for enabled LLT blocks */1961		if (strstr(pmc->block_name[i], "llt_miss")) {1962			unsigned int llt_num;1963 1964			if (sscanf(pmc->block_name[i], "llt_miss%u", &llt_num) != 1)1965				continue;1966 1967			if (!((pmc->llt_enable >> llt_num) & 0x1))1968				continue;1969		} else if (strstr(pmc->block_name[i], "llt")) {1970			unsigned int llt_num;1971 1972			if (sscanf(pmc->block_name[i], "llt%u", &llt_num) != 1)1973				continue;1974 1975			if (!((pmc->llt_enable >> llt_num) & 0x1))1976				continue;1977		}1978 1979		ret = device_property_read_u64_array(dev, pmc->block_name[i],1980						     info, MLXBF_PMC_INFO_SZ);1981		if (ret)1982			return ret;1983 1984		/*1985		 * Do not remap if the proper SMC calls are supported,1986		 * since the SMC calls expect physical addresses.1987		 */1988		if (pmc->svc_sreg_support)1989			pmc->block[i].mmio_base = (void __iomem *)info[0];1990		else1991			pmc->block[i].mmio_base =1992				devm_ioremap(dev, info[0], info[1]);1993 1994		pmc->block[i].blk_size = info[1];1995		pmc->block[i].counters = info[2];1996		pmc->block[i].type = info[3];1997 1998		if (!pmc->block[i].mmio_base)1999			return -ENOMEM;2000 2001		ret = mlxbf_pmc_create_groups(dev, i);2002		if (ret == -ENOENT) {2003			dev_warn(dev, "ignoring unsupported block: '%s'\n", pmc->block_name[i]);2004			continue;2005		}2006		if (ret)2007			return ret;2008	}2009 2010	return 0;2011}2012 2013static int mlxbf_pmc_probe(struct platform_device *pdev)2014{2015	struct acpi_device *acpi_dev = ACPI_COMPANION(&pdev->dev);2016	const char *hid = acpi_device_hid(acpi_dev);2017	struct device *dev = &pdev->dev;2018	struct arm_smccc_res res;2019	guid_t guid;2020	int ret;2021 2022	/* Ensure we have the UUID we expect for this service. */2023	arm_smccc_smc(MLXBF_PMC_SIP_SVC_UID, 0, 0, 0, 0, 0, 0, 0, &res);2024	guid_parse(mlxbf_pmc_svc_uuid_str, &guid);2025	if (!mlxbf_pmc_guid_match(&guid, &res))2026		return -ENODEV;2027 2028	pmc = devm_kzalloc(dev, sizeof(struct mlxbf_pmc_context), GFP_KERNEL);2029	if (!pmc)2030		return -ENOMEM;2031 2032	/*2033	 * ACPI indicates whether we use SMCs to access registers or not.2034	 * If sreg_tbl_perf is not present, just assume we're not using SMCs.2035	 */2036	ret = device_property_read_u32(dev, "sec_reg_block",2037				       &pmc->sreg_tbl_perf);2038	if (ret) {2039		pmc->svc_sreg_support = false;2040	} else {2041		/*2042		 * Check service version to see if we actually do support the2043		 * needed SMCs. If we have the calls we need, mark support for2044		 * them in the pmc struct.2045		 */2046		arm_smccc_smc(MLXBF_PMC_SIP_SVC_VERSION, 0, 0, 0, 0, 0, 0, 0,2047			      &res);2048		if (res.a0 == MLXBF_PMC_SVC_REQ_MAJOR &&2049		    res.a1 >= MLXBF_PMC_SVC_MIN_MINOR)2050			pmc->svc_sreg_support = true;2051		else2052			return -EINVAL;2053	}2054 2055	if (!strcmp(hid, "MLNXBFD0"))2056		pmc->event_set = MLXBF_PMC_EVENT_SET_BF1;2057	else if (!strcmp(hid, "MLNXBFD1"))2058		pmc->event_set = MLXBF_PMC_EVENT_SET_BF2;2059	else if (!strcmp(hid, "MLNXBFD2"))2060		pmc->event_set = MLXBF_PMC_EVENT_SET_BF3;2061	else2062		return -ENODEV;2063 2064	ret = device_property_read_u32(dev, "block_num", &pmc->total_blocks);2065	if (ret)2066		return ret;2067 2068	ret = device_property_read_string_array(dev, "block_name",2069						pmc->block_name,2070						pmc->total_blocks);2071	if (ret != pmc->total_blocks)2072		return -EFAULT;2073 2074	if (device_property_read_u32(dev, "tile_num", &pmc->tile_count)) {2075		if (device_property_read_u8(dev, "llt_enable", &pmc->llt_enable)) {2076			dev_err(dev, "Number of tiles/LLTs undefined\n");2077			return -EINVAL;2078		}2079		if (device_property_read_u8(dev, "mss_enable", &pmc->mss_enable)) {2080			dev_err(dev, "Number of tiles/MSSs undefined\n");2081			return -EINVAL;2082		}2083	}2084 2085	pmc->pdev = pdev;2086	pmc->group_num = 0;2087 2088	ret = mlxbf_pmc_map_counters(dev);2089	if (ret)2090		return ret;2091 2092	pmc->hwmon_dev = devm_hwmon_device_register_with_groups(2093		dev, "bfperf", pmc, pmc->groups);2094	if (IS_ERR(pmc->hwmon_dev))2095		return PTR_ERR(pmc->hwmon_dev);2096	platform_set_drvdata(pdev, pmc);2097 2098	return 0;2099}2100 2101static const struct acpi_device_id mlxbf_pmc_acpi_ids[] = { { "MLNXBFD0", 0 },2102							    { "MLNXBFD1", 0 },2103							    { "MLNXBFD2", 0 },2104							    {}, };2105 2106MODULE_DEVICE_TABLE(acpi, mlxbf_pmc_acpi_ids);2107static struct platform_driver pmc_driver = {2108	.driver = { .name = "mlxbf-pmc",2109		    .acpi_match_table = ACPI_PTR(mlxbf_pmc_acpi_ids), },2110	.probe = mlxbf_pmc_probe,2111};2112 2113module_platform_driver(pmc_driver);2114 2115MODULE_AUTHOR("Shravan Kumar Ramani <sramani@mellanox.com>");2116MODULE_DESCRIPTION("Mellanox PMC driver");2117MODULE_LICENSE("Dual BSD/GPL");2118