0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/coresight.h>
0011 #include <linux/device.h>
0012 #include <linux/irq.h>
0013 #include <linux/kernel.h>
0014 #include <linux/of.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/smp.h>
0017
0018 #include "coresight-etm-perf.h"
0019
0020 static inline bool is_trbe_available(void)
0021 {
0022 u64 aa64dfr0 = read_sysreg_s(SYS_ID_AA64DFR0_EL1);
0023 unsigned int trbe = cpuid_feature_extract_unsigned_field(aa64dfr0, ID_AA64DFR0_TRBE_SHIFT);
0024
0025 return trbe >= 0b0001;
0026 }
0027
0028 static inline bool is_trbe_enabled(void)
0029 {
0030 u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1);
0031
0032 return trblimitr & TRBLIMITR_ENABLE;
0033 }
0034
0035 #define TRBE_EC_OTHERS 0
0036 #define TRBE_EC_STAGE1_ABORT 36
0037 #define TRBE_EC_STAGE2_ABORT 37
0038
0039 static inline int get_trbe_ec(u64 trbsr)
0040 {
0041 return (trbsr >> TRBSR_EC_SHIFT) & TRBSR_EC_MASK;
0042 }
0043
0044 #define TRBE_BSC_NOT_STOPPED 0
0045 #define TRBE_BSC_FILLED 1
0046 #define TRBE_BSC_TRIGGERED 2
0047
0048 static inline int get_trbe_bsc(u64 trbsr)
0049 {
0050 return (trbsr >> TRBSR_BSC_SHIFT) & TRBSR_BSC_MASK;
0051 }
0052
0053 static inline void clr_trbe_irq(void)
0054 {
0055 u64 trbsr = read_sysreg_s(SYS_TRBSR_EL1);
0056
0057 trbsr &= ~TRBSR_IRQ;
0058 write_sysreg_s(trbsr, SYS_TRBSR_EL1);
0059 }
0060
0061 static inline bool is_trbe_irq(u64 trbsr)
0062 {
0063 return trbsr & TRBSR_IRQ;
0064 }
0065
0066 static inline bool is_trbe_trg(u64 trbsr)
0067 {
0068 return trbsr & TRBSR_TRG;
0069 }
0070
0071 static inline bool is_trbe_wrap(u64 trbsr)
0072 {
0073 return trbsr & TRBSR_WRAP;
0074 }
0075
0076 static inline bool is_trbe_abort(u64 trbsr)
0077 {
0078 return trbsr & TRBSR_ABORT;
0079 }
0080
0081 static inline bool is_trbe_running(u64 trbsr)
0082 {
0083 return !(trbsr & TRBSR_STOP);
0084 }
0085
0086 #define TRBE_TRIG_MODE_STOP 0
0087 #define TRBE_TRIG_MODE_IRQ 1
0088 #define TRBE_TRIG_MODE_IGNORE 3
0089
0090 #define TRBE_FILL_MODE_FILL 0
0091 #define TRBE_FILL_MODE_WRAP 1
0092 #define TRBE_FILL_MODE_CIRCULAR_BUFFER 3
0093
0094 static inline bool get_trbe_flag_update(u64 trbidr)
0095 {
0096 return trbidr & TRBIDR_FLAG;
0097 }
0098
0099 static inline bool is_trbe_programmable(u64 trbidr)
0100 {
0101 return !(trbidr & TRBIDR_PROG);
0102 }
0103
0104 static inline int get_trbe_address_align(u64 trbidr)
0105 {
0106 return (trbidr >> TRBIDR_ALIGN_SHIFT) & TRBIDR_ALIGN_MASK;
0107 }
0108
0109 static inline unsigned long get_trbe_write_pointer(void)
0110 {
0111 return read_sysreg_s(SYS_TRBPTR_EL1);
0112 }
0113
0114 static inline void set_trbe_write_pointer(unsigned long addr)
0115 {
0116 WARN_ON(is_trbe_enabled());
0117 write_sysreg_s(addr, SYS_TRBPTR_EL1);
0118 }
0119
0120 static inline unsigned long get_trbe_limit_pointer(void)
0121 {
0122 u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1);
0123 unsigned long addr = trblimitr & (TRBLIMITR_LIMIT_MASK << TRBLIMITR_LIMIT_SHIFT);
0124
0125 WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE));
0126 return addr;
0127 }
0128
0129 static inline unsigned long get_trbe_base_pointer(void)
0130 {
0131 u64 trbbaser = read_sysreg_s(SYS_TRBBASER_EL1);
0132 unsigned long addr = trbbaser & (TRBBASER_BASE_MASK << TRBBASER_BASE_SHIFT);
0133
0134 WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE));
0135 return addr;
0136 }
0137
0138 static inline void set_trbe_base_pointer(unsigned long addr)
0139 {
0140 WARN_ON(is_trbe_enabled());
0141 WARN_ON(!IS_ALIGNED(addr, (1UL << TRBBASER_BASE_SHIFT)));
0142 WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE));
0143 write_sysreg_s(addr, SYS_TRBBASER_EL1);
0144 }