source: rtems/c/src/lib/libbsp/powerpc/virtex4/clock/clock.c @ 16a8616

4.11
Last change on this file since 16a8616 was 16a8616, checked in by Ric Claus <claus@…>, on Mar 30, 2012 at 3:03:43 PM

Add Virtex4 and Virtex5 BSPs

This commit covers at least PR2020, 2022, and 2023. This
patch adds all of the code for both BSPs, modifications
to libcpu/powerpc for the ppc440, and some updates to the
BSPs from follow up review and testing.

These BSPs should be good baselines for future development.
The configurations used by Ric are custom and have a non-standard
NIC. They also do not have a UART. Thus the current console
driver just prints to a RAM buffer.

The NIC and UART support are left for future work. When the UART
support is added, moving the existing "to RAM" console driver to
a shared location is likely desirable because boards with no debug
UART port are commonly deployed. This would let printk() go to RAM.

  • Property mode set to 100644
File size: 7.0 KB
Line 
1/*  clock.c
2 *
3 *  This routine initializes the interval timer on the
4 *  PowerPC 403 CPU.  The tick frequency is specified by the bsp.
5 *
6 *  Author: Andrew Bray <andy@i-cubed.co.uk>
7 *
8 *  COPYRIGHT (c) 1995 by i-cubed ltd.
9 *
10 *  To anyone who acknowledges that this file is provided "AS IS"
11 *  without any express or implied warranty:
12 *      permission to use, copy, modify, and distribute this file
13 *      for any purpose is hereby granted without fee, provided that
14 *      the above copyright notice and this notice appears in all
15 *      copies, and that the name of i-cubed limited not be used in
16 *      advertising or publicity pertaining to distribution of the
17 *      software without specific, written prior permission.
18 *      i-cubed limited makes no representations about the suitability
19 *      of this software for any purpose.
20 *
21 *  Derived from c/src/lib/libcpu/hppa1.1/clock/clock.c:
22 *
23 *  Modifications for deriving timer clock from cpu system clock by
24 *              Thomas Doerfler <td@imd.m.isar.de>
25 *  for these modifications:
26 *  COPYRIGHT (c) 1997 by IMD, Puchheim, Germany.
27 *
28 *  COPYRIGHT (c) 1989-2007.
29 *  On-Line Applications Research Corporation (OAR).
30 *
31 *  The license and distribution terms for this file may be
32 *  found in the file LICENSE in this distribution or at
33 *  http://www.rtems.com/license/LICENSE.
34 *
35 *  Modifications for PPC405GP by Dennis Ehlin
36 *
37 *  $Id: clock.c 63 2011-04-26 00:23:51Z claus $
38 */
39
40#include <rtems.h>
41#include <rtems/clockdrv.h>
42#include <rtems/libio.h>
43#include <stdlib.h>                     /* for atexit() */
44#include <rtems/bspIo.h>
45#include <rtems/powerpc/powerpc.h>
46
47/*
48 * check, which exception handling code is present
49 */
50
51#include <bsp.h>
52
53#include <bsp/vectors.h>
54#include <bsp/irq_supp.h>
55
56volatile uint32_t   Clock_driver_ticks;
57static uint32_t   pit_value, tick_time;
58static bool auto_restart;
59
60void Clock_exit( void );
61
62rtems_isr_entry set_vector(                     /* returns old vector */
63  rtems_isr_entry     handler,                  /* isr routine        */
64  rtems_vector_number vector,                   /* vector number      */
65  int                 type                      /* RTEMS or RAW intr  */
66);
67
68/*
69 * These are set by clock driver during its init
70 */
71
72rtems_device_major_number rtems_clock_major = ~0;
73rtems_device_minor_number rtems_clock_minor;
74
75static inline uint32_t   get_itimer(void)
76{
77    register uint32_t   rc;
78
79    asm volatile ("mfspr %0, 0x10c" : "=r" ((rc))); /* 405GP TBL */
80
81    return rc;
82}
83
84/*
85 *  ISR Handler
86 */
87
88int Clock_isr(BSP_Exception_frame *f, unsigned int vector)
89{
90    uint32_t   clicks_til_next_interrupt;
91#if defined(BSP_PPC403_CLOCK_ISR_IRQ_LEVEL)
92    uint32_t   l_orig = _ISR_Get_level();
93#endif
94    if (!auto_restart)
95    {
96      uint32_t   itimer_value;
97      /*
98       * setup for next interrupt; making sure the new value is reasonably
99       * in the future.... in case we lost out on an interrupt somehow
100       */
101
102      itimer_value = get_itimer();
103      tick_time += pit_value;
104
105      /*
106       * how far away is next interrupt *really*
107       * It may be a long time; this subtraction works even if
108       * Clock_clicks_interrupt < Clock_clicks_low_order via
109       * the miracle of unsigned math.
110       */
111      clicks_til_next_interrupt = tick_time - itimer_value;
112
113      /*
114       * If it is too soon then bump it up.
115       * This should only happen if CPU_HPPA_CLICKS_PER_TICK is too small.
116       * But setting it low is useful for debug, so...
117       */
118
119      if (clicks_til_next_interrupt < 400)
120      {
121        tick_time = itimer_value + 1000;
122        clicks_til_next_interrupt = 1000;
123        /* XXX: count these! this should be rare */
124      }
125
126      /*
127       * If it is too late, that means we missed the interrupt somehow.
128       * Rather than wait 35-50s for a wrap, we just fudge it here.
129       */
130
131      if (clicks_til_next_interrupt > pit_value)
132      {
133        tick_time = itimer_value + 1000;
134        clicks_til_next_interrupt = 1000;
135        /* XXX: count these! this should never happen :-) */
136      }
137
138      asm volatile ("mtspr 0x3db, %0" :: "r"
139                         (clicks_til_next_interrupt)); /* PIT */
140    }
141
142    /* Clear the Programmable Interrupt Status */
143    asm volatile ( "mtspr 0x3d8, %0" :: "r" (0x08000000)); /* TSR */
144
145    Clock_driver_ticks++;
146
147    rtems_clock_tick();
148
149    return 0;
150}
151
152void ClockOff(void)
153{
154    register uint32_t   tcr;
155
156    asm volatile ("mfspr %0, 0x3da" : "=r" ((tcr))); /* TCR */
157
158    tcr &= ~ 0x04400000;
159
160    asm volatile ("mtspr 0x3da, %0" : "=r" ((tcr)) : "0" ((tcr))); /* TCR */
161}
162
163void ClockOn(void)
164{
165    uint32_t   iocr;
166    register uint32_t   tcr;
167
168    Clock_driver_ticks = 0;
169
170    asm volatile ("mfdcr %0, 0x0b2" : "=r" (iocr));  /*405GP CPC0_CR1 */
171    if (bsp_timer_internal_clock) {
172      iocr &=~0x800000;               /* timer clocked from system clock CETE*/
173    }
174    else {
175      iocr |= 0x800000;               /* select external timer clock CETE*/
176    }
177    asm volatile ("mtdcr 0x0b2, %0" : "=r" (iocr) : "0" (iocr)); /* 405GP CPC0_CR1 */
178
179     /*
180      * Enable auto restart
181      */
182
183    auto_restart = true;
184
185    pit_value = rtems_configuration_get_microseconds_per_tick() *
186      bsp_clicks_per_usec;
187
188     /*
189      * Set PIT value
190      */
191
192    asm volatile ("mtspr 0x3db, %0" : : "r" (pit_value)); /* PIT */
193
194     /*
195      * Set timer to autoreload, bit TCR->ARE = 1  0x0400000
196      * Enable PIT interrupt, bit TCR->PIE = 1     0x4000000
197      */
198    tick_time = get_itimer() + pit_value;
199
200    asm volatile ("mfspr %0, 0x3da" : "=r" ((tcr)));               /* TCR */
201    tcr = (tcr & ~0x04400000) | (auto_restart ? 0x04400000 : 0x04000000);
202    asm volatile ("mtspr 0x3da, %0" : "=r" ((tcr)) : "0" ((tcr))); /* TCR */
203}
204
205
206
207void Install_clock(ppc_exc_handler_t clock_isr)
208{
209#ifdef ppc403
210   uint32_t   pvr;
211#endif /* ppc403 */
212
213   Clock_driver_ticks = 0;
214
215   /*
216    * initialize the interval here
217    * First tick is set to right amount of time in the future
218    * Future ticks will be incremented over last value set
219    * in order to provide consistent clicks in the face of
220    * interrupt overhead
221    */
222
223   ppc_exc_set_handler( BSP_PPC403_CLOCK_HOOK_EXCEPTION, clock_isr );
224   ClockOn();
225
226   atexit(Clock_exit);
227}
228
229void
230ReInstall_clock(ppc_exc_handler_t clock_isr)
231{
232  uint32_t   isrlevel = 0;
233
234  rtems_interrupt_disable(isrlevel);
235
236   ppc_exc_set_handler( BSP_PPC403_CLOCK_HOOK_EXCEPTION, clock_isr );
237   ClockOn();
238
239  rtems_interrupt_enable(isrlevel);
240}
241
242
243/*
244 * Called via atexit()
245 * Remove the clock interrupt handler by setting handler to NULL
246 *
247 * This will not work on the 405GP because
248 * when bit's are set in TCR they can only be unset by a reset
249 */
250
251void Clock_exit(void)
252{
253  ClockOff();
254  ppc_exc_set_handler( BSP_PPC403_CLOCK_HOOK_EXCEPTION, 0 );
255}
256
257rtems_device_driver Clock_initialize(
258  rtems_device_major_number major,
259  rtems_device_minor_number minor,
260  void *pargp
261)
262{
263  Install_clock( Clock_isr );
264
265  /*
266   * make major/minor avail to others such as shared memory driver
267   */
268
269  rtems_clock_major = major;
270  rtems_clock_minor = minor;
271
272  return RTEMS_SUCCESSFUL;
273}
Note: See TracBrowser for help on using the repository browser.