source: rtems/bsps/powerpc/tqm8xx/dev/clock.c @ 9964895

5
Last change on this file since 9964895 was b8c468b, checked in by Sebastian Huber <sebastian.huber@…>, on Mar 23, 2018 at 3:11:55 PM

bsp/tqm8xx: Move libcpu content to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 5.2 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
7/*
8 *  Author: Jay Monkman (jmonkman@frasca.com)
9 *  Copyright (C) 1998 by Frasca International, Inc.
10 *
11 *  Derived from c/src/lib/libcpu/ppc/ppc403/clock/clock.c:
12 *
13 *  Author: Andrew Bray <andy@i-cubed.co.uk>
14 *
15 *  COPYRIGHT (c) 1995 by i-cubed ltd.
16 *
17 *  To anyone who acknowledges that this file is provided "AS IS"
18 *  without any express or implied warranty:
19 *      permission to use, copy, modify, and distribute this file
20 *      for any purpose is hereby granted without fee, provided that
21 *      the above copyright notice and this notice appears in all
22 *      copies, and that the name of i-cubed limited not be used in
23 *      advertising or publicity pertaining to distribution of the
24 *      software without specific, written prior permission.
25 *      i-cubed limited makes no representations about the suitability
26 *      of this software for any purpose.
27 *
28 *  Derived from c/src/lib/libcpu/hppa1_1/clock/clock.c:
29 *
30 *  COPYRIGHT (c) 1989-2007.
31 *  On-Line Applications Research Corporation (OAR).
32 *
33 *  The license and distribution terms for this file may be
34 *  found in the file LICENSE in this distribution or at
35 *  http://www.rtems.org/license/LICENSE.
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#include <bsp.h>
46
47volatile uint32_t   Clock_driver_ticks;
48extern volatile m8xx_t m8xx;
49extern int BSP_get_clock_irq_level(void);
50extern uint32_t bsp_clicks_per_usec;
51
52/*
53 *  Prototypes
54 */
55rtems_isr Clock_isr(rtems_vector_number vector);
56void Clock_exit( void );
57void clockOn(void* unused);
58void clockOff(void* unused);
59int clockIsOn(void* unused);
60void Install_clock(rtems_isr_entry clock_isr);
61void ReInstall_clock(rtems_isr_entry new_clock_isr);
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  }
134
135  if ((pit_value > 0xffff) || force_prescaler) {
136    /*
137     * try to activate prescaler
138     * NOTE: divider generates odd values now...
139     */
140    pit_value = pit_value / 128;
141    m8xx.sccr |= (1<<24);
142  }
143  else {
144    m8xx.sccr &= ~(1<<24);
145  }
146
147  if (pit_value > 0xffff) {           /* pit is only 16 bits long */
148    rtems_fatal_error_occurred(-1);
149  }
150  m8xx.pitc = pit_value - 1;
151
152  desiredLevel = BSP_get_clock_irq_level();
153  /* set PIT irq level, enable PIT, PIT interrupts */
154  /*  and clear int. status */
155  m8xx.piscr = M8xx_PISCR_PIRQ(desiredLevel) |
156    M8xx_PISCR_PTE | M8xx_PISCR_PS | M8xx_PISCR_PIE;
157}
158
159/*
160 * Called via atexit()
161 * Remove the clock interrupt handler by setting handler to NULL
162 */
163void clockOff(void* unused)
164{
165  /* disable PIT and PIT interrupts */
166  m8xx.piscr &= ~(M8xx_PISCR_PTE | M8xx_PISCR_PIE);
167}
168
169int clockIsOn(void* unused)
170{
171  if (m8xx.piscr & M8xx_PISCR_PIE)
172    return 1;
173  return 0;
174}
175
176/*
177 * Called via atexit()
178 * Remove the clock interrupt handler by setting handler to NULL
179 */
180void Clock_exit(void)
181{
182  (void) BSP_disconnect_clock_handler ();
183}
184
185void Install_clock(rtems_isr_entry clock_isr)
186{
187  Clock_driver_ticks = 0;
188
189  BSP_connect_clock_handler (clock_isr);
190  atexit(Clock_exit);
191}
192
193void ReInstall_clock(rtems_isr_entry new_clock_isr)
194{
195  BSP_connect_clock_handler (new_clock_isr);
196}
197
198rtems_device_driver Clock_initialize(
199  rtems_device_major_number major,
200  rtems_device_minor_number minor,
201  void *pargp
202)
203{
204  Install_clock( Clock_isr );
205
206  return RTEMS_SUCCESSFUL;
207}
Note: See TracBrowser for help on using the repository browser.