From a762dc2a49fad0e7797806fefd34d144b6d998b2 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 23 Jan 2012 11:19:22 +0100 Subject: Support for MPC5643L. Rework of the start sequence to reduce the amount assembler code and to support configuration tables which may be provided by the application. --- .../libbsp/powerpc/mpc55xxevb/clock/clock-config.c | 168 ++++++++++++++------- 1 file changed, 114 insertions(+), 54 deletions(-) (limited to 'c/src/lib/libbsp/powerpc/mpc55xxevb/clock') diff --git a/c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c b/c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c index 0d1561880f..d8a6594ad2 100644 --- a/c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c +++ b/c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c @@ -7,81 +7,76 @@ */ /* - * Copyright (c) 2009 - * embedded brains GmbH - * Obere Lagerstr. 30 - * D-82178 Puchheim - * Germany - * + * Copyright (c) 2009-2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * * * 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. */ -#include -#include - -#include - #include #include -#define RTEMS_STATUS_CHECKS_USE_PRINTK +#include -#include +static uint64_t mpc55xx_clock_factor; -/* This is defined in clockdrv_shell.h */ -rtems_isr Clock_isr( rtems_vector_number vector); +#if defined(MPC55XX_CLOCK_EMIOS_CHANNEL) -#define Clock_driver_support_at_tick() \ - do { \ - union EMIOS_CSR_tag csr = MPC55XX_ZERO_FLAGS; \ - csr.B.FLAG = 1; \ - EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL].CSR.R = csr.R; \ - } while (0) +#include -static uint64_t mpc55xx_clock_factor; +static void mpc55xx_clock_at_tick(void) +{ + union EMIOS_CSR_tag csr = MPC55XX_ZERO_FLAGS; + csr.B.FLAG = 1; + EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL].CSR.R = csr.R; +} -static void mpc55xx_clock_handler_install( rtems_isr_entry isr, - rtems_isr_entry *old_isr) +static void mpc55xx_clock_handler_install(rtems_isr_entry isr) { rtems_status_code sc = RTEMS_SUCCESSFUL; sc = mpc55xx_interrupt_handler_install( - MPC55XX_IRQ_EMIOS( MPC55XX_CLOCK_EMIOS_CHANNEL), + MPC55XX_IRQ_EMIOS(MPC55XX_CLOCK_EMIOS_CHANNEL), "clock", RTEMS_INTERRUPT_UNIQUE, MPC55XX_INTC_MIN_PRIORITY, (rtems_interrupt_handler) isr, NULL ); - *old_isr = NULL; - RTEMS_CHECK_SC_VOID( sc, "install clock interrupt handler"); + if (sc != RTEMS_SUCCESSFUL) { + rtems_fatal_error_occurred(0xdeadbeef); + } } -static void mpc55xx_clock_initialize( void) +static void mpc55xx_clock_initialize(void) { volatile struct EMIOS_CH_tag *regs = &EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL]; union EMIOS_CCR_tag ccr = MPC55XX_ZERO_FLAGS; union EMIOS_CSR_tag csr = MPC55XX_ZERO_FLAGS; unsigned prescaler = mpc55xx_emios_global_prescaler(); - uint64_t interval = ((uint64_t) bsp_clock_speed - * (uint64_t) rtems_configuration_get_microseconds_per_tick()) / 1000000; + uint64_t reference_clock = bsp_clock_speed; + uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick(); + uint64_t interval = (reference_clock * us_per_tick) / 1000000; - mpc55xx_clock_factor = (1000000000ULL << 32) / bsp_clock_speed; + mpc55xx_clock_factor = (1000000000ULL << 32) / reference_clock; /* Apply prescaler */ if (prescaler > 0) { interval /= (uint64_t) prescaler; } else { - RTEMS_SYSLOG_ERROR( "unexpected global eMIOS prescaler\n"); + rtems_fatal_error_occurred(0xdeadbeef); } /* Check interval */ if (interval == 0 || interval > MPC55XX_EMIOS_VALUE_MAX) { - interval = MPC55XX_EMIOS_VALUE_MAX; - RTEMS_SYSLOG_ERROR( "clock timer interval out of range\n"); + rtems_fatal_error_occurred(0xdeadbeef); } /* Configure eMIOS channel */ @@ -103,37 +98,28 @@ static void mpc55xx_clock_initialize( void) regs->CADR.R = (uint32_t) interval - 1; /* Set control register */ -#if MPC55XX_CHIP_TYPE / 10 == 551 - ccr.B.MODE = MPC55XX_EMIOS_MODE_MCB_UP_INT_CLK; -#else - ccr.B.MODE = MPC55XX_EMIOS_MODE_MC_UP_INT_CLK; -#endif + #if MPC55XX_CHIP_TYPE / 10 == 551 + ccr.B.MODE = MPC55XX_EMIOS_MODE_MCB_UP_INT_CLK; + #else + ccr.B.MODE = MPC55XX_EMIOS_MODE_MC_UP_INT_CLK; + #endif ccr.B.UCPREN = 1; ccr.B.FEN = 1; ccr.B.FREN = 1; regs->CCR.R = ccr.R; } -static void mpc55xx_clock_cleanup( void) +static void mpc55xx_clock_cleanup(void) { - rtems_status_code sc = RTEMS_SUCCESSFUL; volatile struct EMIOS_CH_tag *regs = &EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL]; union EMIOS_CCR_tag ccr = MPC55XX_ZERO_FLAGS; /* Set channel in GPIO mode */ ccr.B.MODE = MPC55XX_EMIOS_MODE_GPIO_INPUT; regs->CCR.R = ccr.R; - - /* Remove interrupt handler */ - sc = rtems_interrupt_handler_remove( - MPC55XX_IRQ_EMIOS( MPC55XX_CLOCK_EMIOS_CHANNEL), - (rtems_interrupt_handler) Clock_isr, - NULL - ); - RTEMS_CHECK_SC_VOID( sc, "remove clock interrupt handler"); } -static uint32_t mpc55xx_clock_nanoseconds_since_last_tick( void) +static uint32_t mpc55xx_clock_nanoseconds_since_last_tick(void) { volatile struct EMIOS_CH_tag *regs = &EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL]; uint64_t c = regs->CCNTR.R; @@ -147,13 +133,87 @@ static uint32_t mpc55xx_clock_nanoseconds_since_last_tick( void) return (uint32_t) ((c * k) >> 32); } -#define Clock_driver_support_initialize_hardware() mpc55xx_clock_initialize() +#elif defined(MPC55XX_CLOCK_PIT_CHANNEL) + +static void mpc55xx_clock_at_tick(void) +{ + volatile PIT_RTI_CHANNEL_tag *channel = + &PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL]; + PIT_RTI_TFLG_32B_tag tflg = { .B = { .TIF = 1 } }; + + channel->TFLG.R = tflg.R; +} + +static void mpc55xx_clock_handler_install(rtems_isr_entry isr) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + sc = mpc55xx_interrupt_handler_install( + MPC55XX_IRQ_PIT_CHANNEL(MPC55XX_CLOCK_PIT_CHANNEL), + "clock", + RTEMS_INTERRUPT_UNIQUE, + MPC55XX_INTC_MIN_PRIORITY, + (rtems_interrupt_handler) isr, + NULL + ); + if (sc != RTEMS_SUCCESSFUL) { + rtems_fatal_error_occurred(0xdeadbeef); + } +} + +static void mpc55xx_clock_initialize(void) +{ + volatile PIT_RTI_CHANNEL_tag *channel = + &PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL]; + uint64_t reference_clock = bsp_clock_speed; + uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick(); + uint64_t interval = (reference_clock * us_per_tick) / 1000000; + PIT_RTI_PITMCR_32B_tag pitmcr = { .B = { .FRZ = 1 } }; + PIT_RTI_TCTRL_32B_tag tctrl = { .B = { .TIE = 1, .TEN = 1 } }; + + mpc55xx_clock_factor = (1000000000ULL << 32) / reference_clock; + + PIT_RTI.PITMCR.R = pitmcr.R; + channel->LDVAL.R = interval; + channel->TCTRL.R = tctrl.R; +} + +static void mpc55xx_clock_cleanup(void) +{ + volatile PIT_RTI_CHANNEL_tag *channel = + &PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL]; -#define Clock_driver_support_install_isr( isr, old_isr) \ - mpc55xx_clock_handler_install(isr,&old_isr) + channel->TCTRL.R = 0; +} -#define Clock_driver_support_shutdown_hardware() mpc55xx_clock_cleanup() +static uint32_t mpc55xx_clock_nanoseconds_since_last_tick(void) +{ + volatile PIT_RTI_CHANNEL_tag *channel = + &PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL]; + uint32_t c = channel->CVAL.R; + uint32_t i = channel->LDVAL.R; + uint64_t k = mpc55xx_clock_factor; + if (channel->TFLG.B.TIF != 0) { + c = channel->CVAL.R - i; + } + + return (uint32_t) (((i - c) * k) >> 32); +} + +#endif + +#define Clock_driver_support_at_tick() \ + mpc55xx_clock_at_tick() +#define Clock_driver_support_initialize_hardware() \ + mpc55xx_clock_initialize() +#define Clock_driver_support_install_isr(isr, old_isr) \ + do { \ + mpc55xx_clock_handler_install(isr); \ + old_isr = NULL; \ + } while (0) +#define Clock_driver_support_shutdown_hardware() \ + mpc55xx_clock_cleanup() #define Clock_driver_nanoseconds_since_last_tick \ mpc55xx_clock_nanoseconds_since_last_tick -- cgit v1.2.3