OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libcpu/] [sh/] [sh7032/] [clock/] [ckinit.c] - Blame information for rev 173

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
2
 *  This file contains the clock driver the Hitachi SH 703X
3
 *
4
 *  Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and
5
 *           Bernd Becker (becker@faw.uni-ulm.de)
6
 *
7
 *  COPYRIGHT (c) 1997-1998, FAW Ulm, Germany
8
 *
9
 *  This program is distributed in the hope that it will be useful,
10
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
 *
13
 *
14
 *  COPYRIGHT (c) 1998.
15
 *  On-Line Applications Research Corporation (OAR).
16
 *  Copyright assigned to U.S. Government, 1994.
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.OARcorp.com/rtems/license.html.
21
 *
22
 *  $Id: ckinit.c,v 1.2 2001-09-27 12:01:31 chris Exp $
23
 */
24
 
25
#include <rtems.h>
26
 
27
#include <stdlib.h>
28
 
29
#include <rtems/libio.h>
30
#include <rtems/score/sh_io.h>
31
#include <rtems/score/sh.h>
32
#include <rtems/score/ispsh7032.h>
33
#include <rtems/score/iosh7032.h>
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
 */
82
static unsigned int sh_clicks_per_tick(
83
  unsigned int clicks_per_sec,
84
  unsigned int usec_per_tick )
85
{
86
#if 1
87
  unsigned int clicks_per_tick = 0 ;
88
 
89
  unsigned int b = clicks_per_sec ;
90
  unsigned int c = 1000000 ;
91
  unsigned int d = 1 ;
92
  unsigned int a = ( ( b / c ) * usec_per_tick ) / d;
93
 
94
  clicks_per_tick += a ;
95
 
96
  while ( ( b %= c ) > 0 )
97
  {
98
    c /= 10 ;
99
    d *= 10 ;
100
    a = ( ( b / c ) * usec_per_tick ) / d ;
101
    clicks_per_tick += a ;
102
  }
103
  return clicks_per_tick ;
104
#else
105
  double fclicks_per_tick =
106
    ((double) clicks_per_sec * (double) usec_per_tick) / 1000000.0 ;
107
  return (unsigned32) fclicks_per_tick ;
108
#endif
109
}
110
 
111
/*
112
 *  The interrupt vector number associated with the clock tick device
113
 *  driver.
114
 */
115
 
116
#define CLOCK_VECTOR IMIA0_ISP_V
117
 
118
/*
119
 *  Clock_driver_ticks is a monotonically increasing counter of the
120
 *  number of clock ticks since the driver was initialized.
121
 */
122
 
123
volatile rtems_unsigned32 Clock_driver_ticks;
124
 
125
static void Clock_exit( void );
126
static rtems_isr Clock_isr( rtems_vector_number vector );
127
 
128
/*
129
 *  Clock_isrs is the number of clock ISRs until the next invocation of
130
 *  the RTEMS clock tick routine.  The clock tick device driver
131
 *  gets an interrupt once a millisecond and counts down until the
132
 *  length of time between the user configured microseconds per tick
133
 *  has passed.
134
 */
135
 
136
rtems_unsigned32 Clock_isrs;              /* ISRs until next tick */
137
static rtems_unsigned32 Clock_isrs_const;        /* only calculated once */
138
 
139
/*
140
 * These are set by clock driver during its init
141
 */
142
 
143
rtems_device_major_number rtems_clock_major = ~0;
144
rtems_device_minor_number rtems_clock_minor;
145
 
146
/*
147
 *  The previous ISR on this clock tick interrupt vector.
148
 */
149
 
150
rtems_isr_entry  Old_ticker;
151
 
152
/*
153
 *  Isr Handler
154
 */
155
 
156
rtems_isr Clock_isr(
157
  rtems_vector_number vector
158
)
159
{
160
  /*
161
   * bump the number of clock driver ticks since initialization
162
   *
163
   * determine if it is time to announce the passing of tick as configured
164
   * to RTEMS through the rtems_clock_tick directive
165
   *
166
   * perform any timer dependent tasks
167
   */
168
  unsigned8 temp;
169
 
170
  /* reset the flags of the status register */
171
  temp = read8( ITU_TSR0) & ITU_STAT_MASK;
172
  write8( temp, ITU_TSR0);
173
 
174
  Clock_driver_ticks++ ;
175
 
176
  if( Clock_isrs == 1)
177
    {
178
      rtems_clock_tick();
179
      Clock_isrs = Clock_isrs_const;
180
    }
181
  else
182
    {
183
      Clock_isrs-- ;
184
    }
185
}
186
 
187
/*
188
 *  Install_clock
189
 *
190
 *  Install a clock tick handler and reprograms the chip.  This
191
 *  is used to initially establish the clock tick.
192
 */
193
 
194
void Install_clock(
195
  rtems_isr_entry clock_isr
196
)
197
{
198
  unsigned8 temp8 = 0;
199
  unsigned32 microseconds_per_tick ;
200
  unsigned32 cclicks_per_tick ;
201
  unsigned16 Clock_limit ;
202
 
203
  /*
204
   *  Initialize the clock tick device driver variables
205
   */
206
 
207
  Clock_driver_ticks = 0;
208
 
209
  if ( rtems_configuration_get_microseconds_per_tick() != 0 )
210
    microseconds_per_tick = rtems_configuration_get_microseconds_per_tick() ;
211
  else
212
    microseconds_per_tick = 10000 ; /* 10000 us */
213
 
214
  /* clock clicks per tick */
215
  cclicks_per_tick =
216
    sh_clicks_per_tick(
217
      rtems_cpu_configuration_get_clicks_per_second() / CLOCK_SCALE,
218
      microseconds_per_tick );
219
 
220
  Clock_isrs_const = cclicks_per_tick >> 16 ;
221
  if ( ( cclicks_per_tick | 0xffff ) > 0 )
222
    Clock_isrs_const++ ;
223
  Clock_limit = cclicks_per_tick / Clock_isrs_const ;
224
  Clock_isrs = Clock_isrs_const;
225
 
226
  rtems_interrupt_catch( Clock_isr, CLOCK_VECTOR, &Old_ticker );
227
  /*
228
   *  Hardware specific initialize goes here
229
   */
230
 
231
  /* stop Timer 0 */
232
  temp8 = read8( ITU_TSTR) & ITU0_STARTMASK;
233
  write8( temp8, ITU_TSTR);
234
 
235
  /* set initial counter value to 0 */
236
  write16( 0, ITU_TCNT0);
237
 
238
  /* Timer 0 runs independent */
239
  temp8 = read8( ITU_TSNC) & ITU0_SYNCMASK;
240
  write8( temp8, ITU_TSNC);
241
 
242
  /* Timer 0 normal mode */
243
  temp8 = read8( ITU_TMDR) & ITU0_MODEMASK;
244
  write8( temp8, ITU_TMDR);
245
 
246
  /* TCNT is cleared by GRA ; internal clock /4 */
247
  write8( ITU0_TCRMASK , ITU_TCR0);
248
 
249
  /* use GRA without I/O - pins  */
250
  write8( ITU0_TIORVAL, ITU_TIOR0);
251
 
252
  /* reset flags of the status register */
253
  temp8 = read8( ITU_TSR0) & ITU_STAT_MASK;
254
  write8( temp8, ITU_TSR0);
255
 
256
  /* Irq if is equal GRA */
257
  temp8 = read8( ITU_TIER0) | ITU0_TIERMASK;
258
  write8( temp8, ITU_TIER0);
259
 
260
  /* set interrupt priority */
261
  if( sh_set_irq_priority( CLOCK_VECTOR, CLOCKPRIO ) != RTEMS_SUCCESSFUL)
262
    rtems_fatal_error_occurred( RTEMS_NOT_CONFIGURED);
263
 
264
  /* set counter limits */
265
  write16( Clock_limit, ITU_GRA0);
266
 
267
  /* start counter */
268
  temp8 = read8( ITU_TSTR) |~ITU0_STARTMASK;
269
  write8( temp8, ITU_TSTR);
270
 
271
  /*
272
   *  Schedule the clock cleanup routine to execute if the application exits.
273
   */
274
 
275
  atexit( Clock_exit );
276
}
277
 
278
/*
279
 *  Clean up before the application exits
280
 */
281
 
282
void Clock_exit( void )
283
{
284
  unsigned8 temp8 = 0;
285
 
286
  /* turn off the timer interrupts */
287
  /* set interrupt priority to 0 */
288
  if( sh_set_irq_priority( CLOCK_VECTOR, 0 ) != RTEMS_SUCCESSFUL)
289
    rtems_fatal_error_occurred( RTEMS_UNSATISFIED);
290
 
291
/*
292
 *   temp16 = read16( ITU_TIER0) & IPRC_ITU0_IRQMASK;
293
 *   write16( temp16, ITU_TIER0);
294
 */
295
 
296
  /* stop counter */
297
  temp8 = read8( ITU_TSTR) & ITU0_STARTMASK;
298
  write8( temp8, ITU_TSTR);
299
 
300
  /* old vector shall not be installed */
301
}
302
 
303
/*
304
 *  Clock_initialize
305
 *
306
 *  Device driver entry point for clock tick driver initialization.
307
 */
308
 
309
rtems_device_driver Clock_initialize(
310
  rtems_device_major_number major,
311
  rtems_device_minor_number minor,
312
  void *pargp
313
)
314
{
315
  Install_clock( Clock_isr );
316
 
317
  /*
318
   * make major/minor avail to others such as shared memory driver
319
   */
320
 
321
  rtems_clock_major = major;
322
  rtems_clock_minor = minor;
323
 
324
  return RTEMS_SUCCESSFUL;
325
}
326
 
327
rtems_device_driver Clock_control(
328
  rtems_device_major_number major,
329
  rtems_device_minor_number minor,
330
  void *pargp
331
)
332
{
333
  rtems_unsigned32 isrlevel;
334
  rtems_libio_ioctl_args_t *args = pargp;
335
 
336
  if (args != 0)
337
    {
338
      /*
339
       * This is hokey, but until we get a defined interface
340
       * to do this, it will just be this simple...
341
       */
342
 
343
      if (args->command == rtems_build_name('I', 'S', 'R', ' '))
344
        {
345
          Clock_isr(CLOCK_VECTOR);
346
        }
347
      else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
348
        {
349
          rtems_isr_entry       ignored ;
350
          rtems_interrupt_disable( isrlevel );
351
          rtems_interrupt_catch( args->buffer, CLOCK_VECTOR, &ignored );
352
 
353
          rtems_interrupt_enable( isrlevel );
354
        }
355
    }
356
  return RTEMS_SUCCESSFUL;
357
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.