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

Subversion Repositories or1k

[/] [or1k/] [tags/] [rel-0-3-0-rc3/] [or1ksim/] [peripheral/] [gpio.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 444 erez
/* gpio.h -- GPIO code simulation
2 1748 jeremybenn
 
3 444 erez
   Copyright (C) 2001 Erez Volk, erez@mailandnews.comopencores.org
4 1748 jeremybenn
   Copyright (C) 2008 Embecosm Limited
5 444 erez
 
6 1748 jeremybenn
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
7 444 erez
 
8 1748 jeremybenn
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
9 444 erez
 
10 1748 jeremybenn
   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 1350 nogj
#include "config.h"
29 1748 jeremybenn
#include "port.h"
30 1350 nogj
 
31 1748 jeremybenn
/* System includes */
32
#include <stdlib.h>
33 1350 nogj
 
34 1748 jeremybenn
/* Package includes */
35
#include "sim-config.h"
36 1350 nogj
#include "arch.h"
37 444 erez
#include "vapi.h"
38 1374 nogj
#include "sched.h"
39 1748 jeremybenn
#include "pic.h"
40
#include "abstract.h"
41
#include "toplevel-support.h"
42
#include "sim-cmd.h"
43 444 erez
 
44 1489 nogj
 
45 1748 jeremybenn
/* Address space required by one GPIO */
46
#define GPIO_ADDR_SPACE      0x20
47 1724 nogj
 
48 1748 jeremybenn
/* 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 1724 nogj
/*
66
 * The various VAPI IDs each GPIO device has
67
 */
68 1748 jeremybenn
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 1724 nogj
 
80
/*
81
 * Implementatino of GPIO Code Registers and State
82
 */
83 1748 jeremybenn
struct gpio_device
84 1724 nogj
{
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 1748 jeremybenn
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 444 erez
 
125
/* Initialize all parameters and state */
126 1748 jeremybenn
static void
127
gpio_reset (void *dat)
128 444 erez
{
129 1374 nogj
  struct gpio_device *gpio = dat;
130 444 erez
 
131 1748 jeremybenn
  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 444 erez
    }
140 1748 jeremybenn
  SCHED_ADD (gpio_clock, dat, 1);
141 444 erez
}
142
 
143
 
144
/* Dump status */
145 1748 jeremybenn
static void
146
gpio_status (void *dat)
147 444 erez
{
148 1374 nogj
  struct gpio_device *gpio = dat;
149 1748 jeremybenn
 
150
  if (gpio->baseaddr == 0)
151 1374 nogj
    return;
152 444 erez
 
153 1748 jeremybenn
  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 444 erez
}
163
 
164
 
165
/* Wishbone read */
166 1748 jeremybenn
static uint32_t
167
gpio_read32 (oraddr_t addr, void *dat)
168 444 erez
{
169 1374 nogj
  struct gpio_device *gpio = dat;
170 444 erez
 
171 1748 jeremybenn
  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 1374 nogj
 
191
  return 0;
192 444 erez
}
193
 
194
 
195
/* Wishbone write */
196 1748 jeremybenn
static void
197
gpio_write32 (oraddr_t addr, uint32_t value, void *dat)
198 444 erez
{
199 1374 nogj
  struct gpio_device *gpio = dat;
200 444 erez
 
201 1748 jeremybenn
  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 444 erez
}
230
 
231
 
232
/* Input from "outside world" */
233 1748 jeremybenn
static void
234
gpio_vapi_read (unsigned long id, unsigned long data, void *dat)
235 444 erez
{
236
  unsigned which;
237 1374 nogj
  struct gpio_device *gpio = dat;
238 444 erez
 
239 1374 nogj
  which = id - gpio->base_vapi_id;
240 444 erez
 
241 1748 jeremybenn
  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 1564 nogj
}
269 444 erez
 
270 1564 nogj
/* System Clock. */
271 1748 jeremybenn
static void
272
gpio_clock (void *dat)
273 1564 nogj
{
274
  struct gpio_device *gpio = dat;
275
 
276 1374 nogj
  /* Clock the device */
277 1748 jeremybenn
  if (!(gpio->curr.ctrl & RGPIO_CTRL_ECLK))
278
    gpio_device_clock (gpio);
279
  SCHED_ADD (gpio_clock, dat, 1);
280 444 erez
}
281
 
282
/* External Clock. */
283 1748 jeremybenn
static void
284
gpio_external_clock (unsigned long value, struct gpio_device *gpio)
285 444 erez
{
286 1748 jeremybenn
  int use_external_clock =
287
    ((gpio->curr.ctrl & RGPIO_CTRL_ECLK) == RGPIO_CTRL_ECLK);
288 1374 nogj
  int negative_edge = ((gpio->curr.ctrl & RGPIO_CTRL_NEC) == RGPIO_CTRL_NEC);
289 444 erez
 
290 477 erez
  /* "Normalize" clock value */
291 444 erez
  value = (value != 0);
292
 
293 1374 nogj
  gpio->next.external_clock = value;
294 1748 jeremybenn
 
295
  if (use_external_clock
296
      && (gpio->next.external_clock != gpio->curr.external_clock)
297
      && (value != negative_edge))
298 1374 nogj
    /* Make sure that in vapi_read, we don't clock the device */
299 1748 jeremybenn
    if (gpio->curr.ctrl & RGPIO_CTRL_ECLK)
300
      gpio_device_clock (gpio);
301 444 erez
}
302
 
303 1374 nogj
/* Report an interrupt to the sim */
304 1748 jeremybenn
static void
305
gpio_do_int (void *dat)
306 1374 nogj
{
307
  struct gpio_device *gpio = dat;
308 477 erez
 
309 1748 jeremybenn
  report_interrupt (gpio->irq);
310 1374 nogj
}
311
 
312 444 erez
/* Clock as handld by one device. */
313 1748 jeremybenn
static void
314
gpio_device_clock (struct gpio_device *gpio)
315 444 erez
{
316 445 erez
  /* Calculate new inputs and outputs */
317 1748 jeremybenn
  gpio->next.in &= ~gpio->next.oe;      /* Only input bits */
318 445 erez
  /* Replace requested output bits with aux input */
319 1748 jeremybenn
  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 444 erez
  /* If any outputs changed, notify the world (i.e. vapi) */
325 1748 jeremybenn
  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 445 erez
  /* If any inputs changed and interrupt enabled, generate interrupt */
332 1748 jeremybenn
  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 444 erez
    }
354 1748 jeremybenn
 
355 444 erez
  /* Switch to values for next clock */
356 1748 jeremybenn
  memcpy (&(gpio->curr), &(gpio->next), sizeof (gpio->curr));
357 444 erez
}
358 1358 nogj
 
359
/*---------------------------------------------------[ GPIO configuration ]---*/
360 1748 jeremybenn
static void
361
gpio_baseaddr (union param_val val, void *dat)
362 1358 nogj
{
363 1374 nogj
  struct gpio_device *gpio = dat;
364
  gpio->baseaddr = val.addr_val;
365 1358 nogj
}
366
 
367 1748 jeremybenn
static void
368
gpio_irq (union param_val val, void *dat)
369 1358 nogj
{
370 1374 nogj
  struct gpio_device *gpio = dat;
371
  gpio->irq = val.int_val;
372 1358 nogj
}
373
 
374 1748 jeremybenn
static void
375
gpio_base_vapi_id (union param_val val, void *dat)
376 1358 nogj
{
377 1374 nogj
  struct gpio_device *gpio = dat;
378
  gpio->base_vapi_id = val.int_val;
379 1358 nogj
}
380
 
381 1748 jeremybenn
static void
382
gpio_enabled (union param_val val, void *dat)
383 1461 nogj
{
384
  struct gpio_device *gpio = dat;
385
  gpio->enabled = val.int_val;
386
}
387
 
388 1748 jeremybenn
static void *
389
gpio_sec_start (void)
390 1374 nogj
{
391 1748 jeremybenn
  struct gpio_device *new = malloc (sizeof (struct gpio_device));
392 1374 nogj
 
393 1748 jeremybenn
  if (!new)
394
    {
395
      fprintf (stderr, "Peripheral gpio: Run out of memory\n");
396
      exit (-1);
397
    }
398 1374 nogj
 
399
  new->auxiliary_inputs = 0;
400 1748 jeremybenn
  memset (&new->curr, 0, sizeof (new->curr));
401
  memset (&new->next, 0, sizeof (new->next));
402 1374 nogj
 
403 1461 nogj
  new->enabled = 1;
404 1748 jeremybenn
  new->baseaddr = 0;
405
  new->irq = 0;
406
  new->base_vapi_id = 0;
407 1461 nogj
 
408 1374 nogj
  return new;
409
}
410
 
411 1748 jeremybenn
static void
412
gpio_sec_end (void *dat)
413 1374 nogj
{
414
  struct gpio_device *gpio = dat;
415 1486 nogj
  struct mem_ops ops;
416 1374 nogj
 
417 1748 jeremybenn
  if (!gpio->enabled)
418
    {
419
      free (dat);
420
      return;
421
    }
422 1461 nogj
 
423 1748 jeremybenn
  memset (&ops, 0, sizeof (struct mem_ops));
424 1486 nogj
 
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 1374 nogj
  /* Register memory range */
435 1748 jeremybenn
  reg_mem_area (gpio->baseaddr, GPIO_ADDR_SPACE, 0, &ops);
436 1374 nogj
 
437 1748 jeremybenn
  reg_sim_reset (gpio_reset, dat);
438
  reg_sim_stat (gpio_status, dat);
439 1374 nogj
}
440
 
441 1748 jeremybenn
void
442
reg_gpio_sec (void)
443 1358 nogj
{
444 1748 jeremybenn
  struct config_section *sec =
445
    reg_config_sec ("gpio", gpio_sec_start, gpio_sec_end);
446 1358 nogj
 
447 1748 jeremybenn
  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 1358 nogj
}

powered by: WebSVN 2.1.0

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