* am33.igen (translate_xreg): New function. Use it as needed.
[deliverable/binutils-gdb.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 };
This page took 0.047582 seconds and 4 git commands to generate.