13fbf7f01SAnshuman Khandual /* SPDX-License-Identifier: GPL-2.0 */
23fbf7f01SAnshuman Khandual /*
33fbf7f01SAnshuman Khandual  * This contains all required hardware related helper functions for
43fbf7f01SAnshuman Khandual  * Trace Buffer Extension (TRBE) driver in the coresight framework.
53fbf7f01SAnshuman Khandual  *
63fbf7f01SAnshuman Khandual  * Copyright (C) 2020 ARM Ltd.
73fbf7f01SAnshuman Khandual  *
83fbf7f01SAnshuman Khandual  * Author: Anshuman Khandual <anshuman.khandual@arm.com>
93fbf7f01SAnshuman Khandual  */
103fbf7f01SAnshuman Khandual #include <linux/coresight.h>
113fbf7f01SAnshuman Khandual #include <linux/device.h>
123fbf7f01SAnshuman Khandual #include <linux/irq.h>
133fbf7f01SAnshuman Khandual #include <linux/kernel.h>
143fbf7f01SAnshuman Khandual #include <linux/of.h>
153fbf7f01SAnshuman Khandual #include <linux/platform_device.h>
163fbf7f01SAnshuman Khandual #include <linux/smp.h>
173fbf7f01SAnshuman Khandual 
183fbf7f01SAnshuman Khandual #include "coresight-etm-perf.h"
193fbf7f01SAnshuman Khandual 
203fbf7f01SAnshuman Khandual static inline bool is_trbe_available(void)
213fbf7f01SAnshuman Khandual {
223fbf7f01SAnshuman Khandual 	u64 aa64dfr0 = read_sysreg_s(SYS_ID_AA64DFR0_EL1);
23db74cd63SNathan Chancellor 	unsigned int trbe = cpuid_feature_extract_unsigned_field(aa64dfr0,
24db74cd63SNathan Chancellor 								 ID_AA64DFR0_EL1_TraceBuffer_SHIFT);
253fbf7f01SAnshuman Khandual 
263fbf7f01SAnshuman Khandual 	return trbe >= 0b0001;
273fbf7f01SAnshuman Khandual }
283fbf7f01SAnshuman Khandual 
293fbf7f01SAnshuman Khandual static inline bool is_trbe_enabled(void)
303fbf7f01SAnshuman Khandual {
313fbf7f01SAnshuman Khandual 	u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1);
323fbf7f01SAnshuman Khandual 
33*92b1efcdSAnshuman Khandual 	return trblimitr & TRBLIMITR_EL1_E;
343fbf7f01SAnshuman Khandual }
353fbf7f01SAnshuman Khandual 
363fbf7f01SAnshuman Khandual #define TRBE_EC_OTHERS		0
373fbf7f01SAnshuman Khandual #define TRBE_EC_STAGE1_ABORT	36
383fbf7f01SAnshuman Khandual #define TRBE_EC_STAGE2_ABORT	37
393fbf7f01SAnshuman Khandual 
403fbf7f01SAnshuman Khandual static inline int get_trbe_ec(u64 trbsr)
413fbf7f01SAnshuman Khandual {
423fbf7f01SAnshuman Khandual 	return (trbsr >> TRBSR_EC_SHIFT) & TRBSR_EC_MASK;
433fbf7f01SAnshuman Khandual }
443fbf7f01SAnshuman Khandual 
453fbf7f01SAnshuman Khandual #define TRBE_BSC_NOT_STOPPED 0
463fbf7f01SAnshuman Khandual #define TRBE_BSC_FILLED      1
473fbf7f01SAnshuman Khandual #define TRBE_BSC_TRIGGERED   2
483fbf7f01SAnshuman Khandual 
493fbf7f01SAnshuman Khandual static inline int get_trbe_bsc(u64 trbsr)
503fbf7f01SAnshuman Khandual {
513fbf7f01SAnshuman Khandual 	return (trbsr >> TRBSR_BSC_SHIFT) & TRBSR_BSC_MASK;
523fbf7f01SAnshuman Khandual }
533fbf7f01SAnshuman Khandual 
543fbf7f01SAnshuman Khandual static inline void clr_trbe_irq(void)
553fbf7f01SAnshuman Khandual {
563fbf7f01SAnshuman Khandual 	u64 trbsr = read_sysreg_s(SYS_TRBSR_EL1);
573fbf7f01SAnshuman Khandual 
583fbf7f01SAnshuman Khandual 	trbsr &= ~TRBSR_IRQ;
593fbf7f01SAnshuman Khandual 	write_sysreg_s(trbsr, SYS_TRBSR_EL1);
603fbf7f01SAnshuman Khandual }
613fbf7f01SAnshuman Khandual 
623fbf7f01SAnshuman Khandual static inline bool is_trbe_irq(u64 trbsr)
633fbf7f01SAnshuman Khandual {
643fbf7f01SAnshuman Khandual 	return trbsr & TRBSR_IRQ;
653fbf7f01SAnshuman Khandual }
663fbf7f01SAnshuman Khandual 
673fbf7f01SAnshuman Khandual static inline bool is_trbe_trg(u64 trbsr)
683fbf7f01SAnshuman Khandual {
693fbf7f01SAnshuman Khandual 	return trbsr & TRBSR_TRG;
703fbf7f01SAnshuman Khandual }
713fbf7f01SAnshuman Khandual 
723fbf7f01SAnshuman Khandual static inline bool is_trbe_wrap(u64 trbsr)
733fbf7f01SAnshuman Khandual {
743fbf7f01SAnshuman Khandual 	return trbsr & TRBSR_WRAP;
753fbf7f01SAnshuman Khandual }
763fbf7f01SAnshuman Khandual 
773fbf7f01SAnshuman Khandual static inline bool is_trbe_abort(u64 trbsr)
783fbf7f01SAnshuman Khandual {
793fbf7f01SAnshuman Khandual 	return trbsr & TRBSR_ABORT;
803fbf7f01SAnshuman Khandual }
813fbf7f01SAnshuman Khandual 
823fbf7f01SAnshuman Khandual static inline bool is_trbe_running(u64 trbsr)
833fbf7f01SAnshuman Khandual {
843fbf7f01SAnshuman Khandual 	return !(trbsr & TRBSR_STOP);
853fbf7f01SAnshuman Khandual }
863fbf7f01SAnshuman Khandual 
873fbf7f01SAnshuman Khandual #define TRBE_TRIG_MODE_STOP		0
883fbf7f01SAnshuman Khandual #define TRBE_TRIG_MODE_IRQ		1
89*92b1efcdSAnshuman Khandual #define TRBLIMITR_EL1_TM_IGNR		3
903fbf7f01SAnshuman Khandual 
91*92b1efcdSAnshuman Khandual #define TRBLIMITR_EL1_FM_FILL		0
923fbf7f01SAnshuman Khandual #define TRBE_FILL_MODE_FILL		0
933fbf7f01SAnshuman Khandual #define TRBE_FILL_MODE_WRAP		1
943fbf7f01SAnshuman Khandual #define TRBE_FILL_MODE_CIRCULAR_BUFFER	3
953fbf7f01SAnshuman Khandual 
963fbf7f01SAnshuman Khandual static inline bool get_trbe_flag_update(u64 trbidr)
973fbf7f01SAnshuman Khandual {
983fbf7f01SAnshuman Khandual 	return trbidr & TRBIDR_FLAG;
993fbf7f01SAnshuman Khandual }
1003fbf7f01SAnshuman Khandual 
1013fbf7f01SAnshuman Khandual static inline bool is_trbe_programmable(u64 trbidr)
1023fbf7f01SAnshuman Khandual {
1033fbf7f01SAnshuman Khandual 	return !(trbidr & TRBIDR_PROG);
1043fbf7f01SAnshuman Khandual }
1053fbf7f01SAnshuman Khandual 
1063fbf7f01SAnshuman Khandual static inline int get_trbe_address_align(u64 trbidr)
1073fbf7f01SAnshuman Khandual {
1083fbf7f01SAnshuman Khandual 	return (trbidr >> TRBIDR_ALIGN_SHIFT) & TRBIDR_ALIGN_MASK;
1093fbf7f01SAnshuman Khandual }
1103fbf7f01SAnshuman Khandual 
1113fbf7f01SAnshuman Khandual static inline unsigned long get_trbe_write_pointer(void)
1123fbf7f01SAnshuman Khandual {
1133fbf7f01SAnshuman Khandual 	return read_sysreg_s(SYS_TRBPTR_EL1);
1143fbf7f01SAnshuman Khandual }
1153fbf7f01SAnshuman Khandual 
1163fbf7f01SAnshuman Khandual static inline void set_trbe_write_pointer(unsigned long addr)
1173fbf7f01SAnshuman Khandual {
1183fbf7f01SAnshuman Khandual 	WARN_ON(is_trbe_enabled());
1193fbf7f01SAnshuman Khandual 	write_sysreg_s(addr, SYS_TRBPTR_EL1);
1203fbf7f01SAnshuman Khandual }
1213fbf7f01SAnshuman Khandual 
1223fbf7f01SAnshuman Khandual static inline unsigned long get_trbe_limit_pointer(void)
1233fbf7f01SAnshuman Khandual {
1243fbf7f01SAnshuman Khandual 	u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1);
125*92b1efcdSAnshuman Khandual 	unsigned long addr = trblimitr & TRBLIMITR_EL1_LIMIT_MASK;
1263fbf7f01SAnshuman Khandual 
1273fbf7f01SAnshuman Khandual 	WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE));
1283fbf7f01SAnshuman Khandual 	return addr;
1293fbf7f01SAnshuman Khandual }
1303fbf7f01SAnshuman Khandual 
1313fbf7f01SAnshuman Khandual static inline unsigned long get_trbe_base_pointer(void)
1323fbf7f01SAnshuman Khandual {
1333fbf7f01SAnshuman Khandual 	u64 trbbaser = read_sysreg_s(SYS_TRBBASER_EL1);
1343fbf7f01SAnshuman Khandual 	unsigned long addr = trbbaser & (TRBBASER_BASE_MASK << TRBBASER_BASE_SHIFT);
1353fbf7f01SAnshuman Khandual 
1363fbf7f01SAnshuman Khandual 	WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE));
1373fbf7f01SAnshuman Khandual 	return addr;
1383fbf7f01SAnshuman Khandual }
1393fbf7f01SAnshuman Khandual 
1403fbf7f01SAnshuman Khandual static inline void set_trbe_base_pointer(unsigned long addr)
1413fbf7f01SAnshuman Khandual {
1423fbf7f01SAnshuman Khandual 	WARN_ON(is_trbe_enabled());
1433fbf7f01SAnshuman Khandual 	WARN_ON(!IS_ALIGNED(addr, (1UL << TRBBASER_BASE_SHIFT)));
1443fbf7f01SAnshuman Khandual 	WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE));
1453fbf7f01SAnshuman Khandual 	write_sysreg_s(addr, SYS_TRBBASER_EL1);
1463fbf7f01SAnshuman Khandual }
147