xref: /utopia/UTPA2-700.0.x/modules/usb/drv/usb_ecos/usbhost/drvTimer.c (revision 53ee8cc121a030b8d368113ac3e966b4705770ef)
1 //<MStar Software>
2 //******************************************************************************
3 // MStar Software
4 // Copyright (c) 2010 - 2012 MStar Semiconductor, Inc. All rights reserved.
5 // All software, firmware and related documentation herein ("MStar Software") are
6 // intellectual property of MStar Semiconductor, Inc. ("MStar") and protected by
7 // law, including, but not limited to, copyright law and international treaties.
8 // Any use, modification, reproduction, retransmission, or republication of all
9 // or part of MStar Software is expressly prohibited, unless prior written
10 // permission has been granted by MStar.
11 //
12 // By accessing, browsing and/or using MStar Software, you acknowledge that you
13 // have read, understood, and agree, to be bound by below terms ("Terms") and to
14 // comply with all applicable laws and regulations:
15 //
16 // 1. MStar shall retain any and all right, ownership and interest to MStar
17 //    Software and any modification/derivatives thereof.
18 //    No right, ownership, or interest to MStar Software and any
19 //    modification/derivatives thereof is transferred to you under Terms.
20 //
21 // 2. You understand that MStar Software might include, incorporate or be
22 //    supplied together with third party`s software and the use of MStar
23 //    Software may require additional licenses from third parties.
24 //    Therefore, you hereby agree it is your sole responsibility to separately
25 //    obtain any and all third party right and license necessary for your use of
26 //    such third party`s software.
27 //
28 // 3. MStar Software and any modification/derivatives thereof shall be deemed as
29 //    MStar`s confidential information and you agree to keep MStar`s
30 //    confidential information in strictest confidence and not disclose to any
31 //    third party.
32 //
33 // 4. MStar Software is provided on an "AS IS" basis without warranties of any
34 //    kind. Any warranties are hereby expressly disclaimed by MStar, including
35 //    without limitation, any warranties of merchantability, non-infringement of
36 //    intellectual property rights, fitness for a particular purpose, error free
37 //    and in conformity with any international standard.  You agree to waive any
38 //    claim against MStar for any loss, damage, cost or expense that you may
39 //    incur related to your use of MStar Software.
40 //    In no event shall MStar be liable for any direct, indirect, incidental or
41 //    consequential damages, including without limitation, lost of profit or
42 //    revenues, lost or damage of data, and unauthorized system use.
43 //    You agree that this Section 4 shall still apply without being affected
44 //    even if MStar Software has been modified by MStar in accordance with your
45 //    request or instruction for your use, except otherwise agreed by both
46 //    parties in writing.
47 //
48 // 5. If requested, MStar may from time to time provide technical supports or
49 //    services in relation with MStar Software to you for your use of
50 //    MStar Software in conjunction with your or your customer`s product
51 //    ("Services").
52 //    You understand and agree that, except otherwise agreed by both parties in
53 //    writing, Services are provided on an "AS IS" basis and the warranty
54 //    disclaimer set forth in Section 4 above shall apply.
55 //
56 // 6. Nothing contained herein shall be construed as by implication, estoppels
57 //    or otherwise:
58 //    (a) conferring any license or right to use MStar name, trademark, service
59 //        mark, symbol or any other identification;
60 //    (b) obligating MStar or any of its affiliates to furnish any person,
61 //        including without limitation, you and your customers, any assistance
62 //        of any kind whatsoever, or any information; or
63 //    (c) conferring any license or right under any intellectual property right.
64 //
65 // 7. These terms shall be governed by and construed in accordance with the laws
66 //    of Taiwan, R.O.C., excluding its conflict of law rules.
67 //    Any and all dispute arising out hereof or related hereto shall be finally
68 //    settled by arbitration referred to the Chinese Arbitration Association,
69 //    Taipei in accordance with the ROC Arbitration Law and the Arbitration
70 //    Rules of the Association by three (3) arbitrators appointed in accordance
71 //    with the said Rules.
72 //    The place of arbitration shall be in Taipei, Taiwan and the language shall
73 //    be English.
74 //    The arbitration award shall be final and binding to both parties.
75 //
76 //******************************************************************************
77 //<MStar Software>
78 
79 //=============================================================================
80 #include <MsCommon.h>
81 
82 #include  "include/drvConfig.h"
83 #include  "include/drvCompiler.h"
84 #include  "include/drvErrno.h"
85 #include  "include/drvPorts.h"
86 #include "include/drvTimer.h"
87 #include "include/drvKernel.h"
88 #include "include/drvList.h"
89 
90 U32 volatile jiffies;
91 
92 //void SW_Timer_Tick(U32 u32Value);
93 void SW_Timer_Tick(U32 u32StTimer, U32 u32TimerID);
94 
95 static struct list_head sw_timer_vec_head;
96 
97 S32 g_Timer_ID;
98 
99 #ifdef TIMER_NO_ALL_INT_DISABLE
100 #include "drvHUB.h"
101 extern struct s_ChipUsbHostDef *pCurrentChip;
disable_USB_interrupts(void)102 void disable_USB_interrupts(void)
103 {
104     U8 i;
105 
106     for (i=0; i<pCurrentChip->nRootHub; i++)
107         MsOS_DisableInterrupt(pCurrentChip->reg[i].uhcIRQ);
108 }
109 
enable_USB_interrupts(void)110 void enable_USB_interrupts(void)
111 {
112     U8 i;
113 
114     for (i=0; i<pCurrentChip->nRootHub; i++)
115         MsOS_EnableInterrupt(pCurrentChip->reg[i].uhcIRQ);
116 }
117 #endif
118 
119 S32 _s32MutexUTimer;
init_timers(void)120 void init_timers(void)
121 {
122 	INIT_LIST_HEAD(&sw_timer_vec_head);
123 	// Register software timer dispatch program
124 	// Base 1 ms, interruptted every 1 ms
125 
126 	BOOL err;
127 
128 	g_Timer_ID = MsOS_CreateTimer((TimerCb) SW_Timer_Tick,100, 100, FALSE, "USB_TIMER");
129 	//err = OS_DefineCyclicHandler(&g_Timer_ID, SW_Timer_Tick, (void*) 0, 100);
130 	//USB_ASSERT((err == TRUE), "Define USB timer fail");
131 
132 	//err = OS_ActivateCyclicHandler(g_Timer_ID);
133 	//
134 	err=MsOS_StartTimer(g_Timer_ID);
135 	USB_ASSERT((err == TRUE), "Activate USB timer fail");
136 	//kdbg("Init Software Timer ok %s","\n");
137 	printk("Init Software Timer ok \n");
138         _s32MutexUTimer = MsOS_CreateMutex(E_MSOS_FIFO, "UTimer_MUTEX", MSOS_PROCESS_SHARED);
139 }
140 
remove_timers(void)141 void remove_timers(void)
142 {
143 	MsOS_DeleteTimer(g_Timer_ID);
144 	printk("Remove Software Timer ok \n");
145         MsOS_DeleteMutex(_s32MutexUTimer);
146 }
147 
148 /*
149  * Timer ISR: It's responsible for dispatching tasks registered to software-timer
150  * task queue. It need to be implemented as Bottom-Half mechanism of Linux
151  * Timer and USB IRQ have the same priority and cannot be interrupted by each other
152  */
153 //void SW_Timer_Tick(U32 pData)
SW_Timer_Tick(U32 u32StTimer,U32 u32TimerID)154 void SW_Timer_Tick(U32 u32StTimer, U32 u32TimerID)
155 {
156 	struct timer_list *timer;
157 	struct list_head  *tmp;
158 
159 	jiffies+=100;
160 
161 	if ( Timer_task_lock == 1 )
162 		goto sw_done;
163 
164 	// Dispath task from task queue of software-timer here
165 	if (!list_empty(&sw_timer_vec_head))
166 	{
167 		tmp = sw_timer_vec_head.next;
168 		while (tmp != &sw_timer_vec_head)
169 		{
170 			timer = list_entry (tmp, struct timer_list, entry);
171 			tmp = tmp->next;
172 			//list_entry (tmp, struct timer_list, entry, struct list_head, timer);
173 			// Check if time expired ?
174 			timer->expires -= 100;
175 			if ( timer->expires <= 0 )
176 			{
177 				void (*fn)(U32);
178 				U32 data;
179 				// If lock ==> don't dispatch task
180 				/*
181 				if ( Timer_task_lock == 1 )
182 				{
183 				  timer->expires++;
184 				  continue;
185 				}
186 				*/
187 				fn = timer->function;
188 				data = timer->data;
189 				del_timer(timer);
190 				// Call registered function
191 				if ( (U32)fn )
192 				{
193 					lock_usb_core();
194 					fn(data);
195 					unlock_usb_core();
196 				}
197 				else
198 				{
199 					printk("ERROR: fun is NULL\n");
200 					while(1);
201 				}
202 				//Current version only support dispatch one task each time
203 				//break;
204 			}
205 			/*
206 			if ( (U32)tmp->next == (U32)0x1 )
207 			while(1);
208 			if ( tmp->next == NULL )
209 			while(1);*/
210 		}
211 	}
212 sw_done:
213 	return;
214 	// End of dispatching
215 }
216 
217 #ifdef TIMER_NO_ALL_INT_DISABLE
timerSectionIn(void)218 void timerSectionIn(void)
219 {
220     MsOS_StopTimer(g_Timer_ID);
221     disable_USB_interrupts();
222     MsOS_ObtainMutex(_s32MutexUTimer, MSOS_WAIT_FOREVER);
223 }
timerSectionOut(void)224 void timerSectionOut(void)
225 {
226     enable_USB_interrupts();
227     MsOS_StartTimer(g_Timer_ID);
228     MsOS_ReleaseMutex(_s32MutexUTimer);
229 }
del_timer_body(struct timer_list * timer)230 int del_timer_body(struct timer_list *timer)
231 {
232      //MsOS_StopTimer(g_Timer_ID);
233      //disable_USB_interrupts();
234 
235 	if( timer->entry.next != NULL && timer->entry.prev != NULL )
236 	{
237 		USB_ASSERT(timer->entry.prev->next == &timer->entry, "timer->entry.prev->next error!!!!\n");
238 		USB_ASSERT(timer->entry.next != 0, "timer->entry.next!!!!\n");
239 		USB_ASSERT(timer->entry.next->prev == &timer->entry, "timer->entry.next->prev error!!!!\n");
240 		USB_ASSERT(timer->entry.prev != 0, "timer->entry.prev error!!!!\n");
241 		list_del_init(&timer->entry);
242 	}
243 
244      //enable_USB_interrupts();
245      //MsOS_StartTimer(g_Timer_ID);
246 
247 	//TIMER_TASK_LOCK = flags;
248 	return 1;
249 }
del_timer(struct timer_list * timer)250 int del_timer(struct timer_list *timer)
251 {
252     //timerSectionIn();
253     del_timer_body(timer);
254     //timerSectionOut();
255     return 1;
256 }
del_timer_sync_body(struct timer_list * timer)257 int del_timer_sync_body(struct timer_list *timer)
258 {
259     //MsOS_StopTimer(g_Timer_ID);
260     //disable_USB_interrupts();
261 
262 	if( timer->entry.next != NULL && timer->entry.prev != NULL )
263 	{
264 		USB_ASSERT(timer->entry.prev->next == &timer->entry, "timer->entry.prev->next error!!!!\n");
265 		USB_ASSERT(timer->entry.next != 0, "timer->entry.next!!!!\n");
266 		USB_ASSERT(timer->entry.next->prev == &timer->entry, "timer->entry.next->prev error!!!!\n");
267 		USB_ASSERT(timer->entry.prev != 0, "timer->entry.prev error!!!!\n");
268 		list_del_init(&timer->entry);
269 	}
270 
271      //enable_USB_interrupts();
272      //MsOS_StartTimer(g_Timer_ID);
273 
274 	//TIMER_TASK_LOCK = flags;
275 	return 1;
276 }
del_timer_sync(struct timer_list * timer)277 int del_timer_sync(struct timer_list *timer)
278 {
279     timerSectionIn();
280     del_timer_sync_body(timer);
281     timerSectionOut();
282     return 1;
283 }
add_timer_body(struct timer_list * timer)284 void add_timer_body(struct timer_list *timer)
285 {
286     //MsOS_StopTimer(g_Timer_ID);
287     //disable_USB_interrupts();
288 
289 	if ( (timer->tmout_step > 0) && (timer->tmout_value > timer->tmout_step) )
290 		timer->expires = timer->tmout_step;
291 	else
292 		timer->expires = timer->tmout_value;
293 
294 	list_add_tail(&timer->entry, &sw_timer_vec_head);
295 
296      //enable_USB_interrupts();
297      //MsOS_StartTimer(g_Timer_ID);
298 
299 	//TIMER_TASK_LOCK = flags;
300 }
add_timer(struct timer_list * timer)301 void add_timer(struct timer_list *timer)
302 {
303     timerSectionIn();
304     add_timer_body(timer);
305     timerSectionOut();
306 }
mod_timer_body(struct timer_list * timer,U32 expires,U32 steps)307 int mod_timer_body(struct timer_list *timer, U32 expires, U32 steps)
308 {
309 	//U32 flags;
310 	int ret = 0;
311 
312     //MsOS_StopTimer(g_Timer_ID);
313     //disable_USB_interrupts();
314 
315 	timer->tmout_value = expires;
316 	timer->tmout_step = steps;
317 
318 	//ret = del_timer(timer);
319 	if( timer->entry.next != NULL && timer->entry.prev != NULL )
320 	{
321 		USB_ASSERT(timer->entry.prev->next == &timer->entry, "timer->entry.prev->next error!!!!\n");
322 		USB_ASSERT(timer->entry.next != 0, "timer->entry.next!!!!\n");
323 		USB_ASSERT(timer->entry.next->prev == &timer->entry, "timer->entry.next->prev error!!!!\n");
324 		USB_ASSERT(timer->entry.prev != 0, "timer->entry.prev error!!!!\n");
325 		list_del_init(&timer->entry);
326 	}
327 
328 	//add_timer(timer);
329 	if ( (timer->tmout_step > 0) && (timer->tmout_value > timer->tmout_step) )
330 		timer->expires = timer->tmout_step;
331 	else
332 		timer->expires = timer->tmout_value;
333 	list_add_tail(&timer->entry, &sw_timer_vec_head);
334 
335      //enable_USB_interrupts();
336      //MsOS_StartTimer(g_Timer_ID);
337 
338 	return ret;
339 }
mod_timer(struct timer_list * timer,U32 expires,U32 steps)340 int mod_timer(struct timer_list *timer, U32 expires, U32 steps)
341 {
342     int ret = 0;
343     //timerSectionIn();
344     ret = mod_timer_body(timer, expires, steps);
345     //timerSectionOut();
346     return ret;
347 }
348 #else // Disable All Interrupts
349 /***
350  * del_timer - deactive a timer.
351  * @timer: the timer to be deactivated
352  *
353  * del_timer() deactivates a timer - this works on both active and inactive
354  * timers.
355  *
356  * The function returns whether it has deactivated a pending timer or not.
357  * (ie. del_timer() of an inactive timer returns 0, del_timer() of an
358  * active timer returns 1.)
359  */
del_timer(struct timer_list * timer)360 int del_timer(struct timer_list *timer)
361 {
362 	//U32 flags;
363 
364 	//flags = TIMER_TASK_LOCK;
365 	//lock_TmrTaskDispatch();
366 	//save_and_disable_firqs(&flags);
367 	//HAL_DISABLE_INTERRUPTS(flags);
368 	//OS_DisableDispatch();yuwen
369 	//MsOS_DisableInterrupt(E_IRQ_FIQ_ALL);
370 	 U32 u32OldIntr;
371      u32OldIntr = MsOS_DisableAllInterrupts();
372 
373 	if( timer->entry.next != NULL && timer->entry.prev != NULL )
374 	{
375 		USB_ASSERT(timer->entry.prev->next == &timer->entry, "timer->entry.prev->next error!!!!\n");
376 		USB_ASSERT(timer->entry.next != 0, "timer->entry.next!!!!\n");
377 		USB_ASSERT(timer->entry.next->prev == &timer->entry, "timer->entry.next->prev error!!!!\n");
378 		USB_ASSERT(timer->entry.prev != 0, "timer->entry.prev error!!!!\n");
379 		list_del_init(&timer->entry);
380 	}
381 
382 	//restore_firqs(&flags);
383 	//HAL_RESTORE_INTERRUPTS(flags);
384 	//OS_EnableDispatch();yuwen
385 	//MsOS_EnableInterrupt(E_IRQ_FIQ_ALL);
386      MsOS_RestoreAllInterrupts(u32OldIntr);
387 
388 	//TIMER_TASK_LOCK = flags;
389 	return 1;
390 }
391 
392 /***
393  * del_timer_sync - deactive a timer.
394  * @timer: the timer to be deactivated
395  *
396  * del_timer_sync() deactivates a timer - this works on both active and inactive
397  * timers.
398  *
399  * The function will protect synchronization problem before deactivating timer
400  */
del_timer_sync(struct timer_list * timer)401 int del_timer_sync(struct timer_list *timer)
402 {
403 	//U32 flags;
404 
405 	//flags = TIMER_TASK_LOCK;
406 	//lock_TmrTaskDispatch();
407 	//save_and_disable_firqs(&flags);
408 	//HAL_DISABLE_INTERRUPTS(flags);
409 	//OS_DisableDispatch();
410 	//MsOS_DisableInterrupt(E_IRQ_FIQ_ALL);
411      U32 u32OldIntr;
412      u32OldIntr = MsOS_DisableAllInterrupts();
413 
414 	if( timer->entry.next != NULL && timer->entry.prev != NULL )
415 	{
416 		USB_ASSERT(timer->entry.prev->next == &timer->entry, "timer->entry.prev->next error!!!!\n");
417 		USB_ASSERT(timer->entry.next != 0, "timer->entry.next!!!!\n");
418 		USB_ASSERT(timer->entry.next->prev == &timer->entry, "timer->entry.next->prev error!!!!\n");
419 		USB_ASSERT(timer->entry.prev != 0, "timer->entry.prev error!!!!\n");
420 		list_del_init(&timer->entry);
421 	}
422 
423 	//restore_firqs(&flags);
424 	//HAL_RESTORE_INTERRUPTS(flags);
425 	//OS_EnableDispatch();
426 	//MsOS_EnableInterrupt(E_IRQ_FIQ_ALL);
427      MsOS_RestoreAllInterrupts(u32OldIntr);
428 
429 	//TIMER_TASK_LOCK = flags;
430 	return 1;
431 }
432 
433 /***
434  * add_timer - start a timer
435  * @timer: the timer to be added
436  *
437  * The kernel will do a ->function(->data) callback from the
438  * timer interrupt at the ->expired point in the future. The
439  * current time is 'jiffies'.
440  *
441  * The timer's ->expired, ->function (and if the handler uses it, ->data)
442  * fields must be set prior calling this function.
443  *
444  * Timers with an ->expired field in the past will be executed in the next
445  * timer tick. It's illegal to add an already pending timer.
446  */
add_timer(struct timer_list * timer)447 void add_timer(struct timer_list *timer)
448 {
449 	//U32 flags;
450 
451 	//flags = TIMER_TASK_LOCK;
452 	//lock_TmrTaskDispatch();
453 	//save_and_disable_firqs(&flags);
454 	//HAL_DISABLE_INTERRUPTS(flags);
455 	//OS_DisableDispatch();
456 	//MsOS_DisableInterrupt(E_IRQ_FIQ_ALL);
457     U32 u32OldIntr;
458     u32OldIntr = MsOS_DisableAllInterrupts();
459 
460 	if ( (timer->tmout_step > 0) && (timer->tmout_value > timer->tmout_step) )
461 		timer->expires = timer->tmout_step;
462 	else
463 		timer->expires = timer->tmout_value;
464 
465 	list_add_tail(&timer->entry, &sw_timer_vec_head);
466 
467 	//restore_firqs(&flags);
468 	//HAL_RESTORE_INTERRUPTS(flags);
469 	//OS_EnableDispatch();
470 	//MsOS_EnableInterrupt(E_IRQ_FIQ_ALL);
471      MsOS_RestoreAllInterrupts(u32OldIntr);
472 
473 	//TIMER_TASK_LOCK = flags;
474 }
475 
mod_timer(struct timer_list * timer,U32 expires,U32 steps)476 int mod_timer(struct timer_list *timer, U32 expires, U32 steps)
477 {
478 	//U32 flags;
479 	int ret = 0;
480 
481 	//save_and_disable_firqs(&flags);
482 	//OS_DisableDispatch();
483 	//MsOS_DisableInterrupt(E_IRQ_FIQ_ALL);
484     U32 u32OldIntr;
485     u32OldIntr = MsOS_DisableAllInterrupts();
486 
487 	timer->tmout_value = expires;
488 	timer->tmout_step = steps;
489 
490 	//ret = del_timer(timer);
491 	if( timer->entry.next != NULL && timer->entry.prev != NULL )
492 	{
493 		USB_ASSERT(timer->entry.prev->next == &timer->entry, "timer->entry.prev->next error!!!!\n");
494 		USB_ASSERT(timer->entry.next != 0, "timer->entry.next!!!!\n");
495 		USB_ASSERT(timer->entry.next->prev == &timer->entry, "timer->entry.next->prev error!!!!\n");
496 		USB_ASSERT(timer->entry.prev != 0, "timer->entry.prev error!!!!\n");
497 		list_del_init(&timer->entry);
498 	}
499 
500 	//add_timer(timer);
501 	if ( (timer->tmout_step > 0) && (timer->tmout_value > timer->tmout_step) )
502 		timer->expires = timer->tmout_step;
503 	else
504 		timer->expires = timer->tmout_value;
505 	list_add_tail(&timer->entry, &sw_timer_vec_head);
506 
507 	//restore_firqs(&flags);
508 	//OS_EnableDispatch();
509 	//MsOS_EnableInterrupt(E_IRQ_FIQ_ALL);
510      MsOS_RestoreAllInterrupts(u32OldIntr);
511 
512 	return ret;
513 }
514 #endif	//#ifdef
515 
516