source: rtems/c/src/lib/libbsp/powerpc/gen5200/clock/clock.c @ f8506230

4.104.114.9
Last change on this file since f8506230 was f8506230, checked in by Ralf Corsepius <ralf.corsepius@…>, on Aug 20, 2008 at 4:28:02 AM

Add missing prototypes.

  • Property mode set to 100644
File size: 13.7 KB
Line 
1/*===============================================================*\
2| Project: RTEMS generic MPC5200 BSP                              |
3+-----------------------------------------------------------------+
4| Partially based on the code references which are named below.   |
5| Adaptions, modifications, enhancements and any recent parts of  |
6| the code are:                                                   |
7|                    Copyright (c) 2005                           |
8|                    Embedded Brains GmbH                         |
9|                    Obere Lagerstr. 30                           |
10|                    D-82178 Puchheim                             |
11|                    Germany                                      |
12|                    rtems@embedded-brains.de                     |
13|                                                                 |
14| Reworked by Joel Sherrill to use clockdrv_shell.c               |
15+-----------------------------------------------------------------+
16| The license and distribution terms for this file may be         |
17| found in the file LICENSE in this distribution or at            |
18|                                                                 |
19| http://www.rtems.com/license/LICENSE.                           |
20|                                                                 |
21+-----------------------------------------------------------------+
22| this file contains the clock driver functions                   |
23\*===============================================================*/
24/***********************************************************************/
25/*                                                                     */
26/*   Module:       clock.c                                             */
27/*   Date:         07/17/2003                                          */
28/*   Purpose:      RTEMS MPC5x00 clock driver                          */
29/*                                                                     */
30/*---------------------------------------------------------------------*/
31/*                                                                     */
32/*   Description:  Use one of the GPTs for time base generation        */
33/*                 instead of the decrementer. The routine initializes */
34/*                 the General Purpose Timer GPT6 on the MPC5x00.      */
35/*                 The tick frequency is specified by the bsp.         */
36/*                                                                     */
37/*---------------------------------------------------------------------*/
38/*                                                                     */
39/*   Code                                                              */
40/*   References:   Clock driver for PPC403                             */
41/*   Module:       clock.c                                             */
42/*   Project:      RTEMS 4.6.0pre1 / PPC403 BSP                        */
43/*   Version       1.16                                                */
44/*   Date:         2002/11/01                                          */
45/*   Author(s) / Copyright(s):                                         */
46/*                                                                     */
47/*   Author: Jay Monkman (jmonkman@frasca.com)                         */
48/*   Copyright (C) 1998 by Frasca International, Inc.                  */
49/*                                                                     */
50/*   Derived from c/src/lib/libcpu/ppc/ppc403/clock/clock.c:           */
51/*                                                                     */
52/*   Author: Andrew Bray <andy@i-cubed.co.uk>                          */
53/*                                                                     */
54/*   COPYRIGHT (c) 1995 by i-cubed ltd.                                */
55/*                                                                     */
56/*   To anyone who acknowledges that this file is provided "AS IS"     */
57/*   without any express or implied warranty:                          */
58/*      permission to use, copy, modify, and distribute this file      */
59/*      for any purpose is hereby granted without fee, provided that   */
60/*      the above copyright notice and this notice appears in all      */
61/*      copies, and that the name of i-cubed limited not be used in    */
62/*      advertising or publicity pertaining to distribution of the     */
63/*      software without specific, written prior permission.           */
64/*      i-cubed limited makes no representations about the suitability */
65/*      of this software for any purpose.                              */
66/*                                                                     */
67/*   Derived from c/src/lib/libcpu/hppa1.1/clock/clock.c:              */
68/*                                                                     */
69/*   Modifications for deriving timer clock from cpu system clock by   */
70/*              Thomas Doerfler <td@imd.m.isar.de>                     */
71/*   for these modifications:                                          */
72/*   COPYRIGHT (c) 1997 by IMD, Puchheim, Germany.                     */
73/*                                                                     */
74/*   COPYRIGHT (c) 1989-2007.                                          */
75/*   On-Line Applications Research Corporation (OAR).                  */
76/*                                                                     */
77/*   The license and distribution terms for this file may be           */
78/*   found in the file LICENSE in this distribution or at              */
79/*   http://www.rtems.com/license/LICENSE.                             */
80/*                                                                     */
81/*   Modifications for PPC405GP by Dennis Ehlin                        */
82/*---------------------------------------------------------------------*/
83/*                                                                     */
84/*   Partially based on the code references which are named above.     */
85/*   Adaptions, modifications, enhancements and any recent parts of    */
86/*   the code are under the right of                                   */
87/*                                                                     */
88/*         IPR Engineering, Dachauer Straße 38, D-80335 MÃŒnchen        */
89/*                        Copyright(C) 2003                            */
90/*                                                                     */
91/*---------------------------------------------------------------------*/
92/*                                                                     */
93/*   IPR Engineering makes no representation or warranties with        */
94/*   respect to the performance of this computer program, and          */
95/*   specifically disclaims any responsibility for any damages,        */
96/*   special or consequential, connected with the use of this program. */
97/*                                                                     */
98/*---------------------------------------------------------------------*/
99/*                                                                     */
100/*   Version history:  1.0                                             */
101/*                                                                     */
102/***********************************************************************/
103
104#include <bsp.h>
105#include <rtems/bspIo.h>
106#include "../irq/irq.h"
107
108#include <rtems.h>
109#include <rtems/clockdrv.h>
110#include <rtems/libio.h>
111
112#include <stdlib.h>                     /* for atexit() */
113#include "../include/mpc5200.h"
114
115#define GPT (BSP_PERIODIC_TIMER - BSP_SIU_IRQ_TMR0)
116
117/* this lets us do nanoseconds since last tick */
118uint64_t Clock_last_TBR;
119volatile uint32_t counter_value;
120volatile int ClockInitialized = 0;
121
122/*
123 *  ISR Handlers
124 */
125void mpc5200_gpt_clock_isr(rtems_irq_hdl_param handle)
126{
127  uint32_t status;
128  struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)handle;
129
130  status = gpt->status;
131
132  if (ClockInitialized  && (status & GPT_STATUS_TEXP)) {
133    gpt->status |= GPT_STATUS_RESET;
134    Clock_last_TBR = PPC_Get_timebase_register();
135
136    Clock_driver_ticks++;
137    rtems_clock_tick();
138  }
139}
140
141/*
142 *  Initialize MPC5x00 GPT
143 */
144void mpc5200_init_gpt(uint32_t gpt_no)
145{
146  struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[gpt_no]);
147
148  gpt->status = GPT_STATUS_RESET;
149  gpt->emsel  = GPT_EMSEL_CE | GPT_EMSEL_ST_CONT | GPT_EMSEL_INTEN | 
150                GPT_EMSEL_GPIO_OUT_HIGH | GPT_EMSEL_TIMER_MS_GPIO;
151
152}
153
154/*
155 *  Set MPC5x00 GPT counter
156 */
157void mpc5200_set_gpt_count(uint32_t counter_value, uint32_t gpt_no)
158{
159  uint32_t prescaler_value = 1;
160  uint32_t counter = counter_value;
161  struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[gpt_no]);
162
163  /* Calculate counter/prescaler value, e.g.
164   *   IPB_Clock=33MHz -> Int. every 0,3 nsecs. - 130 secs
165   */
166  while ((counter >= (1 << 16)) && (prescaler_value < (1 << 16))) {
167    prescaler_value++;
168    counter = counter_value / prescaler_value;
169  }
170
171  counter = (uint16_t)counter;
172
173  gpt->count_in = (prescaler_value << 16) + counter;
174
175}
176
177uint32_t bsp_clock_nanoseconds_since_last_tick(void)
178{
179  uint64_t new_tbr;
180  uint64_t bus_cycles;
181  uint32_t nsecs;
182
183  new_tbr = PPC_Get_timebase_register();
184  bus_cycles = (new_tbr - Clock_last_TBR) * 4;
185  nsecs =  (uint32_t) (bus_cycles / (XLB_CLOCK / 1000000)) * 1000;
186
187  return nsecs;
188}
189
190/*
191 *  Enable MPC5x00 GPT interrupt
192 */
193void mpc5200_enable_gpt_int(uint32_t gpt_no)
194{
195  struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[gpt_no]);
196
197  gpt->emsel |= GPT_EMSEL_CE | GPT_EMSEL_INTEN;
198  Clock_last_TBR = PPC_Get_timebase_register();
199}
200
201/*
202 *  Disable MPC5x00 GPT interrupt
203 */
204void mpc5200_disable_gpt_int(uint32_t gpt_no)
205{
206  struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[gpt_no]);
207
208  gpt->emsel &= ~(GPT_EMSEL_CE | GPT_EMSEL_INTEN);
209}
210
211/*
212 *  Check MPC5x00 GPT status
213 */
214uint32_t mpc5200_check_gpt_status(uint32_t gpt_no)
215{
216  struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[gpt_no]);
217
218  return ((gpt->emsel) & (GPT_EMSEL_CE | GPT_EMSEL_INTEN));
219}
220
221void clockOn(const rtems_irq_connect_data* irq)
222{
223  uint32_t gpt_no;
224  extern uint32_t bsp_clicks_per_usec;
225
226  gpt_no = BSP_SIU_IRQ_TMR0 - (irq->name);
227
228  counter_value = rtems_configuration_get_microseconds_per_tick() *
229                      bsp_clicks_per_usec;
230
231  mpc5200_set_gpt_count(counter_value, (uint32_t)gpt_no);
232  mpc5200_enable_gpt_int((uint32_t)gpt_no);
233
234  ClockInitialized = 1;
235}
236
237void clockOff(const rtems_irq_connect_data* irq)
238{
239  uint32_t gpt_no;
240
241  gpt_no = BSP_SIU_IRQ_TMR0 - (irq->name);
242
243  mpc5200_disable_gpt_int((uint32_t)gpt_no);
244
245  ClockInitialized = 0;
246}
247
248int clockIsOn(const rtems_irq_connect_data* irq)
249{
250  uint32_t gpt_no;
251
252  gpt_no = BSP_SIU_IRQ_TMR0 - (irq->name);
253
254  if (mpc5200_check_gpt_status(gpt_no) && ClockInitialized)
255    return ClockInitialized;
256  return 0;
257}
258
259
260int BSP_get_clock_irq_level(void)
261{
262  /*
263   * Caution : if you change this, you must change the
264   * definition of BSP_PERIODIC_TIMER accordingly
265    */
266  return BSP_PERIODIC_TIMER;
267}
268
269
270int BSP_disconnect_clock_handler (void)
271{
272  rtems_irq_connect_data clockIrqData;
273  clockIrqData.name   = BSP_PERIODIC_TIMER;
274
275
276  if (!BSP_get_current_rtems_irq_handler(&clockIrqData)) {
277    printk("Unable to stop system clock\n");
278    rtems_fatal_error_occurred(1);
279  }
280
281  return BSP_remove_rtems_irq_handler (&clockIrqData);
282}
283
284
285int BSP_connect_clock_handler (uint32_t gpt_no)
286{
287  rtems_irq_hdl hdl = 0;
288  rtems_irq_connect_data clockIrqData;
289
290  /*
291   * Reinit structure
292   */
293  clockIrqData.name   = BSP_PERIODIC_TIMER;
294
295  if (!BSP_get_current_rtems_irq_handler(&clockIrqData)) {
296    printk("Unable to get system clock handler\n");
297    rtems_fatal_error_occurred(1);
298  }
299
300  if (!BSP_remove_rtems_irq_handler (&clockIrqData)) {
301    printk("Unable to remove current system clock handler\n");
302    rtems_fatal_error_occurred(1);
303  }
304
305  if ((gpt_no >= GPT0) || (gpt_no <= GPT7)) {
306    hdl = (rtems_irq_hdl_param )&mpc5200.gpt[gpt_no];
307  } else {
308    printk("Unable to set system clock handler\n");
309    rtems_fatal_error_occurred(1);
310  }
311
312  clockIrqData.hdl    = mpc5200_gpt_clock_isr;
313  clockIrqData.handle = (rtems_irq_hdl_param) hdl;
314  clockIrqData.on     = clockOn;
315  clockIrqData.off    = clockOff;
316  clockIrqData.isOn   = clockIsOn;
317
318  return BSP_install_rtems_irq_handler (&clockIrqData);
319}
320
321#define CLOCK_VECTOR 0
322
323#define Clock_driver_support_at_tick()                                   \
324  do {                                                                   \
325    uint32_t status;                                                     \
326    struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[GPT]); \
327    \
328    status = gpt->status;                                                \
329    \
330    if (ClockInitialized  && (status & GPT_STATUS_TEXP)) {               \
331      gpt->status |= GPT_STATUS_RESET;                                   \
332      Clock_last_TBR = PPC_Get_timebase_register();                      \
333    }                                                                    \
334  } while(0)
335
336#define Clock_driver_support_install_isr( _new, _old ) \
337  do {                                                 \
338      (_old) = NULL; /* avoid warning */;              \
339      BSP_connect_clock_handler(GPT);                  \
340  } while(0)
341
342/* This driver does this in clockOn called at connection time */
343#define Clock_driver_support_initialize_hardware() \
344  do {        \
345    extern uint32_t bsp_clicks_per_usec; \
346    counter_value = rtems_configuration_get_microseconds_per_tick() * \
347                    bsp_clicks_per_usec; \
348    mpc5200_init_gpt(GPT); \
349    mpc5200_set_gpt_count(counter_value, GPT); \
350  } while (0)
351
352#define Clock_driver_nanoseconds_since_last_tick \
353    bsp_clock_nanoseconds_since_last_tick
354
355#define Clock_driver_support_shutdown_hardware() \
356  do { \
357    (void) BSP_disconnect_clock_handler (); \
358  } while (0)
359
360#include "../../../shared/clockdrv_shell.c"
361
Note: See TracBrowser for help on using the repository browser.