Updated copyright notices for most files.
[deliverable/binutils-gdb.git] / sim / mn10300 / dv-mn103int.c
... / ...
CommitLineData
1/* This file is part of the program GDB, the GNU debugger.
2
3 Copyright (C) 1998, 2007, 2008 Free Software Foundation, Inc.
4 Contributed by Cygnus Solutions.
5
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 3 of the License, or
9 (at your option) any later version.
10
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.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21
22#include "sim-main.h"
23#include "hw-main.h"
24#include "sim-hw.h"
25
26/* DEVICE
27
28
29 mn103int - mn103002 interrupt controller
30
31
32 DESCRIPTION
33
34
35 Implements the mn103002 interrupt controller described in the
36 mn103002 user guide.
37
38
39 PROPERTIES
40
41
42 reg = <icr-adr> <icr-siz> <iagr-adr> <iadr-siz> <extmd-adr> <extmd-siz>
43
44 Specify the address of the ICR (total of 30 registers), IAGR and
45 EXTMD registers (within the parent bus).
46
47 The reg property value `0x34000100 0x7C 0x34000200 0x8 0x3400280
48 0x8' locates the interrupt controller at the addresses specified in
49 the mn103002 interrupt controller user guide.
50
51
52 PORTS
53
54
55 nmi (output)
56
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.
60
61
62 level (output)
63
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.
67
68 The interrupt controller will generate an event on this port
69 whenever there is a change to the internal state of the interrupt
70 controller.
71
72
73 ack (input)
74
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.
78
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.
82
83
84 int[0..100] (input)
85
86 Level or edge triggered interrupt input port. Each of the 30
87 groups (0..30) 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.
90
91 For convenience, numerous aliases to these interrupt inputs are
92 provided.
93
94
95 BUGS
96
97
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
101 interrupt trigger.
102
103 For level sensitive interrupts, the interrupt controller ignores
104 active HIGH/LOW settings and instead always interprets a nonzero
105 port value as an interrupt assertion and a zero port value as a
106 negation.
107
108 */
109
110
111/* The interrupt groups - numbered according to mn103002 convention */
112
113enum mn103int_trigger {
114 ACTIVE_LOW,
115 ACTIVE_HIGH,
116 POSITIVE_EDGE,
117 NEGATIVE_EDGE,
118};
119
120enum mn103int_type {
121 NMI_GROUP,
122 LEVEL_GROUP,
123};
124
125struct mn103int_group {
126 int gid;
127 int level;
128 unsigned enable;
129 unsigned request;
130 unsigned input;
131 enum mn103int_trigger trigger;
132 enum mn103int_type type;
133};
134
135enum {
136 FIRST_NMI_GROUP = 0,
137 LAST_NMI_GROUP = 1,
138 FIRST_LEVEL_GROUP = 2,
139 LAST_LEVEL_GROUP = 30,
140 NR_GROUPS,
141};
142
143enum {
144 LOWEST_LEVEL = 7,
145};
146
147/* The interrupt controller register address blocks */
148
149struct mn103int_block {
150 unsigned_word base;
151 unsigned_word bound;
152};
153
154enum { ICR_BLOCK, IAGR_BLOCK, EXTMD_BLOCK, NR_BLOCKS };
155
156
157struct mn103int {
158 struct mn103int_block block[NR_BLOCKS];
159 struct mn103int_group group[NR_GROUPS];
160 unsigned interrupt_accepted_group;
161};
162
163
164
165/* output port ID's */
166
167enum {
168 NMI_PORT,
169 LEVEL_PORT,
170};
171
172
173/* input port ID's */
174
175enum {
176 G0_PORT = 0,
177 G1_PORT = 4,
178 G2_PORT = 8,
179 G3_PORT = 12,
180 G4_PORT = 16,
181 G5_PORT = 20,
182 G6_PORT = 24,
183 G7_PORT = 28,
184 G8_PORT = 32,
185 G9_PORT = 36,
186 G10_PORT = 40,
187 G11_PORT = 44,
188 G12_PORT = 48,
189 G13_PORT = 52,
190 G14_PORT = 56,
191 G15_PORT = 60,
192 G16_PORT = 64,
193 G17_PORT = 68,
194 G18_PORT = 72,
195 G19_PORT = 76,
196 G20_PORT = 80,
197 G21_PORT = 84,
198 G22_PORT = 88,
199 G23_PORT = 92,
200 IRQ0_PORT = G23_PORT,
201 G24_PORT = 96,
202 G25_PORT = 100,
203 G26_PORT = 104,
204 G27_PORT = 108,
205 IRQ4_PORT = G27_PORT,
206 G28_PORT = 112,
207 G29_PORT = 116,
208 G30_PORT = 120,
209 NR_G_PORTS = 124,
210 ACK_PORT,
211};
212
213static const struct hw_port_descriptor mn103int_ports[] = {
214
215 /* interrupt outputs */
216
217 { "nmi", NMI_PORT, 0, output_port, },
218 { "level", LEVEL_PORT, 0, output_port, },
219
220 /* interrupt ack (latch) input from cpu */
221
222 { "ack", ACK_PORT, 0, input_port, },
223
224 /* interrupt inputs (as names) */
225
226 { "nmirq", G0_PORT + 0, 0, input_port, },
227 { "watchdog", G0_PORT + 1, 0, input_port, },
228 { "syserr", G0_PORT + 2, 0, input_port, },
229
230 { "timer-0-underflow", G2_PORT, 0, input_port, },
231 { "timer-1-underflow", G3_PORT, 0, input_port, },
232 { "timer-2-underflow", G4_PORT, 0, input_port, },
233 { "timer-3-underflow", G5_PORT, 0, input_port, },
234 { "timer-4-underflow", G6_PORT, 0, input_port, },
235 { "timer-5-underflow", G7_PORT, 0, input_port, },
236 { "timer-6-underflow", G8_PORT, 0, input_port, },
237
238 { "timer-6-compare-a", G9_PORT, 0, input_port, },
239 { "timer-6-compare-b", G10_PORT, 0, input_port, },
240
241 { "dma-0-end", G12_PORT, 0, input_port, },
242 { "dma-1-end", G13_PORT, 0, input_port, },
243 { "dma-2-end", G14_PORT, 0, input_port, },
244 { "dma-3-end", G15_PORT, 0, input_port, },
245
246 { "serial-0-receive", G16_PORT, 0, input_port, },
247 { "serial-0-transmit", G17_PORT, 0, input_port, },
248
249 { "serial-1-receive", G18_PORT, 0, input_port, },
250 { "serial-1-transmit", G19_PORT, 0, input_port, },
251
252 { "serial-2-receive", G20_PORT, 0, input_port, },
253 { "serial-2-transmit", G21_PORT, 0, input_port, },
254
255 { "irq-0", G23_PORT, 0, input_port, },
256 { "irq-1", G24_PORT, 0, input_port, },
257 { "irq-2", G25_PORT, 0, input_port, },
258 { "irq-3", G26_PORT, 0, input_port, },
259 { "irq-4", G27_PORT, 0, input_port, },
260 { "irq-5", G28_PORT, 0, input_port, },
261 { "irq-6", G29_PORT, 0, input_port, },
262 { "irq-7", G30_PORT, 0, input_port, },
263
264 /* interrupt inputs (as generic numbers) */
265
266 { "int", 0, NR_G_PORTS, input_port, },
267
268 { NULL, },
269};
270
271
272/* Macros for extracting/restoring the various register bits */
273
274#define EXTRACT_ID(X) (LSEXTRACTED8 ((X), 3, 0))
275#define INSERT_ID(X) (LSINSERTED8 ((X), 3, 0))
276
277#define EXTRACT_IR(X) (LSEXTRACTED8 ((X), 7, 4))
278#define INSERT_IR(X) (LSINSERTED8 ((X), 7, 4))
279
280#define EXTRACT_IE(X) (LSEXTRACTED8 ((X), 3, 0))
281#define INSERT_IE(X) (LSINSERTED8 ((X), 3, 0))
282
283#define EXTRACT_LV(X) (LSEXTRACTED8 ((X), 6, 4))
284#define INSERT_LV(X) (LSINSERTED8 ((X), 6, 4))
285
286
287
288/* Finish off the partially created hw device. Attach our local
289 callbacks. Wire up our port names etc */
290
291static hw_io_read_buffer_method mn103int_io_read_buffer;
292static hw_io_write_buffer_method mn103int_io_write_buffer;
293static hw_port_event_method mn103int_port_event;
294static hw_ioctl_method mn103int_ioctl;
295
296
297
298static void
299attach_mn103int_regs (struct hw *me,
300 struct mn103int *controller)
301{
302 int i;
303 if (hw_find_property (me, "reg") == NULL)
304 hw_abort (me, "Missing \"reg\" property");
305 for (i = 0; i < NR_BLOCKS; i++)
306 {
307 unsigned_word attach_address;
308 int attach_space;
309 unsigned attach_size;
310 reg_property_spec reg;
311 if (!hw_find_reg_array_property (me, "reg", i, &reg))
312 hw_abort (me, "\"reg\" property must contain three addr/size entries");
313 hw_unit_address_to_attach_address (hw_parent (me),
314 &reg.address,
315 &attach_space,
316 &attach_address,
317 me);
318 controller->block[i].base = attach_address;
319 hw_unit_size_to_attach_size (hw_parent (me),
320 &reg.size,
321 &attach_size, me);
322 controller->block[i].bound = attach_address + (attach_size - 1);
323 hw_attach_address (hw_parent (me),
324 0,
325 attach_space, attach_address, attach_size,
326 me);
327 }
328}
329
330static void
331mn103int_finish (struct hw *me)
332{
333 int gid;
334 struct mn103int *controller;
335
336 controller = HW_ZALLOC (me, struct mn103int);
337 set_hw_data (me, controller);
338 set_hw_io_read_buffer (me, mn103int_io_read_buffer);
339 set_hw_io_write_buffer (me, mn103int_io_write_buffer);
340 set_hw_ports (me, mn103int_ports);
341 set_hw_port_event (me, mn103int_port_event);
342 me->to_ioctl = mn103int_ioctl;
343
344 /* Attach ourself to our parent bus */
345 attach_mn103int_regs (me, controller);
346
347 /* Initialize all the groups according to their default configuration */
348 for (gid = 0; gid < NR_GROUPS; gid++)
349 {
350 struct mn103int_group *group = &controller->group[gid];
351 group->trigger = NEGATIVE_EDGE;
352 group->gid = gid;
353 if (FIRST_NMI_GROUP <= gid && gid <= LAST_NMI_GROUP)
354 {
355 group->enable = 0xf;
356 group->type = NMI_GROUP;
357 }
358 else if (FIRST_LEVEL_GROUP <= gid && gid <= LAST_LEVEL_GROUP)
359 {
360 group->enable = 0x0;
361 group->type = LEVEL_GROUP;
362 }
363 else
364 hw_abort (me, "internal error - unknown group id");
365 }
366}
367
368
369
370/* Perform the nasty work of figuring out which of the interrupt
371 groups should have its interrupt delivered. */
372
373static int
374find_highest_interrupt_group (struct hw *me,
375 struct mn103int *controller)
376{
377 int gid;
378 int selected;
379
380 /* FIRST_NMI_GROUP (group zero) is used as a special default value
381 when searching for an interrupt group.*/
382 selected = FIRST_NMI_GROUP;
383 controller->group[FIRST_NMI_GROUP].level = 7;
384
385 for (gid = FIRST_LEVEL_GROUP; gid <= LAST_LEVEL_GROUP; gid++)
386 {
387 struct mn103int_group *group = &controller->group[gid];
388 if ((group->request & group->enable) != 0)
389 {
390 /* Remember, lower level, higher priority. */
391 if (group->level < controller->group[selected].level)
392 {
393 selected = gid;
394 }
395 }
396 }
397 return selected;
398}
399
400
401/* Notify the processor of an interrupt level update */
402
403static void
404push_interrupt_level (struct hw *me,
405 struct mn103int *controller)
406{
407 int selected = find_highest_interrupt_group (me, controller);
408 int level = controller->group[selected].level;
409 HW_TRACE ((me, "port-out - selected=%d level=%d", selected, level));
410 hw_port_event (me, LEVEL_PORT, level);
411}
412
413
414/* An event arrives on an interrupt port */
415
416static void
417mn103int_port_event (struct hw *me,
418 int my_port,
419 struct hw *source,
420 int source_port,
421 int level)
422{
423 struct mn103int *controller = hw_data (me);
424
425 switch (my_port)
426 {
427
428 case ACK_PORT:
429 {
430 int selected = find_highest_interrupt_group (me, controller);
431 if (controller->group[selected].level != level)
432 hw_abort (me, "botched level synchronisation");
433 controller->interrupt_accepted_group = selected;
434 HW_TRACE ((me, "port-event port=ack level=%d - selected=%d",
435 level, selected));
436 break;
437 }
438
439 default:
440 {
441 int gid;
442 int iid;
443 struct mn103int_group *group;
444 unsigned interrupt;
445 if (my_port > NR_G_PORTS)
446 hw_abort (me, "Event on unknown port %d", my_port);
447
448 /* map the port onto an interrupt group */
449 gid = (my_port % NR_G_PORTS) / 4;
450 group = &controller->group[gid];
451 iid = (my_port % 4);
452 interrupt = 1 << iid;
453
454 /* update our cached input */
455 if (level)
456 group->input |= interrupt;
457 else
458 group->input &= ~interrupt;
459
460 /* update the request bits */
461 switch (group->trigger)
462 {
463 case ACTIVE_LOW:
464 case ACTIVE_HIGH:
465 if (level)
466 group->request |= interrupt;
467 break;
468 case NEGATIVE_EDGE:
469 case POSITIVE_EDGE:
470 group->request |= interrupt;
471 }
472
473 /* force a corresponding output */
474 switch (group->type)
475 {
476
477 case NMI_GROUP:
478 {
479 /* for NMI's the event is the trigger */
480 HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - NMI",
481 my_port, gid, iid));
482 if ((group->request & group->enable) != 0)
483 {
484 HW_TRACE ((me, "port-out NMI"));
485 hw_port_event (me, NMI_PORT, 1);
486 }
487 break;
488 }
489
490 case LEVEL_GROUP:
491 {
492 /* if an interrupt is now pending */
493 HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - INT",
494 my_port, gid, iid));
495 push_interrupt_level (me, controller);
496 break;
497 }
498 }
499 break;
500 }
501
502 }
503}
504
505/* Read/write to to an ICR (group control register) */
506
507static struct mn103int_group *
508decode_group (struct hw *me,
509 struct mn103int *controller,
510 unsigned_word base,
511 unsigned_word *offset)
512{
513 int gid = (base / 4) % NR_GROUPS;
514 *offset = (base % 4);
515 return &controller->group[gid];
516}
517
518static unsigned8
519read_icr (struct hw *me,
520 struct mn103int *controller,
521 unsigned_word base)
522{
523 unsigned_word offset;
524 struct mn103int_group *group = decode_group (me, controller, base, &offset);
525 unsigned8 val = 0;
526 switch (group->type)
527 {
528
529 case NMI_GROUP:
530 switch (offset)
531 {
532 case 0:
533 val = INSERT_ID (group->request);
534 HW_TRACE ((me, "read-icr group=%d:0 nmi 0x%02x",
535 group->gid, val));
536 break;
537 default:
538 break;
539 }
540 break;
541
542 case LEVEL_GROUP:
543 switch (offset)
544 {
545 case 0:
546 val = (INSERT_IR (group->request)
547 | INSERT_ID (group->request & group->enable));
548 HW_TRACE ((me, "read-icr group=%d:0 level 0x%02x",
549 group->gid, val));
550 break;
551 case 1:
552 val = (INSERT_LV (group->level)
553 | INSERT_IE (group->enable));
554 HW_TRACE ((me, "read-icr level-%d:1 level 0x%02x",
555 group->gid, val));
556 break;
557 }
558 break;
559
560 default:
561 break;
562
563 }
564
565 return val;
566}
567
568static void
569write_icr (struct hw *me,
570 struct mn103int *controller,
571 unsigned_word base,
572 unsigned8 val)
573{
574 unsigned_word offset;
575 struct mn103int_group *group = decode_group (me, controller, base, &offset);
576 switch (group->type)
577 {
578
579 case NMI_GROUP:
580 switch (offset)
581 {
582 case 0:
583 HW_TRACE ((me, "write-icr group=%d:0 nmi 0x%02x",
584 group->gid, val));
585 group->request &= ~EXTRACT_ID (val);
586 break;
587 /* Special backdoor access to SYSEF flag from CPU. See
588 interp.c:program_interrupt(). */
589 case 3:
590 HW_TRACE ((me, "write-icr-special group=%d:0 nmi 0x%02x",
591 group->gid, val));
592 group->request |= EXTRACT_ID (val);
593 default:
594 break;
595 }
596 break;
597
598 case LEVEL_GROUP:
599 switch (offset)
600 {
601 case 0: /* request/detect */
602 /* Clear any ID bits and then set them according to IR */
603 HW_TRACE ((me, "write-icr group=%d:0 level 0x%02x %x:%x:%x",
604 group->gid, val,
605 group->request, EXTRACT_IR (val), EXTRACT_ID (val)));
606 group->request =
607 ((EXTRACT_IR (val) & EXTRACT_ID (val))
608 | (EXTRACT_IR (val) & group->request)
609 | (~EXTRACT_IR (val) & ~EXTRACT_ID (val) & group->request));
610 break;
611 case 1: /* level/enable */
612 HW_TRACE ((me, "write-icr group=%d:1 level 0x%02x",
613 group->gid, val));
614 group->level = EXTRACT_LV (val);
615 group->enable = EXTRACT_IE (val);
616 break;
617 default:
618 /* ignore */
619 break;
620 }
621 push_interrupt_level (me, controller);
622 break;
623
624 default:
625 break;
626
627 }
628}
629
630
631/* Read the IAGR (Interrupt accepted group register) */
632
633static unsigned8
634read_iagr (struct hw *me,
635 struct mn103int *controller,
636 unsigned_word offset)
637{
638 unsigned8 val;
639 switch (offset)
640 {
641 case 0:
642 {
643 if (!(controller->group[controller->interrupt_accepted_group].request
644 & controller->group[controller->interrupt_accepted_group].enable))
645 {
646 /* oops, lost the request */
647 val = 0;
648 HW_TRACE ((me, "read-iagr:0 lost-0"));
649 }
650 else
651 {
652 val = (controller->interrupt_accepted_group << 2);
653 HW_TRACE ((me, "read-iagr:0 %d", (int) val));
654 }
655 break;
656 }
657 case 1:
658 val = 0;
659 HW_TRACE ((me, "read-iagr:1 %d", (int) val));
660 break;
661 default:
662 val = 0;
663 HW_TRACE ((me, "read-iagr 0x%08lx bad offset", (long) offset));
664 break;
665 }
666 return val;
667}
668
669
670/* Reads/writes to the EXTMD (external interrupt trigger configuration
671 register) */
672
673static struct mn103int_group *
674external_group (struct mn103int *controller,
675 unsigned_word offset)
676{
677 switch (offset)
678 {
679 case 0:
680 return &controller->group[IRQ0_PORT/4];
681 case 1:
682 return &controller->group[IRQ4_PORT/4];
683 default:
684 return NULL;
685 }
686}
687
688static unsigned8
689read_extmd (struct hw *me,
690 struct mn103int *controller,
691 unsigned_word offset)
692{
693 int gid;
694 unsigned8 val = 0;
695 struct mn103int_group *group = external_group (controller, offset);
696 if (group != NULL)
697 {
698 for (gid = 0; gid < 4; gid++)
699 {
700 val |= (group[gid].trigger << (gid * 2));
701 }
702 }
703 HW_TRACE ((me, "read-extmd 0x%02lx", (long) val));
704 return val;
705}
706
707static void
708write_extmd (struct hw *me,
709 struct mn103int *controller,
710 unsigned_word offset,
711 unsigned8 val)
712{
713 int gid;
714 struct mn103int_group *group = external_group (controller, offset);
715 if (group != NULL)
716 {
717 for (gid = 0; gid < 4; gid++)
718 {
719 group[gid].trigger = (val >> (gid * 2)) & 0x3;
720 /* MAYBE: interrupts already pending? */
721 }
722 }
723 HW_TRACE ((me, "write-extmd 0x%02lx", (long) val));
724}
725
726
727/* generic read/write */
728
729static int
730decode_addr (struct hw *me,
731 struct mn103int *controller,
732 unsigned_word address,
733 unsigned_word *offset)
734{
735 int i;
736 for (i = 0; i < NR_BLOCKS; i++)
737 {
738 if (address >= controller->block[i].base
739 && address <= controller->block[i].bound)
740 {
741 *offset = address - controller->block[i].base;
742 return i;
743 }
744 }
745 hw_abort (me, "bad address");
746 return -1;
747}
748
749static unsigned
750mn103int_io_read_buffer (struct hw *me,
751 void *dest,
752 int space,
753 unsigned_word base,
754 unsigned nr_bytes)
755{
756 struct mn103int *controller = hw_data (me);
757 unsigned8 *buf = dest;
758 unsigned byte;
759 /* HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); */
760 for (byte = 0; byte < nr_bytes; byte++)
761 {
762 unsigned_word address = base + byte;
763 unsigned_word offset;
764 switch (decode_addr (me, controller, address, &offset))
765 {
766 case ICR_BLOCK:
767 buf[byte] = read_icr (me, controller, offset);
768 break;
769 case IAGR_BLOCK:
770 buf[byte] = read_iagr (me, controller, offset);
771 break;
772 case EXTMD_BLOCK:
773 buf[byte] = read_extmd (me, controller, offset);
774 break;
775 default:
776 hw_abort (me, "bad switch");
777 }
778 }
779 return nr_bytes;
780}
781
782static unsigned
783mn103int_io_write_buffer (struct hw *me,
784 const void *source,
785 int space,
786 unsigned_word base,
787 unsigned nr_bytes)
788{
789 struct mn103int *controller = hw_data (me);
790 const unsigned8 *buf = source;
791 unsigned byte;
792 /* HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); */
793 for (byte = 0; byte < nr_bytes; byte++)
794 {
795 unsigned_word address = base + byte;
796 unsigned_word offset;
797 switch (decode_addr (me, controller, address, &offset))
798 {
799 case ICR_BLOCK:
800 write_icr (me, controller, offset, buf[byte]);
801 break;
802 case IAGR_BLOCK:
803 /* not allowed */
804 break;
805 case EXTMD_BLOCK:
806 write_extmd (me, controller, offset, buf[byte]);
807 break;
808 default:
809 hw_abort (me, "bad switch");
810 }
811 }
812 return nr_bytes;
813}
814
815static int
816mn103int_ioctl(struct hw *me,
817 hw_ioctl_request request,
818 va_list ap)
819{
820 struct mn103int *controller = (struct mn103int *)hw_data(me);
821 controller->group[0].request = EXTRACT_ID(4);
822 mn103int_port_event(me, 2 /* nmi_port(syserr) */, NULL, 0, 0);
823 return 0;
824}
825
826
827const struct hw_descriptor dv_mn103int_descriptor[] = {
828 { "mn103int", mn103int_finish, },
829 { NULL },
830};
This page took 0.024512 seconds and 4 git commands to generate.