]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/bfin/dv-bfin_sic.c
e6878855cef88f400fba461e22856d59a89221e7
[thirdparty/binutils-gdb.git] / sim / bfin / dv-bfin_sic.c
1 /* Blackfin System Interrupt Controller (SIC) model.
2
3 Copyright (C) 2010-2016 Free Software Foundation, Inc.
4 Contributed by Analog Devices, Inc.
5
6 This file is part of simulators.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21 #include "config.h"
22
23 #include "sim-main.h"
24 #include "devices.h"
25 #include "dv-bfin_sic.h"
26 #include "dv-bfin_cec.h"
27
28 struct bfin_sic
29 {
30 /* We assume first element is the base. */
31 bu32 base;
32
33 /* Order after here is important -- matches hardware MMR layout. */
34 bu16 BFIN_MMR_16(swrst);
35 bu16 BFIN_MMR_16(syscr);
36 bu16 BFIN_MMR_16(rvect); /* XXX: BF59x has a 32bit AUX_REVID here. */
37 union {
38 struct {
39 bu32 imask0;
40 bu32 iar0, iar1, iar2, iar3;
41 bu32 isr0, iwr0;
42 bu32 _pad0[9];
43 bu32 imask1;
44 bu32 iar4, iar5, iar6, iar7;
45 bu32 isr1, iwr1;
46 } bf52x;
47 struct {
48 bu32 imask;
49 bu32 iar0, iar1, iar2, iar3;
50 bu32 isr, iwr;
51 } bf537;
52 struct {
53 bu32 imask0, imask1, imask2;
54 bu32 isr0, isr1, isr2;
55 bu32 iwr0, iwr1, iwr2;
56 bu32 iar0, iar1, iar2, iar3;
57 bu32 iar4, iar5, iar6, iar7;
58 bu32 iar8, iar9, iar10, iar11;
59 } bf54x;
60 struct {
61 bu32 imask0, imask1;
62 bu32 iar0, iar1, iar2, iar3;
63 bu32 iar4, iar5, iar6, iar7;
64 bu32 isr0, isr1;
65 bu32 iwr0, iwr1;
66 } bf561;
67 };
68 };
69 #define mmr_base() offsetof(struct bfin_sic, swrst)
70 #define mmr_offset(mmr) (offsetof(struct bfin_sic, mmr) - mmr_base())
71 #define mmr_idx(mmr) (mmr_offset (mmr) / 4)
72
73 static const char * const bf52x_mmr_names[] =
74 {
75 "SWRST", "SYSCR", "SIC_RVECT", "SIC_IMASK0", "SIC_IAR0", "SIC_IAR1",
76 "SIC_IAR2", "SIC_IAR3", "SIC_ISR0", "SIC_IWR0",
77 [mmr_idx (bf52x.imask1)] = "SIC_IMASK1", "SIC_IAR4", "SIC_IAR5",
78 "SIC_IAR6", "SIC_IAR7", "SIC_ISR1", "SIC_IWR1",
79 };
80 static const char * const bf537_mmr_names[] =
81 {
82 "SWRST", "SYSCR", "SIC_RVECT", "SIC_IMASK", "SIC_IAR0", "SIC_IAR1",
83 "SIC_IAR2", "SIC_IAR3", "SIC_ISR", "SIC_IWR",
84 };
85 static const char * const bf54x_mmr_names[] =
86 {
87 "SWRST", "SYSCR", "SIC_RVECT", "SIC_IMASK0", "SIC_IMASK1", "SIC_IMASK2",
88 "SIC_ISR0", "SIC_ISR1", "SIC_ISR2", "SIC_IWR0", "SIC_IWR1", "SIC_IWR2",
89 "SIC_IAR0", "SIC_IAR1", "SIC_IAR2", "SIC_IAR3",
90 "SIC_IAR4", "SIC_IAR5", "SIC_IAR6", "SIC_IAR7",
91 "SIC_IAR8", "SIC_IAR9", "SIC_IAR10", "SIC_IAR11",
92 };
93 static const char * const bf561_mmr_names[] =
94 {
95 "SWRST", "SYSCR", "SIC_RVECT", "SIC_IMASK0", "SIC_IMASK1",
96 "SIC_IAR0", "SIC_IAR1", "SIC_IAR2", "SIC_IAR3",
97 "SIC_IAR4", "SIC_IAR5", "SIC_IAR6", "SIC_IAR7",
98 "SIC_ISR0", "SIC_ISR1", "SIC_IWR0", "SIC_IWR1",
99 };
100 static const char * const *mmr_names;
101 #define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>")
102
103 static void
104 bfin_sic_forward_interrupts (struct hw *me, bu32 *isr, bu32 *imask, bu32 *iar)
105 {
106 int my_port;
107 bu32 ipend;
108
109 /* Process pending and unmasked interrupts. */
110 ipend = *isr & *imask;
111
112 /* Usually none are pending unmasked, so avoid bit twiddling. */
113 if (!ipend)
114 return;
115
116 for (my_port = 0; my_port < 32; ++my_port)
117 {
118 bu32 iar_idx, iar_off, iar_val;
119 bu32 bit = (1 << my_port);
120
121 /* This bit isn't pending, so check next one. */
122 if (!(ipend & bit))
123 continue;
124
125 /* The IAR registers map the System input to the Core output.
126 Every 4 bits in the IAR are used to map to IVG{7..15}. */
127 iar_idx = my_port / 8;
128 iar_off = (my_port % 8) * 4;
129 iar_val = (iar[iar_idx] & (0xf << iar_off)) >> iar_off;
130 HW_TRACE ((me, "forwarding int %i to CEC", IVG7 + iar_val));
131 hw_port_event (me, IVG7 + iar_val, 1);
132 }
133 }
134
135 static void
136 bfin_sic_52x_forward_interrupts (struct hw *me, struct bfin_sic *sic)
137 {
138 bfin_sic_forward_interrupts (me, &sic->bf52x.isr0, &sic->bf52x.imask0, &sic->bf52x.iar0);
139 bfin_sic_forward_interrupts (me, &sic->bf52x.isr1, &sic->bf52x.imask1, &sic->bf52x.iar4);
140 }
141
142 static unsigned
143 bfin_sic_52x_io_write_buffer (struct hw *me, const void *source, int space,
144 address_word addr, unsigned nr_bytes)
145 {
146 struct bfin_sic *sic = hw_data (me);
147 bu32 mmr_off;
148 bu32 value;
149 bu16 *value16p;
150 bu32 *value32p;
151 void *valuep;
152
153 /* Invalid access mode is higher priority than missing register. */
154 if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, true))
155 return 0;
156
157 if (nr_bytes == 4)
158 value = dv_load_4 (source);
159 else
160 value = dv_load_2 (source);
161
162 mmr_off = addr - sic->base;
163 valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
164 value16p = valuep;
165 value32p = valuep;
166
167 HW_TRACE_WRITE ();
168
169 /* XXX: Discard all SIC writes for now. */
170 switch (mmr_off)
171 {
172 case mmr_offset(swrst):
173 /* XXX: This should trigger a software reset ... */
174 break;
175 case mmr_offset(syscr):
176 /* XXX: what to do ... */
177 break;
178 case mmr_offset(bf52x.imask0):
179 case mmr_offset(bf52x.imask1):
180 bfin_sic_52x_forward_interrupts (me, sic);
181 *value32p = value;
182 break;
183 case mmr_offset(bf52x.iar0) ... mmr_offset(bf52x.iar3):
184 case mmr_offset(bf52x.iar4) ... mmr_offset(bf52x.iar7):
185 case mmr_offset(bf52x.iwr0):
186 case mmr_offset(bf52x.iwr1):
187 *value32p = value;
188 break;
189 case mmr_offset(bf52x.isr0):
190 case mmr_offset(bf52x.isr1):
191 /* ISR is read-only. */
192 break;
193 default:
194 /* XXX: Should discard other writes. */
195 ;
196 }
197
198 return nr_bytes;
199 }
200
201 static unsigned
202 bfin_sic_52x_io_read_buffer (struct hw *me, void *dest, int space,
203 address_word addr, unsigned nr_bytes)
204 {
205 struct bfin_sic *sic = hw_data (me);
206 bu32 mmr_off;
207 bu16 *value16p;
208 bu32 *value32p;
209 void *valuep;
210
211 /* Invalid access mode is higher priority than missing register. */
212 if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, false))
213 return 0;
214
215 mmr_off = addr - sic->base;
216 valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
217 value16p = valuep;
218 value32p = valuep;
219
220 HW_TRACE_READ ();
221
222 switch (mmr_off)
223 {
224 case mmr_offset(swrst):
225 case mmr_offset(syscr):
226 case mmr_offset(rvect):
227 dv_store_2 (dest, *value16p);
228 break;
229 case mmr_offset(bf52x.imask0):
230 case mmr_offset(bf52x.imask1):
231 case mmr_offset(bf52x.iar0) ... mmr_offset(bf52x.iar3):
232 case mmr_offset(bf52x.iar4) ... mmr_offset(bf52x.iar7):
233 case mmr_offset(bf52x.iwr0):
234 case mmr_offset(bf52x.iwr1):
235 case mmr_offset(bf52x.isr0):
236 case mmr_offset(bf52x.isr1):
237 dv_store_4 (dest, *value32p);
238 break;
239 default:
240 if (nr_bytes == 2)
241 dv_store_2 (dest, 0);
242 else
243 dv_store_4 (dest, 0);
244 break;
245 }
246
247 return nr_bytes;
248 }
249
250 static void
251 bfin_sic_537_forward_interrupts (struct hw *me, struct bfin_sic *sic)
252 {
253 bfin_sic_forward_interrupts (me, &sic->bf537.isr, &sic->bf537.imask, &sic->bf537.iar0);
254 }
255
256 static unsigned
257 bfin_sic_537_io_write_buffer (struct hw *me, const void *source, int space,
258 address_word addr, unsigned nr_bytes)
259 {
260 struct bfin_sic *sic = hw_data (me);
261 bu32 mmr_off;
262 bu32 value;
263 bu16 *value16p;
264 bu32 *value32p;
265 void *valuep;
266
267 /* Invalid access mode is higher priority than missing register. */
268 if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, true))
269 return 0;
270
271 if (nr_bytes == 4)
272 value = dv_load_4 (source);
273 else
274 value = dv_load_2 (source);
275
276 mmr_off = addr - sic->base;
277 valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
278 value16p = valuep;
279 value32p = valuep;
280
281 HW_TRACE_WRITE ();
282
283 /* XXX: Discard all SIC writes for now. */
284 switch (mmr_off)
285 {
286 case mmr_offset(swrst):
287 /* XXX: This should trigger a software reset ... */
288 break;
289 case mmr_offset(syscr):
290 /* XXX: what to do ... */
291 break;
292 case mmr_offset(bf537.imask):
293 bfin_sic_537_forward_interrupts (me, sic);
294 *value32p = value;
295 break;
296 case mmr_offset(bf537.iar0):
297 case mmr_offset(bf537.iar1):
298 case mmr_offset(bf537.iar2):
299 case mmr_offset(bf537.iar3):
300 case mmr_offset(bf537.iwr):
301 *value32p = value;
302 break;
303 case mmr_offset(bf537.isr):
304 /* ISR is read-only. */
305 break;
306 default:
307 /* XXX: Should discard other writes. */
308 ;
309 }
310
311 return nr_bytes;
312 }
313
314 static unsigned
315 bfin_sic_537_io_read_buffer (struct hw *me, void *dest, int space,
316 address_word addr, unsigned nr_bytes)
317 {
318 struct bfin_sic *sic = hw_data (me);
319 bu32 mmr_off;
320 bu16 *value16p;
321 bu32 *value32p;
322 void *valuep;
323
324 /* Invalid access mode is higher priority than missing register. */
325 if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, false))
326 return 0;
327
328 mmr_off = addr - sic->base;
329 valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
330 value16p = valuep;
331 value32p = valuep;
332
333 HW_TRACE_READ ();
334
335 switch (mmr_off)
336 {
337 case mmr_offset(swrst):
338 case mmr_offset(syscr):
339 case mmr_offset(rvect):
340 dv_store_2 (dest, *value16p);
341 break;
342 case mmr_offset(bf537.imask):
343 case mmr_offset(bf537.iar0):
344 case mmr_offset(bf537.iar1):
345 case mmr_offset(bf537.iar2):
346 case mmr_offset(bf537.iar3):
347 case mmr_offset(bf537.isr):
348 case mmr_offset(bf537.iwr):
349 dv_store_4 (dest, *value32p);
350 break;
351 default:
352 if (nr_bytes == 2)
353 dv_store_2 (dest, 0);
354 else
355 dv_store_4 (dest, 0);
356 break;
357 }
358
359 return nr_bytes;
360 }
361
362 static void
363 bfin_sic_54x_forward_interrupts (struct hw *me, struct bfin_sic *sic)
364 {
365 bfin_sic_forward_interrupts (me, &sic->bf54x.isr0, &sic->bf54x.imask0, &sic->bf54x.iar0);
366 bfin_sic_forward_interrupts (me, &sic->bf54x.isr1, &sic->bf54x.imask1, &sic->bf54x.iar4);
367 bfin_sic_forward_interrupts (me, &sic->bf54x.isr2, &sic->bf54x.imask2, &sic->bf54x.iar8);
368 }
369
370 static unsigned
371 bfin_sic_54x_io_write_buffer (struct hw *me, const void *source, int space,
372 address_word addr, unsigned nr_bytes)
373 {
374 struct bfin_sic *sic = hw_data (me);
375 bu32 mmr_off;
376 bu32 value;
377 bu16 *value16p;
378 bu32 *value32p;
379 void *valuep;
380
381 /* Invalid access mode is higher priority than missing register. */
382 if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, true))
383 return 0;
384
385 if (nr_bytes == 4)
386 value = dv_load_4 (source);
387 else
388 value = dv_load_2 (source);
389
390 mmr_off = addr - sic->base;
391 valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
392 value16p = valuep;
393 value32p = valuep;
394
395 HW_TRACE_WRITE ();
396
397 /* XXX: Discard all SIC writes for now. */
398 switch (mmr_off)
399 {
400 case mmr_offset(swrst):
401 /* XXX: This should trigger a software reset ... */
402 break;
403 case mmr_offset(syscr):
404 /* XXX: what to do ... */
405 break;
406 case mmr_offset(bf54x.imask0) ... mmr_offset(bf54x.imask2):
407 bfin_sic_54x_forward_interrupts (me, sic);
408 *value32p = value;
409 break;
410 case mmr_offset(bf54x.iar0) ... mmr_offset(bf54x.iar11):
411 case mmr_offset(bf54x.iwr0) ... mmr_offset(bf54x.iwr2):
412 *value32p = value;
413 break;
414 case mmr_offset(bf54x.isr0) ... mmr_offset(bf54x.isr2):
415 /* ISR is read-only. */
416 break;
417 default:
418 /* XXX: Should discard other writes. */
419 ;
420 }
421
422 return nr_bytes;
423 }
424
425 static unsigned
426 bfin_sic_54x_io_read_buffer (struct hw *me, void *dest, int space,
427 address_word addr, unsigned nr_bytes)
428 {
429 struct bfin_sic *sic = hw_data (me);
430 bu32 mmr_off;
431 bu16 *value16p;
432 bu32 *value32p;
433 void *valuep;
434
435 /* Invalid access mode is higher priority than missing register. */
436 if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, false))
437 return 0;
438
439 mmr_off = addr - sic->base;
440 valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
441 value16p = valuep;
442 value32p = valuep;
443
444 HW_TRACE_READ ();
445
446 switch (mmr_off)
447 {
448 case mmr_offset(swrst):
449 case mmr_offset(syscr):
450 case mmr_offset(rvect):
451 dv_store_2 (dest, *value16p);
452 break;
453 case mmr_offset(bf54x.imask0) ... mmr_offset(bf54x.imask2):
454 case mmr_offset(bf54x.iar0) ... mmr_offset(bf54x.iar11):
455 case mmr_offset(bf54x.iwr0) ... mmr_offset(bf54x.iwr2):
456 case mmr_offset(bf54x.isr0) ... mmr_offset(bf54x.isr2):
457 dv_store_4 (dest, *value32p);
458 break;
459 default:
460 if (nr_bytes == 2)
461 dv_store_2 (dest, 0);
462 else
463 dv_store_4 (dest, 0);
464 break;
465 }
466
467 return nr_bytes;
468 }
469
470 static void
471 bfin_sic_561_forward_interrupts (struct hw *me, struct bfin_sic *sic)
472 {
473 bfin_sic_forward_interrupts (me, &sic->bf561.isr0, &sic->bf561.imask0, &sic->bf561.iar0);
474 bfin_sic_forward_interrupts (me, &sic->bf561.isr1, &sic->bf561.imask1, &sic->bf561.iar4);
475 }
476
477 static unsigned
478 bfin_sic_561_io_write_buffer (struct hw *me, const void *source, int space,
479 address_word addr, unsigned nr_bytes)
480 {
481 struct bfin_sic *sic = hw_data (me);
482 bu32 mmr_off;
483 bu32 value;
484 bu16 *value16p;
485 bu32 *value32p;
486 void *valuep;
487
488 /* Invalid access mode is higher priority than missing register. */
489 if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, true))
490 return 0;
491
492 if (nr_bytes == 4)
493 value = dv_load_4 (source);
494 else
495 value = dv_load_2 (source);
496
497 mmr_off = addr - sic->base;
498 valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
499 value16p = valuep;
500 value32p = valuep;
501
502 HW_TRACE_WRITE ();
503
504 /* XXX: Discard all SIC writes for now. */
505 switch (mmr_off)
506 {
507 case mmr_offset(swrst):
508 /* XXX: This should trigger a software reset ... */
509 break;
510 case mmr_offset(syscr):
511 /* XXX: what to do ... */
512 break;
513 case mmr_offset(bf561.imask0):
514 case mmr_offset(bf561.imask1):
515 bfin_sic_561_forward_interrupts (me, sic);
516 *value32p = value;
517 break;
518 case mmr_offset(bf561.iar0) ... mmr_offset(bf561.iar3):
519 case mmr_offset(bf561.iar4) ... mmr_offset(bf561.iar7):
520 case mmr_offset(bf561.iwr0):
521 case mmr_offset(bf561.iwr1):
522 *value32p = value;
523 break;
524 case mmr_offset(bf561.isr0):
525 case mmr_offset(bf561.isr1):
526 /* ISR is read-only. */
527 break;
528 default:
529 /* XXX: Should discard other writes. */
530 ;
531 }
532
533 return nr_bytes;
534 }
535
536 static unsigned
537 bfin_sic_561_io_read_buffer (struct hw *me, void *dest, int space,
538 address_word addr, unsigned nr_bytes)
539 {
540 struct bfin_sic *sic = hw_data (me);
541 bu32 mmr_off;
542 bu16 *value16p;
543 bu32 *value32p;
544 void *valuep;
545
546 /* Invalid access mode is higher priority than missing register. */
547 if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, false))
548 return 0;
549
550 mmr_off = addr - sic->base;
551 valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
552 value16p = valuep;
553 value32p = valuep;
554
555 HW_TRACE_READ ();
556
557 switch (mmr_off)
558 {
559 case mmr_offset(swrst):
560 case mmr_offset(syscr):
561 case mmr_offset(rvect):
562 dv_store_2 (dest, *value16p);
563 break;
564 case mmr_offset(bf561.imask0):
565 case mmr_offset(bf561.imask1):
566 case mmr_offset(bf561.iar0) ... mmr_offset(bf561.iar3):
567 case mmr_offset(bf561.iar4) ... mmr_offset(bf561.iar7):
568 case mmr_offset(bf561.iwr0):
569 case mmr_offset(bf561.iwr1):
570 case mmr_offset(bf561.isr0):
571 case mmr_offset(bf561.isr1):
572 dv_store_4 (dest, *value32p);
573 break;
574 default:
575 if (nr_bytes == 2)
576 dv_store_2 (dest, 0);
577 else
578 dv_store_4 (dest, 0);
579 break;
580 }
581
582 return nr_bytes;
583 }
584
585 /* Give each SIC its own base to make it easier to extract the pin at
586 runtime. The pin is used as its bit position in the SIC MMRs. */
587 #define ENC(sic, pin) (((sic) << 8) + (pin))
588 #define DEC_PIN(pin) ((pin) % 0x100)
589 #define DEC_SIC(pin) ((pin) >> 8)
590
591 /* It would be nice to declare just one set of input_ports, and then
592 have the device tree instantiate multiple SICs, but the MMR layout
593 on the BF54x/BF561 makes this pretty hard to pull off since their
594 regs are interwoven in the address space. */
595
596 #define BFIN_SIC_TO_CEC_PORTS \
597 { "ivg7", IVG7, 0, output_port, }, \
598 { "ivg8", IVG8, 0, output_port, }, \
599 { "ivg9", IVG9, 0, output_port, }, \
600 { "ivg10", IVG10, 0, output_port, }, \
601 { "ivg11", IVG11, 0, output_port, }, \
602 { "ivg12", IVG12, 0, output_port, }, \
603 { "ivg13", IVG13, 0, output_port, }, \
604 { "ivg14", IVG14, 0, output_port, }, \
605 { "ivg15", IVG15, 0, output_port, },
606
607 #define SIC_PORTS(n) \
608 { "int0@"#n, ENC(n, 0), 0, input_port, }, \
609 { "int1@"#n, ENC(n, 1), 0, input_port, }, \
610 { "int2@"#n, ENC(n, 2), 0, input_port, }, \
611 { "int3@"#n, ENC(n, 3), 0, input_port, }, \
612 { "int4@"#n, ENC(n, 4), 0, input_port, }, \
613 { "int5@"#n, ENC(n, 5), 0, input_port, }, \
614 { "int6@"#n, ENC(n, 6), 0, input_port, }, \
615 { "int7@"#n, ENC(n, 7), 0, input_port, }, \
616 { "int8@"#n, ENC(n, 8), 0, input_port, }, \
617 { "int9@"#n, ENC(n, 9), 0, input_port, }, \
618 { "int10@"#n, ENC(n, 10), 0, input_port, }, \
619 { "int11@"#n, ENC(n, 11), 0, input_port, }, \
620 { "int12@"#n, ENC(n, 12), 0, input_port, }, \
621 { "int13@"#n, ENC(n, 13), 0, input_port, }, \
622 { "int14@"#n, ENC(n, 14), 0, input_port, }, \
623 { "int15@"#n, ENC(n, 15), 0, input_port, }, \
624 { "int16@"#n, ENC(n, 16), 0, input_port, }, \
625 { "int17@"#n, ENC(n, 17), 0, input_port, }, \
626 { "int18@"#n, ENC(n, 18), 0, input_port, }, \
627 { "int19@"#n, ENC(n, 19), 0, input_port, }, \
628 { "int20@"#n, ENC(n, 20), 0, input_port, }, \
629 { "int21@"#n, ENC(n, 21), 0, input_port, }, \
630 { "int22@"#n, ENC(n, 22), 0, input_port, }, \
631 { "int23@"#n, ENC(n, 23), 0, input_port, }, \
632 { "int24@"#n, ENC(n, 24), 0, input_port, }, \
633 { "int25@"#n, ENC(n, 25), 0, input_port, }, \
634 { "int26@"#n, ENC(n, 26), 0, input_port, }, \
635 { "int27@"#n, ENC(n, 27), 0, input_port, }, \
636 { "int28@"#n, ENC(n, 28), 0, input_port, }, \
637 { "int29@"#n, ENC(n, 29), 0, input_port, }, \
638 { "int30@"#n, ENC(n, 30), 0, input_port, }, \
639 { "int31@"#n, ENC(n, 31), 0, input_port, },
640
641 static const struct hw_port_descriptor bfin_sic1_ports[] =
642 {
643 BFIN_SIC_TO_CEC_PORTS
644 SIC_PORTS(0)
645 { NULL, 0, 0, 0, },
646 };
647
648 static const struct hw_port_descriptor bfin_sic2_ports[] =
649 {
650 BFIN_SIC_TO_CEC_PORTS
651 SIC_PORTS(0)
652 SIC_PORTS(1)
653 { NULL, 0, 0, 0, },
654 };
655
656 static const struct hw_port_descriptor bfin_sic3_ports[] =
657 {
658 BFIN_SIC_TO_CEC_PORTS
659 SIC_PORTS(0)
660 SIC_PORTS(1)
661 SIC_PORTS(2)
662 { NULL, 0, 0, 0, },
663 };
664
665 static const struct hw_port_descriptor bfin_sic_561_ports[] =
666 {
667 { "sup_irq@0", 0, 0, output_port, },
668 { "sup_irq@1", 1, 0, output_port, },
669 BFIN_SIC_TO_CEC_PORTS
670 SIC_PORTS(0)
671 SIC_PORTS(1)
672 { NULL, 0, 0, 0, },
673 };
674
675 static void
676 bfin_sic_port_event (struct hw *me, bu32 *isr, bu32 bit, int level)
677 {
678 if (level)
679 *isr |= bit;
680 else
681 *isr &= ~bit;
682 }
683
684 static void
685 bfin_sic_52x_port_event (struct hw *me, int my_port, struct hw *source,
686 int source_port, int level)
687 {
688 struct bfin_sic *sic = hw_data (me);
689 bu32 idx = DEC_SIC (my_port);
690 bu32 pin = DEC_PIN (my_port);
691 bu32 bit = 1 << pin;
692
693 HW_TRACE ((me, "processing level %i from port %i (SIC %u pin %u)",
694 level, my_port, idx, pin));
695
696 /* SIC only exists to forward interrupts from the system to the CEC. */
697 switch (idx)
698 {
699 case 0: bfin_sic_port_event (me, &sic->bf52x.isr0, bit, level); break;
700 case 1: bfin_sic_port_event (me, &sic->bf52x.isr1, bit, level); break;
701 }
702
703 /* XXX: Handle SIC wakeup source ?
704 if (sic->bf52x.iwr0 & bit)
705 What to do ?;
706 if (sic->bf52x.iwr1 & bit)
707 What to do ?;
708 */
709
710 bfin_sic_52x_forward_interrupts (me, sic);
711 }
712
713 static void
714 bfin_sic_537_port_event (struct hw *me, int my_port, struct hw *source,
715 int source_port, int level)
716 {
717 struct bfin_sic *sic = hw_data (me);
718 bu32 idx = DEC_SIC (my_port);
719 bu32 pin = DEC_PIN (my_port);
720 bu32 bit = 1 << pin;
721
722 HW_TRACE ((me, "processing level %i from port %i (SIC %u pin %u)",
723 level, my_port, idx, pin));
724
725 /* SIC only exists to forward interrupts from the system to the CEC. */
726 bfin_sic_port_event (me, &sic->bf537.isr, bit, level);
727
728 /* XXX: Handle SIC wakeup source ?
729 if (sic->bf537.iwr & bit)
730 What to do ?;
731 */
732
733 bfin_sic_537_forward_interrupts (me, sic);
734 }
735
736 static void
737 bfin_sic_54x_port_event (struct hw *me, int my_port, struct hw *source,
738 int source_port, int level)
739 {
740 struct bfin_sic *sic = hw_data (me);
741 bu32 idx = DEC_SIC (my_port);
742 bu32 pin = DEC_PIN (my_port);
743 bu32 bit = 1 << pin;
744
745 HW_TRACE ((me, "processing level %i from port %i (SIC %u pin %u)",
746 level, my_port, idx, pin));
747
748 /* SIC only exists to forward interrupts from the system to the CEC. */
749 switch (idx)
750 {
751 case 0: bfin_sic_port_event (me, &sic->bf54x.isr0, bit, level); break;
752 case 1: bfin_sic_port_event (me, &sic->bf54x.isr0, bit, level); break;
753 case 2: bfin_sic_port_event (me, &sic->bf54x.isr0, bit, level); break;
754 }
755
756 /* XXX: Handle SIC wakeup source ?
757 if (sic->bf54x.iwr0 & bit)
758 What to do ?;
759 if (sic->bf54x.iwr1 & bit)
760 What to do ?;
761 if (sic->bf54x.iwr2 & bit)
762 What to do ?;
763 */
764
765 bfin_sic_54x_forward_interrupts (me, sic);
766 }
767
768 static void
769 bfin_sic_561_port_event (struct hw *me, int my_port, struct hw *source,
770 int source_port, int level)
771 {
772 struct bfin_sic *sic = hw_data (me);
773 bu32 idx = DEC_SIC (my_port);
774 bu32 pin = DEC_PIN (my_port);
775 bu32 bit = 1 << pin;
776
777 HW_TRACE ((me, "processing level %i from port %i (SIC %u pin %u)",
778 level, my_port, idx, pin));
779
780 /* SIC only exists to forward interrupts from the system to the CEC. */
781 switch (idx)
782 {
783 case 0: bfin_sic_port_event (me, &sic->bf561.isr0, bit, level); break;
784 case 1: bfin_sic_port_event (me, &sic->bf561.isr1, bit, level); break;
785 }
786
787 /* XXX: Handle SIC wakeup source ?
788 if (sic->bf561.iwr0 & bit)
789 What to do ?;
790 if (sic->bf561.iwr1 & bit)
791 What to do ?;
792 */
793
794 bfin_sic_561_forward_interrupts (me, sic);
795 }
796
797 static void
798 attach_bfin_sic_regs (struct hw *me, struct bfin_sic *sic)
799 {
800 address_word attach_address;
801 int attach_space;
802 unsigned attach_size;
803 reg_property_spec reg;
804
805 if (hw_find_property (me, "reg") == NULL)
806 hw_abort (me, "Missing \"reg\" property");
807
808 if (!hw_find_reg_array_property (me, "reg", 0, &reg))
809 hw_abort (me, "\"reg\" property must contain three addr/size entries");
810
811 hw_unit_address_to_attach_address (hw_parent (me),
812 &reg.address,
813 &attach_space, &attach_address, me);
814 hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
815
816 if (attach_size != BFIN_MMR_SIC_SIZE)
817 hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_SIC_SIZE);
818
819 hw_attach_address (hw_parent (me),
820 0, attach_space, attach_address, attach_size, me);
821
822 sic->base = attach_address;
823 }
824
825 static void
826 bfin_sic_finish (struct hw *me)
827 {
828 struct bfin_sic *sic;
829
830 sic = HW_ZALLOC (me, struct bfin_sic);
831
832 set_hw_data (me, sic);
833 attach_bfin_sic_regs (me, sic);
834
835 switch (hw_find_integer_property (me, "type"))
836 {
837 case 500 ... 509:
838 set_hw_io_read_buffer (me, bfin_sic_52x_io_read_buffer);
839 set_hw_io_write_buffer (me, bfin_sic_52x_io_write_buffer);
840 set_hw_ports (me, bfin_sic2_ports);
841 set_hw_port_event (me, bfin_sic_52x_port_event);
842 mmr_names = bf52x_mmr_names;
843
844 /* Initialize the SIC. */
845 sic->bf52x.imask0 = sic->bf52x.imask1 = 0;
846 sic->bf52x.isr0 = sic->bf52x.isr1 = 0;
847 sic->bf52x.iwr0 = sic->bf52x.iwr1 = 0xFFFFFFFF;
848 sic->bf52x.iar0 = 0x00000000;
849 sic->bf52x.iar1 = 0x22111000;
850 sic->bf52x.iar2 = 0x33332222;
851 sic->bf52x.iar3 = 0x44444433;
852 sic->bf52x.iar4 = 0x55555555;
853 sic->bf52x.iar5 = 0x06666655;
854 sic->bf52x.iar6 = 0x33333003;
855 sic->bf52x.iar7 = 0x00000000; /* XXX: Find and fix */
856 break;
857 case 510 ... 519:
858 set_hw_io_read_buffer (me, bfin_sic_52x_io_read_buffer);
859 set_hw_io_write_buffer (me, bfin_sic_52x_io_write_buffer);
860 set_hw_ports (me, bfin_sic2_ports);
861 set_hw_port_event (me, bfin_sic_52x_port_event);
862 mmr_names = bf52x_mmr_names;
863
864 /* Initialize the SIC. */
865 sic->bf52x.imask0 = sic->bf52x.imask1 = 0;
866 sic->bf52x.isr0 = sic->bf52x.isr1 = 0;
867 sic->bf52x.iwr0 = sic->bf52x.iwr1 = 0xFFFFFFFF;
868 sic->bf52x.iar0 = 0x00000000;
869 sic->bf52x.iar1 = 0x11000000;
870 sic->bf52x.iar2 = 0x33332222;
871 sic->bf52x.iar3 = 0x44444433;
872 sic->bf52x.iar4 = 0x55555555;
873 sic->bf52x.iar5 = 0x06666655;
874 sic->bf52x.iar6 = 0x33333000;
875 sic->bf52x.iar7 = 0x00000000; /* XXX: Find and fix */
876 break;
877 case 522 ... 527:
878 set_hw_io_read_buffer (me, bfin_sic_52x_io_read_buffer);
879 set_hw_io_write_buffer (me, bfin_sic_52x_io_write_buffer);
880 set_hw_ports (me, bfin_sic2_ports);
881 set_hw_port_event (me, bfin_sic_52x_port_event);
882 mmr_names = bf52x_mmr_names;
883
884 /* Initialize the SIC. */
885 sic->bf52x.imask0 = sic->bf52x.imask1 = 0;
886 sic->bf52x.isr0 = sic->bf52x.isr1 = 0;
887 sic->bf52x.iwr0 = sic->bf52x.iwr1 = 0xFFFFFFFF;
888 sic->bf52x.iar0 = 0x00000000;
889 sic->bf52x.iar1 = 0x11000000;
890 sic->bf52x.iar2 = 0x33332222;
891 sic->bf52x.iar3 = 0x44444433;
892 sic->bf52x.iar4 = 0x55555555;
893 sic->bf52x.iar5 = 0x06666655;
894 sic->bf52x.iar6 = 0x33333000;
895 sic->bf52x.iar7 = 0x00000000; /* XXX: Find and fix */
896 break;
897 case 531 ... 533:
898 set_hw_io_read_buffer (me, bfin_sic_537_io_read_buffer);
899 set_hw_io_write_buffer (me, bfin_sic_537_io_write_buffer);
900 set_hw_ports (me, bfin_sic1_ports);
901 set_hw_port_event (me, bfin_sic_537_port_event);
902 mmr_names = bf537_mmr_names;
903
904 /* Initialize the SIC. */
905 sic->bf537.imask = 0;
906 sic->bf537.isr = 0;
907 sic->bf537.iwr = 0xFFFFFFFF;
908 sic->bf537.iar0 = 0x10000000;
909 sic->bf537.iar1 = 0x33322221;
910 sic->bf537.iar2 = 0x66655444;
911 sic->bf537.iar3 = 0; /* XXX: fix this */
912 break;
913 case 534:
914 case 536:
915 case 537:
916 set_hw_io_read_buffer (me, bfin_sic_537_io_read_buffer);
917 set_hw_io_write_buffer (me, bfin_sic_537_io_write_buffer);
918 set_hw_ports (me, bfin_sic1_ports);
919 set_hw_port_event (me, bfin_sic_537_port_event);
920 mmr_names = bf537_mmr_names;
921
922 /* Initialize the SIC. */
923 sic->bf537.imask = 0;
924 sic->bf537.isr = 0;
925 sic->bf537.iwr = 0xFFFFFFFF;
926 sic->bf537.iar0 = 0x22211000;
927 sic->bf537.iar1 = 0x43333332;
928 sic->bf537.iar2 = 0x55555444;
929 sic->bf537.iar3 = 0x66655555;
930 break;
931 case 538 ... 539:
932 set_hw_io_read_buffer (me, bfin_sic_52x_io_read_buffer);
933 set_hw_io_write_buffer (me, bfin_sic_52x_io_write_buffer);
934 set_hw_ports (me, bfin_sic2_ports);
935 set_hw_port_event (me, bfin_sic_52x_port_event);
936 mmr_names = bf52x_mmr_names;
937
938 /* Initialize the SIC. */
939 sic->bf52x.imask0 = sic->bf52x.imask1 = 0;
940 sic->bf52x.isr0 = sic->bf52x.isr1 = 0;
941 sic->bf52x.iwr0 = sic->bf52x.iwr1 = 0xFFFFFFFF;
942 sic->bf52x.iar0 = 0x10000000;
943 sic->bf52x.iar1 = 0x33322221;
944 sic->bf52x.iar2 = 0x66655444;
945 sic->bf52x.iar3 = 0x00000000;
946 sic->bf52x.iar4 = 0x32222220;
947 sic->bf52x.iar5 = 0x44433333;
948 sic->bf52x.iar6 = 0x00444664;
949 sic->bf52x.iar7 = 0x00000000; /* XXX: Find and fix */
950 break;
951 case 540 ... 549:
952 set_hw_io_read_buffer (me, bfin_sic_54x_io_read_buffer);
953 set_hw_io_write_buffer (me, bfin_sic_54x_io_write_buffer);
954 set_hw_ports (me, bfin_sic3_ports);
955 set_hw_port_event (me, bfin_sic_54x_port_event);
956 mmr_names = bf54x_mmr_names;
957
958 /* Initialize the SIC. */
959 sic->bf54x.imask0 = sic->bf54x.imask1 = sic->bf54x.imask2 = 0;
960 sic->bf54x.isr0 = sic->bf54x.isr1 = sic->bf54x.isr2 = 0;
961 sic->bf54x.iwr0 = sic->bf54x.iwr1 = sic->bf54x.iwr2 = 0xFFFFFFFF;
962 sic->bf54x.iar0 = 0x10000000;
963 sic->bf54x.iar1 = 0x33322221;
964 sic->bf54x.iar2 = 0x66655444;
965 sic->bf54x.iar3 = 0x00000000;
966 sic->bf54x.iar4 = 0x32222220;
967 sic->bf54x.iar5 = 0x44433333;
968 sic->bf54x.iar6 = 0x00444664;
969 sic->bf54x.iar7 = 0x00000000;
970 sic->bf54x.iar8 = 0x44111111;
971 sic->bf54x.iar9 = 0x44444444;
972 sic->bf54x.iar10 = 0x44444444;
973 sic->bf54x.iar11 = 0x55444444;
974 break;
975 case 561:
976 set_hw_io_read_buffer (me, bfin_sic_561_io_read_buffer);
977 set_hw_io_write_buffer (me, bfin_sic_561_io_write_buffer);
978 set_hw_ports (me, bfin_sic_561_ports);
979 set_hw_port_event (me, bfin_sic_561_port_event);
980 mmr_names = bf561_mmr_names;
981
982 /* Initialize the SIC. */
983 sic->bf561.imask0 = sic->bf561.imask1 = 0;
984 sic->bf561.isr0 = sic->bf561.isr1 = 0;
985 sic->bf561.iwr0 = sic->bf561.iwr1 = 0xFFFFFFFF;
986 sic->bf561.iar0 = 0x00000000;
987 sic->bf561.iar1 = 0x11111000;
988 sic->bf561.iar2 = 0x21111111;
989 sic->bf561.iar3 = 0x22222222;
990 sic->bf561.iar4 = 0x33333222;
991 sic->bf561.iar5 = 0x43333333;
992 sic->bf561.iar6 = 0x21144444;
993 sic->bf561.iar7 = 0x00006552;
994 break;
995 case 590 ... 599:
996 set_hw_io_read_buffer (me, bfin_sic_537_io_read_buffer);
997 set_hw_io_write_buffer (me, bfin_sic_537_io_write_buffer);
998 set_hw_ports (me, bfin_sic1_ports);
999 set_hw_port_event (me, bfin_sic_537_port_event);
1000 mmr_names = bf537_mmr_names;
1001
1002 /* Initialize the SIC. */
1003 sic->bf537.imask = 0;
1004 sic->bf537.isr = 0;
1005 sic->bf537.iwr = 0xFFFFFFFF;
1006 sic->bf537.iar0 = 0x00000000;
1007 sic->bf537.iar1 = 0x33322221;
1008 sic->bf537.iar2 = 0x55444443;
1009 sic->bf537.iar3 = 0x66600005;
1010 break;
1011 default:
1012 hw_abort (me, "no support for SIC on this Blackfin model yet");
1013 }
1014 }
1015
1016 const struct hw_descriptor dv_bfin_sic_descriptor[] =
1017 {
1018 {"bfin_sic", bfin_sic_finish,},
1019 {NULL, NULL},
1020 };