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

4.104.114.84.95
Last change on this file since aee474b was ba71076, checked in by Joel Sherrill <joel.sherrill@…>, on 10/12/01 at 13:19:08

2001-10-11 Alexandra Kossovsky <sasha@…>

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