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