OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [sim/] [mips/] [dv-tx3904irc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*  This file is part of the program GDB, the GNU debugger.
2
 
3
    Copyright (C) 1998 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 2 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, write to the Free Software
18
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
 
20
    */
21
 
22
 
23
#include "sim-main.h"
24
#include "hw-main.h"
25
 
26
 
27
/* DEVICE
28
 
29
 
30
   tx3904irc - tx3904 interrupt controller
31
 
32
 
33
   DESCRIPTION
34
 
35
 
36
   Implements the tx3904 interrupt controller described in the tx3904
37
   user guide.  It does not include the interrupt detection circuit
38
   that preprocesses the eight external interrupts, so assumes that
39
   each event on an input interrupt port signals a new interrupt.
40
   That is, it implements edge- rather than level-triggered
41
   interrupts.
42
 
43
   This implementation does not support multiple concurrent
44
   interrupts.
45
 
46
 
47
   PROPERTIES
48
 
49
 
50
   reg <base> <length>
51
 
52
   Base of IRC control register bank.  <length> must equal 0x20.
53
   Registers offsets:       0: ISR: interrupt status register
54
                            4: IMR: interrupt mask register
55
                           16: ILR0: interrupt level register 3..0
56
                           20: ILR1: interrupt level register 7..4
57
                           24: ILR2: interrupt level register 11..8
58
                           28: ILR3: interrupt level register 15..12
59
 
60
 
61
 
62
   PORTS
63
 
64
 
65
   ip (output)
66
 
67
   Interrupt priority port.  An event is generated when an interrupt
68
   of a sufficient priority is passed through the IRC.  The value
69
   associated with the event is the interrupt level (16-31), as given
70
   for bits IP[5:0] in the book TMPR3904F Rev. 2.0, pg. 11-3.  Note
71
   that even though INT[0] is tied externally to IP[5], we simulate
72
   it as passing through the controller.
73
 
74
   An output level of zero signals the clearing of a level interrupt.
75
 
76
 
77
   int0-7 (input)
78
 
79
   External interrupts.  Level = 0 -> level interrupt cleared.
80
 
81
 
82
   dmac0-3 (input)
83
 
84
   DMA internal interrupts, correspond to DMA channels 0-3.  Level = 0 -> level interrupt cleared.
85
 
86
 
87
   sio0-1 (input)
88
 
89
   SIO internal interrupts.  Level = 0 -> level interrupt cleared.
90
 
91
 
92
   tmr0-2 (input)
93
 
94
   Timer internal interrupts.  Level = 0 -> level interrupt cleared.
95
 
96
   */
97
 
98
 
99
 
100
 
101
 
102
/* register numbers; each is one word long */
103
enum
104
{
105
  ISR_REG = 0,
106
  IMR_REG = 1,
107
  ILR0_REG = 4,
108
  ILR1_REG = 5,
109
  ILR2_REG = 6,
110
  ILR3_REG = 7,
111
};
112
 
113
 
114
/* port ID's */
115
 
116
enum
117
{
118
  /* inputs, ordered to correspond to interrupt sources 0..15 */
119
  INT1_PORT = 0, INT2_PORT, INT3_PORT, INT4_PORT, INT5_PORT, INT6_PORT, INT7_PORT,
120
  DMAC3_PORT, DMAC2_PORT, DMAC1_PORT, DMAC0_PORT, SIO0_PORT, SIO1_PORT,
121
  TMR0_PORT, TMR1_PORT, TMR2_PORT,
122
 
123
  /* special INT[0] port */
124
  INT0_PORT,
125
 
126
  /* reset */
127
  RESET_PORT,
128
 
129
  /* output */
130
  IP_PORT
131
};
132
 
133
 
134
static const struct hw_port_descriptor tx3904irc_ports[] = {
135
 
136
  /* interrupt output */
137
 
138
  { "ip", IP_PORT, 0, output_port, },
139
 
140
  /* interrupt inputs (as names) */
141
  /* in increasing order of level number */
142
 
143
  { "int1", INT1_PORT, 0, input_port, },
144
  { "int2", INT2_PORT, 0, input_port, },
145
  { "int3", INT3_PORT, 0, input_port, },
146
  { "int4", INT4_PORT, 0, input_port, },
147
  { "int5", INT5_PORT, 0, input_port, },
148
  { "int6", INT6_PORT, 0, input_port, },
149
  { "int7", INT7_PORT, 0, input_port, },
150
 
151
  { "dmac3", DMAC3_PORT, 0, input_port, },
152
  { "dmac2", DMAC2_PORT, 0, input_port, },
153
  { "dmac1", DMAC1_PORT, 0, input_port, },
154
  { "dmac0", DMAC0_PORT, 0, input_port, },
155
 
156
  { "sio0", SIO0_PORT, 0, input_port, },
157
  { "sio1", SIO1_PORT, 0, input_port, },
158
 
159
  { "tmr0", TMR0_PORT, 0, input_port, },
160
  { "tmr1", TMR1_PORT, 0, input_port, },
161
  { "tmr2", TMR2_PORT, 0, input_port, },
162
 
163
  { "reset", RESET_PORT, 0, input_port, },
164
  { "int0", INT0_PORT, 0, input_port, },
165
 
166
  { NULL, },
167
};
168
 
169
 
170
#define NR_SOURCES (TMR3_PORT - INT1_PORT + 1) /* 16: number of interrupt sources */
171
 
172
 
173
/* The interrupt controller register internal state.  Note that we
174
   store state using the control register images, in host endian
175
   order. */
176
 
177
struct tx3904irc {
178
  address_word base_address; /* control register base */
179
  unsigned_4 isr;
180
#define ISR_SET(c,s) ((c)->isr &= ~ (1 << (s)))
181
  unsigned_4 imr;
182
#define IMR_GET(c) ((c)->imr)
183
  unsigned_4 ilr[4];
184
#define ILR_GET(c,s) LSEXTRACTED32((c)->ilr[(s)/4], (s) % 4 * 8 + 2, (s) % 4 * 8)
185
};
186
 
187
 
188
 
189
/* Finish off the partially created hw device.  Attach our local
190
   callbacks.  Wire up our port names etc */
191
 
192
static hw_io_read_buffer_method tx3904irc_io_read_buffer;
193
static hw_io_write_buffer_method tx3904irc_io_write_buffer;
194
static hw_port_event_method tx3904irc_port_event;
195
 
196
static void
197
attach_tx3904irc_regs (struct hw *me,
198
                      struct tx3904irc *controller)
199
{
200
  unsigned_word attach_address;
201
  int attach_space;
202
  unsigned attach_size;
203
  reg_property_spec reg;
204
 
205
  if (hw_find_property (me, "reg") == NULL)
206
    hw_abort (me, "Missing \"reg\" property");
207
 
208
  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
209
    hw_abort (me, "\"reg\" property must contain one addr/size entry");
210
 
211
  hw_unit_address_to_attach_address (hw_parent (me),
212
                                     &reg.address,
213
                                     &attach_space,
214
                                     &attach_address,
215
                                     me);
216
  hw_unit_size_to_attach_size (hw_parent (me),
217
                               &reg.size,
218
                               &attach_size, me);
219
 
220
  hw_attach_address (hw_parent (me), 0,
221
                     attach_space, attach_address, attach_size,
222
                     me);
223
 
224
  controller->base_address = attach_address;
225
}
226
 
227
 
228
static void
229
tx3904irc_finish (struct hw *me)
230
{
231
  struct tx3904irc *controller;
232
 
233
  controller = HW_ZALLOC (me, struct tx3904irc);
234
  set_hw_data (me, controller);
235
  set_hw_io_read_buffer (me, tx3904irc_io_read_buffer);
236
  set_hw_io_write_buffer (me, tx3904irc_io_write_buffer);
237
  set_hw_ports (me, tx3904irc_ports);
238
  set_hw_port_event (me, tx3904irc_port_event);
239
 
240
  /* Attach ourself to our parent bus */
241
  attach_tx3904irc_regs (me, controller);
242
 
243
  /* Initialize to reset state */
244
  controller->isr = 0x0000ffff;
245
  controller->imr = 0;
246
  controller->ilr[0] =
247
    controller->ilr[1] =
248
    controller->ilr[2] =
249
    controller->ilr[3] = 0;
250
}
251
 
252
 
253
 
254
/* An event arrives on an interrupt port */
255
 
256
static void
257
tx3904irc_port_event (struct hw *me,
258
                     int my_port,
259
                     struct hw *source_dev,
260
                     int source_port,
261
                     int level)
262
{
263
  struct tx3904irc *controller = hw_data (me);
264
 
265
  /* handle deactivated interrupt */
266
  if(level == 0)
267
    {
268
      HW_TRACE ((me, "interrupt cleared on port %d", my_port));
269
      hw_port_event(me, IP_PORT, 0);
270
      return;
271
    }
272
 
273
  switch (my_port)
274
    {
275
    case INT0_PORT:
276
      {
277
        int ip_number = 32; /* compute IP[5:0] */
278
        HW_TRACE ((me, "port-event INT[0]"));
279
        hw_port_event(me, IP_PORT, ip_number);
280
        break;
281
      }
282
 
283
    case INT1_PORT: case INT2_PORT: case INT3_PORT: case INT4_PORT:
284
    case INT5_PORT: case INT6_PORT: case INT7_PORT: case DMAC3_PORT:
285
    case DMAC2_PORT: case DMAC1_PORT: case DMAC0_PORT: case SIO0_PORT:
286
    case SIO1_PORT: case TMR0_PORT: case TMR1_PORT: case TMR2_PORT:
287
      {
288
        int source = my_port - INT1_PORT;
289
 
290
        HW_TRACE ((me, "interrupt asserted on port %d", source));
291
        ISR_SET(controller, source);
292
        if(ILR_GET(controller, source) > IMR_GET(controller))
293
          {
294
            int ip_number = 16 + source; /* compute IP[4:0] */
295
            HW_TRACE ((me, "interrupt level %d", ILR_GET(controller,source)));
296
            hw_port_event(me, IP_PORT, ip_number);
297
          }
298
        break;
299
      }
300
 
301
    case RESET_PORT:
302
      {
303
        HW_TRACE ((me, "reset"));
304
        controller->isr = 0x0000ffff;
305
        controller->imr = 0;
306
        controller->ilr[0] =
307
          controller->ilr[1] =
308
          controller->ilr[2] =
309
          controller->ilr[3] = 0;
310
        break;
311
      }
312
 
313
    case IP_PORT:
314
      hw_abort (me, "Event on output port %d", my_port);
315
      break;
316
 
317
    default:
318
      hw_abort (me, "Event on unknown port %d", my_port);
319
      break;
320
    }
321
}
322
 
323
 
324
/* generic read/write */
325
 
326
static unsigned
327
tx3904irc_io_read_buffer (struct hw *me,
328
                         void *dest,
329
                         int space,
330
                         unsigned_word base,
331
                         unsigned nr_bytes)
332
{
333
  struct tx3904irc *controller = hw_data (me);
334
  unsigned byte;
335
 
336
  HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
337
  for (byte = 0; byte < nr_bytes; byte++)
338
    {
339
      address_word address = base + byte;
340
      int reg_number = (address - controller->base_address) / 4;
341
      int reg_offset = (address - controller->base_address) % 4;
342
      unsigned_4 register_value; /* in target byte order */
343
 
344
      /* fill in entire register_value word */
345
      switch (reg_number)
346
        {
347
        case ISR_REG: register_value = controller->isr; break;
348
        case IMR_REG: register_value = controller->imr; break;
349
        case ILR0_REG: register_value = controller->ilr[0]; break;
350
        case ILR1_REG: register_value = controller->ilr[1]; break;
351
        case ILR2_REG: register_value = controller->ilr[2]; break;
352
        case ILR3_REG: register_value = controller->ilr[3]; break;
353
        default: register_value = 0;
354
        }
355
 
356
      /* write requested byte out */
357
      register_value = H2T_4(register_value);
358
      memcpy ((char*) dest + byte, ((char*)& register_value)+reg_offset, 1);
359
    }
360
 
361
  return nr_bytes;
362
}
363
 
364
 
365
 
366
static unsigned
367
tx3904irc_io_write_buffer (struct hw *me,
368
                          const void *source,
369
                          int space,
370
                          unsigned_word base,
371
                          unsigned nr_bytes)
372
{
373
  struct tx3904irc *controller = hw_data (me);
374
  unsigned byte;
375
 
376
  HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
377
  for (byte = 0; byte < nr_bytes; byte++)
378
    {
379
      address_word address = base + byte;
380
      int reg_number = (address - controller->base_address) / 4;
381
      int reg_offset = (address - controller->base_address) % 4;
382
      unsigned_4* register_ptr;
383
      unsigned_4 register_value;
384
 
385
      /* fill in entire register_value word */
386
      switch (reg_number)
387
        {
388
        case ISR_REG: register_ptr = & controller->isr; break;
389
        case IMR_REG: register_ptr = & controller->imr; break;
390
        case ILR0_REG: register_ptr = & controller->ilr[0]; break;
391
        case ILR1_REG: register_ptr = & controller->ilr[1]; break;
392
        case ILR2_REG: register_ptr = & controller->ilr[2]; break;
393
        case ILR3_REG: register_ptr = & controller->ilr[3]; break;
394
        default: register_ptr = & register_value; /* used as a dummy */
395
        }
396
 
397
      /* HW_TRACE ((me, "reg %d pre: %08lx", reg_number, (long) *register_ptr)); */
398
 
399
      /* overwrite requested byte */
400
      register_value = H2T_4(* register_ptr);
401
      memcpy (((char*)&register_value)+reg_offset, (const char*)source + byte, 1);
402
      * register_ptr = T2H_4(register_value);
403
 
404
      /* HW_TRACE ((me, "post: %08lx", (long) *register_ptr)); */
405
    }
406
  return nr_bytes;
407
}
408
 
409
 
410
const struct hw_descriptor dv_tx3904irc_descriptor[] = {
411
  { "tx3904irc", tx3904irc_finish, },
412
  { NULL },
413
};

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.