/* * pmu.h * * Copyright (c) 2019 Semidrive Semiconductor. * All rights reserved. * * Description: Cortex V7R Performance Monitor driver. * * Revision History: * ----------------- */ #ifndef INCLUDE_ARCH_PMU_H #define INCLUDE_ARCH_PMU_H #include #include typedef enum pmu_evt_cntr { PMU_EVT_COUNTER1 = 0, PMU_EVT_COUNTER2 = 1, PMU_EVT_COUNTER3 = 2, } pmu_evt_cntr_e; typedef enum pmu_evt { PMU_EVT_SOFTWARE_INCREMENT = 0x0, PMU_EVT_ICACHE_MISS = 0x1, PMU_EVT_DCACHE_MISS = 0x3, PMU_EVT_DCACHE_ACCESS = 0x4, PMU_EVT_DATA_READ = 0x6, PMU_EVT_DATA_WRITE = 0x7, PMU_EVT_INSTRUCTION_EXECUTED = 0x8, PMU_EVT_DUAL_ISSUED_INSTUCTIONS = 0x5e, PMU_EVT_EXECPTION_TAKEN = 0x9, PMU_EVT_EXECPTION_RETURN = 0xa, PMU_EVT_CHANGE_CONTEXT_ID = 0xb, PMU_EVT_SW_CHANGE_PC = 0xc, PMU_EVT_BRANCH_IMMEDIATE = 0xd, PMU_EVT_PROCEDURE_RETURN = 0xe, PMU_EVT_UNALIGNED_ACCESS = 0xf, PMU_EVT_BRANCH_NOT_PREDICTED = 0x10, PMU_EVT_CYCLE_CNT = 0x11, PMU_EVT_BRANCH_PREDICTED = 0x12, PMU_EVT_STALL_INSTRUCTION = 0x40, PMU_EVT_STALL_DATA_DEPENDENCY = 0x41, PMU_EVT_DCACHE_WRITE_BACK = 0x42, PMU_EVT_EXT_MEMORY_REQ = 0x43, PMU_EVT_STALL_LSU_BUSY = 0x44, PMU_EVT_DRAIN_STORE_BUFFER = 0x45, PMU_EVT_FIQ_DISABLE_CYCLES = 0x46, PMU_EVT_IRQ_DISABLE_CYCLES = 0x47, PMU_EVT_ETMEXTOUTM0 = 0x48, PMU_EVT_ETMEXTOUTM1 = 0x49, PMU_EVT_ICACHE_TAG_ECCERR = 0x4a, PMU_EVT_ICACHE_DATA_ECCERR = 0x4b, PMU_EVT_DCACHE_TAG_ECCERR = 0x4c, PMU_EVT_DCACHE_DATA_ECCERR = 0x4d, PMU_EVT_TCM_ECCERR_PFU = 0x4e, PMU_EVT_TCM_ECCERR_LSU = 0x4f, PMU_EVT_STORE_BUFFER_MERGE = 0x50, PMU_EVT_LSU_STALL_BY_STORE_BUFFER = 0x51, PMU_EVT_LSU_STALL_BY_STORE_QUEUE = 0x52, PMU_EVT_INT_DIV = 0x53, PMU_EVT_STALL_CYCLE_BY_INT_DIV = 0x54, PMU_EVT_PLD_LINEFILL = 0x55, PMU_EVT_PLD_NO_LINEFILL = 0x56, PMU_EVT_NON_CACHEABLE_AXI_ACCESS = 0x57, PMU_EVT_ICACHE_ACCESS = 0x58, PMU_EVT_STORE_BUFFER_SLOT_ATTR_CONFLICT = 0x59, PMU_EVT_DUAL_ISSUE_CASE_A = 0x5a, PMU_EVT_DUAL_ISSUE_CASE_B1_B2_F2_F2D = 0x5b, PMU_EVT_DUAL_ISSUE_CASE_OTHER = 0x5c, PMU_EVT_DOUBLE_PRECISION_FLOAT_EXEC = 0x5d, PMU_EVT_DCACHE_DATA_FATAL_ECCERR = 0x60, PMU_EVT_DCACHE_TAG_FATAL_ECCERR = 0x61, PMU_EVT_PROCESSOR_LIVELOCK = 0x62, PMU_EVT_ATCM_MB_ECCERR = 0x64, PMU_EVT_B0TCM_MB_ECCERR = 0x65, PMU_EVT_B1TCM_MB_ECCERR = 0x66, PMU_EVT_ATCM_SB_ECCERR = 0x67, PMU_EVT_B0TCM_SB_ECCERR = 0x68, PMU_EVT_B1TCM_SB_ECCERR = 0x69, PMU_EVT_TCM_CORRECTABLE_ECCERR_LSU = 0x6a, PMU_EVT_TCM_CORRECTABLE_ECCERR_PFU = 0x6b, PMU_EVT_TCM_FATAL_ECCERR_AXI_SLAVE = 0x6c, PMU_EVT_TCM_CORRECTABLE_ECCERR_AXI_SLAVE = 0x6d, PMU_EVT_CORRECTABLE_EVENTS = 0x6e, PMU_EVT_FATAL_EVENTS = 0x6f, PMU_EVT_CORRECTABLE_BUS_FAULTS = 0x70, PMU_EVT_FATAL_BUS_FAULTS = 0x71, PMU_EVT_ACP_DCACHE_ACCESS = 0x72, PMU_EVT_ACP_DCACHE_INVALIDATE = 0x73, } pmu_evt_e; #define PMCR_E (1 << 0) /* pmu enable */ #define PMCR_P (1 << 1) /* event counter reset */ #define PMCR_C (1 << 2) /* cycle counter reset */ #define PMCR_D (1 << 3) /* count every 64 clock cycles */ #if CONFIG_ARM_WITH_PMU /* Enable the PMU. All counters are cleared. */ static inline void pmu_enable(void) { uint32_t val = arm_read_pmcr(); val |= PMCR_P | PMCR_C | PMCR_E; arm_write_pmcr(val); } /* Diable the PMU. All counters are cleared. */ static inline void pmu_disable(void) { uint32_t val = arm_read_pmcr(); val &= ~(PMCR_P | PMCR_C | PMCR_E); arm_write_pmcr(val); } /* Get cycle counter enable status */ static inline bool pmu_cycle_cntr_status(void) { uint32_t val = arm_read_pmcntenset(); return !!(val & (1U << 31)); } /* Start cycle counter. Set div64 = true to count every * 64 clock cycles. */ static inline void pmu_start_cycle_cntr(bool div64) { uint32_t val = arm_read_pmcr(); if (div64) val |= PMCR_D; else val &= ~PMCR_D; arm_write_pmcr(val); arm_write_pmcntenset(1U << 31); } /* Stop cycle counter. */ static inline void pmu_stop_cycle_cntr(void) { arm_write_pmcntenclr(1U << 31); } /* Stop and clear the cycle counter. */ static inline void pmu_stop_clear_cycle_cntr(void) { pmu_stop_cycle_cntr(); arm_write_pmccntr(0); } /* Get cycle counter value. */ static inline uint32_t pmu_get_cycle_cntr(void) { return arm_read_pmccntr(); } /* Bind event counter to specific event and start it. */ static inline void pmu_start_evt_cntr(pmu_evt_cntr_e cntr, pmu_evt_e evt) { arm_write_pmselr(cntr); arm_write_pmxevtyper(evt); arm_write_pmcntenset(1 << cntr); } /* Stop event counter without clearing. */ static inline void pmu_stop_evt_cntr(pmu_evt_cntr_e cntr) { arm_write_pmcntenclr(1 << cntr); } /* Stop and clear the event counter. */ static inline void pmu_stop_clear_evt_cntr(pmu_evt_cntr_e cntr) { pmu_stop_evt_cntr(cntr); arm_write_pmselr(cntr); arm_write_pmxevcntr(0); } /* Get event counter value. */ static inline uint32_t pmu_get_evt_cntr(pmu_evt_cntr_e cntr) { arm_write_pmselr(cntr); return arm_read_pmxevcntr(); } #else #define pmu_enable() #define pmu_disable() #define pmu_start_cycle_cntr(div64) #define pmu_stop_cycle_cntr() #define pmu_stop_clear_cycle_cntr() #define pmu_get_cycle_cntr() #define pmu_start_evt_cntr() #define pmu_stop_evt_cntr() #define pmu_stop_clear_evt_cntr() #define pmu_get_evt_cntr() #endif #endif /* ARCH_ARM_PMU_H */