1 #ifndef __ALT_AVALON_TIMER_H__
2 #define __ALT_AVALON_TIMER_H__
3 
4 /******************************************************************************
5 *                                                                             *
6 * License Agreement                                                           *
7 *                                                                             *
8 * Copyright (c) 2003 Altera Corporation, San Jose, California, USA.           *
9 * All rights reserved.                                                        *
10 *                                                                             *
11 * Permission is hereby granted, free of charge, to any person obtaining a     *
12 * copy of this software and associated documentation files (the "Software"),  *
13 * to deal in the Software without restriction, including without limitation   *
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,    *
15 * and/or sell copies of the Software, and to permit persons to whom the       *
16 * Software is furnished to do so, subject to the following conditions:        *
17 *                                                                             *
18 * The above copyright notice and this permission notice shall be included in  *
19 * all copies or substantial portions of the Software.                         *
20 *                                                                             *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  *
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,    *
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER      *
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING     *
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER         *
27 * DEALINGS IN THE SOFTWARE.                                                   *
28 *                                                                             *
29 *                                                                             *
30 * Altera does not recommend, suggest or require that this reference design    *
31 * file be used in conjunction or combination with any other product.          *
32 ******************************************************************************/
33 
34 #include <string.h>
35 
36 #include "alt_types.h"
37 #include "sys/alt_dev.h"
38 #include "sys/alt_warning.h"
39 
40 #ifdef __cplusplus
41 extern "C"
42 {
43 #endif /* __cplusplus */
44 
45 
46 #define __ALT_COUNTER_SIZE(name) name##_COUNTER_SIZE
47 #define _ALT_COUNTER_SIZE(name) __ALT_COUNTER_SIZE(name)
48 
49 #define ALT_SYS_CLK_COUNTER_SIZE _ALT_COUNTER_SIZE(ALT_SYS_CLK)
50 #define ALT_TIMESTAMP_COUNTER_SIZE _ALT_COUNTER_SIZE(ALT_TIMESTAMP_CLK)
51 
52 #if (ALT_SYS_CLK_COUNTER_SIZE == 64)
53 #define alt_sysclk_type alt_u64
54 #else
55 #define alt_sysclk_type alt_u32
56 #endif
57 
58 #if (ALT_TIMESTAMP_COUNTER_SIZE == 64)
59 #define alt_timestamp_type alt_u64
60 #else
61 #define alt_timestamp_type alt_u32
62 #endif
63 
64 /*
65  * The function alt_avalon_timer_sc_init() is the initialisation function for
66  * the system clock. It registers the timers interrupt handler, and then calls
67  * the system clock regestration function, alt_sysclk_init().
68  */
69 
70 extern void alt_avalon_timer_sc_init (void* base, alt_u32 irq_controller_id,
71                                       alt_u32 irq, alt_u32 freq);
72 
73 /*
74  * Variables used to store the timestamp parameters, when the device is to be
75  * accessed using the high resolution timestamp driver.
76  */
77 
78 extern void*   altera_avalon_timer_ts_base;
79 extern alt_u32 altera_avalon_timer_ts_freq;
80 
81 /*
82  * ALTERA_AVALON_TIMER_INSTANCE is the macro used by alt_sys_init() to
83  * allocate any per device memory that may be required. In this case no
84  * allocation is necessary.
85  */
86 
87 #define ALTERA_AVALON_TIMER_INSTANCE(name, dev) extern int alt_no_storage
88 
89 /*
90  * Macro used to calculate the timer interrupt frequency. Although this is
91  * somewhat fearsome, when compiled with -O2 it will be resolved at compile
92  * time to a constant value.
93  */
94 
95 #define ALTERA_AVALON_TIMER_FREQ(freq, period, units) \
96   strcmp (units, "us") ?                              \
97     (strcmp (units, "ms") ?                           \
98       (strcmp (units, "s") ?                          \
99         ((freq + (period - 1))/period)                \
100       : 1)                                            \
101     : (1000 + (period - 1))/period)                   \
102   : ((1000000 + (period - 1))/period)
103 
104 /*
105  * Construct macros which contain the base address of the system clock and the
106  * timestamp device. These are used below to determine which driver to use for
107  * a given timer.
108  */
109 
110 #define __ALT_CLK_BASE(name) name##_BASE
111 #define _ALT_CLK_BASE(name) __ALT_CLK_BASE(name)
112 
113 #define ALT_SYS_CLK_BASE _ALT_CLK_BASE(ALT_SYS_CLK)
114 #define ALT_TIMESTAMP_CLK_BASE _ALT_CLK_BASE(ALT_TIMESTAMP_CLK)
115 
116 /*
117  * If there is no system clock, then the above macro will result in
118  * ALT_SYS_CLK_BASE being set to none_BASE. We therefore need to provide an
119  * invalid value for this, so that no timer is wrongly identified as the system
120  * clock.
121  */
122 
123 #define none_BASE 0xffffffff
124 
125 /*
126  * ALTERA_AVALON_TIMER_INIT is the macro used by alt_sys_init() to provide
127  * the run time initialisation of the device. In this case this translates to
128  * a call to alt_avalon_timer_sc_init() if the device is the system clock, i.e.
129  * if it has the name "sysclk".
130  *
131  * If the device is not the system clock, then it is used to provide the
132  * timestamp facility.
133  *
134  * To ensure as much as possible is evaluated at compile time, rather than
135  * compare the name of the device to "/dev/sysclk" using strcmp(), the base
136  * address of the device is compared to SYSCLK_BASE to determine whether it's
137  * the system clock. Since the base address of a device must be unique, these
138  * two aproaches are equivalent.
139  *
140  * This macro performs a sanity check to ensure that the interrupt has been
141  * connected for this device. If not, then an apropriate error message is
142  * generated at build time.
143  */
144 
145 
146 #define ALTERA_AVALON_TIMER_INIT(name, dev)                                   \
147   if (name##_BASE == ALT_SYS_CLK_BASE)                                        \
148   {                                                                           \
149     if (name##_IRQ == ALT_IRQ_NOT_CONNECTED)                                  \
150     {                                                                         \
151       ALT_LINK_ERROR ("Error: Interrupt not connected for " #dev ". "         \
152                       "The system clock driver requires an interrupt to be "  \
153                       "connected. Please select an IRQ for this device in "   \
154                       "SOPC builder.");                                       \
155     }                                                                         \
156     else                                                                      \
157     {                                                                         \
158       alt_avalon_timer_sc_init((void*) name##_BASE,                           \
159                                name##_IRQ_INTERRUPT_CONTROLLER_ID,            \
160                                name##_IRQ,                                    \
161                                ALTERA_AVALON_TIMER_FREQ(name##_FREQ,          \
162                                                         name##_PERIOD,        \
163                                                         name##_PERIOD_UNITS));\
164     }                                                                         \
165   }                                                                           \
166   else if (name##_BASE == ALT_TIMESTAMP_CLK_BASE)                             \
167   {                                                                           \
168     if (name##_SNAPSHOT)                                                      \
169     {                                                                         \
170       altera_avalon_timer_ts_base = (void*) name##_BASE;                      \
171       altera_avalon_timer_ts_freq = name##_FREQ;                              \
172     }                                                                         \
173     else                                                                      \
174     {                                                                         \
175        ALT_LINK_ERROR ("Error: Snapshot register not available for "          \
176                        #dev ". "                                              \
177                       "The timestamp driver requires the snapshot register "  \
178                       "to be readable. Please enable this register for this " \
179                       "device in SOPC builder.");                             \
180     }                                                                         \
181   }
182 
183 /*
184  *
185  */
186 
187 #ifdef __cplusplus
188 }
189 #endif /* __cplusplus */
190 
191 #endif /* __ALT_AVALON_TIMER_H__ */
192