source: rtems/bsps/sh/gensh1/clock/ckinit.c @ bb99cd0d

5
Last change on this file since bb99cd0d was bb99cd0d, checked in by Sebastian Huber <sebastian.huber@…>, on Dec 5, 2019 at 6:22:33 PM

clock: Simplify driver initialization

Use a system initialization handler instead of a legacy IO driver.

Update #3834.

  • Property mode set to 100644
File size: 7.1 KB
Line 
1/*
2 *  This file contains the clock driver the Hitachi SH 703X
3 */
4
5/*
6 *  Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and
7 *           Bernd Becker (becker@faw.uni-ulm.de)
8 *
9 *  COPYRIGHT (c) 1997-1998, FAW Ulm, Germany
10 *
11 *  This program is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 *
15 *  COPYRIGHT (c) 1998.
16 *  On-Line Applications Research Corporation (OAR).
17 *
18 *  The license and distribution terms for this file may be
19 *  found in the file LICENSE in this distribution or at
20 *  http://www.rtems.org/license/LICENSE.
21 */
22
23#include <rtems.h>
24
25#include <stdlib.h>
26
27#include <rtems/clockdrv.h>
28#include <rtems/score/sh_io.h>
29#include <rtems/score/sh.h>
30#include <rtems/score/ispsh7032.h>
31#include <rtems/score/iosh7032.h>
32
33extern uint32_t bsp_clicks_per_second;
34
35#ifndef CLOCKPRIO
36#define CLOCKPRIO 10
37#endif
38
39#define I_CLK_PHI_1     0
40#define I_CLK_PHI_2     1
41#define I_CLK_PHI_4     2
42#define I_CLK_PHI_8     3
43
44/*
45 * Set I_CLK_PHI to one of the I_CLK_PHI_X values from above to choose
46 * a PHI/X clock rate.
47 */
48
49#define I_CLK_PHI       I_CLK_PHI_4
50#define CLOCK_SCALE     (1<<I_CLK_PHI)
51
52#define ITU0_STARTMASK  0xfe
53#define ITU0_SYNCMASK   0xfe
54#define ITU0_MODEMASK   0xfe
55#define ITU0_TCRMASK    (0x20 | I_CLK_PHI)
56#define ITU_STAT_MASK   0xf8
57#define ITU0_IRQMASK    0xfe
58#define ITU0_TIERMASK   0x01
59#define IPRC_ITU0_MASK  0xff0f
60#define ITU0_TIORVAL    0x08
61
62/*
63 * clicks_per_tick := clicks_per_sec * usec_per_tick
64 *
65 * This is a very expensive function ;-)
66 *
67 * Below are two variants:
68 * 1. A variant applying integer arithmetics, only.
69 * 2. A variant applying floating point arithmetics
70 *
71 * The floating point variant pulls in the fmath routines when linking,
72 * resulting in slightly larger executables for applications that do not
73 * apply fmath otherwise. However, the imath variant is significantly slower
74 * than the fmath variant and more complex.
75 *
76 * Assuming that most applications will not use fmath, but are critical
77 * in memory size constraints, we apply the integer variant.
78 *
79 * To the sake of simplicity, we might abandon one of both variants in
80 * future.
81 */
82static unsigned int sh_clicks_per_tick(
83  unsigned int clicks_per_sec,
84  unsigned int usec_per_tick
85)
86{
87#if 1
88  unsigned int clicks_per_tick = 0 ;
89
90  unsigned int b = clicks_per_sec ;
91  unsigned int c = 1000000 ;
92  unsigned int d = 1 ;
93  unsigned int a = ( ( b / c ) * usec_per_tick ) / d;
94
95  clicks_per_tick += a ;
96
97  while ( ( b %= c ) > 0 )
98  {
99    c /= 10 ;
100    d *= 10 ;
101    a = ( ( b / c ) * usec_per_tick ) / d ;
102    clicks_per_tick += a ;
103  }
104  return clicks_per_tick ;
105#else
106  double fclicks_per_tick =
107    ((double) clicks_per_sec * (double) usec_per_tick) / 1000000.0 ;
108  return (uint32_t) fclicks_per_tick ;
109#endif
110}
111
112/*
113 *  The interrupt vector number associated with the clock tick device
114 *  driver.
115 */
116
117#define CLOCK_VECTOR IMIA0_ISP_V
118
119/*
120 *  Clock_driver_ticks is a monotonically increasing counter of the
121 *  number of clock ticks since the driver was initialized.
122 */
123
124volatile uint32_t   Clock_driver_ticks;
125
126static void Clock_exit( void );
127static rtems_isr Clock_isr( rtems_vector_number vector );
128
129/*
130 *  Clock_isrs is the number of clock ISRs until the next invocation of
131 *  the RTEMS clock tick routine.  The clock tick device driver
132 *  gets an interrupt once a millisecond and counts down until the
133 *  length of time between the user configured microseconds per tick
134 *  has passed.
135 */
136
137uint32_t   Clock_isrs;              /* ISRs until next tick */
138static uint32_t   Clock_isrs_const;        /* only calculated once */
139
140/*
141 *  The previous ISR on this clock tick interrupt vector.
142 */
143rtems_isr_entry  Old_ticker;
144
145/*
146 *  Isr Handler
147 */
148static rtems_isr Clock_isr(
149  rtems_vector_number vector
150)
151{
152  /*
153   * bump the number of clock driver ticks since initialization
154   *
155   * determine if it is time to announce the passing of tick as configured
156   * to RTEMS through the rtems_clock_tick directive
157   *
158   * perform any timer dependent tasks
159   */
160  uint8_t   temp;
161
162  /* reset the flags of the status register */
163  temp = read8( ITU_TSR0) & ITU_STAT_MASK;
164  write8( temp, ITU_TSR0);
165
166  Clock_driver_ticks++ ;
167
168  if( Clock_isrs == 1)
169    {
170      rtems_clock_tick();
171      Clock_isrs = Clock_isrs_const;
172    }
173  else
174    {
175      Clock_isrs-- ;
176    }
177}
178
179/*
180 *  Install_clock
181 *
182 *  Install a clock tick handler and reprograms the chip.  This
183 *  is used to initially establish the clock tick.
184 */
185static void Install_clock(
186  rtems_isr_entry clock_isr
187)
188{
189  uint8_t   temp8 = 0;
190  uint32_t   microseconds_per_tick;
191  uint32_t   cclicks_per_tick;
192  uint16_t   Clock_limit;
193
194  /*
195   *  Initialize the clock tick device driver variables
196   */
197
198  Clock_driver_ticks = 0;
199
200  if ( rtems_configuration_get_microseconds_per_tick() != 0 )
201    microseconds_per_tick = rtems_configuration_get_microseconds_per_tick() ;
202  else
203    microseconds_per_tick = 10000 ; /* 10000 us */
204
205  /* clock clicks per tick */
206  cclicks_per_tick = sh_clicks_per_tick(
207     bsp_clicks_per_second / CLOCK_SCALE, microseconds_per_tick );
208
209  Clock_isrs_const = cclicks_per_tick >> 16 ;
210  if ( ( cclicks_per_tick | 0xffff ) > 0 )
211    Clock_isrs_const++ ;
212  Clock_limit = cclicks_per_tick / Clock_isrs_const ;
213  Clock_isrs = Clock_isrs_const;
214
215  rtems_interrupt_catch( Clock_isr, CLOCK_VECTOR, &Old_ticker );
216  /*
217   *  Hardware specific initialize goes here
218   */
219
220  /* stop Timer 0 */
221  temp8 = read8( ITU_TSTR) & ITU0_STARTMASK;
222  write8( temp8, ITU_TSTR);
223
224  /* set initial counter value to 0 */
225  write16( 0, ITU_TCNT0);
226
227  /* Timer 0 runs independent */
228  temp8 = read8( ITU_TSNC) & ITU0_SYNCMASK;
229  write8( temp8, ITU_TSNC);
230
231  /* Timer 0 normal mode */
232  temp8 = read8( ITU_TMDR) & ITU0_MODEMASK;
233  write8( temp8, ITU_TMDR);
234
235  /* TCNT is cleared by GRA ; internal clock /4 */
236  write8( ITU0_TCRMASK , ITU_TCR0);
237
238  /* use GRA without I/O - pins  */
239  write8( ITU0_TIORVAL, ITU_TIOR0);
240
241  /* reset flags of the status register */
242  temp8 = read8( ITU_TSR0) & ITU_STAT_MASK;
243  write8( temp8, ITU_TSR0);
244
245  /* Irq if is equal GRA */
246  temp8 = read8( ITU_TIER0) | ITU0_TIERMASK;
247  write8( temp8, ITU_TIER0);
248
249  /* set interrupt priority */
250  if( sh_set_irq_priority( CLOCK_VECTOR, CLOCKPRIO ) != RTEMS_SUCCESSFUL)
251    rtems_fatal_error_occurred( RTEMS_NOT_CONFIGURED);
252
253  /* set counter limits */
254  write16( Clock_limit, ITU_GRA0);
255
256  /* start counter */
257  temp8 = read8( ITU_TSTR) |~ITU0_STARTMASK;
258  write8( temp8, ITU_TSTR);
259
260  /*
261   *  Schedule the clock cleanup routine to execute if the application exits.
262   */
263
264  atexit( Clock_exit );
265}
266
267/*
268 *  Clean up before the application exits
269 */
270void Clock_exit( void )
271{
272  uint8_t   temp8 = 0;
273
274  /* turn off the timer interrupts */
275  /* set interrupt priority to 0 */
276  if( sh_set_irq_priority( CLOCK_VECTOR, 0 ) != RTEMS_SUCCESSFUL)
277    rtems_fatal_error_occurred( RTEMS_UNSATISFIED);
278
279/*
280 *   temp16 = read16( ITU_TIER0) & IPRC_ITU0_IRQMASK;
281 *   write16( temp16, ITU_TIER0);
282 */
283
284  /* stop counter */
285  temp8 = read8( ITU_TSTR) & ITU0_STARTMASK;
286  write8( temp8, ITU_TSTR);
287
288  /* old vector shall not be installed */
289}
290
291void _Clock_Initialize( void )
292{
293  Install_clock( Clock_isr );
294}
Note: See TracBrowser for help on using the repository browser.