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