Changeset 295 for soft/giet_vm/giet_drivers/xcu_driver.c
- Timestamp:
- Mar 26, 2014, 6:44:44 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_drivers/xcu_driver.c
r281 r295 5 5 // Copyright (c) UPMC-LIP6 6 6 /////////////////////////////////////////////////////////////////////////////////// 7 // The xcu_driver.c and xcu_driver.h files are part ot the GIET-VM nano-kernel.8 // This driver supports the SoCLib vci_xicu, that is a vectorised interrupt9 // controler supporting IPI (Inter Processor Interrupts) and integrated timers.10 //11 // It can exist several interrupt controller unit in the architecture12 // (one per cluster), and each one can contain several channels.13 // The number of XICU channels is equal to NB_PROCS_MAX, because there is14 // one private XICU channel per processor in a cluster.15 ////////////////////////////////////////////////////////////////////////////////16 // The virtual base address of the segment associated to the component is:17 //18 // seg_xcu_base + cluster_xy * vseg_cluster_increment19 //20 // The seg_xcu_base and vseg_cluster_increment values must be defined21 // in giet_vsegs.ld file.22 ////////////////////////////////////////////////////////////////////////////////23 7 24 8 #include <giet_config.h> … … 52 36 #endif 53 37 54 //////////////////////////////////////////////////////////////////////////////// 55 // _xcu_set_mask() 56 // This function set the mask register for the XICU channel identified by the 57 // cluster index and the processor index multiplied by the number of IRQ per 58 // processor. 38 39 //////////////////////////////////////////////////////////////////////////////// 40 // This function set the mask register for the IRQ type defined by "irq_type", 41 // and for the channel identified by the "cluster_xy" and "channel" arguments. 59 42 // All '1' bits are set / all '0' bits are not modified. 60 // Returns 0 if success, > 0 if error. 61 //////////////////////////////////////////////////////////////////////////////// 62 unsigned int _xcu_set_mask( unsigned int cluster_xy, 63 unsigned int irq_index, 64 unsigned int value, 65 unsigned int irq_type ) 66 { 67 // parameters checking 68 unsigned int x = cluster_xy >> Y_WIDTH; 69 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 70 if (x >= X_SIZE) return 1; 71 if (y >= Y_SIZE) return 1; 72 if (irq_index >= (NB_PROCS_MAX * IRQ_PER_PROCESSOR)) return 1; 73 74 #if USE_XICU 43 //////////////////////////////////////////////////////////////////////////////// 44 void _xcu_set_mask( unsigned int cluster_xy, 45 unsigned int channel, 46 unsigned int value, 47 unsigned int irq_type ) 48 { 49 #if USE_XICU 50 // parameters checking 51 unsigned int x = cluster_xy >> Y_WIDTH; 52 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 53 if (x >= X_SIZE) _exit(); 54 if (y >= Y_SIZE) _exit(); 55 if (channel >= (NB_PROCS_MAX * IRQ_PER_PROCESSOR)) _exit(); 56 75 57 volatile unsigned int* xcu_address = 76 58 (unsigned int *) ((unsigned int)&seg_xcu_base + … … 79 61 unsigned int func; 80 62 if (irq_type == IRQ_TYPE_PTI) func = XICU_MSK_PTI_ENABLE; 81 else if (irq_type == IRQ_TYPE_SWI) func = XICU_MSK_WTI_ENABLE; 82 else func = XICU_MSK_HWI_ENABLE; 83 xcu_address[XICU_REG(func,irq_index)] = value; 84 return 0; 85 #else 86 _tty_get_lock( 0 ); 87 _puts("[GIET ERROR] _xcu_set_mask should not be used if USE_XICU is not set\n"); 88 _tty_release_lock( 0 ); 89 return 1; 90 #endif 91 } 92 93 //////////////////////////////////////////////////////////////////////////////// 94 // _xcu_get_index() 95 // This function returns the index of the highest priority (smaller index) 96 // - active HWI (Hardware Interrupt), or 97 // - active PTI (Timer Interrupt), or 98 // - active SWI (Software Interrupt). 99 // The ICU channel is identified by the cluster index and the processor index 100 // multiplied by the number of IRQ per processor. 101 // Returns 0 if success, > 0 if error. 102 //////////////////////////////////////////////////////////////////////////////// 103 unsigned int _xcu_get_index( unsigned int cluster_xy, 104 unsigned int irq_index, 105 unsigned int * buffer) 106 { 107 // parameters checking 108 unsigned int x = cluster_xy >> Y_WIDTH; 109 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 110 if (x >= X_SIZE) return 1; 111 if (y >= Y_SIZE) return 1; 112 if (irq_index >= (NB_PROCS_MAX * IRQ_PER_PROCESSOR)) return 1; 113 114 #if USE_XICU 115 volatile unsigned int* xcu_address = 116 (unsigned int *) ((unsigned int)&seg_xcu_base + 117 (cluster_xy * (unsigned int)&vseg_cluster_increment)); 118 119 unsigned int prio = xcu_address[XICU_REG(XICU_PRIO,irq_index)]; 63 else if (irq_type == IRQ_TYPE_WTI) func = XICU_MSK_WTI_ENABLE; 64 else if (irq_type == IRQ_TYPE_HWI) func = XICU_MSK_HWI_ENABLE; 65 else 66 { 67 _printf("[GIET ERROR] _xcu_set_mask() receives illegal IRQ type\n"); 68 _exit(); 69 } 70 71 xcu_address[XICU_REG(func,channel)] = value; 72 73 #else 74 _printf("[GIET ERROR] _xcu_set_mask() should not be used if USE_XICU not set\n"); 75 _exit(); 76 #endif 77 } 78 79 //////////////////////////////////////////////////////////////////////////////// 80 // This function returns the index and the type of the highest priority 81 // - active PTI (Timer Interrupt), then 82 // - active HWI (Hardware Interrupt), then 83 // - active WTI (Software Interrupt) 84 // As the hardware can define more than one IRQ per processor, but the GIET 85 // use only one, channel = lpid * IRQ_PER_PROCESSOR. 86 //////////////////////////////////////////////////////////////////////////////// 87 void _xcu_get_index( unsigned int cluster_xy, 88 unsigned int channel, 89 unsigned int * index, 90 unsigned int * irq_type ) 91 { 92 #if USE_XICU 93 // parameters checking 94 unsigned int x = cluster_xy >> Y_WIDTH; 95 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 96 if (x >= X_SIZE) _exit(); 97 if (y >= Y_SIZE) _exit(); 98 if (channel >= (NB_PROCS_MAX * IRQ_PER_PROCESSOR)) _exit(); 99 100 volatile unsigned int* xcu_address = 101 (unsigned int *) ((unsigned int)&seg_xcu_base + 102 (cluster_xy * (unsigned int)&vseg_cluster_increment)); 103 104 unsigned int prio = xcu_address[XICU_REG(XICU_PRIO,channel)]; 120 105 unsigned int pti_ok = (prio & 0x00000001); 121 106 unsigned int hwi_ok = (prio & 0x00000002); 122 unsigned int swi_ok = (prio & 0x00000004);107 unsigned int wti_ok = (prio & 0x00000004); 123 108 unsigned int pti_id = (prio & 0x00001F00) >> 8; 124 109 unsigned int hwi_id = (prio & 0x001F0000) >> 16; 125 unsigned int swi_id = (prio & 0x1F000000) >> 24; 126 if (pti_ok) *buffer = pti_id; 127 else if (hwi_ok) *buffer = hwi_id; 128 else if (swi_ok) *buffer = swi_id; 129 else *buffer = 32; 130 return 0; 131 #else 132 _tty_get_lock( 0 ); 133 _puts("[GIET ERROR] _xcu_get_index should not be used if USE_XICU is not set\n"); 134 _tty_release_lock( 0 ); 135 return 1; 136 #endif 137 } 138 139 //////////////////////////////////////////////////////////////////////////////// 140 // _xcu_send_ipi() 141 // This function can be used only in an architecture using XICU components. 142 // It writes the "wdata" value in the mailbox defined by the cluster index 143 // and the processor index. 144 // Giet-VM supports at most NB_PROCS_MAX mailboxes: 145 // (0 <= wti_index <= NB_PROCS_MAX-1) 146 // Returns 0 if success, > 0 if error. 147 //////////////////////////////////////////////////////////////////////////////// 148 unsigned int _xcu_send_ipi( unsigned int cluster_xy, 149 unsigned int wti_index, 150 unsigned int wdata ) 110 unsigned int wti_id = (prio & 0x1F000000) >> 24; 111 if (pti_ok) 112 { 113 *index = pti_id; 114 *irq_type = IRQ_TYPE_PTI; 115 } 116 else if (hwi_ok) 117 { 118 *index = hwi_id; 119 *irq_type = IRQ_TYPE_HWI; 120 } 121 else if (wti_ok) 122 { 123 *index = wti_id; 124 *irq_type = IRQ_TYPE_WTI; 125 } 126 else 127 { 128 *index = 32; 129 } 130 131 #else 132 _printf("[GIET ERROR] _xcu_get_index should not be used if USE_XICU is not set\n"); 133 _exit(); 134 #endif 135 } 136 137 //////////////////////////////////////////////////////////////////////////////// 138 // This function writes the "wdata" value in the mailbox defined 139 // by the "cluster_xy" and "wti_index" arguments. 140 //////////////////////////////////////////////////////////////////////////////// 141 void _xcu_send_wti( unsigned int cluster_xy, 142 unsigned int wti_index, 143 unsigned int wdata ) 151 144 { 152 // parameters checking 153 unsigned int x = cluster_xy >> Y_WIDTH;154 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);155 if (x >= X_SIZE) return 1;156 if ( y >= Y_SIZE) return 1;157 if ( wti_index >= NB_PROCS_MAX) return 1;158 159 #if USE_XICU 145 #if USE_XICU 146 // parameters checking 147 unsigned int x = cluster_xy >> Y_WIDTH; 148 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 149 if (x >= X_SIZE) _exit(); 150 if (y >= Y_SIZE) _exit(); 151 if (wti_index >= 32) _exit(); 152 160 153 volatile unsigned int* xcu_address = 161 154 (unsigned int *) ((unsigned int)&seg_xcu_base + … … 163 156 164 157 xcu_address[XICU_REG(XICU_WTI_REG,wti_index)] = wdata; 165 return 0; 166 #else 167 _tty_get_lock( 0 ); 168 _puts("[GIET ERROR] _xcu_send_ipi should not be used if USE_XICU is not set\n"); 169 _tty_release_lock( 0 ); 170 return 1; 158 159 #else 160 _printf("[GIET ERROR] _xcu_send_ipi should not be used if USE_XICU is not set\n"); 161 _exit(); 171 162 #endif 172 163 } 173 164 174 165 //////////////////////////////////////////////////////////////////////////////// 175 // _xcu_timer_start() 166 // This function returns the value contained in a WTI mailbox defined by 167 // the cluster_xy and "wti_index" arguments. This value is written in 168 // the "value" argument, and the corresponding WTI is acknowledged. 169 // returns 0 if success, > 0 if error. 170 //////////////////////////////////////////////////////////////////////////////// 171 void _xcu_get_wti_value( unsigned int cluster_xy, 172 unsigned int wti_index, 173 unsigned int * value ) 174 { 175 #if USE_XICU 176 // parameters checking 177 unsigned int x = cluster_xy >> Y_WIDTH; 178 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 179 if (x >= X_SIZE) _exit(); 180 if (y >= Y_SIZE) _exit(); 181 if (wti_index >= 32) _exit(); 182 183 volatile unsigned int* xcu_address = 184 (unsigned int *) ((unsigned int)&seg_xcu_base + 185 (cluster_xy * (unsigned int)&vseg_cluster_increment)); 186 187 *value = xcu_address[XICU_REG(XICU_WTI_REG, wti_index)]; 188 189 #else 190 _printf("[GIET ERROR] in _xcu_get_wti_value() USE_XICU is not set\n"); 191 _exit(); 192 #endif 193 } 194 195 //////////////////////////////////////////////////////////////////////////////// 196 // This function returns the address of a WTI mailbox defined by 197 // the "wti_index" argument, in the unsigned int "address" argument. 198 // It is used by the GIET to configurate the IOPIC component. 199 // There is no access to a specific XCU component in a specific cluster. 200 // returns 0 if success, > 0 if error. 201 //////////////////////////////////////////////////////////////////////////////// 202 void _xcu_get_wti_address( unsigned int wti_index, 203 unsigned int * address ) 204 { 205 #if USE_XICU 206 if (wti_index >= 32) _exit(); 207 208 unsigned int xcu_address = (unsigned int)&seg_xcu_base; 209 *address = xcu_address + (XICU_REG(XICU_WTI_REG, wti_index)<<2); 210 211 #else 212 _printf("[GIET ERROR] in _xcu_get_wti_address() USE_XICU is not set\n"); 213 _exit(); 214 #endif 215 } 216 217 //////////////////////////////////////////////////////////////////////////////// 176 218 // This function activates a timer contained in XICU by writing in the 177 219 // proper register the period value. 178 // Returns 0 if success, > 0 if error. 179 //////////////////////////////////////////////////////////////////////////////// 180 unsigned int _xcu_timer_start( unsigned int cluster_xy, 181 unsigned int pti_index, 182 unsigned int period ) 183 { 184 // parameters checking 185 unsigned int x = cluster_xy >> Y_WIDTH; 186 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 187 if (x >= X_SIZE) return 1; 188 if (y >= Y_SIZE) return 1; 189 190 #if USE_XICU 220 //////////////////////////////////////////////////////////////////////////////// 221 void _xcu_timer_start( unsigned int cluster_xy, 222 unsigned int pti_index, 223 unsigned int period ) 224 { 225 #if USE_XICU 226 // parameters checking 227 unsigned int x = cluster_xy >> Y_WIDTH; 228 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 229 if (x >= X_SIZE) _exit(); 230 if (y >= Y_SIZE) _exit(); 231 191 232 volatile unsigned int* xcu_address = 192 233 (unsigned int *) ((unsigned int)&seg_xcu_base + … … 194 235 195 236 xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = period; 196 return 0; 197 #else 198 _tty_get_lock( 0 ); 199 _puts("[GIET ERROR] _xcu_timer_start should not be used if USE_XICU is not set\n"); 200 _tty_release_lock( 0 ); 201 return 1; 202 #endif 203 } 204 205 ////////////////////////////////////////////////////////////////////////////// 206 // _xcu_timer_stop() 237 238 #else 239 _printf("[GIET ERROR] in _xcu_timer_start() USE_XICU is not set\n"); 240 _exit(); 241 #endif 242 } 243 244 ////////////////////////////////////////////////////////////////////////////// 207 245 // This function desactivates a timer in XICU component 208 246 // by writing in the proper register. 209 // Returns 0 if success, > 0 if error. 210 ////////////////////////////////////////////////////////////////////////////// 211 unsigned int _xcu_timer_stop( unsigned int cluster_xy, 212 unsigned int pti_index) 213 { 214 // parameters checking 215 unsigned int x = cluster_xy >> Y_WIDTH; 216 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 217 if (x >= X_SIZE) return 1; 218 if (y >= Y_SIZE) return 1; 219 220 #if USE_XICU 247 ////////////////////////////////////////////////////////////////////////////// 248 void _xcu_timer_stop( unsigned int cluster_xy, 249 unsigned int pti_index) 250 { 251 #if USE_XICU 252 // parameters checking 253 unsigned int x = cluster_xy >> Y_WIDTH; 254 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 255 if (x >= X_SIZE) _exit(); 256 if (y >= Y_SIZE) _exit(); 257 221 258 volatile unsigned int * xcu_address = 222 259 (unsigned int *) ((unsigned int)&seg_xcu_base + … … 224 261 225 262 xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = 0; 226 return 0; 227 #else 228 _tty_get_lock( 0 ); 229 _puts("[GIET ERROR] _xcu_timer_stop should not be used if USE_XICU is not set\n"); 230 _tty_release_lock( 0 ); 231 return 1; 232 #endif 233 } 234 235 ////////////////////////////////////////////////////////////////////////////// 236 // _xcu_timer_reset_irq() 263 264 #else 265 _printf("[GIET ERROR] in _xcu_timer_stop() USE_XICU is not set\n"); 266 _exit(); 267 #endif 268 } 269 270 ////////////////////////////////////////////////////////////////////////////// 237 271 // This function acknowlegge a timer interrupt in XICU 238 272 // component by reading in the proper register. 239 273 // It can be used by both the isr_switch() for a "system" timer, 240 274 // or by the _isr_timer() for an "user" timer. 241 // Returns 0 if success, > 0 if error. 242 ////////////////////////////////////////////////////////////////////////////// 243 unsigned int _xcu_timer_reset_irq( unsigned int cluster_xy, 244 unsigned int pti_index ) 245 { 246 // parameters checking 247 unsigned int x = cluster_xy >> Y_WIDTH; 248 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 249 if (x >= X_SIZE) return 1; 250 if (y >= Y_SIZE) return 1; 251 252 #if USE_XICU 275 ////////////////////////////////////////////////////////////////////////////// 276 void _xcu_timer_reset_irq( unsigned int cluster_xy, 277 unsigned int pti_index ) 278 { 279 #if USE_XICU 280 // parameters checking 281 unsigned int x = cluster_xy >> Y_WIDTH; 282 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 283 if (x >= X_SIZE) _exit(); 284 if (y >= Y_SIZE) _exit(); 285 253 286 volatile unsigned int * xcu_address = 254 287 (unsigned int *) ((unsigned int)&seg_xcu_base + … … 256 289 257 290 xcu_address[XICU_REG(XICU_PTI_ACK, pti_index)]; 258 return 0; 259 #else 260 _tty_get_lock( 0 ); 261 _puts("[GIET ERROR] _xcu_timer_reset_irq should not be used if USE_XICU is not set\n"); 262 _tty_release_lock( 0 ); 263 return 1; 264 #endif 265 } 266 267 ////////////////////////////////////////////////////////////////////////////// 268 // _xcu_timer_reset_cpt() 291 292 #else 293 _printf("[GIET ERROR] in _xcu_timer_reset_irq() USE_XICU is not set\n"); 294 _exit(); 295 #endif 296 } 297 298 ////////////////////////////////////////////////////////////////////////////// 269 299 // This function resets a timer counter. To do so, we re-write the period 270 300 // in the proper register, what causes the count to restart. 271 301 // The period value is read from the same (TIMER_PERIOD) register, 272 302 // this is why in appearance we do nothing useful (read a value 273 // from a register and write this value in the same register) 303 // from a register and write this value in the same register). 274 304 // This function is called during a context switch (user or preemptive) 275 305 ///////////////////////////////////////////////////////////////////////////// 276 unsigned int_xcu_timer_reset_cpt( unsigned int cluster_xy,277 278 { 279 // parameters checking 280 unsigned int x = cluster_xy >> Y_WIDTH;281 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);282 if (x >= X_SIZE) return 1;283 if ( y >= Y_SIZE) return 1;284 285 #if USE_XICU 306 void _xcu_timer_reset_cpt( unsigned int cluster_xy, 307 unsigned int pti_index ) 308 { 309 #if USE_XICU 310 // parameters checking 311 unsigned int x = cluster_xy >> Y_WIDTH; 312 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 313 if (x >= X_SIZE) _exit(); 314 if (y >= Y_SIZE) _exit(); 315 286 316 volatile unsigned int * xcu_address = 287 317 (unsigned int *) ((unsigned int) &seg_xcu_base + … … 294 324 xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = 0; 295 325 xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = period; 296 return 0; 297 #else 298 _tty_get_lock( 0 ); 299 _puts("[GIET ERROR] _xcu_timer_reset_irq should not be used if USE_XICU is not set\n"); 300 _tty_release_lock( 0 ); 301 return 1; 326 327 #else 328 _printf("[GIET ERROR] in _xcu_timer_reset_cpt() USE_XICU is not set\n"); 329 _exit(); 302 330 #endif 303 331 }
Note: See TracChangeset
for help on using the changeset viewer.