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 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 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 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 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 623fbf7f01SAnshuman Khandual static inline bool is_trbe_irq(u64 trbsr) 633fbf7f01SAnshuman Khandual { 647bb94882SAnshuman Khandual return trbsr & TRBSR_EL1_IRQ; 653fbf7f01SAnshuman Khandual } 663fbf7f01SAnshuman Khandual 673fbf7f01SAnshuman Khandual static inline bool is_trbe_trg(u64 trbsr) 683fbf7f01SAnshuman Khandual { 697bb94882SAnshuman Khandual return trbsr & TRBSR_EL1_TRG; 703fbf7f01SAnshuman Khandual } 713fbf7f01SAnshuman Khandual 723fbf7f01SAnshuman Khandual static inline bool is_trbe_wrap(u64 trbsr) 733fbf7f01SAnshuman Khandual { 747bb94882SAnshuman Khandual return trbsr & TRBSR_EL1_WRAP; 753fbf7f01SAnshuman Khandual } 763fbf7f01SAnshuman Khandual 773fbf7f01SAnshuman Khandual static inline bool is_trbe_abort(u64 trbsr) 783fbf7f01SAnshuman Khandual { 797bb94882SAnshuman Khandual return trbsr & TRBSR_EL1_EA; 803fbf7f01SAnshuman Khandual } 813fbf7f01SAnshuman Khandual 823fbf7f01SAnshuman Khandual static inline bool is_trbe_running(u64 trbsr) 833fbf7f01SAnshuman Khandual { 847bb94882SAnshuman Khandual return !(trbsr & TRBSR_EL1_S); 853fbf7f01SAnshuman Khandual } 863fbf7f01SAnshuman Khandual 873fbf7f01SAnshuman Khandual #define TRBE_TRIG_MODE_STOP 0 883fbf7f01SAnshuman Khandual #define TRBE_TRIG_MODE_IRQ 1 8992b1efcdSAnshuman Khandual #define TRBLIMITR_EL1_TM_IGNR 3 903fbf7f01SAnshuman Khandual 9192b1efcdSAnshuman 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 { 98*f170aa51SAnshuman Khandual return trbidr & TRBIDR_EL1_F; 993fbf7f01SAnshuman Khandual } 1003fbf7f01SAnshuman Khandual 1013fbf7f01SAnshuman Khandual static inline bool is_trbe_programmable(u64 trbidr) 1023fbf7f01SAnshuman Khandual { 103*f170aa51SAnshuman Khandual return !(trbidr & TRBIDR_EL1_P); 1043fbf7f01SAnshuman Khandual } 1053fbf7f01SAnshuman Khandual 1063fbf7f01SAnshuman Khandual static inline int get_trbe_address_align(u64 trbidr) 1073fbf7f01SAnshuman Khandual { 108*f170aa51SAnshuman Khandual return (trbidr & TRBIDR_EL1_Align_MASK) >> TRBIDR_EL1_Align_SHIFT; 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); 12592b1efcdSAnshuman 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); 13490cdde83SAnshuman Khandual unsigned long addr = trbbaser & TRBBASER_EL1_BASE_MASK; 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()); 14390cdde83SAnshuman Khandual WARN_ON(!IS_ALIGNED(addr, (1UL << TRBBASER_EL1_BASE_SHIFT))); 1443fbf7f01SAnshuman Khandual WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE)); 1453fbf7f01SAnshuman Khandual write_sysreg_s(addr, SYS_TRBBASER_EL1); 1463fbf7f01SAnshuman Khandual } 147