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 
is_trbe_available(void)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 
26*c0070112SAnshuman Khandual 	return trbe >= ID_AA64DFR0_EL1_TraceBuffer_IMP;
273fbf7f01SAnshuman Khandual }
283fbf7f01SAnshuman Khandual 
is_trbe_enabled(void)293fbf7f01SAnshuman Khandual static inline bool is_trbe_enabled(void)
303fbf7f01SAnshuman Khandual {
313fbf7f01SAnshuman Khandual 	u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1);
323fbf7f01SAnshuman Khandual 
3392b1efcdSAnshuman 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 
get_trbe_ec(u64 trbsr)403fbf7f01SAnshuman Khandual static inline int get_trbe_ec(u64 trbsr)
413fbf7f01SAnshuman Khandual {
427bb94882SAnshuman Khandual 	return (trbsr & TRBSR_EL1_EC_MASK) >> TRBSR_EL1_EC_SHIFT;
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 
get_trbe_bsc(u64 trbsr)493fbf7f01SAnshuman Khandual static inline int get_trbe_bsc(u64 trbsr)
503fbf7f01SAnshuman Khandual {
517bb94882SAnshuman Khandual 	return (trbsr & TRBSR_EL1_BSC_MASK) >> TRBSR_EL1_BSC_SHIFT;
523fbf7f01SAnshuman Khandual }
533fbf7f01SAnshuman Khandual 
clr_trbe_irq(void)543fbf7f01SAnshuman Khandual static inline void clr_trbe_irq(void)
553fbf7f01SAnshuman Khandual {
563fbf7f01SAnshuman Khandual 	u64 trbsr = read_sysreg_s(SYS_TRBSR_EL1);
573fbf7f01SAnshuman Khandual 
587bb94882SAnshuman Khandual 	trbsr &= ~TRBSR_EL1_IRQ;
593fbf7f01SAnshuman Khandual 	write_sysreg_s(trbsr, SYS_TRBSR_EL1);
603fbf7f01SAnshuman Khandual }
613fbf7f01SAnshuman Khandual 
is_trbe_irq(u64 trbsr)623fbf7f01SAnshuman Khandual static inline bool is_trbe_irq(u64 trbsr)
633fbf7f01SAnshuman Khandual {
647bb94882SAnshuman Khandual 	return trbsr & TRBSR_EL1_IRQ;
653fbf7f01SAnshuman Khandual }
663fbf7f01SAnshuman Khandual 
is_trbe_trg(u64 trbsr)673fbf7f01SAnshuman Khandual static inline bool is_trbe_trg(u64 trbsr)
683fbf7f01SAnshuman Khandual {
697bb94882SAnshuman Khandual 	return trbsr & TRBSR_EL1_TRG;
703fbf7f01SAnshuman Khandual }
713fbf7f01SAnshuman Khandual 
is_trbe_wrap(u64 trbsr)723fbf7f01SAnshuman Khandual static inline bool is_trbe_wrap(u64 trbsr)
733fbf7f01SAnshuman Khandual {
747bb94882SAnshuman Khandual 	return trbsr & TRBSR_EL1_WRAP;
753fbf7f01SAnshuman Khandual }
763fbf7f01SAnshuman Khandual 
is_trbe_abort(u64 trbsr)773fbf7f01SAnshuman Khandual static inline bool is_trbe_abort(u64 trbsr)
783fbf7f01SAnshuman Khandual {
797bb94882SAnshuman Khandual 	return trbsr & TRBSR_EL1_EA;
803fbf7f01SAnshuman Khandual }
813fbf7f01SAnshuman Khandual 
is_trbe_running(u64 trbsr)823fbf7f01SAnshuman Khandual static inline bool is_trbe_running(u64 trbsr)
833fbf7f01SAnshuman Khandual {
847bb94882SAnshuman Khandual 	return !(trbsr & TRBSR_EL1_S);
853fbf7f01SAnshuman Khandual }
863fbf7f01SAnshuman Khandual 
get_trbe_flag_update(u64 trbidr)873fbf7f01SAnshuman Khandual static inline bool get_trbe_flag_update(u64 trbidr)
883fbf7f01SAnshuman Khandual {
89f170aa51SAnshuman Khandual 	return trbidr & TRBIDR_EL1_F;
903fbf7f01SAnshuman Khandual }
913fbf7f01SAnshuman Khandual 
is_trbe_programmable(u64 trbidr)923fbf7f01SAnshuman Khandual static inline bool is_trbe_programmable(u64 trbidr)
933fbf7f01SAnshuman Khandual {
94f170aa51SAnshuman Khandual 	return !(trbidr & TRBIDR_EL1_P);
953fbf7f01SAnshuman Khandual }
963fbf7f01SAnshuman Khandual 
get_trbe_address_align(u64 trbidr)973fbf7f01SAnshuman Khandual static inline int get_trbe_address_align(u64 trbidr)
983fbf7f01SAnshuman Khandual {
99f170aa51SAnshuman Khandual 	return (trbidr & TRBIDR_EL1_Align_MASK) >> TRBIDR_EL1_Align_SHIFT;
1003fbf7f01SAnshuman Khandual }
1013fbf7f01SAnshuman Khandual 
get_trbe_write_pointer(void)1023fbf7f01SAnshuman Khandual static inline unsigned long get_trbe_write_pointer(void)
1033fbf7f01SAnshuman Khandual {
1043fbf7f01SAnshuman Khandual 	return read_sysreg_s(SYS_TRBPTR_EL1);
1053fbf7f01SAnshuman Khandual }
1063fbf7f01SAnshuman Khandual 
set_trbe_write_pointer(unsigned long addr)1073fbf7f01SAnshuman Khandual static inline void set_trbe_write_pointer(unsigned long addr)
1083fbf7f01SAnshuman Khandual {
1093fbf7f01SAnshuman Khandual 	WARN_ON(is_trbe_enabled());
1103fbf7f01SAnshuman Khandual 	write_sysreg_s(addr, SYS_TRBPTR_EL1);
1113fbf7f01SAnshuman Khandual }
1123fbf7f01SAnshuman Khandual 
get_trbe_limit_pointer(void)1133fbf7f01SAnshuman Khandual static inline unsigned long get_trbe_limit_pointer(void)
1143fbf7f01SAnshuman Khandual {
1153fbf7f01SAnshuman Khandual 	u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1);
11692b1efcdSAnshuman Khandual 	unsigned long addr = trblimitr & TRBLIMITR_EL1_LIMIT_MASK;
1173fbf7f01SAnshuman Khandual 
1183fbf7f01SAnshuman Khandual 	WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE));
1193fbf7f01SAnshuman Khandual 	return addr;
1203fbf7f01SAnshuman Khandual }
1213fbf7f01SAnshuman Khandual 
get_trbe_base_pointer(void)1223fbf7f01SAnshuman Khandual static inline unsigned long get_trbe_base_pointer(void)
1233fbf7f01SAnshuman Khandual {
1243fbf7f01SAnshuman Khandual 	u64 trbbaser = read_sysreg_s(SYS_TRBBASER_EL1);
12590cdde83SAnshuman Khandual 	unsigned long addr = trbbaser & TRBBASER_EL1_BASE_MASK;
1263fbf7f01SAnshuman Khandual 
1273fbf7f01SAnshuman Khandual 	WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE));
1283fbf7f01SAnshuman Khandual 	return addr;
1293fbf7f01SAnshuman Khandual }
1303fbf7f01SAnshuman Khandual 
set_trbe_base_pointer(unsigned long addr)1313fbf7f01SAnshuman Khandual static inline void set_trbe_base_pointer(unsigned long addr)
1323fbf7f01SAnshuman Khandual {
1333fbf7f01SAnshuman Khandual 	WARN_ON(is_trbe_enabled());
13490cdde83SAnshuman Khandual 	WARN_ON(!IS_ALIGNED(addr, (1UL << TRBBASER_EL1_BASE_SHIFT)));
1353fbf7f01SAnshuman Khandual 	WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE));
1363fbf7f01SAnshuman Khandual 	write_sysreg_s(addr, SYS_TRBBASER_EL1);
1373fbf7f01SAnshuman Khandual }
138