source: rtems/c/src/lib/libcpu/powerpc/ppc403/clock/clock.c @ 3235ad9

4.104.114.84.95
Last change on this file since 3235ad9 was 3235ad9, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 23, 1995 at 7:30:23 PM

Support for variable length names added to Object Handler. This supports
both fixed length "raw" names and strings from the API's point of view.

Both inline and macro implementations were tested.

  • Property mode set to 100644
File size: 5.6 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.demon.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 *  COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
24 *  On-Line Applications Research Corporation (OAR).
25 *  All rights assigned to U.S. Government, 1994.
26 *
27 *  This material may be reproduced by or for the U.S. Government pursuant
28 *  to the copyright license under the clause at DFARS 252.227-7013.  This
29 *  notice must appear in all copies of this file and its derivatives.
30 *
31 *  clock.c,v 1.2 1995/05/31 16:59:06 joel Exp
32 */
33
34#include <bsp.h>
35#include <clockdrv.h>
36
37#include <stdlib.h>                     /* for atexit() */
38
39extern rtems_cpu_table           Cpu_table;             /* owned by BSP */
40
41volatile rtems_unsigned32 Clock_driver_ticks;
42static rtems_unsigned32 pit_value, tick_time;
43static rtems_boolean auto_restart;
44
45rtems_device_driver Clock_initialize(
46  rtems_device_major_number major,
47  rtems_device_minor_number minor,
48  void *pargp,
49  rtems_id tid,
50  rtems_unsigned32 *rval
51)
52{
53    Install_clock(Clock_isr);
54}
55
56
57void
58ReInstall_clock(rtems_isr_entry new_clock_isr)
59{
60    rtems_isr_entry previous_isr;
61    rtems_unsigned32 isrlevel = 0;
62
63    rtems_interrupt_disable(isrlevel);
64   
65    rtems_interrupt_catch(new_clock_isr, PPC_IRQ_PIT,
66                          &previous_isr);
67
68    rtems_interrupt_enable(isrlevel);
69}
70
71static INLINE rtems_unsigned32 get_itimer(void)
72{
73    register rtems_unsigned32 rc;
74
75    asm volatile ("mftblo %0" : "=r" ((rc)));
76
77    return rc;
78}
79
80void Install_clock(rtems_isr_entry clock_isr)
81{
82    rtems_isr_entry previous_isr;
83    rtems_unsigned32 pvr, iocr;
84
85    Clock_driver_ticks = 0;
86
87    asm volatile ("mfiocr %0" : "=r" (iocr));
88    iocr &= ~4;
89    iocr |= 4;  /* Select external timer clock */
90    asm volatile ("mtiocr %0" : "=r" (iocr) : "0" (iocr));
91
92    asm volatile ("mfpvr %0" : "=r" ((pvr)));
93
94    if (((pvr & 0xffff0000) >> 16) != 0x0020)
95        return; /* Not a ppc403 */
96
97    if ((pvr & 0xff00) == 0x0000) /* 403GA */
98        auto_restart = (pvr & 0x00f0) > 0x0000 ? 1 : 0;
99    else if ((pvr & 0xff00) == 0x0100) /* 403GB */
100        auto_restart = 1;
101
102    pit_value = BSP_Configuration.microseconds_per_tick *
103        Cpu_table.clicks_per_usec;
104
105    if (BSP_Configuration.ticks_per_timeslice)
106    {
107        register rtems_unsigned32 tcr;
108        /*
109         * initialize the interval here
110         * First tick is set to right amount of time in the future
111         * Future ticks will be incremented over last value set
112         * in order to provide consistent clicks in the face of
113         * interrupt overhead
114         */
115
116        rtems_interrupt_catch(clock_isr, PPC_IRQ_PIT,
117                              &previous_isr);
118
119        asm volatile ("mtpit %0" : : "r" (pit_value));
120
121        asm volatile ("mftcr %0" : "=r" ((tcr)));
122
123        tcr &= ~ 0x04400000;
124
125        tcr |= (auto_restart ? 0x04400000 : 0x04000000);
126
127        tick_time = get_itimer() + pit_value;
128
129        asm volatile ("mttcr %0" : "=r" ((tcr)) : "0" ((tcr)));
130    }
131    atexit(Clock_exit);
132}
133
134
135rtems_isr
136Clock_isr(rtems_vector_number vector)
137{
138    if (!auto_restart)
139        {
140            rtems_unsigned32 clicks_til_next_interrupt;
141            rtems_unsigned32 itimer_value;
142
143            /*
144             * setup for next interrupt; making sure the new value is reasonably
145             * in the future.... in case we lost out on an interrupt somehow
146             */
147
148            itimer_value = get_itimer();
149            tick_time += pit_value;
150
151            /*
152             * how far away is next interrupt *really*
153             * It may be a long time; this subtraction works even if
154             * Clock_clicks_interrupt < Clock_clicks_low_order via
155             * the miracle of unsigned math.
156             */
157            clicks_til_next_interrupt = tick_time - itimer_value;
158
159            /*
160             * If it is too soon then bump it up.
161             * This should only happen if CPU_HPPA_CLICKS_PER_TICK is too small.
162             * But setting it low is useful for debug, so...
163             */
164
165            if (clicks_til_next_interrupt < 400)
166                {
167                    tick_time = itimer_value + 1000;
168                    clicks_til_next_interrupt = 1000;
169                    /* XXX: count these! this should be rare */
170                }
171
172            /*
173             * If it is too late, that means we missed the interrupt somehow.
174             * Rather than wait 35-50s for a wrap, we just fudge it here.
175             */
176           
177            if (clicks_til_next_interrupt > pit_value)
178                {
179                    tick_time = itimer_value + 1000;
180                    clicks_til_next_interrupt = 1000;
181                    /* XXX: count these! this should never happen :-) */
182                }
183
184            asm volatile ("mtpit %0" :: "r" (clicks_til_next_interrupt));
185        }
186
187    asm volatile ( "mttsr %0" :: "r" (0x08000000));
188
189    Clock_driver_ticks++;
190
191    rtems_clock_tick();
192}
193
194/*
195 * Called via atexit()
196 * Remove the clock interrupt handler by setting handler to NULL
197 */
198
199void
200Clock_exit(void)
201{
202    if ( BSP_Configuration.ticks_per_timeslice )
203    {
204        register rtems_unsigned32 tcr;
205
206        asm volatile ("mftcr %0" : "=r" ((tcr)));
207
208        tcr &= ~ 0x04400000;
209
210        asm volatile ("mttcr %0" : "=r" ((tcr)) : "0" ((tcr)));
211
212        (void) set_vector(0, PPC_IRQ_PIT, 1);
213    }
214}
215
Note: See TracBrowser for help on using the repository browser.