147 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			147 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Copyright (c) 2011 Aeroflex Gaisler
 | |
|  *
 | |
|  * BSD license:
 | |
|  *
 | |
|  * Permission is hereby granted, free of charge, to any person obtaining a copy
 | |
|  * of this software and associated documentation files (the "Software"), to deal
 | |
|  * in the Software without restriction, including without limitation the rights
 | |
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | |
|  * copies of the Software, and to permit persons to whom the Software is
 | |
|  * furnished to do so, subject to the following conditions:
 | |
|  *
 | |
|  * The above copyright notice and this permission notice shall be included in
 | |
|  * all copies or substantial portions of the Software.
 | |
|  *
 | |
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | |
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | |
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | |
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | |
|  * THE SOFTWARE.
 | |
|  */
 | |
| 
 | |
| 
 | |
| #include <sys/types.h>
 | |
| #include <sys/time.h>
 | |
| #include <sys/errno.h>
 | |
| #include <asm-leon/leon.h>
 | |
| #include <asm-leon/irq.h>
 | |
| #include <asm-leon/timer.h>
 | |
| #include <asm-leon/leoncompat.h>
 | |
| 
 | |
| // '''''''''''''''''''''''''''''''''''''''''''''''''''''
 | |
| 
 | |
| TAILQ_HEAD (timer_queue, timerevent) timers = TAILQ_HEAD_INITIALIZER (timers);
 | |
| 
 | |
|      int
 | |
|      addtimer (struct timerevent *e)
 | |
| {
 | |
|   struct timerevent *next;
 | |
|   unsigned long old = leonbare_disable_traps ();
 | |
|   TAILQ_FOREACH (next, &timers, n)
 | |
|   {
 | |
|     if (!GT_TIMESPEC (e->expire, next->expire))
 | |
|       break;
 | |
|   }
 | |
|   if (next)
 | |
|     {
 | |
|       TAILQ_INSERT_BEFORE (next, e, n);
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       TAILQ_INSERT_TAIL (&timers, e, n);
 | |
|     }
 | |
|   leonbare_enable_traps (old);
 | |
| }
 | |
| 
 | |
| extern unsigned long noalarm;
 | |
| void
 | |
| settimer ()
 | |
| {
 | |
|   struct timeval tv, te;
 | |
|   struct timerevent *e = TAILQ_FIRST (&timers), *n;
 | |
|   while (e)
 | |
|     {
 | |
|       n = TAILQ_NEXT (e, n);
 | |
|       te.tv_sec = e->expire.tv_sec;
 | |
|       te.tv_usec = e->expire.tv_nsec / NSEC_PER_USEC;
 | |
|       do_gettimeofday (&tv);
 | |
|       if (GT_TIMEVAL (te, tv))
 | |
| 	{
 | |
| 	  MINUS_TIMEVAL (te, te, tv);
 | |
| 	  if (!tv.tv_sec || te.tv_usec <= tick_usec)
 | |
| 	    {
 | |
| 	      if (!noalarm)
 | |
| 		{
 | |
| 		  //---------------------
 | |
| 		  switch (LEONCOMPAT_VERSION)
 | |
| 		    {
 | |
| 		    case 3:
 | |
| 		    default:
 | |
| 		      LEON3_GpTimer_Regs->e[1].val = 0;
 | |
| 		      LEON3_GpTimer_Regs->e[1].rld = te.tv_usec - 1;
 | |
| 		      LEON3_GpTimer_Regs->e[1].ctrl = 0;
 | |
| 		      LEON3_GpTimer_Regs->e[1].ctrl =
 | |
| 			LEON3_GPTIMER_EN |
 | |
| 			LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN;
 | |
| 		      break;
 | |
| 		    }
 | |
| 		}
 | |
| 	      //---------------------
 | |
| 	    }
 | |
| 	}
 | |
|       else
 | |
| 	{
 | |
| 	  unsigned long old = leonbare_disable_traps ();
 | |
| 	  TAILQ_REMOVE (&timers, e, n);
 | |
| 	  e->handler (e->arg);
 | |
| 	  leonbare_enable_traps (old);
 | |
| 	}
 | |
|       e = n;
 | |
|     }
 | |
| }
 | |
| 
 | |
| int
 | |
| Timer_getTimer1 (unsigned int **count, unsigned int **reload,
 | |
| 		 unsigned int **ctrl)
 | |
| {
 | |
|   //---------------------
 | |
|   switch (LEONCOMPAT_VERSION)
 | |
|     {
 | |
|     case 3:
 | |
|     default:
 | |
|       amba_init ();
 | |
|       *count = (unsigned int *) &(LEON3_GpTimer_Regs->e[0].val);
 | |
|       *reload = (unsigned int *) &(LEON3_GpTimer_Regs->e[0].rld);
 | |
|       *ctrl = (unsigned int *) &(LEON3_GpTimer_Regs->e[0].ctrl);
 | |
|       break;
 | |
|     }
 | |
|   //---------------------
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| int
 | |
| Timer_getTimer2 (unsigned int **count, unsigned int **reload,
 | |
| 		 unsigned int **ctrl)
 | |
| {
 | |
|   //---------------------
 | |
|   switch (LEONCOMPAT_VERSION)
 | |
|     {
 | |
|     case 3:
 | |
|     default:
 | |
|       amba_init ();
 | |
|       if (!noalarm)
 | |
| 	{
 | |
| 	  *count = (unsigned int *) &(LEON3_GpTimer_Regs->e[1].val);
 | |
| 	  *reload = (unsigned int *) &(LEON3_GpTimer_Regs->e[1].rld);
 | |
| 	  *ctrl = (unsigned int *) &(LEON3_GpTimer_Regs->e[1].ctrl);
 | |
| 	  break;
 | |
| 	}
 | |
|       return 0;
 | |
|     }
 | |
|   //---------------------
 | |
|   return 1;
 | |
| }
 |