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.
30 mn103int - mn103002 interrupt controller
36 Implements the mn103002 interrupt controller described in the
43 reg = <icr-adr> <icr-siz> <iagr-adr> <iadr-siz> <extmd-adr> <extmd-siz>
45 Specify the address of the ICR (total of 30 registers), IAGR and
46 EXTMD registers (within the parent bus).
48 The reg property value `0x34000100 0x7C 0x34000200 0x8 0x3400280
49 0x8' locates the interrupt controller at the addresses specified in
50 the mn103002 interrupt controller user guide.
58 Non-maskable interrupt output port. An event on this output ports
59 indicates a NMI request from the interrupt controller. The value
60 attached to the event should be ignored.
65 Maskable interrupt level output port. An event on this output port
66 indicates a maskable interrupt request at the specified level. The
67 event value defines the level being requested.
69 The interrupt controller will generate an event on this port
70 whenever there is a change to the internal state of the interrupt
76 Signal from processor indicating that a maskable interrupt has been
77 accepted and the interrupt controller should latch the IAGR with
78 value of the current highest priority interrupting group.
80 The event value is the interrupt level being accepted by the
81 processor. It should be consistent with the most recent LEVEL sent
82 to the processor from the interrupt controller.
87 Level or edge triggered interrupt input port. Each of the 30
88 groups (0..30) can have up to 4 (0..3) interrupt inputs. The
89 interpretation of a port event/value is determined by the
90 configuration of the corresponding interrupt group.
92 For convenience, numerous aliases to these interrupt inputs are
99 For edge triggered interrupts, the interrupt controller does not
100 differentiate between POSITIVE (rising) and NEGATIVE (falling)
101 edges. Instead any input port event is considered to be an
104 For level sensitive interrupts, the interrupt controller ignores
105 active HIGH/LOW settings and instead always interprets a nonzero
106 port value as an interrupt assertion and a zero port value as a
112 /* The interrupt groups - numbered according to mn103002 convention */
114 enum mn103int_trigger
{
126 struct mn103int_group
{
132 enum mn103int_trigger trigger
;
133 enum mn103int_type type
;
139 FIRST_LEVEL_GROUP
= 2,
140 LAST_LEVEL_GROUP
= 30,
148 /* The interrupt controller register address blocks */
150 struct mn103int_block
{
155 enum { ICR_BLOCK
, IAGR_BLOCK
, EXTMD_BLOCK
, NR_BLOCKS
};
159 struct mn103int_block block
[NR_BLOCKS
];
160 struct mn103int_group group
[NR_GROUPS
];
161 unsigned interrupt_accepted_group
;
166 /* output port ID's */
174 /* input port ID's */
201 IRQ0_PORT
= G23_PORT
,
206 IRQ4_PORT
= G27_PORT
,
214 static const struct hw_port_descriptor mn103int_ports
[] = {
216 /* interrupt outputs */
218 { "nmi", NMI_PORT
, 0, output_port
, },
219 { "level", LEVEL_PORT
, 0, output_port
, },
221 /* interrupt ack (latch) input from cpu */
223 { "ack", ACK_PORT
, 0, input_port
, },
225 /* interrupt inputs (as names) */
227 { "nmirq", G0_PORT
+ 0, 0, input_port
, },
228 { "watchdog", G0_PORT
+ 1, 0, input_port
, },
229 { "syserr", G0_PORT
+ 2, 0, input_port
, },
231 { "timer-0-underflow", G2_PORT
, 0, input_port
, },
232 { "timer-1-underflow", G3_PORT
, 0, input_port
, },
233 { "timer-2-underflow", G4_PORT
, 0, input_port
, },
234 { "timer-3-underflow", G5_PORT
, 0, input_port
, },
235 { "timer-4-underflow", G6_PORT
, 0, input_port
, },
236 { "timer-5-underflow", G7_PORT
, 0, input_port
, },
237 { "timer-6-underflow", G8_PORT
, 0, input_port
, },
239 { "timer-6-compare-a", G9_PORT
, 0, input_port
, },
240 { "timer-6-compare-b", G10_PORT
, 0, input_port
, },
242 { "dma-0-end", G12_PORT
, 0, input_port
, },
243 { "dma-1-end", G13_PORT
, 0, input_port
, },
244 { "dma-2-end", G14_PORT
, 0, input_port
, },
245 { "dma-3-end", G15_PORT
, 0, input_port
, },
247 { "serial-0-receive", G16_PORT
, 0, input_port
, },
248 { "serial-0-transmit", G17_PORT
, 0, input_port
, },
250 { "serial-1-receive", G18_PORT
, 0, input_port
, },
251 { "serial-1-transmit", G19_PORT
, 0, input_port
, },
253 { "serial-2-receive", G20_PORT
, 0, input_port
, },
254 { "serial-2-transmit", G21_PORT
, 0, input_port
, },
256 { "irq-0", G23_PORT
, 0, input_port
, },
257 { "irq-1", G24_PORT
, 0, input_port
, },
258 { "irq-2", G25_PORT
, 0, input_port
, },
259 { "irq-3", G26_PORT
, 0, input_port
, },
260 { "irq-4", G27_PORT
, 0, input_port
, },
261 { "irq-5", G28_PORT
, 0, input_port
, },
262 { "irq-6", G29_PORT
, 0, input_port
, },
263 { "irq-7", G30_PORT
, 0, input_port
, },
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
;
295 static hw_ioctl_method mn103int_ioctl
;
300 attach_mn103int_regs (struct hw
*me
,
301 struct mn103int
*controller
)
304 if (hw_find_property (me
, "reg") == NULL
)
305 hw_abort (me
, "Missing \"reg\" property");
306 for (i
= 0; i
< NR_BLOCKS
; i
++)
308 unsigned_word attach_address
;
310 unsigned attach_size
;
311 reg_property_spec reg
;
312 if (!hw_find_reg_array_property (me
, "reg", i
, ®
))
313 hw_abort (me
, "\"reg\" property must contain three addr/size entries");
314 hw_unit_address_to_attach_address (hw_parent (me
),
319 controller
->block
[i
].base
= attach_address
;
320 hw_unit_size_to_attach_size (hw_parent (me
),
323 controller
->block
[i
].bound
= attach_address
+ (attach_size
- 1);
324 hw_attach_address (hw_parent (me
),
326 attach_space
, attach_address
, attach_size
,
332 mn103int_finish (struct hw
*me
)
335 struct mn103int
*controller
;
337 controller
= HW_ZALLOC (me
, struct mn103int
);
338 set_hw_data (me
, controller
);
339 set_hw_io_read_buffer (me
, mn103int_io_read_buffer
);
340 set_hw_io_write_buffer (me
, mn103int_io_write_buffer
);
341 set_hw_ports (me
, mn103int_ports
);
342 set_hw_port_event (me
, mn103int_port_event
);
343 me
->to_ioctl
= mn103int_ioctl
;
345 /* Attach ourself to our parent bus */
346 attach_mn103int_regs (me
, controller
);
348 /* Initialize all the groups according to their default configuration */
349 for (gid
= 0; gid
< NR_GROUPS
; gid
++)
351 struct mn103int_group
*group
= &controller
->group
[gid
];
352 group
->trigger
= NEGATIVE_EDGE
;
354 if (FIRST_NMI_GROUP
<= gid
&& gid
<= LAST_NMI_GROUP
)
357 group
->type
= NMI_GROUP
;
359 else if (FIRST_LEVEL_GROUP
<= gid
&& gid
<= LAST_LEVEL_GROUP
)
362 group
->type
= LEVEL_GROUP
;
365 hw_abort (me
, "internal error - unknown group id");
371 /* Perform the nasty work of figuring out which of the interrupt
372 groups should have its interrupt delivered. */
375 find_highest_interrupt_group (struct hw
*me
,
376 struct mn103int
*controller
)
381 /* FIRST_NMI_GROUP (group zero) is used as a special default value
382 when searching for an interrupt group.*/
383 selected
= FIRST_NMI_GROUP
;
384 controller
->group
[FIRST_NMI_GROUP
].level
= 7;
386 for (gid
= FIRST_LEVEL_GROUP
; gid
<= LAST_LEVEL_GROUP
; gid
++)
388 struct mn103int_group
*group
= &controller
->group
[gid
];
389 if ((group
->request
& group
->enable
) != 0)
391 /* Remember, lower level, higher priority. */
392 if (group
->level
< controller
->group
[selected
].level
)
402 /* Notify the processor of an interrupt level update */
405 push_interrupt_level (struct hw
*me
,
406 struct mn103int
*controller
)
408 int selected
= find_highest_interrupt_group (me
, controller
);
409 int level
= controller
->group
[selected
].level
;
410 HW_TRACE ((me
, "port-out - selected=%d level=%d", selected
, level
));
411 hw_port_event (me
, LEVEL_PORT
, level
);
415 /* An event arrives on an interrupt port */
418 mn103int_port_event (struct hw
*me
,
424 struct mn103int
*controller
= hw_data (me
);
431 int selected
= find_highest_interrupt_group (me
, controller
);
432 if (controller
->group
[selected
].level
!= level
)
433 hw_abort (me
, "botched level synchronisation");
434 controller
->interrupt_accepted_group
= selected
;
435 HW_TRACE ((me
, "port-event port=ack level=%d - selected=%d",
444 struct mn103int_group
*group
;
446 if (my_port
> NR_G_PORTS
)
447 hw_abort (me
, "Event on unknown port %d", my_port
);
449 /* map the port onto an interrupt group */
450 gid
= (my_port
% NR_G_PORTS
) / 4;
451 group
= &controller
->group
[gid
];
453 interrupt
= 1 << iid
;
455 /* update our cached input */
457 group
->input
|= interrupt
;
459 group
->input
&= ~interrupt
;
461 /* update the request bits */
462 switch (group
->trigger
)
467 group
->request
|= interrupt
;
471 group
->request
|= interrupt
;
474 /* force a corresponding output */
480 /* for NMI's the event is the trigger */
481 HW_TRACE ((me
, "port-in port=%d group=%d interrupt=%d - NMI",
483 if ((group
->request
& group
->enable
) != 0)
485 HW_TRACE ((me
, "port-out NMI"));
486 hw_port_event (me
, NMI_PORT
, 1);
493 /* if an interrupt is now pending */
494 HW_TRACE ((me
, "port-in port=%d group=%d interrupt=%d - INT",
496 push_interrupt_level (me
, controller
);
506 /* Read/write to to an ICR (group control register) */
508 static struct mn103int_group
*
509 decode_group (struct hw
*me
,
510 struct mn103int
*controller
,
512 unsigned_word
*offset
)
514 int gid
= (base
/ 4) % NR_GROUPS
;
515 *offset
= (base
% 4);
516 return &controller
->group
[gid
];
520 read_icr (struct hw
*me
,
521 struct mn103int
*controller
,
524 unsigned_word offset
;
525 struct mn103int_group
*group
= decode_group (me
, controller
, base
, &offset
);
534 val
= INSERT_ID (group
->request
);
535 HW_TRACE ((me
, "read-icr group=%d:0 nmi 0x%02x",
547 val
= (INSERT_IR (group
->request
)
548 | INSERT_ID (group
->request
& group
->enable
));
549 HW_TRACE ((me
, "read-icr group=%d:0 level 0x%02x",
553 val
= (INSERT_LV (group
->level
)
554 | INSERT_IE (group
->enable
));
555 HW_TRACE ((me
, "read-icr level-%d:1 level 0x%02x",
570 write_icr (struct hw
*me
,
571 struct mn103int
*controller
,
575 unsigned_word offset
;
576 struct mn103int_group
*group
= decode_group (me
, controller
, base
, &offset
);
584 HW_TRACE ((me
, "write-icr group=%d:0 nmi 0x%02x",
586 group
->request
&= ~EXTRACT_ID (val
);
596 case 0: /* request/detect */
597 /* Clear any ID bits and then set them according to IR */
598 HW_TRACE ((me
, "write-icr group=%d:0 level 0x%02x %x:%x:%x",
600 group
->request
, EXTRACT_IR (val
), EXTRACT_ID (val
)));
602 ((EXTRACT_IR (val
) & EXTRACT_ID (val
))
603 | (EXTRACT_IR (val
) & group
->request
)
604 | (~EXTRACT_IR (val
) & ~EXTRACT_ID (val
) & group
->request
));
606 case 1: /* level/enable */
607 HW_TRACE ((me
, "write-icr group=%d:1 level 0x%02x",
609 group
->level
= EXTRACT_LV (val
);
610 group
->enable
= EXTRACT_IE (val
);
616 push_interrupt_level (me
, controller
);
626 /* Read the IAGR (Interrupt accepted group register) */
629 read_iagr (struct hw
*me
,
630 struct mn103int
*controller
,
631 unsigned_word offset
)
638 if (!(controller
->group
[controller
->interrupt_accepted_group
].request
639 & controller
->group
[controller
->interrupt_accepted_group
].enable
))
641 /* oops, lost the request */
643 HW_TRACE ((me
, "read-iagr:0 lost-0"));
647 val
= (controller
->interrupt_accepted_group
<< 2);
648 HW_TRACE ((me
, "read-iagr:0 %d", (int) val
));
654 HW_TRACE ((me
, "read-iagr:1 %d", (int) val
));
658 HW_TRACE ((me
, "read-iagr 0x%08lx bad offset", (long) offset
));
665 /* Reads/writes to the EXTMD (external interrupt trigger configuration
668 static struct mn103int_group
*
669 external_group (struct mn103int
*controller
,
670 unsigned_word offset
)
675 return &controller
->group
[IRQ0_PORT
/4];
677 return &controller
->group
[IRQ4_PORT
/4];
684 read_extmd (struct hw
*me
,
685 struct mn103int
*controller
,
686 unsigned_word offset
)
690 struct mn103int_group
*group
= external_group (controller
, offset
);
693 for (gid
= 0; gid
< 4; gid
++)
695 val
|= (group
[gid
].trigger
<< (gid
* 2));
698 HW_TRACE ((me
, "read-extmd 0x%02lx", (long) val
));
703 write_extmd (struct hw
*me
,
704 struct mn103int
*controller
,
705 unsigned_word offset
,
709 struct mn103int_group
*group
= external_group (controller
, offset
);
712 for (gid
= 0; gid
< 4; gid
++)
714 group
[gid
].trigger
= (val
>> (gid
* 2)) & 0x3;
715 /* MAYBE: interrupts already pending? */
718 HW_TRACE ((me
, "write-extmd 0x%02lx", (long) val
));
722 /* generic read/write */
725 decode_addr (struct hw
*me
,
726 struct mn103int
*controller
,
727 unsigned_word address
,
728 unsigned_word
*offset
)
731 for (i
= 0; i
< NR_BLOCKS
; i
++)
733 if (address
>= controller
->block
[i
].base
734 && address
<= controller
->block
[i
].bound
)
736 *offset
= address
- controller
->block
[i
].base
;
740 hw_abort (me
, "bad address");
745 mn103int_io_read_buffer (struct hw
*me
,
751 struct mn103int
*controller
= hw_data (me
);
752 unsigned8
*buf
= dest
;
754 /* HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); */
755 for (byte
= 0; byte
< nr_bytes
; byte
++)
757 unsigned_word address
= base
+ byte
;
758 unsigned_word offset
;
759 switch (decode_addr (me
, controller
, address
, &offset
))
762 buf
[byte
] = read_icr (me
, controller
, offset
);
765 buf
[byte
] = read_iagr (me
, controller
, offset
);
768 buf
[byte
] = read_extmd (me
, controller
, offset
);
771 hw_abort (me
, "bad switch");
778 mn103int_io_write_buffer (struct hw
*me
,
784 struct mn103int
*controller
= hw_data (me
);
785 const unsigned8
*buf
= source
;
787 /* HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); */
788 for (byte
= 0; byte
< nr_bytes
; byte
++)
790 unsigned_word address
= base
+ byte
;
791 unsigned_word offset
;
792 switch (decode_addr (me
, controller
, address
, &offset
))
795 write_icr (me
, controller
, offset
, buf
[byte
]);
801 write_extmd (me
, controller
, offset
, buf
[byte
]);
804 hw_abort (me
, "bad switch");
811 mn103int_ioctl(struct hw
*me
,
812 hw_ioctl_request request
,
815 struct mn103int
*controller
= (struct mn103int
*)hw_data(me
);
816 controller
->group
[0].request
= EXTRACT_ID(4);
817 mn103int_port_event(me
, 2 /* nmi_port(syserr) */, NULL
, 0, 0);
821 const struct hw_descriptor dv_mn103int_descriptor
[] = {
822 { "mn103int", mn103int_finish
, },