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

4.104.114.84.95
Last change on this file since 9dffd2de was dcf0c5b8, checked in by Joel Sherrill <joel.sherrill@…>, on 09/04/03 at 18:52:18

2003-09-04 Joel Sherrill <joel@…>

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