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

4.104.114.9
Last change on this file since 82bd8d9d was 82bd8d9d, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on Sep 3, 2008 at 3:39:03 PM

Converted to use shared

exception and interrupt code.

  • Property mode set to 100644
File size: 13.0 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 <bsp/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
117extern uint32_t bsp_clicks_per_usec;
118
119/* this lets us do nanoseconds since last tick */
120uint64_t Clock_last_TBR;
121volatile uint32_t counter_value;
122volatile int ClockInitialized = 0;
123
124/*
125 *  ISR Handlers
126 */
127void mpc5200_gpt_clock_isr(rtems_vector_number vector, void *handle)
128{
129  uint32_t status;
130  struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)handle;
131
132  status = gpt->status;
133
134  if (ClockInitialized  && (status & GPT_STATUS_TEXP)) {
135    gpt->status |= GPT_STATUS_RESET;
136    Clock_last_TBR = PPC_Get_timebase_register();
137
138    Clock_driver_ticks++;
139    rtems_clock_tick();
140  }
141}
142
143/*
144 *  Initialize MPC5x00 GPT
145 */
146void mpc5200_init_gpt(uint32_t gpt_no)
147{
148  struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[gpt_no]);
149
150  gpt->status = GPT_STATUS_RESET;
151  gpt->emsel  = GPT_EMSEL_CE | GPT_EMSEL_ST_CONT | GPT_EMSEL_INTEN | 
152                GPT_EMSEL_GPIO_OUT_HIGH | GPT_EMSEL_TIMER_MS_GPIO;
153
154}
155
156/*
157 *  Set MPC5x00 GPT counter
158 */
159void mpc5200_set_gpt_count(uint32_t counter_value, uint32_t gpt_no)
160{
161  uint32_t prescaler_value = 1;
162  uint32_t counter = counter_value;
163  struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[gpt_no]);
164
165  /* Calculate counter/prescaler value, e.g.
166   *   IPB_Clock=33MHz -> Int. every 0,3 nsecs. - 130 secs
167   */
168  while ((counter >= (1 << 16)) && (prescaler_value < (1 << 16))) {
169    prescaler_value++;
170    counter = counter_value / prescaler_value;
171  }
172
173  counter = (uint16_t)counter;
174
175  gpt->count_in = (prescaler_value << 16) + counter;
176
177}
178
179uint32_t bsp_clock_nanoseconds_since_last_tick(void)
180{
181  uint64_t new_tbr;
182  uint64_t bus_cycles;
183  uint32_t nsecs;
184
185  new_tbr = PPC_Get_timebase_register();
186  bus_cycles = (new_tbr - Clock_last_TBR) * 4;
187  nsecs =  (uint32_t) (bus_cycles / (XLB_CLOCK / 1000000)) * 1000;
188
189  return nsecs;
190}
191
192/*
193 *  Enable MPC5x00 GPT interrupt
194 */
195void mpc5200_enable_gpt_int(uint32_t gpt_no)
196{
197  struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[gpt_no]);
198
199  gpt->emsel |= GPT_EMSEL_CE | GPT_EMSEL_INTEN;
200  Clock_last_TBR = PPC_Get_timebase_register();
201}
202
203/*
204 *  Disable MPC5x00 GPT interrupt
205 */
206void mpc5200_disable_gpt_int(uint32_t gpt_no)
207{
208  struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[gpt_no]);
209
210  gpt->emsel &= ~(GPT_EMSEL_CE | GPT_EMSEL_INTEN);
211}
212
213/*
214 *  Check MPC5x00 GPT status
215 */
216uint32_t mpc5200_check_gpt_status(uint32_t gpt_no)
217{
218  struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[gpt_no]);
219
220  return ((gpt->emsel) & (GPT_EMSEL_CE | GPT_EMSEL_INTEN));
221}
222
223void clockOn()
224{
225  uint32_t gpt_no;
226
227  gpt_no = BSP_SIU_IRQ_TMR0 - BSP_PERIODIC_TIMER;
228
229  counter_value = rtems_configuration_get_microseconds_per_tick() *
230                      bsp_clicks_per_usec;
231
232  mpc5200_set_gpt_count(counter_value, gpt_no);
233  mpc5200_enable_gpt_int(gpt_no);
234
235  ClockInitialized = 1;
236}
237
238void clockOff()
239{
240  uint32_t gpt_no;
241
242  gpt_no = BSP_SIU_IRQ_TMR0 - BSP_PERIODIC_TIMER;
243
244  mpc5200_disable_gpt_int(gpt_no);
245
246  ClockInitialized = 0;
247}
248
249int BSP_get_clock_irq_level(void)
250{
251  /*
252   * Caution : if you change this, you must change the
253   * definition of BSP_PERIODIC_TIMER accordingly
254    */
255  return BSP_PERIODIC_TIMER;
256}
257
258int BSP_disconnect_clock_handler (unsigned gpt_no)
259{
260  rtems_status_code sc = RTEMS_SUCCESSFUL;
261
262  if ((gpt_no < GPT0) || (gpt_no > GPT7)) {
263    return 0;
264  }
265
266  clockOff( BSP_PERIODIC_TIMER);
267
268  sc = rtems_interrupt_handler_remove(
269    BSP_PERIODIC_TIMER,
270    mpc5200_gpt_clock_isr,
271    &mpc5200.gpt [gpt_no]
272  );
273  if (sc != RTEMS_SUCCESSFUL) {
274    return 0;
275  }
276
277  return 1;
278}
279
280int BSP_connect_clock_handler (unsigned gpt_no)
281{
282  rtems_status_code sc = RTEMS_SUCCESSFUL;
283
284  if ((gpt_no < GPT0) || (gpt_no > GPT7)) {
285    printk("Unable to set system clock handler\n");
286    rtems_fatal_error_occurred(1);
287  }
288
289  sc = rtems_interrupt_handler_install(
290    BSP_PERIODIC_TIMER,
291    "Clock",
292    RTEMS_INTERRUPT_UNIQUE,
293    mpc5200_gpt_clock_isr,
294    &mpc5200.gpt [gpt_no]
295  );
296  if (sc != RTEMS_SUCCESSFUL) {
297    return 0;
298  }
299
300  clockOn();
301
302  return 1;
303}
304
305#define CLOCK_VECTOR 0
306
307#define Clock_driver_support_at_tick()                                   \
308  do {                                                                   \
309    uint32_t status;                                                     \
310    struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[GPT]); \
311    \
312    status = gpt->status;                                                \
313    \
314    if (ClockInitialized  && (status & GPT_STATUS_TEXP)) {               \
315      gpt->status |= GPT_STATUS_RESET;                                   \
316      Clock_last_TBR = PPC_Get_timebase_register();                      \
317    }                                                                    \
318  } while(0)
319
320#define Clock_driver_support_install_isr( _new, _old ) \
321  do {                                                 \
322      (_old) = NULL; /* avoid warning */;              \
323      BSP_connect_clock_handler(GPT);                  \
324  } while(0)
325
326/* This driver does this in clockOn called at connection time */
327#define Clock_driver_support_initialize_hardware() \
328  do {        \
329    counter_value = rtems_configuration_get_microseconds_per_tick() * \
330                    bsp_clicks_per_usec; \
331    mpc5200_init_gpt(GPT); \
332    mpc5200_set_gpt_count(counter_value, GPT); \
333  } while (0)
334
335#define Clock_driver_nanoseconds_since_last_tick \
336    bsp_clock_nanoseconds_since_last_tick
337
338#define Clock_driver_support_shutdown_hardware() \
339  do { \
340    (void) BSP_disconnect_clock_handler (GPT); \
341  } while (0)
342
343#include "../../../shared/clockdrv_shell.c"
344
Note: See TracBrowser for help on using the repository browser.