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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [sim/] [mips/] [dv-tx3904irc.c] - Blame information for rev 819

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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