source: rtems/c/src/lib/libcpu/powerpc/mpc8xx/clock/clock.c @ 359e537

4.104.115
Last change on this file since 359e537 was 359e537, checked in by Ralf Corsepius <ralf.corsepius@…>, on 11/30/09 at 05:09:41

Whitespace removal.

  • Property mode set to 100644
File size: 5.3 KB
Line 
1/*  clock.c
2 *
3 *  This routine initializes the PIT on the MPC8xx.
4 *  The tick frequency is specified by the bsp.
5 *
6 *  Author: Jay Monkman (jmonkman@frasca.com)
7 *  Copyright (C) 1998 by Frasca International, Inc.
8 *
9 *  Derived from c/src/lib/libcpu/ppc/ppc403/clock/clock.c:
10 *
11 *  Author: Andrew Bray <andy@i-cubed.co.uk>
12 *
13 *  COPYRIGHT (c) 1995 by i-cubed ltd.
14 *
15 *  To anyone who acknowledges that this file is provided "AS IS"
16 *  without any express or implied warranty:
17 *      permission to use, copy, modify, and distribute this file
18 *      for any purpose is hereby granted without fee, provided that
19 *      the above copyright notice and this notice appears in all
20 *      copies, and that the name of i-cubed limited not be used in
21 *      advertising or publicity pertaining to distribution of the
22 *      software without specific, written prior permission.
23 *      i-cubed limited makes no representations about the suitability
24 *      of this software for any purpose.
25 *
26 *  Derived from c/src/lib/libcpu/hppa1_1/clock/clock.c:
27 *
28 *  COPYRIGHT (c) 1989-2007.
29 *  On-Line Applications Research Corporation (OAR).
30 *
31 *  The license and distribution terms for this file may be
32 *  found in the file LICENSE in this distribution or at
33 *  http://www.rtems.com/license/LICENSE.
34 *
35 *  $Id$
36 */
37
38#include <rtems.h>
39#include <rtems/clockdrv.h>
40#include <rtems/libio.h>
41#include <rtems/powerpc/powerpc.h>
42
43#include <stdlib.h>                     /* for atexit() */
44#include <mpc8xx.h>
45
46volatile uint32_t   Clock_driver_ticks;
47extern volatile m8xx_t m8xx;
48extern int BSP_get_clock_irq_level(void);
49extern int BSP_connect_clock_handler(rtems_isr_entry);
50extern int BSP_disconnect_clock_handler(void);
51extern uint32_t bsp_clicks_per_usec;
52extern uint32_t bsp_clock_speed;
53
54void Clock_exit( void );
55
56/*
57 * These are set by clock driver during its init
58 */
59
60rtems_device_major_number rtems_clock_major = ~0;
61rtems_device_minor_number rtems_clock_minor;
62
63/*
64 *  ISR Handler
65 */
66rtems_isr Clock_isr(rtems_vector_number vector)
67{
68  m8xx.piscr |= M8xx_PISCR_PS;
69  Clock_driver_ticks++;
70  rtems_clock_tick();
71}
72
73void clockOn(void* unused)
74{
75  unsigned desiredLevel;
76  uint32_t   pit_value;
77  uint32_t   extclk;
78  bool force_prescaler = false;
79  uint32_t immr_val;
80
81  if (bsp_clicks_per_usec == 0) {
82    /*
83     * oscclk is too low for PIT, compute extclk and derive PIT from there
84     */
85    /*
86     * determine external input clock by examining the PLL settings
87     * this must be done differently depending on type of PLL
88     */
89    _mfspr(immr_val,M8xx_IMMR);
90    if (8 == ((immr_val & 0x0000FF00) >> 8)) {
91      /*
92       * for MPC866: complex PLL
93       */
94      uint32_t plprcr_val;
95      uint32_t mfn_value;
96      uint32_t mfd_value;
97      uint32_t mfi_value;
98      uint32_t pdf_value;
99      uint32_t s_value;
100
101      plprcr_val = m8xx.plprcr;
102      mfn_value  = (plprcr_val & (0xf8000000)) >> (31- 4);
103      mfd_value  = (plprcr_val & (0x07c00000)) >> (31- 9);
104      s_value    = (plprcr_val & (0x00300000)) >> (31-11);
105      mfi_value  = (plprcr_val & (0x000f0000)) >> (31-15);
106      pdf_value  = (plprcr_val & (0x00000006)) >> (31-30);
107      extclk = (((uint64_t)bsp_clock_speed)
108                * ((pdf_value + 1) * (mfd_value + 1))
109                / (mfi_value * (mfd_value + 1) + mfn_value)
110                * (1 << s_value));
111    }
112    else {
113      /*
114       * for MPC860/850 etc: simple PLL
115       */
116      uint32_t mf_value;
117      mf_value  = m8xx.plprcr >> 20;
118      extclk    = bsp_clock_speed / (mf_value+1);
119    }
120    pit_value = (extclk
121                 / 1000
122                 / 4
123                 * rtems_configuration_get_microseconds_per_tick()
124                 / 1000);
125    m8xx.sccr |=  (1<<23);
126    force_prescaler = true;
127  }
128  else {
129    pit_value = (rtems_configuration_get_microseconds_per_tick() *
130                 bsp_clicks_per_usec);
131
132    m8xx.sccr &= ~(1<<23);
133  }
134if ((pit_value > 0xffff) || force_prescaler){
135    /*
136     * try to activate prescaler
137     * NOTE: divider generates odd values now...
138     */
139    pit_value = pit_value / 128;
140    m8xx.sccr |= (1<<24);
141  }
142  else {
143    m8xx.sccr &= ~(1<<24);
144  }
145
146  if (pit_value > 0xffff) {           /* pit is only 16 bits long */
147    rtems_fatal_error_occurred(-1);
148  }
149  m8xx.pitc = pit_value - 1;
150
151  desiredLevel = BSP_get_clock_irq_level();
152  /* set PIT irq level, enable PIT, PIT interrupts */
153  /*  and clear int. status */
154  m8xx.piscr = M8xx_PISCR_PIRQ(desiredLevel) |
155    M8xx_PISCR_PTE | M8xx_PISCR_PS | M8xx_PISCR_PIE;
156}
157/*
158 * Called via atexit()
159 * Remove the clock interrupt handler by setting handler to NULL
160 */
161void
162clockOff(void* unused)
163{
164  /* disable PIT and PIT interrupts */
165  m8xx.piscr &= ~(M8xx_PISCR_PTE | M8xx_PISCR_PIE);
166}
167
168int clockIsOn(void* unused)
169{
170  if (m8xx.piscr & M8xx_PISCR_PIE) return 1;
171  return 0;
172}
173
174/*
175 * Called via atexit()
176 * Remove the clock interrupt handler by setting handler to NULL
177 */
178void
179Clock_exit(void)
180{
181  (void) BSP_disconnect_clock_handler ();
182}
183
184void Install_clock(rtems_isr_entry clock_isr)
185{
186  Clock_driver_ticks = 0;
187
188  BSP_connect_clock_handler (clock_isr);
189  atexit(Clock_exit);
190}
191
192void
193ReInstall_clock(rtems_isr_entry new_clock_isr)
194{
195  BSP_connect_clock_handler (new_clock_isr);
196}
197
198
199rtems_device_driver Clock_initialize(
200  rtems_device_major_number major,
201  rtems_device_minor_number minor,
202  void *pargp
203)
204{
205  Install_clock( Clock_isr );
206
207  /*
208   * make major/minor avail to others such as shared memory driver
209   */
210
211  rtems_clock_major = major;
212  rtems_clock_minor = minor;
213
214  return RTEMS_SUCCESSFUL;
215}
Note: See TracBrowser for help on using the repository browser.