diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-19 06:35:52 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-20 09:57:01 +0200 |
commit | 7632906fc290b652416ab59eb5fb49356c064ed6 (patch) | |
tree | ac036b1f95637e044e10138ceea8d2b56d80ec97 /bsps/powerpc/shared/clock | |
parent | bsps: Move bspsmpgetcurrentprocessor.c to bsps (diff) | |
download | rtems-7632906fc290b652416ab59eb5fb49356c064ed6.tar.bz2 |
bsps: Move clock drivers to bsps
This patch is a part of the BSP source reorganization.
Update #3285.
Diffstat (limited to 'bsps/powerpc/shared/clock')
-rw-r--r-- | bsps/powerpc/shared/clock/clock-ppc-dec.c | 266 | ||||
-rw-r--r-- | bsps/powerpc/shared/clock/clock-ppc403.c | 275 | ||||
-rw-r--r-- | bsps/powerpc/shared/clock/clock.c | 247 | ||||
-rw-r--r-- | bsps/powerpc/shared/clock/p_clock.c | 43 |
4 files changed, 831 insertions, 0 deletions
diff --git a/bsps/powerpc/shared/clock/clock-ppc-dec.c b/bsps/powerpc/shared/clock/clock-ppc-dec.c new file mode 100644 index 0000000000..c9bb16c451 --- /dev/null +++ b/bsps/powerpc/shared/clock/clock-ppc-dec.c @@ -0,0 +1,266 @@ +/** + * @brief Clock Tick Device Driver + * + * This routine utilizes the Decrementer Register common to the PPC family. + * + * The tick frequency is directly programmed to the configured number of + * microseconds per tick. + */ + +/* + * COPYRIGHT (c) 1989-2014. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + * + * Modified to support the MPC750. + * Modifications Copyright (c) 1999 Eric Valette valette@crf.canon.fr + */ + +#include <rtems.h> +#include <rtems/libio.h> +#include <rtems/clockdrv.h> +#include <stdlib.h> /* for atexit() */ +#include <assert.h> +#include <libcpu/c_clock.h> +#include <libcpu/cpuIdent.h> +#include <libcpu/spr.h> +#include <rtems/bspIo.h> /* for printk() */ +#include <libcpu/powerpc-utility.h> +#include <rtems/timecounter.h> +#include <rtems/score/percpu.h> + +#include <bspopts.h> /* for CLOCK_DRIVER_USE_FAST_IDLE */ + +SPR_RW(BOOKE_TCR) +SPR_RW(BOOKE_TSR) +SPR_RW(BOOKE_DECAR) + +extern int BSP_connect_clock_handler (void); + +/* + * Clock ticks since initialization + */ +volatile uint32_t Clock_driver_ticks; + +/* + * This is the value programmed into the count down timer. + */ +static uint32_t Clock_Decrementer_value; + +static struct timecounter Clock_TC; + +static uint32_t Clock_Get_timecount(struct timecounter *tc) +{ + return ppc_time_base(); +} + +void clockOff(void* unused) +{ + rtems_interrupt_level l; + + if ( ppc_cpu_is_bookE() ) { + rtems_interrupt_disable(l); + _write_BOOKE_TCR(_read_BOOKE_TCR() & ~BOOKE_TCR_DIE); + rtems_interrupt_enable(l); + } else { + /* + * Nothing to do as we cannot disable all interrupts and + * the decrementer interrupt enable is MSR_EE + */ + } +} + +void clockOn(void* unused) +{ + rtems_interrupt_level l; + + PPC_Set_decrementer( Clock_Decrementer_value ); + + if ( ppc_cpu_is_bookE() ) { + _write_BOOKE_DECAR( Clock_Decrementer_value ); + + rtems_interrupt_disable(l); + + /* clear pending/stale irq */ + _write_BOOKE_TSR( BOOKE_TSR_DIS ); + /* enable */ + _write_BOOKE_TCR( _read_BOOKE_TCR() | BOOKE_TCR_DIE ); + + rtems_interrupt_enable(l); + + } +} + +static void clockHandler(void) +{ + #if (CLOCK_DRIVER_USE_FAST_IDLE == 1) + rtems_interrupt_level level; + uint32_t tb; + + rtems_interrupt_disable(level); + + tb = ppc_time_base(); + rtems_timecounter_tick(); + + while ( _Thread_Heir == _Thread_Executing && _Thread_Executing->is_idle ) { + tb += Clock_Decrementer_value; + ppc_set_time_base( tb ); + rtems_timecounter_tick(); + } + + rtems_interrupt_enable(level); + #else + rtems_timecounter_tick(); + #endif +} + +static void (*clock_handler)(void); + +/* + * Clock_isr + * + * This is the clock tick interrupt handler. + * + * Input parameters: + * vector - vector number + * + * Output parameters: NONE + * + * Return values: NONE + * + */ +void clockIsr(void *unused) +{ + int decr; + + /* + * The driver has seen another tick. + */ + do { + register uint32_t flags; + + rtems_interrupt_disable(flags); + __asm__ volatile ( + "mfdec %0; add %0, %0, %1; mtdec %0" + : "=&r"(decr) + : "r"(Clock_Decrementer_value) + ); + rtems_interrupt_enable(flags); + + Clock_driver_ticks += 1; + /* + * Real Time Clock counter/timer is set to automatically reload. + */ + clock_handler(); + } while ( decr < 0 ); +} + +/* + * Clock_isr_bookE + * + * This is the clock tick interrupt handler + * for bookE CPUs. For efficiency reasons we + * provide a separate handler rather than + * checking the CPU type each time. + */ +void clockIsrBookE(void *unused) +{ + /* Note: TSR bit has already been cleared in the exception handler */ + + /* + * The driver has seen another tick. + */ + + Clock_driver_ticks += 1; + + /* + * Real Time Clock counter/timer is set to automatically reload. + */ + clock_handler(); +} + +int clockIsOn(void* unused) +{ + uint32_t msr_value; + + _CPU_MSR_GET( msr_value ); + + if ( ppc_cpu_is_bookE() && ! (_read_BOOKE_TCR() & BOOKE_TCR_DIE) ) + msr_value = 0; + + if (msr_value & MSR_EE) return 1; + + return 0; +} + +/* + * Clock_exit + * + * This routine allows the clock driver to exit by masking the interrupt and + * disabling the clock's counter. + */ +void Clock_exit( void ) +{ + (void) BSP_disconnect_clock_handler (); +} + +/* + * Clock_initialize + * + * This routine initializes the clock driver. + */ +rtems_device_driver Clock_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *pargp +) +{ + rtems_interrupt_level l,tcr; + + Clock_Decrementer_value = (BSP_bus_frequency/BSP_time_base_divisor)* + rtems_configuration_get_milliseconds_per_tick(); + + /* set the decrementer now, prior to installing the handler + * so no interrupts will happen in a while. + */ + PPC_Set_decrementer( (unsigned)-1 ); + + /* On a bookE CPU the decrementer works differently. It doesn't + * count past zero but we can enable auto-reload :-) + */ + if ( ppc_cpu_is_bookE() ) { + + rtems_interrupt_disable(l); + + tcr = _read_BOOKE_TCR(); + tcr |= BOOKE_TCR_ARE; + tcr &= ~BOOKE_TCR_DIE; + _write_BOOKE_TCR(tcr); + + rtems_interrupt_enable(l); + } + + Clock_TC.tc_get_timecount = Clock_Get_timecount; + Clock_TC.tc_counter_mask = 0xffffffff; + Clock_TC.tc_frequency = (UINT64_C(1000) * BSP_bus_frequency) / BSP_time_base_divisor; + Clock_TC.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(&Clock_TC); + + /* + * If a decrementer exception was pending, it is cleared by + * executing the default (nop) handler at this point; + * The next exception will then be taken by our clock handler. + * Clock handler installation initializes the decrementer to + * the correct value. + */ + clock_handler = clockHandler; + if (!BSP_connect_clock_handler ()) { + printk("Unable to initialize system clock\n"); + rtems_fatal_error_occurred(1); + } + + return RTEMS_SUCCESSFUL; +} /* Clock_initialize */ diff --git a/bsps/powerpc/shared/clock/clock-ppc403.c b/bsps/powerpc/shared/clock/clock-ppc403.c new file mode 100644 index 0000000000..64e6f29d39 --- /dev/null +++ b/bsps/powerpc/shared/clock/clock-ppc403.c @@ -0,0 +1,275 @@ +/** + * @file + * + * This routine initializes the interval timer on the + * PowerPC 403 CPU. The tick frequency is specified by the BSP. + */ + +/* + * Original PPC403 Code from: + * Author: Andrew Bray <andy@i-cubed.co.uk> + * COPYRIGHT (c) 1995 by i-cubed ltd. + * + * Modifications for PPC405GP by Dennis Ehlin + * + * 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. + * + * 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-2012. + * 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.org/license/LICENSE. + */ + +#include <rtems.h> +#include <rtems/clockdrv.h> +#include <rtems/libio.h> +#include <stdlib.h> /* for atexit() */ +#include <rtems/bspIo.h> +#include <rtems/powerpc/powerpc.h> + +/* + * check, which exception handling code is present + */ + +#include <bsp.h> + +#include <bsp/vectors.h> +#include <bsp/irq.h> + +extern uint32_t bsp_clicks_per_usec; + +volatile uint32_t Clock_driver_ticks; +static uint32_t pit_value, tick_time; +static bool auto_restart; + +void Clock_exit( void ); + +static inline uint32_t get_itimer(void) +{ + register uint32_t rc; + +#ifndef ppc405 /* this is a ppc403 */ + __asm__ volatile ("mfspr %0, 0x3dd" : "=r" ((rc))); /* TBLO */ +#else /* ppc405 */ + __asm__ volatile ("mfspr %0, 0x10c" : "=r" ((rc))); /* 405GP TBL */ +#endif /* ppc405 */ + + return rc; +} + +/* + * ISR Handler + */ +static void Clock_isr(void* handle) +{ + uint32_t clicks_til_next_interrupt; +#if defined(BSP_PPC403_CLOCK_ISR_IRQ_LEVEL) + uint32_t l_orig = _ISR_Get_level(); +#endif + + if (!auto_restart) { + uint32_t itimer_value; + /* + * setup for next interrupt; making sure the new value is reasonably + * in the future.... in case we lost out on an interrupt somehow + */ + itimer_value = get_itimer(); + tick_time += pit_value; + + /* + * how far away is next interrupt *really* + * It may be a long time; this subtraction works even if + * Clock_clicks_interrupt < Clock_clicks_low_order via + * the miracle of unsigned math. + */ + clicks_til_next_interrupt = tick_time - itimer_value; + + /* + * If it is too soon then bump it up. + * This should only happen if CPU_HPPA_CLICKS_PER_TICK is too small. + * But setting it low is useful for debug, so... + */ + if (clicks_til_next_interrupt < 400) { + tick_time = itimer_value + 1000; + clicks_til_next_interrupt = 1000; + /* XXX: count these! this should be rare */ + } + + /* + * If it is too late, that means we missed the interrupt somehow. + * Rather than wait 35-50s for a wrap, we just fudge it here. + */ + if (clicks_til_next_interrupt > pit_value) { + tick_time = itimer_value + 1000; + clicks_til_next_interrupt = 1000; + /* XXX: count these! this should never happen :-) */ + } + + __asm__ volatile ("mtspr 0x3db, %0" :: "r" + (clicks_til_next_interrupt)); /* PIT */ + } + + __asm__ volatile ("mtspr 0x3d8, %0" :: "r" (0x08000000)); /* TSR */ + + Clock_driver_ticks++; + + /* Give BSP a chance to say if they want to re-enable interrupts */ +#if defined(BSP_PPC403_CLOCK_ISR_IRQ_LEVEL) + _ISR_Set_level(BSP_PPC403_CLOCK_ISR_IRQ_LEVEL); +#endif + rtems_clock_tick(); + +#if defined(BSP_PPC403_CLOCK_ISR_IRQ_LEVEL) + _ISR_Set_level(l_orig) +#endif +} + +static int ClockIsOn(const rtems_irq_connect_data* unused) +{ + register uint32_t tcr; + + __asm__ volatile ("mfspr %0, 0x3da" : "=r" ((tcr))); /* TCR */ + + return (tcr & 0x04000000) != 0; +} + +static void ClockOff(const rtems_irq_connect_data* unused) +{ + register uint32_t tcr; + + __asm__ volatile ("mfspr %0, 0x3da" : "=r" ((tcr))); /* TCR */ + tcr &= ~ 0x04400000; + __asm__ volatile ("mtspr 0x3da, %0" : "=r" ((tcr)) : "0" ((tcr))); /* TCR */ +} + +static void ClockOn(const rtems_irq_connect_data* unused) +{ + uint32_t iocr; + register uint32_t tcr; +#ifndef ppc405 + uint32_t pvr; +#endif /* ppc403 */ + + Clock_driver_ticks = 0; + +#ifndef ppc405 /* this is a ppc403 */ + __asm__ volatile ("mfdcr %0, 0xa0" : "=r" (iocr)); /* IOCR */ + iocr &= ~4; /* timer clocked from system clock */ + __asm__ volatile ("mtdcr 0xa0, %0" : "=r" (iocr) : "0" (iocr)); /* IOCR */ + + __asm__ volatile ("mfspr %0, 0x11f" : "=r" ((pvr))); /* PVR */ + if (((pvr & 0xffff0000) >> 16) != 0x0020) + return; /* Not a ppc403 */ + + if ((pvr & 0xff00) == 0x0000) /* 403GA */ +#if 0 /* FIXME: in which processor versions will "autoload" work properly? */ + auto_restart = (pvr & 0x00f0) > 0x0000 ? true : false; +#else + /* no known chip version supports auto restart of timer... */ + auto_restart = false; +#endif + else if ((pvr & 0xff00) == 0x0100) /* 403GB */ + auto_restart = true; + +#else /* ppc405 */ + __asm__ volatile ("mfdcr %0, 0x0b2" : "=r" (iocr)); /*405GP CPC0_CR1 */ + iocr &=~0x800000; /* timer clocked from system clock CETE*/ + __asm__ volatile ("mtdcr 0x0b2, %0" : "=r" (iocr) : "0" (iocr)); /* 405GP CPC0_CR1 */ + + /* + * Enable auto restart + */ + auto_restart = true; +#endif /* ppc405 */ + + pit_value = rtems_configuration_get_microseconds_per_tick() * + bsp_clicks_per_usec; + + /* + * Set PIT value + */ + __asm__ volatile ("mtspr 0x3db, %0" : : "r" (pit_value)); /* PIT */ + + /* + * Set timer to autoreload, bit TCR->ARE = 1 0x0400000 + * Enable PIT interrupt, bit TCR->PIE = 1 0x4000000 + */ + tick_time = get_itimer() + pit_value; + + __asm__ volatile ("mfspr %0, 0x3da" : "=r" ((tcr))); /* TCR */ + tcr = (tcr & ~0x04400000) | (auto_restart ? 0x04400000 : 0x04000000); +#if 1 + __asm__ volatile ("mtspr 0x3da, %0" : "=r" ((tcr)) : "0" ((tcr))); /* TCR */ +#endif +} + +static void Install_clock(void (*clock_isr)(void *)) +{ + rtems_irq_connect_data clockIrqConnData; + + Clock_driver_ticks = 0; + + /* + * 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 + */ + 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); +} + +/* + * 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 ); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/powerpc/shared/clock/clock.c b/bsps/powerpc/shared/clock/clock.c new file mode 100644 index 0000000000..431488a901 --- /dev/null +++ b/bsps/powerpc/shared/clock/clock.c @@ -0,0 +1,247 @@ +/** + * @file + * + * @ingroup powerpc_shared + * + * @brief Source file for a clock driver. + */ + +/* + * Copyright (c) 2008-2015 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +#include <rtems.h> +#include <rtems/clockdrv.h> +#include <rtems/timecounter.h> + +#include <libcpu/powerpc-utility.h> +#include <bsp/vectors.h> + +#define RTEMS_STATUS_CHECKS_USE_PRINTK + +#include <rtems/status-checks.h> + +/* + * This variable must be defined in the BSP and valid before clock driver + * initialization. + */ +extern uint32_t bsp_time_base_frequency; + +#define PPC405_PIT 0x3db + +#define PPC_CLOCK_DECREMENTER_MAX UINT32_MAX + +volatile uint32_t Clock_driver_ticks = 0; + +static uint32_t ppc_clock_decrementer_value = PPC_CLOCK_DECREMENTER_MAX; + +static uint32_t ppc_clock_next_time_base; + +static struct timecounter ppc_tc; + +static uint32_t ppc_get_timecount(struct timecounter *tc) +{ + return ppc_time_base(); +} + +static void ppc_clock_no_tick(void) +{ + /* Do nothing */ +} + +static void (*ppc_clock_tick)(void) = ppc_clock_no_tick; + +static int ppc_clock_exception_handler( + BSP_Exception_frame *frame, + unsigned number +) +{ + uint32_t delta = ppc_clock_decrementer_value; + uint32_t next = ppc_clock_next_time_base; + uint32_t dec = 0; + uint32_t now = 0; + uint32_t msr = 0; + + do { + /* Increment clock ticks */ + Clock_driver_ticks += 1; + + /* Enable external exceptions */ + msr = ppc_external_exceptions_enable(); + + /* Call clock ticker */ + ppc_clock_tick(); + + /* Restore machine state */ + ppc_external_exceptions_disable( msr); + + /* Next time base */ + next += delta; + + /* Current time */ + now = ppc_time_base(); + + /* New decrementer value */ + dec = next - now; + } while (dec > delta); + + /* Set decrementer */ + ppc_set_decrementer_register( dec); + + /* Expected next time base */ + ppc_clock_next_time_base = next; + + return 0; +} + +static int ppc_clock_exception_handler_first( + BSP_Exception_frame *frame, + unsigned number +) +{ + /* We have to clear the first pending decrementer exception this way */ + + if (ppc_decrementer_register() >= 0x80000000) { + ppc_clock_exception_handler( frame, number); + } + + ppc_exc_set_handler( ASM_DEC_VECTOR, ppc_clock_exception_handler); + + return 0; +} + +static int ppc_clock_exception_handler_booke( + BSP_Exception_frame *frame, + unsigned number +) +{ + uint32_t msr; + + /* Acknowledge decrementer request */ + PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_TSR, BOOKE_TSR_DIS); + + /* Increment clock ticks */ + Clock_driver_ticks += 1; + + /* Enable external exceptions */ + msr = ppc_external_exceptions_enable(); + + /* Call clock ticker */ + ppc_clock_tick(); + + /* Restore machine state */ + ppc_external_exceptions_disable( msr); + + return 0; +} + +static int ppc_clock_exception_handler_ppc405(BSP_Exception_frame *frame, unsigned number) +{ + uint32_t msr; + + /* Acknowledge PIT request */ + PPC_SET_SPECIAL_PURPOSE_REGISTER(PPC405_TSR, BOOKE_TSR_DIS); + + /* Increment clock ticks */ + Clock_driver_ticks += 1; + + /* Enable external exceptions */ + msr = ppc_external_exceptions_enable(); + + /* Call clock ticker */ + ppc_clock_tick(); + + /* Restore machine state */ + ppc_external_exceptions_disable(msr); + + return 0; +} + +void Clock_exit(void) +{ + /* Set the decrementer to the maximum value */ + ppc_set_decrementer_register( PPC_CLOCK_DECREMENTER_MAX); + + /* Use default clock handler */ + ppc_clock_tick = ppc_clock_no_tick; +} + +rtems_device_driver Clock_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + uint64_t frequency = bsp_time_base_frequency; + uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick(); + uint32_t interval = (uint32_t) ((frequency * us_per_tick) / 1000000); + + /* + * Set default ticker. + */ + ppc_clock_tick = rtems_timecounter_tick; + + if (ppc_cpu_is_bookE() != PPC_BOOKE_405) { + /* Decrementer value */ + ppc_clock_decrementer_value = interval - 1; + + /* Check decrementer value */ + if (ppc_clock_decrementer_value == 0) { + ppc_clock_decrementer_value = PPC_CLOCK_DECREMENTER_MAX; + RTEMS_SYSLOG_ERROR( "decrementer value would be zero, will be set to maximum value instead\n"); + } + if (ppc_cpu_is_bookE()) { + /* Set decrementer auto-reload value */ + PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_DECAR, ppc_clock_decrementer_value); + + /* Install exception handler */ + ppc_exc_set_handler( ASM_BOOKE_DEC_VECTOR, ppc_clock_exception_handler_booke); + + /* Enable decrementer and auto-reload */ + PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( BOOKE_TCR, BOOKE_TCR_DIE | BOOKE_TCR_ARE); + } else { + /* Here the decrementer value is actually the interval */ + ++ppc_clock_decrementer_value; + + /* Initialize next time base */ + ppc_clock_next_time_base = ppc_time_base() + ppc_clock_decrementer_value; + + /* Install exception handler */ + ppc_exc_set_handler( ASM_DEC_VECTOR, ppc_clock_exception_handler_first); + } + + /* Set the decrementer value */ + ppc_set_decrementer_register( ppc_clock_decrementer_value); + } else { + /* PIT interval value */ + ppc_clock_decrementer_value = interval; + + /* Install exception handler */ + ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, ppc_clock_exception_handler_ppc405); + + /* Enable PIT and auto-reload */ + PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS(PPC405_TCR, BOOKE_TCR_DIE | BOOKE_TCR_ARE); + + /* Set PIT auto-reload and initial value */ + PPC_SET_SPECIAL_PURPOSE_REGISTER(PPC405_PIT, interval); + } + + /* Install timecounter */ + ppc_tc.tc_get_timecount = ppc_get_timecount; + ppc_tc.tc_counter_mask = 0xffffffff; + ppc_tc.tc_frequency = frequency; + ppc_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(&ppc_tc); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/powerpc/shared/clock/p_clock.c b/bsps/powerpc/shared/clock/p_clock.c new file mode 100644 index 0000000000..1ff7ca06a6 --- /dev/null +++ b/bsps/powerpc/shared/clock/p_clock.c @@ -0,0 +1,43 @@ +/* + * Clock Tick interrupt conexion code. + */ + +/* + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + * + * Modified to support the MPC750. + * Modifications Copyright (c) 1999 Eric Valette valette@crf.canon.fr + */ + +#include <bsp.h> +#include <bsp/irq.h> +#include <libcpu/c_clock.h> +#include <libcpu/cpuIdent.h> + +static rtems_irq_connect_data clockIrqData; +static rtems_irq_connect_data clockIrqData = { + BSP_DECREMENTER, + clockIsr, + NULL, + (rtems_irq_enable)clockOn, + (rtems_irq_disable)clockOff, + (rtems_irq_is_enabled) clockIsOn +}; + +int BSP_disconnect_clock_handler(void) +{ + return BSP_remove_rtems_irq_handler(&clockIrqData); +} + +int BSP_connect_clock_handler(void) +{ + if ( ppc_cpu_is_bookE() ) + clockIrqData.hdl = clockIsrBookE; + + return BSP_install_rtems_irq_handler(&clockIrqData); +} |