Wed June 10 14:34:00 1998 Joyce Janczyn <janczyn@cygnus.com>
[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   IRQ0_PORT = G23_PORT,
201   G24_PORT = 96,
202   G25_PORT = 100,
203   G26_PORT = 104,
204   G27_PORT = 108,
205   IRQ4_PORT = G27_PORT,
206   G28_PORT = 112,
207   G29_PORT = 116,
208   G30_PORT = 120,
209   NR_G_PORTS = 124,
210   ACK_PORT,
211 };
212
213 static const struct hw_port_descriptor mn103int_ports[] = {
214
215   /* interrupt outputs */
216
217   { "nmi", NMI_PORT, 0, output_port, },
218   { "level", LEVEL_PORT, 0, output_port, },
219
220   /* interrupt ack (latch) input from cpu */
221
222   { "ack", ACK_PORT, 0, input_port, },
223
224   /* interrupt inputs (as names) */
225
226   { "nmirq", G0_PORT + 0, 0, input_port, },
227   { "watchdog", G0_PORT + 1, 0, input_port, },
228   { "syserr", G0_PORT + 2, 0, input_port, },
229
230   { "timer-0-underflow", G2_PORT, 0, input_port, },
231   { "timer-1-underflow", G3_PORT, 0, input_port, },
232   { "timer-2-underflow", G4_PORT, 0, input_port, },
233   { "timer-3-underflow", G5_PORT, 0, input_port, },
234   { "timer-4-underflow", G6_PORT, 0, input_port, },
235   { "timer-5-underflow", G7_PORT, 0, input_port, },
236   { "timer-6-underflow", G8_PORT, 0, input_port, },
237
238   { "timer-6-compare-a", G9_PORT, 0, input_port, },
239   { "timer-6-compare-b", G10_PORT, 0, input_port, },
240
241   { "dma-0-end", G12_PORT, 0, input_port, },
242   { "dma-1-end", G13_PORT, 0, input_port, },
243   { "dma-2-end", G14_PORT, 0, input_port, },
244   { "dma-3-end", G15_PORT, 0, input_port, },
245
246   { "serial-0-receive",  G16_PORT, 0, input_port, },
247   { "serial-0-transmit", G17_PORT, 0, input_port, },
248
249   { "serial-1-receive",  G18_PORT, 0, input_port, },
250   { "serial-1-transmit", G19_PORT, 0, input_port, },
251
252   { "serial-2-receive",  G20_PORT, 0, input_port, },
253   { "serial-2-transmit", G21_PORT, 0, input_port, },
254
255   { "irq-0", G23_PORT, 0, input_port, },
256   { "irq-1", G24_PORT, 0, input_port, },
257   { "irq-2", G25_PORT, 0, input_port, },
258   { "irq-3", G26_PORT, 0, input_port, },
259   { "irq-4", G27_PORT, 0, input_port, },
260   { "irq-5", G28_PORT, 0, input_port, },
261   { "irq-6", G29_PORT, 0, input_port, },
262   { "irq-7", G30_PORT, 0, input_port, },
263
264   /* interrupt inputs (as generic numbers) */
265
266   { "int", 0, NR_G_PORTS, input_port, },
267
268   { NULL, },
269 };
270
271
272 /* Macros for extracting/restoring the various register bits */
273
274 #define EXTRACT_ID(X) (LSEXTRACTED8 ((X), 3, 0))
275 #define INSERT_ID(X) (LSINSERTED8 ((X), 3, 0))
276
277 #define EXTRACT_IR(X) (LSEXTRACTED8 ((X), 7, 4))
278 #define INSERT_IR(X) (LSINSERTED8 ((X), 7, 4))
279
280 #define EXTRACT_IE(X) (LSEXTRACTED8 ((X), 3, 0))
281 #define INSERT_IE(X) (LSINSERTED8 ((X), 3, 0))
282
283 #define EXTRACT_LV(X) (LSEXTRACTED8 ((X), 6, 4))
284 #define INSERT_LV(X) (LSINSERTED8 ((X), 6, 4))
285
286
287
288 /* Finish off the partially created hw device.  Attach our local
289    callbacks.  Wire up our port names etc */
290
291 static hw_io_read_buffer_method mn103int_io_read_buffer;
292 static hw_io_write_buffer_method mn103int_io_write_buffer;
293 static hw_port_event_method mn103int_port_event;
294
295 static void
296 attach_mn103int_regs (struct hw *me,
297                       struct mn103int *controller)
298 {
299   int i;
300   if (hw_find_property (me, "reg") == NULL)
301     hw_abort (me, "Missing \"reg\" property");
302   for (i = 0; i < NR_BLOCKS; i++)
303     {
304       unsigned_word attach_address;
305       int attach_space;
306       unsigned attach_size;
307       reg_property_spec reg;
308       if (!hw_find_reg_array_property (me, "reg", i, &reg))
309         hw_abort (me, "\"reg\" property must contain three addr/size entries");
310       hw_unit_address_to_attach_address (hw_parent (me),
311                                          &reg.address,
312                                          &attach_space,
313                                          &attach_address,
314                                          me);
315       controller->block[i].base = attach_address;
316       hw_unit_size_to_attach_size (hw_parent (me),
317                                    &reg.size,
318                                    &attach_size, me);
319       controller->block[i].bound = attach_address + (attach_size - 1);
320       hw_attach_address (hw_parent (me),
321                          0,
322                          attach_space, attach_address, attach_size,
323                          me);
324     }
325 }
326
327 static void
328 mn103int_finish (struct hw *me)
329 {
330   int gid;
331   struct mn103int *controller;
332
333   controller = HW_ZALLOC (me, struct mn103int);
334   set_hw_data (me, controller);
335   set_hw_io_read_buffer (me, mn103int_io_read_buffer);
336   set_hw_io_write_buffer (me, mn103int_io_write_buffer);
337   set_hw_ports (me, mn103int_ports);
338   set_hw_port_event (me, mn103int_port_event);
339
340   /* Attach ourself to our parent bus */
341   attach_mn103int_regs (me, controller);
342
343   /* Initialize all the groups according to their default configuration */
344   for (gid = 0; gid < NR_GROUPS; gid++)
345     {
346       struct mn103int_group *group = &controller->group[gid];
347       group->enable = 0xf;
348       group->trigger = NEGATIVE_EDGE;
349       group->gid = gid;
350       if (FIRST_NMI_GROUP <= gid && gid <= LAST_NMI_GROUP)
351         {
352           group->type = NMI_GROUP;
353         }
354       else if (FIRST_LEVEL_GROUP <= gid && gid <= LAST_LEVEL_GROUP)
355         {
356           group->type = LEVEL_GROUP;
357         }
358       else
359         hw_abort (me, "internal error - unknown group id");
360     }
361 }
362
363
364
365 /* Perform the nasty work of figuring out which of the interrupt
366    groups should have its interrupt delivered. */
367
368 static int
369 find_highest_interrupt_group (struct hw *me,
370                               struct mn103int *controller)
371 {
372   int gid;
373   int selected;
374
375   /* FIRST_NMI_GROUP (group zero) is used as a special default value
376      when searching for an interrupt group.*/
377   selected = FIRST_NMI_GROUP; 
378   controller->group[FIRST_NMI_GROUP].level = 7;
379   
380   for (gid = FIRST_LEVEL_GROUP; gid <= LAST_LEVEL_GROUP; gid++)
381     {
382       struct mn103int_group *group = &controller->group[gid];
383       if ((group->request & group->enable) != 0)
384         {
385           /* Remember, lower level, higher priority.  */
386           if (group->level < controller->group[selected].level)
387             {
388               selected = gid;
389             }
390         }
391     }
392   return selected;
393 }
394
395
396 /* Notify the processor of an interrupt level update */
397
398 static void
399 push_interrupt_level (struct hw *me,
400                       struct mn103int *controller)
401 {
402   int selected = find_highest_interrupt_group (me, controller);
403   int level = controller->group[selected].level;
404   HW_TRACE ((me, "port-out - selected=%d level=%d", selected, level));
405   hw_port_event (me, LEVEL_PORT, level);
406 }
407
408
409 /* An event arrives on an interrupt port */
410
411 static void
412 mn103int_port_event (struct hw *me,
413                      int my_port,
414                      struct hw *source,
415                      int source_port,
416                      int level)
417 {
418   struct mn103int *controller = hw_data (me);
419
420   switch (my_port)
421     {
422
423     case ACK_PORT:
424       {
425         int selected = find_highest_interrupt_group (me, controller);
426         if (controller->group[selected].level != level)
427           hw_abort (me, "botched level synchronisation");
428         controller->interrupt_accepted_group = selected;        
429         HW_TRACE ((me, "port-event port=ack level=%d - selected=%d",
430                    level, selected));
431         break;
432       }
433
434     default:
435       {
436         int gid;
437         int iid;
438         struct mn103int_group *group;
439         unsigned interrupt;
440         if (my_port > NR_G_PORTS)
441           hw_abort (me, "Event on unknown port %d", my_port);
442
443         /* map the port onto an interrupt group */
444         gid = (my_port % NR_G_PORTS) / 4;
445         group = &controller->group[gid];
446         iid = (my_port % 4);
447         interrupt = 1 << iid;
448
449         /* update our cached input */
450         if (level)
451           group->input |= interrupt;
452         else
453           group->input &= ~interrupt;
454
455         /* update the request bits */
456         switch (group->trigger)
457           {
458           case ACTIVE_LOW:
459           case ACTIVE_HIGH:
460             if (level)
461               group->request |= interrupt;
462             break;
463           case NEGATIVE_EDGE:
464           case POSITIVE_EDGE:
465             group->request |= interrupt;
466           }
467
468         /* force a corresponding output */
469         switch (group->type)
470           {
471
472           case NMI_GROUP:
473             {
474               /* for NMI's the event is the trigger */
475               HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - NMI",
476                          my_port, gid, iid));
477               if ((group->request & group->enable) != 0)
478                 {
479                   HW_TRACE ((me, "port-out NMI"));
480                   hw_port_event (me, NMI_PORT, 1);
481                 }
482               break;
483             }
484               
485           case LEVEL_GROUP:
486             {
487               /* if an interrupt is now pending */
488               HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - INT",
489                          my_port, gid, iid));
490               push_interrupt_level (me, controller);
491               break;
492             }
493           }
494         break;
495       }
496
497     }
498 }
499
500 /* Read/write to to an ICR (group control register) */
501
502 static struct mn103int_group *
503 decode_group (struct hw *me,
504               struct mn103int *controller,
505               unsigned_word base,
506               unsigned_word *offset)
507 {
508   int gid = (base / 4) % NR_GROUPS;
509   *offset = (base % 4);
510   return &controller->group[gid];
511 }
512
513 static unsigned8
514 read_icr (struct hw *me,
515           struct mn103int *controller,
516           unsigned_word base)
517 {
518   unsigned_word offset;
519   struct mn103int_group *group = decode_group (me, controller, base, &offset);
520   unsigned8 val = 0;
521   switch (group->type)
522     {
523
524     case NMI_GROUP:
525       switch (offset)
526         {
527         case 0:
528           val = INSERT_ID (group->request);
529           HW_TRACE ((me, "read-icr group=%d:0 nmi 0x%02x",
530                      group->gid, val));
531           break;
532         default:
533           break;
534         }
535       break;
536
537     case LEVEL_GROUP:
538       switch (offset)
539         {
540         case 0:
541           val = (INSERT_IR (group->request)
542                  | INSERT_ID (group->request & group->enable));
543           HW_TRACE ((me, "read-icr group=%d:0 level 0x%02x",
544                      group->gid, val));
545           break;
546         case 1:
547           val = (INSERT_LV (group->level)
548                  | INSERT_IE (group->enable));
549           HW_TRACE ((me, "read-icr level-%d:1 level 0x%02x",
550                      group->gid, val));
551           break;
552         }
553       break;
554
555     default:
556       break;
557
558     }
559
560   return val;
561 }
562
563 static void
564 write_icr (struct hw *me,
565            struct mn103int *controller,
566            unsigned_word base,
567            unsigned8 val)
568 {
569   unsigned_word offset;
570   struct mn103int_group *group = decode_group (me, controller, base, &offset);
571   switch (group->type)
572     {
573
574     case NMI_GROUP:
575       switch (offset)
576         {
577         case 0:
578           HW_TRACE ((me, "write-icr group=%d:0 nmi 0x%02x",
579                      group->gid, val));
580           group->request &= ~EXTRACT_ID (val);
581           break;
582         default:
583           break;
584         }
585       break;
586
587     case LEVEL_GROUP:
588       switch (offset)
589         {
590         case 0: /* request/detect */
591           /* Clear any ID bits and then set them according to IR */
592           HW_TRACE ((me, "write-icr group=%d:0 level 0x%02x %x:%x:%x",
593                      group->gid, val,
594                      group->request, EXTRACT_IR (val), EXTRACT_ID (val)));
595           group->request =
596             ((EXTRACT_IR (val) & EXTRACT_ID (val))
597              | (EXTRACT_IR (val) & group->request)
598              | (~EXTRACT_IR (val) & ~EXTRACT_ID (val) & group->request));
599           break;
600         case 1: /* level/enable */
601           HW_TRACE ((me, "write-icr group=%d:1 level 0x%02x",
602                      group->gid, val));
603           group->level = EXTRACT_LV (val);
604           group->enable = EXTRACT_IE (val);
605           break;
606         default:
607           /* ignore */
608           break;
609         }
610       push_interrupt_level (me, controller);
611       break;
612
613     default:
614       break;
615
616     }
617 }
618
619
620 /* Read the IAGR (Interrupt accepted group register) */
621
622 static unsigned8
623 read_iagr (struct hw *me,
624            struct mn103int *controller,
625            unsigned_word offset)
626 {
627   unsigned8 val;
628   switch (offset)
629     {
630     case 0:
631       {
632         if (!(controller->group[controller->interrupt_accepted_group].request
633               & controller->group[controller->interrupt_accepted_group].enable))
634           {
635             /* oops, lost the request */
636             val = 0;
637             HW_TRACE ((me, "read-iagr:0 lost-0"));
638           }
639         else
640           {
641             val = (controller->interrupt_accepted_group << 2);
642             HW_TRACE ((me, "read-iagr:0 %d", (int) val));
643           }
644         break;
645       }
646     case 1:
647       val = 0;
648       HW_TRACE ((me, "read-iagr:1 %d", (int) val));
649       break;
650     default:
651       val = 0;
652       HW_TRACE ((me, "read-iagr 0x%08lx bad offset", (long) offset));
653       break;
654     }
655   return val;
656 }
657
658
659 /* Reads/writes to the EXTMD (external interrupt trigger configuration
660    register) */
661
662 static struct mn103int_group *
663 external_group (struct mn103int *controller,
664                 unsigned_word offset)
665 {
666   switch (offset)
667     {
668     case 0:
669       return &controller->group[IRQ0_PORT/4];
670     case 1:
671       return &controller->group[IRQ4_PORT/4];
672     default:
673       return NULL;
674     }
675 }
676
677 static unsigned8
678 read_extmd (struct hw *me,
679             struct mn103int *controller,
680             unsigned_word offset)
681 {
682   int gid;
683   unsigned8 val = 0;
684   struct mn103int_group *group = external_group (controller, offset);
685   if (group != NULL)
686     {
687       for (gid = 0; gid < 4; gid++)
688         {
689           val |= (group[gid].trigger << (gid * 2));
690         }
691     }
692   HW_TRACE ((me, "read-extmd 0x%02lx", (long) val));
693   return val;
694 }
695
696 static void
697 write_extmd (struct hw *me,
698              struct mn103int *controller,
699              unsigned_word offset,
700              unsigned8 val)
701 {
702   int gid;
703   struct mn103int_group *group = external_group (controller, offset);
704   if (group != NULL)
705     {
706       for (gid = 0; gid < 4; gid++)
707         {
708           group[gid].trigger = (val >> (gid * 2)) & 0x3;
709           /* MAYBE: interrupts already pending? */
710         }
711     }
712   HW_TRACE ((me, "write-extmd 0x%02lx", (long) val));
713 }
714
715
716 /* generic read/write */
717
718 static int
719 decode_addr (struct hw *me,
720              struct mn103int *controller,
721              unsigned_word address,
722              unsigned_word *offset)
723 {
724   int i;
725   for (i = 0; i < NR_BLOCKS; i++)
726     {
727       if (address >= controller->block[i].base
728           && address <= controller->block[i].bound)
729         {
730           *offset = address - controller->block[i].base;
731           return i;
732         }
733     }
734   hw_abort (me, "bad address");
735   return -1;
736 }
737
738 static unsigned
739 mn103int_io_read_buffer (struct hw *me,
740                          void *dest,
741                          int space,
742                          unsigned_word base,
743                          unsigned nr_bytes)
744 {
745   struct mn103int *controller = hw_data (me);
746   unsigned8 *buf = dest;
747   unsigned byte;
748   /* HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); */
749   for (byte = 0; byte < nr_bytes; byte++)
750     {
751       unsigned_word address = base + byte;
752       unsigned_word offset;
753       switch (decode_addr (me, controller, address, &offset))
754         {
755         case ICR_BLOCK:
756           buf[byte] = read_icr (me, controller, offset);
757           break;
758         case IAGR_BLOCK:
759           buf[byte] = read_iagr (me, controller, offset);
760           break;
761         case EXTMD_BLOCK:
762           buf[byte] = read_extmd (me, controller, offset);
763           break;
764         default:
765           hw_abort (me, "bad switch");
766         }
767     }
768   return nr_bytes;
769 }     
770
771 static unsigned
772 mn103int_io_write_buffer (struct hw *me,
773                           const void *source,
774                           int space,
775                           unsigned_word base,
776                           unsigned nr_bytes)
777 {
778   struct mn103int *controller = hw_data (me);
779   const unsigned8 *buf = source;
780   unsigned byte;
781   /* HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); */
782   for (byte = 0; byte < nr_bytes; byte++)
783     {
784       unsigned_word address = base + byte;
785       unsigned_word offset;
786       switch (decode_addr (me, controller, address, &offset))
787         {
788         case ICR_BLOCK:
789           write_icr (me, controller, offset, buf[byte]);
790           break;
791         case IAGR_BLOCK:
792           /* not allowed */
793           break;
794         case EXTMD_BLOCK:
795           write_extmd (me, controller, offset, buf[byte]);
796           break;
797         default:
798           hw_abort (me, "bad switch");
799         }
800     }
801   return nr_bytes;
802 }     
803
804
805 const struct hw_descriptor dv_mn103int_descriptor[] = {
806   { "mn103int", mn103int_finish, },
807   { NULL },
808 };