summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWayne <[email protected]>2022-10-07 10:01:33 +0800
committerBernard Xiong <[email protected]>2022-10-11 08:46:01 +0800
commit5d014e8d31fb882c25063d58db89876d1eca9a96 (patch)
treec7a2dd74413edeedc57d50b2d5cd2880a72f1d55
parent901a24c7590bd6dbffb4ace13e1c302b2d7674c2 (diff)
Revert "[libcpu] remove gtimer/pmu from cortex-a"
-rw-r--r--libcpu/arm/cortex-a/SConscript3
-rw-r--r--libcpu/arm/cortex-a/armv7.h6
-rw-r--r--libcpu/arm/cortex-a/gtimer.c179
-rw-r--r--libcpu/arm/cortex-a/gtimer.h27
-rw-r--r--libcpu/arm/cortex-a/pmu.c20
-rw-r--r--libcpu/arm/cortex-a/pmu.h159
6 files changed, 388 insertions, 6 deletions
diff --git a/libcpu/arm/cortex-a/SConscript b/libcpu/arm/cortex-a/SConscript
index 78a5e64101..6075a8622c 100644
--- a/libcpu/arm/cortex-a/SConscript
+++ b/libcpu/arm/cortex-a/SConscript
@@ -8,8 +8,11 @@ cwd = GetCurrentDir()
src = Split('''
cache.c
cpu.c
+gtimer.c
mmu.c
+pmu.c
stack.c
+
''')
CPPPATH = [cwd]
diff --git a/libcpu/arm/cortex-a/armv7.h b/libcpu/arm/cortex-a/armv7.h
index 325d0ed0ae..f284bb5255 100644
--- a/libcpu/arm/cortex-a/armv7.h
+++ b/libcpu/arm/cortex-a/armv7.h
@@ -69,10 +69,4 @@ struct rt_hw_stack
#define E_Bit (1<<9)
#define J_Bit (1<<24)
-#define PABT_EXCEPTION 0x1
-#define DABT_EXCEPTION 0x2
-#define UND_EXCEPTION 0x3
-#define SWI_EXCEPTION 0x4
-#define RESV_EXCEPTION 0xF
-
#endif
diff --git a/libcpu/arm/cortex-a/gtimer.c b/libcpu/arm/cortex-a/gtimer.c
new file mode 100644
index 0000000000..b35acc6e6f
--- /dev/null
+++ b/libcpu/arm/cortex-a/gtimer.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-03-30 huijie.feng first version
+ */
+
+#include "cp15.h"
+#include <rtdef.h>
+
+/** Set CNTFRQ
+ * This function assigns the given value to PL1 Physical Timer Counter Frequency Register (CNTFRQ).
+ * @param value: CNTFRQ Register value to set
+ */
+static inline void __set_cntfrq(rt_uint32_t value)
+{
+ __set_cp(15, 0, value, 14, 0, 0);
+}
+
+/** Get CNTFRQ
+ * This function returns the value of the PL1 Physical Timer Counter Frequency Register (CNTFRQ).
+ * return CNTFRQ Register value
+ */
+static inline rt_uint32_t __get_cntfrq(void)
+{
+ rt_uint32_t result;
+ __get_cp(15, 0, result, 14, 0 , 0);
+ return result;
+}
+
+/** Set CNTP_TVAL
+ * This function assigns the given value to PL1 Physical Timer Value Register (CNTP_TVAL).
+ * param value: CNTP_TVAL Register value to set
+ */
+static inline void __set_cntp_tval(rt_uint32_t value)
+{
+ __set_cp(15, 0, value, 14, 2, 0);
+}
+
+/** Get CNTP_TVAL
+ * This function returns the value of the PL1 Physical Timer Value Register (CNTP_TVAL).
+ * return CNTP_TVAL Register value
+ */
+static inline rt_uint32_t __get_cntp_tval(void)
+{
+ rt_uint32_t result;
+ __get_cp(15, 0, result, 14, 2, 0);
+ return result;
+}
+
+/** Get CNTPCT
+ * This function returns the value of the 64 bits PL1 Physical Count Register (CNTPCT).
+ * return CNTPCT Register value
+ */
+static inline rt_uint64_t __get_cntpct(void)
+{
+ rt_uint64_t result;
+ __get_cp64(15, 0, result, 14);
+ return result;
+}
+
+/** Set CNTP_CVAL
+ * This function assigns the given value to 64bits PL1 Physical Timer CompareValue Register (CNTP_CVAL).
+ * param value: CNTP_CVAL Register value to set
+*/
+static inline void __set_cntp_cval(rt_uint64_t value)
+{
+ __set_cp64(15, 2, value, 14);
+}
+
+/** Get CNTP_CVAL
+ * This function returns the value of the 64 bits PL1 Physical Timer CompareValue Register (CNTP_CVAL).
+ * return CNTP_CVAL Register value
+ */
+static inline rt_uint64_t __get_cntp_cval(void)
+{
+ rt_uint64_t result;
+ __get_cp64(15, 2, result, 14);
+ return result;
+}
+
+/** Set CNTP_CTL
+ * This function assigns the given value to PL1 Physical Timer Control Register (CNTP_CTL).
+ * param value: CNTP_CTL Register value to set
+ */
+static inline void __set_cntp_ctl(uint32_t value)
+{
+ __set_cp(15, 0, value, 14, 2, 1);
+}
+
+/** Get CNTP_CTL register
+ * return CNTP_CTL Register value
+ */
+static inline rt_uint32_t __get_cntp_ctl(void)
+{
+ rt_uint32_t result;
+ __get_cp(15, 0, result, 14, 2, 1);
+ return result;
+}
+
+/** Configures the frequency the timer shall run at.
+ * param value The timer frequency in Hz.
+ */
+void gtimer_set_counter_frequency(rt_uint32_t value)
+{
+ __set_cntfrq(value);
+ __asm__ volatile ("isb 0xF":::"memory");
+}
+
+/** Get the frequency the timer shall run at.
+ * return timer frequency in Hz.
+ */
+rt_uint32_t gtimer_get_counter_frequency(void)
+{
+ return(__get_cntfrq());
+}
+
+/** Sets the reset value of the timer.
+ * param value: The value the timer is loaded with.
+ */
+void gtimer_set_load_value(rt_uint32_t value)
+{
+ __set_cntp_tval(value);
+ __asm__ volatile ("isb 0xF":::"memory");
+}
+
+/** Get the current counter value.
+ * return Current counter value.
+ */
+rt_uint32_t gtimer_get_current_value(void)
+{
+ return(__get_cntp_tval());
+}
+
+/** Get the current physical counter value.
+ * return Current physical counter value.
+ */
+rt_uint64_t gtimer_get_current_physical_value(void)
+{
+ return(__get_cntpct());
+}
+
+/** Set the physical compare value.
+ * param value: New physical timer compare value.
+ */
+void gtimer_set_physical_compare_value(rt_uint64_t value)
+{
+ __set_cntp_cval(value);
+ __asm__ volatile ("isb 0xF":::"memory");
+}
+
+/** Get the physical compare value.
+ * return Physical compare value.
+ */
+rt_uint64_t gtimer_get_physical_compare_value(void)
+{
+ return(__get_cntp_cval());
+}
+
+/** Configure the timer by setting the control value.
+ * param value: New timer control value.
+ */
+void gtimer_set_control(rt_uint32_t value)
+{
+ __set_cntp_ctl(value);
+ __asm__ volatile ("isb 0xF":::"memory");
+}
+
+/** Get the control value.
+ * return Control value.
+ */
+rt_uint32_t gtimer_get_control(void)
+{
+ return(__get_cntp_ctl());
+}
+
diff --git a/libcpu/arm/cortex-a/gtimer.h b/libcpu/arm/cortex-a/gtimer.h
new file mode 100644
index 0000000000..ec5d54127e
--- /dev/null
+++ b/libcpu/arm/cortex-a/gtimer.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-03-30 huijie.feng first version
+ */
+
+#ifndef __GTIMER_H__
+#define __GTIMER_H__
+
+#include <rtdef.h>
+
+void gtimer_set_counter_frequency(rt_uint32_t value);
+rt_uint32_t gtimer_get_counter_frequency(void);
+void gtimer_set_load_value(rt_uint32_t value);
+rt_uint32_t gtimer_get_current_value(void);
+rt_uint64_t gtimer_get_current_physical_value(void);
+void gtimer_set_physical_compare_value(rt_uint64_t value);
+rt_uint64_t gtimer_get_physical_compare_value(void);
+void gtimer_set_control(rt_uint32_t value);
+rt_uint32_t gtimer_get_control(void);
+
+#endif
+
diff --git a/libcpu/arm/cortex-a/pmu.c b/libcpu/arm/cortex-a/pmu.c
new file mode 100644
index 0000000000..2b9165cc8b
--- /dev/null
+++ b/libcpu/arm/cortex-a/pmu.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ */
+#include <rtthread.h>
+#include "pmu.h"
+
+void rt_hw_pmu_dump_feature(void)
+{
+ unsigned long reg;
+
+ reg = rt_hw_pmu_get_control();
+ rt_kprintf("ARM PMU Implementor: %c, ID code: %02x, %d counters\n",
+ reg >> 24, (reg >> 16) & 0xff, (reg >> 11) & 0x1f);
+ RT_ASSERT(ARM_PMU_CNTER_NR == ((reg >> 11) & 0x1f));
+}
diff --git a/libcpu/arm/cortex-a/pmu.h b/libcpu/arm/cortex-a/pmu.h
new file mode 100644
index 0000000000..64a74b5d39
--- /dev/null
+++ b/libcpu/arm/cortex-a/pmu.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ */
+#ifndef __PMU_H__
+#define __PMU_H__
+
+#include "board.h"
+
+/* Number of counters */
+#define ARM_PMU_CNTER_NR 4
+
+enum rt_hw_pmu_event_type {
+ ARM_PMU_EVENT_PMNC_SW_INCR = 0x00,
+ ARM_PMU_EVENT_L1_ICACHE_REFILL = 0x01,
+ ARM_PMU_EVENT_ITLB_REFILL = 0x02,
+ ARM_PMU_EVENT_L1_DCACHE_REFILL = 0x03,
+ ARM_PMU_EVENT_L1_DCACHE_ACCESS = 0x04,
+ ARM_PMU_EVENT_DTLB_REFILL = 0x05,
+ ARM_PMU_EVENT_MEM_READ = 0x06,
+ ARM_PMU_EVENT_MEM_WRITE = 0x07,
+ ARM_PMU_EVENT_INSTR_EXECUTED = 0x08,
+ ARM_PMU_EVENT_EXC_TAKEN = 0x09,
+ ARM_PMU_EVENT_EXC_EXECUTED = 0x0A,
+ ARM_PMU_EVENT_CID_WRITE = 0x0B,
+};
+
+/* Enable bit */
+#define ARM_PMU_PMCR_E (0x01 << 0)
+/* Event counter reset */
+#define ARM_PMU_PMCR_P (0x01 << 1)
+/* Cycle counter reset */
+#define ARM_PMU_PMCR_C (0x01 << 2)
+/* Cycle counter divider */
+#define ARM_PMU_PMCR_D (0x01 << 3)
+
+#ifdef __GNUC__
+rt_inline void rt_hw_pmu_enable_cnt(int divide64)
+{
+ unsigned long pmcr;
+ unsigned long pmcntenset;
+
+ asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
+ pmcr |= ARM_PMU_PMCR_E | ARM_PMU_PMCR_P | ARM_PMU_PMCR_C;
+ if (divide64)
+ pmcr |= ARM_PMU_PMCR_D;
+ else
+ pmcr &= ~ARM_PMU_PMCR_D;
+ asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
+
+ /* enable all the counters */
+ pmcntenset = ~0;
+ asm volatile ("mcr p15, 0, %0, c9, c12, 1" :: "r"(pmcntenset));
+ /* clear overflows(just in case) */
+ asm volatile ("mcr p15, 0, %0, c9, c12, 3" :: "r"(pmcntenset));
+}
+
+rt_inline unsigned long rt_hw_pmu_get_control(void)
+{
+ unsigned long pmcr;
+ asm ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
+ return pmcr;
+}
+
+rt_inline unsigned long rt_hw_pmu_get_ceid(void)
+{
+ unsigned long reg;
+ /* only PMCEID0 is supported, PMCEID1 is RAZ. */
+ asm ("mrc p15, 0, %0, c9, c12, 6" : "=r"(reg));
+ return reg;
+}
+
+rt_inline unsigned long rt_hw_pmu_get_cnten(void)
+{
+ unsigned long pmcnt;
+ asm ("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcnt));
+ return pmcnt;
+}
+
+rt_inline void rt_hw_pmu_reset_cycle(void)
+{
+ unsigned long pmcr;
+
+ asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
+ pmcr |= ARM_PMU_PMCR_C;
+ asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
+ asm volatile ("isb");
+}
+
+rt_inline void rt_hw_pmu_reset_event(void)
+{
+ unsigned long pmcr;
+
+ asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
+ pmcr |= ARM_PMU_PMCR_P;
+ asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
+ asm volatile ("isb");
+}
+
+rt_inline unsigned long rt_hw_pmu_get_cycle(void)
+{
+ unsigned long cyc;
+ asm volatile ("isb");
+ asm volatile ("mrc p15, 0, %0, c9, c13, 0" : "=r"(cyc));
+ return cyc;
+}
+
+rt_inline void rt_hw_pmu_select_counter(int idx)
+{
+ RT_ASSERT(idx < ARM_PMU_CNTER_NR);
+
+ asm volatile ("mcr p15, 0, %0, c9, c12, 5" : : "r"(idx));
+ /* Linux add an isb here, don't know why here. */
+ asm volatile ("isb");
+}
+
+rt_inline void rt_hw_pmu_select_event(int idx,
+ enum rt_hw_pmu_event_type eve)
+{
+ RT_ASSERT(idx < ARM_PMU_CNTER_NR);
+
+ rt_hw_pmu_select_counter(idx);
+ asm volatile ("mcr p15, 0, %0, c9, c13, 1" : : "r"(eve));
+}
+
+rt_inline unsigned long rt_hw_pmu_read_counter(int idx)
+{
+ unsigned long reg;
+
+ rt_hw_pmu_select_counter(idx);
+ asm volatile ("isb");
+ asm volatile ("mrc p15, 0, %0, c9, c13, 2" : "=r"(reg));
+ return reg;
+}
+
+rt_inline unsigned long rt_hw_pmu_get_ovsr(void)
+{
+ unsigned long reg;
+ asm volatile ("isb");
+ asm ("mrc p15, 0, %0, c9, c12, 3" : "=r"(reg));
+ return reg;
+}
+
+rt_inline void rt_hw_pmu_clear_ovsr(unsigned long reg)
+{
+ asm ("mcr p15, 0, %0, c9, c12, 3" : : "r"(reg));
+ asm volatile ("isb");
+}
+
+#endif
+
+void rt_hw_pmu_dump_feature(void);
+
+#endif /* end of include guard: __PMU_H__ */
+