1 /* This file is part of the program GDB, the GNU debugger.
3 Copyright (C) 1998 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 2 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, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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 25 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 */
211 static const struct hw_port_descriptor mn103int_ports[] = {
213 /* interrupt outputs */
215 { "nmi", NMI_PORT, 0, output_port, },
216 { "level", LEVEL_PORT, 0, output_port, },
218 /* interrupt ack (latch) input from cpu */
220 { "ack", ACK_PORT, 0, input_port, },
222 /* interrupt inputs (as names) */
224 { "nmirq", G0_PORT + 0, 0, input_port, },
225 { "watchdog", G0_PORT + 1, 0, input_port, },
226 { "syserr", G0_PORT + 2, 0, input_port, },
228 { "timer-0-underflow", G2_PORT, 0, input_port, },
229 { "timer-1-underflow", G3_PORT, 0, input_port, },
230 { "timer-2-underflow", G4_PORT, 0, input_port, },
231 { "timer-3-underflow", G5_PORT, 0, input_port, },
232 { "timer-4-underflow", G6_PORT, 0, input_port, },
233 { "timer-5-underflow", G7_PORT, 0, input_port, },
234 { "timer-6-underflow", G8_PORT, 0, input_port, },
236 { "timer-6-compare-a", G9_PORT, 0, input_port, },
237 { "timer-6-compare-b", G10_PORT, 0, input_port, },
239 { "dma-0-end", G12_PORT, 0, input_port, },
240 { "dma-1-end", G13_PORT, 0, input_port, },
241 { "dma-2-end", G14_PORT, 0, input_port, },
242 { "dma-3-end", G15_PORT, 0, input_port, },
244 { "serial-0-receive", G16_PORT, 0, input_port, },
245 { "serial-0-transmit", G17_PORT, 0, input_port, },
247 { "serial-1-receive", G18_PORT, 0, input_port, },
248 { "serial-1-transmit", G19_PORT, 0, input_port, },
250 { "serial-2-receive", G20_PORT, 0, input_port, },
251 { "serial-2-transmit", G21_PORT, 0, input_port, },
253 { "irq-0", G23_PORT, 0, input_port, },
254 { "irq-1", G24_PORT, 0, input_port, },
255 { "irq-2", G25_PORT, 0, input_port, },
256 { "irq-3", G26_PORT, 0, input_port, },
257 { "irq-4", G27_PORT, 0, input_port, },
258 { "irq-5", G28_PORT, 0, input_port, },
259 { "irq-6", G29_PORT, 0, input_port, },
260 { "irq-7", G30_PORT, 0, input_port, },
262 /* { "ad-end", G24_PORT, 0, input_port, }, a/d conversion end, not in 103002? */
265 /* interrupt inputs (as generic numbers) */
267 { "int", 0, NR_G_PORTS, input_port, },
273 /* Macros for extracting/restoring the various register bits */
275 #define EXTRACT_ID(X) (LSEXTRACTED8 ((X), 3, 0))
276 #define INSERT_ID(X) (LSINSERTED8 ((X), 3, 0))
278 #define EXTRACT_IR(X) (LSEXTRACTED8 ((X), 7, 4))
279 #define INSERT_IR(X) (LSINSERTED8 ((X), 7, 4))
281 #define EXTRACT_IE(X) (LSEXTRACTED8 ((X), 3, 0))
282 #define INSERT_IE(X) (LSINSERTED8 ((X), 3, 0))
284 #define EXTRACT_LV(X) (LSEXTRACTED8 ((X), 6, 4))
285 #define INSERT_LV(X) (LSINSERTED8 ((X), 6, 4))
289 /* Finish off the partially created hw device. Attach our local
290 callbacks. Wire up our port names etc */
292 static hw_io_read_buffer_method mn103int_io_read_buffer;
293 static hw_io_write_buffer_method mn103int_io_write_buffer;
294 static hw_port_event_method mn103int_port_event;
297 attach_mn103int_regs (struct hw *me,
298 struct mn103int *controller)
301 if (hw_find_property (me, "reg") == NULL)
302 hw_abort (me, "Missing \"reg\" property");
303 for (i = 0; i < NR_BLOCKS; i++)
305 unsigned_word attach_address;
307 unsigned attach_size;
308 reg_property_spec reg;
309 if (!hw_find_reg_array_property (me, "reg", i, ®))
310 hw_abort (me, "\"reg\" property must contain three addr/size entries");
311 hw_unit_address_to_attach_address (hw_parent (me),
316 controller->block[i].base = attach_address;
317 hw_unit_size_to_attach_size (hw_parent (me),
320 controller->block[i].bound = attach_address + (attach_size - 1);
321 hw_attach_address (hw_parent (me),
323 attach_space, attach_address, attach_size,
329 mn103int_finish (struct hw *me)
332 struct mn103int *controller;
334 controller = HW_ZALLOC (me, struct mn103int);
335 set_hw_data (me, controller);
336 set_hw_io_read_buffer (me, mn103int_io_read_buffer);
337 set_hw_io_write_buffer (me, mn103int_io_write_buffer);
338 set_hw_ports (me, mn103int_ports);
339 set_hw_port_event (me, mn103int_port_event);
341 /* Attach ourself to our parent bus */
342 attach_mn103int_regs (me, controller);
344 /* Initialize all the groups according to their default configuration */
345 for (gid = 0; gid < NR_GROUPS; gid++)
347 struct mn103int_group *group = &controller->group[gid];
349 group->trigger = NEGATIVE_EDGE;
351 if (FIRST_NMI_GROUP <= gid && gid <= LAST_NMI_GROUP)
353 group->type = NMI_GROUP;
355 else if (FIRST_LEVEL_GROUP <= gid && gid <= LAST_LEVEL_GROUP)
357 group->type = LEVEL_GROUP;
360 hw_abort (me, "internal error - unknown group id");
366 /* Perform the nasty work of figuring out which of the interrupt
367 groups should have its interrupt delivered. */
370 find_highest_interrupt_group (struct hw *me,
371 struct mn103int *controller)
376 /* FIRST_NMI_GROUP (group zero) is used as a special default value
377 when searching for an interrupt group.*/
378 selected = FIRST_NMI_GROUP;
379 controller->group[FIRST_NMI_GROUP].level = 7;
381 for (gid = FIRST_LEVEL_GROUP; gid <= LAST_LEVEL_GROUP; gid++)
383 struct mn103int_group *group = &controller->group[gid];
384 if ((group->request & group->enable) != 0)
386 /* Remember, lower level, higher priority. */
387 if (group->level < controller->group[selected].level)
397 /* Notify the processor of an interrupt level update */
400 push_interrupt_level (struct hw *me,
401 struct mn103int *controller)
403 int selected = find_highest_interrupt_group (me, controller);
404 int level = controller->group[selected].level;
405 HW_TRACE ((me, "port-out - selected=%d level=%d", selected, level));
406 hw_port_event (me, LEVEL_PORT, level);
410 /* An event arrives on an interrupt port */
413 mn103int_port_event (struct hw *me,
419 struct mn103int *controller = hw_data (me);
426 int selected = find_highest_interrupt_group (me, controller);
427 if (controller->group[selected].level != level)
428 hw_abort (me, "botched level synchronisation");
429 controller->interrupt_accepted_group = selected;
430 HW_TRACE ((me, "port-event port=ack level=%d - selected=%d",
439 struct mn103int_group *group;
441 if (my_port > NR_G_PORTS)
442 hw_abort (me, "Event on unknown port %d", my_port);
444 /* map the port onto an interrupt group */
445 gid = (my_port % NR_G_PORTS) / 4;
446 group = &controller->group[gid];
448 interrupt = 1 << iid;
450 /* update our cached input */
452 group->input |= interrupt;
454 group->input &= ~interrupt;
456 /* update the request bits */
457 switch (group->trigger)
462 group->request |= interrupt;
466 group->request |= interrupt;
469 /* force a corresponding output */
475 /* for NMI's the event is the trigger */
476 HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - NMI",
478 if ((group->request & group->enable) != 0)
480 HW_TRACE ((me, "port-out NMI"));
481 hw_port_event (me, NMI_PORT, 1);
488 /* if an interrupt is now pending */
489 HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - INT",
491 push_interrupt_level (me, controller);
501 /* Read/write to to an ICR (group control register) */
503 static struct mn103int_group *
504 decode_group (struct hw *me,
505 struct mn103int *controller,
507 unsigned_word *offset)
509 int gid = (base / 4) % NR_GROUPS;
510 *offset = (base % 4);
511 return &controller->group[gid];
515 read_icr (struct hw *me,
516 struct mn103int *controller,
519 unsigned_word offset;
520 struct mn103int_group *group = decode_group (me, controller, base, &offset);
529 val = INSERT_ID (group->request);
530 HW_TRACE ((me, "read-icr group=%d:0 nmi 0x%02x",
542 val = (INSERT_IR (group->request)
543 | INSERT_ID (group->request & group->enable));
544 HW_TRACE ((me, "read-icr group=%d:0 level 0x%02x",
548 val = (INSERT_LV (group->level)
549 | INSERT_IE (group->enable));
550 HW_TRACE ((me, "read-icr level-%d:1 level 0x%02x",
565 write_icr (struct hw *me,
566 struct mn103int *controller,
570 unsigned_word offset;
571 struct mn103int_group *group = decode_group (me, controller, base, &offset);
579 HW_TRACE ((me, "write-icr group=%d:0 nmi 0x%02x",
581 group->request &= ~EXTRACT_ID (val);
591 case 0: /* request/detect */
592 /* Clear any ID bits and then set them according to IR */
593 HW_TRACE ((me, "write-icr group=%d:0 level 0x%02x %x:%x:%x",
595 group->request, EXTRACT_IR (val), EXTRACT_ID (val)));
597 ((EXTRACT_IR (val) & EXTRACT_ID (val))
598 | (EXTRACT_IR (val) & group->request)
599 | (~EXTRACT_IR (val) & ~EXTRACT_ID (val) & group->request));
601 case 1: /* level/enable */
602 HW_TRACE ((me, "write-icr group=%d:1 level 0x%02x",
604 group->level = EXTRACT_LV (val);
605 group->enable = EXTRACT_IE (val);
611 push_interrupt_level (me, controller);
621 /* Read the IAGR (Interrupt accepted group register) */
624 read_iagr (struct hw *me,
625 struct mn103int *controller,
626 unsigned_word offset)
633 if (!(controller->group[controller->interrupt_accepted_group].request
634 & controller->group[controller->interrupt_accepted_group].enable))
636 /* oops, lost the request */
638 HW_TRACE ((me, "read-iagr:0 lost-0"));
642 val = (controller->interrupt_accepted_group << 2);
643 HW_TRACE ((me, "read-iagr:0 %d", (int) val));
649 HW_TRACE ((me, "read-iagr:1 %d", (int) val));
653 HW_TRACE ((me, "read-iagr 0x%08lx bad offset", (long) offset));
660 /* Reads/writes to the EXTMD (external interrupt trigger configuration
663 static struct mn103int_group *
664 external_group (struct mn103int *controller,
665 unsigned_word offset)
670 return &controller->group[16];
672 return &controller->group[20];
679 read_extmd (struct hw *me,
680 struct mn103int *controller,
681 unsigned_word offset)
685 struct mn103int_group *group = external_group (controller, offset);
688 for (gid = 0; gid < 4; gid++)
690 val |= (group[gid].trigger << (gid * 2));
693 HW_TRACE ((me, "read-extmd 0x%02lx", (long) val));
698 write_extmd (struct hw *me,
699 struct mn103int *controller,
700 unsigned_word offset,
704 struct mn103int_group *group = external_group (controller, offset);
707 for (gid = 0; gid < 4; gid++)
709 group[gid].trigger = (val >> (gid * 2)) & 0x3;
710 /* MAYBE: interrupts already pending? */
713 HW_TRACE ((me, "write-extmd 0x%02lx", (long) val));
717 /* generic read/write */
720 decode_addr (struct hw *me,
721 struct mn103int *controller,
722 unsigned_word address,
723 unsigned_word *offset)
726 for (i = 0; i < NR_BLOCKS; i++)
728 if (address >= controller->block[i].base
729 && address <= controller->block[i].bound)
731 *offset = address - controller->block[i].base;
735 hw_abort (me, "bad address");
740 mn103int_io_read_buffer (struct hw *me,
746 struct mn103int *controller = hw_data (me);
747 unsigned8 *buf = dest;
749 /* HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); */
750 for (byte = 0; byte < nr_bytes; byte++)
752 unsigned_word address = base + byte;
753 unsigned_word offset;
754 switch (decode_addr (me, controller, address, &offset))
757 buf[byte] = read_icr (me, controller, offset);
760 buf[byte] = read_iagr (me, controller, offset);
763 buf[byte] = read_extmd (me, controller, offset);
766 hw_abort (me, "bad switch");
773 mn103int_io_write_buffer (struct hw *me,
779 struct mn103int *controller = hw_data (me);
780 const unsigned8 *buf = source;
782 /* HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); */
783 for (byte = 0; byte < nr_bytes; byte++)
785 unsigned_word address = base + byte;
786 unsigned_word offset;
787 switch (decode_addr (me, controller, address, &offset))
790 write_icr (me, controller, offset, buf[byte]);
796 write_extmd (me, controller, offset, buf[byte]);
799 hw_abort (me, "bad switch");
806 const struct hw_descriptor dv_mn103int_descriptor[] = {
807 { "mn103int", mn103int_finish, },