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 {
130 enum mn103int_trigger trigger;
131 enum mn103int_type type;
146 /* The interrupt controller register address blocks */
148 struct mn103int_block {
153 enum { ICR_BLOCK, IAGR_BLOCK, EXTMD_BLOCK, NR_BLOCKS };
157 struct mn103int_block block[NR_BLOCKS];
158 struct mn103int_group group[NR_GROUPS];
159 unsigned interrupt_accepted_group;
164 /* output port ID's */
172 /* input port ID's */
204 static const struct hw_port_descriptor mn103int_ports[] = {
206 /* interrupt outputs */
208 { "nmi", NMI_PORT, 0, output_port, },
209 { "level", LEVEL_PORT, 0, output_port, },
211 /* interrupt ack (latch) input from cpu */
213 { "ack", ACK_PORT, 0, input_port, },
215 /* interrupt inputs (as names) */
217 { "nmirq", G0_PORT + 0, 0, input_port, },
218 { "watchdog", G0_PORT + 1, 0, input_port, },
219 { "syserr", G0_PORT + 2, 0, input_port, },
221 { "timer-0-underflow", G2_PORT + 0, 0, input_port, },
222 { "timer-1-underflow", G2_PORT + 1, 0, input_port, },
223 { "timer-2-underflow", G2_PORT + 2, 0, input_port, },
224 { "timer-3-underflow", G2_PORT + 3, 0, input_port, },
225 { "timer-4-underflow", G3_PORT + 0, 0, input_port, },
226 { "timer-5-underflow", G3_PORT + 1, 0, input_port, },
227 { "timer-6-underflow", G3_PORT + 2, 0, input_port, },
228 { "timer-7-underflow", G3_PORT + 3, 0, input_port, },
230 { "timer-8-underflow", G4_PORT + 0, 0, input_port, },
231 { "timer-8-compare-a", G4_PORT + 1, 0, input_port, },
232 { "timer-8-compare-b", G4_PORT + 2, 0, input_port, },
234 { "timer-9-underflow", G5_PORT + 0, 0, input_port, },
235 { "timer-9-compare-a", G5_PORT + 1, 0, input_port, },
236 { "timer-9-compare-b", G5_PORT + 2, 0, input_port, },
238 { "timer-10-underflow", G6_PORT + 0, 0, input_port, },
239 { "timer-10-compare-a", G6_PORT + 1, 0, input_port, },
240 { "timer-10-compare-b", G6_PORT + 2, 0, input_port, },
241 { "timer-10-compare-c", G6_PORT + 3, 0, input_port, },
243 { "timer-11-underflow", G7_PORT + 0, 0, input_port, },
244 { "timer-11-compare-a", G7_PORT + 1, 0, input_port, },
245 { "timer-11-compare-b", G7_PORT + 2, 0, input_port, },
246 { "timer-11-compare-c", G7_PORT + 3, 0, input_port, },
248 { "timer-12-underflow", G8_PORT + 0, 0, input_port, },
249 { "timer-12-compare-a", G8_PORT + 1, 0, input_port, },
250 { "timer-12-compare-b", G8_PORT + 2, 0, input_port, },
251 { "timer-12-compare-c", G8_PORT + 3, 0, input_port, },
253 { "timer-11-compare-d", G9_PORT + 0, 0, input_port, },
254 { "timer-12-compare-d", G9_PORT + 1, 0, input_port, },
256 { "dma-0-end", G10_PORT, 0, input_port, },
257 { "dma-1-end", G11_PORT, 0, input_port, },
258 { "dma-2-end", G12_PORT, 0, input_port, },
259 { "dma-3-end", G13_PORT, 0, input_port, },
261 { "serial-0-recieve", G14_PORT + 0, 0, input_port, },
262 { "serial-0-transmit", G14_PORT + 1, 0, input_port, },
264 { "serial-1-recieve", G15_PORT + 0, 0, input_port, },
265 { "serial-1-transmit", G15_PORT + 1, 0, input_port, },
267 { "irq-0", G16_PORT, 0, input_port, },
268 { "irq-1", G17_PORT, 0, input_port, },
269 { "irq-2", G18_PORT, 0, input_port, },
270 { "irq-3", G19_PORT, 0, input_port, },
271 { "irq-4", G20_PORT, 0, input_port, },
272 { "irq-5", G21_PORT, 0, input_port, },
273 { "irq-6", G22_PORT, 0, input_port, },
274 { "irq-7", G23_PORT, 0, input_port, },
276 { "ad-end", G24_PORT, 0, input_port, },
278 /* interrupt inputs (as generic numbers) */
280 { "int", 0, NR_G_PORTS, input_port, },
286 /* Macros for extracting/restoring the various register bits */
288 #define EXTRACT_ID(X) (LSEXTRACTED8 ((X), 3, 0))
289 #define INSERT_ID(X) (LSINSERTED8 ((X), 3, 0))
291 #define EXTRACT_IR(X) (LSEXTRACTED8 ((X), 7, 4))
292 #define INSERT_IR(X) (LSINSERTED8 ((X), 7, 4))
294 #define EXTRACT_IE(X) (LSEXTRACTED8 ((X), 3, 0))
295 #define INSERT_IE(X) (LSINSERTED8 ((X), 3, 0))
297 #define EXTRACT_LV(X) (LSEXTRACTED8 ((X), 6, 4))
298 #define INSERT_LV(X) (LSINSERTED8 ((X), 6, 4))
302 /* Finish off the partially created hw device. Attach our local
303 callbacks. Wire up our port names etc */
305 static hw_io_read_buffer_callback mn103int_io_read_buffer;
306 static hw_io_write_buffer_callback mn103int_io_write_buffer;
307 static hw_port_event_callback mn103int_port_event;
310 attach_mn103int_regs (struct hw *me,
311 struct mn103int *controller)
314 if (hw_find_property (me, "reg") == NULL)
315 hw_abort (me, "Missing \"reg\" property");
316 for (i = 0; i < NR_BLOCKS; i++)
318 unsigned_word attach_address;
320 unsigned attach_size;
321 reg_property_spec reg;
322 if (!hw_find_reg_array_property (me, "reg", i, ®))
323 hw_abort (me, "\"reg\" property must contain three addr/size entries");
324 hw_unit_address_to_attach_address (hw_parent (me),
329 controller->block[i].base = attach_address;
330 hw_unit_size_to_attach_size (hw_parent (me),
333 controller->block[i].bound = attach_address + (attach_size - 1);
334 hw_attach_address (hw_parent (me),
336 attach_space, attach_address, attach_size,
342 mn103int_finish (struct hw *me)
345 struct mn103int *controller;
347 controller = HW_ZALLOC (me, struct mn103int);
348 set_hw_data (me, controller);
349 set_hw_io_read_buffer (me, mn103int_io_read_buffer);
350 set_hw_io_write_buffer (me, mn103int_io_write_buffer);
351 set_hw_ports (me, mn103int_ports);
352 set_hw_port_event (me, mn103int_port_event);
354 /* Attach ourself to our parent bus */
355 attach_mn103int_regs (me, controller);
357 /* Initialize all the groups according to their default configuration */
358 for (gid = 0; gid < NR_GROUPS; gid++)
360 struct mn103int_group *group = &controller->group[gid];
362 group->trigger = NEGATIVE_EDGE;
363 if (FIRST_NMI_GROUP <= gid && gid <= LAST_NMI_GROUP)
365 group->type = NMI_GROUP;
367 else if (FIRST_INT_GROUP <= gid && gid <= LAST_INT_GROUP)
369 group->type = INT_GROUP;
372 hw_abort (me, "internal error - unknown group id");
378 /* Perform the nasty work of figuring out which of the interrupt
379 groups should have its interrupt delivered. */
382 find_highest_interrupt_group (struct hw *me,
383 struct mn103int *controller)
388 /* FIRST_NMI_GROUP (group zero) is used as a special default value
389 when searching for an interrupt group */
390 selected = FIRST_NMI_GROUP;
391 controller->group[FIRST_NMI_GROUP].level = 7;
393 for (gid = FIRST_INT_GROUP; gid <= LAST_INT_GROUP; gid++)
395 struct mn103int_group *group = &controller->group[gid];
396 if ((group->request & group->enable) != 0)
398 if (group->level > controller->group[selected].level)
408 /* Notify the processor of an interrupt level update */
411 push_interrupt_level (struct hw *me,
412 struct mn103int *controller)
414 int selected = find_highest_interrupt_group (me, controller);
415 int level = controller->group[selected].level;
416 HW_TRACE ((me, "port-out - selected=%d level=%d", selected, level));
417 hw_port_event (me, LEVEL_PORT, level, NULL, NULL_CIA);
421 /* An event arrives on an interrupt port */
424 mn103int_port_event (struct hw *me,
432 struct mn103int *controller = hw_data (me);
439 int selected = find_highest_interrupt_group (me, controller);
440 if (controller->group[selected].level != level)
441 hw_abort (me, "botched level synchronisation");
442 controller->interrupt_accepted_group = selected;
443 HW_TRACE ((me, "port-event port=ack level=%d - selected=%d",
452 struct mn103int_group *group;
454 if (my_port > NR_G_PORTS)
455 hw_abort (me, "Event on unknown port %d", my_port);
457 /* map the port onto an interrupt group */
458 gid = (my_port % NR_G_PORTS) / 4;
459 group = &controller->group[gid];
461 interrupt = 1 << iid;
463 /* update our cached input */
465 group->input |= interrupt;
467 group->input &= ~interrupt;
469 /* update the request bits */
470 switch (group->trigger)
475 group->request |= interrupt;
479 group->request |= interrupt;
482 /* force a corresponding output */
488 /* for NMI's the event is the trigger */
489 HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - NMI",
491 if ((group->request & group->enable) != 0)
493 HW_TRACE ((me, "port-out NMI"));
494 hw_port_event (me, NMI_PORT, 0, NULL, NULL_CIA);
501 /* if an interrupt is now pending */
502 HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - INT",
504 push_interrupt_level (me, controller);
514 /* Read/write to to an ICR (group control register) */
517 read_icr (struct hw *me,
518 struct mn103int *controller,
519 struct mn103int_group *group,
520 unsigned_word offset)
530 val = INSERT_ID (group->request);
531 HW_TRACE ((me, "read-icr 0x%02x", val));
540 val = (INSERT_IR (group->request)
541 | INSERT_ID (group->request & group->enable));
542 HW_TRACE ((me, "read-icr 0:0x%02x", val));
545 val = (INSERT_LV (group->level)
546 | INSERT_IE (group->enable));
547 HW_TRACE ((me, "read-icr 1:0x%02x", val));
556 write_icr (struct hw *me,
557 struct mn103int *controller,
558 struct mn103int_group *group,
559 unsigned_word offset,
569 HW_TRACE ((me, "write-icr 0x%02x", val));
570 group->request &= ~EXTRACT_ID (val);
580 case 0: /* request/detect */
581 /* Clear any ID bits and then set them according to IR */
582 HW_TRACE ((me, "write-icr 0:0x%02x", val));
583 group->request &= EXTRACT_ID (val);
584 group->request |= EXTRACT_IR (val) & EXTRACT_ID (val);
586 case 1: /* level/enable */
587 HW_TRACE ((me, "write-icr 1:0x%02x", val));
588 group->level = EXTRACT_LV (val);
589 group->enable = EXTRACT_IE (val);
595 push_interrupt_level (me, controller);
602 /* Read the IAGR (Interrupt accepted group register) */
605 read_iagr (struct hw *me,
606 struct mn103int *controller,
607 unsigned_word offset)
614 val = (controller->interrupt_accepted_group << 2);
615 if (!(controller->group[val].request
616 & controller->group[val].enable))
617 /* oops, lost the request */
628 /* Reads/writes to the EXTMD (external interrupt trigger configuration
631 static struct mn103int_group *
632 external_group (struct mn103int *controller,
633 unsigned_word offset)
638 return &controller->group[16];
640 return &controller->group[20];
647 read_extmd (struct hw *me,
648 struct mn103int *controller,
649 unsigned_word offset)
653 struct mn103int_group *group = external_group (controller, offset);
656 for (gid = 0; gid < 4; gid++)
658 val |= (group[gid].trigger << (gid * 2));
665 write_extmd (struct hw *me,
666 struct mn103int *controller,
667 unsigned_word offset,
671 struct mn103int_group *group = external_group (controller, offset);
674 for (gid = 0; gid < 4; gid++)
676 group[gid].trigger = (val >> (gid * 2)) & 0x3;
677 /* MAYBE: interrupts already pending? */
683 /* generic read/write */
686 decode_addr (struct hw *me,
687 struct mn103int *controller,
691 for (i = 0; i < NR_BLOCKS; i++)
693 if (addr >= controller->block[i].base
694 && addr <= controller->block[i].bound)
697 hw_abort (me, "bad address");
701 static struct mn103int_group *
702 decode_group (struct hw *me,
703 struct mn103int *controller,
706 unsigned_word offset = (addr - controller->block[ICR_BLOCK].base);
707 int gid = (offset / 8) % NR_GROUPS;
708 return &controller->group[gid];
712 mn103int_io_read_buffer (struct hw *me,
720 struct mn103int *controller = hw_data (me);
721 unsigned8 *buf = dest;
723 for (byte = 0; byte < nr_bytes; byte++)
725 unsigned_word address = base + byte;
726 switch (decode_addr (me, controller, address))
729 buf[byte] = read_icr (me, controller,
730 decode_group (me, controller, address),
734 buf[byte] = read_iagr (me, controller, address);
737 buf[byte] = read_extmd (me, controller, address);
740 hw_abort (me, "bad switch");
747 mn103int_io_write_buffer (struct hw *me,
755 struct mn103int *controller = hw_data (me);
756 const unsigned8 *buf = source;
758 for (byte = 0; byte < nr_bytes; byte++)
760 unsigned_word address = base + byte;
761 switch (decode_addr (me, controller, address))
764 write_icr (me, controller,
765 decode_group (me, controller, address),
772 write_extmd (me, controller, address, buf[byte]);
775 hw_abort (me, "bad switch");
782 const struct hw_device_descriptor dv_mn103int_descriptor[] = {
783 { "mn103int", mn103int_finish, },