1/*  This file is part of the program GDB, the GNU debugger.
2
3    Copyright (C) 1998, 2007 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
105static void deliver_tx3904tmr_tick (struct hw *me, void *data);
106
107
108/* register numbers; each is one word long */
109enum
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
126enum
127 {
128  RESET_PORT,
129  INT_PORT,
130  FF_PORT
131};
132
133
134static 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
147struct 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
197static hw_io_read_buffer_method tx3904tmr_io_read_buffer;
198static hw_io_write_buffer_method tx3904tmr_io_write_buffer;
199static hw_port_event_method tx3904tmr_port_event;
200
201static void
202attach_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
239static void
240tx3904tmr_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
276static void
277tx3904tmr_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
318static unsigned
319tx3904tmr_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
360static unsigned
361tx3904tmr_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. */
490static void
491deliver_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
695const struct hw_descriptor dv_tx3904tmr_descriptor[] = {
696  { "tx3904tmr", tx3904tmr_finish, },
697  { NULL },
698};
699