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

4.104.114.84.95
Last change on this file since 56758965 was 56758965, checked in by Joel Sherrill <joel.sherrill@…>, on Apr 5, 2006 at 8:11:57 PM

2006-04-05 Victor V. Vengerov <Victor.Vengerov@…>

  • mpc6xx/clock/c_clock.c: Now works with MPCI SHM driver.
  • Property mode set to 100644
File size: 4.9 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
63static void clockHandler(void)
64{
65    rtems_clock_tick();
66}
67
68static void (*clock_handler)(void);
69
70/*
71 *  Clock_isr
72 *
73 *  This is the clock tick interrupt handler.
74 *
75 *  Input parameters:
76 *    vector - vector number
77 *
78 *  Output parameters:  NONE
79 *
80 *  Return values:      NONE
81 *
82 */
83void clockIsr(void *unused)
84{
85int decr;
86  /*
87   *  The driver has seen another tick.
88   */
89  do {
90        register uint32_t flags;
91        rtems_interrupt_disable(flags);
92        asm volatile ("mfdec %0; add %0, %0, %1; mtdec %0":"=&r"(decr):"r"(Clock_Decrementer_value));
93        rtems_interrupt_enable(flags);
94
95        Clock_driver_ticks += 1;
96
97        /*
98         *  Real Time Clock counter/timer is set to automatically reload.
99         */
100        clock_handler();
101  } while ( decr < 0 );
102}
103
104int clockIsOn(void* unused)
105{
106  uint32_t   msr_value;
107
108  _CPU_MSR_GET( msr_value );
109  if (msr_value & MSR_EE) return 1;
110  return 0;
111}
112
113
114/*
115 *  Clock_exit
116 *
117 *  This routine allows the clock driver to exit by masking the interrupt and
118 *  disabling the clock's counter.
119 *
120 *  Input parameters:   NONE
121 *
122 *  Output parameters:  NONE
123 *
124 *  Return values:      NONE
125 *
126 */
127
128void Clock_exit( void )
129{
130  (void) BSP_disconnect_clock_handler ();
131}
132 
133/*
134 *  Clock_initialize
135 *
136 *  This routine initializes the clock driver.
137 *
138 *  Input parameters:
139 *    major - clock device major number
140 *    minor - clock device minor number
141 *    parg  - pointer to optional device driver arguments
142 *
143 *  Output parameters:  NONE
144 *
145 *  Return values:
146 *    rtems_device_driver status code
147 */
148
149rtems_device_driver Clock_initialize(
150  rtems_device_major_number major,
151  rtems_device_minor_number minor,
152  void *pargp
153)
154{
155  Clock_Decrementer_value = (BSP_bus_frequency/BSP_time_base_divisor)*
156            (rtems_configuration_get_microseconds_per_tick()/1000);
157
158  /* set the decrementer now, prior to installing the handler
159   * so no interrupts will happen in a while.
160   */
161  PPC_Set_decrementer( (unsigned)-1 );
162
163  /* if a decrementer exception was pending, it is cleared by
164   * executing the default (nop) handler at this point;
165   * The next exception will then be taken by our clock handler.
166   * Clock handler installation initializes the decrementer to
167   * the correct value.
168   */
169
170  clock_handler = clockHandler;
171  if (!BSP_connect_clock_handler ()) {
172    printk("Unable to initialize system clock\n");
173    rtems_fatal_error_occurred(1);
174  }
175  /* make major/minor avail to others such as shared memory driver */
176 
177  rtems_clock_major = major;
178  rtems_clock_minor = minor;
179
180  return RTEMS_SUCCESSFUL;
181} /* Clock_initialize */
182 
183/*
184 *  Clock_control
185 *
186 *  This routine is the clock device driver control entry point.
187 *
188 *  Input parameters:
189 *    major - clock device major number
190 *    minor - clock device minor number
191 *    parg  - pointer to optional device driver arguments
192 *
193 *  Output parameters:  NONE
194 *
195 *  Return values:
196 *    rtems_device_driver status code
197 */
198
199rtems_device_driver Clock_control(
200  rtems_device_major_number major,
201  rtems_device_minor_number minor,
202  void *pargp
203)
204{
205    rtems_libio_ioctl_args_t *args = pargp;
206 
207    if (args == 0)
208        goto done;
209 
210    Clock_Decrementer_value = (BSP_bus_frequency/BSP_time_base_divisor)*
211      (rtems_configuration_get_microseconds_per_tick()/1000);
212
213    if      (args->command == rtems_build_name('I', 'S', 'R', ' '))
214      clockHandler();
215    else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
216    {
217        if (clock_handler == NULL)
218            Clock_initialize(major, minor, 0);
219        clock_handler = args->buffer;
220    }
221done:
222    return RTEMS_SUCCESSFUL;
223}
Note: See TracBrowser for help on using the repository browser.