Fix primary reason why the SH simulation hasn't been working on 64 bit hosts.
[external/binutils.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 };