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.
28 mn103int - mn10300 interrupt controller
34 Implements the mn10300 interrupt controller described in the
41 reg = <icr-adr> <icr-siz> <iagr-adr> <iadr-siz> <extmd-adr> <extmd-siz>
43 Specify the address of the ICR (total of 25 registers), IAGR and
44 EXTMD registers (within the parent bus).
46 The reg property value `0x34000100 0x68 0x34000200 0x8 0x3400280
47 0x8' locates the interrupt controller at the addresses specified in
48 the mn10300 interrupt controller user guide.
56 Non-maskable interrupt output port. An event on this output ports
57 indicates a NMI request from the interrupt controller. The value
58 attached to the event should be ignored.
63 Maskable interrupt level output port. An event on this output port
64 indicates a maskable interrupt request at the specified level. The
65 event value defines the level being requested.
67 The interrupt controller will generate an event on this port
68 whenever there is a change to the internal state of the interrupt
74 Signal from processor indicating that a maskable interrupt has been
75 accepted and the interrupt controller should latch the IAGR with
76 value of the current highest priority interrupting group.
78 The event value is the interrupt level being accepted by the
79 processor. It should be consistent with the most recent LEVEL sent
80 to the processor from the interrupt controller.
85 Level or edge triggered interrupt input port. Each of the 25
86 groups (0..24) can have up to 4 (0..3) interrupt inputs. The
87 interpretation of a port event/value is determined by the
88 configuration of the corresponding interrupt group.
90 For convenience, numerous aliases to these interrupt inputs are
97 For edge triggered interrupts, the interrupt controller does not
98 differentiate between POSITIVE (rising) and NEGATIVE (falling)
99 edges. Instead any input port event is considered to be an
102 For level sensative interrupts, the interrupt controller ignores
103 active HIGH/LOW settings and instead always interprets a nonzero
104 port value as an interupt assertion and a zero port value as a
110 /* The interrupt groups - numbered according to mn10300 convention */
112 enum mn103int_trigger
{
124 struct mn103int_group
{
130 enum mn103int_trigger trigger
;
131 enum mn103int_type type
;
137 FIRST_LEVEL_GROUP
= 2,
138 LAST_LEVEL_GROUP
= 24,
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_method mn103int_io_read_buffer
;
306 static hw_io_write_buffer_method mn103int_io_write_buffer
;
307 static hw_port_event_method 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
;
364 if (FIRST_NMI_GROUP
<= gid
&& gid
<= LAST_NMI_GROUP
)
366 group
->type
= NMI_GROUP
;
368 else if (FIRST_LEVEL_GROUP
<= gid
&& gid
<= LAST_LEVEL_GROUP
)
370 group
->type
= LEVEL_GROUP
;
373 hw_abort (me
, "internal error - unknown group id");
379 /* Perform the nasty work of figuring out which of the interrupt
380 groups should have its interrupt delivered. */
383 find_highest_interrupt_group (struct hw
*me
,
384 struct mn103int
*controller
)
389 /* FIRST_NMI_GROUP (group zero) is used as a special default value
390 when searching for an interrupt group.*/
391 selected
= FIRST_NMI_GROUP
;
392 controller
->group
[FIRST_NMI_GROUP
].level
= 7;
394 for (gid
= FIRST_LEVEL_GROUP
; gid
<= LAST_LEVEL_GROUP
; gid
++)
396 struct mn103int_group
*group
= &controller
->group
[gid
];
397 if ((group
->request
& group
->enable
) != 0)
399 /* Remember, lower level, higher priority. */
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
);
423 /* An event arrives on an interrupt port */
426 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
, 1);
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) */
516 static struct mn103int_group
*
517 decode_group (struct hw
*me
,
518 struct mn103int
*controller
,
520 unsigned_word
*offset
)
522 int gid
= (base
/ 4) % NR_GROUPS
;
523 *offset
= (base
% 4);
524 return &controller
->group
[gid
];
528 read_icr (struct hw
*me
,
529 struct mn103int
*controller
,
532 unsigned_word offset
;
533 struct mn103int_group
*group
= decode_group (me
, controller
, base
, &offset
);
542 val
= INSERT_ID (group
->request
);
543 HW_TRACE ((me
, "read-icr group=%d:0 nmi 0x%02x",
555 val
= (INSERT_IR (group
->request
)
556 | INSERT_ID (group
->request
& group
->enable
));
557 HW_TRACE ((me
, "read-icr group=%d:0 level 0x%02x",
561 val
= (INSERT_LV (group
->level
)
562 | INSERT_IE (group
->enable
));
563 HW_TRACE ((me
, "read-icr level-%d:1 level 0x%02x",
578 write_icr (struct hw
*me
,
579 struct mn103int
*controller
,
583 unsigned_word offset
;
584 struct mn103int_group
*group
= decode_group (me
, controller
, base
, &offset
);
592 HW_TRACE ((me
, "write-icr group=%d:0 nmi 0x%02x",
594 group
->request
&= ~EXTRACT_ID (val
);
604 case 0: /* request/detect */
605 /* Clear any ID bits and then set them according to IR */
606 HW_TRACE ((me
, "write-icr group=%d:0 level 0x%02x %x:%x:%x",
608 group
->request
, EXTRACT_IR (val
), EXTRACT_ID (val
)));
610 ((EXTRACT_IR (val
) & EXTRACT_ID (val
))
611 | (EXTRACT_IR (val
) & group
->request
)
612 | (~EXTRACT_IR (val
) & ~EXTRACT_ID (val
) & group
->request
));
614 case 1: /* level/enable */
615 HW_TRACE ((me
, "write-icr group=%d:1 level 0x%02x",
617 group
->level
= EXTRACT_LV (val
);
618 group
->enable
= EXTRACT_IE (val
);
624 push_interrupt_level (me
, controller
);
634 /* Read the IAGR (Interrupt accepted group register) */
637 read_iagr (struct hw
*me
,
638 struct mn103int
*controller
,
639 unsigned_word offset
)
646 if (!(controller
->group
[controller
->interrupt_accepted_group
].request
647 & controller
->group
[controller
->interrupt_accepted_group
].enable
))
649 /* oops, lost the request */
651 HW_TRACE ((me
, "read-iagr:0 lost-0"));
655 val
= (controller
->interrupt_accepted_group
<< 2);
656 HW_TRACE ((me
, "read-iagr:0 %d", (int) val
));
662 HW_TRACE ((me
, "read-iagr:1 %d", (int) val
));
666 HW_TRACE ((me
, "read-iagr 0x%08lx bad offset", (long) offset
));
673 /* Reads/writes to the EXTMD (external interrupt trigger configuration
676 static struct mn103int_group
*
677 external_group (struct mn103int
*controller
,
678 unsigned_word offset
)
683 return &controller
->group
[16];
685 return &controller
->group
[20];
692 read_extmd (struct hw
*me
,
693 struct mn103int
*controller
,
694 unsigned_word offset
)
698 struct mn103int_group
*group
= external_group (controller
, offset
);
701 for (gid
= 0; gid
< 4; gid
++)
703 val
|= (group
[gid
].trigger
<< (gid
* 2));
706 HW_TRACE ((me
, "read-extmd 0x%02lx", (long) val
));
711 write_extmd (struct hw
*me
,
712 struct mn103int
*controller
,
713 unsigned_word offset
,
717 struct mn103int_group
*group
= external_group (controller
, offset
);
720 for (gid
= 0; gid
< 4; gid
++)
722 group
[gid
].trigger
= (val
>> (gid
* 2)) & 0x3;
723 /* MAYBE: interrupts already pending? */
726 HW_TRACE ((me
, "write-extmd 0x%02lx", (long) val
));
730 /* generic read/write */
733 decode_addr (struct hw
*me
,
734 struct mn103int
*controller
,
735 unsigned_word address
,
736 unsigned_word
*offset
)
739 for (i
= 0; i
< NR_BLOCKS
; i
++)
741 if (address
>= controller
->block
[i
].base
742 && address
<= controller
->block
[i
].bound
)
744 *offset
= address
- controller
->block
[i
].base
;
748 hw_abort (me
, "bad address");
753 mn103int_io_read_buffer (struct hw
*me
,
759 struct mn103int
*controller
= hw_data (me
);
760 unsigned8
*buf
= dest
;
762 /* HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); */
763 for (byte
= 0; byte
< nr_bytes
; byte
++)
765 unsigned_word address
= base
+ byte
;
766 unsigned_word offset
;
767 switch (decode_addr (me
, controller
, address
, &offset
))
770 buf
[byte
] = read_icr (me
, controller
, offset
);
773 buf
[byte
] = read_iagr (me
, controller
, offset
);
776 buf
[byte
] = read_extmd (me
, controller
, offset
);
779 hw_abort (me
, "bad switch");
786 mn103int_io_write_buffer (struct hw
*me
,
792 struct mn103int
*controller
= hw_data (me
);
793 const unsigned8
*buf
= source
;
795 /* HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); */
796 for (byte
= 0; byte
< nr_bytes
; byte
++)
798 unsigned_word address
= base
+ byte
;
799 unsigned_word offset
;
800 switch (decode_addr (me
, controller
, address
, &offset
))
803 write_icr (me
, controller
, offset
, buf
[byte
]);
809 write_extmd (me
, controller
, offset
, buf
[byte
]);
812 hw_abort (me
, "bad switch");
819 const struct hw_descriptor dv_mn103int_descriptor
[] = {
820 { "mn103int", mn103int_finish
, },