source: rtems/bsps/m68k/mvme167/clock/ckinit.c @ 58adad4

5
Last change on this file since 58adad4 was 7632906, checked in by Sebastian Huber <sebastian.huber@…>, on 04/19/18 at 04:35:52

bsps: Move clock drivers to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/*
2 *  Implementation of the Clock_initialize() functions
3 *  prototyped in rtems/c/src/lib/include/clockdrv.h.
4 *
5 *  This port does not allow the application to select which timer on the
6 *  MVME167 to use for the clock, nor does it allow the application to
7 *  configure the clock. The clock uses the VMEchip2 Tick Timer #2. This
8 *  timer is set up to raise a MC680x0 level-6 interrupt every 1 ms. The
9 *  interrupt vector is 0x69.
10 *
11 *  All page references are to the MVME166/MVME167/MVME187 Single Board
12 *  Computer Programmer's Reference Guide (MVME187PG/D2) with the April
13 *  1993 supplements/addenda (MVME187PG/D2A1).
14 */
15
16/*
17 *  COPYRIGHT (c) 1989-1999.
18 *  On-Line Applications Research Corporation (OAR).
19 *
20 *  The license and distribution terms for this file may be
21 *  found in the file LICENSE in this distribution or at
22 *  http://www.rtems.org/license/LICENSE.
23 *
24 *  Modifications of respective RTEMS files:
25 *  Copyright (c) 1998, National Research Council of Canada
26 */
27
28#include <stdlib.h>
29#include <bsp.h>
30#include <rtems/clockdrv.h>
31
32#define MS_COUNT          1000              /* T2's countdown constant (1 ms) */
33#define CLOCK_INT_LEVEL   6                 /* T2's interrupt level */
34#define CLOCK_VECTOR (VBR0 * 0x10 + 0x9)    /* T2 is vector $X9 (p. 2-71)*/
35
36/*
37 *  Clock_driver_ticks is a monotonically increasing counter of the number of
38 *  VMEchip2 timer #2 ticks since the driver was initialized.
39 */
40volatile uint32_t Clock_driver_ticks;
41
42/*
43 *  Clock_isrs is the number of clock ISRs until the next invocation of the
44 *  RTEMS clock tick routine. This clock tick device driver gets an interrupt
45 *  once a millisecond and counts down until the length of time between the
46 *  user configured microseconds per tick has passed. This allows the clock
47 *  device to "tick" faster than the kernel clock. Of course, the kernel clock
48 *  cannot tick faster than the hardware clock. Therefore, the kernel clock
49 *  ticks cannot occur more frequently than every 1 millisecond.
50 */
51uint32_t         Clock_isrs;
52
53/*
54 *  Records the previous clock ISR (should be NULL)
55 */
56rtems_isr_entry  Old_ticker;
57
58/*
59 *  Called when the kernel exits.
60 */
61void clock_exit( void );
62
63/*
64 *  VMEchip2_T2_isr
65 *
66 *  C ISR Handler. Increment the number of internal ticks. If it is time for a
67 *  kernel clock tick (if Clock_isrs == 1), call rtems_clock_tick() to signal
68 *  the event and reset the Clock_isrs counter; else, just decrement it.
69 */
70static rtems_isr VMEchip2_T2_isr(
71  rtems_vector_number vector
72)
73{
74  char overflow;                /* Content of overflow counter */
75  long i;
76  long ct;                      /* Number of T2 ticks per RTEMS ticks */
77
78  ct = rtems_configuration_get_microseconds_per_tick() / 1000;
79
80  /*
81   *  May have missed interrupts, so should look at the overflow counter.
82   */
83  lcsr->intr_clear |= 0x02000000;   /* Clear the interrupt */
84  overflow = (lcsr->board_ctl >> 12) & 0xF;
85  lcsr->board_ctl |= 0x400;         /* Reset overflow counter */
86
87  /* Attempt to protect against one more period */
88  if ( overflow == 0 )
89    overflow = 16;
90
91  Clock_driver_ticks += overflow;   /* One or more internal ticks */
92
93  if ( Clock_isrs <= overflow ) {
94    /* If its time for kernel clock ticks, signal the events to RTEMS */
95    for( i = overflow - Clock_isrs; i >= 0; i -= ct ) {
96      rtems_clock_tick();
97    }
98    /* Reset the counter */
99    Clock_isrs = (uint32_t)-i;
100  }
101  else
102    Clock_isrs -= overflow;
103}
104
105/*
106 *  VMEchip2_T2_initialize
107 *
108 *  Initialize the VMEchip2 Tick Timer #2.
109 *
110 *  THE VMECHIP2 PRESCALER REGISTER IS ASSUMED TO BE SET!
111 *  The prescaler is used by all VMEchip2 timers, including the VMEbus grant
112 *  timeout counter, the DMAC time off timer, the DMAC timer on timer, and the
113 *  VMEbus global timeout timer. The prescaler value is normally set by the
114 *  boot ROM to provide a 1 MHz clock to the timers. For a 25 MHz MVME167, the
115 *  prescaler value should be 0xE7 (page 2-63).
116 */
117static void VMEchip2_T2_initialize( void )
118{
119  Clock_driver_ticks = 0;
120  Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
121
122  lcsr->intr_ena &= 0xFDFFFFFF;   /* Disable tick timer 2 interrupt */
123  lcsr->intr_clear = 0x02000000;  /* Clear tick timer 2 interrupt */
124  lcsr->intr_level[0] =           /* Set tick timer 2 interrupt level */
125      (lcsr->intr_level[0] & 0xFFFFFF0F ) | (CLOCK_INT_LEVEL << 4);
126  lcsr->timer_cmp_2 = MS_COUNT;   /* Period in compare register */
127  lcsr->timer_cnt_2 = 0;          /* Clear tick timer 2 counter */
128  Old_ticker =                    /* Install C ISR */
129      (rtems_isr_entry) set_vector( VMEchip2_T2_isr, CLOCK_VECTOR, 1 );
130  lcsr->board_ctl |= 0x700;       /* Start tick timer 2, reset-on-compare, */
131                                  /*  and clear tick timer 2 overflow counter */
132  lcsr->intr_ena |= 0x02000000;   /* Enable tick timer 2 interrupt */
133  lcsr->vector_base |= 0x00800000;/* Unmask VMEchip2 interrupts */
134  atexit( clock_exit );           /* Turn off T2 interrupts when we exit */
135}
136
137/*
138 *  This routine stops the VMEchip2 T2 timer, disables its interrupt, and
139 *  re-install the old interrupt vectors.
140 */
141void clock_exit( void )
142{
143  lcsr->board_ctl &= 0xFFFFFEFF;  /* Stop tick timer 2 */
144  lcsr->intr_ena &= 0xFDFFFFFF;   /* Disable tick timer 2 interrupt */
145  lcsr->intr_clear = 0x02000000;  /* Clear tick timer 2 interrupt */
146
147  set_vector( Old_ticker, CLOCK_VECTOR, 1 );
148}
149
150rtems_device_driver Clock_initialize(
151  rtems_device_major_number major,
152  rtems_device_minor_number minor,
153  void *pargp
154)
155{
156  VMEchip2_T2_initialize();
157
158  return RTEMS_SUCCESSFUL;
159}
Note: See TracBrowser for help on using the repository browser.