diff options
author | Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | 2008-07-14 08:46:06 +0000 |
---|---|---|
committer | Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | 2008-07-14 08:46:06 +0000 |
commit | 3c6fe2e7f95f6bff53123df9377b114cadeac874 (patch) | |
tree | fef9ad7a4cd45497a1a84c1b7f9cd103eb258c43 /c/src/lib/libcpu/powerpc/ppc403/clock | |
parent | corrections in display driver (diff) | |
download | rtems-3c6fe2e7f95f6bff53123df9377b114cadeac874.tar.bz2 |
added haleakala BSP contributed by Michael Hamel
Diffstat (limited to 'c/src/lib/libcpu/powerpc/ppc403/clock')
-rw-r--r-- | c/src/lib/libcpu/powerpc/ppc403/clock/clock_4xx.c | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/c/src/lib/libcpu/powerpc/ppc403/clock/clock_4xx.c b/c/src/lib/libcpu/powerpc/ppc403/clock/clock_4xx.c new file mode 100644 index 0000000000..890e75509d --- /dev/null +++ b/c/src/lib/libcpu/powerpc/ppc403/clock/clock_4xx.c @@ -0,0 +1,251 @@ +/* clock.c + * + * This routine initializes the interval timer on the + * PowerPC 405 CPU. The tick frequency is specified by the bsp. + * + * 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-2007. + * 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.rtems.com/license/LICENSE. + * + * Modifications for PPC405GP by Dennis Ehlin + * + * Further modifications for PPC405GP/EX by Michael Hamel + * + * $Id$ + */ + +#include <rtems.h> +#include <rtems/clockdrv.h> +#include <rtems/libio.h> +#include <stdlib.h> /* for atexit() */ +#include <rtems/bspIo.h> +#include <ppc405common.h> +#include <libcpu/cpuIdent.h> +#include <bsp/irq.h> + + + +/* PPC405GP */ +#define CPC0_CR1 0xB2 + #define CR1_CETE 0x00800000 + +/* PPC405EX */ +#define SDR0_C405 0x180 + #define SDR_CETE 0x02000000 + +volatile uint32_t Clock_driver_ticks; +static uint32_t pit_value, tick_time; + +void Clock_exit( void ); + +rtems_isr_entry set_vector( /* returns old vector */ + rtems_isr_entry handler, /* isr routine */ + rtems_vector_number vector, /* vector number */ + int type /* RTEMS or RAW intr */ +); + +/* Defined in bspstart.c */ +extern uint32_t bsp_clicks_per_usec; +extern boolean bsp_timer_internal_clock; + +/* + * 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 Handler + */ + +void Clock_isr(void* handle) +{ + Clock_driver_ticks++; + rtems_clock_tick(); +} + +int ClockIsOn(const rtems_irq_connect_data* unused) +{ + return ((mfspr(TCR) & PIE) != 0); +} + + +void ClockOff(const rtems_irq_connect_data* unused) +{ + register uint32_t r; + + r = mfspr(TCR); + mtspr(TCR, r & ~(PIE | ARE) ); +} + +void ClockOn(const rtems_irq_connect_data* unused) +{ + uint32_t iocr, r; + ppc_cpu_id_t cpu; + Clock_driver_ticks = 0; + + cpu = get_ppc_cpu_type(); + if (cpu==PPC_405GP) { + iocr = mfdcr(CPC0_CR1); + if (bsp_timer_internal_clock) iocr &= ~CR1_CETE ;/* timer clocked from system clock */ + else iocr |= CR1_CETE; /* select external timer clock */ + mtdcr(CPC0_CR1,iocr); + } else if (cpu==PPC_405EX) { + mfsdr(SDR0_C405,iocr); + if (bsp_timer_internal_clock) iocr &= ~SDR_CETE ;/* timer clocked from system clock */ + else iocr |= SDR_CETE; /* select external timer clock */ + mtsdr(SDR0_C405,iocr); + } else { + printk("clock.c:unrecognised CPU"); + rtems_fatal_error_occurred(1); + } + + pit_value = rtems_configuration_get_microseconds_per_tick() * bsp_clicks_per_usec; + mtspr(PIT,pit_value); + + tick_time = mfspr(TBL) + pit_value; + r = mfspr(TCR); + mtspr(TCR, r | PIE | ARE); +} + + + +void Install_clock(void (*clock_isr)(void *)) +{ + + /* + * initialize the interval here + * First tick is set to right amount of time in the future + * Future ticks will be incremented over last value set + * in order to provide consistent clicks in the face of + * interrupt overhead + */ + + rtems_irq_connect_data clockIrqConnData; + + Clock_driver_ticks = 0; + clockIrqConnData.on = ClockOn; + clockIrqConnData.off = ClockOff; + clockIrqConnData.isOn = ClockIsOn; + clockIrqConnData.name = BSP_PIT; + clockIrqConnData.hdl = clock_isr; + if ( ! BSP_install_rtems_irq_handler (&clockIrqConnData)) { + printk("Unable to connect Clock Irq handler\n"); + rtems_fatal_error_occurred(1); + } + atexit(Clock_exit); +} + +void +ReInstall_clock(void (*new_clock_isr)(void *)) +{ + uint32_t isrlevel = 0; + rtems_irq_connect_data clockIrqConnData; + + rtems_interrupt_disable(isrlevel); + clockIrqConnData.name = BSP_PIT; + if ( ! BSP_get_current_rtems_irq_handler(&clockIrqConnData)) { + printk("Unable to stop system clock\n"); + rtems_fatal_error_occurred(1); + } + + BSP_remove_rtems_irq_handler (&clockIrqConnData); + clockIrqConnData.on = ClockOn; + clockIrqConnData.off = ClockOff; + clockIrqConnData.isOn = ClockIsOn; + clockIrqConnData.name = BSP_PIT; + clockIrqConnData.hdl = new_clock_isr; + if (!BSP_install_rtems_irq_handler (&clockIrqConnData)) { + printk("Unable to connect Clock Irq handler\n"); + rtems_fatal_error_occurred(1); + } + rtems_interrupt_enable(isrlevel); +} + + +/* + * Called via atexit() + * Remove the clock interrupt handler by setting handler to NULL + * + * This will not work on the 405GP because + * when bit's are set in TCR they can only be unset by a reset + */ + +void Clock_exit(void) +{ + rtems_irq_connect_data clockIrqConnData; + + clockIrqConnData.name = BSP_PIT; + if (!BSP_get_current_rtems_irq_handler(&clockIrqConnData)) { + printk("Unable to stop system clock\n"); + rtems_fatal_error_occurred(1); + } + BSP_remove_rtems_irq_handler (&clockIrqConnData); +} + + +rtems_device_driver Clock_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *pargp +) +{ + Install_clock( Clock_isr ); + + /* + * 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; + + if (args!=NULL) { + /* + * 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', ' ')) + Clock_isr(NULL); + else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) + ReInstall_clock(args->buffer); + } + return RTEMS_SUCCESSFUL; +} |