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

4.115
Last change on this file since c499856 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

  • Property mode set to 100644
File size: 6.5 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.rtems.org/license/LICENSE.
13 */
14
15#include <rtems.h>
16
17#include <stdlib.h>
18
19#include <rtems/libio.h>
20#include <rtems/score/sh_io.h>
21#include <rtems/score/sh.h>
22#include <rtems/score/ispsh7750.h>
23#include <rtems/score/iosh7750.h>
24
25extern uint32_t bsp_clicks_per_second;
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 uint32_t   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    uint16_t   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    uint32_t   timer_divider; /* Calculated Timer Divider value */
112    uint8_t   temp8;
113    uint16_t   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        (bsp_clicks_per_second * cpudiv / (tidiv*1000000)) *
180        rtems_configuration_get_microseconds_per_tick();
181
182    /*
183     *  Hardware specific initialization
184     */
185
186    /* Stop the Timer 0 */
187    temp8 = read8(SH7750_TSTR);
188    temp8 &= ~SH7750_TSTR_STR0;
189    write8(temp8, SH7750_TSTR);
190
191    /* Establish interrupt handler */
192    rtems_interrupt_catch( Clock_isr, CLOCK_VECTOR, &Old_ticker );
193
194    /* Reset counter */
195    write32(timer_divider, SH7750_TCNT0);
196
197    /* Load divider */
198    write32(timer_divider, SH7750_TCOR0);
199
200    write16(
201        SH7750_TCR_UNIE |        /* Enable Underflow Interrupt */
202        SH7750_TCR_CKEG_RAISE |  /* Count on rising edge */
203        TCR0_TPSC,               /* Timer prescaler ratio */
204        SH7750_TCR0);
205
206    /* Set clock interrupt priority */
207    temp16 = read16(SH7750_IPRA);
208    temp16 = (temp16 & ~SH7750_IPRA_TMU0) | (CLOCKPRIO << SH7750_IPRA_TMU0_S);
209    write16(temp16, SH7750_IPRA);
210
211    /* Start the Timer 0 */
212    temp8 = read8(SH7750_TSTR);
213    temp8 |= SH7750_TSTR_STR0;
214    write8(temp8, SH7750_TSTR);
215
216    /*
217     *  Schedule the clock cleanup routine to execute if the application exits.
218     */
219
220    atexit( Clock_exit );
221}
222
223/* Clock_exit --
224 *     Clean up before the application exits
225 *
226 * PARAMETERS:
227 *     none
228 *
229 * RETURNS:
230 *     none
231 *
232 * SIDE EFFECTS:
233 *     Stop Timer 0 counting, set timer 0 interrupt priority level to 0.
234 */
235void
236Clock_exit(void)
237{
238    uint8_t   temp8 = 0;
239    uint16_t   temp16 = 0;
240
241    /* turn off the timer interrupts */
242    /* Stop the Timer 0 */
243    temp8 = read8(SH7750_TSTR);
244    temp8 &= ~SH7750_TSTR_STR0;
245    write8(temp8, SH7750_TSTR);
246
247    /* Lower timer interrupt priority to 0 */
248    temp16 = read16(SH7750_IPRA);
249    temp16 = (temp16 & ~SH7750_IPRA_TMU0) | (0 << SH7750_IPRA_TMU0_S);
250    write16(temp16, SH7750_IPRA);
251
252  /* old vector shall not be installed */
253}
254
255/* Clock_initialize --
256 *     Device driver entry point for clock tick driver initialization.
257 *
258 * PARAMETERS:
259 *     major - clock major device number
260 *     minor - clock minor device number
261 *     pargp - driver initialize primitive argument, not used
262 *
263 * RETURNS:
264 *     RTEMS_SUCCESSFUL
265 */
266rtems_device_driver
267Clock_initialize(rtems_device_major_number major,
268                 rtems_device_minor_number minor,
269                 void *pargp)
270{
271    Install_clock( Clock_isr );
272
273    /*
274     * make major/minor avail to others such as shared memory driver
275     */
276    rtems_clock_major = major;
277    rtems_clock_minor = minor;
278
279    return RTEMS_SUCCESSFUL;
280}
Note: See TracBrowser for help on using the repository browser.