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