diff options
author | Ralf Corsepius <ralf.corsepius@rtems.org> | 2005-12-31 05:09:26 +0000 |
---|---|---|
committer | Ralf Corsepius <ralf.corsepius@rtems.org> | 2005-12-31 05:09:26 +0000 |
commit | ca680bc5890abe0d6bfe7eb4a40a0229f1b6bd36 (patch) | |
tree | 805a5ddce1250235d6133376ddabb5543eb2cf82 /c/src/lib/libbsp/powerpc/gen5200/clock | |
parent | Add BuildRoot. (diff) | |
download | rtems-ca680bc5890abe0d6bfe7eb4a40a0229f1b6bd36.tar.bz2 |
New (CVS import Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>'s
submission).
Diffstat (limited to 'c/src/lib/libbsp/powerpc/gen5200/clock')
-rw-r--r-- | c/src/lib/libbsp/powerpc/gen5200/clock/clock.c | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/gen5200/clock/clock.c b/c/src/lib/libbsp/powerpc/gen5200/clock/clock.c new file mode 100644 index 0000000000..2ef30514a8 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/gen5200/clock/clock.c @@ -0,0 +1,474 @@ +/*===============================================================*\ +| Project: RTEMS generic MPC5200 BSP | ++-----------------------------------------------------------------+ +| File: clock.c ++-----------------------------------------------------------------+ +| Partially based on the code references which are named below. | +| Adaptions, modifications, enhancements and any recent parts of | +| the code are: | +| Copyright (c) 2005 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| The license and distribution terms for this file may be | +| found in the file LICENSE in this distribution or at | +| | +| http://www.rtems.com/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file contains the clock driver functions | ++-----------------------------------------------------------------+ +| date history ID | +| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | +| 01.12.05 creation doe | +|*****************************************************************| +|*CVS information: | +|*(the following information is created automatically, | +|*do not edit here) | +|*****************************************************************| +|* $Log$ +|* Revision 1.9 2005/12/09 08:57:03 thomas +|* added/modifed file headers +|* +|* Revision 1.8 2005/12/06 14:30:42 thomas +|* updated name for peripheral register block +|* +|* Revision 1.7 2005/12/06 14:11:11 thomas +|* added EB file headers +|* + * +|*****************************************************************| +\*===============================================================*/ +/***********************************************************************/ +/* */ +/* Module: clock.c */ +/* Date: 07/17/2003 */ +/* Purpose: RTEMS MPC5x00 clock driver */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Description: Use one of the GPTs for time base generation */ +/* instead of the decrementer. The routine initializes */ +/* the General Purpose Timer GPT6 on the MPC5x00. */ +/* The tick frequency is specified by the bsp. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Code */ +/* References: Clock driver for PPC403 */ +/* Module: clock.c */ +/* Project: RTEMS 4.6.0pre1 / PPC403 BSP */ +/* Version 1.16 */ +/* Date: 2002/11/01 */ +/* Author(s) / Copyright(s): */ +/* */ +/* Author: Jay Monkman (jmonkman@frasca.com) */ +/* Copyright (C) 1998 by Frasca International, Inc. */ +/* */ +/* Derived from c/src/lib/libcpu/ppc/ppc403/clock/clock.c: */ +/* */ +/* Author: Andrew Bray <andy@i-cubed.co.uk> */ +/* */ +/* COPYRIGHT (c) 1995 by i-cubed ltd. */ +/* */ +/* To anyone who acknowledges that this file is provided "AS IS" */ +/* without any express or implied warranty: */ +/* permission to use, copy, modify, and distribute this file */ +/* for any purpose is hereby granted without fee, provided that */ +/* the above copyright notice and this notice appears in all */ +/* copies, and that the name of i-cubed limited not be used in */ +/* advertising or publicity pertaining to distribution of the */ +/* software without specific, written prior permission. */ +/* i-cubed limited makes no representations about the suitability */ +/* of this software for any purpose. */ +/* */ +/* Derived from c/src/lib/libcpu/hppa1.1/clock/clock.c: */ +/* */ +/* Modifications for deriving timer clock from cpu system clock by */ +/* Thomas Doerfler <td@imd.m.isar.de> */ +/* for these modifications: */ +/* COPYRIGHT (c) 1997 by IMD, Puchheim, Germany. */ +/* */ +/* COPYRIGHT (c) 1989-1999. */ +/* On-Line Applications Research Corporation (OAR). */ +/* */ +/* The license and distribution terms for this file may be */ +/* found in the file LICENSE in this distribution or at */ +/* http://www.OARcorp.com/rtems/license.html. */ +/* */ +/* Modifications for PPC405GP by Dennis Ehlin */ +/*---------------------------------------------------------------------*/ +/* */ +/* Partially based on the code references which are named above. */ +/* Adaptions, modifications, enhancements and any recent parts of */ +/* the code are under the right of */ +/* */ +/* IPR Engineering, Dachauer Straße 38, D-80335 München */ +/* Copyright(C) 2003 */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* IPR Engineering makes no representation or warranties with */ +/* respect to the performance of this computer program, and */ +/* specifically disclaims any responsibility for any damages, */ +/* special or consequential, connected with the use of this program. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Version history: 1.0 */ +/* */ +/***********************************************************************/ + +/*#include "../include/bsp.h"*/ +#include "../include/bsp.h" +#include <rtems/bspIo.h> +/*#include "../irq/irq.h"*/ +#include "../irq/irq.h" + +#include <rtems.h> +#include <rtems/clockdrv.h> +#include <rtems/libio.h> + +#include <stdlib.h> /* for atexit() */ +#include "../include/bsp.h" +#include "../irq/irq.h" +#include "../include/mpc5200.h" + +volatile uint32_t Clock_driver_ticks; + +void Clock_exit(void); + +uint32_t counter_value; + +volatile int ClockInitialized = 0; + + +/* + * These are set by clock driver during its init + */ +rtems_device_major_number rtems_clock_major = ~0; +rtems_device_minor_number rtems_clock_minor; + + +/* + * ISR Handlers + */ +void mpc5200_gpt_clock_isr(rtems_irq_hdl_param handle) + { + uint32_t status; + struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)handle; + + status = gpt->status; + + + if(ClockInitialized && (status & GPT_STATUS_TEXP)) + { + + gpt->status |= GPT_STATUS_TEXP; + + + Clock_driver_ticks++; + rtems_clock_tick(); + + } + + } + + +/* + * Initialize MPC5x00 GPT + */ +void mpc5200_init_gpt(uint32_t gpt_no) + { + struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[gpt_no]); + + gpt->status = GPT_STATUS_RESET; + gpt->emsel = GPT_EMSEL_CE | GPT_EMSEL_ST_CONT | GPT_EMSEL_INTEN | GPT_EMSEL_GPIO_OUT_HIGH | GPT_EMSEL_TIMER_MS_GPIO; + + } + + +/* + * Set MPC5x00 GPT counter + */ +void mpc5200_set_gpt_count(uint32_t counter_value, uint32_t gpt_no) + { + uint32_t prescaler_value = 1; + struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[gpt_no]); + + /* Calculate counter/prescaler value, e.g. IPB_Clock=33MHz -> Int. every 0,3 nsecs. - 130 secs.*/ + while((counter_value >= (1 << 16)) && (prescaler_value < (1 << 16))) + { + + prescaler_value++; + counter_value /= prescaler_value; + + } + + counter_value = (uint16_t)counter_value; + + gpt->count_in = (prescaler_value << 16) + counter_value; + + } + + +/* + * Enable MPC5x00 GPT interrupt + */ +void mpc5200_enable_gpt_int(uint32_t gpt_no) + { + struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[gpt_no]); + + gpt->emsel |= GPT_EMSEL_CE | GPT_EMSEL_INTEN; + + } + + +/* + * Disable MPC5x00 GPT interrupt + */ +void mpc5200_disable_gpt_int(uint32_t gpt_no) + { + struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[gpt_no]); + + gpt->emsel &= ~(GPT_EMSEL_CE | GPT_EMSEL_INTEN); + + } + + +/* + * Check MPC5x00 GPT status + */ +uint32_t mpc5200_check_gpt_status(uint32_t gpt_no) + { + struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[gpt_no]); + + return ((gpt->emsel) & (GPT_EMSEL_CE | GPT_EMSEL_INTEN)); + + } + + +void clockOn(const rtems_irq_connect_data* irq) + { + uint32_t gpt_no; + + + gpt_no = BSP_SIU_IRQ_TMR0 - (irq->name); + + counter_value = rtems_configuration_get_microseconds_per_tick() * + rtems_cpu_configuration_get_clicks_per_usec(); + + mpc5200_set_gpt_count(counter_value, (uint32_t)gpt_no); + mpc5200_enable_gpt_int((uint32_t)gpt_no); + + Clock_driver_ticks = 0; + ClockInitialized = 1; + + } + + +void clockOff(const rtems_irq_connect_data* irq) + { + uint32_t gpt_no; + + gpt_no = BSP_SIU_IRQ_TMR0 - (irq->name); + + mpc5200_disable_gpt_int((uint32_t)gpt_no); + + ClockInitialized = 0; + + } + + +int clockIsOn(const rtems_irq_connect_data* irq) + { + uint32_t gpt_no; + + gpt_no = BSP_SIU_IRQ_TMR0 - (irq->name); + + if(mpc5200_check_gpt_status(gpt_no) && ClockInitialized) + return ClockInitialized; + else + return 0; + } + + +int BSP_get_clock_irq_level() + { + + /* + * Caution : if you change this, you must change the + * definition of BSP_PERIODIC_TIMER accordingly + */ + return BSP_PERIODIC_TIMER; + } + + +int BSP_disconnect_clock_handler (void) + { + rtems_irq_connect_data clockIrqData; + clockIrqData.name = BSP_PERIODIC_TIMER; + + + if (!BSP_get_current_rtems_irq_handler(&clockIrqData)) + { + + printk("Unable to stop system clock\n"); + rtems_fatal_error_occurred(1); + + } + + return BSP_remove_rtems_irq_handler (&clockIrqData); + + } + + +int BSP_connect_clock_handler (uint32_t gpt_no) + { + + rtems_irq_hdl hdl = 0; + rtems_irq_connect_data clockIrqData; + + + /* + * Reinit structure + */ + + clockIrqData.name = BSP_PERIODIC_TIMER; + + if(!BSP_get_current_rtems_irq_handler(&clockIrqData)) + { + + printk("Unable to get system clock handler\n"); + rtems_fatal_error_occurred(1); + + } + + if(!BSP_remove_rtems_irq_handler (&clockIrqData)) + { + + printk("Unable to remove current system clock handler\n"); + rtems_fatal_error_occurred(1); + + } + + if ((gpt_no >= GPT0) || + (gpt_no <= GPT7)) { + hdl = (rtems_irq_hdl_param )&mpc5200.gpt[gpt_no]; + } + else { + printk("Unable to set system clock handler\n"); + rtems_fatal_error_occurred(1); + } + + clockIrqData.hdl = mpc5200_gpt_clock_isr; + clockIrqData.handle = (rtems_irq_hdl_param) hdl; + clockIrqData.on = clockOn; + clockIrqData.off = clockOff; + clockIrqData.isOn = clockIsOn; + + return BSP_install_rtems_irq_handler (&clockIrqData); + + } + + +/* + * Called via atexit() + * Remove the clock interrupt handler by setting handler to NULL + */ +void Clock_exit(void) + { + + (void) BSP_disconnect_clock_handler (); + + } + + +void Install_clock(rtems_device_minor_number gpt_no) + { + + Clock_driver_ticks = 0; + + counter_value = rtems_configuration_get_microseconds_per_tick() * + rtems_cpu_configuration_get_clicks_per_usec(); + + mpc5200_init_gpt((uint32_t)gpt_no); + mpc5200_set_gpt_count(counter_value, (uint32_t)gpt_no); + + + BSP_connect_clock_handler(gpt_no); + + ClockInitialized = 1; + + atexit(Clock_exit); + + } + +void ReInstall_clock(uint32_t gpt_no) + { + + BSP_connect_clock_handler(gpt_no); + + } + + +rtems_device_driver Clock_initialize + ( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *pargp + ) + { + /* force minor according to definitions in irq.h */ + minor = BSP_PERIODIC_TIMER - BSP_SIU_IRQ_TMR0; + + Install_clock((uint32_t)minor); + + /* + * make major/minor avail to others such as shared memory driver + */ + rtems_clock_major = major; + rtems_clock_minor = minor; + + return RTEMS_SUCCESSFUL; + + } + +rtems_device_driver Clock_control + ( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *pargp + ) { + + rtems_libio_ioctl_args_t *args = pargp; + + /* forec minor according to definitions in irq.h */ + minor = BSP_PERIODIC_TIMER - BSP_SIU_IRQ_TMR0; + + if(args != 0) { + /* + * This is hokey, but until we get a defined interface + * to do this, it will just be this simple... + */ + if(args->command == rtems_build_name('I', 'S', 'R', ' ')) { + if ((minor >= GPT0) || + (minor <= GPT7)) { + mpc5200_gpt_clock_isr((rtems_irq_hdl_param )&mpc5200.gpt[minor]); + } + else { + printk("Unable to call system clock handler\n"); + rtems_fatal_error_occurred(1); + } + } + else if(args->command == rtems_build_name('N', 'E', 'W', ' ')) { + ReInstall_clock((uint32_t)minor); + } + } + return RTEMS_SUCCESSFUL; + +} + |