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
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 @@
 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);
+}