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

Subversion Repositories openrisc

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

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 82 jeremybenn
#include "gpio.h"
44 19 jeremybenn
 
45
 
46
/*
47
 * The various VAPI IDs each GPIO device has
48
 */
49
enum
50
{ GPIO_VAPI_DATA = 0,
51
  GPIO_VAPI_AUX,
52
  GPIO_VAPI_CLOCK,
53
  GPIO_VAPI_RGPIO_OE,
54
  GPIO_VAPI_RGPIO_INTE,
55
  GPIO_VAPI_RGPIO_PTRIG,
56
  GPIO_VAPI_RGPIO_AUX,
57
  GPIO_VAPI_RGPIO_CTRL,
58
  GPIO_NUM_VAPI_IDS
59
};
60
 
61
/*
62
 * Implementatino of GPIO Code Registers and State
63
 */
64
struct gpio_device
65
{
66
  /* Is peripheral enabled */
67
  int enabled;
68
 
69
  /* Base address in memory */
70
  oraddr_t baseaddr;
71
 
72
  /* Which IRQ to generate */
73
  int irq;
74
 
75
  /* Which GPIO is this? */
76
  unsigned gpio_number;
77
 
78
  /* VAPI IDs */
79
  unsigned long base_vapi_id;
80
 
81
  /* Auxiliary inputs */
82
  unsigned long auxiliary_inputs;
83
 
84
  /* Visible registers */
85
  struct
86
  {
87
    unsigned long in;
88
    unsigned long out;
89
    unsigned long oe;
90
    unsigned long inte;
91
    unsigned long ptrig;
92
    unsigned long aux;
93
    unsigned long ctrl;
94
    unsigned long ints;
95
 
96
    int external_clock;
97
  } curr, next;
98
};
99
 
100
static void gpio_vapi_read (unsigned long id, unsigned long data, void *dat);
101
static void gpio_external_clock (unsigned long value,
102
                                 struct gpio_device *gpio);
103
static void gpio_device_clock (struct gpio_device *gpio);
104
static void gpio_clock (void *dat);
105
 
106
/* Initialize all parameters and state */
107
static void
108
gpio_reset (void *dat)
109
{
110
  struct gpio_device *gpio = dat;
111
 
112
  if (gpio->baseaddr != 0)
113
    {
114
      /* Possibly connect to VAPI */
115
      if (gpio->base_vapi_id)
116
        {
117
          vapi_install_multi_handler (gpio->base_vapi_id, GPIO_NUM_VAPI_IDS,
118
                                      gpio_vapi_read, dat);
119
        }
120
    }
121
  SCHED_ADD (gpio_clock, dat, 1);
122
}
123
 
124
 
125
/* Dump status */
126
static void
127
gpio_status (void *dat)
128
{
129
  struct gpio_device *gpio = dat;
130
 
131
  if (gpio->baseaddr == 0)
132
    return;
133
 
134
  PRINTF ("\nGPIO at 0x%" PRIxADDR ":\n", gpio->baseaddr);
135
  PRINTF ("RGPIO_IN     : 0x%08lX\n", gpio->curr.in);
136
  PRINTF ("RGPIO_OUT    : 0x%08lX\n", gpio->curr.out);
137
  PRINTF ("RGPIO_OE     : 0x%08lX\n", gpio->curr.oe);
138
  PRINTF ("RGPIO_INTE   : 0x%08lX\n", gpio->curr.inte);
139
  PRINTF ("RGPIO_PTRIG  : 0x%08lX\n", gpio->curr.ptrig);
140
  PRINTF ("RGPIO_AUX    : 0x%08lX\n", gpio->curr.aux);
141
  PRINTF ("RGPIO_CTRL   : 0x%08lX\n", gpio->curr.ctrl);
142
  PRINTF ("RGPIO_INTS   : 0x%08lX\n", gpio->curr.ints);
143
}
144
 
145
 
146
/* Wishbone read */
147
static uint32_t
148
gpio_read32 (oraddr_t addr, void *dat)
149
{
150
  struct gpio_device *gpio = dat;
151
 
152
  switch (addr)
153
    {
154
    case RGPIO_IN:
155
      return gpio->curr.in | gpio->curr.out;
156
    case RGPIO_OUT:
157
      return gpio->curr.out;
158
    case RGPIO_OE:
159
      return gpio->curr.oe;
160
    case RGPIO_INTE:
161
      return gpio->curr.inte;
162
    case RGPIO_PTRIG:
163
      return gpio->curr.ptrig;
164
    case RGPIO_AUX:
165
      return gpio->curr.aux;
166
    case RGPIO_CTRL:
167
      return gpio->curr.ctrl;
168
    case RGPIO_INTS:
169
      return gpio->curr.ints;
170
    }
171
 
172
  return 0;
173
}
174
 
175
 
176
/* Wishbone write */
177
static void
178
gpio_write32 (oraddr_t addr, uint32_t value, void *dat)
179
{
180
  struct gpio_device *gpio = dat;
181
 
182
  switch (addr)
183
    {
184
    case RGPIO_IN:
185
      break;
186
    case RGPIO_OUT:
187
      gpio->next.out = value;
188
      break;
189
    case RGPIO_OE:
190
      gpio->next.oe = value;
191
      break;
192
    case RGPIO_INTE:
193
      gpio->next.inte = value;
194
      break;
195
    case RGPIO_PTRIG:
196
      gpio->next.ptrig = value;
197
      break;
198
    case RGPIO_AUX:
199
      gpio->next.aux = value;
200
      break;
201
    case RGPIO_CTRL:
202
      gpio->next.ctrl = value;
203
      break;
204
    case RGPIO_INTS:
205
      if (gpio->next.ints && !value)
206
        clear_interrupt (gpio->irq);
207
      gpio->next.ints = value;
208
      break;
209
    }
210
}
211
 
212
 
213
/* Input from "outside world" */
214
static void
215
gpio_vapi_read (unsigned long id, unsigned long data, void *dat)
216
{
217
  unsigned which;
218
  struct gpio_device *gpio = dat;
219
 
220
  which = id - gpio->base_vapi_id;
221
 
222
  switch (which)
223
    {
224
    case GPIO_VAPI_DATA:
225
      gpio->next.in = data;
226
      break;
227
    case GPIO_VAPI_AUX:
228
      gpio->auxiliary_inputs = data;
229
      break;
230
    case GPIO_VAPI_RGPIO_OE:
231
      gpio->next.oe = data;
232
      break;
233
    case GPIO_VAPI_RGPIO_INTE:
234
      gpio->next.inte = data;
235
      break;
236
    case GPIO_VAPI_RGPIO_PTRIG:
237
      gpio->next.ptrig = data;
238
      break;
239
    case GPIO_VAPI_RGPIO_AUX:
240
      gpio->next.aux = data;
241
      break;
242
    case GPIO_VAPI_RGPIO_CTRL:
243
      gpio->next.ctrl = data;
244
      break;
245
    case GPIO_VAPI_CLOCK:
246
      gpio_external_clock (data, gpio);
247
      break;
248
    }
249
}
250
 
251
/* System Clock. */
252
static void
253
gpio_clock (void *dat)
254
{
255
  struct gpio_device *gpio = dat;
256
 
257
  /* Clock the device */
258
  if (!(gpio->curr.ctrl & RGPIO_CTRL_ECLK))
259
    gpio_device_clock (gpio);
260
  SCHED_ADD (gpio_clock, dat, 1);
261
}
262
 
263
/* External Clock. */
264
static void
265
gpio_external_clock (unsigned long value, struct gpio_device *gpio)
266
{
267
  int use_external_clock =
268
    ((gpio->curr.ctrl & RGPIO_CTRL_ECLK) == RGPIO_CTRL_ECLK);
269
  int negative_edge = ((gpio->curr.ctrl & RGPIO_CTRL_NEC) == RGPIO_CTRL_NEC);
270
 
271
  /* "Normalize" clock value */
272
  value = (value != 0);
273
 
274
  gpio->next.external_clock = value;
275
 
276
  if (use_external_clock
277
      && (gpio->next.external_clock != gpio->curr.external_clock)
278
      && (value != negative_edge))
279
    /* Make sure that in vapi_read, we don't clock the device */
280
    if (gpio->curr.ctrl & RGPIO_CTRL_ECLK)
281
      gpio_device_clock (gpio);
282
}
283
 
284
/* Report an interrupt to the sim */
285
static void
286
gpio_do_int (void *dat)
287
{
288
  struct gpio_device *gpio = dat;
289
 
290
  report_interrupt (gpio->irq);
291
}
292
 
293
/* Clock as handld by one device. */
294
static void
295
gpio_device_clock (struct gpio_device *gpio)
296
{
297
  /* Calculate new inputs and outputs */
298
  gpio->next.in &= ~gpio->next.oe;      /* Only input bits */
299
  /* Replace requested output bits with aux input */
300
  gpio->next.out =
301
    (gpio->next.out & ~gpio->next.aux) | (gpio->auxiliary_inputs & gpio->next.
302
                                          aux);
303
  gpio->next.out &= gpio->next.oe;      /* Only output-enabled bits */
304
 
305
  /* If any outputs changed, notify the world (i.e. vapi) */
306
  if (gpio->next.out != gpio->curr.out)
307
    {
308
      if (gpio->base_vapi_id)
309
        vapi_send (gpio->base_vapi_id + GPIO_VAPI_DATA, gpio->next.out);
310
    }
311
 
312
  /* If any inputs changed and interrupt enabled, generate interrupt */
313
  if (gpio->next.in != gpio->curr.in)
314
    {
315
      if (gpio->next.ctrl & RGPIO_CTRL_INTE)
316
        {
317
          unsigned changed_bits = gpio->next.in ^ gpio->curr.in;        /* inputs that have changed */
318
          unsigned set_bits = changed_bits & gpio->next.in;     /* inputs that have been set */
319
          unsigned cleared_bits = changed_bits & gpio->curr.in; /* inputs that have been cleared */
320
          unsigned relevant_bits =
321
            (gpio->next.ptrig & set_bits) | (~gpio->next.
322
                                             ptrig & cleared_bits);
323
 
324
          if (relevant_bits & gpio->next.inte)
325
            {
326
              gpio->next.ctrl |= RGPIO_CTRL_INTS;
327
              gpio->next.ints |= relevant_bits & gpio->next.inte;
328
              /* Since we can't report an interrupt during a readmem/writemem
329
               * schedule the scheduler to do it.  Read the comment above
330
               * report_interrupt in pic/pic.c */
331
              SCHED_ADD (gpio_do_int, gpio, 1);
332
            }
333
        }
334
    }
335
 
336
  /* Switch to values for next clock */
337
  memcpy (&(gpio->curr), &(gpio->next), sizeof (gpio->curr));
338
}
339
 
340
/*---------------------------------------------------[ GPIO configuration ]---*/
341
static void
342
gpio_baseaddr (union param_val val, void *dat)
343
{
344
  struct gpio_device *gpio = dat;
345
  gpio->baseaddr = val.addr_val;
346
}
347
 
348
static void
349
gpio_irq (union param_val val, void *dat)
350
{
351
  struct gpio_device *gpio = dat;
352
  gpio->irq = val.int_val;
353
}
354
 
355
static void
356
gpio_base_vapi_id (union param_val val, void *dat)
357
{
358
  struct gpio_device *gpio = dat;
359
  gpio->base_vapi_id = val.int_val;
360
}
361
 
362
static void
363
gpio_enabled (union param_val val, void *dat)
364
{
365
  struct gpio_device *gpio = dat;
366
  gpio->enabled = val.int_val;
367
}
368
 
369
static void *
370
gpio_sec_start (void)
371
{
372
  struct gpio_device *new = malloc (sizeof (struct gpio_device));
373
 
374
  if (!new)
375
    {
376
      fprintf (stderr, "Peripheral gpio: Run out of memory\n");
377
      exit (-1);
378
    }
379
 
380
  new->auxiliary_inputs = 0;
381
  memset (&new->curr, 0, sizeof (new->curr));
382
  memset (&new->next, 0, sizeof (new->next));
383
 
384
  new->enabled = 1;
385
  new->baseaddr = 0;
386
  new->irq = 0;
387
  new->base_vapi_id = 0;
388
 
389
  return new;
390
}
391
 
392
static void
393
gpio_sec_end (void *dat)
394
{
395
  struct gpio_device *gpio = dat;
396
  struct mem_ops ops;
397
 
398
  if (!gpio->enabled)
399
    {
400
      free (dat);
401
      return;
402
    }
403
 
404
  memset (&ops, 0, sizeof (struct mem_ops));
405
 
406
  ops.readfunc32 = gpio_read32;
407
  ops.writefunc32 = gpio_write32;
408
  ops.write_dat32 = dat;
409
  ops.read_dat32 = dat;
410
 
411
  /* FIXME: Correct delays? */
412
  ops.delayr = 2;
413
  ops.delayw = 2;
414
 
415
  /* Register memory range */
416
  reg_mem_area (gpio->baseaddr, GPIO_ADDR_SPACE, 0, &ops);
417
 
418
  reg_sim_reset (gpio_reset, dat);
419
  reg_sim_stat (gpio_status, dat);
420
}
421
 
422
void
423
reg_gpio_sec (void)
424
{
425
  struct config_section *sec =
426
    reg_config_sec ("gpio", gpio_sec_start, gpio_sec_end);
427
 
428 224 jeremybenn
  reg_config_param (sec, "enabled",      PARAMT_INT, gpio_enabled);
429
  reg_config_param (sec, "baseaddr",     PARAMT_ADDR, gpio_baseaddr);
430
  reg_config_param (sec, "irq",          PARAMT_INT, gpio_irq);
431
  reg_config_param (sec, "vapi_id",      PARAMT_INT, gpio_base_vapi_id);
432
  reg_config_param (sec, "base_vapi_id", PARAMT_INT, gpio_base_vapi_id);
433 19 jeremybenn
}

powered by: WebSVN 2.1.0

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