1 /* This file is part of the program GDB, the GNU debugger.
3 Copyright (C) 1998-2019 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/>.
29 mn103int - mn103002 interrupt controller
35 Implements the mn103002 interrupt controller described in the
42 reg = <icr-adr> <icr-siz> <iagr-adr> <iadr-siz> <extmd-adr> <extmd-siz>
44 Specify the address of the ICR (total of 30 registers), IAGR and
45 EXTMD registers (within the parent bus).
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.
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.
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.
68 The interrupt controller will generate an event on this port
69 whenever there is a change to the internal state of the interrupt
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.
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.
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.
91 For convenience, numerous aliases to these interrupt inputs are
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
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
111 /* The interrupt groups - numbered according to mn103002 convention */
113 enum mn103int_trigger
{
125 struct mn103int_group
{
131 enum mn103int_trigger trigger
;
132 enum mn103int_type type
;
138 FIRST_LEVEL_GROUP
= 2,
139 LAST_LEVEL_GROUP
= 30,
147 /* The interrupt controller register address blocks */
149 struct mn103int_block
{
154 enum { ICR_BLOCK
, IAGR_BLOCK
, EXTMD_BLOCK
, NR_BLOCKS
};
158 struct mn103int_block block
[NR_BLOCKS
];
159 struct mn103int_group group
[NR_GROUPS
];
160 unsigned interrupt_accepted_group
;
165 /* output port ID's */
173 /* input port ID's */
200 IRQ0_PORT
= G23_PORT
,
205 IRQ4_PORT
= G27_PORT
,
213 static const struct hw_port_descriptor mn103int_ports
[] = {
215 /* interrupt outputs */
217 { "nmi", NMI_PORT
, 0, output_port
, },
218 { "level", LEVEL_PORT
, 0, output_port
, },
220 /* interrupt ack (latch) input from cpu */
222 { "ack", ACK_PORT
, 0, input_port
, },
224 /* interrupt inputs (as names) */
226 { "nmirq", G0_PORT
+ 0, 0, input_port
, },
227 { "watchdog", G0_PORT
+ 1, 0, input_port
, },
228 { "syserr", G0_PORT
+ 2, 0, input_port
, },
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
, },
238 { "timer-6-compare-a", G9_PORT
, 0, input_port
, },
239 { "timer-6-compare-b", G10_PORT
, 0, input_port
, },
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
, },
246 { "serial-0-receive", G16_PORT
, 0, input_port
, },
247 { "serial-0-transmit", G17_PORT
, 0, input_port
, },
249 { "serial-1-receive", G18_PORT
, 0, input_port
, },
250 { "serial-1-transmit", G19_PORT
, 0, input_port
, },
252 { "serial-2-receive", G20_PORT
, 0, input_port
, },
253 { "serial-2-transmit", G21_PORT
, 0, input_port
, },
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
, },
264 /* interrupt inputs (as generic numbers) */
266 { "int", 0, NR_G_PORTS
, input_port
, },
272 /* Macros for extracting/restoring the various register bits */
274 #define EXTRACT_ID(X) (LSEXTRACTED8 ((X), 3, 0))
275 #define INSERT_ID(X) (LSINSERTED8 ((X), 3, 0))
277 #define EXTRACT_IR(X) (LSEXTRACTED8 ((X), 7, 4))
278 #define INSERT_IR(X) (LSINSERTED8 ((X), 7, 4))
280 #define EXTRACT_IE(X) (LSEXTRACTED8 ((X), 3, 0))
281 #define INSERT_IE(X) (LSINSERTED8 ((X), 3, 0))
283 #define EXTRACT_LV(X) (LSEXTRACTED8 ((X), 6, 4))
284 #define INSERT_LV(X) (LSINSERTED8 ((X), 6, 4))
288 /* Finish off the partially created hw device. Attach our local
289 callbacks. Wire up our port names etc */
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 static hw_ioctl_method mn103int_ioctl
;
299 attach_mn103int_regs (struct hw
*me
,
300 struct mn103int
*controller
)
303 if (hw_find_property (me
, "reg") == NULL
)
304 hw_abort (me
, "Missing \"reg\" property");
305 for (i
= 0; i
< NR_BLOCKS
; i
++)
307 unsigned_word attach_address
;
309 unsigned attach_size
;
310 reg_property_spec reg
;
311 if (!hw_find_reg_array_property (me
, "reg", i
, ®
))
312 hw_abort (me
, "\"reg\" property must contain three addr/size entries");
313 hw_unit_address_to_attach_address (hw_parent (me
),
318 controller
->block
[i
].base
= attach_address
;
319 hw_unit_size_to_attach_size (hw_parent (me
),
322 controller
->block
[i
].bound
= attach_address
+ (attach_size
- 1);
323 hw_attach_address (hw_parent (me
),
325 attach_space
, attach_address
, attach_size
,
331 mn103int_finish (struct hw
*me
)
334 struct mn103int
*controller
;
336 controller
= HW_ZALLOC (me
, struct mn103int
);
337 set_hw_data (me
, controller
);
338 set_hw_io_read_buffer (me
, mn103int_io_read_buffer
);
339 set_hw_io_write_buffer (me
, mn103int_io_write_buffer
);
340 set_hw_ports (me
, mn103int_ports
);
341 set_hw_port_event (me
, mn103int_port_event
);
342 me
->to_ioctl
= mn103int_ioctl
;
344 /* Attach ourself to our parent bus */
345 attach_mn103int_regs (me
, controller
);
347 /* Initialize all the groups according to their default configuration */
348 for (gid
= 0; gid
< NR_GROUPS
; gid
++)
350 struct mn103int_group
*group
= &controller
->group
[gid
];
351 group
->trigger
= NEGATIVE_EDGE
;
353 if (FIRST_NMI_GROUP
<= gid
&& gid
<= LAST_NMI_GROUP
)
356 group
->type
= NMI_GROUP
;
358 else if (FIRST_LEVEL_GROUP
<= gid
&& gid
<= LAST_LEVEL_GROUP
)
361 group
->type
= LEVEL_GROUP
;
364 hw_abort (me
, "internal error - unknown group id");
370 /* Perform the nasty work of figuring out which of the interrupt
371 groups should have its interrupt delivered. */
374 find_highest_interrupt_group (struct hw
*me
,
375 struct mn103int
*controller
)
380 /* FIRST_NMI_GROUP (group zero) is used as a special default value
381 when searching for an interrupt group.*/
382 selected
= FIRST_NMI_GROUP
;
383 controller
->group
[FIRST_NMI_GROUP
].level
= 7;
385 for (gid
= FIRST_LEVEL_GROUP
; gid
<= LAST_LEVEL_GROUP
; gid
++)
387 struct mn103int_group
*group
= &controller
->group
[gid
];
388 if ((group
->request
& group
->enable
) != 0)
390 /* Remember, lower level, higher priority. */
391 if (group
->level
< controller
->group
[selected
].level
)
401 /* Notify the processor of an interrupt level update */
404 push_interrupt_level (struct hw
*me
,
405 struct mn103int
*controller
)
407 int selected
= find_highest_interrupt_group (me
, controller
);
408 int level
= controller
->group
[selected
].level
;
409 HW_TRACE ((me
, "port-out - selected=%d level=%d", selected
, level
));
410 hw_port_event (me
, LEVEL_PORT
, level
);
414 /* An event arrives on an interrupt port */
417 mn103int_port_event (struct hw
*me
,
423 struct mn103int
*controller
= hw_data (me
);
430 int selected
= find_highest_interrupt_group (me
, controller
);
431 if (controller
->group
[selected
].level
!= level
)
432 hw_abort (me
, "botched level synchronisation");
433 controller
->interrupt_accepted_group
= selected
;
434 HW_TRACE ((me
, "port-event port=ack level=%d - selected=%d",
443 struct mn103int_group
*group
;
445 if (my_port
> NR_G_PORTS
)
446 hw_abort (me
, "Event on unknown port %d", my_port
);
448 /* map the port onto an interrupt group */
449 gid
= (my_port
% NR_G_PORTS
) / 4;
450 group
= &controller
->group
[gid
];
452 interrupt
= 1 << iid
;
454 /* update our cached input */
456 group
->input
|= interrupt
;
458 group
->input
&= ~interrupt
;
460 /* update the request bits */
461 switch (group
->trigger
)
466 group
->request
|= interrupt
;
470 group
->request
|= interrupt
;
473 /* force a corresponding output */
479 /* for NMI's the event is the trigger */
480 HW_TRACE ((me
, "port-in port=%d group=%d interrupt=%d - NMI",
482 if ((group
->request
& group
->enable
) != 0)
484 HW_TRACE ((me
, "port-out NMI"));
485 hw_port_event (me
, NMI_PORT
, 1);
492 /* if an interrupt is now pending */
493 HW_TRACE ((me
, "port-in port=%d group=%d interrupt=%d - INT",
495 push_interrupt_level (me
, controller
);
505 /* Read/write to to an ICR (group control register) */
507 static struct mn103int_group
*
508 decode_group (struct hw
*me
,
509 struct mn103int
*controller
,
511 unsigned_word
*offset
)
513 int gid
= (base
/ 4) % NR_GROUPS
;
514 *offset
= (base
% 4);
515 return &controller
->group
[gid
];
519 read_icr (struct hw
*me
,
520 struct mn103int
*controller
,
523 unsigned_word offset
;
524 struct mn103int_group
*group
= decode_group (me
, controller
, base
, &offset
);
533 val
= INSERT_ID (group
->request
);
534 HW_TRACE ((me
, "read-icr group=%d:0 nmi 0x%02x",
546 val
= (INSERT_IR (group
->request
)
547 | INSERT_ID (group
->request
& group
->enable
));
548 HW_TRACE ((me
, "read-icr group=%d:0 level 0x%02x",
552 val
= (INSERT_LV (group
->level
)
553 | INSERT_IE (group
->enable
));
554 HW_TRACE ((me
, "read-icr level-%d:1 level 0x%02x",
569 write_icr (struct hw
*me
,
570 struct mn103int
*controller
,
574 unsigned_word offset
;
575 struct mn103int_group
*group
= decode_group (me
, controller
, base
, &offset
);
583 HW_TRACE ((me
, "write-icr group=%d:0 nmi 0x%02x",
585 group
->request
&= ~EXTRACT_ID (val
);
587 /* Special backdoor access to SYSEF flag from CPU. See
588 interp.c:program_interrupt(). */
590 HW_TRACE ((me
, "write-icr-special group=%d:0 nmi 0x%02x",
592 group
->request
|= EXTRACT_ID (val
);
601 case 0: /* request/detect */
602 /* Clear any ID bits and then set them according to IR */
603 HW_TRACE ((me
, "write-icr group=%d:0 level 0x%02x %x:%x:%x",
605 group
->request
, EXTRACT_IR (val
), EXTRACT_ID (val
)));
607 ((EXTRACT_IR (val
) & EXTRACT_ID (val
))
608 | (EXTRACT_IR (val
) & group
->request
)
609 | (~EXTRACT_IR (val
) & ~EXTRACT_ID (val
) & group
->request
));
611 case 1: /* level/enable */
612 HW_TRACE ((me
, "write-icr group=%d:1 level 0x%02x",
614 group
->level
= EXTRACT_LV (val
);
615 group
->enable
= EXTRACT_IE (val
);
621 push_interrupt_level (me
, controller
);
631 /* Read the IAGR (Interrupt accepted group register) */
634 read_iagr (struct hw
*me
,
635 struct mn103int
*controller
,
636 unsigned_word offset
)
643 if (!(controller
->group
[controller
->interrupt_accepted_group
].request
644 & controller
->group
[controller
->interrupt_accepted_group
].enable
))
646 /* oops, lost the request */
648 HW_TRACE ((me
, "read-iagr:0 lost-0"));
652 val
= (controller
->interrupt_accepted_group
<< 2);
653 HW_TRACE ((me
, "read-iagr:0 %d", (int) val
));
659 HW_TRACE ((me
, "read-iagr:1 %d", (int) val
));
663 HW_TRACE ((me
, "read-iagr 0x%08lx bad offset", (long) offset
));
670 /* Reads/writes to the EXTMD (external interrupt trigger configuration
673 static struct mn103int_group
*
674 external_group (struct mn103int
*controller
,
675 unsigned_word offset
)
680 return &controller
->group
[IRQ0_PORT
/4];
682 return &controller
->group
[IRQ4_PORT
/4];
689 read_extmd (struct hw
*me
,
690 struct mn103int
*controller
,
691 unsigned_word offset
)
695 struct mn103int_group
*group
= external_group (controller
, offset
);
698 for (gid
= 0; gid
< 4; gid
++)
700 val
|= (group
[gid
].trigger
<< (gid
* 2));
703 HW_TRACE ((me
, "read-extmd 0x%02lx", (long) val
));
708 write_extmd (struct hw
*me
,
709 struct mn103int
*controller
,
710 unsigned_word offset
,
714 struct mn103int_group
*group
= external_group (controller
, offset
);
717 for (gid
= 0; gid
< 4; gid
++)
719 group
[gid
].trigger
= (val
>> (gid
* 2)) & 0x3;
720 /* MAYBE: interrupts already pending? */
723 HW_TRACE ((me
, "write-extmd 0x%02lx", (long) val
));
727 /* generic read/write */
730 decode_addr (struct hw
*me
,
731 struct mn103int
*controller
,
732 unsigned_word address
,
733 unsigned_word
*offset
)
736 for (i
= 0; i
< NR_BLOCKS
; i
++)
738 if (address
>= controller
->block
[i
].base
739 && address
<= controller
->block
[i
].bound
)
741 *offset
= address
- controller
->block
[i
].base
;
745 hw_abort (me
, "bad address");
750 mn103int_io_read_buffer (struct hw
*me
,
756 struct mn103int
*controller
= hw_data (me
);
757 unsigned8
*buf
= dest
;
759 /* HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); */
760 for (byte
= 0; byte
< nr_bytes
; byte
++)
762 unsigned_word address
= base
+ byte
;
763 unsigned_word offset
;
764 switch (decode_addr (me
, controller
, address
, &offset
))
767 buf
[byte
] = read_icr (me
, controller
, offset
);
770 buf
[byte
] = read_iagr (me
, controller
, offset
);
773 buf
[byte
] = read_extmd (me
, controller
, offset
);
776 hw_abort (me
, "bad switch");
783 mn103int_io_write_buffer (struct hw
*me
,
789 struct mn103int
*controller
= hw_data (me
);
790 const unsigned8
*buf
= source
;
792 /* HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); */
793 for (byte
= 0; byte
< nr_bytes
; byte
++)
795 unsigned_word address
= base
+ byte
;
796 unsigned_word offset
;
797 switch (decode_addr (me
, controller
, address
, &offset
))
800 write_icr (me
, controller
, offset
, buf
[byte
]);
806 write_extmd (me
, controller
, offset
, buf
[byte
]);
809 hw_abort (me
, "bad switch");
816 mn103int_ioctl(struct hw
*me
,
817 hw_ioctl_request request
,
820 struct mn103int
*controller
= (struct mn103int
*)hw_data(me
);
821 controller
->group
[0].request
= EXTRACT_ID(4);
822 mn103int_port_event(me
, 2 /* nmi_port(syserr) */, NULL
, 0, 0);
827 const struct hw_descriptor dv_mn103int_descriptor
[] = {
828 { "mn103int", mn103int_finish
, },