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

Subversion Repositories or1k

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

powered by: WebSVN 2.1.0

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