]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/at91/var/v2_0/src/timer_pit.c
Initial revision
[karo-tx-redboot.git] / packages / hal / arm / at91 / var / v2_0 / src / timer_pit.c
1 /*==========================================================================
2 //
3 //      timer_pit.c
4 //
5 //      HAL timer code using the Periodic Interval Timer
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 2006 eCosCentric Ltd
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 // -------------------------------------------
36 //####ECOSGPLCOPYRIGHTEND####
37 //==========================================================================
38 //#####DESCRIPTIONBEGIN####
39 //
40 // Author(s):    asl, Oliver Munz
41 // Contributors: asl, Oliver Munz
42 // Date:         2006-02-12
43 // Purpose:      Clock support using the PIT
44 // Description:  
45 //
46 //####DESCRIPTIONEND####
47 //
48 //========================================================================*/
49
50 #include <pkgconf/hal.h>
51
52 #include <cyg/infra/cyg_type.h>         // base types
53 #include <cyg/infra/cyg_ass.h>          // assertion macros
54
55 #include <cyg/hal/hal_io.h>             // IO macros
56 #include <cyg/hal/hal_platform_ints.h>
57 // -------------------------------------------------------------------------
58 // Use system clock
59 void
60 hal_clock_initialize(cyg_uint32 period)
61 {
62   cyg_uint32 sr;
63   
64   CYG_ASSERT(CYGNUM_HAL_INTERRUPT_RTC == CYGNUM_HAL_INTERRUPT_PITC,
65              "Invalid timer interrupt");
66   
67   /* Set Period Interval timer and enable interrupt */
68   HAL_WRITE_UINT32((AT91_PITC + AT91_PITC_PIMR), 
69                    (period - 1) |  
70                    AT91_PITC_PIMR_PITEN |
71                    AT91_PITC_PIMR_PITIEN);
72   
73   // Read the status register to clear any pending interrupt
74   HAL_READ_UINT32(AT91_PITC + AT91_PITC_PISR, sr);
75 }
76
77 // This routine is called during a clock interrupt.
78 void
79 hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
80 {
81   cyg_uint32 reg;
82   cyg_uint32 pimr;
83   
84   CYG_ASSERT(period < AT91_PITC_VALUE_MASK, "Invalid HAL clock configuration");
85   
86   // Check that the PIT has the right period.
87   HAL_READ_UINT32((AT91_PITC + AT91_PITC_PIMR), pimr);
88   if ((pimr & AT91_PITC_VALUE_MASK) != (period - 1)) {
89     HAL_WRITE_UINT32((AT91_PITC + AT91_PITC_PIMR), 
90                      (period - 1) |  
91                      AT91_PITC_PIMR_PITEN |
92                      AT91_PITC_PIMR_PITIEN);
93   }
94
95   /* Read the value register so that we clear the interrupt */
96   HAL_READ_UINT32(AT91_PITC + AT91_PITC_PIVR, reg);
97 }
98
99 // Read the current value of the clock, returning the number of hardware
100 // "ticks" that have occurred (i.e. how far away the current value is from
101 // the start)
102 void
103 hal_clock_read(cyg_uint32 *pvalue)
104 {
105   cyg_uint32 ir;
106   cyg_uint32 pimr;
107   
108   // Check that the PIT is running. If not start it.
109   HAL_READ_UINT32((AT91_PITC + AT91_PITC_PIMR),pimr);
110   if (!(pimr & AT91_PITC_PIMR_PITEN)) {
111     HAL_WRITE_UINT32((AT91_PITC + AT91_PITC_PIMR), 
112                      AT91_PITC_VALUE_MASK | AT91_PITC_PIMR_PITEN);
113   }
114   
115   HAL_READ_UINT32(AT91_PITC + AT91_PITC_PIIR, ir);
116   *pvalue = ir & AT91_PITC_VALUE_MASK;
117 }
118
119 // -------------------------------------------------------------------------
120 //
121 // Delay for some number of micro-seconds
122 // PIT is clocked at MCLK / 16
123 //
124 void hal_delay_us(cyg_int32 usecs)
125 {
126   cyg_int64 ticks;
127   cyg_uint32 val1, val2;
128   cyg_uint32 piv;
129   
130   // Calculate how many PIT ticks the required number of microseconds
131   // equate to. We do this calculation in 64 bit arithmetic to avoid
132   // overflow.
133   ticks = (((cyg_uint64)usecs) * 
134            ((cyg_uint64)CYGNUM_HAL_ARM_AT91_CLOCK_SPEED))/16/1000000LL;
135   
136   // Calculate the wrap around period. 
137   HAL_READ_UINT32(AT91_PITC + AT91_PITC_PIMR, piv);
138   piv = (piv & AT91_PITC_VALUE_MASK) - 1; 
139   
140   hal_clock_read(&val1);
141   while (ticks > 0) {
142     hal_clock_read(&val2);
143     if (val2 < val1)
144       ticks -= ((piv + val2) - val1); //overflow occurred
145     else 
146       ticks -= (val2 - val1);
147     val1 = val2;
148   }
149 }
150
151 // timer_pit.c