1 /* This file is part of the program GDB, the GU 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 - mn10300 interrupt controller
35 Implements the mn10300 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 0x68 0x34000200 0x8 0x3400280
48 0x8' locates the interrupt controller at the addresses specified in
49 the mn10300 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 25
87 groups (0..24) 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 sensative interrupts, the interrupt controller ignores
104 active HIGH/LOW settings and instead always interprets a nonzero
105 port value as an interupt assertion and a zero port value as a
111 /* The interrupt groups - numbered according to mn10300 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 = 24,
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 */
205 static const struct hw_port_descriptor mn103int_ports[] = {
207 /* interrupt outputs */
209 { "nmi", NMI_PORT, 0, output_port, },
210 { "level", LEVEL_PORT, 0, output_port, },
212 /* interrupt ack (latch) input from cpu */
214 { "ack", ACK_PORT, 0, input_port, },
216 /* interrupt inputs (as names) */
218 { "nmirq", G0_PORT + 0, 0, input_port, },
219 { "watchdog", G0_PORT + 1, 0, input_port, },
220 { "syserr", G0_PORT + 2, 0, input_port, },
222 { "timer-0-underflow", G2_PORT + 0, 0, input_port, },
223 { "timer-1-underflow", G2_PORT + 1, 0, input_port, },
224 { "timer-2-underflow", G2_PORT + 2, 0, input_port, },
225 { "timer-3-underflow", G2_PORT + 3, 0, input_port, },
226 { "timer-4-underflow", G3_PORT + 0, 0, input_port, },
227 { "timer-5-underflow", G3_PORT + 1, 0, input_port, },
228 { "timer-6-underflow", G3_PORT + 2, 0, input_port, },
229 { "timer-7-underflow", G3_PORT + 3, 0, input_port, },
231 { "timer-8-underflow", G4_PORT + 0, 0, input_port, },
232 { "timer-8-compare-a", G4_PORT + 1, 0, input_port, },
233 { "timer-8-compare-b", G4_PORT + 2, 0, input_port, },
235 { "timer-9-underflow", G5_PORT + 0, 0, input_port, },
236 { "timer-9-compare-a", G5_PORT + 1, 0, input_port, },
237 { "timer-9-compare-b", G5_PORT + 2, 0, input_port, },
239 { "timer-10-underflow", G6_PORT + 0, 0, input_port, },
240 { "timer-10-compare-a", G6_PORT + 1, 0, input_port, },
241 { "timer-10-compare-b", G6_PORT + 2, 0, input_port, },
242 { "timer-10-compare-c", G6_PORT + 3, 0, input_port, },
244 { "timer-11-underflow", G7_PORT + 0, 0, input_port, },
245 { "timer-11-compare-a", G7_PORT + 1, 0, input_port, },
246 { "timer-11-compare-b", G7_PORT + 2, 0, input_port, },
247 { "timer-11-compare-c", G7_PORT + 3, 0, input_port, },
249 { "timer-12-underflow", G8_PORT + 0, 0, input_port, },
250 { "timer-12-compare-a", G8_PORT + 1, 0, input_port, },
251 { "timer-12-compare-b", G8_PORT + 2, 0, input_port, },
252 { "timer-12-compare-c", G8_PORT + 3, 0, input_port, },
254 { "timer-11-compare-d", G9_PORT + 0, 0, input_port, },
255 { "timer-12-compare-d", G9_PORT + 1, 0, input_port, },
257 { "dma-0-end", G10_PORT, 0, input_port, },
258 { "dma-1-end", G11_PORT, 0, input_port, },
259 { "dma-2-end", G12_PORT, 0, input_port, },
260 { "dma-3-end", G13_PORT, 0, input_port, },
262 { "serial-0-recieve", G14_PORT + 0, 0, input_port, },
263 { "serial-0-transmit", G14_PORT + 1, 0, input_port, },
265 { "serial-1-recieve", G15_PORT + 0, 0, input_port, },
266 { "serial-1-transmit", G15_PORT + 1, 0, input_port, },
268 { "irq-0", G16_PORT, 0, input_port, },
269 { "irq-1", G17_PORT, 0, input_port, },
270 { "irq-2", G18_PORT, 0, input_port, },
271 { "irq-3", G19_PORT, 0, input_port, },
272 { "irq-4", G20_PORT, 0, input_port, },
273 { "irq-5", G21_PORT, 0, input_port, },
274 { "irq-6", G22_PORT, 0, input_port, },
275 { "irq-7", G23_PORT, 0, input_port, },
277 { "ad-end", G24_PORT, 0, input_port, },
279 /* interrupt inputs (as generic numbers) */
281 { "int", 0, NR_G_PORTS, input_port, },
287 /* Macros for extracting/restoring the various register bits */
289 #define EXTRACT_ID(X) (LSEXTRACTED8 ((X), 3, 0))
290 #define INSERT_ID(X) (LSINSERTED8 ((X), 3, 0))
292 #define EXTRACT_IR(X) (LSEXTRACTED8 ((X), 7, 4))
293 #define INSERT_IR(X) (LSINSERTED8 ((X), 7, 4))
295 #define EXTRACT_IE(X) (LSEXTRACTED8 ((X), 3, 0))
296 #define INSERT_IE(X) (LSINSERTED8 ((X), 3, 0))
298 #define EXTRACT_LV(X) (LSEXTRACTED8 ((X), 6, 4))
299 #define INSERT_LV(X) (LSINSERTED8 ((X), 6, 4))
303 /* Finish off the partially created hw device. Attach our local
304 callbacks. Wire up our port names etc */
306 static hw_io_read_buffer_callback mn103int_io_read_buffer;
307 static hw_io_write_buffer_callback mn103int_io_write_buffer;
308 static hw_port_event_callback mn103int_port_event;
311 attach_mn103int_regs (struct hw *me,
312 struct mn103int *controller)
315 if (hw_find_property (me, "reg") == NULL)
316 hw_abort (me, "Missing \"reg\" property");
317 for (i = 0; i < NR_BLOCKS; i++)
319 unsigned_word attach_address;
321 unsigned attach_size;
322 reg_property_spec reg;
323 if (!hw_find_reg_array_property (me, "reg", i, ®))
324 hw_abort (me, "\"reg\" property must contain three addr/size entries");
325 hw_unit_address_to_attach_address (hw_parent (me),
330 controller->block[i].base = attach_address;
331 hw_unit_size_to_attach_size (hw_parent (me),
334 controller->block[i].bound = attach_address + (attach_size - 1);
335 hw_attach_address (hw_parent (me),
337 attach_space, attach_address, attach_size,
343 mn103int_finish (struct hw *me)
346 struct mn103int *controller;
348 controller = HW_ZALLOC (me, struct mn103int);
349 set_hw_data (me, controller);
350 set_hw_io_read_buffer (me, mn103int_io_read_buffer);
351 set_hw_io_write_buffer (me, mn103int_io_write_buffer);
352 set_hw_ports (me, mn103int_ports);
353 set_hw_port_event (me, mn103int_port_event);
355 /* Attach ourself to our parent bus */
356 attach_mn103int_regs (me, controller);
358 /* Initialize all the groups according to their default configuration */
359 for (gid = 0; gid < NR_GROUPS; gid++)
361 struct mn103int_group *group = &controller->group[gid];
363 group->trigger = NEGATIVE_EDGE;
365 if (FIRST_NMI_GROUP <= gid && gid <= LAST_NMI_GROUP)
367 group->type = NMI_GROUP;
369 else if (FIRST_LEVEL_GROUP <= gid && gid <= LAST_LEVEL_GROUP)
371 group->type = LEVEL_GROUP;
374 hw_abort (me, "internal error - unknown group id");
380 /* Perform the nasty work of figuring out which of the interrupt
381 groups should have its interrupt delivered. */
384 find_highest_interrupt_group (struct hw *me,
385 struct mn103int *controller)
390 /* FIRST_NMI_GROUP (group zero) is used as a special default value
391 when searching for an interrupt group */
392 selected = FIRST_NMI_GROUP;
393 controller->group[FIRST_NMI_GROUP].level = 7;
395 for (gid = FIRST_LEVEL_GROUP; gid <= LAST_LEVEL_GROUP; gid++)
397 struct mn103int_group *group = &controller->group[gid];
398 if ((group->request & group->enable) != 0)
400 if (group->level > controller->group[selected].level)
410 /* Notify the processor of an interrupt level update */
413 push_interrupt_level (struct hw *me,
414 struct mn103int *controller)
416 int selected = find_highest_interrupt_group (me, controller);
417 int level = controller->group[selected].level;
418 HW_TRACE ((me, "port-out - selected=%d level=%d", selected, level));
419 hw_port_event (me, LEVEL_PORT, level, NULL, NULL_CIA);
423 /* An event arrives on an interrupt port */
426 mn103int_port_event (struct hw *me,
434 struct mn103int *controller = hw_data (me);
441 int selected = find_highest_interrupt_group (me, controller);
442 if (controller->group[selected].level != level)
443 hw_abort (me, "botched level synchronisation");
444 controller->interrupt_accepted_group = selected;
445 HW_TRACE ((me, "port-event port=ack level=%d - selected=%d",
454 struct mn103int_group *group;
456 if (my_port > NR_G_PORTS)
457 hw_abort (me, "Event on unknown port %d", my_port);
459 /* map the port onto an interrupt group */
460 gid = (my_port % NR_G_PORTS) / 4;
461 group = &controller->group[gid];
463 interrupt = 1 << iid;
465 /* update our cached input */
467 group->input |= interrupt;
469 group->input &= ~interrupt;
471 /* update the request bits */
472 switch (group->trigger)
477 group->request |= interrupt;
481 group->request |= interrupt;
484 /* force a corresponding output */
490 /* for NMI's the event is the trigger */
491 HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - NMI",
493 if ((group->request & group->enable) != 0)
495 HW_TRACE ((me, "port-out NMI"));
496 hw_port_event (me, NMI_PORT, 1, NULL, NULL_CIA);
503 /* if an interrupt is now pending */
504 HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - INT",
506 push_interrupt_level (me, controller);
516 /* Read/write to to an ICR (group control register) */
518 static struct mn103int_group *
519 decode_group (struct hw *me,
520 struct mn103int *controller,
522 unsigned_word *offset)
524 int gid = (base / 8) % NR_GROUPS;
525 *offset = (base % 8);
526 return &controller->group[gid];
530 read_icr (struct hw *me,
531 struct mn103int *controller,
534 unsigned_word offset;
535 struct mn103int_group *group = decode_group (me, controller, base, &offset);
544 val = INSERT_ID (group->request);
545 HW_TRACE ((me, "read-icr group=%d nmi 0x%02x",
557 val = (INSERT_IR (group->request)
558 | INSERT_ID (group->request & group->enable));
559 HW_TRACE ((me, "read-icr group=%d level 0 0x%02x",
563 val = (INSERT_LV (group->level)
564 | INSERT_IE (group->enable));
565 HW_TRACE ((me, "read-icr level-%d level 1 0x%02x",
580 write_icr (struct hw *me,
581 struct mn103int *controller,
585 unsigned_word offset;
586 struct mn103int_group *group = decode_group (me, controller, base, &offset);
594 HW_TRACE ((me, "write-icr group=%d nmi 0x%02x",
596 group->request &= ~EXTRACT_ID (val);
606 case 0: /* request/detect */
607 /* Clear any ID bits and then set them according to IR */
608 HW_TRACE ((me, "write-icr group=%d level 0 0x%02x",
610 group->request &= EXTRACT_ID (val);
611 group->request |= EXTRACT_IR (val) & EXTRACT_ID (val);
613 case 1: /* level/enable */
614 HW_TRACE ((me, "write-icr group=%d level 1 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 val = (controller->interrupt_accepted_group << 2);
646 if (!(controller->group[val].request
647 & controller->group[val].enable))
648 /* oops, lost the request */
650 HW_TRACE ((me, "read-iagr %d", (int) val));
655 HW_TRACE ((me, "read-iagr 0x%08lx bad offset", (long) offset));
662 /* Reads/writes to the EXTMD (external interrupt trigger configuration
665 static struct mn103int_group *
666 external_group (struct mn103int *controller,
667 unsigned_word offset)
672 return &controller->group[16];
674 return &controller->group[20];
681 read_extmd (struct hw *me,
682 struct mn103int *controller,
683 unsigned_word offset)
687 struct mn103int_group *group = external_group (controller, offset);
690 for (gid = 0; gid < 4; gid++)
692 val |= (group[gid].trigger << (gid * 2));
695 HW_TRACE ((me, "read-extmd 0x%02lx", (long) val));
700 write_extmd (struct hw *me,
701 struct mn103int *controller,
702 unsigned_word offset,
706 struct mn103int_group *group = external_group (controller, offset);
709 for (gid = 0; gid < 4; gid++)
711 group[gid].trigger = (val >> (gid * 2)) & 0x3;
712 /* MAYBE: interrupts already pending? */
715 HW_TRACE ((me, "write-extmd 0x%02lx", (long) val));
719 /* generic read/write */
722 decode_addr (struct hw *me,
723 struct mn103int *controller,
724 unsigned_word address,
725 unsigned_word *offset)
728 for (i = 0; i < NR_BLOCKS; i++)
730 if (address >= controller->block[i].base
731 && address <= controller->block[i].bound)
733 *offset = address - controller->block[i].base;
737 hw_abort (me, "bad address");
742 mn103int_io_read_buffer (struct hw *me,
750 struct mn103int *controller = hw_data (me);
751 unsigned8 *buf = dest;
753 HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
754 for (byte = 0; byte < nr_bytes; byte++)
756 unsigned_word address = base + byte;
757 unsigned_word offset;
758 switch (decode_addr (me, controller, address, &offset))
761 buf[byte] = read_icr (me, controller, offset);
764 buf[byte] = read_iagr (me, controller, offset);
767 buf[byte] = read_extmd (me, controller, offset);
770 hw_abort (me, "bad switch");
777 mn103int_io_write_buffer (struct hw *me,
785 struct mn103int *controller = hw_data (me);
786 const unsigned8 *buf = source;
788 HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
789 for (byte = 0; byte < nr_bytes; byte++)
791 unsigned_word address = base + byte;
792 unsigned_word offset;
793 switch (decode_addr (me, controller, address, &offset))
796 write_icr (me, controller, offset, buf[byte]);
802 write_extmd (me, controller, offset, buf[byte]);
805 hw_abort (me, "bad switch");
812 const struct hw_device_descriptor dv_mn103int_descriptor[] = {
813 { "mn103int", mn103int_finish, },