Fix typo.
[external/binutils.git] / sim / mn10300 / dv-mn103int.c
1 /*  This file is part of the program GDB, the GNU debugger.
2     
3     Copyright (C) 1998 Free Software Foundation, Inc.
4     Contributed by Cygnus Solutions.
5     
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10     
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15     
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19     
20     */
21
22
23 #include "sim-main.h"
24 #include "hw-main.h"
25
26 /* DEVICE
27
28    
29    mn103int - mn103002 interrupt controller
30
31    
32    DESCRIPTION
33
34    
35    Implements the mn103002 interrupt controller described in the
36    mn103002 user guide.
37
38
39    PROPERTIES
40    
41
42    reg = <icr-adr> <icr-siz> <iagr-adr> <iadr-siz> <extmd-adr> <extmd-siz>
43
44    Specify the address of the ICR (total of 25 registers), IAGR and
45    EXTMD registers (within the parent bus).
46
47    The reg property value `0x34000100 0x7C 0x34000200 0x8 0x3400280
48    0x8' locates the interrupt controller at the addresses specified in
49    the mn103002 interrupt controller user guide.
50
51
52    PORTS
53
54
55    nmi (output)
56
57    Non-maskable interrupt output port.  An event on this output ports
58    indicates a NMI request from the interrupt controller.  The value
59    attached to the event should be ignored.
60
61
62    level (output)
63
64    Maskable interrupt level output port.  An event on this output port
65    indicates a maskable interrupt request at the specified level.  The
66    event value defines the level being requested.
67
68    The interrupt controller will generate an event on this port
69    whenever there is a change to the internal state of the interrupt
70    controller.
71
72
73    ack (input)
74
75    Signal from processor indicating that a maskable interrupt has been
76    accepted and the interrupt controller should latch the IAGR with
77    value of the current highest priority interrupting group.
78
79    The event value is the interrupt level being accepted by the
80    processor.  It should be consistent with the most recent LEVEL sent
81    to the processor from the interrupt controller.
82
83
84    int[0..100] (input)
85
86    Level or edge triggered interrupt input port.  Each of the 30
87    groups (0..30) can have up to 4 (0..3) interrupt inputs.  The
88    interpretation of a port event/value is determined by the
89    configuration of the corresponding interrupt group.
90
91    For convenience, numerous aliases to these interrupt inputs are
92    provided.
93
94
95    BUGS
96
97
98    For edge triggered interrupts, the interrupt controller does not
99    differentiate between POSITIVE (rising) and NEGATIVE (falling)
100    edges.  Instead any input port event is considered to be an
101    interrupt trigger.
102
103    For level sensitive interrupts, the interrupt controller ignores
104    active HIGH/LOW settings and instead always interprets a nonzero
105    port value as an interrupt assertion and a zero port value as a
106    negation.
107
108    */
109
110
111 /* The interrupt groups - numbered according to mn103002 convention */
112
113 enum mn103int_trigger {
114   ACTIVE_LOW,
115   ACTIVE_HIGH,
116   POSITIVE_EDGE,
117   NEGATIVE_EDGE,
118 };
119
120 enum mn103int_type {
121   NMI_GROUP,
122   LEVEL_GROUP,
123 };
124
125 struct mn103int_group {
126   int gid;
127   int level;
128   unsigned enable;
129   unsigned request;
130   unsigned input;
131   enum mn103int_trigger trigger;
132   enum mn103int_type type;
133 };
134
135 enum {
136   FIRST_NMI_GROUP = 0,
137   LAST_NMI_GROUP = 1,
138   FIRST_LEVEL_GROUP = 2,
139   LAST_LEVEL_GROUP = 30,
140   NR_GROUPS,
141 };
142
143 enum {
144   LOWEST_LEVEL = 7,
145 };
146
147 /* The interrupt controller register address blocks */
148
149 struct mn103int_block {
150   unsigned_word base;
151   unsigned_word bound;
152 };
153
154 enum { ICR_BLOCK, IAGR_BLOCK, EXTMD_BLOCK, NR_BLOCKS };
155
156
157 struct mn103int {
158   struct mn103int_block block[NR_BLOCKS];
159   struct mn103int_group group[NR_GROUPS];
160   unsigned interrupt_accepted_group;
161 };
162
163
164
165 /* output port ID's */ 
166
167 enum {
168   NMI_PORT,
169   LEVEL_PORT,
170 };
171
172
173 /* input port ID's */
174
175 enum {
176   G0_PORT = 0,
177   G1_PORT = 4,
178   G2_PORT = 8,
179   G3_PORT = 12,
180   G4_PORT = 16,
181   G5_PORT = 20,
182   G6_PORT = 24,
183   G7_PORT = 28,
184   G8_PORT = 32,
185   G9_PORT = 36,
186   G10_PORT = 40,
187   G11_PORT = 44,
188   G12_PORT = 48,
189   G13_PORT = 52,
190   G14_PORT = 56,
191   G15_PORT = 60,
192   G16_PORT = 64,
193   G17_PORT = 68,
194   G18_PORT = 72,
195   G19_PORT = 76,
196   G20_PORT = 80,
197   G21_PORT = 84,
198   G22_PORT = 88,
199   G23_PORT = 92,
200   G24_PORT = 96,
201   G25_PORT = 100,
202   G26_PORT = 104,
203   G27_PORT = 108,
204   G28_PORT = 112,
205   G29_PORT = 116,
206   G30_PORT = 120,
207   NR_G_PORTS = 124,
208   ACK_PORT,
209 };
210
211 static const struct hw_port_descriptor mn103int_ports[] = {
212
213   /* interrupt outputs */
214
215   { "nmi", NMI_PORT, 0, output_port, },
216   { "level", LEVEL_PORT, 0, output_port, },
217
218   /* interrupt ack (latch) input from cpu */
219
220   { "ack", ACK_PORT, 0, input_port, },
221
222   /* interrupt inputs (as names) */
223
224   { "nmirq", G0_PORT + 0, 0, input_port, },
225   { "watchdog", G0_PORT + 1, 0, input_port, },
226   { "syserr", G0_PORT + 2, 0, input_port, },
227
228   { "timer-0-underflow", G2_PORT, 0, input_port, },
229   { "timer-1-underflow", G3_PORT, 0, input_port, },
230   { "timer-2-underflow", G4_PORT, 0, input_port, },
231   { "timer-3-underflow", G5_PORT, 0, input_port, },
232   { "timer-4-underflow", G6_PORT, 0, input_port, },
233   { "timer-5-underflow", G7_PORT, 0, input_port, },
234   { "timer-6-underflow", G8_PORT, 0, input_port, },
235
236   { "timer-6-compare-a", G9_PORT, 0, input_port, },
237   { "timer-6-compare-b", G10_PORT, 0, input_port, },
238
239   { "dma-0-end", G12_PORT, 0, input_port, },
240   { "dma-1-end", G13_PORT, 0, input_port, },
241   { "dma-2-end", G14_PORT, 0, input_port, },
242   { "dma-3-end", G15_PORT, 0, input_port, },
243
244   { "serial-0-receive",  G16_PORT, 0, input_port, },
245   { "serial-0-transmit", G17_PORT, 0, input_port, },
246
247   { "serial-1-receive",  G18_PORT, 0, input_port, },
248   { "serial-1-transmit", G19_PORT, 0, input_port, },
249
250   { "serial-2-receive",  G20_PORT, 0, input_port, },
251   { "serial-2-transmit", G21_PORT, 0, input_port, },
252
253   { "irq-0", G23_PORT, 0, input_port, },
254   { "irq-1", G24_PORT, 0, input_port, },
255   { "irq-2", G25_PORT, 0, input_port, },
256   { "irq-3", G26_PORT, 0, input_port, },
257   { "irq-4", G27_PORT, 0, input_port, },
258   { "irq-5", G28_PORT, 0, input_port, },
259   { "irq-6", G29_PORT, 0, input_port, },
260   { "irq-7", G30_PORT, 0, input_port, },
261
262   /* interrupt inputs (as generic numbers) */
263
264   { "int", 0, NR_G_PORTS, input_port, },
265
266   { NULL, },
267 };
268
269
270 /* Macros for extracting/restoring the various register bits */
271
272 #define EXTRACT_ID(X) (LSEXTRACTED8 ((X), 3, 0))
273 #define INSERT_ID(X) (LSINSERTED8 ((X), 3, 0))
274
275 #define EXTRACT_IR(X) (LSEXTRACTED8 ((X), 7, 4))
276 #define INSERT_IR(X) (LSINSERTED8 ((X), 7, 4))
277
278 #define EXTRACT_IE(X) (LSEXTRACTED8 ((X), 3, 0))
279 #define INSERT_IE(X) (LSINSERTED8 ((X), 3, 0))
280
281 #define EXTRACT_LV(X) (LSEXTRACTED8 ((X), 6, 4))
282 #define INSERT_LV(X) (LSINSERTED8 ((X), 6, 4))
283
284
285
286 /* Finish off the partially created hw device.  Attach our local
287    callbacks.  Wire up our port names etc */
288
289 static hw_io_read_buffer_method mn103int_io_read_buffer;
290 static hw_io_write_buffer_method mn103int_io_write_buffer;
291 static hw_port_event_method mn103int_port_event;
292
293 static void
294 attach_mn103int_regs (struct hw *me,
295                       struct mn103int *controller)
296 {
297   int i;
298   if (hw_find_property (me, "reg") == NULL)
299     hw_abort (me, "Missing \"reg\" property");
300   for (i = 0; i < NR_BLOCKS; i++)
301     {
302       unsigned_word attach_address;
303       int attach_space;
304       unsigned attach_size;
305       reg_property_spec reg;
306       if (!hw_find_reg_array_property (me, "reg", i, &reg))
307         hw_abort (me, "\"reg\" property must contain three addr/size entries");
308       hw_unit_address_to_attach_address (hw_parent (me),
309                                          &reg.address,
310                                          &attach_space,
311                                          &attach_address,
312                                          me);
313       controller->block[i].base = attach_address;
314       hw_unit_size_to_attach_size (hw_parent (me),
315                                    &reg.size,
316                                    &attach_size, me);
317       controller->block[i].bound = attach_address + (attach_size - 1);
318       hw_attach_address (hw_parent (me),
319                          0,
320                          attach_space, attach_address, attach_size,
321                          me);
322     }
323 }
324
325 static void
326 mn103int_finish (struct hw *me)
327 {
328   int gid;
329   struct mn103int *controller;
330
331   controller = HW_ZALLOC (me, struct mn103int);
332   set_hw_data (me, controller);
333   set_hw_io_read_buffer (me, mn103int_io_read_buffer);
334   set_hw_io_write_buffer (me, mn103int_io_write_buffer);
335   set_hw_ports (me, mn103int_ports);
336   set_hw_port_event (me, mn103int_port_event);
337
338   /* Attach ourself to our parent bus */
339   attach_mn103int_regs (me, controller);
340
341   /* Initialize all the groups according to their default configuration */
342   for (gid = 0; gid < NR_GROUPS; gid++)
343     {
344       struct mn103int_group *group = &controller->group[gid];
345       group->enable = 0xf;
346       group->trigger = NEGATIVE_EDGE;
347       group->gid = gid;
348       if (FIRST_NMI_GROUP <= gid && gid <= LAST_NMI_GROUP)
349         {
350           group->type = NMI_GROUP;
351         }
352       else if (FIRST_LEVEL_GROUP <= gid && gid <= LAST_LEVEL_GROUP)
353         {
354           group->type = LEVEL_GROUP;
355         }
356       else
357         hw_abort (me, "internal error - unknown group id");
358     }
359 }
360
361
362
363 /* Perform the nasty work of figuring out which of the interrupt
364    groups should have its interrupt delivered. */
365
366 static int
367 find_highest_interrupt_group (struct hw *me,
368                               struct mn103int *controller)
369 {
370   int gid;
371   int selected;
372
373   /* FIRST_NMI_GROUP (group zero) is used as a special default value
374      when searching for an interrupt group.*/
375   selected = FIRST_NMI_GROUP; 
376   controller->group[FIRST_NMI_GROUP].level = 7;
377   
378   for (gid = FIRST_LEVEL_GROUP; gid <= LAST_LEVEL_GROUP; gid++)
379     {
380       struct mn103int_group *group = &controller->group[gid];
381       if ((group->request & group->enable) != 0)
382         {
383           /* Remember, lower level, higher priority.  */
384           if (group->level < controller->group[selected].level)
385             {
386               selected = gid;
387             }
388         }
389     }
390   return selected;
391 }
392
393
394 /* Notify the processor of an interrupt level update */
395
396 static void
397 push_interrupt_level (struct hw *me,
398                       struct mn103int *controller)
399 {
400   int selected = find_highest_interrupt_group (me, controller);
401   int level = controller->group[selected].level;
402   HW_TRACE ((me, "port-out - selected=%d level=%d", selected, level));
403   hw_port_event (me, LEVEL_PORT, level);
404 }
405
406
407 /* An event arrives on an interrupt port */
408
409 static void
410 mn103int_port_event (struct hw *me,
411                      int my_port,
412                      struct hw *source,
413                      int source_port,
414                      int level)
415 {
416   struct mn103int *controller = hw_data (me);
417
418   switch (my_port)
419     {
420
421     case ACK_PORT:
422       {
423         int selected = find_highest_interrupt_group (me, controller);
424         if (controller->group[selected].level != level)
425           hw_abort (me, "botched level synchronisation");
426         controller->interrupt_accepted_group = selected;        
427         HW_TRACE ((me, "port-event port=ack level=%d - selected=%d",
428                    level, selected));
429         break;
430       }
431
432     default:
433       {
434         int gid;
435         int iid;
436         struct mn103int_group *group;
437         unsigned interrupt;
438         if (my_port > NR_G_PORTS)
439           hw_abort (me, "Event on unknown port %d", my_port);
440
441         /* map the port onto an interrupt group */
442         gid = (my_port % NR_G_PORTS) / 4;
443         group = &controller->group[gid];
444         iid = (my_port % 4);
445         interrupt = 1 << iid;
446
447         /* update our cached input */
448         if (level)
449           group->input |= interrupt;
450         else
451           group->input &= ~interrupt;
452
453         /* update the request bits */
454         switch (group->trigger)
455           {
456           case ACTIVE_LOW:
457           case ACTIVE_HIGH:
458             if (level)
459               group->request |= interrupt;
460             break;
461           case NEGATIVE_EDGE:
462           case POSITIVE_EDGE:
463             group->request |= interrupt;
464           }
465
466         /* force a corresponding output */
467         switch (group->type)
468           {
469
470           case NMI_GROUP:
471             {
472               /* for NMI's the event is the trigger */
473               HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - NMI",
474                          my_port, gid, iid));
475               if ((group->request & group->enable) != 0)
476                 {
477                   HW_TRACE ((me, "port-out NMI"));
478                   hw_port_event (me, NMI_PORT, 1);
479                 }
480               break;
481             }
482               
483           case LEVEL_GROUP:
484             {
485               /* if an interrupt is now pending */
486               HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - INT",
487                          my_port, gid, iid));
488               push_interrupt_level (me, controller);
489               break;
490             }
491           }
492         break;
493       }
494
495     }
496 }
497
498 /* Read/write to to an ICR (group control register) */
499
500 static struct mn103int_group *
501 decode_group (struct hw *me,
502               struct mn103int *controller,
503               unsigned_word base,
504               unsigned_word *offset)
505 {
506   int gid = (base / 4) % NR_GROUPS;
507   *offset = (base % 4);
508   return &controller->group[gid];
509 }
510
511 static unsigned8
512 read_icr (struct hw *me,
513           struct mn103int *controller,
514           unsigned_word base)
515 {
516   unsigned_word offset;
517   struct mn103int_group *group = decode_group (me, controller, base, &offset);
518   unsigned8 val = 0;
519   switch (group->type)
520     {
521
522     case NMI_GROUP:
523       switch (offset)
524         {
525         case 0:
526           val = INSERT_ID (group->request);
527           HW_TRACE ((me, "read-icr group=%d:0 nmi 0x%02x",
528                      group->gid, val));
529           break;
530         default:
531           break;
532         }
533       break;
534
535     case LEVEL_GROUP:
536       switch (offset)
537         {
538         case 0:
539           val = (INSERT_IR (group->request)
540                  | INSERT_ID (group->request & group->enable));
541           HW_TRACE ((me, "read-icr group=%d:0 level 0x%02x",
542                      group->gid, val));
543           break;
544         case 1:
545           val = (INSERT_LV (group->level)
546                  | INSERT_IE (group->enable));
547           HW_TRACE ((me, "read-icr level-%d:1 level 0x%02x",
548                      group->gid, val));
549           break;
550         }
551       break;
552
553     default:
554       break;
555
556     }
557
558   return val;
559 }
560
561 static void
562 write_icr (struct hw *me,
563            struct mn103int *controller,
564            unsigned_word base,
565            unsigned8 val)
566 {
567   unsigned_word offset;
568   struct mn103int_group *group = decode_group (me, controller, base, &offset);
569   switch (group->type)
570     {
571
572     case NMI_GROUP:
573       switch (offset)
574         {
575         case 0:
576           HW_TRACE ((me, "write-icr group=%d:0 nmi 0x%02x",
577                      group->gid, val));
578           group->request &= ~EXTRACT_ID (val);
579           break;
580         default:
581           break;
582         }
583       break;
584
585     case LEVEL_GROUP:
586       switch (offset)
587         {
588         case 0: /* request/detect */
589           /* Clear any ID bits and then set them according to IR */
590           HW_TRACE ((me, "write-icr group=%d:0 level 0x%02x %x:%x:%x",
591                      group->gid, val,
592                      group->request, EXTRACT_IR (val), EXTRACT_ID (val)));
593           group->request =
594             ((EXTRACT_IR (val) & EXTRACT_ID (val))
595              | (EXTRACT_IR (val) & group->request)
596              | (~EXTRACT_IR (val) & ~EXTRACT_ID (val) & group->request));
597           break;
598         case 1: /* level/enable */
599           HW_TRACE ((me, "write-icr group=%d:1 level 0x%02x",
600                      group->gid, val));
601           group->level = EXTRACT_LV (val);
602           group->enable = EXTRACT_IE (val);
603           break;
604         default:
605           /* ignore */
606           break;
607         }
608       push_interrupt_level (me, controller);
609       break;
610
611     default:
612       break;
613
614     }
615 }
616
617
618 /* Read the IAGR (Interrupt accepted group register) */
619
620 static unsigned8
621 read_iagr (struct hw *me,
622            struct mn103int *controller,
623            unsigned_word offset)
624 {
625   unsigned8 val;
626   switch (offset)
627     {
628     case 0:
629       {
630         if (!(controller->group[controller->interrupt_accepted_group].request
631               & controller->group[controller->interrupt_accepted_group].enable))
632           {
633             /* oops, lost the request */
634             val = 0;
635             HW_TRACE ((me, "read-iagr:0 lost-0"));
636           }
637         else
638           {
639             val = (controller->interrupt_accepted_group << 2);
640             HW_TRACE ((me, "read-iagr:0 %d", (int) val));
641           }
642         break;
643       }
644     case 1:
645       val = 0;
646       HW_TRACE ((me, "read-iagr:1 %d", (int) val));
647       break;
648     default:
649       val = 0;
650       HW_TRACE ((me, "read-iagr 0x%08lx bad offset", (long) offset));
651       break;
652     }
653   return val;
654 }
655
656
657 /* Reads/writes to the EXTMD (external interrupt trigger configuration
658    register) */
659
660 static struct mn103int_group *
661 external_group (struct mn103int *controller,
662                 unsigned_word offset)
663 {
664   switch (offset)
665     {
666     case 0:
667       return &controller->group[16];
668     case 1:
669       return &controller->group[20];
670     default:
671       return NULL;
672     }
673 }
674
675 static unsigned8
676 read_extmd (struct hw *me,
677             struct mn103int *controller,
678             unsigned_word offset)
679 {
680   int gid;
681   unsigned8 val = 0;
682   struct mn103int_group *group = external_group (controller, offset);
683   if (group != NULL)
684     {
685       for (gid = 0; gid < 4; gid++)
686         {
687           val |= (group[gid].trigger << (gid * 2));
688         }
689     }
690   HW_TRACE ((me, "read-extmd 0x%02lx", (long) val));
691   return val;
692 }
693
694 static void
695 write_extmd (struct hw *me,
696              struct mn103int *controller,
697              unsigned_word offset,
698              unsigned8 val)
699 {
700   int gid;
701   struct mn103int_group *group = external_group (controller, offset);
702   if (group != NULL)
703     {
704       for (gid = 0; gid < 4; gid++)
705         {
706           group[gid].trigger = (val >> (gid * 2)) & 0x3;
707           /* MAYBE: interrupts already pending? */
708         }
709     }
710   HW_TRACE ((me, "write-extmd 0x%02lx", (long) val));
711 }
712
713
714 /* generic read/write */
715
716 static int
717 decode_addr (struct hw *me,
718              struct mn103int *controller,
719              unsigned_word address,
720              unsigned_word *offset)
721 {
722   int i;
723   for (i = 0; i < NR_BLOCKS; i++)
724     {
725       if (address >= controller->block[i].base
726           && address <= controller->block[i].bound)
727         {
728           *offset = address - controller->block[i].base;
729           return i;
730         }
731     }
732   hw_abort (me, "bad address");
733   return -1;
734 }
735
736 static unsigned
737 mn103int_io_read_buffer (struct hw *me,
738                          void *dest,
739                          int space,
740                          unsigned_word base,
741                          unsigned nr_bytes)
742 {
743   struct mn103int *controller = hw_data (me);
744   unsigned8 *buf = dest;
745   unsigned byte;
746   /* HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); */
747   for (byte = 0; byte < nr_bytes; byte++)
748     {
749       unsigned_word address = base + byte;
750       unsigned_word offset;
751       switch (decode_addr (me, controller, address, &offset))
752         {
753         case ICR_BLOCK:
754           buf[byte] = read_icr (me, controller, offset);
755           break;
756         case IAGR_BLOCK:
757           buf[byte] = read_iagr (me, controller, offset);
758           break;
759         case EXTMD_BLOCK:
760           buf[byte] = read_extmd (me, controller, offset);
761           break;
762         default:
763           hw_abort (me, "bad switch");
764         }
765     }
766   return nr_bytes;
767 }     
768
769 static unsigned
770 mn103int_io_write_buffer (struct hw *me,
771                           const void *source,
772                           int space,
773                           unsigned_word base,
774                           unsigned nr_bytes)
775 {
776   struct mn103int *controller = hw_data (me);
777   const unsigned8 *buf = source;
778   unsigned byte;
779   /* HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); */
780   for (byte = 0; byte < nr_bytes; byte++)
781     {
782       unsigned_word address = base + byte;
783       unsigned_word offset;
784       switch (decode_addr (me, controller, address, &offset))
785         {
786         case ICR_BLOCK:
787           write_icr (me, controller, offset, buf[byte]);
788           break;
789         case IAGR_BLOCK:
790           /* not allowed */
791           break;
792         case EXTMD_BLOCK:
793           write_extmd (me, controller, offset, buf[byte]);
794           break;
795         default:
796           hw_abort (me, "bad switch");
797         }
798     }
799   return nr_bytes;
800 }     
801
802
803 const struct hw_descriptor dv_mn103int_descriptor[] = {
804   { "mn103int", mn103int_finish, },
805   { NULL },
806 };