source: rtems/c/src/lib/libcpu/sh/sh7750/clock/ckinit.c @ 4cf920c4

4.104.114.84.95
Last change on this file since 4cf920c4 was f08c3a86, checked in by Joel Sherrill <joel.sherrill@…>, on 10/12/01 at 21:00:22

2001-10-12 Joel Sherrill <joel@…>

  • clock/ckinit.c, include/iosh7750.h, include/ipl.h, include/ispsh7750.h, sci/console.c, sci/sh4uart.c, score/cpu_asm.c, score/ispsh7750.c, timer/timer.c: Fixed typo.
  • Property mode set to 100644
File size: 7.6 KB
Line 
1/*
2 * This file contains the generic RTEMS clock driver the Hitachi SH 7750
3 *
4 * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
5 * Author: Victor V. Vengerov <vvv@oktet.ru>
6 *
7 *  COPYRIGHT (c) 2001
8 *  On-Line Applications Research Corporation (OAR).
9 *
10 *  The license and distribution terms for this file may be
11 *  found in the file LICENSE in this distribution or at
12 *  http://www.OARcorp.com/rtems/license.html.
13 *
14 *  $Id$
15 */
16
17#include <rtems.h>
18
19#include <stdlib.h>
20
21#include <rtems/libio.h>
22#include <rtems/score/sh_io.h>
23#include <rtems/score/sh.h>
24#include <rtems/score/ispsh7750.h>
25#include <rtems/score/iosh7750.h>
26
27#ifndef CLOCKPRIO
28#define CLOCKPRIO 10
29#endif
30
31/* Clock timer prescaler division ratio */
32#define CLOCK_PRESCALER 4
33#define TCR0_TPSC       SH7750_TCR_TPSC_DIV4
34
35/*
36 *  The interrupt vector number associated with the clock tick device
37 *  driver.
38 */
39
40#define CLOCK_VECTOR SH7750_EVT_TO_NUM(SH7750_EVT_TUNI0)
41
42/*
43 *  Clock_driver_ticks is a monotonically increasing counter of the
44 *  number of clock ticks since the driver was initialized.
45 */
46
47volatile rtems_unsigned32 Clock_driver_ticks;
48
49static void Clock_exit( void );
50static rtems_isr Clock_isr( rtems_vector_number vector );
51
52/*
53 * These are set by clock driver during its init
54 */
55rtems_device_major_number rtems_clock_major = ~0;
56rtems_device_minor_number rtems_clock_minor;
57
58/*
59 *  The previous ISR on this clock tick interrupt vector.
60 */
61
62rtems_isr_entry  Old_ticker;
63
64/*
65 *  Isr Handler
66 */
67
68/* Clock_isr --
69 *     Clock interrupt handling routine.
70 *
71 * PARAMETERS:
72 *     vector - interrupt vector number
73 *
74 * RETURNS:
75 *     none
76 */
77rtems_isr
78Clock_isr(rtems_vector_number vector)
79{
80    unsigned16 tcr;
81
82    /* reset the timer underflow flag */
83    tcr = read16(SH7750_TCR0);
84    write16(tcr & ~SH7750_TCR_UNF, SH7750_TCR0);
85
86    /* Increment the clock interrupt counter */
87    Clock_driver_ticks++ ;
88
89    /* Invoke rtems clock service routine */
90    rtems_clock_tick();
91}
92
93/* Install_clock --
94 *     Install a clock tick handler and reprograms the chip.  This
95 *     is used to initially establish the clock tick.
96 *
97 * PARAMETERS:
98 *     clock_isr - Clock interrupt stay routine
99 *
100 * RETURNS:
101 *     none
102 *
103 * SIDE EFFECTS:
104 *     Establish clock interrupt handler, configure Timer 0 hardware
105 */
106void
107Install_clock(rtems_isr_entry clock_isr)
108{
109    int cpudiv = 1; /* CPU frequency divider */
110    int tidiv = 1;  /* Timer input frequency divider */
111    unsigned32 timer_divider; /* Calculated Timer Divider value */
112    unsigned8 temp8;
113    unsigned16 temp16;
114 
115    /*
116     *  Initialize the clock tick device driver variables
117     */
118
119    Clock_driver_ticks = 0;
120
121    /* Get CPU frequency divider from clock unit */
122    switch (read16(SH7750_FRQCR) & SH7750_FRQCR_IFC)
123    {
124        case SH7750_FRQCR_IFCDIV1:
125            cpudiv = 1;
126            break;
127       
128        case SH7750_FRQCR_IFCDIV2:
129            cpudiv = 2;
130            break;
131           
132        case SH7750_FRQCR_IFCDIV3:
133            cpudiv = 3;
134            break;
135       
136        case SH7750_FRQCR_IFCDIV4:
137            cpudiv = 4;
138            break;
139       
140        case SH7750_FRQCR_IFCDIV6:
141            cpudiv = 6;
142            break;
143       
144        case SH7750_FRQCR_IFCDIV8:
145            cpudiv = 8;
146            break;
147       
148        default:
149            rtems_fatal_error_occurred( RTEMS_NOT_CONFIGURED);
150    }
151
152    /* Get peripheral module frequency divider from clock unit */
153    switch (read16(SH7750_FRQCR) & SH7750_FRQCR_PFC)
154    {
155        case SH7750_FRQCR_PFCDIV2:
156            tidiv = 2 * CLOCK_PRESCALER;
157            break;
158           
159        case SH7750_FRQCR_PFCDIV3:
160            tidiv = 3 * CLOCK_PRESCALER;
161            break;
162       
163        case SH7750_FRQCR_PFCDIV4:
164            tidiv = 4 * CLOCK_PRESCALER;
165            break;
166       
167        case SH7750_FRQCR_PFCDIV6:
168            tidiv = 6 * CLOCK_PRESCALER;
169            break;
170       
171        case SH7750_FRQCR_PFCDIV8:
172            tidiv = 8 * CLOCK_PRESCALER;
173            break;
174       
175        default:
176            rtems_fatal_error_occurred( RTEMS_NOT_CONFIGURED);
177    }
178    timer_divider =
179        (rtems_cpu_configuration_get_clicks_per_second() *
180         cpudiv / (tidiv*1000000)) *
181        rtems_configuration_get_microseconds_per_tick();
182
183    /*
184     *  Hardware specific initialization
185     */
186 
187    /* Stop the Timer 0 */
188    temp8 = read8(SH7750_TSTR);
189    temp8 &= ~SH7750_TSTR_STR0;
190    write8(temp8, SH7750_TSTR);
191
192    /* Establish interrupt handler */
193    rtems_interrupt_catch( Clock_isr, CLOCK_VECTOR, &Old_ticker );
194
195    /* Reset counter */
196    write32(timer_divider, SH7750_TCNT0);
197
198    /* Load divider */
199    write32(timer_divider, SH7750_TCOR0);
200   
201    write16(
202        SH7750_TCR_UNIE |        /* Enable Underflow Interrupt */
203        SH7750_TCR_CKEG_RAISE |  /* Count on rising edge */
204        TCR0_TPSC,               /* Timer prescaler ratio */
205        SH7750_TCR0);
206
207    /* Set clock interrupt priority */
208    temp16 = read16(SH7750_IPRA);
209    temp16 = (temp16 & ~SH7750_IPRA_TMU0) | (CLOCKPRIO << SH7750_IPRA_TMU0_S);
210    write16(temp16, SH7750_IPRA);
211
212    /* Start the Timer 0 */
213    temp8 = read8(SH7750_TSTR);
214    temp8 |= SH7750_TSTR_STR0;
215    write8(temp8, SH7750_TSTR);
216
217    /*
218     *  Schedule the clock cleanup routine to execute if the application exits.
219     */
220
221    atexit( Clock_exit );
222}
223
224/* Clock_exit --
225 *     Clean up before the application exits
226 *
227 * PARAMETERS:
228 *     none
229 *
230 * RETURNS:
231 *     none
232 *
233 * SIDE EFFECTS:
234 *     Stop Timer 0 counting, set timer 0 interrupt priority level to 0.
235 */
236void
237Clock_exit(void)
238{
239    unsigned8 temp8 = 0;
240    unsigned16 temp16 = 0;
241
242    /* turn off the timer interrupts */
243    /* Stop the Timer 0 */
244    temp8 = read8(SH7750_TSTR);
245    temp8 &= ~SH7750_TSTR_STR0;
246    write8(temp8, SH7750_TSTR);
247
248    /* Lower timer interrupt priority to 0 */
249    temp16 = read16(SH7750_IPRA);
250    temp16 = (temp16 & ~SH7750_IPRA_TMU0) | (0 << SH7750_IPRA_TMU0_S);
251    write16(temp16, SH7750_IPRA);
252
253  /* old vector shall not be installed */
254}
255
256/* Clock_initialize --
257 *     Device driver entry point for clock tick driver initialization.
258 *
259 * PARAMETERS:
260 *     major - clock major device number
261 *     minor - clock minor device number
262 *     pargp - driver initialize primitive argument, not used
263 *
264 * RETURNS:
265 *     RTEMS_SUCCESSFUL
266 */
267rtems_device_driver
268Clock_initialize(rtems_device_major_number major,
269                 rtems_device_minor_number minor,
270                 void *pargp)
271{
272    Install_clock( Clock_isr );
273 
274    /*
275     * make major/minor avail to others such as shared memory driver
276     */
277    rtems_clock_major = major;
278    rtems_clock_minor = minor;
279 
280    return RTEMS_SUCCESSFUL;
281}
282
283/* Clock_control --
284 *     Device driver entry point for clock driver IOCTL functions.
285 *
286 * PARAMETERS:
287 *     major - clock major device number
288 *     minor - clock minor device number
289 *     pargp - driver ioctl primitive argument, not used
290 *
291 * RETURNS:
292 *     RTEMS_SUCCESSFUL
293 */
294rtems_device_driver
295Clock_control(rtems_device_major_number major,
296              rtems_device_minor_number minor,
297              void *pargp)
298{
299  rtems_unsigned32 isrlevel;
300  rtems_libio_ioctl_args_t *args = pargp;
301 
302  if (args != 0)
303    {
304      /*
305       * This is hokey, but until we get a defined interface
306       * to do this, it will just be this simple...
307       */
308     
309      if (args->command == rtems_build_name('I', 'S', 'R', ' '))
310        {
311          Clock_isr(CLOCK_VECTOR);
312        }
313      else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
314        {
315          rtems_isr_entry       ignored ;
316          rtems_interrupt_disable( isrlevel );
317          rtems_interrupt_catch( args->buffer, CLOCK_VECTOR, &ignored );
318         
319          rtems_interrupt_enable( isrlevel );
320        }
321    }
322  return RTEMS_SUCCESSFUL;
323}
Note: See TracBrowser for help on using the repository browser.