Home | History | Annotate | Line # | Download | only in bfin
dv-bfin_sic.c revision 1.1.1.5
      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 };
   1021