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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [peripheral/] [gpio.c] - Blame information for rev 72

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

Line No. Rev Author Line
1 19 jeremybenn
/* gpio.h -- GPIO code simulation
2
 
3
   Copyright (C) 2001 Erez Volk, erez@mailandnews.comopencores.org
4
   Copyright (C) 2008 Embecosm Limited
5
 
6
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
7
 
8
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
9
 
10
   This program is free software; you can redistribute it and/or modify it
11
   under the terms of the GNU General Public License as published by the Free
12
   Software Foundation; either version 3 of the License, or (at your option)
13
   any later version.
14
 
15
   This program is distributed in the hope that it will be useful, but WITHOUT
16
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18
   more details.
19
 
20
   You should have received a copy of the GNU General Public License along
21
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
 
23
/* This program is commented throughout in a fashion suitable for processing
24
   with Doxygen. */
25
 
26
 
27
/* Autoconf and/or portability configuration */
28
#include "config.h"
29
#include "port.h"
30
 
31
/* System includes */
32
#include <stdlib.h>
33
 
34
/* Package includes */
35
#include "sim-config.h"
36
#include "arch.h"
37
#include "vapi.h"
38
#include "sched.h"
39
#include "pic.h"
40
#include "abstract.h"
41
#include "toplevel-support.h"
42
#include "sim-cmd.h"
43
 
44
 
45
/* Address space required by one GPIO */
46
#define GPIO_ADDR_SPACE      0x20
47
 
48
/* Relative Register Addresses */
49
#define RGPIO_IN             0x00
50
#define RGPIO_OUT            0x04
51
#define RGPIO_OE             0x08
52
#define RGPIO_INTE           0x0C
53
#define RGPIO_PTRIG          0x10
54
#define RGPIO_AUX            0x14
55
#define RGPIO_CTRL           0x18
56
#define RGPIO_INTS           0x1C
57
 
58
/* Fields inside RGPIO_CTRL */
59
#define RGPIO_CTRL_ECLK      0x00000001
60
#define RGPIO_CTRL_NEC       0x00000002
61
#define RGPIO_CTRL_INTE      0x00000004
62
#define RGPIO_CTRL_INTS      0x00000008
63
 
64
 
65
/*
66
 * The various VAPI IDs each GPIO device has
67
 */
68
enum
69
{ GPIO_VAPI_DATA = 0,
70
  GPIO_VAPI_AUX,
71
  GPIO_VAPI_CLOCK,
72
  GPIO_VAPI_RGPIO_OE,
73
  GPIO_VAPI_RGPIO_INTE,
74
  GPIO_VAPI_RGPIO_PTRIG,
75
  GPIO_VAPI_RGPIO_AUX,
76
  GPIO_VAPI_RGPIO_CTRL,
77
  GPIO_NUM_VAPI_IDS
78
};
79
 
80
/*
81
 * Implementatino of GPIO Code Registers and State
82
 */
83
struct gpio_device
84
{
85
  /* Is peripheral enabled */
86
  int enabled;
87
 
88
  /* Base address in memory */
89
  oraddr_t baseaddr;
90
 
91
  /* Which IRQ to generate */
92
  int irq;
93
 
94
  /* Which GPIO is this? */
95
  unsigned gpio_number;
96
 
97
  /* VAPI IDs */
98
  unsigned long base_vapi_id;
99
 
100
  /* Auxiliary inputs */
101
  unsigned long auxiliary_inputs;
102
 
103
  /* Visible registers */
104
  struct
105
  {
106
    unsigned long in;
107
    unsigned long out;
108
    unsigned long oe;
109
    unsigned long inte;
110
    unsigned long ptrig;
111
    unsigned long aux;
112
    unsigned long ctrl;
113
    unsigned long ints;
114
 
115
    int external_clock;
116
  } curr, next;
117
};
118
 
119
static void gpio_vapi_read (unsigned long id, unsigned long data, void *dat);
120
static void gpio_external_clock (unsigned long value,
121
                                 struct gpio_device *gpio);
122
static void gpio_device_clock (struct gpio_device *gpio);
123
static void gpio_clock (void *dat);
124
 
125
/* Initialize all parameters and state */
126
static void
127
gpio_reset (void *dat)
128
{
129
  struct gpio_device *gpio = dat;
130
 
131
  if (gpio->baseaddr != 0)
132
    {
133
      /* Possibly connect to VAPI */
134
      if (gpio->base_vapi_id)
135
        {
136
          vapi_install_multi_handler (gpio->base_vapi_id, GPIO_NUM_VAPI_IDS,
137
                                      gpio_vapi_read, dat);
138
        }
139
    }
140
  SCHED_ADD (gpio_clock, dat, 1);
141
}
142
 
143
 
144
/* Dump status */
145
static void
146
gpio_status (void *dat)
147
{
148
  struct gpio_device *gpio = dat;
149
 
150
  if (gpio->baseaddr == 0)
151
    return;
152
 
153
  PRINTF ("\nGPIO at 0x%" PRIxADDR ":\n", gpio->baseaddr);
154
  PRINTF ("RGPIO_IN     : 0x%08lX\n", gpio->curr.in);
155
  PRINTF ("RGPIO_OUT    : 0x%08lX\n", gpio->curr.out);
156
  PRINTF ("RGPIO_OE     : 0x%08lX\n", gpio->curr.oe);
157
  PRINTF ("RGPIO_INTE   : 0x%08lX\n", gpio->curr.inte);
158
  PRINTF ("RGPIO_PTRIG  : 0x%08lX\n", gpio->curr.ptrig);
159
  PRINTF ("RGPIO_AUX    : 0x%08lX\n", gpio->curr.aux);
160
  PRINTF ("RGPIO_CTRL   : 0x%08lX\n", gpio->curr.ctrl);
161
  PRINTF ("RGPIO_INTS   : 0x%08lX\n", gpio->curr.ints);
162
}
163
 
164
 
165
/* Wishbone read */
166
static uint32_t
167
gpio_read32 (oraddr_t addr, void *dat)
168
{
169
  struct gpio_device *gpio = dat;
170
 
171
  switch (addr)
172
    {
173
    case RGPIO_IN:
174
      return gpio->curr.in | gpio->curr.out;
175
    case RGPIO_OUT:
176
      return gpio->curr.out;
177
    case RGPIO_OE:
178
      return gpio->curr.oe;
179
    case RGPIO_INTE:
180
      return gpio->curr.inte;
181
    case RGPIO_PTRIG:
182
      return gpio->curr.ptrig;
183
    case RGPIO_AUX:
184
      return gpio->curr.aux;
185
    case RGPIO_CTRL:
186
      return gpio->curr.ctrl;
187
    case RGPIO_INTS:
188
      return gpio->curr.ints;
189
    }
190
 
191
  return 0;
192
}
193
 
194
 
195
/* Wishbone write */
196
static void
197
gpio_write32 (oraddr_t addr, uint32_t value, void *dat)
198
{
199
  struct gpio_device *gpio = dat;
200
 
201
  switch (addr)
202
    {
203
    case RGPIO_IN:
204
      break;
205
    case RGPIO_OUT:
206
      gpio->next.out = value;
207
      break;
208
    case RGPIO_OE:
209
      gpio->next.oe = value;
210
      break;
211
    case RGPIO_INTE:
212
      gpio->next.inte = value;
213
      break;
214
    case RGPIO_PTRIG:
215
      gpio->next.ptrig = value;
216
      break;
217
    case RGPIO_AUX:
218
      gpio->next.aux = value;
219
      break;
220
    case RGPIO_CTRL:
221
      gpio->next.ctrl = value;
222
      break;
223
    case RGPIO_INTS:
224
      if (gpio->next.ints && !value)
225
        clear_interrupt (gpio->irq);
226
      gpio->next.ints = value;
227
      break;
228
    }
229
}
230
 
231
 
232
/* Input from "outside world" */
233
static void
234
gpio_vapi_read (unsigned long id, unsigned long data, void *dat)
235
{
236
  unsigned which;
237
  struct gpio_device *gpio = dat;
238
 
239
  which = id - gpio->base_vapi_id;
240
 
241
  switch (which)
242
    {
243
    case GPIO_VAPI_DATA:
244
      gpio->next.in = data;
245
      break;
246
    case GPIO_VAPI_AUX:
247
      gpio->auxiliary_inputs = data;
248
      break;
249
    case GPIO_VAPI_RGPIO_OE:
250
      gpio->next.oe = data;
251
      break;
252
    case GPIO_VAPI_RGPIO_INTE:
253
      gpio->next.inte = data;
254
      break;
255
    case GPIO_VAPI_RGPIO_PTRIG:
256
      gpio->next.ptrig = data;
257
      break;
258
    case GPIO_VAPI_RGPIO_AUX:
259
      gpio->next.aux = data;
260
      break;
261
    case GPIO_VAPI_RGPIO_CTRL:
262
      gpio->next.ctrl = data;
263
      break;
264
    case GPIO_VAPI_CLOCK:
265
      gpio_external_clock (data, gpio);
266
      break;
267
    }
268
}
269
 
270
/* System Clock. */
271
static void
272
gpio_clock (void *dat)
273
{
274
  struct gpio_device *gpio = dat;
275
 
276
  /* Clock the device */
277
  if (!(gpio->curr.ctrl & RGPIO_CTRL_ECLK))
278
    gpio_device_clock (gpio);
279
  SCHED_ADD (gpio_clock, dat, 1);
280
}
281
 
282
/* External Clock. */
283
static void
284
gpio_external_clock (unsigned long value, struct gpio_device *gpio)
285
{
286
  int use_external_clock =
287
    ((gpio->curr.ctrl & RGPIO_CTRL_ECLK) == RGPIO_CTRL_ECLK);
288
  int negative_edge = ((gpio->curr.ctrl & RGPIO_CTRL_NEC) == RGPIO_CTRL_NEC);
289
 
290
  /* "Normalize" clock value */
291
  value = (value != 0);
292
 
293
  gpio->next.external_clock = value;
294
 
295
  if (use_external_clock
296
      && (gpio->next.external_clock != gpio->curr.external_clock)
297
      && (value != negative_edge))
298
    /* Make sure that in vapi_read, we don't clock the device */
299
    if (gpio->curr.ctrl & RGPIO_CTRL_ECLK)
300
      gpio_device_clock (gpio);
301
}
302
 
303
/* Report an interrupt to the sim */
304
static void
305
gpio_do_int (void *dat)
306
{
307
  struct gpio_device *gpio = dat;
308
 
309
  report_interrupt (gpio->irq);
310
}
311
 
312
/* Clock as handld by one device. */
313
static void
314
gpio_device_clock (struct gpio_device *gpio)
315
{
316
  /* Calculate new inputs and outputs */
317
  gpio->next.in &= ~gpio->next.oe;      /* Only input bits */
318
  /* Replace requested output bits with aux input */
319
  gpio->next.out =
320
    (gpio->next.out & ~gpio->next.aux) | (gpio->auxiliary_inputs & gpio->next.
321
                                          aux);
322
  gpio->next.out &= gpio->next.oe;      /* Only output-enabled bits */
323
 
324
  /* If any outputs changed, notify the world (i.e. vapi) */
325
  if (gpio->next.out != gpio->curr.out)
326
    {
327
      if (gpio->base_vapi_id)
328
        vapi_send (gpio->base_vapi_id + GPIO_VAPI_DATA, gpio->next.out);
329
    }
330
 
331
  /* If any inputs changed and interrupt enabled, generate interrupt */
332
  if (gpio->next.in != gpio->curr.in)
333
    {
334
      if (gpio->next.ctrl & RGPIO_CTRL_INTE)
335
        {
336
          unsigned changed_bits = gpio->next.in ^ gpio->curr.in;        /* inputs that have changed */
337
          unsigned set_bits = changed_bits & gpio->next.in;     /* inputs that have been set */
338
          unsigned cleared_bits = changed_bits & gpio->curr.in; /* inputs that have been cleared */
339
          unsigned relevant_bits =
340
            (gpio->next.ptrig & set_bits) | (~gpio->next.
341
                                             ptrig & cleared_bits);
342
 
343
          if (relevant_bits & gpio->next.inte)
344
            {
345
              gpio->next.ctrl |= RGPIO_CTRL_INTS;
346
              gpio->next.ints |= relevant_bits & gpio->next.inte;
347
              /* Since we can't report an interrupt during a readmem/writemem
348
               * schedule the scheduler to do it.  Read the comment above
349
               * report_interrupt in pic/pic.c */
350
              SCHED_ADD (gpio_do_int, gpio, 1);
351
            }
352
        }
353
    }
354
 
355
  /* Switch to values for next clock */
356
  memcpy (&(gpio->curr), &(gpio->next), sizeof (gpio->curr));
357
}
358
 
359
/*---------------------------------------------------[ GPIO configuration ]---*/
360
static void
361
gpio_baseaddr (union param_val val, void *dat)
362
{
363
  struct gpio_device *gpio = dat;
364
  gpio->baseaddr = val.addr_val;
365
}
366
 
367
static void
368
gpio_irq (union param_val val, void *dat)
369
{
370
  struct gpio_device *gpio = dat;
371
  gpio->irq = val.int_val;
372
}
373
 
374
static void
375
gpio_base_vapi_id (union param_val val, void *dat)
376
{
377
  struct gpio_device *gpio = dat;
378
  gpio->base_vapi_id = val.int_val;
379
}
380
 
381
static void
382
gpio_enabled (union param_val val, void *dat)
383
{
384
  struct gpio_device *gpio = dat;
385
  gpio->enabled = val.int_val;
386
}
387
 
388
static void *
389
gpio_sec_start (void)
390
{
391
  struct gpio_device *new = malloc (sizeof (struct gpio_device));
392
 
393
  if (!new)
394
    {
395
      fprintf (stderr, "Peripheral gpio: Run out of memory\n");
396
      exit (-1);
397
    }
398
 
399
  new->auxiliary_inputs = 0;
400
  memset (&new->curr, 0, sizeof (new->curr));
401
  memset (&new->next, 0, sizeof (new->next));
402
 
403
  new->enabled = 1;
404
  new->baseaddr = 0;
405
  new->irq = 0;
406
  new->base_vapi_id = 0;
407
 
408
  return new;
409
}
410
 
411
static void
412
gpio_sec_end (void *dat)
413
{
414
  struct gpio_device *gpio = dat;
415
  struct mem_ops ops;
416
 
417
  if (!gpio->enabled)
418
    {
419
      free (dat);
420
      return;
421
    }
422
 
423
  memset (&ops, 0, sizeof (struct mem_ops));
424
 
425
  ops.readfunc32 = gpio_read32;
426
  ops.writefunc32 = gpio_write32;
427
  ops.write_dat32 = dat;
428
  ops.read_dat32 = dat;
429
 
430
  /* FIXME: Correct delays? */
431
  ops.delayr = 2;
432
  ops.delayw = 2;
433
 
434
  /* Register memory range */
435
  reg_mem_area (gpio->baseaddr, GPIO_ADDR_SPACE, 0, &ops);
436
 
437
  reg_sim_reset (gpio_reset, dat);
438
  reg_sim_stat (gpio_status, dat);
439
}
440
 
441
void
442
reg_gpio_sec (void)
443
{
444
  struct config_section *sec =
445
    reg_config_sec ("gpio", gpio_sec_start, gpio_sec_end);
446
 
447
  reg_config_param (sec, "enabled", paramt_int, gpio_enabled);
448
  reg_config_param (sec, "baseaddr", paramt_addr, gpio_baseaddr);
449
  reg_config_param (sec, "irq", paramt_int, gpio_irq);
450
  reg_config_param (sec, "vapi_id", paramt_int, gpio_base_vapi_id);
451
  reg_config_param (sec, "base_vapi_id", paramt_int, gpio_base_vapi_id);
452
}

powered by: WebSVN 2.1.0

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