Fix whitespace snafu in tc-riscv.c
[binutils-gdb.git] / sim / mn10300 / dv-mn103int.c
blob724bad6b4c8390a5a68b8167261fcf12269002b9
1 /* This file is part of the program GDB, the GNU debugger.
3 Copyright (C) 1998-2023 Free Software Foundation, Inc.
4 Contributed by Cygnus Solutions.
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 3 of the License, or
9 (at your option) any later version.
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.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 /* This must come before any other includes. */
22 #include "defs.h"
24 #include "sim-main.h"
25 #include "hw-main.h"
26 #include "sim-hw.h"
28 /* DEVICE
31 mn103int - mn103002 interrupt controller
34 DESCRIPTION
37 Implements the mn103002 interrupt controller described in the
38 mn103002 user guide.
41 PROPERTIES
44 reg = <icr-adr> <icr-siz> <iagr-adr> <iadr-siz> <extmd-adr> <extmd-siz>
46 Specify the address of the ICR (total of 30 registers), IAGR and
47 EXTMD registers (within the parent bus).
49 The reg property value `0x34000100 0x7C 0x34000200 0x8 0x3400280
50 0x8' locates the interrupt controller at the addresses specified in
51 the mn103002 interrupt controller user guide.
54 PORTS
57 nmi (output)
59 Non-maskable interrupt output port. An event on this output ports
60 indicates a NMI request from the interrupt controller. The value
61 attached to the event should be ignored.
64 level (output)
66 Maskable interrupt level output port. An event on this output port
67 indicates a maskable interrupt request at the specified level. The
68 event value defines the level being requested.
70 The interrupt controller will generate an event on this port
71 whenever there is a change to the internal state of the interrupt
72 controller.
75 ack (input)
77 Signal from processor indicating that a maskable interrupt has been
78 accepted and the interrupt controller should latch the IAGR with
79 value of the current highest priority interrupting group.
81 The event value is the interrupt level being accepted by the
82 processor. It should be consistent with the most recent LEVEL sent
83 to the processor from the interrupt controller.
86 int[0..100] (input)
88 Level or edge triggered interrupt input port. Each of the 30
89 groups (0..30) can have up to 4 (0..3) interrupt inputs. The
90 interpretation of a port event/value is determined by the
91 configuration of the corresponding interrupt group.
93 For convenience, numerous aliases to these interrupt inputs are
94 provided.
97 BUGS
100 For edge triggered interrupts, the interrupt controller does not
101 differentiate between POSITIVE (rising) and NEGATIVE (falling)
102 edges. Instead any input port event is considered to be an
103 interrupt trigger.
105 For level sensitive interrupts, the interrupt controller ignores
106 active HIGH/LOW settings and instead always interprets a nonzero
107 port value as an interrupt assertion and a zero port value as a
108 negation.
113 /* The interrupt groups - numbered according to mn103002 convention */
115 enum mn103int_trigger {
116 ACTIVE_LOW,
117 ACTIVE_HIGH,
118 POSITIVE_EDGE,
119 NEGATIVE_EDGE,
122 enum mn103int_type {
123 NMI_GROUP,
124 LEVEL_GROUP,
127 struct mn103int_group {
128 int gid;
129 int level;
130 unsigned enable;
131 unsigned request;
132 unsigned input;
133 enum mn103int_trigger trigger;
134 enum mn103int_type type;
137 enum {
138 FIRST_NMI_GROUP = 0,
139 LAST_NMI_GROUP = 1,
140 FIRST_LEVEL_GROUP = 2,
141 LAST_LEVEL_GROUP = 30,
142 NR_GROUPS,
145 enum {
146 LOWEST_LEVEL = 7,
149 /* The interrupt controller register address blocks */
151 struct mn103int_block {
152 unsigned_word base;
153 unsigned_word bound;
156 enum { ICR_BLOCK, IAGR_BLOCK, EXTMD_BLOCK, NR_BLOCKS };
159 struct mn103int {
160 struct mn103int_block block[NR_BLOCKS];
161 struct mn103int_group group[NR_GROUPS];
162 unsigned interrupt_accepted_group;
167 /* output port ID's */
169 enum {
170 NMI_PORT,
171 LEVEL_PORT,
175 /* input port ID's */
177 enum {
178 G0_PORT = 0,
179 G1_PORT = 4,
180 G2_PORT = 8,
181 G3_PORT = 12,
182 G4_PORT = 16,
183 G5_PORT = 20,
184 G6_PORT = 24,
185 G7_PORT = 28,
186 G8_PORT = 32,
187 G9_PORT = 36,
188 G10_PORT = 40,
189 G11_PORT = 44,
190 G12_PORT = 48,
191 G13_PORT = 52,
192 G14_PORT = 56,
193 G15_PORT = 60,
194 G16_PORT = 64,
195 G17_PORT = 68,
196 G18_PORT = 72,
197 G19_PORT = 76,
198 G20_PORT = 80,
199 G21_PORT = 84,
200 G22_PORT = 88,
201 G23_PORT = 92,
202 IRQ0_PORT = G23_PORT,
203 G24_PORT = 96,
204 G25_PORT = 100,
205 G26_PORT = 104,
206 G27_PORT = 108,
207 IRQ4_PORT = G27_PORT,
208 G28_PORT = 112,
209 G29_PORT = 116,
210 G30_PORT = 120,
211 NR_G_PORTS = 124,
212 ACK_PORT,
215 static const struct hw_port_descriptor mn103int_ports[] = {
217 /* interrupt outputs */
219 { "nmi", NMI_PORT, 0, output_port, },
220 { "level", LEVEL_PORT, 0, output_port, },
222 /* interrupt ack (latch) input from cpu */
224 { "ack", ACK_PORT, 0, input_port, },
226 /* interrupt inputs (as names) */
228 { "nmirq", G0_PORT + 0, 0, input_port, },
229 { "watchdog", G0_PORT + 1, 0, input_port, },
230 { "syserr", G0_PORT + 2, 0, input_port, },
232 { "timer-0-underflow", G2_PORT, 0, input_port, },
233 { "timer-1-underflow", G3_PORT, 0, input_port, },
234 { "timer-2-underflow", G4_PORT, 0, input_port, },
235 { "timer-3-underflow", G5_PORT, 0, input_port, },
236 { "timer-4-underflow", G6_PORT, 0, input_port, },
237 { "timer-5-underflow", G7_PORT, 0, input_port, },
238 { "timer-6-underflow", G8_PORT, 0, input_port, },
240 { "timer-6-compare-a", G9_PORT, 0, input_port, },
241 { "timer-6-compare-b", G10_PORT, 0, input_port, },
243 { "dma-0-end", G12_PORT, 0, input_port, },
244 { "dma-1-end", G13_PORT, 0, input_port, },
245 { "dma-2-end", G14_PORT, 0, input_port, },
246 { "dma-3-end", G15_PORT, 0, input_port, },
248 { "serial-0-receive", G16_PORT, 0, input_port, },
249 { "serial-0-transmit", G17_PORT, 0, input_port, },
251 { "serial-1-receive", G18_PORT, 0, input_port, },
252 { "serial-1-transmit", G19_PORT, 0, input_port, },
254 { "serial-2-receive", G20_PORT, 0, input_port, },
255 { "serial-2-transmit", G21_PORT, 0, input_port, },
257 { "irq-0", G23_PORT, 0, input_port, },
258 { "irq-1", G24_PORT, 0, input_port, },
259 { "irq-2", G25_PORT, 0, input_port, },
260 { "irq-3", G26_PORT, 0, input_port, },
261 { "irq-4", G27_PORT, 0, input_port, },
262 { "irq-5", G28_PORT, 0, input_port, },
263 { "irq-6", G29_PORT, 0, input_port, },
264 { "irq-7", G30_PORT, 0, input_port, },
266 /* interrupt inputs (as generic numbers) */
268 { "int", 0, NR_G_PORTS, input_port, },
270 { NULL, },
274 /* Macros for extracting/restoring the various register bits */
276 #define EXTRACT_ID(X) (LSEXTRACTED8 ((X), 3, 0))
277 #define INSERT_ID(X) (LSINSERTED8 ((X), 3, 0))
279 #define EXTRACT_IR(X) (LSEXTRACTED8 ((X), 7, 4))
280 #define INSERT_IR(X) (LSINSERTED8 ((X), 7, 4))
282 #define EXTRACT_IE(X) (LSEXTRACTED8 ((X), 3, 0))
283 #define INSERT_IE(X) (LSINSERTED8 ((X), 3, 0))
285 #define EXTRACT_LV(X) (LSEXTRACTED8 ((X), 6, 4))
286 #define INSERT_LV(X) (LSINSERTED8 ((X), 6, 4))
290 /* Finish off the partially created hw device. Attach our local
291 callbacks. Wire up our port names etc */
293 static hw_io_read_buffer_method mn103int_io_read_buffer;
294 static hw_io_write_buffer_method mn103int_io_write_buffer;
295 static hw_port_event_method mn103int_port_event;
296 static hw_ioctl_method mn103int_ioctl;
300 static void
301 attach_mn103int_regs (struct hw *me,
302 struct mn103int *controller)
304 int i;
305 if (hw_find_property (me, "reg") == NULL)
306 hw_abort (me, "Missing \"reg\" property");
307 for (i = 0; i < NR_BLOCKS; i++)
309 unsigned_word attach_address;
310 int attach_space;
311 unsigned attach_size;
312 reg_property_spec reg;
313 if (!hw_find_reg_array_property (me, "reg", i, &reg))
314 hw_abort (me, "\"reg\" property must contain three addr/size entries");
315 hw_unit_address_to_attach_address (hw_parent (me),
316 &reg.address,
317 &attach_space,
318 &attach_address,
319 me);
320 controller->block[i].base = attach_address;
321 hw_unit_size_to_attach_size (hw_parent (me),
322 &reg.size,
323 &attach_size, me);
324 controller->block[i].bound = attach_address + (attach_size - 1);
325 hw_attach_address (hw_parent (me),
327 attach_space, attach_address, attach_size,
328 me);
332 static void
333 mn103int_finish (struct hw *me)
335 int gid;
336 struct mn103int *controller;
338 controller = HW_ZALLOC (me, struct mn103int);
339 set_hw_data (me, controller);
340 set_hw_io_read_buffer (me, mn103int_io_read_buffer);
341 set_hw_io_write_buffer (me, mn103int_io_write_buffer);
342 set_hw_ports (me, mn103int_ports);
343 set_hw_port_event (me, mn103int_port_event);
344 me->to_ioctl = mn103int_ioctl;
346 /* Attach ourself to our parent bus */
347 attach_mn103int_regs (me, controller);
349 /* Initialize all the groups according to their default configuration */
350 for (gid = 0; gid < NR_GROUPS; gid++)
352 struct mn103int_group *group = &controller->group[gid];
353 group->trigger = NEGATIVE_EDGE;
354 group->gid = gid;
355 if (FIRST_NMI_GROUP <= gid && gid <= LAST_NMI_GROUP)
357 group->enable = 0xf;
358 group->type = NMI_GROUP;
360 else if (FIRST_LEVEL_GROUP <= gid && gid <= LAST_LEVEL_GROUP)
362 group->enable = 0x0;
363 group->type = LEVEL_GROUP;
365 else
366 hw_abort (me, "internal error - unknown group id");
372 /* Perform the nasty work of figuring out which of the interrupt
373 groups should have its interrupt delivered. */
375 static int
376 find_highest_interrupt_group (struct hw *me,
377 struct mn103int *controller)
379 int gid;
380 int selected;
382 /* FIRST_NMI_GROUP (group zero) is used as a special default value
383 when searching for an interrupt group.*/
384 selected = FIRST_NMI_GROUP;
385 controller->group[FIRST_NMI_GROUP].level = 7;
387 for (gid = FIRST_LEVEL_GROUP; gid <= LAST_LEVEL_GROUP; gid++)
389 struct mn103int_group *group = &controller->group[gid];
390 if ((group->request & group->enable) != 0)
392 /* Remember, lower level, higher priority. */
393 if (group->level < controller->group[selected].level)
395 selected = gid;
399 return selected;
403 /* Notify the processor of an interrupt level update */
405 static void
406 push_interrupt_level (struct hw *me,
407 struct mn103int *controller)
409 int selected = find_highest_interrupt_group (me, controller);
410 int level = controller->group[selected].level;
411 HW_TRACE ((me, "port-out - selected=%d level=%d", selected, level));
412 hw_port_event (me, LEVEL_PORT, level);
416 /* An event arrives on an interrupt port */
418 static void
419 mn103int_port_event (struct hw *me,
420 int my_port,
421 struct hw *source,
422 int source_port,
423 int level)
425 struct mn103int *controller = hw_data (me);
427 switch (my_port)
430 case ACK_PORT:
432 int selected = find_highest_interrupt_group (me, controller);
433 if (controller->group[selected].level != level)
434 hw_abort (me, "botched level synchronisation");
435 controller->interrupt_accepted_group = selected;
436 HW_TRACE ((me, "port-event port=ack level=%d - selected=%d",
437 level, selected));
438 break;
441 default:
443 int gid;
444 int iid;
445 struct mn103int_group *group;
446 unsigned interrupt;
447 if (my_port > NR_G_PORTS)
448 hw_abort (me, "Event on unknown port %d", my_port);
450 /* map the port onto an interrupt group */
451 gid = (my_port % NR_G_PORTS) / 4;
452 group = &controller->group[gid];
453 iid = (my_port % 4);
454 interrupt = 1 << iid;
456 /* update our cached input */
457 if (level)
458 group->input |= interrupt;
459 else
460 group->input &= ~interrupt;
462 /* update the request bits */
463 switch (group->trigger)
465 case ACTIVE_LOW:
466 case ACTIVE_HIGH:
467 if (level)
468 group->request |= interrupt;
469 break;
470 case NEGATIVE_EDGE:
471 case POSITIVE_EDGE:
472 group->request |= interrupt;
475 /* force a corresponding output */
476 switch (group->type)
479 case NMI_GROUP:
481 /* for NMI's the event is the trigger */
482 HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - NMI",
483 my_port, gid, iid));
484 if ((group->request & group->enable) != 0)
486 HW_TRACE ((me, "port-out NMI"));
487 hw_port_event (me, NMI_PORT, 1);
489 break;
492 case LEVEL_GROUP:
494 /* if an interrupt is now pending */
495 HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - INT",
496 my_port, gid, iid));
497 push_interrupt_level (me, controller);
498 break;
501 break;
507 /* Read/write to to an ICR (group control register) */
509 static struct mn103int_group *
510 decode_group (struct hw *me,
511 struct mn103int *controller,
512 unsigned_word base,
513 unsigned_word *offset)
515 int gid = (base / 4) % NR_GROUPS;
516 *offset = (base % 4);
517 return &controller->group[gid];
520 static uint8_t
521 read_icr (struct hw *me,
522 struct mn103int *controller,
523 unsigned_word base)
525 unsigned_word offset;
526 struct mn103int_group *group = decode_group (me, controller, base, &offset);
527 uint8_t val = 0;
528 switch (group->type)
531 case NMI_GROUP:
532 switch (offset)
534 case 0:
535 val = INSERT_ID (group->request);
536 HW_TRACE ((me, "read-icr group=%d:0 nmi 0x%02x",
537 group->gid, val));
538 break;
539 default:
540 break;
542 break;
544 case LEVEL_GROUP:
545 switch (offset)
547 case 0:
548 val = (INSERT_IR (group->request)
549 | INSERT_ID (group->request & group->enable));
550 HW_TRACE ((me, "read-icr group=%d:0 level 0x%02x",
551 group->gid, val));
552 break;
553 case 1:
554 val = (INSERT_LV (group->level)
555 | INSERT_IE (group->enable));
556 HW_TRACE ((me, "read-icr level-%d:1 level 0x%02x",
557 group->gid, val));
558 break;
560 break;
562 default:
563 break;
567 return val;
570 static void
571 write_icr (struct hw *me,
572 struct mn103int *controller,
573 unsigned_word base,
574 uint8_t val)
576 unsigned_word offset;
577 struct mn103int_group *group = decode_group (me, controller, base, &offset);
578 switch (group->type)
581 case NMI_GROUP:
582 switch (offset)
584 case 0:
585 HW_TRACE ((me, "write-icr group=%d:0 nmi 0x%02x",
586 group->gid, val));
587 group->request &= ~EXTRACT_ID (val);
588 break;
589 /* Special backdoor access to SYSEF flag from CPU. See
590 interp.c:program_interrupt(). */
591 case 3:
592 HW_TRACE ((me, "write-icr-special group=%d:0 nmi 0x%02x",
593 group->gid, val));
594 group->request |= EXTRACT_ID (val);
595 default:
596 break;
598 break;
600 case LEVEL_GROUP:
601 switch (offset)
603 case 0: /* request/detect */
604 /* Clear any ID bits and then set them according to IR */
605 HW_TRACE ((me, "write-icr group=%d:0 level 0x%02x %x:%x:%x",
606 group->gid, val,
607 group->request, EXTRACT_IR (val), EXTRACT_ID (val)));
608 group->request =
609 ((EXTRACT_IR (val) & EXTRACT_ID (val))
610 | (EXTRACT_IR (val) & group->request)
611 | (~EXTRACT_IR (val) & ~EXTRACT_ID (val) & group->request));
612 break;
613 case 1: /* level/enable */
614 HW_TRACE ((me, "write-icr group=%d:1 level 0x%02x",
615 group->gid, val));
616 group->level = EXTRACT_LV (val);
617 group->enable = EXTRACT_IE (val);
618 break;
619 default:
620 /* ignore */
621 break;
623 push_interrupt_level (me, controller);
624 break;
626 default:
627 break;
633 /* Read the IAGR (Interrupt accepted group register) */
635 static uint8_t
636 read_iagr (struct hw *me,
637 struct mn103int *controller,
638 unsigned_word offset)
640 uint8_t val;
641 switch (offset)
643 case 0:
645 if (!(controller->group[controller->interrupt_accepted_group].request
646 & controller->group[controller->interrupt_accepted_group].enable))
648 /* oops, lost the request */
649 val = 0;
650 HW_TRACE ((me, "read-iagr:0 lost-0"));
652 else
654 val = (controller->interrupt_accepted_group << 2);
655 HW_TRACE ((me, "read-iagr:0 %d", (int) val));
657 break;
659 case 1:
660 val = 0;
661 HW_TRACE ((me, "read-iagr:1 %d", (int) val));
662 break;
663 default:
664 val = 0;
665 HW_TRACE ((me, "read-iagr 0x%08lx bad offset", (long) offset));
666 break;
668 return val;
672 /* Reads/writes to the EXTMD (external interrupt trigger configuration
673 register) */
675 static struct mn103int_group *
676 external_group (struct mn103int *controller,
677 unsigned_word offset)
679 switch (offset)
681 case 0:
682 return &controller->group[IRQ0_PORT/4];
683 case 1:
684 return &controller->group[IRQ4_PORT/4];
685 default:
686 return NULL;
690 static uint8_t
691 read_extmd (struct hw *me,
692 struct mn103int *controller,
693 unsigned_word offset)
695 int gid;
696 uint8_t val = 0;
697 struct mn103int_group *group = external_group (controller, offset);
698 if (group != NULL)
700 for (gid = 0; gid < 4; gid++)
702 val |= (group[gid].trigger << (gid * 2));
705 HW_TRACE ((me, "read-extmd 0x%02lx", (long) val));
706 return val;
709 static void
710 write_extmd (struct hw *me,
711 struct mn103int *controller,
712 unsigned_word offset,
713 uint8_t val)
715 int gid;
716 struct mn103int_group *group = external_group (controller, offset);
717 if (group != NULL)
719 for (gid = 0; gid < 4; gid++)
721 group[gid].trigger = (val >> (gid * 2)) & 0x3;
722 /* MAYBE: interrupts already pending? */
725 HW_TRACE ((me, "write-extmd 0x%02lx", (long) val));
729 /* generic read/write */
731 static int
732 decode_addr (struct hw *me,
733 struct mn103int *controller,
734 unsigned_word address,
735 unsigned_word *offset)
737 int i;
738 for (i = 0; i < NR_BLOCKS; i++)
740 if (address >= controller->block[i].base
741 && address <= controller->block[i].bound)
743 *offset = address - controller->block[i].base;
744 return i;
747 hw_abort (me, "bad address");
748 return -1;
751 static unsigned
752 mn103int_io_read_buffer (struct hw *me,
753 void *dest,
754 int space,
755 unsigned_word base,
756 unsigned nr_bytes)
758 struct mn103int *controller = hw_data (me);
759 uint8_t *buf = dest;
760 unsigned byte;
761 /* HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); */
762 for (byte = 0; byte < nr_bytes; byte++)
764 unsigned_word address = base + byte;
765 unsigned_word offset;
766 switch (decode_addr (me, controller, address, &offset))
768 case ICR_BLOCK:
769 buf[byte] = read_icr (me, controller, offset);
770 break;
771 case IAGR_BLOCK:
772 buf[byte] = read_iagr (me, controller, offset);
773 break;
774 case EXTMD_BLOCK:
775 buf[byte] = read_extmd (me, controller, offset);
776 break;
777 default:
778 hw_abort (me, "bad switch");
781 return nr_bytes;
784 static unsigned
785 mn103int_io_write_buffer (struct hw *me,
786 const void *source,
787 int space,
788 unsigned_word base,
789 unsigned nr_bytes)
791 struct mn103int *controller = hw_data (me);
792 const uint8_t *buf = source;
793 unsigned byte;
794 /* HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); */
795 for (byte = 0; byte < nr_bytes; byte++)
797 unsigned_word address = base + byte;
798 unsigned_word offset;
799 switch (decode_addr (me, controller, address, &offset))
801 case ICR_BLOCK:
802 write_icr (me, controller, offset, buf[byte]);
803 break;
804 case IAGR_BLOCK:
805 /* not allowed */
806 break;
807 case EXTMD_BLOCK:
808 write_extmd (me, controller, offset, buf[byte]);
809 break;
810 default:
811 hw_abort (me, "bad switch");
814 return nr_bytes;
817 static int
818 mn103int_ioctl(struct hw *me,
819 hw_ioctl_request request,
820 va_list ap)
822 struct mn103int *controller = (struct mn103int *)hw_data(me);
823 controller->group[0].request = EXTRACT_ID(4);
824 mn103int_port_event(me, 2 /* nmi_port(syserr) */, NULL, 0, 0);
825 return 0;
829 const struct hw_descriptor dv_mn103int_descriptor[] = {
830 { "mn103int", mn103int_finish, },
831 { NULL },