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 12/05/19 at 18:22:33

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
RevLine 
[f8b27df9]1/*
2 *  This file contains the clock driver the Hitachi SH 703X
[3dc9d80f]3 */
4
5/*
[f8b27df9]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.
[3906b3ea]14 *
[f8b27df9]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
[c499856]20 *  http://www.rtems.org/license/LICENSE.
[f8b27df9]21 */
22
[f817b02]23#include <rtems.h>
[f8b27df9]24
25#include <stdlib.h>
26
[3dc9d80f]27#include <rtems/clockdrv.h>
[f8b27df9]28#include <rtems/score/sh_io.h>
29#include <rtems/score/sh.h>
[4a238002]30#include <rtems/score/ispsh7032.h>
31#include <rtems/score/iosh7032.h>
[f8b27df9]32
[99f6793]33extern uint32_t bsp_clicks_per_second;
34
[f8b27df9]35#ifndef CLOCKPRIO
36#define CLOCKPRIO 10
37#endif
38
[4a238002]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
[3906b3ea]44/*
[4a238002]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 */
[3906b3ea]48
[4a238002]49#define I_CLK_PHI       I_CLK_PHI_4
50#define CLOCK_SCALE     (1<<I_CLK_PHI)
51
[f8b27df9]52#define ITU0_STARTMASK  0xfe
53#define ITU0_SYNCMASK   0xfe
54#define ITU0_MODEMASK   0xfe
[4a238002]55#define ITU0_TCRMASK    (0x20 | I_CLK_PHI)
[f8b27df9]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
[4a238002]62/*
63 * clicks_per_tick := clicks_per_sec * usec_per_tick
64 *
65 * This is a very expensive function ;-)
[3906b3ea]66 *
[4a238002]67 * Below are two variants:
68 * 1. A variant applying integer arithmetics, only.
69 * 2. A variant applying floating point arithmetics
70 *
[3906b3ea]71 * The floating point variant pulls in the fmath routines when linking,
[4a238002]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 */
[3906b3ea]82static unsigned int sh_clicks_per_tick(
[4a238002]83  unsigned int clicks_per_sec,
[99f6793]84  unsigned int usec_per_tick
85)
[4a238002]86{
87#if 1
88  unsigned int clicks_per_tick = 0 ;
[3906b3ea]89
[4a238002]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 ;
[3906b3ea]103  }
[4a238002]104  return clicks_per_tick ;
105#else
[3906b3ea]106  double fclicks_per_tick =
[4a238002]107    ((double) clicks_per_sec * (double) usec_per_tick) / 1000000.0 ;
[e75cef9]108  return (uint32_t) fclicks_per_tick ;
[4a238002]109#endif
110}
111
[f8b27df9]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
[e96a950b]124volatile uint32_t   Clock_driver_ticks;
[f8b27df9]125
[a6b2080]126static void Clock_exit( void );
[f8b27df9]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
[e96a950b]137uint32_t   Clock_isrs;              /* ISRs until next tick */
138static uint32_t   Clock_isrs_const;        /* only calculated once */
[f8b27df9]139
140/*
141 *  The previous ISR on this clock tick interrupt vector.
142 */
143rtems_isr_entry  Old_ticker;
144
145/*
146 *  Isr Handler
147 */
[3dc9d80f]148static rtems_isr Clock_isr(
[f8b27df9]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   */
[e96a950b]160  uint8_t   temp;
[f8b27df9]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 */
[3dc9d80f]185static void Install_clock(
[f8b27df9]186  rtems_isr_entry clock_isr
187)
188{
[e96a950b]189  uint8_t   temp8 = 0;
[99f6793]190  uint32_t   microseconds_per_tick;
191  uint32_t   cclicks_per_tick;
192  uint16_t   Clock_limit;
[3906b3ea]193
[f8b27df9]194  /*
195   *  Initialize the clock tick device driver variables
196   */
197
198  Clock_driver_ticks = 0;
[3906b3ea]199
[4a238002]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 */
[99f6793]206  cclicks_per_tick = sh_clicks_per_tick(
207     bsp_clicks_per_second / CLOCK_SCALE, microseconds_per_tick );
[4a238002]208
209  Clock_isrs_const = cclicks_per_tick >> 16 ;
[3906b3ea]210  if ( ( cclicks_per_tick | 0xffff ) > 0 )
[4a238002]211    Clock_isrs_const++ ;
212  Clock_limit = cclicks_per_tick / Clock_isrs_const ;
[f8b27df9]213  Clock_isrs = Clock_isrs_const;
214
[0dd1d44]215  rtems_interrupt_catch( Clock_isr, CLOCK_VECTOR, &Old_ticker );
[f8b27df9]216  /*
[0dd1d44]217   *  Hardware specific initialize goes here
[f8b27df9]218   */
[3906b3ea]219
[0dd1d44]220  /* stop Timer 0 */
221  temp8 = read8( ITU_TSTR) & ITU0_STARTMASK;
222  write8( temp8, ITU_TSTR);
[f8b27df9]223
[0dd1d44]224  /* set initial counter value to 0 */
225  write16( 0, ITU_TCNT0);
[f8b27df9]226
[0dd1d44]227  /* Timer 0 runs independent */
228  temp8 = read8( ITU_TSNC) & ITU0_SYNCMASK;
229  write8( temp8, ITU_TSNC);
[f8b27df9]230
[0dd1d44]231  /* Timer 0 normal mode */
232  temp8 = read8( ITU_TMDR) & ITU0_MODEMASK;
233  write8( temp8, ITU_TMDR);
[f8b27df9]234
[0dd1d44]235  /* TCNT is cleared by GRA ; internal clock /4 */
236  write8( ITU0_TCRMASK , ITU_TCR0);
[f8b27df9]237
[0dd1d44]238  /* use GRA without I/O - pins  */
[3906b3ea]239  write8( ITU0_TIORVAL, ITU_TIOR0);
240
[0dd1d44]241  /* reset flags of the status register */
242  temp8 = read8( ITU_TSR0) & ITU_STAT_MASK;
243  write8( temp8, ITU_TSR0);
[f8b27df9]244
[0dd1d44]245  /* Irq if is equal GRA */
246  temp8 = read8( ITU_TIER0) | ITU0_TIERMASK;
247  write8( temp8, ITU_TIER0);
[f8b27df9]248
[0dd1d44]249  /* set interrupt priority */
250  if( sh_set_irq_priority( CLOCK_VECTOR, CLOCKPRIO ) != RTEMS_SUCCESSFUL)
251    rtems_fatal_error_occurred( RTEMS_NOT_CONFIGURED);
[f8b27df9]252
[0dd1d44]253  /* set counter limits */
254  write16( Clock_limit, ITU_GRA0);
[3906b3ea]255
[0dd1d44]256  /* start counter */
257  temp8 = read8( ITU_TSTR) |~ITU0_STARTMASK;
258  write8( temp8, ITU_TSTR);
[f8b27df9]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{
[e96a950b]272  uint8_t   temp8 = 0;
[f8b27df9]273
[0dd1d44]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);
[f8b27df9]278
279/*
280 *   temp16 = read16( ITU_TIER0) & IPRC_ITU0_IRQMASK;
281 *   write16( temp16, ITU_TIER0);
282 */
283
[0dd1d44]284  /* stop counter */
285  temp8 = read8( ITU_TSTR) & ITU0_STARTMASK;
286  write8( temp8, ITU_TSTR);
[f8b27df9]287
[0dd1d44]288  /* old vector shall not be installed */
[f8b27df9]289}
290
[bb99cd0d]291void _Clock_Initialize( void )
[f8b27df9]292{
293  Install_clock( Clock_isr );
294}
Note: See TracBrowser for help on using the repository browser.