OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libbsp/] [m68k/] [gen68360/] [clock/] [ckinit.c] - Blame information for rev 30

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
2
 * This routine initializes the MC68360 Periodic Interval Timer
3
 *
4
 * The PIT has rather poor resolution, but it is easy to set up
5
 * and requires no housekeeping once it is going.
6
 *
7
 * Based on the `gen68302' board support package, and covered by the
8
 * original distribution terms.
9
 *
10
 * W. Eric Norum
11
 * Saskatchewan Accelerator Laboratory
12
 * University of Saskatchewan
13
 * Saskatoon, Saskatchewan, CANADA
14
 * eric@skatter.usask.ca
15
 *
16
 *  $Id: ckinit.c,v 1.2 2001-09-27 12:00:08 chris Exp $
17
 */
18
 
19
/*
20
 * Input parameters:    NONE
21
 *
22
 * Output parameters:   NONE
23
 *
24
 * COPYRIGHT (c) 1989-1999.
25
 * On-Line Applications Research Corporation (OAR).
26
 *
27
 * The license and distribution terms for this file may be
28
 * found in the file LICENSE in this distribution or at
29
 * http://www.OARcorp.com/rtems/license.html.
30
 */
31
 
32
#include <stdlib.h>                     /* for atexit() */
33
#include <bsp.h>
34
#include <rtems/libio.h>
35
#include "m68360.h"
36
 
37
#define CLOCK_VECTOR    120
38
#define CLOCK_IRQ_LEVEL 4
39
 
40
/*
41
 * Clock_driver_ticks is a monotonically increasing counter of the
42
 * number of clock ticks since the driver was initialized.
43
 */
44
volatile rtems_unsigned32 Clock_driver_ticks;
45
 
46
/*
47
 * These are set by clock driver during its init
48
 */
49
 
50
rtems_device_major_number rtems_clock_major = ~0;
51
rtems_device_minor_number rtems_clock_minor;
52
 
53
char M360DefaultWatchdogFeeder = 1;
54
 
55
/*
56
 * RTEMS and hardware have different notions of clock rate.
57
 */
58
static unsigned long rtems_nsec_per_tick;
59
static unsigned long pit_nsec_per_tick;
60
 
61
/*
62
 * Periodic interval timer interrupt handler
63
 */
64
 
65
rtems_isr
66
Clock_isr (rtems_vector_number vector)
67
{
68
        static unsigned long nsec;
69
 
70
        /*
71
         * See if it's really time for a `tick'
72
         */
73
        nsec += pit_nsec_per_tick;
74
        if (nsec >= rtems_nsec_per_tick) {
75
                nsec -= rtems_nsec_per_tick;
76
 
77
                /*
78
                 * Perform a dummy read of DPRAM.
79
                 * This works around a bug in Rev. B of the 68360
80
                 */
81
                m360.dpram0[0];
82
 
83
                /*
84
                 * Feed the watchdog
85
                 * Application code can override this by
86
                 * setting M360DefaultWatchdogFeeder to zero.
87
                 */
88
                if (M360DefaultWatchdogFeeder) {
89
                        m360.swsr = 0x55;
90
                        m360.swsr = 0xAA;
91
                }
92
 
93
                /*
94
                 * Announce the clock tick
95
                 */
96
                Clock_driver_ticks++;
97
                rtems_clock_tick();
98
        }
99
}
100
 
101
void
102
Clock_exit (void)
103
{
104
        /*
105
         * Turn off periodic interval timer
106
         */
107
        m360.pitr &= ~0xFF;
108
}
109
 
110
static void
111
Install_clock (rtems_isr_entry clock_isr)
112
{
113
        int divisor;
114
        extern int m360_clock_rate; /* This should be somewhere in a config file */
115
        unsigned long nsec_per_chip_tick = 1000000000 / m360_clock_rate;
116
        unsigned long nsec_per_pit_tick = 512 * nsec_per_chip_tick;
117
 
118
        Clock_driver_ticks = 0;
119
        /*
120
         * Choose periodic interval timer register value
121
         * The rate at which the periodic interval timer
122
         * can generate interrupts is almost certainly not
123
         * the same as desired by the BSP configuration.
124
         * Handle the difference by choosing the largest PIT
125
         * interval which is less than or equal to the RTEMS
126
         * interval and skipping some hardware interrupts.
127
         * To reduce the jitter in the calls to RTEMS the
128
         * hardware interrupt interval is never less than
129
         * the maximum non-prescaled value from the PIT.
130
         *
131
         * For a 25 MHz external clock the basic clock rate is
132
         *      40 nsec * 128 * 4 = 20.48 usec/tick
133
         */
134
 
135
        rtems_nsec_per_tick = BSP_Configuration.microseconds_per_tick * 1000;
136
        divisor = rtems_nsec_per_tick / nsec_per_pit_tick;
137
        if (divisor >= 256) {
138
                divisor = 255;
139
        } else if (divisor == 0) {
140
                divisor = 1;
141
        }
142
        pit_nsec_per_tick = nsec_per_pit_tick * divisor;
143
        m360.pitr &= ~0x1FF;
144
        m360.picr = (CLOCK_IRQ_LEVEL << 8) | CLOCK_VECTOR;
145
        set_vector (clock_isr, CLOCK_VECTOR, 1);
146
        m360.pitr |= divisor;
147
        atexit (Clock_exit);
148
}
149
 
150
rtems_device_driver
151
Clock_initialize(
152
        rtems_device_major_number major,
153
        rtems_device_minor_number minor,
154
        void *pargp
155
)
156
{
157
        Install_clock (Clock_isr);
158
 
159
        /*
160
         * make major/minor avail to others such as shared memory driver
161
         */
162
        rtems_clock_major = major;
163
        rtems_clock_minor = minor;
164
 
165
        return RTEMS_SUCCESSFUL;
166
}
167
 
168
rtems_device_driver Clock_control(
169
        rtems_device_major_number major,
170
        rtems_device_minor_number minor,
171
        void *pargp
172
)
173
{
174
        rtems_unsigned32 isrlevel;
175
        rtems_libio_ioctl_args_t *args = pargp;
176
 
177
        if (args) {
178
                /*
179
                 * This is hokey, but until we get a defined interface
180
                 * to do this, it will just be this simple...
181
                 */
182
                if (args->command == rtems_build_name('I', 'S', 'R', ' ')) {
183
                        Clock_isr( CLOCK_VECTOR);
184
                }
185
                else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) {
186
                        rtems_interrupt_disable( isrlevel );
187
                         (void) set_vector( args->buffer, CLOCK_VECTOR, 1 );
188
                        rtems_interrupt_enable( isrlevel );
189
                }
190
        }
191
        return RTEMS_SUCCESSFUL;
192
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.