Setting up repository
[linux-libre-firmware.git] / ath9k_htc / sboot / magpie_1_1 / sboot / cmnos / timer / src / cmnos_timer.c
1 /*
2  * Copyright (c) 2013 Qualcomm Atheros, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted (subject to the limitations in the
7  * disclaimer below) provided that the following conditions are met:
8  *
9  *  * Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  *  * Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the
15  *    distribution.
16  *
17  *  * Neither the name of Qualcomm Atheros nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific prior written permission.
20  *
21  * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
22  * GRANTED BY THIS LICENSE.  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
23  * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
24  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
32  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
33  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 #include "sys_cfg.h"
36 #include "athos_api.h"
37
38 #if SYSTEM_MODULE_TIMER
39
40 //#define TIMER_NOT_IN_USE ((cmnos_timer_t *)-1)
41 #define TIMER_NOT_IN_USE NULL
42
43 /* convert milliseconds to ticks */
44 #define MILLIS_TO_TIMER_TICKS(ms)       (ms*ONE_MSEC)   
45
46 /* Current tick time */
47 //#define NOW()                             xthal_get_ccount()
48
49 #define TIMER_IS_EARLIER(t1, t2)          ((A_INT32)((A_UINT32)t1-(A_UINT32)t2)<=0)
50
51
52 typedef struct cmnos_timer_s {
53     struct cmnos_timer_s    *timer_next;
54     A_UINT32                 timer_expire;
55     A_UINT32                 timer_period;
56     A_TIMER_FUNC            *timer_function;
57     void                    *timer_arg;
58 } cmnos_timer_t; /*  A_timer_t */
59
60 LOCAL cmnos_timer_t *timer_list = NULL;
61
62
63 /* Initialize a timer. Initially, it is unarmed. */
64 LOCAL void
65 cmnos_timer_setfn(A_timer_t *A_timer, A_TIMER_FUNC *pfunction, void *parg)
66 {
67     cmnos_timer_t *ptimer = (cmnos_timer_t *)A_timer;
68
69     ptimer->timer_next = TIMER_NOT_IN_USE;
70     ptimer->timer_expire = 0; /* sanity */
71     ptimer->timer_function = pfunction;
72     ptimer->timer_arg = parg;
73 }
74
75 /* Arm a timer to trigger after the specified time */
76 LOCAL void
77 cmnos_timer_arm(A_timer_t *A_timer,
78                 unsigned int milliseconds)
79 {
80     cmnos_timer_t *ptimer = (cmnos_timer_t *)A_timer;
81     A_UINT32 timer_expire;
82     A_UINT32 timer_ticks;
83     cmnos_timer_t *curr, *prev = NULL;
84
85     /* Convert milliseconds to ticks */
86     timer_ticks = MILLIS_TO_TIMER_TICKS(milliseconds);
87     
88     /* Calculate expiring tick time */
89     timer_expire = NOW() + timer_ticks;
90     
91     /* Find the right place to insert */
92     for (curr = timer_list;
93          curr;
94          prev=curr, curr = curr->timer_next)
95     {
96         if (TIMER_IS_EARLIER(timer_expire, curr->timer_expire))
97             break;
98     }
99
100     /* Inster timer to the list */
101     ptimer->timer_next = curr;
102     ptimer->timer_expire = timer_expire;
103     if (prev) {
104         prev->timer_next = ptimer;
105     } else {
106         /* Insert at head of the timer list */
107         timer_list = ptimer;
108     }
109     
110     return;
111 }
112
113 /* Disarm a timer, if it is currently armed. */
114 LOCAL void
115 cmnos_timer_disarm(A_timer_t *A_timer)
116 {
117     cmnos_timer_t *ptimer = (cmnos_timer_t *)A_timer;
118     cmnos_timer_t *curr, *prev = NULL;
119     
120     /* Find desired timer */
121     for (curr = timer_list;
122          curr;
123          prev=curr, curr = curr->timer_next)
124     {
125         if (ptimer == curr) {
126             break;
127         }
128     }
129
130     /* Remove it from the timer list */
131     if (curr) {
132         if (prev) {
133             prev->timer_next = curr->timer_next;
134         } else {
135             timer_list = curr->timer_next;
136         }
137     }
138
139     /* Clear timer parameters */
140     ptimer->timer_next = TIMER_NOT_IN_USE;
141     ptimer->timer_period = 0;
142 }
143
144 /* Initialize timer software.  Called once during initialization. */
145 LOCAL void
146 cmnos_timer_init(void)
147 {
148     timer_list = NULL;
149 }
150
151 /* Handler for LF0 Timer. */
152 LOCAL void
153 cmnos_timer_handler(void)
154 {
155     cmnos_timer_t *ptimer;
156
157     while (timer_list &&
158            TIMER_IS_EARLIER(timer_list->timer_expire, NOW()))
159     {
160         ptimer = timer_list;
161         timer_list = timer_list->timer_next;
162         ptimer->timer_next = TIMER_NOT_IN_USE;
163         ptimer->timer_function((A_HANDLE)ptimer, ptimer->timer_arg);
164     }
165     return;
166 }
167
168 void
169 cmnos_timer_module_install(struct timer_api *tbl)
170 {
171     tbl->_timer_init         = cmnos_timer_init;
172     tbl->_timer_arm          = cmnos_timer_arm;
173     tbl->_timer_disarm       = cmnos_timer_disarm;
174     tbl->_timer_setfn        = cmnos_timer_setfn;
175     tbl->_timer_run          = cmnos_timer_handler;
176 }
177
178 //#define CMNOS_TIMER_UT
179 #ifdef CMNOS_TIMER_UT
180
181 #include <adf_os_timer.h>
182
183 adf_os_timer_t timer1;
184 adf_os_timer_t timer2;
185
186 void test_timer(void *arg)
187 {
188     adf_os_timer_t *tmp = (adf_os_timer_t *) arg;
189     
190     if ( tmp == &timer1 ) {
191         adf_os_print("Timer1 is fired\n");
192         adf_os_timer_start(&timer1, 1000);
193     } else {
194         adf_os_print("Timer2 is fired\n");
195         adf_os_timer_start(&timer2, 3000);        
196     }
197 }
198
199 void 
200 cmnos_timer_test()
201 {
202     adf_os_timer_init(NULL, &timer1, test_timer, &timer1);
203     adf_os_timer_init(NULL, &timer2, test_timer, &timer2);
204     adf_os_timer_start(&timer1, 1000);
205     adf_os_timer_start(&timer2, 3000);    
206 }
207
208 #endif
209
210 #endif /* end SYSTEM_MODULE_TIMER */
211