OSDN Git Service

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