summaryrefslogtreecommitdiff
path: root/components/drivers/hwtimer
diff options
context:
space:
mode:
authorzms123456 <[email protected]>2024-02-29 22:27:38 +0800
committerGitHub <[email protected]>2024-02-29 22:27:38 +0800
commit6b5058ba5c084f14846fd127e33552c0d44916b9 (patch)
tree55bf99ee7d41bf9afcfbe69324b5b6d5ed659bce /components/drivers/hwtimer
parent97c5edf947b0c1b02ad39fd5bedb1853a9140c2d (diff)
[components/drivers]update hwtimer (#8565)
Diffstat (limited to 'components/drivers/hwtimer')
-rw-r--r--components/drivers/hwtimer/Kconfig10
-rw-r--r--components/drivers/hwtimer/SConscript16
-rw-r--r--components/drivers/hwtimer/hwtimer-arm_arch.c383
-rw-r--r--components/drivers/hwtimer/hwtimer.c18
4 files changed, 424 insertions, 3 deletions
diff --git a/components/drivers/hwtimer/Kconfig b/components/drivers/hwtimer/Kconfig
new file mode 100644
index 0000000000..a1755ba0e6
--- /dev/null
+++ b/components/drivers/hwtimer/Kconfig
@@ -0,0 +1,10 @@
+menuconfig RT_USING_HWTIMER
+ bool "Using Hardware Timer device drivers"
+ default n
+
+config RT_HWTIMER_ARM_ARCH
+ bool "ARM ARCH Timer"
+ depends on RT_USING_DM
+ depends on RT_USING_HWTIMER
+ depends on ARCH_ARM_CORTEX_A || ARCH_ARMV8
+ default n
diff --git a/components/drivers/hwtimer/SConscript b/components/drivers/hwtimer/SConscript
index 534e04b6c0..b6ffc580ed 100644
--- a/components/drivers/hwtimer/SConscript
+++ b/components/drivers/hwtimer/SConscript
@@ -1,8 +1,18 @@
from building import *
-cwd = GetCurrentDir()
-src = Glob('*.c')
+group = []
+
+if not GetDepend(['RT_USING_HWTIMER']):
+ Return('group')
+
+cwd = GetCurrentDir()
CPPPATH = [cwd + '/../include']
-group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_HWTIMER'], CPPPATH = CPPPATH)
+
+src = ['hwtimer.c']
+
+if GetDepend(['RT_HWTIMER_ARM_ARCH']):
+ src += ['hwtimer-arm_arch.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
diff --git a/components/drivers/hwtimer/hwtimer-arm_arch.c b/components/drivers/hwtimer/hwtimer-arm_arch.c
new file mode 100644
index 0000000000..3cfb4318d8
--- /dev/null
+++ b/components/drivers/hwtimer/hwtimer-arm_arch.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-12-20 GuEe-GUI first version
+ * 2022-08-24 GuEe-GUI Add OFW support
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+/* support registers access and timer registers in libcpu */
+#include <cpu.h>
+#include <cpuport.h>
+
+typedef void (*timer_ctrl_handle)(rt_bool_t enable);
+typedef rt_uint64_t (*timer_value_handle)(rt_uint64_t val);
+
+static volatile rt_uint64_t timer_step;
+
+static int arm_arch_timer_irq = -1;
+static timer_ctrl_handle arm_arch_timer_ctrl_handle = RT_NULL;
+static timer_value_handle arm_arch_timer_value_handle = RT_NULL;
+
+/* CTL */
+static void mon_ptimer_ctrl(rt_bool_t enable)
+{
+ rt_hw_sysreg_write(CNTPS_CTL, !!enable);
+}
+
+static void hyp_s_ptimer_ctrl(rt_bool_t enable)
+{
+#if ARCH_ARMV8_EXTENSIONS > 1
+ rt_hw_sysreg_write(CNTHPS_CTL, !!enable);
+#endif
+}
+
+static void hyp_ns_ptimer_ctrl(rt_bool_t enable)
+{
+ rt_hw_sysreg_write(CNTHP_CTL, !!enable);
+}
+
+static void hyp_s_vtimer_ctrl(rt_bool_t enable)
+{
+#if ARCH_ARMV8_EXTENSIONS > 1
+ rt_hw_sysreg_write(CNTHVS_CTL, !!enable);
+#endif
+}
+
+static void hyp_ns_vtimer_ctrl(rt_bool_t enable)
+{
+#if ARCH_ARMV8_EXTENSIONS > 1
+ rt_hw_sysreg_write(CNTHV_CTL, !!enable);
+#endif
+}
+
+static void os_ptimer_ctrl(rt_bool_t enable)
+{
+ rt_hw_sysreg_write(CNTP_CTL, !!enable);
+}
+
+static void os_vtimer_ctrl(rt_bool_t enable)
+{
+ rt_hw_sysreg_write(CNTV_CTL, !!enable);
+}
+
+/* TVAL */
+static rt_uint64_t mon_ptimer_value(rt_uint64_t val)
+{
+ if (val)
+ {
+ rt_hw_sysreg_write(CNTPS_TVAL, val);
+ }
+ else
+ {
+ rt_hw_sysreg_read(CNTPS_TVAL, val);
+ }
+
+ return val;
+}
+
+static rt_uint64_t hyp_s_ptimer_value(rt_uint64_t val)
+{
+#if ARCH_ARMV8_EXTENSIONS > 1
+ if (val)
+ {
+ rt_hw_sysreg_write(CNTHPS_TVAL, val);
+ }
+ else
+ {
+ rt_hw_sysreg_read(CNTHPS_TVAL, val);
+ }
+
+ return val;
+#else
+ return 0;
+#endif
+}
+
+static rt_uint64_t hyp_ns_ptimer_value(rt_uint64_t val)
+{
+ if (val)
+ {
+ rt_hw_sysreg_write(CNTHP_TVAL, val);
+ }
+ else
+ {
+ rt_hw_sysreg_read(CNTHP_TVAL, val);
+ }
+
+ return val;
+}
+
+static rt_uint64_t hyp_s_vtimer_value(rt_uint64_t val)
+{
+#if ARCH_ARMV8_EXTENSIONS > 1
+ if (val)
+ {
+ rt_hw_sysreg_write(CNTHVS_TVAL, val);
+ }
+ else
+ {
+ rt_hw_sysreg_read(CNTHVS_TVAL, val);
+ }
+
+ return val;
+#else
+ return 0;
+#endif
+}
+
+static rt_uint64_t hyp_ns_vtimer_value(rt_uint64_t val)
+{
+#if ARCH_ARMV8_EXTENSIONS > 1
+ if (val)
+ {
+ rt_hw_sysreg_write(CNTHV_TVAL, val);
+ }
+ else
+ {
+ rt_hw_sysreg_read(CNTHV_TVAL, val);
+ }
+
+ return val;
+#else
+ return 0;
+#endif
+}
+
+static rt_uint64_t os_ptimer_value(rt_uint64_t val)
+{
+ if (val)
+ {
+ rt_hw_sysreg_write(CNTP_TVAL, val);
+ }
+ else
+ {
+ rt_hw_sysreg_read(CNTP_TVAL, val);
+ }
+
+ return val;
+}
+
+static rt_uint64_t os_vtimer_value(rt_uint64_t val)
+{
+ if (val)
+ {
+ rt_hw_sysreg_write(CNTV_TVAL, val);
+ }
+ else
+ {
+ rt_hw_sysreg_read(CNTV_TVAL, val);
+ }
+
+ return val;
+}
+
+static timer_ctrl_handle ctrl_handle[] =
+{
+ mon_ptimer_ctrl,
+ hyp_s_ptimer_ctrl,
+ hyp_ns_ptimer_ctrl,
+ hyp_s_vtimer_ctrl,
+ hyp_ns_vtimer_ctrl,
+ os_ptimer_ctrl,
+ os_vtimer_ctrl,
+};
+
+static timer_value_handle value_handle[] =
+{
+ mon_ptimer_value,
+ hyp_s_ptimer_value,
+ hyp_ns_ptimer_value,
+ hyp_s_vtimer_value,
+ hyp_ns_vtimer_value,
+ os_ptimer_value,
+ os_vtimer_value,
+};
+
+static rt_err_t arm_arch_timer_local_enable(void)
+{
+ rt_err_t ret = RT_EOK;
+
+ if (arm_arch_timer_irq >= 0)
+ {
+ arm_arch_timer_ctrl_handle(RT_FALSE);
+ arm_arch_timer_value_handle(timer_step);
+
+ rt_hw_interrupt_umask(arm_arch_timer_irq);
+
+ arm_arch_timer_ctrl_handle(RT_TRUE);
+ }
+ else
+ {
+ ret = -RT_ENOSYS;
+ }
+
+ return ret;
+}
+
+rt_used
+static rt_err_t arm_arch_timer_local_disable(void)
+{
+ rt_err_t ret = RT_EOK;
+
+ if (arm_arch_timer_ctrl_handle)
+ {
+ arm_arch_timer_ctrl_handle(RT_FALSE);
+ rt_hw_interrupt_mask(arm_arch_timer_irq);
+ }
+ else
+ {
+ ret = -RT_ENOSYS;
+ }
+
+ return ret;
+}
+
+rt_used
+static rt_err_t arm_arch_timer_set_frequency(rt_uint64_t frq)
+{
+ rt_err_t ret = RT_EOK;
+
+#ifdef ARCH_SUPPORT_TEE
+ rt_hw_isb();
+ rt_hw_sysreg_write(CNTFRQ, frq);
+ rt_hw_dsb();
+#else
+ ret = -RT_ENOSYS;
+#endif
+
+ return ret;
+}
+
+rt_used
+static rt_uint64_t arm_arch_timer_get_frequency(void)
+{
+ rt_uint64_t frq;
+
+ rt_hw_isb();
+ rt_hw_sysreg_read(CNTFRQ, frq);
+ rt_hw_isb();
+
+ return frq;
+}
+
+rt_used
+static rt_err_t arm_arch_timer_set_value(rt_uint64_t val)
+{
+ rt_err_t ret = RT_EOK;
+
+ if (arm_arch_timer_value_handle)
+ {
+ val = arm_arch_timer_value_handle(val);
+ }
+ else
+ {
+ ret = -RT_ENOSYS;
+ }
+
+ return ret;
+}
+
+rt_used
+static rt_uint64_t arm_arch_timer_get_value(void)
+{
+ rt_uint64_t val = 0;
+
+ if (arm_arch_timer_value_handle)
+ {
+ val = arm_arch_timer_value_handle(0);
+ }
+
+ return val;
+}
+
+static void arm_arch_timer_isr(int vector, void *param)
+{
+ arm_arch_timer_set_value(timer_step);
+
+ rt_tick_increase();
+}
+
+static int arm_arch_timer_post_init(void)
+{
+ arm_arch_timer_local_enable();
+
+ return 0;
+}
+INIT_SECONDARY_CPU_EXPORT(arm_arch_timer_post_init);
+
+static rt_err_t arm_arch_timer_probe(struct rt_platform_device *pdev)
+{
+ int mode_idx, irq_idx;
+ const char *irq_name[] =
+ {
+ "phys", /* Secure Phys IRQ */
+ "virt", /* Non-secure Phys IRQ */
+ "hyp-phys", /* Virt IRQ */
+ "hyp-virt", /* Hyp IRQ */
+ };
+
+#if defined(ARCH_SUPPORT_TEE)
+ mode_idx = 0;
+ irq_idx = 0;
+#elif defined(ARCH_SUPPORT_HYP)
+ mode_idx = 2;
+ irq_idx = 3;
+#else
+ mode_idx = 5;
+ irq_idx = 1;
+#endif
+
+ arm_arch_timer_irq = rt_dm_dev_get_irq_by_name(&pdev->parent, irq_name[irq_idx]);
+
+ if (arm_arch_timer_irq < 0)
+ {
+ arm_arch_timer_irq = rt_dm_dev_get_irq(&pdev->parent, irq_idx);
+ }
+
+ if (arm_arch_timer_irq < 0)
+ {
+ return -RT_EEMPTY;
+ }
+
+ arm_arch_timer_ctrl_handle = ctrl_handle[mode_idx];
+ arm_arch_timer_value_handle = value_handle[mode_idx];
+
+ rt_hw_interrupt_install(arm_arch_timer_irq, arm_arch_timer_isr, RT_NULL, "tick-arm-timer");
+
+ timer_step = arm_arch_timer_get_frequency() / RT_TICK_PER_SECOND;
+
+ arm_arch_timer_local_enable();
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id arm_arch_timer_ofw_ids[] =
+{
+ { .compatible = "arm,armv7-timer", },
+ { .compatible = "arm,armv8-timer", },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver arm_arch_timer_driver =
+{
+ .name = "arm-arch-timer",
+ .ids = arm_arch_timer_ofw_ids,
+
+ .probe = arm_arch_timer_probe,
+};
+
+static int arm_arch_timer_drv_register(void)
+{
+ rt_platform_driver_register(&arm_arch_timer_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(arm_arch_timer_drv_register);
diff --git a/components/drivers/hwtimer/hwtimer.c b/components/drivers/hwtimer/hwtimer.c
index 27ffff6025..bcf9ea9a2a 100644
--- a/components/drivers/hwtimer/hwtimer.c
+++ b/components/drivers/hwtimer/hwtimer.c
@@ -15,6 +15,24 @@
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
+#ifdef RT_USING_DM
+void (*rt_device_hwtimer_us_delay)(rt_uint32_t us) = RT_NULL;
+
+void rt_hw_us_delay(rt_uint32_t us)
+{
+ if (rt_device_hwtimer_us_delay)
+ {
+ rt_device_hwtimer_us_delay(us);
+ }
+ else
+ {
+ LOG_E("Implemented at least in the libcpu");
+
+ RT_ASSERT(0);
+ }
+}
+#endif /* RT_USING_DM */
+
rt_inline rt_uint32_t timeout_calc(rt_hwtimer_t *timer, rt_hwtimerval_t *tv)
{
float overflow;