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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [sim/] [mips/] [dv-tx3904tmr.c] - Blame information for rev 866

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

Line No. Rev Author Line
1 330 jeremybenn
/*  This file is part of the program GDB, the GNU debugger.
2
 
3
    Copyright (C) 1998, 2007, 2008, 2009, 2010 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
   tx3904tmr - tx3904 timer
30
 
31
 
32
   DESCRIPTION
33
 
34
 
35
   Implements one tx3904 timer/counter described in the tx3904
36
   user guide.  Three instances are required for TMR0, TMR1, and
37
   TMR3 within the tx3904, at different base addresses.
38
 
39
   Both internal and system clocks are synthesized as divided versions
40
   of the simulator clock.
41
 
42
   There is no support for:
43
    - edge sensitivity of external clock
44
    - different mode restrictions for TMR0..2
45
    - level interrupts (interrupts are treated as events that occur at edges)
46
 
47
 
48
 
49
   PROPERTIES
50
 
51
 
52
   reg <base> <length>
53
 
54
   Base of TMR control register bank.  <length> must equal 0x100.
55
   Register offsets:       0: TCR: timer control  register
56
                           4: TISR: timer interrupt status register
57
                           8: CPRA: compare register A
58
                          12: CPRB: compare register B
59
                          16: ITMR: interval timer mode register
60
                          32: CCDR: divider register
61
                          48: PMGR: pulse generator mode register
62
                          64: WTMR: watchdog timer mode register
63
                         240: TRR: timer read register
64
 
65
 
66
   clock <ticks>
67
 
68
   Rate of timer clock signal.  This number is the number of simulator
69
   ticks per clock signal tick.  Default 1.
70
 
71
 
72
   ext <ticks>
73
 
74
   Rate of "external input clock signal", the other clock input of the
75
   timer.  It uses the same scale as above.  Default 100.
76
 
77
 
78
 
79
   PORTS
80
 
81
 
82
   int (output)
83
 
84
   Interrupt port.  An event is generated when a timer interrupt
85
   occurs.
86
 
87
 
88
   ff (output)
89
 
90
   Flip-flop output, corresponds to the TMFFOUT port.  An event is
91
   generated when flip-flop changes value.  The integer associated
92
   with the event is 1/0 according to flip-flop value.
93
 
94
 
95
   reset (input)
96
 
97
   Reset port.
98
 
99
   */
100
 
101
 
102
 
103
/* static functions */
104
 
105
static void deliver_tx3904tmr_tick (struct hw *me, void *data);
106
 
107
 
108
/* register numbers; each is one word long */
109
enum
110
{
111
  TCR_REG = 0,
112
  TISR_REG = 1,
113
  CPRA_REG = 2,
114
  CPRB_REG = 3,
115
  ITMR_REG = 4,
116
  CCDR_REG = 8,
117
  PMGR_REG = 12,
118
  WTMR_REG = 16,
119
  TRR_REG = 60
120
};
121
 
122
 
123
 
124
/* port ID's */
125
 
126
enum
127
 {
128
  RESET_PORT,
129
  INT_PORT,
130
  FF_PORT
131
};
132
 
133
 
134
static const struct hw_port_descriptor tx3904tmr_ports[] =
135
{
136
  { "int", INT_PORT, 0, output_port, },
137
  { "ff", FF_PORT, 0, output_port, },
138
  { "reset", RESET_PORT, 0, input_port, },
139
  { NULL, },
140
};
141
 
142
 
143
 
144
/* The timer/counter register internal state.  Note that we store
145
   state using the control register images, in host endian order. */
146
 
147
struct tx3904tmr {
148
  address_word base_address; /* control register base */
149
  unsigned_4 clock_ticks, ext_ticks; /* clock frequencies */
150
  signed_8 last_ticks; /* time at last deliver_*_tick call */
151
  signed_8 roundoff_ticks; /* sim ticks unprocessed during last tick call */
152
  int ff; /* pulse generator flip-flop value: 1/0 */
153
  struct hw_event* event; /* last scheduled event */
154
 
155
  unsigned_4 tcr;
156
#define GET_TCR_TCE(c)      (((c)->tcr & 0x80) >> 7)
157
#define GET_TCR_CCDE(c)     (((c)->tcr & 0x40) >> 6)
158
#define GET_TCR_CRE(c)      (((c)->tcr & 0x20) >> 5)
159
#define GET_TCR_CCS(c)      (((c)->tcr & 0x04) >> 2)
160
#define GET_TCR_TMODE(c)    (((c)->tcr & 0x03) >> 0)
161
  unsigned_4 tisr;
162
#define SET_TISR_TWIS(c)    ((c)->tisr |= 0x08)
163
#define SET_TISR_TPIBS(c)   ((c)->tisr |= 0x04)
164
#define SET_TISR_TPIAS(c)   ((c)->tisr |= 0x02)
165
#define SET_TISR_TIIS(c)    ((c)->tisr |= 0x01)
166
  unsigned_4 cpra;
167
  unsigned_4 cprb;
168
  unsigned_4 itmr;
169
#define GET_ITMR_TIIE(c)    (((c)->itmr & 0x8000) >> 15)
170
#define SET_ITMR_TIIE(c,v)  BLIT32((c)->itmr, 15, (v) ? 1 : 0)
171
#define GET_ITMR_TZCE(c)    (((c)->itmr & 0x0001) >> 0)
172
#define SET_ITMR_TZCE(c,v)  BLIT32((c)->itmr, 0, (v) ? 1 : 0)
173
  unsigned_4 ccdr;
174
#define GET_CCDR_CDR(c)     (((c)->ccdr & 0x07) >> 0)
175
  unsigned_4 pmgr;
176
#define GET_PMGR_TPIBE(c)   (((c)->pmgr & 0x8000) >> 15)
177
#define SET_PMGR_TPIBE(c,v) BLIT32((c)->pmgr, 15, (v) ? 1 : 0)
178
#define GET_PMGR_TPIAE(c)   (((c)->pmgr & 0x4000) >> 14)
179
#define SET_PMGR_TPIAE(c,v) BLIT32((c)->pmgr, 14, (v) ? 1 : 0)
180
#define GET_PMGR_FFI(c)     (((c)->pmgr & 0x0001) >> 0)
181
#define SET_PMGR_FFI(c,v)   BLIT32((c)->pmgr, 0, (v) ? 1 : 0)
182
  unsigned_4 wtmr;
183
#define GET_WTMR_TWIE(c)    (((c)->wtmr & 0x8000) >> 15)
184
#define SET_WTMR_TWIE(c,v)  BLIT32((c)->wtmr, 15, (v) ? 1 : 0)
185
#define GET_WTMR_WDIS(c)    (((c)->wtmr & 0x0080) >> 7)
186
#define SET_WTMR_WDIS(c,v)  BLIT32((c)->wtmr, 7, (v) ? 1 : 0)
187
#define GET_WTMR_TWC(c)     (((c)->wtmr & 0x0001) >> 0)
188
#define SET_WTMR_TWC(c,v)   BLIT32((c)->wtmr, 0, (v) ? 1 : 0)
189
  unsigned_4 trr;
190
};
191
 
192
 
193
 
194
/* Finish off the partially created hw device.  Attach our local
195
   callbacks.  Wire up our port names etc */
196
 
197
static hw_io_read_buffer_method tx3904tmr_io_read_buffer;
198
static hw_io_write_buffer_method tx3904tmr_io_write_buffer;
199
static hw_port_event_method tx3904tmr_port_event;
200
 
201
static void
202
attach_tx3904tmr_regs (struct hw *me,
203
                      struct tx3904tmr *controller)
204
{
205
  unsigned_word attach_address;
206
  int attach_space;
207
  unsigned attach_size;
208
  reg_property_spec reg;
209
 
210
  if (hw_find_property (me, "reg") == NULL)
211
    hw_abort (me, "Missing \"reg\" property");
212
 
213
  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
214
    hw_abort (me, "\"reg\" property must contain one addr/size entry");
215
 
216
  hw_unit_address_to_attach_address (hw_parent (me),
217
                                     &reg.address,
218
                                     &attach_space,
219
                                     &attach_address,
220
                                     me);
221
  hw_unit_size_to_attach_size (hw_parent (me),
222
                               &reg.size,
223
                               &attach_size, me);
224
 
225
  hw_attach_address (hw_parent (me), 0,
226
                     attach_space, attach_address, attach_size,
227
                     me);
228
 
229
  if(hw_find_property(me, "clock") != NULL)
230
    controller->clock_ticks = (unsigned_4) hw_find_integer_property(me, "clock");
231
 
232
  if(hw_find_property(me, "ext") != NULL)
233
    controller->ext_ticks = (unsigned_4) hw_find_integer_property(me, "ext");
234
 
235
  controller->base_address = attach_address;
236
}
237
 
238
 
239
static void
240
tx3904tmr_finish (struct hw *me)
241
{
242
  struct tx3904tmr *controller;
243
 
244
  controller = HW_ZALLOC (me, struct tx3904tmr);
245
  set_hw_data (me, controller);
246
  set_hw_io_read_buffer (me, tx3904tmr_io_read_buffer);
247
  set_hw_io_write_buffer (me, tx3904tmr_io_write_buffer);
248
  set_hw_ports (me, tx3904tmr_ports);
249
  set_hw_port_event (me, tx3904tmr_port_event);
250
 
251
  /* Preset clock dividers */
252
  controller->clock_ticks = 1;
253
  controller->ext_ticks = 100;
254
 
255
  /* Attach ourself to our parent bus */
256
  attach_tx3904tmr_regs (me, controller);
257
 
258
  /* Initialize to reset state */
259
  controller->tcr =
260
    controller->itmr =
261
    controller->ccdr =
262
    controller->pmgr =
263
    controller->wtmr =
264
    controller->tisr =
265
    controller->trr = 0;
266
  controller->cpra = controller->cprb = 0x00FFFFFF;
267
  controller->ff = 0;
268
  controller->last_ticks = controller->roundoff_ticks = 0;
269
  controller->event = NULL;
270
}
271
 
272
 
273
 
274
/* An event arrives on an interrupt port */
275
 
276
static void
277
tx3904tmr_port_event (struct hw *me,
278
                     int my_port,
279
                     struct hw *source,
280
                     int source_port,
281
                     int level)
282
{
283
  struct tx3904tmr *controller = hw_data (me);
284
 
285
  switch (my_port)
286
    {
287
    case RESET_PORT:
288
      {
289
        HW_TRACE ((me, "reset"));
290
 
291
        /* preset flip-flop to FFI value */
292
        controller->ff = GET_PMGR_FFI(controller);
293
 
294
        controller->tcr =
295
          controller->itmr =
296
          controller->ccdr =
297
          controller->pmgr =
298
          controller->wtmr =
299
          controller->tisr =
300
          controller->trr = 0;
301
        controller->cpra = controller->cprb = 0x00FFFFFF;
302
        controller->last_ticks = controller->roundoff_ticks = 0;
303
        if(controller->event != NULL)
304
          hw_event_queue_deschedule(me, controller->event);
305
        controller->event = NULL;
306
        break;
307
      }
308
 
309
    default:
310
      hw_abort (me, "Event on unknown port %d", my_port);
311
      break;
312
    }
313
}
314
 
315
 
316
/* generic read/write */
317
 
318
static unsigned
319
tx3904tmr_io_read_buffer (struct hw *me,
320
                         void *dest,
321
                         int space,
322
                         unsigned_word base,
323
                         unsigned nr_bytes)
324
{
325
  struct tx3904tmr *controller = hw_data (me);
326
  unsigned byte;
327
 
328
  HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
329
  for (byte = 0; byte < nr_bytes; byte++)
330
    {
331
      address_word address = base + byte;
332
      int reg_number = (address - controller->base_address) / 4;
333
      int reg_offset = 3 - (address - controller->base_address) % 4;
334
      unsigned_4 register_value; /* in target byte order */
335
 
336
      /* fill in entire register_value word */
337
      switch (reg_number)
338
        {
339
        case TCR_REG: register_value = controller->tcr; break;
340
        case TISR_REG: register_value = controller->tisr; break;
341
        case CPRA_REG: register_value = controller->cpra; break;
342
        case CPRB_REG: register_value = controller->cprb; break;
343
        case ITMR_REG: register_value = controller->itmr; break;
344
        case CCDR_REG: register_value = controller->ccdr; break;
345
        case PMGR_REG: register_value = controller->pmgr; break;
346
        case WTMR_REG: register_value = controller->wtmr; break;
347
        case TRR_REG: register_value = controller->trr; break;
348
        default: register_value = 0;
349
        }
350
 
351
      /* write requested byte out */
352
      memcpy ((char*) dest + byte, ((char*)& register_value)+reg_offset, 1);
353
    }
354
 
355
  return nr_bytes;
356
}
357
 
358
 
359
 
360
static unsigned
361
tx3904tmr_io_write_buffer (struct hw *me,
362
                          const void *source,
363
                          int space,
364
                          unsigned_word base,
365
                          unsigned nr_bytes)
366
{
367
  struct tx3904tmr *controller = hw_data (me);
368
  unsigned byte;
369
 
370
  HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
371
  for (byte = 0; byte < nr_bytes; byte++)
372
    {
373
      address_word address = base + byte;
374
      unsigned_1 write_byte = ((const char*) source)[byte];
375
      int reg_number = (address - controller->base_address) / 4;
376
      int reg_offset = 3 - (address - controller->base_address) % 4;
377
 
378
      /* fill in entire register_value word */
379
      switch (reg_number)
380
        {
381
        case TCR_REG:
382
          if(reg_offset == 0) /* first byte */
383
            {
384
              /* update register, but mask out NOP bits */
385
              controller->tcr = (unsigned_4) (write_byte & 0xef);
386
 
387
              /* Reset counter value if timer suspended and CRE is set. */
388
              if(GET_TCR_TCE(controller) == 0 &&
389
                 GET_TCR_CRE(controller) == 1)
390
                controller->trr = 0;
391
            }
392
          /* HW_TRACE ((me, "tcr: %08lx", (long) controller->tcr)); */
393
          break;
394
 
395
        case ITMR_REG:
396
          if(reg_offset == 1) /* second byte */
397
            {
398
              SET_ITMR_TIIE(controller, write_byte & 0x80);
399
            }
400
          else if(reg_offset == 0) /* first byte */
401
            {
402
              SET_ITMR_TZCE(controller, write_byte & 0x01);
403
            }
404
          /* HW_TRACE ((me, "itmr: %08lx", (long) controller->itmr)); */
405
          break;
406
 
407
        case CCDR_REG:
408
          if(reg_offset == 0) /* first byte */
409
            {
410
              controller->ccdr = write_byte & 0x07;
411
            }
412
          /* HW_TRACE ((me, "ccdr: %08lx", (long) controller->ccdr)); */
413
          break;
414
 
415
        case PMGR_REG:
416
          if(reg_offset == 1) /* second byte */
417
            {
418
              SET_PMGR_TPIBE(controller, write_byte & 0x80);
419
              SET_PMGR_TPIAE(controller, write_byte & 0x40);
420
            }
421
          else if(reg_offset == 0) /* first byte */
422
            {
423
              SET_PMGR_FFI(controller, write_byte & 0x01);
424
            }
425
          /* HW_TRACE ((me, "pmgr: %08lx", (long) controller->pmgr)); */
426
          break;
427
 
428
        case WTMR_REG:
429
          if(reg_offset == 1) /* second byte */
430
            {
431
              SET_WTMR_TWIE(controller, write_byte & 0x80);
432
            }
433
          else if(reg_offset == 0) /* first byte */
434
            {
435
              SET_WTMR_WDIS(controller, write_byte & 0x80);
436
              SET_WTMR_TWC(controller, write_byte & 0x01);
437
            }
438
          /* HW_TRACE ((me, "wtmr: %08lx", (long) controller->wtmr)); */
439
          break;
440
 
441
        case TISR_REG:
442
          if(reg_offset == 0) /* first byte */
443
            {
444
              /* All bits must be zero in given byte, according to
445
                 spec. */
446
 
447
              /* Send an "interrupt off" event on the interrupt port */
448
              if(controller->tisr != 0) /* any interrupts active? */
449
                {
450
                  hw_port_event(me, INT_PORT, 0);
451
                }
452
 
453
              /* clear interrupt status register */
454
              controller->tisr = 0;
455
            }
456
          /* HW_TRACE ((me, "tisr: %08lx", (long) controller->tisr)); */
457
          break;
458
 
459
        case CPRA_REG:
460
          if(reg_offset < 3) /* first, second, or third byte */
461
            {
462
              MBLIT32(controller->cpra, (reg_offset*8)+7, (reg_offset*8), write_byte);
463
            }
464
          /* HW_TRACE ((me, "cpra: %08lx", (long) controller->cpra)); */
465
          break;
466
 
467
        case CPRB_REG:
468
          if(reg_offset < 3) /* first, second, or third byte */
469
            {
470
              MBLIT32(controller->cprb, (reg_offset*8)+7, (reg_offset*8), write_byte);
471
            }
472
          /* HW_TRACE ((me, "cprb: %08lx", (long) controller->cprb)); */
473
          break;
474
 
475
        default:
476
          HW_TRACE ((me, "write to illegal register %d", reg_number));
477
        }
478
    } /* loop over bytes */
479
 
480
  /* Schedule a timer event in near future, so we can increment or
481
     stop the counter, to respond to register updates. */
482
  hw_event_queue_schedule(me, 1, deliver_tx3904tmr_tick, NULL);
483
 
484
  return nr_bytes;
485
}
486
 
487
 
488
 
489
/* Deliver a clock tick to the counter. */
490
static void
491
deliver_tx3904tmr_tick (struct hw *me,
492
                        void *data)
493
{
494
  struct tx3904tmr *controller = hw_data (me);
495
  SIM_DESC sd = hw_system (me);
496
  signed_8 this_ticks = sim_events_time(sd);
497
 
498
  signed_8 warp;
499
  signed_8 divisor;
500
  signed_8 quotient, remainder;
501
 
502
  /* compute simulation ticks between last tick and this tick */
503
  if(controller->last_ticks != 0)
504
    warp = this_ticks - controller->last_ticks + controller->roundoff_ticks;
505
  else
506
    {
507
      controller->last_ticks = this_ticks; /* initialize */
508
      warp = controller->roundoff_ticks;
509
    }
510
 
511
  if(controller->event != NULL)
512
    hw_event_queue_deschedule(me, controller->event);
513
  controller->event = NULL;
514
 
515
  /* Check whether the timer ticking is enabled at this moment.  This
516
     largely a function of the TCE bit, but is also slightly
517
     mode-dependent. */
518
  switch((int) GET_TCR_TMODE(controller))
519
    {
520
    case 0: /* interval */
521
      /* do not advance counter if TCE = 0 or if holding at count = CPRA */
522
      if(GET_TCR_TCE(controller) == 0 ||
523
         controller->trr == controller->cpra)
524
        return;
525
      break;
526
 
527
    case 1: /* pulse generator */
528
      /* do not advance counter if TCE = 0 */
529
      if(GET_TCR_TCE(controller) == 0)
530
        return;
531
      break;
532
 
533
    case 2: /* watchdog */
534
      /* do not advance counter if TCE = 0 and WDIS = 1 */
535
      if(GET_TCR_TCE(controller) == 0 &&
536
         GET_WTMR_WDIS(controller) == 1)
537
        return;
538
      break;
539
 
540
    case 3: /* disabled */
541
      /* regardless of TCE, do not advance counter */
542
      return;
543
    }
544
 
545
  /* In any of the above cases that return, a subsequent register
546
     write will be needed to restart the timer.  A tick event is
547
     scheduled by any register write, so it is more efficient not to
548
     reschedule dummy events here. */
549
 
550
 
551
  /* find appropriate divisor etc. */
552
  if(GET_TCR_CCS(controller) == 0) /* internal system clock */
553
    {
554
      /* apply internal clock divider */
555
      if(GET_TCR_CCDE(controller)) /* divisor circuit enabled? */
556
        divisor = controller->clock_ticks * (1 << (1 + GET_CCDR_CDR(controller)));
557
      else
558
        divisor = controller->clock_ticks;
559
    }
560
  else
561
    {
562
      divisor = controller->ext_ticks;
563
    }
564
 
565
  /* how many times to increase counter? */
566
  quotient = warp / divisor;
567
  remainder = warp % divisor;
568
 
569
  /* NOTE: If the event rescheduling code works properly, the quotient
570
     should never be larger than 1.  That is, we should receive events
571
     here at least as frequently as the simulated counter is supposed
572
     to decrement.  So the remainder (-> roundoff_ticks) will slowly
573
     accumulate, with the quotient == 0.  Once in a while, quotient
574
     will equal 1. */
575
 
576
  controller->roundoff_ticks = remainder;
577
  controller->last_ticks = this_ticks;
578
  while(quotient > 0) /* Is it time to increment counter? */
579
    {
580
      /* next 24-bit counter value */
581
      unsigned_4 next_trr = (controller->trr + 1) % (1 << 24);
582
      quotient --;
583
 
584
      switch((int) GET_TCR_TMODE(controller))
585
        {
586
        case 0: /* interval timer mode */
587
          {
588
            /* Current or next counter value matches CPRA value?  The
589
               first case covers counter holding at maximum before
590
               reset.  The second case covers normal counting
591
               behavior. */
592
            if(controller->trr == controller->cpra ||
593
               next_trr == controller->cpra)
594
              {
595
                /* likely hold CPRA value */
596
                if(controller->trr == controller->cpra)
597
                  next_trr = controller->cpra;
598
 
599
                SET_TISR_TIIS(controller);
600
 
601
                /* Signal an interrupt if it is enabled with TIIE,
602
                   and if we just arrived at CPRA.  Don't repeatedly
603
                   interrupt if holding due to TZCE=0 */
604
                if(GET_ITMR_TIIE(controller) &&
605
                   next_trr != controller->trr)
606
                  {
607
                    hw_port_event(me, INT_PORT, 1);
608
                  }
609
 
610
                /* Reset counter? */
611
                if(GET_ITMR_TZCE(controller))
612
                  {
613
                    next_trr = 0;
614
                  }
615
              }
616
          }
617
        break;
618
 
619
        case 1: /* pulse generator mode */
620
          {
621
            /* first trip point */
622
            if(next_trr == controller->cpra)
623
              {
624
                /* flip flip-flop & report */
625
                controller->ff ^= 1;
626
                hw_port_event(me, FF_PORT, controller->ff);
627
                SET_TISR_TPIAS(controller);
628
 
629
                /* signal interrupt */
630
                if(GET_PMGR_TPIAE(controller))
631
                  {
632
                    hw_port_event(me, INT_PORT, 1);
633
                  }
634
 
635
              }
636
            /* second trip point */
637
            else if(next_trr == controller->cprb)
638
              {
639
                /* flip flip-flop & report */
640
                controller->ff ^= 1;
641
                hw_port_event(me, FF_PORT, controller->ff);
642
                SET_TISR_TPIBS(controller);
643
 
644
                /* signal interrupt */
645
                if(GET_PMGR_TPIBE(controller))
646
                  {
647
                    hw_port_event(me, INT_PORT, 1);
648
                  }
649
 
650
                /* clear counter */
651
                next_trr = 0;
652
              }
653
          }
654
        break;
655
 
656
        case 2: /* watchdog timer mode */
657
          {
658
            /* watchdog timer expiry */
659
            if(next_trr == controller->cpra)
660
              {
661
                SET_TISR_TWIS(controller);
662
 
663
                /* signal interrupt */
664
                if(GET_WTMR_TWIE(controller))
665
                  {
666
                    hw_port_event(me, INT_PORT, 1);
667
                  }
668
 
669
                /* clear counter */
670
                next_trr = 0;
671
              }
672
          }
673
        break;
674
 
675
        case 3: /* disabled */
676
        default:
677
          break;
678
        }
679
 
680
      /* update counter and report */
681
      controller->trr = next_trr;
682
      /* HW_TRACE ((me, "counter trr %ld tisr %lx",
683
         (long) controller->trr, (long) controller->tisr)); */
684
    } /* end quotient loop */
685
 
686
  /* Reschedule a timer event in near future, so we can increment the
687
     counter again.  Set the event about 75% of divisor time away, so
688
     we will experience roughly 1.3 events per counter increment. */
689
  controller->event = hw_event_queue_schedule(me, divisor*3/4, deliver_tx3904tmr_tick, NULL);
690
}
691
 
692
 
693
 
694
 
695
const struct hw_descriptor dv_tx3904tmr_descriptor[] = {
696
  { "tx3904tmr", tx3904tmr_finish, },
697
  { NULL },
698
};

powered by: WebSVN 2.1.0

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