1 /* This file is part of the program GDB, the GNU debugger.
3 Copyright (C) 1998-2024 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. */
31 mn103int - mn103002 interrupt controller
37 Implements the mn103002 interrupt controller described in the
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.
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.
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
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.
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
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
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
113 /* The interrupt groups - numbered according to mn103002 convention */
115 enum mn103int_trigger
{
127 struct mn103int_group
{
133 enum mn103int_trigger trigger
;
134 enum mn103int_type type
;
140 FIRST_LEVEL_GROUP
= 2,
141 LAST_LEVEL_GROUP
= 30,
149 /* The interrupt controller register address blocks */
151 struct mn103int_block
{
156 enum { ICR_BLOCK
, IAGR_BLOCK
, EXTMD_BLOCK
, NR_BLOCKS
};
160 struct mn103int_block block
[NR_BLOCKS
];
161 struct mn103int_group group
[NR_GROUPS
];
162 unsigned interrupt_accepted_group
;
167 /* output port ID's */
175 /* input port ID's */
202 IRQ0_PORT
= G23_PORT
,
207 IRQ4_PORT
= G27_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
, },
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
;
301 attach_mn103int_regs (struct hw
*me
,
302 struct mn103int
*controller
)
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
;
311 unsigned attach_size
;
312 reg_property_spec reg
;
313 if (!hw_find_reg_array_property (me
, "reg", i
, ®
))
314 hw_abort (me
, "\"reg\" property must contain three addr/size entries");
315 hw_unit_address_to_attach_address (hw_parent (me
),
320 controller
->block
[i
].base
= attach_address
;
321 hw_unit_size_to_attach_size (hw_parent (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
,
333 mn103int_finish (struct hw
*me
)
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
;
355 if (FIRST_NMI_GROUP
<= gid
&& gid
<= LAST_NMI_GROUP
)
358 group
->type
= NMI_GROUP
;
360 else if (FIRST_LEVEL_GROUP
<= gid
&& gid
<= LAST_LEVEL_GROUP
)
363 group
->type
= LEVEL_GROUP
;
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. */
376 find_highest_interrupt_group (struct hw
*me
,
377 struct mn103int
*controller
)
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
)
403 /* Notify the processor of an interrupt level update */
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 */
419 mn103int_port_event (struct hw
*me
,
425 struct mn103int
*controller
= hw_data (me
);
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",
445 struct mn103int_group
*group
;
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
];
454 interrupt
= 1 << iid
;
456 /* update our cached input */
458 group
->input
|= interrupt
;
460 group
->input
&= ~interrupt
;
462 /* update the request bits */
463 switch (group
->trigger
)
468 group
->request
|= interrupt
;
472 group
->request
|= interrupt
;
475 /* force a corresponding output */
481 /* for NMI's the event is the trigger */
482 HW_TRACE ((me
, "port-in port=%d group=%d interrupt=%d - NMI",
484 if ((group
->request
& group
->enable
) != 0)
486 HW_TRACE ((me
, "port-out NMI"));
487 hw_port_event (me
, NMI_PORT
, 1);
494 /* if an interrupt is now pending */
495 HW_TRACE ((me
, "port-in port=%d group=%d interrupt=%d - INT",
497 push_interrupt_level (me
, controller
);
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
,
513 unsigned_word
*offset
)
515 int gid
= (base
/ 4) % NR_GROUPS
;
516 *offset
= (base
% 4);
517 return &controller
->group
[gid
];
521 read_icr (struct hw
*me
,
522 struct mn103int
*controller
,
525 unsigned_word offset
;
526 struct mn103int_group
*group
= decode_group (me
, controller
, base
, &offset
);
535 val
= INSERT_ID (group
->request
);
536 HW_TRACE ((me
, "read-icr group=%d:0 nmi 0x%02x",
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",
554 val
= (INSERT_LV (group
->level
)
555 | INSERT_IE (group
->enable
));
556 HW_TRACE ((me
, "read-icr level-%d:1 level 0x%02x",
571 write_icr (struct hw
*me
,
572 struct mn103int
*controller
,
576 unsigned_word offset
;
577 struct mn103int_group
*group
= decode_group (me
, controller
, base
, &offset
);
585 HW_TRACE ((me
, "write-icr group=%d:0 nmi 0x%02x",
587 group
->request
&= ~EXTRACT_ID (val
);
589 /* Special backdoor access to SYSEF flag from CPU. See
590 interp.c:program_interrupt(). */
592 HW_TRACE ((me
, "write-icr-special group=%d:0 nmi 0x%02x",
594 group
->request
|= EXTRACT_ID (val
);
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",
607 group
->request
, EXTRACT_IR (val
), EXTRACT_ID (val
)));
609 ((EXTRACT_IR (val
) & EXTRACT_ID (val
))
610 | (EXTRACT_IR (val
) & group
->request
)
611 | (~EXTRACT_IR (val
) & ~EXTRACT_ID (val
) & group
->request
));
613 case 1: /* level/enable */
614 HW_TRACE ((me
, "write-icr group=%d:1 level 0x%02x",
616 group
->level
= EXTRACT_LV (val
);
617 group
->enable
= EXTRACT_IE (val
);
623 push_interrupt_level (me
, controller
);
633 /* Read the IAGR (Interrupt accepted group register) */
636 read_iagr (struct hw
*me
,
637 struct mn103int
*controller
,
638 unsigned_word offset
)
645 if (!(controller
->group
[controller
->interrupt_accepted_group
].request
646 & controller
->group
[controller
->interrupt_accepted_group
].enable
))
648 /* oops, lost the request */
650 HW_TRACE ((me
, "read-iagr:0 lost-0"));
654 val
= (controller
->interrupt_accepted_group
<< 2);
655 HW_TRACE ((me
, "read-iagr:0 %d", (int) val
));
661 HW_TRACE ((me
, "read-iagr:1 %d", (int) val
));
665 HW_TRACE ((me
, "read-iagr 0x%08lx bad offset", (long) offset
));
672 /* Reads/writes to the EXTMD (external interrupt trigger configuration
675 static struct mn103int_group
*
676 external_group (struct mn103int
*controller
,
677 unsigned_word offset
)
682 return &controller
->group
[IRQ0_PORT
/4];
684 return &controller
->group
[IRQ4_PORT
/4];
691 read_extmd (struct hw
*me
,
692 struct mn103int
*controller
,
693 unsigned_word offset
)
697 struct mn103int_group
*group
= external_group (controller
, offset
);
700 for (gid
= 0; gid
< 4; gid
++)
702 val
|= (group
[gid
].trigger
<< (gid
* 2));
705 HW_TRACE ((me
, "read-extmd 0x%02lx", (long) val
));
710 write_extmd (struct hw
*me
,
711 struct mn103int
*controller
,
712 unsigned_word offset
,
716 struct mn103int_group
*group
= external_group (controller
, offset
);
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 */
732 decode_addr (struct hw
*me
,
733 struct mn103int
*controller
,
734 unsigned_word address
,
735 unsigned_word
*offset
)
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
;
747 hw_abort (me
, "bad address");
752 mn103int_io_read_buffer (struct hw
*me
,
758 struct mn103int
*controller
= hw_data (me
);
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
))
769 buf
[byte
] = read_icr (me
, controller
, offset
);
772 buf
[byte
] = read_iagr (me
, controller
, offset
);
775 buf
[byte
] = read_extmd (me
, controller
, offset
);
778 hw_abort (me
, "bad switch");
785 mn103int_io_write_buffer (struct hw
*me
,
791 struct mn103int
*controller
= hw_data (me
);
792 const uint8_t *buf
= source
;
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
))
802 write_icr (me
, controller
, offset
, buf
[byte
]);
808 write_extmd (me
, controller
, offset
, buf
[byte
]);
811 hw_abort (me
, "bad switch");
818 mn103int_ioctl(struct hw
*me
,
819 hw_ioctl_request request
,
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);
829 const struct hw_descriptor dv_mn103int_descriptor
[] = {
830 { "mn103int", mn103int_finish
, },