source: rtems/c/src/lib/libcpu/powerpc/ppc403/clock/clock_4xx.c @ 39d08d55

4.104.114.9
Last change on this file since 39d08d55 was 39d08d55, checked in by Ralf Corsepius <ralf.corsepius@…>, on Sep 6, 2008 at 5:36:55 PM

Convert to "bool".

  • Property mode set to 100644
File size: 6.0 KB
Line 
1/*  clock.c
2 *
3 *  This routine initializes the interval timer on the
4 *  PowerPC 405 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 * Further modifications for PPC405GP/EX by Michael Hamel
38 *
39 *  $Id$
40 */
41
42#include <rtems.h>
43#include <rtems/clockdrv.h>
44#include <rtems/libio.h>
45#include <stdlib.h>                     /* for atexit() */
46#include <rtems/bspIo.h>
47#include <ppc405common.h>
48#include <libcpu/cpuIdent.h>
49#include <bsp/irq.h>
50
51
52
53/* PPC405GP */
54#define CPC0_CR1        0xB2
55 #define CR1_CETE       0x00800000
56
57/* PPC405EX */
58#define SDR0_C405       0x180
59 #define SDR_CETE       0x02000000
60
61volatile uint32_t   Clock_driver_ticks;
62static uint32_t   pit_value, tick_time;
63
64void Clock_exit( void );
65 
66rtems_isr_entry set_vector(                    /* returns old vector */
67  rtems_isr_entry     handler,                  /* isr routine        */
68  rtems_vector_number vector,                   /* vector number      */
69  int                 type                      /* RTEMS or RAW intr  */
70);
71
72/* Defined in bspstart.c */
73extern uint32_t bsp_clicks_per_usec;
74extern bool bsp_timer_internal_clock;
75
76/*
77 * These are set by clock driver during its init
78 */
79 
80rtems_device_major_number rtems_clock_major = ~0;
81rtems_device_minor_number rtems_clock_minor;
82 
83/*
84 *  ISR Handler
85 */
86
87void Clock_isr(void* handle)
88{
89        Clock_driver_ticks++;
90    rtems_clock_tick();
91}
92
93int ClockIsOn(const rtems_irq_connect_data* unused)
94{
95    return ((mfspr(TCR) & PIE) != 0);
96}
97
98
99void ClockOff(const rtems_irq_connect_data* unused)
100{
101    register uint32_t   r;
102 
103        r = mfspr(TCR);
104        mtspr(TCR, r & ~(PIE | ARE) );
105}
106
107void ClockOn(const rtems_irq_connect_data* unused)
108{
109    uint32_t   iocr, r;
110        ppc_cpu_id_t cpu;
111    Clock_driver_ticks = 0;
112 
113        cpu = get_ppc_cpu_type();
114        if (cpu==PPC_405GP) {
115                iocr = mfdcr(CPC0_CR1);
116                if (bsp_timer_internal_clock) iocr &= ~CR1_CETE ;/* timer clocked from system clock */
117                                                                 else iocr |=  CR1_CETE; /* select external timer clock */
118                mtdcr(CPC0_CR1,iocr);
119        } else if (cpu==PPC_405EX) {
120                mfsdr(SDR0_C405,iocr);
121                if (bsp_timer_internal_clock) iocr &= ~SDR_CETE ;/* timer clocked from system clock */
122                                                                 else iocr |=  SDR_CETE; /* select external timer clock */
123                mtsdr(SDR0_C405,iocr);
124        } else {
125                printk("clock.c:unrecognised CPU");
126                rtems_fatal_error_occurred(1);
127        }
128
129    pit_value = rtems_configuration_get_microseconds_per_tick() * bsp_clicks_per_usec;
130        mtspr(PIT,pit_value);
131
132        tick_time = mfspr(TBL) + pit_value;
133        r = mfspr(TCR);
134        mtspr(TCR, r | PIE | ARE);
135}
136
137
138
139void Install_clock(void (*clock_isr)(void *))
140{
141 
142    /*
143     * initialize the interval here
144     * First tick is set to right amount of time in the future
145     * Future ticks will be incremented over last value set
146     * in order to provide consistent clicks in the face of
147     * interrupt overhead
148     */
149
150        rtems_irq_connect_data clockIrqConnData;
151
152        Clock_driver_ticks = 0;
153        clockIrqConnData.on   = ClockOn;
154        clockIrqConnData.off  = ClockOff;
155        clockIrqConnData.isOn = ClockIsOn;
156        clockIrqConnData.name = BSP_PIT;
157        clockIrqConnData.hdl  = clock_isr;
158        if ( ! BSP_install_rtems_irq_handler (&clockIrqConnData)) {
159                 printk("Unable to connect Clock Irq handler\n");
160                 rtems_fatal_error_occurred(1);
161        }
162    atexit(Clock_exit);
163}
164
165void
166ReInstall_clock(void (*new_clock_isr)(void *))
167{
168        uint32_t   isrlevel = 0;
169        rtems_irq_connect_data clockIrqConnData;
170
171        rtems_interrupt_disable(isrlevel);
172        clockIrqConnData.name = BSP_PIT;
173        if ( ! BSP_get_current_rtems_irq_handler(&clockIrqConnData)) {
174                printk("Unable to stop system clock\n");
175                rtems_fatal_error_occurred(1);
176        }
177
178        BSP_remove_rtems_irq_handler (&clockIrqConnData);
179        clockIrqConnData.on   = ClockOn;
180        clockIrqConnData.off  = ClockOff;
181        clockIrqConnData.isOn = ClockIsOn;
182        clockIrqConnData.name = BSP_PIT;
183        clockIrqConnData.hdl  = new_clock_isr;
184        if (!BSP_install_rtems_irq_handler (&clockIrqConnData)) {
185                printk("Unable to connect Clock Irq handler\n");
186                rtems_fatal_error_occurred(1);
187        }
188        rtems_interrupt_enable(isrlevel);
189}
190
191
192/*
193 * Called via atexit()
194 * Remove the clock interrupt handler by setting handler to NULL
195 *
196 * This will not work on the 405GP because
197 * when bit's are set in TCR they can only be unset by a reset
198 */
199
200void Clock_exit(void)
201{
202    rtems_irq_connect_data clockIrqConnData;
203   
204    clockIrqConnData.name = BSP_PIT;
205    if (!BSP_get_current_rtems_irq_handler(&clockIrqConnData)) {
206      printk("Unable to stop system clock\n");
207      rtems_fatal_error_occurred(1);
208    }
209    BSP_remove_rtems_irq_handler (&clockIrqConnData);
210}
211
212
213rtems_device_driver Clock_initialize(
214  rtems_device_major_number major,
215  rtems_device_minor_number minor,
216  void *pargp
217)
218{
219  Install_clock( Clock_isr );
220 
221  /*
222   * make major/minor avail to others such as shared memory driver
223   */
224  rtems_clock_major = major;
225  rtems_clock_minor = minor;
226 
227  return RTEMS_SUCCESSFUL;
228}
Note: See TracBrowser for help on using the repository browser.