1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include "assert_support.h"
16#include "irq.h"
17
18#ifndef __INLINE_GP_DEVICE__
19#define __INLINE_GP_DEVICE__
20#endif
21#include "gp_device.h"
22
23#include "platform_support.h"
24
25static inline void irq_wait_for_write_complete(
26 const irq_ID_t ID);
27
28static inline bool any_irq_channel_enabled(
29 const irq_ID_t ID);
30
31static inline irq_ID_t virq_get_irq_id(
32 const virq_id_t irq_ID,
33 unsigned int *channel_ID);
34
35#ifndef __INLINE_IRQ__
36#include "irq_private.h"
37#endif
38
39static unsigned short IRQ_N_CHANNEL[N_IRQ_ID] = {
40 IRQ0_ID_N_CHANNEL,
41 IRQ1_ID_N_CHANNEL,
42 IRQ2_ID_N_CHANNEL,
43 IRQ3_ID_N_CHANNEL};
44
45static unsigned short IRQ_N_ID_OFFSET[N_IRQ_ID + 1] = {
46 IRQ0_ID_OFFSET,
47 IRQ1_ID_OFFSET,
48 IRQ2_ID_OFFSET,
49 IRQ3_ID_OFFSET,
50 IRQ_END_OFFSET};
51
52static virq_id_t IRQ_NESTING_ID[N_IRQ_ID] = {
53 N_virq_id,
54 virq_ifmt,
55 virq_isys,
56 virq_isel};
57
58void irq_clear_all(
59 const irq_ID_t ID)
60{
61 hrt_data mask = 0xFFFFFFFF;
62
63 assert(ID < N_IRQ_ID);
64 assert(IRQ_N_CHANNEL[ID] <= HRT_DATA_WIDTH);
65
66 if (IRQ_N_CHANNEL[ID] < HRT_DATA_WIDTH) {
67 mask = ~((~(hrt_data)0)>>IRQ_N_CHANNEL[ID]);
68 }
69
70 irq_reg_store(ID,
71 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, mask);
72 return;
73}
74
75
76
77
78void irq_enable_channel(
79 const irq_ID_t ID,
80 const unsigned int irq_id)
81{
82 unsigned int mask = irq_reg_load(ID,
83 _HRT_IRQ_CONTROLLER_MASK_REG_IDX);
84 unsigned int enable = irq_reg_load(ID,
85 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX);
86 unsigned int edge_in = irq_reg_load(ID,
87 _HRT_IRQ_CONTROLLER_EDGE_REG_IDX);
88 unsigned int me = 1U << irq_id;
89
90 assert(ID < N_IRQ_ID);
91 assert(irq_id < IRQ_N_CHANNEL[ID]);
92
93 mask |= me;
94 enable |= me;
95 edge_in |= me;
96
97
98
99
100 irq_reg_store(ID,
101 _HRT_IRQ_CONTROLLER_MASK_REG_IDX, mask & ~me);
102
103 irq_reg_store(ID,
104 _HRT_IRQ_CONTROLLER_EDGE_REG_IDX, edge_in);
105
106 irq_reg_store(ID,
107 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX, enable);
108
109 irq_reg_store(ID,
110 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, me);
111
112 irq_reg_store(ID,
113 _HRT_IRQ_CONTROLLER_MASK_REG_IDX, mask);
114
115 irq_wait_for_write_complete(ID);
116
117 return;
118}
119
120void irq_enable_pulse(
121 const irq_ID_t ID,
122 bool pulse)
123{
124 unsigned int edge_out = 0x0;
125
126 if (pulse) {
127 edge_out = 0xffffffff;
128 }
129
130 irq_reg_store(ID,
131 _HRT_IRQ_CONTROLLER_EDGE_NOT_PULSE_REG_IDX, edge_out);
132 return;
133}
134
135void irq_disable_channel(
136 const irq_ID_t ID,
137 const unsigned int irq_id)
138{
139 unsigned int mask = irq_reg_load(ID,
140 _HRT_IRQ_CONTROLLER_MASK_REG_IDX);
141 unsigned int enable = irq_reg_load(ID,
142 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX);
143 unsigned int me = 1U << irq_id;
144
145 assert(ID < N_IRQ_ID);
146 assert(irq_id < IRQ_N_CHANNEL[ID]);
147
148 mask &= ~me;
149 enable &= ~me;
150
151
152 irq_reg_store(ID,
153 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX, enable);
154
155 irq_reg_store(ID,
156 _HRT_IRQ_CONTROLLER_MASK_REG_IDX, mask);
157
158 irq_reg_store(ID,
159 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, me);
160
161 irq_wait_for_write_complete(ID);
162
163 return;
164}
165
166enum hrt_isp_css_irq_status irq_get_channel_id(
167 const irq_ID_t ID,
168 unsigned int *irq_id)
169{
170 unsigned int irq_status = irq_reg_load(ID,
171 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX);
172 unsigned int idx;
173 enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_success;
174
175 assert(ID < N_IRQ_ID);
176 assert(irq_id != NULL);
177
178
179 for (idx = 0; idx < IRQ_N_CHANNEL[ID]; idx++) {
180 if (irq_status & (1U << idx))
181 break;
182 }
183 if (idx == IRQ_N_CHANNEL[ID])
184 return hrt_isp_css_irq_status_error;
185
186
187 if (irq_status != (1U << idx))
188 status = hrt_isp_css_irq_status_more_irqs;
189
190 irq_reg_store(ID,
191 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, 1U << idx);
192
193 irq_wait_for_write_complete(ID);
194
195 if (irq_id != NULL)
196 *irq_id = (unsigned int)idx;
197
198 return status;
199}
200
201static const hrt_address IRQ_REQUEST_ADDR[N_IRQ_SW_CHANNEL_ID] = {
202 _REG_GP_IRQ_REQUEST0_ADDR,
203 _REG_GP_IRQ_REQUEST1_ADDR};
204
205void irq_raise(
206 const irq_ID_t ID,
207 const irq_sw_channel_id_t irq_id)
208{
209 hrt_address addr;
210
211 OP___assert(ID == IRQ0_ID);
212 OP___assert(IRQ_BASE[ID] != (hrt_address)-1);
213 OP___assert(irq_id < N_IRQ_SW_CHANNEL_ID);
214
215 (void)ID;
216
217 addr = IRQ_REQUEST_ADDR[irq_id];
218
219 gp_device_reg_store(GP_DEVICE0_ID,
220 (unsigned int)addr, 1);
221 gp_device_reg_store(GP_DEVICE0_ID,
222 (unsigned int)addr, 0);
223 return;
224}
225
226void irq_controller_get_state(
227 const irq_ID_t ID,
228 irq_controller_state_t *state)
229{
230 assert(ID < N_IRQ_ID);
231 assert(state != NULL);
232
233 state->irq_edge = irq_reg_load(ID,
234 _HRT_IRQ_CONTROLLER_EDGE_REG_IDX);
235 state->irq_mask = irq_reg_load(ID,
236 _HRT_IRQ_CONTROLLER_MASK_REG_IDX);
237 state->irq_status = irq_reg_load(ID,
238 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX);
239 state->irq_enable = irq_reg_load(ID,
240 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX);
241 state->irq_level_not_pulse = irq_reg_load(ID,
242 _HRT_IRQ_CONTROLLER_EDGE_NOT_PULSE_REG_IDX);
243 return;
244}
245
246bool any_virq_signal(void)
247{
248 unsigned int irq_status = irq_reg_load(IRQ0_ID,
249 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX);
250
251 return (irq_status != 0);
252}
253
254void cnd_virq_enable_channel(
255 const virq_id_t irq_ID,
256 const bool en)
257{
258 irq_ID_t i;
259 unsigned int channel_ID;
260 irq_ID_t ID = virq_get_irq_id(irq_ID, &channel_ID);
261
262 assert(ID < N_IRQ_ID);
263
264 for (i=IRQ1_ID;i<N_IRQ_ID;i++) {
265
266 assert(irq_ID != IRQ_NESTING_ID[i]);
267 }
268
269 if (en) {
270 irq_enable_channel(ID, channel_ID);
271 if (IRQ_NESTING_ID[ID] != N_virq_id) {
272
273 irq_enable_channel(IRQ0_ID, IRQ_NESTING_ID[ID]);
274 }
275 } else {
276 irq_disable_channel(ID, channel_ID);
277 if ((IRQ_NESTING_ID[ID] != N_virq_id) && !any_irq_channel_enabled(ID)) {
278
279 irq_disable_channel(IRQ0_ID, IRQ_NESTING_ID[ID]);
280 }
281 }
282 return;
283}
284
285
286void virq_clear_all(void)
287{
288 irq_ID_t irq_id;
289
290 for (irq_id = (irq_ID_t)0; irq_id < N_IRQ_ID; irq_id++) {
291 irq_clear_all(irq_id);
292 }
293 return;
294}
295
296enum hrt_isp_css_irq_status virq_get_channel_signals(
297 virq_info_t *irq_info)
298{
299 enum hrt_isp_css_irq_status irq_status = hrt_isp_css_irq_status_error;
300 irq_ID_t ID;
301
302 assert(irq_info != NULL);
303
304 for (ID = (irq_ID_t)0 ; ID < N_IRQ_ID; ID++) {
305 if (any_irq_channel_enabled(ID)) {
306 hrt_data irq_data = irq_reg_load(ID,
307 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX);
308
309 if (irq_data != 0) {
310
311 irq_status = hrt_isp_css_irq_status_success;
312 }
313
314 irq_info->irq_status_reg[ID] |= irq_data;
315
316 irq_reg_store(ID,
317 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, irq_data);
318
319 irq_wait_for_write_complete(ID);
320 }
321 }
322
323 return irq_status;
324}
325
326void virq_clear_info(
327 virq_info_t *irq_info)
328{
329 irq_ID_t ID;
330
331 assert(irq_info != NULL);
332
333 for (ID = (irq_ID_t)0 ; ID < N_IRQ_ID; ID++) {
334 irq_info->irq_status_reg[ID] = 0;
335 }
336 return;
337}
338
339enum hrt_isp_css_irq_status virq_get_channel_id(
340 virq_id_t *irq_id)
341{
342 unsigned int irq_status = irq_reg_load(IRQ0_ID,
343 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX);
344 unsigned int idx;
345 enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_success;
346 irq_ID_t ID;
347
348 assert(irq_id != NULL);
349
350
351 for (idx = 0; idx < IRQ_N_CHANNEL[IRQ0_ID]; idx++) {
352 if (irq_status & (1U << idx))
353 break;
354 }
355
356 if (idx == IRQ_N_CHANNEL[IRQ0_ID]) {
357 return hrt_isp_css_irq_status_error;
358 }
359
360
361 if (irq_status != (1U << idx)) {
362 status = hrt_isp_css_irq_status_more_irqs;
363 }
364
365
366 for (ID = N_IRQ_ID-1 ; ID > (irq_ID_t)0; ID--) {
367 if (IRQ_NESTING_ID[ID] == (virq_id_t)idx) {
368 break;
369 }
370 }
371
372
373 if (ID != IRQ0_ID) {
374 irq_status = irq_reg_load(ID,
375 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX);
376
377 for (idx = 0; idx < IRQ_N_CHANNEL[ID]; idx++) {
378 if (irq_status & (1U << idx))
379 break;
380 }
381
382 if (idx == IRQ_N_CHANNEL[ID]) {
383 return hrt_isp_css_irq_status_error;
384 }
385
386
387 if (irq_status != (1U << idx)) {
388 status = hrt_isp_css_irq_status_more_irqs;
389 } else {
390
391 irq_reg_store(IRQ0_ID,
392 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, 1U << IRQ_NESTING_ID[ID]);
393 }
394 }
395
396
397 irq_reg_store(ID,
398 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, 1U << idx);
399
400 irq_wait_for_write_complete(ID);
401
402 idx += IRQ_N_ID_OFFSET[ID];
403 if (irq_id != NULL)
404 *irq_id = (virq_id_t)idx;
405
406 return status;
407}
408
409static inline void irq_wait_for_write_complete(
410 const irq_ID_t ID)
411{
412 assert(ID < N_IRQ_ID);
413 assert(IRQ_BASE[ID] != (hrt_address)-1);
414 (void)ia_css_device_load_uint32(IRQ_BASE[ID] +
415 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX*sizeof(hrt_data));
416}
417
418static inline bool any_irq_channel_enabled(
419 const irq_ID_t ID)
420{
421 hrt_data en_reg;
422
423 assert(ID < N_IRQ_ID);
424
425 en_reg = irq_reg_load(ID,
426 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX);
427
428 return (en_reg != 0);
429}
430
431static inline irq_ID_t virq_get_irq_id(
432 const virq_id_t irq_ID,
433 unsigned int *channel_ID)
434{
435 irq_ID_t ID;
436
437 assert(channel_ID != NULL);
438
439 for (ID = (irq_ID_t)0 ; ID < N_IRQ_ID; ID++) {
440 if (irq_ID < IRQ_N_ID_OFFSET[ID + 1]) {
441 break;
442 }
443 }
444
445 *channel_ID = (unsigned int)irq_ID - IRQ_N_ID_OFFSET[ID];
446
447 return ID;
448}
449