1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author         Notes
8  * 2019-07-29     zdzn           first version
9  */
10 
11 #include "drv_timer.h"
12 
13 #ifdef BSP_USING_SYSTIMER
14 
raspi_systimer_init(rt_hwtimer_t * hwtimer,rt_uint32_t state)15 static void raspi_systimer_init(rt_hwtimer_t *hwtimer, rt_uint32_t state)
16 {
17     if (state == 0)
18         hwtimer->ops->stop(hwtimer);
19 }
20 
raspi_systimer_start(rt_hwtimer_t * hwtimer,rt_uint32_t cnt,rt_hwtimer_mode_t mode)21 static rt_err_t raspi_systimer_start(rt_hwtimer_t *hwtimer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
22 {
23     rt_err_t result = RT_EOK;
24     rt_systimer_t *timer = (rt_systimer_t *)hwtimer->parent.user_data;
25     int timer_id = timer->timer_id;
26 
27     if (mode == HWTIMER_MODE_PERIOD)
28         timer->cnt = cnt;
29     else
30         timer->cnt = 0;
31 
32     __sync_synchronize();
33     if (timer_id == 1)
34     {
35         rt_hw_interrupt_umask(IRQ_SYSTEM_TIMER_1);
36         STIMER_C1 = STIMER_CLO + cnt;
37     }
38     else if (timer_id == 3)
39     {
40         rt_hw_interrupt_umask(IRQ_SYSTEM_TIMER_3);
41         STIMER_C3 = STIMER_CLO + cnt;
42     }
43     else
44         result = -RT_ERROR;
45 
46     __sync_synchronize();
47 
48     return result;
49 }
50 
raspi_systimer_stop(rt_hwtimer_t * hwtimer)51 static void raspi_systimer_stop(rt_hwtimer_t *hwtimer)
52 {
53     rt_systimer_t *timer = (rt_systimer_t *)hwtimer->parent.user_data;
54     int timer_id = timer->timer_id;
55     if (timer_id == 1)
56         rt_hw_interrupt_mask(IRQ_SYSTEM_TIMER_1);
57     else if (timer_id == 3)
58         rt_hw_interrupt_mask(IRQ_SYSTEM_TIMER_3);
59 
60 }
61 
raspi_systimer_ctrl(rt_hwtimer_t * timer,rt_uint32_t cmd,void * arg)62 static rt_err_t raspi_systimer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg)
63 {
64     /* The frequency value is an immutable value. */
65     if (cmd == HWTIMER_CTRL_FREQ_SET)
66     {
67         return RT_EOK;
68     }
69     else
70     {
71         return -RT_ENOSYS;
72     }
73 }
74 
75 
rt_device_systimer_isr(int vector,void * param)76 void rt_device_systimer_isr(int vector, void *param)
77 {
78 
79     rt_hwtimer_t *hwtimer = (rt_hwtimer_t *) param;
80     rt_systimer_t *timer = (rt_systimer_t *)hwtimer->parent.user_data;
81     RT_ASSERT(timer != RT_NULL);
82 
83     int timer_id = timer->timer_id;
84 
85     __sync_synchronize();
86     if (timer_id == 1)
87     {
88         STIMER_CS = 0x2;
89         STIMER_C1 = STIMER_CLO + timer->cnt;
90     }
91     else if (timer_id == 3)
92     {
93         STIMER_CS = 0x8;
94         STIMER_C3 = STIMER_CLO + timer->cnt;
95     }
96     __sync_synchronize();
97 
98     rt_device_hwtimer_isr(hwtimer);
99 }
100 
101 static struct rt_hwtimer_device _hwtimer1;
102 static struct rt_hwtimer_device _hwtimer3;
103 
104 static rt_systimer_t _systimer1;
105 static rt_systimer_t _systimer3;
106 
107 const static struct rt_hwtimer_ops systimer_ops =
108 {
109     raspi_systimer_init,
110     raspi_systimer_start,
111     raspi_systimer_stop,
112     RT_NULL,
113     raspi_systimer_ctrl
114 };
115 
116 static const struct rt_hwtimer_info _info =
117 {
118     1000000,            /* the maxinum count frequency can be set */
119     1000000,            /* the maxinum count frequency can be set */
120     0xFFFFFFFF,         /* the maximum counter value */
121     HWTIMER_CNTMODE_UP  /* count mode (inc/dec) */
122 };
123 
124 #endif
125 
rt_hw_systimer_init(void)126 int rt_hw_systimer_init(void)
127 {
128 
129 #ifdef BSP_USING_SYSTIMER
130 
131 #ifdef RT_USING_SYSTIMER1
132     _systimer1.timer_id =1;
133     _hwtimer1.ops = &systimer_ops;
134     _hwtimer1.info = &_info;
135     rt_device_hwtimer_register(&_hwtimer1, "timer1",&_systimer1);
136     rt_hw_interrupt_install(IRQ_SYSTEM_TIMER_1, rt_device_systimer_isr, &_hwtimer1, "systimer1");
137     rt_hw_interrupt_umask(IRQ_SYSTEM_TIMER_1);
138 #endif
139 
140 #ifdef RT_USING_SYSTIMER3
141     _systimer3.timer_id =3;
142     _hwtimer3.ops = &systimer_ops;
143     _hwtimer3.info = &_info;
144     rt_device_hwtimer_register(&_hwtimer3, "timer3",&_systimer3);
145     rt_hw_interrupt_install(IRQ_SYSTEM_TIMER_3, rt_device_systimer_isr, &_hwtimer3, "systimer3");
146     rt_hw_interrupt_umask(IRQ_SYSTEM_TIMER_3);
147 #endif
148 
149 #endif
150 
151     return 0;
152 }
153 
154 INIT_DEVICE_EXPORT(rt_hw_systimer_init);
155