source: rtems/c/src/lib/libcpu/powerpc/mpc6xx/clock/c_clock.c @ c984fb3

4.104.114.84.9
Last change on this file since c984fb3 was c984fb3, checked in by Joel Sherrill <joel.sherrill@…>, on May 22, 2004 at 3:14:31 PM

2004-05-22 Till Strauman <strauman@…>

PR 619/bsps

  • mpc6xx/clock/c_clock.c: The PPC decrementer must be reloaded on each clock tick. Currently, this is done by just reloading a fixed value. The attached patch takes into account the time that elapsed since the decrementer crossed zero in order to adjust the value to be re-loaded. Without the patch, the effective system clock cycle is increased by the exception handler latency.
  • Property mode set to 100644
File size: 4.6 KB
Line 
1/*
2 *  Clock Tick Device Driver
3 *
4 *  This routine utilizes the Decrementer Register common to the PPC family.
5 *
6 *  The tick frequency is directly programmed to the configured number of
7 *  microseconds per tick.
8 *
9 *  COPYRIGHT (c) 1989-1997.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may in
13 *  the file LICENSE in this distribution or at
14 *  http://www.rtems.com/license/LICENSE.
15 *
16 *  Modified to support the MPC750.
17 *  Modifications Copyright (c) 1999 Eric Valette valette@crf.canon.fr
18 *
19 *  $Id$
20 */
21
22#include <rtems/system.h>
23#include <rtems.h>
24#include <rtems/libio.h>
25#include <stdlib.h>                     /* for atexit() */
26#include <assert.h>
27#include <libcpu/c_clock.h>
28#include <rtems/bspIo.h>                     /* for printk() */
29
30extern int BSP_connect_clock_handler (void);
31
32/*
33 *  Clock ticks since initialization
34 */
35
36volatile uint32_t   Clock_driver_ticks;
37
38/*
39 *  This is the value programmed into the count down timer.
40 */
41
42uint32_t   Clock_Decrementer_value;
43
44/*
45 * These are set by clock driver during its init
46 */
47 
48rtems_device_major_number rtems_clock_major = ~0;
49rtems_device_minor_number rtems_clock_minor;
50
51void clockOff(void* unused)
52{
53  /*
54   * Nothing to do as we cannot disable all interrupts and
55   * the decrementer interrupt enable is MSR_EE
56   */
57}
58void clockOn(void* unused)
59{
60  PPC_Set_decrementer( Clock_Decrementer_value );
61}
62
63/*
64 *  Clock_isr
65 *
66 *  This is the clock tick interrupt handler.
67 *
68 *  Input parameters:
69 *    vector - vector number
70 *
71 *  Output parameters:  NONE
72 *
73 *  Return values:      NONE
74 *
75 */
76
77void clockIsr()
78{
79int decr;
80  /*
81   *  The driver has seen another tick.
82   */
83  do {
84        asm volatile ("mfdec %0; add %0, %0, %1; mtdec %0":"=r"(decr):"r"(Clock_Decrementer_value));
85
86        Clock_driver_ticks += 1;
87
88        /*
89         *  Real Time Clock counter/timer is set to automatically reload.
90         */
91        rtems_clock_tick();
92  } while ( decr < 0 );
93}
94
95int clockIsOn(void* unused)
96{
97  uint32_t   msr_value;
98
99  _CPU_MSR_GET( msr_value );
100  if (msr_value & MSR_EE) return 1;
101  return 0;
102}
103
104
105/*
106 *  Clock_exit
107 *
108 *  This routine allows the clock driver to exit by masking the interrupt and
109 *  disabling the clock's counter.
110 *
111 *  Input parameters:   NONE
112 *
113 *  Output parameters:  NONE
114 *
115 *  Return values:      NONE
116 *
117 */
118
119void Clock_exit( void )
120{
121  (void) BSP_disconnect_clock_handler ();
122}
123 
124/*
125 *  Clock_initialize
126 *
127 *  This routine initializes the clock driver.
128 *
129 *  Input parameters:
130 *    major - clock device major number
131 *    minor - clock device minor number
132 *    parg  - pointer to optional device driver arguments
133 *
134 *  Output parameters:  NONE
135 *
136 *  Return values:
137 *    rtems_device_driver status code
138 */
139
140rtems_device_driver Clock_initialize(
141  rtems_device_major_number major,
142  rtems_device_minor_number minor,
143  void *pargp
144)
145{
146  Clock_Decrementer_value = (BSP_bus_frequency/BSP_time_base_divisor)*
147            (rtems_configuration_get_microseconds_per_tick()/1000);
148
149  /* set the decrementer now, prior to installing the handler
150   * so no interrupts will happen in a while.
151   */
152  PPC_Set_decrementer( (unsigned)-1 );
153
154  /* if a decrementer exception was pending, it is cleared by
155   * executing the default (nop) handler at this point;
156   * The next exception will then be taken by our clock handler.
157   * Clock handler installation initializes the decrementer to
158   * the correct value.
159   */
160
161  if (!BSP_connect_clock_handler ()) {
162    printk("Unable to initialize system clock\n");
163    rtems_fatal_error_occurred(1);
164  }
165  /* make major/minor avail to others such as shared memory driver */
166 
167  rtems_clock_major = major;
168  rtems_clock_minor = minor;
169
170  return RTEMS_SUCCESSFUL;
171} /* Clock_initialize */
172 
173/*
174 *  Clock_control
175 *
176 *  This routine is the clock device driver control entry point.
177 *
178 *  Input parameters:
179 *    major - clock device major number
180 *    minor - clock device minor number
181 *    parg  - pointer to optional device driver arguments
182 *
183 *  Output parameters:  NONE
184 *
185 *  Return values:
186 *    rtems_device_driver status code
187 */
188
189rtems_device_driver Clock_control(
190  rtems_device_major_number major,
191  rtems_device_minor_number minor,
192  void *pargp
193)
194{
195    rtems_libio_ioctl_args_t *args = pargp;
196 
197    if (args == 0)
198        goto done;
199 
200    Clock_Decrementer_value = (BSP_bus_frequency/BSP_time_base_divisor)*
201      (rtems_configuration_get_microseconds_per_tick()/1000);
202
203    if      (args->command == rtems_build_name('I', 'S', 'R', ' '))
204      clockIsr();
205    else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
206    {
207                Clock_initialize(major, minor, 0);
208    }
209done:
210    return RTEMS_SUCCESSFUL;
211}
Note: See TracBrowser for help on using the repository browser.