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 /* Remember, lower level, higher priority. */
401 if (group->level < controller->group[selected].level)
411 /* Notify the processor of an interrupt level update */
414 push_interrupt_level (struct hw *me,
415 struct mn103int *controller)
417 int selected = find_highest_interrupt_group (me, controller);
418 int level = controller->group[selected].level;
419 HW_TRACE ((me, "port-out - selected=%d level=%d", selected, level));
420 hw_port_event (me, LEVEL_PORT, level);
424 /* An event arrives on an interrupt port */
427 mn103int_port_event (struct hw *me,
433 struct mn103int *controller = hw_data (me);
440 int selected = find_highest_interrupt_group (me, controller);
441 if (controller->group[selected].level != level)
442 hw_abort (me, "botched level synchronisation");
443 controller->interrupt_accepted_group = selected;
444 HW_TRACE ((me, "port-event port=ack level=%d - selected=%d",
453 struct mn103int_group *group;
455 if (my_port > NR_G_PORTS)
456 hw_abort (me, "Event on unknown port %d", my_port);
458 /* map the port onto an interrupt group */
459 gid = (my_port % NR_G_PORTS) / 4;
460 group = &controller->group[gid];
462 interrupt = 1 << iid;
464 /* update our cached input */
466 group->input |= interrupt;
468 group->input &= ~interrupt;
470 /* update the request bits */
471 switch (group->trigger)
476 group->request |= interrupt;
480 group->request |= interrupt;
483 /* force a corresponding output */
489 /* for NMI's the event is the trigger */
490 HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - NMI",
492 if ((group->request & group->enable) != 0)
494 HW_TRACE ((me, "port-out NMI"));
495 hw_port_event (me, NMI_PORT, 1);
502 /* if an interrupt is now pending */
503 HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - INT",
505 push_interrupt_level (me, controller);
515 /* Read/write to to an ICR (group control register) */
517 static struct mn103int_group *
518 decode_group (struct hw *me,
519 struct mn103int *controller,
521 unsigned_word *offset)
523 int gid = (base / 4) % NR_GROUPS;
524 *offset = (base % 4);
525 return &controller->group[gid];
529 read_icr (struct hw *me,
530 struct mn103int *controller,
533 unsigned_word offset;
534 struct mn103int_group *group = decode_group (me, controller, base, &offset);
543 val = INSERT_ID (group->request);
544 HW_TRACE ((me, "read-icr group=%d:0 nmi 0x%02x",
556 val = (INSERT_IR (group->request)
557 | INSERT_ID (group->request & group->enable));
558 HW_TRACE ((me, "read-icr group=%d:0 level 0x%02x",
562 val = (INSERT_LV (group->level)
563 | INSERT_IE (group->enable));
564 HW_TRACE ((me, "read-icr level-%d:1 level 0x%02x",
579 write_icr (struct hw *me,
580 struct mn103int *controller,
584 unsigned_word offset;
585 struct mn103int_group *group = decode_group (me, controller, base, &offset);
593 HW_TRACE ((me, "write-icr group=%d:0 nmi 0x%02x",
595 group->request &= ~EXTRACT_ID (val);
605 case 0: /* request/detect */
606 /* Clear any ID bits and then set them according to IR */
607 HW_TRACE ((me, "write-icr group=%d:0 level 0x%02x %x:%x:%x",
609 group->request, EXTRACT_IR (val), EXTRACT_ID (val)));
611 ((EXTRACT_IR (val) & EXTRACT_ID (val))
612 | (EXTRACT_IR (val) & group->request)
613 | (~EXTRACT_IR (val) & ~EXTRACT_ID (val) & group->request));
615 case 1: /* level/enable */
616 HW_TRACE ((me, "write-icr group=%d:1 level 0x%02x",
618 group->level = EXTRACT_LV (val);
619 group->enable = EXTRACT_IE (val);
625 push_interrupt_level (me, controller);
635 /* Read the IAGR (Interrupt accepted group register) */
638 read_iagr (struct hw *me,
639 struct mn103int *controller,
640 unsigned_word offset)
647 if (!(controller->group[controller->interrupt_accepted_group].request
648 & controller->group[controller->interrupt_accepted_group].enable))
650 /* oops, lost the request */
652 HW_TRACE ((me, "read-iagr:0 lost-0"));
656 val = (controller->interrupt_accepted_group << 2);
657 HW_TRACE ((me, "read-iagr:0 %d", (int) val));
663 HW_TRACE ((me, "read-iagr:1 %d", (int) val));
667 HW_TRACE ((me, "read-iagr 0x%08lx bad offset", (long) offset));
674 /* Reads/writes to the EXTMD (external interrupt trigger configuration
677 static struct mn103int_group *
678 external_group (struct mn103int *controller,
679 unsigned_word offset)
684 return &controller->group[16];
686 return &controller->group[20];
693 read_extmd (struct hw *me,
694 struct mn103int *controller,
695 unsigned_word offset)
699 struct mn103int_group *group = external_group (controller, offset);
702 for (gid = 0; gid < 4; gid++)
704 val |= (group[gid].trigger << (gid * 2));
707 HW_TRACE ((me, "read-extmd 0x%02lx", (long) val));
712 write_extmd (struct hw *me,
713 struct mn103int *controller,
714 unsigned_word offset,
718 struct mn103int_group *group = external_group (controller, offset);
721 for (gid = 0; gid < 4; gid++)
723 group[gid].trigger = (val >> (gid * 2)) & 0x3;
724 /* MAYBE: interrupts already pending? */
727 HW_TRACE ((me, "write-extmd 0x%02lx", (long) val));
731 /* generic read/write */
734 decode_addr (struct hw *me,
735 struct mn103int *controller,
736 unsigned_word address,
737 unsigned_word *offset)
740 for (i = 0; i < NR_BLOCKS; i++)
742 if (address >= controller->block[i].base
743 && address <= controller->block[i].bound)
745 *offset = address - controller->block[i].base;
749 hw_abort (me, "bad address");
754 mn103int_io_read_buffer (struct hw *me,
760 struct mn103int *controller = hw_data (me);
761 unsigned8 *buf = dest;
763 /* HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); */
764 for (byte = 0; byte < nr_bytes; byte++)
766 unsigned_word address = base + byte;
767 unsigned_word offset;
768 switch (decode_addr (me, controller, address, &offset))
771 buf[byte] = read_icr (me, controller, offset);
774 buf[byte] = read_iagr (me, controller, offset);
777 buf[byte] = read_extmd (me, controller, offset);
780 hw_abort (me, "bad switch");
787 mn103int_io_write_buffer (struct hw *me,
793 struct mn103int *controller = hw_data (me);
794 const unsigned8 *buf = source;
796 /* HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); */
797 for (byte = 0; byte < nr_bytes; byte++)
799 unsigned_word address = base + byte;
800 unsigned_word offset;
801 switch (decode_addr (me, controller, address, &offset))
804 write_icr (me, controller, offset, buf[byte]);
810 write_extmd (me, controller, offset, buf[byte]);
813 hw_abort (me, "bad switch");
820 const struct hw_device_descriptor dv_mn103int_descriptor[] = {
821 { "mn103int", mn103int_finish, },