source: rtems/c/src/lib/libcpu/sh/sh7032/clock/ckinit.c @ 4a238002

4.104.114.84.95
Last change on this file since 4a238002 was 4a238002, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 18, 1999 at 9:22:58 PM

Patch from "John M. Mills" <jmills@…> with subsequent cleanup from
Ralf Corsepius <corsepiu@…> that adds initial Hitachi SH-2
support to RTEMS. Ralf's comments are:

Changes:
------

  1. SH-Port:
  • Many files renamed.
  • CONSOLE_DEVNAME and MHZ defines removed from libcpu.
  • console.c moved to libbsp/sh/shared, build in libbsp/sh/<BSP>/console applying VPATH.
  • CONSOLE_DEVNAME made BSP-specific, replacement is defined in bsp.h
  • MHZ define replaced with HZ (extendent resolution) in custom/*.cfg
  • -DHZ=HZ used in bspstart.c, only
  • Makefile variable HZ used in bsp-dependent directories only.
  1. SH1-Port
  • clock-driver rewritten to provide better resolution for odd CPU frequencies. This driver is only partially tested on hardware, ie. sightly experimental, but I don't expect severe problems with it.
  • Polling SCI-driver added. This driver is experimental and completly untested yet. Therefore it is not yet used for the console (/dev/console is still pointing to /dev/null, cf. gensh1/bsp.h).
  • minor changes to the timer driver
  • SH1 specific delay()/CPU_delay() now is implemented as a function
  1. SH2-Port
  • Merged
  • IMO, the code is still in its infancy. Therefore I have interspersed comments (FIXME) it for items which I think John should look after.
  • sci and console drivers partially rewritten and extended (John, I hope you don't mind).
  • Copyright notices are not yet adapted
  • Property mode set to 100644
File size: 8.7 KB
Line 
1/*
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$
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 */
82static 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
123volatile rtems_unsigned32 Clock_driver_ticks;
124
125static void Clock_exit( void );
126static 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
136rtems_unsigned32 Clock_isrs;              /* ISRs until next tick */
137static rtems_unsigned32 Clock_isrs_const;        /* only calculated once */
138
139/*
140 * These are set by clock driver during its init
141 */
142 
143rtems_device_major_number rtems_clock_major = ~0;
144rtems_device_minor_number rtems_clock_minor;
145
146/*
147 *  The previous ISR on this clock tick interrupt vector.
148 */
149
150rtems_isr_entry  Old_ticker;
151
152/*
153 *  Isr Handler
154 */
155
156rtems_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
194void 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  /*
227   *  If ticks_per_timeslice is configured as non-zero, then the user
228   *  wants a clock tick.
229   */
230
231  if ( rtems_configuration_get_ticks_per_timeslice() ) {
232    rtems_interrupt_catch( Clock_isr, CLOCK_VECTOR, &Old_ticker );
233    /*
234     *  Hardware specific initialize goes here
235     */
236   
237    /* stop Timer 0 */
238    temp8 = read8( ITU_TSTR) & ITU0_STARTMASK;
239    write8( temp8, ITU_TSTR);
240
241    /* set initial counter value to 0 */
242    write16( 0, ITU_TCNT0);
243
244    /* Timer 0 runs independent */
245    temp8 = read8( ITU_TSNC) & ITU0_SYNCMASK;
246    write8( temp8, ITU_TSNC);
247
248    /* Timer 0 normal mode */
249    temp8 = read8( ITU_TMDR) & ITU0_MODEMASK;
250    write8( temp8, ITU_TMDR);
251
252    /* TCNT is cleared by GRA ; internal clock /4 */
253    write8( ITU0_TCRMASK , ITU_TCR0);
254
255    /* use GRA without I/O - pins  */
256    write8( ITU0_TIORVAL, ITU_TIOR0); 
257   
258    /* reset flags of the status register */
259    temp8 = read8( ITU_TSR0) & ITU_STAT_MASK;
260    write8( temp8, ITU_TSR0);
261
262    /* Irq if is equal GRA */
263    temp8 = read8( ITU_TIER0) | ITU0_TIERMASK;
264    write8( temp8, ITU_TIER0);
265
266    /* set interrupt priority */
267    if( sh_set_irq_priority( CLOCK_VECTOR, CLOCKPRIO ) != RTEMS_SUCCESSFUL)
268      rtems_fatal_error_occurred( RTEMS_NOT_CONFIGURED);
269
270    /* set counter limits */
271    write16( Clock_limit, ITU_GRA0);
272   
273    /* start counter */
274    temp8 = read8( ITU_TSTR) |~ITU0_STARTMASK;
275    write8( temp8, ITU_TSTR);
276   
277  }
278
279  /*
280   *  Schedule the clock cleanup routine to execute if the application exits.
281   */
282
283  atexit( Clock_exit );
284}
285
286/*
287 *  Clean up before the application exits
288 */
289
290void Clock_exit( void )
291{
292  unsigned8 temp8 = 0;
293  if ( rtems_configuration_get_ticks_per_timeslice() ) {
294
295    /* turn off the timer interrupts */
296    /* set interrupt priority to 0 */
297    if( sh_set_irq_priority( CLOCK_VECTOR, 0 ) != RTEMS_SUCCESSFUL)
298      rtems_fatal_error_occurred( RTEMS_UNSATISFIED);
299
300/*
301 *   temp16 = read16( ITU_TIER0) & IPRC_ITU0_IRQMASK;
302 *   write16( temp16, ITU_TIER0);
303 */
304
305    /* stop counter */
306    temp8 = read8( ITU_TSTR) & ITU0_STARTMASK;
307    write8( temp8, ITU_TSTR);
308
309    /* old vector shall not be installed */
310  }
311}
312
313/*
314 *  Clock_initialize
315 *
316 *  Device driver entry point for clock tick driver initialization.
317 */
318
319rtems_device_driver Clock_initialize(
320  rtems_device_major_number major,
321  rtems_device_minor_number minor,
322  void *pargp
323)
324{
325  Install_clock( Clock_isr );
326 
327  /*
328   * make major/minor avail to others such as shared memory driver
329   */
330 
331  rtems_clock_major = major;
332  rtems_clock_minor = minor;
333 
334  return RTEMS_SUCCESSFUL;
335}
336
337rtems_device_driver Clock_control(
338  rtems_device_major_number major,
339  rtems_device_minor_number minor,
340  void *pargp
341)
342{
343  rtems_unsigned32 isrlevel;
344  rtems_libio_ioctl_args_t *args = pargp;
345 
346  if (args != 0)
347    {
348      /*
349       * This is hokey, but until we get a defined interface
350       * to do this, it will just be this simple...
351       */
352     
353      if (args->command == rtems_build_name('I', 'S', 'R', ' '))
354        {
355          Clock_isr(CLOCK_VECTOR);
356        }
357      else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
358        {
359          rtems_isr_entry       ignored ;
360          rtems_interrupt_disable( isrlevel );
361          rtems_interrupt_catch( args->buffer, CLOCK_VECTOR, &ignored );
362         
363          rtems_interrupt_enable( isrlevel );
364        }
365    }
366  return RTEMS_SUCCESSFUL;
367}
Note: See TracBrowser for help on using the repository browser.