From 8e32b0b72be3b109a921bcb33778eb515d27ef70 Mon Sep 17 00:00:00 2001 From: Bhavik Patel Date: Tue, 23 Jun 2020 13:48:25 +0200 Subject: Move PMU functions from pmu_ethosu.h to ethosu_pmu.c This change is done as a prerequisite to be able to set base address for NPU through ethosu_init(). So instead of using a mamory mapped struct we use the same functions to read/write PMU registers as the rest of the ethos-u driver. Change-Id: Ie1f6e6af4627cbe9375e2b2d079ba8017b6294d3 --- src/ethosu_pmu.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 192 insertions(+), 19 deletions(-) (limited to 'src/ethosu_pmu.c') diff --git a/src/ethosu_pmu.c b/src/ethosu_pmu.c index 5e5490c..1d3b66c 100644 --- a/src/ethosu_pmu.c +++ b/src/ethosu_pmu.c @@ -34,24 +34,21 @@ #define COMMA , #define SEMICOLON ; -#define ETHOSU_PMU_CTRL_BASE (NPU_BASE + ((uint32_t)0x180)) -#define ETHOSU_PMU_CNTR_BASE (NPU_BASE + ((uint32_t)0x300)) -#define ETHOSU_PMU_EVNT_BASE (NPU_BASE + ((uint32_t)0x380)) - #define EVTYPE(A, name) \ case PMU_EVENT_TYPE_##name: \ return ETHOSU_PMU_##name #define EVID(A, name) (PMU_EVENT_TYPE_##name) +#define ETHOSU_PMCCNTR_CFG_START_STOP_EVENT_MASK (0x3FF) + +#define NPU_REG_PMEVCNTR(x) (NPU_REG_PMEVCNTR0 + ((x) * sizeof(uint32_t))) +#define NPU_REG_PMEVTYPER(x) (NPU_REG_PMEVTYPER0 + ((x) * sizeof(uint32_t))) + /***************************************************************************** * Variables *****************************************************************************/ -PMU_Ethosu_ctrl_Type *ethosu_pmu_ctrl = (PMU_Ethosu_ctrl_Type *)ETHOSU_PMU_CTRL_BASE; -PMU_Ethosu_cntr_Type *ethosu_pmu_cntr = (PMU_Ethosu_cntr_Type *)ETHOSU_PMU_CNTR_BASE; -PMU_Ethosu_evnt_Type *ethosu_pmu_evnt = (PMU_Ethosu_evnt_Type *)ETHOSU_PMU_EVNT_BASE; - static const enum pmu_event_type eventbyid[] = {EXPAND_PMU_EVENT_TYPE(EVID, COMMA)}; /***************************************************************************** @@ -81,22 +78,198 @@ uint32_t pmu_event_value(enum ethosu_pmu_event_type event) void ethosu_pmu_driver_init(void) { #ifdef PMU_AUTOINIT - *ethosu_pmu_ctrl = (PMU_Ethosu_ctrl_Type){.PMCR = INIT_PMCR, - .PMCNTENSET = INIT_PMCNTENSET, - .PMCNTENCLR = INIT_PMCNTENCLR, - .PMOVSSET = INIT_PMOVSSET, - .PMOVSCLR = INIT_PMOVSCLR, - .PMINTSET = INIT_PMINTSET, - .PMINTCLR = INIT_PMINTCLR, - .PMCCNTR = INIT_PMCCNTR, - .PMCCNTR_CFG = INIT_PMCCNTR_CFG}; + write_reg(NPU_REG_PMCR, INIT_PMCR); + write_reg(NPU_REG_PMCNTENSET, INIT_PMCNTENSET); + write_reg(NPU_REG_PMCNTENCLR, INIT_PMCNTENCLR); + write_reg(NPU_REG_PMOVSSET, INIT_PMOVSSET); + write_reg(NPU_REG_PMOVSCLR, INIT_PMOVSCLR); + write_reg(NPU_REG_PMINTSET, INIT_PMINTSET); + write_reg(NPU_REG_PMINTCLR, INIT_PMINTCLR); + write_reg(NPU_REG_PMCCNTR_LO, INIT_PMCCNTR); + write_reg(NPU_REG_PMCCNTR_HI, INIT_PMCCNTR); + write_reg(NPU_REG_PMCCNTR_CFG, INIT_PMCCNTR_CFG); for (int i = 0; i < ETHOSU_PMU_NCOUNTERS; i++) { - *ethosu_pmu_cntr[i] = 0; - *ethosu_pmu_evnt[i] = 0; + write_reg(NPU_REG_PMEVCNTR(i), 0); + write_reg(NPU_REG_PMEVTYPER(i), 0); } #endif } void ethosu_pmu_driver_exit(void) {} + +void ETHOSU_PMU_Enable(void) +{ + struct pmcr_r pmcr; + pmcr.word = read_reg(NPU_REG_PMCR); + pmcr.cnt_en = 1; + write_reg(NPU_REG_PMCR, pmcr.word); +} + +void ETHOSU_PMU_Disable(void) +{ + struct pmcr_r pmcr; + pmcr.word = read_reg(NPU_REG_PMCR); + pmcr.cnt_en = 0; + write_reg(NPU_REG_PMCR, pmcr.word); +} + +void ETHOSU_PMU_Set_EVTYPER(uint32_t num, enum ethosu_pmu_event_type type) +{ + write_reg(NPU_REG_PMEVTYPER(num), pmu_event_value(type)); +} + +enum ethosu_pmu_event_type ETHOSU_PMU_Get_EVTYPER(uint32_t num) +{ + return pmu_event_type(read_reg(NPU_REG_PMEVTYPER(num))); +} + +void ETHOSU_PMU_CYCCNT_Reset(void) +{ + struct pmcr_r pmcr; + pmcr.word = read_reg(NPU_REG_PMCR); + pmcr.cycle_cnt_rst = 1; + write_reg(NPU_REG_PMCR, pmcr.word); +} + +void ETHOSU_PMU_EVCNTR_ALL_Reset(void) +{ + struct pmcr_r pmcr; + pmcr.word = read_reg(NPU_REG_PMCR); + pmcr.event_cnt_rst = 1; + write_reg(NPU_REG_PMCR, pmcr.word); +} + +void ETHOSU_PMU_CNTR_Enable(uint32_t mask) +{ + write_reg(NPU_REG_PMCNTENSET, mask); +} + +void ETHOSU_PMU_CNTR_Disable(uint32_t mask) +{ + write_reg(NPU_REG_PMCNTENCLR, mask); +} + +uint32_t ETHOSU_PMU_CNTR_Status() +{ + return read_reg(NPU_REG_PMCNTENSET); +} + +uint64_t ETHOSU_PMU_Get_CCNTR(void) +{ + uint64_t val1 = (((uint64_t)read_reg(NPU_REG_PMCCNTR_HI)) << 32) | read_reg(NPU_REG_PMCCNTR_LO); + uint64_t val2 = (((uint64_t)read_reg(NPU_REG_PMCCNTR_HI)) << 32) | read_reg(NPU_REG_PMCCNTR_LO); + + if (val2 > val1) + { + return val2; + } + return val1; +} + +void ETHOSU_PMU_Set_CCNTR(uint64_t val) +{ + uint32_t mask = ETHOSU_PMU_CNTR_Status(); + + if (mask & ETHOSU_PMU_CCNT_Msk) + { + ETHOSU_PMU_CNTR_Disable(ETHOSU_PMU_CCNT_Msk); + } + + write_reg(NPU_REG_PMCCNTR_LO, (val & MASK_0_31_BITS)); + write_reg(NPU_REG_PMCCNTR_HI, (val & MASK_32_47_BITS) >> 32); + + if (mask & ETHOSU_PMU_CCNT_Msk) + { + ETHOSU_PMU_CNTR_Enable(ETHOSU_PMU_CCNT_Msk); + } +} + +uint32_t ETHOSU_PMU_Get_EVCNTR(uint32_t num) +{ + return read_reg(NPU_REG_PMEVCNTR(num)); +} + +void ETHOSU_PMU_Set_EVCNTR(uint32_t num, uint32_t val) +{ + write_reg(NPU_REG_PMEVCNTR(num), val); +} + +uint32_t ETHOSU_PMU_Get_CNTR_OVS(void) +{ + return read_reg(NPU_REG_PMOVSSET); +} + +// TODO: check if this function name match with the description & +// implementation. +void ETHOSU_PMU_Set_CNTR_OVS(uint32_t mask) +{ + write_reg(NPU_REG_PMOVSCLR, mask); +} + +void ETHOSU_PMU_Set_CNTR_IRQ_Enable(uint32_t mask) +{ + write_reg(NPU_REG_PMINTSET, mask); +} + +void ETHOSU_PMU_Set_CNTR_IRQ_Disable(uint32_t mask) +{ + write_reg(NPU_REG_PMINTCLR, mask); +} + +uint32_t ETHOSU_PMU_Get_IRQ_Enable() +{ + return read_reg(NPU_REG_PMINTSET); +} + +void ETHOSU_PMU_CNTR_Increment(uint32_t mask) +{ + uint32_t cntrs_active = ETHOSU_PMU_CNTR_Status(); + + if (mask & ETHOSU_PMU_CCNT_Msk) + { + if (mask & ETHOSU_PMU_CCNT_Msk) + { + ETHOSU_PMU_CNTR_Disable(ETHOSU_PMU_CCNT_Msk); + uint64_t val = ETHOSU_PMU_Get_CCNTR() + 1; + write_reg(NPU_REG_PMCCNTR_LO, (val & MASK_0_31_BITS)); + write_reg(NPU_REG_PMCCNTR_HI, (val & MASK_32_47_BITS) >> 32); + if (cntrs_active & ETHOSU_PMU_CCNT_Msk) + { + ETHOSU_PMU_CNTR_Enable(ETHOSU_PMU_CCNT_Msk); + } + } + } + for (int i = 0; i < ETHOSU_PMU_NCOUNTERS; i++) + { + uint32_t cntr = (0x0001 << i); + + if (mask & cntr) + { + ETHOSU_PMU_CNTR_Disable(cntr); + uint32_t val = read_reg(NPU_REG_PMEVCNTR(i)); + write_reg(NPU_REG_PMEVCNTR(i), val + 1); + if (cntrs_active & cntr) + { + ETHOSU_PMU_CNTR_Enable(cntr); + } + } + } +} + +void ETHOSU_PMU_PMCCNTR_CFG_Set_Start_Event(uint32_t start_event) +{ + struct pmccntr_cfg_r cfg; + cfg.word = read_reg(NPU_REG_PMCCNTR_CFG); + cfg.CYCLE_CNT_CFG_START = start_event & ETHOSU_PMCCNTR_CFG_START_STOP_EVENT_MASK; + write_reg(NPU_REG_PMCCNTR_CFG, cfg.word); +} + +void ETHOSU_PMU_PMCCNTR_CFG_Set_Stop_Event(uint32_t stop_event) +{ + struct pmccntr_cfg_r cfg; + cfg.word = read_reg(NPU_REG_PMCCNTR_CFG); + cfg.CYCLE_CNT_CFG_STOP = stop_event & ETHOSU_PMCCNTR_CFG_START_STOP_EVENT_MASK; + write_reg(NPU_REG_PMCCNTR_CFG, cfg.word); +} -- cgit v1.2.1