source: rtems/c/src/lib/libbsp/or32/orp/clock/clockdrv.c @ f05b2ac

4.104.114.84.95
Last change on this file since f05b2ac was f05b2ac, checked in by Ralf Corsepius <ralf.corsepius@…>, on 04/21/04 at 16:01:48

Remove duplicate white lines.

  • Property mode set to 100644
File size: 5.7 KB
Line 
1/*  ckinit.c
2 *
3 *  This file provides a template for the clock device driver initialization.
4 *
5 *  COPYRIGHT (c) 1989-1999.
6 *  On-Line Applications Research Corporation (OAR).
7 *
8 *  The license and distribution terms for this file may be
9 *  found in the file LICENSE in this distribution or at
10 *  http://www.rtems.com/license/LICENSE.
11 *
12 *  $Id$
13 */
14
15#include <stdlib.h>
16
17#include <rtems.h>
18#include <rtems/libio.h>
19#include <bsp.h>
20static void (*old_handler)(unsigned int,unsigned int,unsigned int,unsigned int);
21
22void Clock_exit( void );
23void Clock_isr( rtems_vector_number vector,unsigned int pc,
24                unsigned int address, unsigned int sr);
25
26/*
27 *  The interrupt vector number associated with the clock tick device
28 *  driver.
29 */
30
31#define CLOCK_VECTOR    8
32
33/*
34 *  Clock_driver_ticks is a monotonically increasing counter of the
35 *  number of clock ticks since the driver was initialized.
36 */
37
38volatile uint32_t         Clock_driver_ticks;
39
40/*
41 *  Clock_isrs is the number of clock ISRs until the next invocation of
42 *  the RTEMS clock tick routine.  The clock tick device driver
43 *  gets an interrupt once a millisecond and counts down until the
44 *  length of time between the user configured microseconds per tick
45 *  has passed.
46 */
47
48uint32_t         Clock_isrs;              /* ISRs until next tick */
49
50/*
51 * These are set by clock driver during its init
52 */
53
54rtems_device_major_number rtems_clock_major = ~0;
55rtems_device_minor_number rtems_clock_minor;
56
57void Clock_exit( void );
58
59/* Write this to restart the Timer. Sets mode = 01,
60   interrupts enabled, interrupt not pending, report
61   at 200,000 (1 msec on 200 MHz CPU) */
62static const unsigned int TTMR_RESET = 0x60030D40;
63
64/*
65 *  Isr Handler
66 */
67
68void Clock_isr(uint32_t   vector,
69               uint32_t   pc,
70               uint32_t   ear,
71               uint32_t   sr)
72{
73  register int pending;
74  register int value = 0x60002710;
75
76  /* Was it us? */
77  asm volatile ("l.mfspr %0,r0,0x4802 \n\t"  /* Read the PIC status */
78                "l.andi  %0,%0,0x8    \n\t" : "=r" (pending));
79
80  if(pending)
81    {
82      rtems_clock_tick();
83      asm ("l.mtspr r0,%0,0x5000 \n\t" :: "r" (value));
84    }
85
86  if(old_handler)
87    (*old_handler)(vector,pc,ear,sr);
88}
89
90/*
91 *  Install_clock
92 *
93 *  Install a clock tick handler and reprograms the chip.  This
94 *  is used to initially establish the clock tick.
95 */
96
97void Install_clock()
98{
99  uint32_t   tmp,sr,ttmr,ttcr;
100  extern uint32_t   Or1k_Interrupt_Vectors[16];
101
102  ttmr = TTMR_RESET;    /* Reset value */
103  ttcr = 0;             /* Start at 0 */
104
105  /*
106   *  Initialize the clock tick device driver variables
107   */
108
109  /* Make sure the Timer (interrupt 3) is enabled and
110     reports a high prority interrupt */
111
112  asm volatile ("l.mfspr %0,r0,0x4800  \n\t"  /* Get the PIC mask */
113                "l.ori   %0,%0,0x8     \n\t"  /* Enable int 3 */
114                "l.mtspr r0,%0,0x4800  \n\t"  /* Write back mask */
115                "l.mfspr %0,r0,0x4801  \n\t"  /* Get priority mask */
116                "l.ori   %0,%0,0x8     \n\t"  /* Set us to high */
117                "l.mtspr r0,%0,0x4801  \n\t"  /* Write back to PICPR */
118                : "=r" (tmp));
119
120  /* Generate a 1 kHz interrupt */
121  asm volatile ("l.mfspr %0,r0,0x11 \n\t"    /* Get the current setting */
122                "l.addi  %1,r0,-5   \n\t"
123                "l.and   %1,%1,%0   \n\t"    /* Turn off interrupts */
124                "l.mtspr r0,%1,0x11 \n\t"    /* Set it in SR */
125                "l.mtspr r0,%2,0x5000\n\t"   /* Set TTMR */
126                "l.mtspr r0,%3,0x5100\n\t"   /* Set TTCR */
127                : "=&r" (sr), "=&r" (tmp) : "r" (ttmr), "r" (ttcr));
128
129  old_handler = (void(*)(unsigned int,unsigned int,unsigned int,unsigned int))
130    Or1k_Interrupt_Vectors[8];
131  Or1k_Interrupt_Vectors[8] = (uint32_t)Clock_isr;
132
133  asm volatile ("l.mtspr r0,%0,0x11\n\t":: "r" (sr));
134
135  Clock_driver_ticks = 0;
136
137  /*
138   *  Schedule the clock cleanup routine to execute if the application exits.
139   */
140
141  atexit( Clock_exit );
142}
143
144/*
145 *  Clean up before the application exits
146 */
147
148void Clock_exit( void )
149{
150  register int temp1;
151  register int temp2;
152
153  /* In the case of a fatal error, we should shut down
154     all the interrupts so we don't get woken up again. */
155  /* First, turn off the clock in the PIC */
156
157  asm volatile ("l.mfspr %0,r0,0x4800  \n\t"  /* Get the PIC mask */
158                "l.addi  %1,%1,-9      \n\t"  /* Create a mask to disable */
159                "l.and   %0,%1,%0      \n\t"  /* Mask us out */
160                "l.mtspr r0,%0,0x4800  \n\t"  /* Write back mask */
161                "l.mfspr %0,r0,0x4801  \n\t"  /* Get priority mask */
162                "l.and   %0,%1,%0      \n\t"  /* Set us to low */
163                "l.mtspr r0,%0,0x4801  \n\t"  /* Write back to PICPR */
164                : "=r" (temp1), "=r" (temp2));
165
166  /* Now turn off the clock at the timer */
167  asm volatile ("l.mtspr r0,r0,0x5000\n\t"   /* Clear TTMR */
168                "l.mtspr r0,r0,0x5100\n\t"); /* Clear TTCR */
169}
170
171/*
172 *  Clock_initialize
173 *
174 *  Device driver entry point for clock tick driver initialization.
175 */
176
177rtems_device_driver Clock_initialize(
178  rtems_device_major_number major,
179  rtems_device_minor_number minor,
180  void *pargp
181)
182{
183  Install_clock();
184
185  /*
186   * make major/minor avail to others such as shared memory driver
187   */
188
189  rtems_clock_major = major;
190  rtems_clock_minor = minor;
191
192  return RTEMS_SUCCESSFUL;
193}
194
195rtems_device_driver Clock_control(
196  rtems_device_major_number major,
197  rtems_device_minor_number minor,
198  void *pargp
199)
200{
201    uint32_t         isrlevel;
202    rtems_libio_ioctl_args_t *args = pargp;
203
204    if (args == 0)
205        goto done;
206
207    /*
208     * This is hokey, but until we get a defined interface
209     * to do this, it will just be this simple...
210     */
211
212    if (args->command == rtems_build_name('I', 'S', 'R', ' '))
213    {
214        Clock_isr(CLOCK_VECTOR,0,0,0);
215    }
216    else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
217    {
218      rtems_interrupt_disable( isrlevel );
219       (void) set_vector( args->buffer, CLOCK_VECTOR, 1 );
220      rtems_interrupt_enable( isrlevel );
221    }
222
223done:
224    return RTEMS_SUCCESSFUL;
225}
Note: See TracBrowser for help on using the repository browser.