/**************************************************************************** * drivers/coresight/coresight_etm4.c * * SPDX-License-Identifier: Apache-2.0 * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include "coresight_common.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ /* Device registers: * 0x000 - 0x2fc: Trace registers * 0x300 - 0x314: Management registers * 0x318 - 0xefc: Trace registers * 0xf00 : Management registers * 0xfa0 - 0xfa4: Trace registers * 0xfa8 - 0xffc: Management registers * * Trace registers (0x000-0x2fc) * Main control and configuration registers */ #define TRCPRGCTLR 0x004 #define TRCPROCSELR 0x008 #define TRCSTATR 0x00c #define TRCCONFIGR 0x010 #define TRCAUXCTLR 0x018 #define TRCEVENTCTL0R 0x020 #define TRCEVENTCTL1R 0x024 #define TRCRSR 0x028 #define TRCSTALLCTLR 0x02c #define TRCTSCTLR 0x030 #define TRCSYNCPR 0x034 #define TRCCCCTLR 0x038 #define TRCBBCTLR 0x03c #define TRCTRACEIDR 0x040 #define TRCQCTLR 0x044 /* Filtering control registers */ #define TRCVICTLR 0x080 #define TRCVIIECTLR 0x084 #define TRCVISSCTLR 0x088 #define TRCVIPCSSCTLR 0x08c #define TRCVDCTLR 0x0a0 #define TRCVDSACCTLR 0x0a4 #define TRCVDARCCTLR 0x0a8 /* Derived resources registers */ #define TRCSEQEVRN(n) (0x100 + (n * 4)) /* n = 0-2 */ #define TRCSEQRSTEVR 0x118 #define TRCSEQSTR 0x11c #define TRCEXTINSELR 0x120 #define TRCEXTINSELRN(n) (0x120 + (n * 4)) /* n = 0-3 */ #define TRCCNTRLDVRN(n) (0x140 + (n * 4)) /* n = 0-3 */ #define TRCCNTCTLRN(n) (0x150 + (n * 4)) /* n = 0-3 */ #define TRCCNTVRN(n) (0x160 + (n * 4)) /* n = 0-3 */ /* ID registers */ #define TRCIDR8 0x180 #define TRCIDR9 0x184 #define TRCIDR10 0x188 #define TRCIDR11 0x18c #define TRCIDR12 0x190 #define TRCIDR13 0x194 #define TRCIMSPEC0 0x1c0 #define TRCIMSPECN(n) (0x1c0 + (n * 4)) /* n = 1-7 */ #define TRCIDR0 0x1e0 #define TRCIDR1 0x1e4 #define TRCIDR2 0x1e8 #define TRCIDR3 0x1eC #define TRCIDR4 0x1f0 #define TRCIDR5 0x1f4 #define TRCIDR6 0x1f8 #define TRCIDR7 0x1fc /* Resource selection registers, n = 2-31. * First pair (regs 0, 1) is always present and is reserved. */ #define TRCRSCTLRN(n) (0x200 + (n * 4)) /* Single-shot comparator registers, n = 0-7 */ #define TRCSSCCRN(n) (0x280 + (n * 4)) #define TRCSSCSRN(n) (0x2a0 + (n * 4)) #define TRCSSPCICRN(n) (0x2c0 + (n * 4)) /* Management registers (0x300-0x314) */ #define TRCOSLAR 0x300 #define TRCOSLSR 0x304 #define TRCPDCR 0x310 #define TRCPDSR 0x314 /* Trace registers (0x318-0xefc) * Address Comparator registers n = 0-15 */ #define TRCACVRN(n) (0x400 + (n * 8)) #define TRCACATRN(n) (0x480 + (n * 8)) /* Data Value Comparator Value registers, n = 0-7 */ #define TRCDVCVRN(n) (0x500 + (n * 16)) #define TRCDVCMRN(n) (0x580 + (n * 16)) /* ContextID/Virtual ContextID comparators, n = 0-7 */ #define TRCCIDCVRN(n) (0x600 + (n * 8)) #define TRCVMIDCVRN(n) (0x640 + (n * 8)) #define TRCCIDCCTLR0 0x680 #define TRCCIDCCTLR1 0x684 #define TRCVMIDCCTLR0 0x688 #define TRCVMIDCCTLR1 0x68c /* Management register (0xf00) * Integration control registers */ #define TRCITCTRL 0xf00 /* Trace registers (0xfa0-0xfa4) * Claim tag registers */ #define TRCCLAIMSET 0xfa0 #define TRCCLAIMCLR 0xfa4 /* Management registers (0xfa8-0xffc) */ #define TRCDEVAFF0 0xfa8 #define TRCDEVAFF1 0xfac #define TRCLAR 0xfb0 #define TRCLSR 0xfb4 #define TRCAUTHSTATUS 0xfb8 #define TRCDEVARCH 0xfbc #define TRCDEVID 0xfc8 #define TRCDEVTYPE 0xfcc #define TRCPIDR4 0xfd0 #define TRCPIDR5 0xfd4 #define TRCPIDR6 0xfd8 #define TRCPIDR7 0xfdc #define TRCPIDR0 0xfe0 #define TRCPIDR1 0xfe4 #define TRCPIDR2 0xfe8 #define TRCPIDR3 0xfec #define TRCCIDR0 0xff0 #define TRCCIDR1 0xff4 #define TRCCIDR2 0xff8 #define TRCCIDR3 0xffc /* Bit positions of registers that are defined above, in the sysreg.h style * of _MASK for multi bit fields and BIT() for single bits. */ #define TRCRSR_TA BIT(12) #define TRCIDR0_INSTP0_MASK GENMASK(2, 1) #define TRCIDR0_TRCBB BIT(5) #define TRCIDR0_TRCCOND BIT(6) #define TRCIDR0_TRCCCI BIT(7) #define TRCIDR0_RETSTACK BIT(9) #define TRCIDR0_NUMEVENT_MASK GENMASK(11, 10) #define TRCIDR0_QSUPP_MASK GENMASK(16, 15) #define TRCIDR0_TSSIZE_MASK GENMASK(28, 24) #define TRCIDR2_CIDSIZE_MASK GENMASK(9, 5) #define TRCIDR2_VMIDSIZE_MASK GENMASK(14, 10) #define TRCIDR2_CCSIZE_MASK GENMASK(28, 25) #define TRCIDR3_CCITMIN_MASK GENMASK(11, 0) #define TRCIDR3_EXLEVEL_S_MASK GENMASK(19, 16) #define TRCIDR3_EXLEVEL_NS_MASK GENMASK(23, 20) #define TRCIDR3_TRCERR BIT(24) #define TRCIDR3_SYNCPR BIT(25) #define TRCIDR3_STALLCTL BIT(26) #define TRCIDR3_SYSSTALL BIT(27) #define TRCIDR3_NUMPROC_LO_MASK GENMASK(30, 28) #define TRCIDR3_NUMPROC_HI_MASK GENMASK(13, 12) #define TRCIDR3_NOOVERFLOW BIT(31) #define TRCIDR4_NUMACPAIRS_MASK GENMASK(3, 0) #define TRCIDR4_NUMPC_MASK GENMASK(15, 12) #define TRCIDR4_NUMRSPAIR_MASK GENMASK(19, 16) #define TRCIDR4_NUMSSCC_MASK GENMASK(23, 20) #define TRCIDR4_NUMCIDC_MASK GENMASK(27, 24) #define TRCIDR4_NUMVMIDC_MASK GENMASK(31, 28) #define TRCIDR5_NUMEXTIN_MASK GENMASK(8, 0) #define TRCIDR5_TRACEIDSIZE_MASK GENMASK(21, 16) #define TRCIDR5_ATBTRIG BIT(22) #define TRCIDR5_LPOVERRIDE BIT(23) #define TRCIDR5_NUMSEQSTATE_MASK GENMASK(27, 25) #define TRCIDR5_NUMCNTR_MASK GENMASK(30, 28) #define TRCCONFIGR_INSTP0_LOAD BIT(1) #define TRCCONFIGR_INSTP0_STORE BIT(2) #define TRCCONFIGR_INSTP0_LOAD_STORE (TRCCONFIGR_INSTP0_LOAD | TRCCONFIGR_INSTP0_STORE) #define TRCCONFIGR_BB BIT(3) #define TRCCONFIGR_CCI BIT(4) #define TRCCONFIGR_CID BIT(6) #define TRCCONFIGR_VMID BIT(7) #define TRCCONFIGR_COND_MASK GENMASK(10, 8) #define TRCCONFIGR_TS BIT(11) #define TRCCONFIGR_RS BIT(12) #define TRCCONFIGR_QE_W_COUNTS BIT(13) #define TRCCONFIGR_QE_WO_COUNTS BIT(14) #define TRCCONFIGR_VMIDOPT BIT(15) #define TRCCONFIGR_DA BIT(16) #define TRCCONFIGR_DV BIT(17) #define TRCEVENTCTL1R_INSTEN_MASK GENMASK(3, 0) #define TRCEVENTCTL1R_INSTEN_0 BIT(0) #define TRCEVENTCTL1R_INSTEN_1 BIT(1) #define TRCEVENTCTL1R_INSTEN_2 BIT(2) #define TRCEVENTCTL1R_INSTEN_3 BIT(3) #define TRCEVENTCTL1R_ATB BIT(11) #define TRCEVENTCTL1R_LPOVERRIDE BIT(12) #define TRCSTALLCTLR_ISTALL BIT(8) #define TRCSTALLCTLR_INSTPRIORITY BIT(10) #define TRCSTALLCTLR_NOOVERFLOW BIT(13) #define TRCVICTLR_EVENT_MASK GENMASK(7, 0) #define TRCVICTLR_SSSTATUS BIT(9) #define TRCVICTLR_TRCRESET BIT(10) #define TRCVICTLR_TRCERR BIT(11) #define TRCVICTLR_EXLEVEL_MASK GENMASK(22, 16) #define TRCVICTLR_EXLEVEL_S_MASK GENMASK(19, 16) #define TRCVICTLR_EXLEVEL_NS_MASK GENMASK(22, 20) #define TRCACATRN_TYPE_MASK GENMASK(1, 0) #define TRCACATRN_CONTEXTTYPE_MASK GENMASK(3, 2) #define TRCACATRN_CONTEXTTYPE_CTXID BIT(2) #define TRCACATRN_CONTEXTTYPE_VMID BIT(3) #define TRCACATRN_CONTEXT_MASK GENMASK(6, 4) #define TRCACATRN_EXLEVEL_MASK GENMASK(14, 8) #define TRCSSCSRN_STATUS BIT(31) #define TRCSSCCRN_SAC_ARC_RST_MASK GENMASK(24, 0) #define TRCSSPCICRN_PC_MASK GENMASK(7, 0) #define TRCBBCTLR_MODE BIT(8) #define TRCBBCTLR_RANGE_MASK GENMASK(7, 0) #define TRCRSCTLRN_PAIRINV BIT(21) #define TRCRSCTLRN_INV BIT(20) #define TRCRSCTLRN_GROUP_MASK GENMASK(19, 16) #define TRCRSCTLRN_SELECT_MASK GENMASK(15, 0) #define TRFCR_ELX_TS_SHIFT 5 #define TRFCR_ELX_TS_VIRTUAL ((0x1UL) << TRFCR_ELX_TS_SHIFT) #define TRFCR_EL2_CX BIT(3) #define TRFCR_ELX_E1TRE BIT(1) #define TRFCR_ELX_E0TRE BIT(0) #define CURRENTEL_EL2 (2 << 2) /* TRCDEVARCH Bit field definitions * Bits[31:21] - ARCHITECT = Always Arm Ltd. * * Bits[31:28] = 0x4 * * Bits[27:21] = 0b0111011 * Bit[20] - PRESENT, Indicates the presence of this register. * * Bit[19:16] - REVISION, Revision of the architecture. * * Bit[15:0] - ARCHID, Identifies this component as an ETM * * Bits[15:12] - architecture version of ETM * * = 4 for ETMv4 * * Bits[11:0] = 0xA13, architecture part number for ETM. */ #define TRCDEVARCH_REVISION_SHIFT 16 #define TRCDEVARCH_REVISION_MASK GENMASK(19, 16) #define TRCDEVARCH_REVISION(x) \ (((x) & TRCDEVARCH_REVISION_MASK) >> TRCDEVARCH_REVISION_SHIFT) #define TRCDEVARCH_ARCHID_ARCH_VER_SHIFT 12 #define TRCDEVARCH_ARCHID_ARCH_VER_MASK GENMASK(15, 12) #define TRCDEVARCH_ARCHID_ARCH_VER(x) \ (((x) & TRCDEVARCH_ARCHID_ARCH_VER_MASK) >> TRCDEVARCH_ARCHID_ARCH_VER_SHIFT) #define ID_AA64DFR0_EL1_TRACEFILT_SHIFT 40 #define ID_AA64DFR0_EL1_TRACEFILT_MASK GENMASK(43, 40) #define ID_AA64DFR0_EL1_TRACEFILT(x) \ (((x) & ID_AA64DFR0_EL1_TRACEFILT_MASK) >> ID_AA64DFR0_EL1_TRACEFILT_SHIFT) #define TRCSTATR_IDLE_BIT BIT(0) #define TRCSTATR_PMSTABLE_BIT BIT(1) #define TRCSSCSRN_PC BIT(3) /* PowerDown Control Register bits */ #define TRCPDCR_PU BIT(3) /* Driver representation of the ETM architecture. * The version of an ETM component can be detected from * * TRCDEVARCH - CoreSight architected register * - Bits[15:12] - Major version * - Bits[19:16] - Minor version * * We must rely only on TRCDEVARCH for the version information. Even though, * TRCIDR1 also provides the architecture version, it is a "Trace" register * and as such must be accessed only with Trace power domain ON. This may * not be available at probe time. * * Now to make certain decisions easier based on the version * we use an internal representation of the version in the * driver, as follows : * * ETM4_ARCH_VERSION[7:0], where : * Bits[7:4] - Major version * Bits[3:0] - Minro version */ #define ETM4_ARCH_VERSION(major, minor) ((((major) & 0xf) << 4) | (((minor) & 0xf))) #define ETM4_ARCH_V4 ETM4_ARCH_VERSION(4, 0) #define ETM4_ARCH_V4_3 ETM4_ARCH_VERSION(4, 3) #define ETM4_ARCH_ETE ETM4_ARCH_VERSION(5, 0) #define ETM4_ARCH_V3_3 ETM4_ARCH_VERSION(3, 3) #define ETM4_ARCH_V3_5 ETM4_ARCH_VERSION(3, 5) #define PFT_ARCH_V1_0 ETM4_ARCH_VERSION(1, 0) #define PFT_ARCH_V1_1 ETM4_ARCH_VERSION(1, 1) /* Below are the definition of bit offsets for perf option */ #define ETM4_OPT_BRANCH_BROADCAST 8 #define ETM4_OPT_CYCACC 12 #define ETM4_OPT_RETSTK 29 /* ETMv4 CONFIGR programming bits for the ETM OPTs */ #define ETM4_CFG_BIT_BB 3 /* ETMv4 programming modes */ #define ETM4_MODE_VIEWINST_STARTSTOP BIT(27) /* System instructions to access ETM registers */ #define ETM4_READ_CASE(res, x, y) \ case (x): \ (res) = read_sysreg(y); \ break; #define ETM4_WRITE_CASE(val, x, y) \ case (x): \ write_sysreg((val), y); \ break; /* List of registers accessible via System instructions */ #define ETM4_READ_ONLY_SYSREG_CASES(res) \ ETM4_READ_CASE(res, TRCIDR9, trcidr9) \ ETM4_READ_CASE(res, TRCIDR12, trcidr12) \ ETM4_READ_CASE(res, TRCIDR1, trcidr1) \ ETM4_READ_CASE(res, TRCIDR4, trcidr4) \ ETM4_READ_CASE(res, TRCIDR7, trcidr7) \ ETM4_READ_CASE(res, TRCOSLSR, trcoslsr) \ ETM4_READ_CASE(res, TRCSTATR, trcstatr) \ ETM4_READ_CASE(res, TRCIDR8, trcidr8) \ ETM4_READ_CASE(res, TRCIDR10, trcidr10) \ ETM4_READ_CASE(res, TRCIDR11, trcidr11) \ ETM4_READ_CASE(res, TRCIDR13, trcidr13) \ ETM4_READ_CASE(res, TRCIDR0, trcidr0) \ ETM4_READ_CASE(res, TRCIDR2, trcidr2) \ ETM4_READ_CASE(res, TRCIDR3, trcidr3) \ ETM4_READ_CASE(res, TRCIDR5, trcidr5) \ ETM4_READ_CASE(res, TRCIDR6, trcidr6) #define ETM4_WRITE_ONLY_SYSREG_CASES(val) \ ETM4_WRITE_CASE(val, TRCOSLAR, trcoslar) #define ETM4_READ_WRITE_SYSREG_CASES(op, val) \ ETM4_##op##_CASE(val, TRCPRGCTLR, trcprgctlr) \ ETM4_##op##_CASE(val, TRCCONFIGR, trcconfigr) \ ETM4_##op##_CASE(val, TRCAUXCTLR, trcauxctlr) \ ETM4_##op##_CASE(val, TRCEVENTCTL0R, trceventctl0r) \ ETM4_##op##_CASE(val, TRCEVENTCTL1R, trceventctl1r) \ ETM4_##op##_CASE(val, TRCSTALLCTLR, trcstallctlr) \ ETM4_##op##_CASE(val, TRCTSCTLR, trctsctlr) \ ETM4_##op##_CASE(val, TRCSYNCPR, trcsyncpr) \ ETM4_##op##_CASE(val, TRCCCCTLR, trcccctlr) \ ETM4_##op##_CASE(val, TRCBBCTLR, trcbbctlr) \ ETM4_##op##_CASE(val, TRCTRACEIDR, trctraceidr) \ ETM4_##op##_CASE(val, TRCQCTLR, trcqctlr) \ ETM4_##op##_CASE(val, TRCVICTLR, trcvictlr) \ ETM4_##op##_CASE(val, TRCVIIECTLR, trcviiectlr) \ ETM4_##op##_CASE(val, TRCVISSCTLR, trcvissctlr) \ ETM4_##op##_CASE(val, TRCVIPCSSCTLR, trcvipcssctlr) \ ETM4_##op##_CASE(val, TRCSEQEVRN(0), trcseqevr0) \ ETM4_##op##_CASE(val, TRCSEQEVRN(1), trcseqevr1) \ ETM4_##op##_CASE(val, TRCSEQEVRN(2), trcseqevr2) \ ETM4_##op##_CASE(val, TRCSEQRSTEVR, trcseqrstevr) \ ETM4_##op##_CASE(val, TRCSEQSTR, trcseqstr) \ ETM4_##op##_CASE(val, TRCEXTINSELR, trcextinselr) \ ETM4_##op##_CASE(val, TRCCNTRLDVRN(0), trccntrldvr0) \ ETM4_##op##_CASE(val, TRCCNTRLDVRN(1), trccntrldvr1) \ ETM4_##op##_CASE(val, TRCCNTRLDVRN(2), trccntrldvr2) \ ETM4_##op##_CASE(val, TRCCNTRLDVRN(3), trccntrldvr3) \ ETM4_##op##_CASE(val, TRCCNTCTLRN(0), trccntctlr0) \ ETM4_##op##_CASE(val, TRCCNTCTLRN(1), trccntctlr1) \ ETM4_##op##_CASE(val, TRCCNTCTLRN(2), trccntctlr2) \ ETM4_##op##_CASE(val, TRCCNTCTLRN(3), trccntctlr3) \ ETM4_##op##_CASE(val, TRCCNTVRN(0), trccntvr0) \ ETM4_##op##_CASE(val, TRCCNTVRN(1), trccntvr1) \ ETM4_##op##_CASE(val, TRCCNTVRN(2), trccntvr2) \ ETM4_##op##_CASE(val, TRCCNTVRN(3), trccntvr3) \ ETM4_##op##_CASE(val, TRCIMSPECN(0), trcimspec0) \ ETM4_##op##_CASE(val, TRCIMSPECN(1), trcimspec1) \ ETM4_##op##_CASE(val, TRCIMSPECN(2), trcimspec2) \ ETM4_##op##_CASE(val, TRCIMSPECN(3), trcimspec3) \ ETM4_##op##_CASE(val, TRCIMSPECN(4), trcimspec4) \ ETM4_##op##_CASE(val, TRCIMSPECN(5), trcimspec5) \ ETM4_##op##_CASE(val, TRCIMSPECN(6), trcimspec6) \ ETM4_##op##_CASE(val, TRCIMSPECN(7), trcimspec7) \ ETM4_##op##_CASE(val, TRCRSCTLRN(2), trcrsctlr2) \ ETM4_##op##_CASE(val, TRCRSCTLRN(3), trcrsctlr3) \ ETM4_##op##_CASE(val, TRCRSCTLRN(4), trcrsctlr4) \ ETM4_##op##_CASE(val, TRCRSCTLRN(5), trcrsctlr5) \ ETM4_##op##_CASE(val, TRCRSCTLRN(6), trcrsctlr6) \ ETM4_##op##_CASE(val, TRCRSCTLRN(7), trcrsctlr7) \ ETM4_##op##_CASE(val, TRCRSCTLRN(8), trcrsctlr8) \ ETM4_##op##_CASE(val, TRCRSCTLRN(9), trcrsctlr9) \ ETM4_##op##_CASE(val, TRCRSCTLRN(10), trcrsctlr10) \ ETM4_##op##_CASE(val, TRCRSCTLRN(11), trcrsctlr11) \ ETM4_##op##_CASE(val, TRCRSCTLRN(12), trcrsctlr12) \ ETM4_##op##_CASE(val, TRCRSCTLRN(13), trcrsctlr13) \ ETM4_##op##_CASE(val, TRCRSCTLRN(14), trcrsctlr14) \ ETM4_##op##_CASE(val, TRCRSCTLRN(15), trcrsctlr15) \ ETM4_##op##_CASE(val, TRCRSCTLRN(16), trcrsctlr16) \ ETM4_##op##_CASE(val, TRCRSCTLRN(17), trcrsctlr17) \ ETM4_##op##_CASE(val, TRCRSCTLRN(18), trcrsctlr18) \ ETM4_##op##_CASE(val, TRCRSCTLRN(19), trcrsctlr19) \ ETM4_##op##_CASE(val, TRCRSCTLRN(20), trcrsctlr20) \ ETM4_##op##_CASE(val, TRCRSCTLRN(21), trcrsctlr21) \ ETM4_##op##_CASE(val, TRCRSCTLRN(22), trcrsctlr22) \ ETM4_##op##_CASE(val, TRCRSCTLRN(23), trcrsctlr23) \ ETM4_##op##_CASE(val, TRCRSCTLRN(24), trcrsctlr24) \ ETM4_##op##_CASE(val, TRCRSCTLRN(25), trcrsctlr25) \ ETM4_##op##_CASE(val, TRCRSCTLRN(26), trcrsctlr26) \ ETM4_##op##_CASE(val, TRCRSCTLRN(27), trcrsctlr27) \ ETM4_##op##_CASE(val, TRCRSCTLRN(28), trcrsctlr28) \ ETM4_##op##_CASE(val, TRCRSCTLRN(29), trcrsctlr29) \ ETM4_##op##_CASE(val, TRCRSCTLRN(30), trcrsctlr30) \ ETM4_##op##_CASE(val, TRCRSCTLRN(31), trcrsctlr31) \ ETM4_##op##_CASE(val, TRCSSCCRN(0), trcssccr0) \ ETM4_##op##_CASE(val, TRCSSCCRN(1), trcssccr1) \ ETM4_##op##_CASE(val, TRCSSCCRN(2), trcssccr2) \ ETM4_##op##_CASE(val, TRCSSCCRN(3), trcssccr3) \ ETM4_##op##_CASE(val, TRCSSCCRN(4), trcssccr4) \ ETM4_##op##_CASE(val, TRCSSCCRN(5), trcssccr5) \ ETM4_##op##_CASE(val, TRCSSCCRN(6), trcssccr6) \ ETM4_##op##_CASE(val, TRCSSCCRN(7), trcssccr7) \ ETM4_##op##_CASE(val, TRCSSCSRN(0), trcsscsr0) \ ETM4_##op##_CASE(val, TRCSSCSRN(1), trcsscsr1) \ ETM4_##op##_CASE(val, TRCSSCSRN(2), trcsscsr2) \ ETM4_##op##_CASE(val, TRCSSCSRN(3), trcsscsr3) \ ETM4_##op##_CASE(val, TRCSSCSRN(4), trcsscsr4) \ ETM4_##op##_CASE(val, TRCSSCSRN(5), trcsscsr5) \ ETM4_##op##_CASE(val, TRCSSCSRN(6), trcsscsr6) \ ETM4_##op##_CASE(val, TRCSSCSRN(7), trcsscsr7) \ ETM4_##op##_CASE(val, TRCSSPCICRN(0), trcsspcicr0) \ ETM4_##op##_CASE(val, TRCSSPCICRN(1), trcsspcicr1) \ ETM4_##op##_CASE(val, TRCSSPCICRN(2), trcsspcicr2) \ ETM4_##op##_CASE(val, TRCSSPCICRN(3), trcsspcicr3) \ ETM4_##op##_CASE(val, TRCSSPCICRN(4), trcsspcicr4) \ ETM4_##op##_CASE(val, TRCSSPCICRN(5), trcsspcicr5) \ ETM4_##op##_CASE(val, TRCSSPCICRN(6), trcsspcicr6) \ ETM4_##op##_CASE(val, TRCSSPCICRN(7), trcsspcicr7) \ ETM4_##op##_CASE(val, TRCACVRN(0), trcacvr0) \ ETM4_##op##_CASE(val, TRCACVRN(1), trcacvr1) \ ETM4_##op##_CASE(val, TRCACVRN(2), trcacvr2) \ ETM4_##op##_CASE(val, TRCACVRN(3), trcacvr3) \ ETM4_##op##_CASE(val, TRCACVRN(4), trcacvr4) \ ETM4_##op##_CASE(val, TRCACVRN(5), trcacvr5) \ ETM4_##op##_CASE(val, TRCACVRN(6), trcacvr6) \ ETM4_##op##_CASE(val, TRCACVRN(7), trcacvr7) \ ETM4_##op##_CASE(val, TRCACVRN(8), trcacvr8) \ ETM4_##op##_CASE(val, TRCACVRN(9), trcacvr9) \ ETM4_##op##_CASE(val, TRCACVRN(10), trcacvr10) \ ETM4_##op##_CASE(val, TRCACVRN(11), trcacvr11) \ ETM4_##op##_CASE(val, TRCACVRN(12), trcacvr12) \ ETM4_##op##_CASE(val, TRCACVRN(13), trcacvr13) \ ETM4_##op##_CASE(val, TRCACVRN(14), trcacvr14) \ ETM4_##op##_CASE(val, TRCACVRN(15), trcacvr15) \ ETM4_##op##_CASE(val, TRCACATRN(0), trcacatr0) \ ETM4_##op##_CASE(val, TRCACATRN(1), trcacatr1) \ ETM4_##op##_CASE(val, TRCACATRN(2), trcacatr2) \ ETM4_##op##_CASE(val, TRCACATRN(3), trcacatr3) \ ETM4_##op##_CASE(val, TRCACATRN(4), trcacatr4) \ ETM4_##op##_CASE(val, TRCACATRN(5), trcacatr5) \ ETM4_##op##_CASE(val, TRCACATRN(6), trcacatr6) \ ETM4_##op##_CASE(val, TRCACATRN(7), trcacatr7) \ ETM4_##op##_CASE(val, TRCACATRN(8), trcacatr8) \ ETM4_##op##_CASE(val, TRCACATRN(9), trcacatr9) \ ETM4_##op##_CASE(val, TRCACATRN(10), trcacatr10) \ ETM4_##op##_CASE(val, TRCACATRN(11), trcacatr11) \ ETM4_##op##_CASE(val, TRCACATRN(12), trcacatr12) \ ETM4_##op##_CASE(val, TRCACATRN(13), trcacatr13) \ ETM4_##op##_CASE(val, TRCACATRN(14), trcacatr14) \ ETM4_##op##_CASE(val, TRCACATRN(15), trcacatr15) \ ETM4_##op##_CASE(val, TRCDVCVRN(0), trcdvcvr0) \ ETM4_##op##_CASE(val, TRCDVCVRN(1), trcdvcvr1) \ ETM4_##op##_CASE(val, TRCDVCVRN(2), trcdvcvr2) \ ETM4_##op##_CASE(val, TRCDVCVRN(3), trcdvcvr3) \ ETM4_##op##_CASE(val, TRCDVCVRN(4), trcdvcvr4) \ ETM4_##op##_CASE(val, TRCDVCVRN(5), trcdvcvr5) \ ETM4_##op##_CASE(val, TRCDVCVRN(6), trcdvcvr6) \ ETM4_##op##_CASE(val, TRCDVCVRN(7), trcdvcvr7) \ ETM4_##op##_CASE(val, TRCDVCMRN(0), trcdvcmr0) \ ETM4_##op##_CASE(val, TRCDVCMRN(1), trcdvcmr1) \ ETM4_##op##_CASE(val, TRCDVCMRN(2), trcdvcmr2) \ ETM4_##op##_CASE(val, TRCDVCMRN(3), trcdvcmr3) \ ETM4_##op##_CASE(val, TRCDVCMRN(4), trcdvcmr4) \ ETM4_##op##_CASE(val, TRCDVCMRN(5), trcdvcmr5) \ ETM4_##op##_CASE(val, TRCDVCMRN(6), trcdvcmr6) \ ETM4_##op##_CASE(val, TRCDVCMRN(7), trcdvcmr7) \ ETM4_##op##_CASE(val, TRCCIDCVRN(0), trccidcvr0) \ ETM4_##op##_CASE(val, TRCCIDCVRN(1), trccidcvr1) \ ETM4_##op##_CASE(val, TRCCIDCVRN(2), trccidcvr2) \ ETM4_##op##_CASE(val, TRCCIDCVRN(3), trccidcvr3) \ ETM4_##op##_CASE(val, TRCCIDCVRN(4), trccidcvr4) \ ETM4_##op##_CASE(val, TRCCIDCVRN(5), trccidcvr5) \ ETM4_##op##_CASE(val, TRCCIDCVRN(6), trccidcvr6) \ ETM4_##op##_CASE(val, TRCCIDCVRN(7), trccidcvr7) \ ETM4_##op##_CASE(val, TRCVMIDCVRN(0), trcvmidcvr0) \ ETM4_##op##_CASE(val, TRCVMIDCVRN(1), trcvmidcvr1) \ ETM4_##op##_CASE(val, TRCVMIDCVRN(2), trcvmidcvr2) \ ETM4_##op##_CASE(val, TRCVMIDCVRN(3), trcvmidcvr3) \ ETM4_##op##_CASE(val, TRCVMIDCVRN(4), trcvmidcvr4) \ ETM4_##op##_CASE(val, TRCVMIDCVRN(5), trcvmidcvr5) \ ETM4_##op##_CASE(val, TRCVMIDCVRN(6), trcvmidcvr6) \ ETM4_##op##_CASE(val, TRCVMIDCVRN(7), trcvmidcvr7) \ ETM4_##op##_CASE(val, TRCCIDCCTLR0, trccidcctlr0) \ ETM4_##op##_CASE(val, TRCCIDCCTLR1, trccidcctlr1) \ ETM4_##op##_CASE(val, TRCVMIDCCTLR0, trcvmidcctlr0) \ ETM4_##op##_CASE(val, TRCVMIDCCTLR1, trcvmidcctlr1) \ ETM4_##op##_CASE(val, TRCCLAIMSET, trcclaimset) \ ETM4_##op##_CASE(val, TRCCLAIMCLR, trcclaimclr) \ ETM4_##op##_CASE(val, TRCAUTHSTATUS, trcauthstatus) \ ETM4_##op##_CASE(val, TRCDEVARCH, trcdevarch) \ ETM4_##op##_CASE(val, TRCDEVID, trcdevid) \ ETM4_##op##_CASE(val, TRCPROCSELR, trcprocselr) \ ETM4_##op##_CASE(val, TRCVDCTLR, trcvdctlr) \ ETM4_##op##_CASE(val, TRCVDSACCTLR, trcvdsacctlr) \ ETM4_##op##_CASE(val, TRCVDARCCTLR, trcvdarcctlr) #define ETM4_READ_SYSREG_CASES(res) \ ETM4_READ_WRITE_SYSREG_CASES(READ, (res)) \ ETM4_READ_ONLY_SYSREG_CASES((res)) #define ETM4_WRITE_SYSREG_CASES(val) \ ETM4_READ_WRITE_SYSREG_CASES(WRITE, (val)) \ ETM4_WRITE_ONLY_SYSREG_CASES((val)) /**************************************************************************** * Private Functions Prototypes ****************************************************************************/ static int etm4_enable(FAR struct coresight_dev_s *csdev); static void etm4_disable(FAR struct coresight_dev_s *csdev); /**************************************************************************** * Private Data ****************************************************************************/ static const struct coresight_source_ops_s g_etm4_source_ops = { .enable = etm4_enable, .disable = etm4_disable, }; static const struct coresight_ops_s g_etm4_ops = { .source_ops = &g_etm4_source_ops, }; /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** * Name: etm4_sysreg_read * * Description: * Read registers using coprocessor. * ****************************************************************************/ static uint64_t etm4_sysreg_read(uint32_t offset) { uint64_t res = 0; switch (offset) { ETM4_READ_SYSREG_CASES(res) default : cserr("etm4x: trying to read unsupported register @%x\n", offset); } return res; } /**************************************************************************** * Name: etm4_sysreg_write * * Description: * Write registers using coprocessor. * ****************************************************************************/ static void etm4_sysreg_write(uint64_t val, uint32_t offset, bool bit_64) { if (!bit_64) { val &= GENMASK(31, 0); } switch (offset) { ETM4_WRITE_SYSREG_CASES(val) default : cserr("etm4x: trying to write to unsupported register @%x\n", offset); } } /**************************************************************************** * Name: etm4_devarch_to_arch * * Description: * Convert the device architecture identifier to an ETMv4 * architecture version. * ****************************************************************************/ static inline uint8_t etm4_devarch_to_arch(uint32_t devarch) { return ETM4_ARCH_VERSION(TRCDEVARCH_ARCHID_ARCH_VER(devarch), TRCDEVARCH_REVISION(devarch)); } /**************************************************************************** * Name: etm4_is_in_el2 * * Description: * Check if the current execution level is EL2. * * Returned Value: * Returns true if the current execution level is EL2, false otherwise. * ****************************************************************************/ static inline bool etm4_is_in_el2(void) { return read_sysreg(currentel) == CURRENTEL_EL2; } /**************************************************************************** * Name: etm4_write_reg32 * * Description: * Writes a 32-bit value to a specified register offset. * ****************************************************************************/ static inline void etm4_write_reg32(FAR struct coresight_etm4_dev_s *etmdev, uint32_t val, uint32_t off) { #ifdef CONFIG_CORESIGHT_ETM_USE_COPROCESSOR etm4_sysreg_write(val, off, false); #else coresight_put32(val, etmdev->csdev.addr + off); #endif } /**************************************************************************** * Name: etm4_write_reg64 * * Description: * Writes a 64-bit value to a specified register offset. * ****************************************************************************/ static inline void etm4_write_reg64(FAR struct coresight_etm4_dev_s *etmdev, uint64_t val, uint32_t off) { #ifdef CONFIG_CORESIGHT_ETM_USE_COPROCESSOR etm4_sysreg_write(val, off, true); #else coresight_put64(val, etmdev->csdev.addr + off); #endif } /**************************************************************************** * Name: etm4_read_reg32 * * Description: * Reads a 32-bit value from a specified register offset. * ****************************************************************************/ static inline uint32_t etm4_read_reg32(FAR struct coresight_etm4_dev_s *etmdev, uint32_t off) { #ifdef CONFIG_CORESIGHT_ETM_USE_COPROCESSOR return etm4_sysreg_read(off); #else return coresight_get32(etmdev->csdev.addr + off); #endif } /**************************************************************************** * Name: etm4_claim_device * * Description: * Claims the ETMv4 device for exclusive access. * ****************************************************************************/ int etm4_claim_device(FAR struct coresight_etm4_dev_s *etmdev) { int ret = -EBUSY; #ifndef CONFIG_CORESIGHT_ETM_USE_COPROCESSOR return coresight_claim_device(etmdev->csdev.addr); #endif if (etm4_read_reg32(etmdev, CORESIGHT_CLAIMCLR) != 0) { return ret; } etm4_write_reg32(etmdev, CORESIGHT_CLAIM_SELF_HOSTED, CORESIGHT_CLAIMSET); if (etm4_read_reg32(etmdev, CORESIGHT_CLAIMCLR) == CORESIGHT_CLAIM_SELF_HOSTED) { ret = 0; } else { /* There was a race setting the tags, clean up and fail */ etm4_write_reg32(etmdev, CORESIGHT_CLAIM_SELF_HOSTED, CORESIGHT_CLAIMCLR); } return ret; } /**************************************************************************** * Name: etm4_disclaim_device * * Description: * Releases the ETMv4 device from exclusive access. * ****************************************************************************/ void etm4_disclaim_device(FAR struct coresight_etm4_dev_s *etmdev) { #ifndef CONFIG_CORESIGHT_ETM_USE_COPROCESSOR return coresight_disclaim_device(etmdev->csdev.addr); #endif if (etm4_read_reg32(etmdev, CORESIGHT_CLAIMCLR) == CORESIGHT_CLAIM_SELF_HOSTED) { etm4_write_reg32(etmdev, CORESIGHT_CLAIM_SELF_HOSTED, CORESIGHT_CLAIMCLR); } else { cserr("current device is not claimed or something wrong happend\n"); } } /**************************************************************************** * Name: etm4_sspcicrn_present * * Description: * Check if a specific single-shot comparator (SSPCICRN) * is present in the ETMv4 device. * ****************************************************************************/ static inline bool etm4_sspcicrn_present(FAR struct coresight_etm4_dev_s *etmdev, int n) { return (n < etmdev->nr_ss_cmp) && etmdev->nr_pe && (etmdev->cfg.ss_status[n] & TRCSSCSRN_PC); } /**************************************************************************** * Name: etm4_lock * * Description: * Locks the ETMv4 device to prevent concurrent modifications. * ****************************************************************************/ static inline void etm4_lock(FAR struct coresight_etm4_dev_s *etmdev) { #ifndef CONFIG_CORESIGHT_ETM_USE_COPROCESSOR coresight_lock(etmdev->csdev.addr); #endif } /**************************************************************************** * Name: etm4_unlock * * Description: * Unlocks the ETMv4 device to allow other operations. * ****************************************************************************/ static inline void etm4_unlock(FAR struct coresight_etm4_dev_s *etmdev) { #ifndef CONFIG_CORESIGHT_ETM_USE_COPROCESSOR coresight_unlock(etmdev->csdev.addr); #endif } /**************************************************************************** * Name: etm4_os_unlock * * Description: * Unlocks the TRCOSLAR register of ETMv4 for further configurations. * ****************************************************************************/ static inline void etm4_os_unlock(FAR struct coresight_etm4_dev_s *etmdev) { etm4_write_reg32(etmdev, 0x0, TRCOSLAR); } /**************************************************************************** * Name: etm4_timeout * * Description: * Loop until a bitmask of register has changed to a specific value. * ****************************************************************************/ static int etm4_timeout(FAR struct coresight_etm4_dev_s *etmdev, uint32_t val, uint32_t mask, uint32_t off) { int i; for (i = CONFIG_CORESIGHT_TIMEOUT; i > 0; i--) { uint32_t value = etm4_read_reg32(etmdev, off); if ((value & mask) == val) { return 0; } up_udelay(1); } return -EAGAIN; } /**************************************************************************** * Name: etm4_enable_hw * * Description: * Enable the ETMv4 hardware by configuring various trace registers. * * Input Parameters: * etmdev - Pointer to the ETMv4 device structure. * ****************************************************************************/ static void etm4_enable_hw(FAR struct coresight_etm4_dev_s *etmdev) { FAR struct etm4_config_s *config = &etmdev->cfg; int i; etm4_unlock(etmdev); etm4_os_unlock(etmdev); /* Disable the trace unit before programming trace registers */ etm4_write_reg32(etmdev, 0, TRCPRGCTLR); /* wait for TRCSTATR.IDLE to go up */ if (etm4_timeout(etmdev, 1, TRCSTATR_IDLE_BIT, TRCSTATR)) { cserr("timeout while waiting for Idle Trace Status\n"); } if (etmdev->nr_pe) { etm4_write_reg32(etmdev, config->pe_sel, TRCPROCSELR); } etm4_write_reg32(etmdev, config->cfg, TRCCONFIGR); /* nothing specific implemented */ etm4_write_reg32(etmdev, 0x0, TRCAUXCTLR); etm4_write_reg32(etmdev, config->eventctrl0, TRCEVENTCTL0R); etm4_write_reg32(etmdev, config->eventctrl1, TRCEVENTCTL1R); if (etmdev->stallctl) { etm4_write_reg32(etmdev, config->stall_ctrl, TRCSTALLCTLR); } etm4_write_reg32(etmdev, config->ts_ctrl, TRCTSCTLR); etm4_write_reg32(etmdev, config->syncfreq, TRCSYNCPR); etm4_write_reg32(etmdev, config->ccctlr, TRCCCCTLR); etm4_write_reg32(etmdev, config->bb_ctrl, TRCBBCTLR); etm4_write_reg32(etmdev, etmdev->trcid, TRCTRACEIDR); etm4_write_reg32(etmdev, config->vinst_ctrl, TRCVICTLR); etm4_write_reg32(etmdev, config->viiectlr, TRCVIIECTLR); etm4_write_reg32(etmdev, config->vissctlr, TRCVISSCTLR); if (etmdev->nr_pe_cmp) { etm4_write_reg32(etmdev, config->vipcssctlr, TRCVIPCSSCTLR); } if (etmdev->nrseqstate) { etm4_write_reg32(etmdev, config->seq_rst, TRCSEQRSTEVR); etm4_write_reg32(etmdev, config->seq_state, TRCSEQSTR); for (i = 0; i < etmdev->nrseqstate - 1; i++) { etm4_write_reg32(etmdev, config->seq_ctrl[i], TRCSEQEVRN(i)); } } etm4_write_reg32(etmdev, config->ext_inp, TRCEXTINSELR); for (i = 0; i < etmdev->nr_cntr; i++) { etm4_write_reg32(etmdev, config->cntrldvr[i], TRCCNTRLDVRN(i)); etm4_write_reg32(etmdev, config->cntr_ctrl[i], TRCCNTCTLRN(i)); etm4_write_reg32(etmdev, config->cntr_val[i], TRCCNTVRN(i)); } /* Resource selector pair 0 is always implemented and reserved. * As such start at 2. */ for (i = 2; i < etmdev->nr_resource * 2; i++) { etm4_write_reg32(etmdev, config->res_ctrl[i], TRCRSCTLRN(i)); } for (i = 0; i < etmdev->nr_ss_cmp; i++) { /* always clear status bit on restart if using single-shot */ if (config->ss_ctrl[i] || config->ss_pe_cmp[i]) { config->ss_status[i] &= ~TRCSSCSRN_STATUS; } etm4_write_reg32(etmdev, config->ss_ctrl[i], TRCSSCCRN(i)); etm4_write_reg32(etmdev, config->ss_status[i], TRCSSCSRN(i)); if (etm4_sspcicrn_present(etmdev, i)) { etm4_write_reg32(etmdev, config->ss_pe_cmp[i], TRCSSPCICRN(i)); } } for (i = 0; i < etmdev->nr_addr_cmp * 2; i++) { etm4_write_reg64(etmdev, config->addr_val[i], TRCACVRN(i)); etm4_write_reg64(etmdev, config->addr_acc[i], TRCACATRN(i)); } for (i = 0; i < etmdev->numcidc; i++) { etm4_write_reg64(etmdev, config->ctxid_pid[i], TRCCIDCVRN(i)); } etm4_write_reg32(etmdev, config->ctxid_mask0, TRCCIDCCTLR0); if (etmdev->numcidc > 4) { etm4_write_reg32(etmdev, config->ctxid_mask1, TRCCIDCCTLR1); } for (i = 0; i < etmdev->numvmidc; i++) { etm4_write_reg64(etmdev, config->vmid_val[i], TRCVMIDCVRN(i)); } etm4_write_reg32(etmdev, config->vmid_mask0, TRCVMIDCCTLR0); if (etmdev->numvmidc > 4) { etm4_write_reg32(etmdev, config->vmid_mask1, TRCVMIDCCTLR1); } if (!etmdev->skip_power_up) { uint32_t trcpdcr = etm4_read_reg32(etmdev, TRCPDCR); /* Request to keep the trace unit powered and also * emulation of powerdown */ etm4_write_reg32(etmdev, trcpdcr | TRCPDCR_PU, TRCPDCR); } /* Enable the trace unit */ etm4_write_reg32(etmdev, 1, TRCPRGCTLR); /* wait for TRCSTATR.IDLE to go back down to '0' */ if (etm4_timeout(etmdev, 0, TRCSTATR_IDLE_BIT, TRCSTATR)) { cserr("timeout while waiting for Idle Trace Status\n"); } etm4_lock(etmdev); } /**************************************************************************** * Name: etm4_enable * * Description: * Enable the ETMv4 device. * * Input Parameters: * csdev - Pointer to the coresight device structure. * * Returned Value: * Zero on success; negative error code on failure. * ****************************************************************************/ static int etm4_enable(FAR struct coresight_dev_s *csdev) { FAR struct coresight_etm4_dev_s *etmdev = (FAR struct coresight_etm4_dev_s *)csdev; int ret; ret = etm4_claim_device(etmdev); if (ret < 0) { return ret; } etm4_enable_hw(etmdev); return ret; } /**************************************************************************** * Name: etm4_disable_hw * * Description: * Disable the ETMv4 hardware by resetting various trace registers. * * Input Parameters: * etmdev - Pointer to the ETMv4 device structure. * ****************************************************************************/ static void etm4_disable_hw(FAR struct coresight_etm4_dev_s *etmdev) { FAR struct etm4_config_s *config = &etmdev->cfg; uint32_t control; int i; etm4_unlock(etmdev); if (!etmdev->skip_power_up) { /* power can be removed from the trace unit now */ control = etm4_read_reg32(etmdev, TRCPDCR); control &= ~TRCPDCR_PU; etm4_write_reg32(etmdev, control, TRCPDCR); } control = etm4_read_reg32(etmdev, TRCPRGCTLR); /* EN, bit[0] Trace unit enable bit */ control &= ~0x1; /* If the CPU supports v8.4 Trace filter Control, * set the ETM to trace prohibited region. */ etm4_write_reg32(etmdev, control, TRCPRGCTLR); /* wait for TRCSTATR.PMSTABLE to go to '1' */ if (etm4_timeout(etmdev, 1, TRCSTATR_PMSTABLE_BIT, TRCSTATR)) { cserr("timeout while waiting for PM stable Trace Status\n"); } /* read the status of the single shot comparators */ for (i = 0; i < etmdev->nr_ss_cmp; i++) { config->ss_status[i] = etm4_read_reg32(etmdev, TRCSSCSRN(i)); } /* read back the current counter values */ for (i = 0; i < etmdev->nr_cntr; i++) { config->cntr_val[i] = etm4_read_reg32(etmdev, TRCCNTVRN(i)); } etm4_lock(etmdev); } /**************************************************************************** * Name: etm4_disable * * Description: * Disable the ETMv4 device. * * Input Parameters: * csdev - Pointer to the coresight device structure. * ****************************************************************************/ static void etm4_disable(FAR struct coresight_dev_s *csdev) { FAR struct coresight_etm4_dev_s *etmdev = (FAR struct coresight_etm4_dev_s *)csdev; etm4_disable_hw(etmdev); etm4_disclaim_device(etmdev); } /**************************************************************************** * Name: etm4_enable_trace_filtering * * Description: * Configure trace filtering for the ETMv4 device if supported by the CPU. * * Input Parameters: * etmdev - Pointer to the coresight ETM4 device structure. * ****************************************************************************/ static void etm4_enable_trace_filtering(struct coresight_etm4_dev_s *etmdev) { uint64_t dfr0 = read_sysreg(id_aa64dfr0_el1); if (!ID_AA64DFR0_EL1_TRACEFILT(dfr0)) { cserr("Trace Filter feature is not support"); return; } /* If the CPU supports v8.4 SelfHosted Tracing, enable * tracing at the kernel EL1 and EL0, forcing to use the * virtual time as the timestamp. */ etmdev->trfcr = TRFCR_ELX_TS_VIRTUAL | TRFCR_ELX_E1TRE | TRFCR_ELX_E0TRE; /* If we are running at EL2, allow tracing the CONTEXTIDR_EL2. */ if (etm4_is_in_el2()) { etmdev->trfcr |= TRFCR_EL2_CX; } write_sysreg(etmdev->trfcr, trfcr_el1); } /**************************************************************************** * Name: etm4_init_arch_data * * Description: * Initialize the architecture-specific data for the ETMv4 device. * * Input Parameters: * etmdev - Pointer to the ETMv4 device structure. * ****************************************************************************/ static void etm4_init_arch_data(FAR struct coresight_etm4_dev_s *etmdev) { uint32_t etmidr; uint32_t devarch; int i; etmdev->skip_power_up = true; /* Make sure all registers are accessible */ etm4_unlock(etmdev); etm4_os_unlock(etmdev); devarch = read_sysreg(trcdevarch); etmdev->arch = etm4_devarch_to_arch(devarch); /* find all capabilities of the tracing unit */ etmidr = etm4_read_reg32(etmdev, TRCIDR0); etmdev->instrp0 = (BMVAL(etmidr, 1, 2) == 0x3); etmdev->trcbb = etmidr & TRCIDR0_TRCBB; etmdev->trccond = etmidr & TRCIDR0_TRCCOND; etmdev->trccci = etmidr & TRCIDR0_TRCCCI; etmdev->retstack = etmidr & TRCIDR0_RETSTACK; etmdev->nr_event = BMVAL(etmidr, 10, 11); etmdev->q_support = BMVAL(etmidr, 15, 16); etmdev->ts_size = BMVAL(etmidr, 24, 28); etmidr = etm4_read_reg32(etmdev, TRCIDR2); etmdev->ctxid_size = BMVAL(etmidr, 5, 9); etmdev->vmid_size = BMVAL(etmidr, 10, 14); etmdev->ccsize = BMVAL(etmidr, 25, 28); etmidr = etm4_read_reg32(etmdev, TRCIDR3); etmdev->ccitmin = BMVAL(etmidr, 0, 11); etmdev->s_ex_level = BMVAL(etmidr, 16, 19); etmdev->cfg.s_ex_level = etmdev->s_ex_level; etmdev->ns_ex_level = BMVAL(etmidr, 20, 23); etmdev->trc_error = etmidr & TRCIDR3_TRCERR; etmdev->syncpr = etmidr & TRCIDR3_SYNCPR; etmdev->stallctl = etmidr & TRCIDR3_STALLCTL; etmdev->sysstall = etmidr & TRCIDR3_SYSSTALL; etmdev->nr_pe = (BMVAL(etmidr, 12, 13) << 3) | BMVAL(etmidr, 28, 30); etmdev->nooverflow = etmidr & TRCIDR3_NOOVERFLOW; etmidr = etm4_read_reg32(etmdev, TRCIDR4); etmdev->nr_addr_cmp = BMVAL(etmidr, 0, 3); etmdev->nr_pe_cmp = BMVAL(etmidr, 12, 15); etmdev->nr_resource = BMVAL(etmidr, 16, 19); if (etmdev->arch < ETM4_ARCH_V4_3 || etmdev->nr_resource > 0) { etmdev->nr_resource += 1; } etmdev->nr_ss_cmp = BMVAL(etmidr, 20, 23); for (i = 0; i < etmdev->nr_ss_cmp; i++) { etmdev->cfg.ss_status[i] = etm4_read_reg32(etmdev, TRCSSCSRN(i)); } etmdev->numcidc = BMVAL(etmidr, 24, 27); etmdev->numvmidc = BMVAL(etmidr, 28, 31); etmidr = etm4_read_reg32(etmdev, TRCIDR5); etmdev->nr_ext_inp = BMVAL(etmidr, 0, 8); etmdev->trcid_size = BMVAL(etmidr, 16, 21); etmdev->atbtrig = etmidr & TRCIDR5_ATBTRIG; etmdev->lpoverride = (etmidr & TRCIDR5_LPOVERRIDE) && (!etmdev->skip_power_up); etmdev->nrseqstate = BMVAL(etmidr, 25, 27); etmdev->nr_cntr = BMVAL(etmidr, 28, 30); etm4_lock(etmdev); etm4_enable_trace_filtering(etmdev); } /**************************************************************************** * Name: etm4_set_default * * Description: * Set default configuration values for the ETMv4 device. * * Input Parameters: * config - Pointer to the ETMv4 configuration structure. * ****************************************************************************/ static void etm4_set_default(FAR struct etm4_config_s *config) { /* enable trace synchronization every 4096 bytes, if available */ config->syncfreq = 0xc; /* TRCVICTLR::EVENT = 0x01, select the always on logic */ config->vinst_ctrl = BIT(0); /* TRCVICTLR::SSSTATUS == 1, the start-stop logic is * in the started state */ config->vinst_ctrl |= TRCVICTLR_SSSTATUS; config->mode |= ETM4_MODE_VIEWINST_STARTSTOP; } /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: etm4_config * * Description: * Configure the ETMv4 device based on the provided configuration. * * Input Parameters: * etmdev - Pointer to the ETMv4 device structure. * config - Pointer to the ETMv4 configuration structure. * ****************************************************************************/ int etm4_config(FAR struct coresight_etm4_dev_s *etmdev, FAR const struct etm4_config_s *config) { etm4_unlock(etmdev); etm4_os_unlock(etmdev); memcpy(&etmdev->cfg, config, sizeof(struct etm4_config_s)); etm4_lock(etmdev); return 0; } /**************************************************************************** * Name: etm4_register * * Description: * Register an ETMv4 device with the system. * * Input Parameters: * desc - Pointer to the description of the coresight device. * * Returned Value: * Pointer to the ETMv4 device structure on success; NULL on failure. * ****************************************************************************/ FAR struct coresight_etm4_dev_s * etm4_register(FAR const struct coresight_desc_s *desc) { FAR struct coresight_etm4_dev_s *etmdev; FAR struct coresight_dev_s *csdev; int ret; etmdev = kmm_zalloc(sizeof(struct coresight_etm4_dev_s)); if (etmdev == NULL) { cserr("%s:malloc failed!\n", desc->name); return NULL; } etmdev->cpu = desc->cpu; etmdev->csdev.addr = desc->addr; etm4_init_arch_data(etmdev); etmdev->trcid = coresight_get_cpu_trace_id(etmdev->cpu); etm4_set_default(&etmdev->cfg); csdev = &etmdev->csdev; csdev->ops = &g_etm4_ops; ret = coresight_register(csdev, desc); if (ret < 0) { kmm_free(etmdev); cserr("%s:register failed\n", desc->name); return NULL; } return etmdev; } /**************************************************************************** * Name: etm4_unregister * * Description: * Unregister an ETMv4 device from the system. * * Input Parameters: * etmdev - Pointer to the ETMv4 device structure. * ****************************************************************************/ void etm4_unregister(FAR struct coresight_etm4_dev_s *etmdev) { coresight_unregister(&etmdev->csdev); kmm_free(etmdev); }