From 7632906fc290b652416ab59eb5fb49356c064ed6 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 19 Apr 2018 06:35:52 +0200 Subject: bsps: Move clock drivers to bsps This patch is a part of the BSP source reorganization. Update #3285. --- bsps/arm/shared/clock/clock-armv7m.c | 159 ++++++++++++++++++++++++++++++++++ bsps/arm/shared/clock/clock-nxp-lpc.c | 136 +++++++++++++++++++++++++++++ 2 files changed, 295 insertions(+) create mode 100644 bsps/arm/shared/clock/clock-armv7m.c create mode 100644 bsps/arm/shared/clock/clock-nxp-lpc.c (limited to 'bsps/arm/shared') diff --git a/bsps/arm/shared/clock/clock-armv7m.c b/bsps/arm/shared/clock/clock-armv7m.c new file mode 100644 index 0000000000..39cd4efdc7 --- /dev/null +++ b/bsps/arm/shared/clock/clock-armv7m.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2011-2012 Sebastian Huber. 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.org/license/LICENSE. + */ + +#include +#include +#include + +#include + +#ifdef ARM_MULTILIB_ARCH_V7M + +/* This is defined in dev/clock/clockimpl.h */ +static void Clock_isr(void *arg); + +typedef struct { + rtems_timecounter_simple base; + void (*tick)(void); + bool countflag; +} ARMV7M_Timecounter; + +static ARMV7M_Timecounter _ARMV7M_TC; + +static uint32_t _ARMV7M_TC_systick_get(rtems_timecounter_simple *tc) +{ + volatile ARMV7M_Systick *systick = _ARMV7M_Systick; + + return systick->cvr; +} + +static bool _ARMV7M_TC_systick_is_pending(rtems_timecounter_simple *base) +{ + ARMV7M_Timecounter *tc = (ARMV7M_Timecounter *) base; + rtems_interrupt_level level; + bool countflag; + + rtems_interrupt_disable(level); + + countflag = tc->countflag; + if (!countflag) { + volatile ARMV7M_Systick *systick = _ARMV7M_Systick; + + countflag = ((systick->csr & ARMV7M_SYSTICK_CSR_COUNTFLAG) != 0); + tc->countflag = countflag; + } + + rtems_interrupt_enable(level); + + return countflag; +} + +static uint32_t _ARMV7M_TC_systick_get_timecount(struct timecounter *tc) +{ + return rtems_timecounter_simple_downcounter_get( + tc, + _ARMV7M_TC_systick_get, + _ARMV7M_TC_systick_is_pending + ); +} + +static void _ARMV7M_TC_systick_at_tick(rtems_timecounter_simple *base) +{ + ARMV7M_Timecounter *tc = (ARMV7M_Timecounter *) base; + volatile ARMV7M_Systick *systick = _ARMV7M_Systick; + + tc->countflag = false; + + /* Clear COUNTFLAG */ + systick->csr; +} + +static void _ARMV7M_TC_systick_tick(void) +{ + rtems_timecounter_simple_downcounter_tick( + &_ARMV7M_TC.base, + _ARMV7M_TC_systick_get, + _ARMV7M_TC_systick_at_tick + ); +} + +static void _ARMV7M_TC_tick(void) +{ + (*_ARMV7M_TC.tick)(); +} + +static void _ARMV7M_Systick_handler(void) +{ + _ARMV7M_Interrupt_service_enter(); + Clock_isr(NULL); + _ARMV7M_Interrupt_service_leave(); +} + +static void _ARMV7M_Systick_handler_install(void) +{ + _ARMV7M_Set_exception_priority_and_handler( + ARMV7M_VECTOR_SYSTICK, + BSP_ARMV7M_SYSTICK_PRIORITY, + _ARMV7M_Systick_handler + ); +} + +static void _ARMV7M_Systick_initialize(void) +{ + volatile ARMV7M_Systick *systick = _ARMV7M_Systick; + #ifdef BSP_ARMV7M_SYSTICK_FREQUENCY + uint64_t freq = BSP_ARMV7M_SYSTICK_FREQUENCY; + #else + uint64_t freq = ARMV7M_SYSTICK_CALIB_TENMS_GET(systick->calib) * 100ULL; + #endif + uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick(); + uint64_t interval = (freq * us_per_tick) / 1000000ULL; + + systick->rvr = (uint32_t) interval; + systick->cvr = 0; + systick->csr = ARMV7M_SYSTICK_CSR_ENABLE + | ARMV7M_SYSTICK_CSR_TICKINT + | ARMV7M_SYSTICK_CSR_CLKSOURCE; + + _ARMV7M_TC.tick = _ARMV7M_TC_systick_tick; + rtems_timecounter_simple_install( + &_ARMV7M_TC.base, + freq, + interval, + _ARMV7M_TC_systick_get_timecount + ); +} + +static void _ARMV7M_Systick_cleanup(void) +{ + volatile ARMV7M_Systick *systick = _ARMV7M_Systick; + + systick->csr = 0; +} + +#define Clock_driver_timecounter_tick() _ARMV7M_TC_tick() + +#define Clock_driver_support_initialize_hardware() \ + _ARMV7M_Systick_initialize() + +#define Clock_driver_support_install_isr(isr) \ + _ARMV7M_Systick_handler_install() + +#define Clock_driver_support_shutdown_hardware() \ + _ARMV7M_Systick_cleanup() + +/* Include shared source clock driver code */ +#include "../../../shared/dev/clock/clockimpl.h" + +#endif /* ARM_MULTILIB_ARCH_V7M */ diff --git a/bsps/arm/shared/clock/clock-nxp-lpc.c b/bsps/arm/shared/clock/clock-nxp-lpc.c new file mode 100644 index 0000000000..c551f75f68 --- /dev/null +++ b/bsps/arm/shared/clock/clock-nxp-lpc.c @@ -0,0 +1,136 @@ +/** + * @file + * + * @ingroup lpc_clock + * + * @brief Clock driver configuration. + */ + +/* + * Copyright (c) 2009-2015 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 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.org/license/LICENSE. + */ + +#include +#include + +#include +#include + +#ifdef ARM_MULTILIB_ARCH_V4 + +/* This is defined in ../../../shared/dev/clock/clockimpl.h */ +void Clock_isr(rtems_irq_hdl_param arg); + +static volatile lpc_timer *const lpc_clock = + (volatile lpc_timer *) LPC_CLOCK_TIMER_BASE; + +static volatile lpc_timer *const lpc_timecounter = + (volatile lpc_timer *) LPC_CLOCK_TIMECOUNTER_BASE; + +static struct timecounter lpc_clock_tc; + +static uint32_t lpc_clock_tc_get_timecount(struct timecounter *tc) +{ + return lpc_timecounter->tc; +} + +static void lpc_clock_at_tick(void) +{ + lpc_clock->ir = LPC_TIMER_IR_MR0; +} + +static void lpc_clock_handler_install(void) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + sc = rtems_interrupt_handler_install( + LPC_CLOCK_INTERRUPT, + "Clock", + RTEMS_INTERRUPT_UNIQUE, + (rtems_interrupt_handler) Clock_isr, + NULL + ); + if (sc != RTEMS_SUCCESSFUL) { + rtems_fatal_error_occurred(0xdeadbeef); + } +} + +static void lpc_clock_initialize(void) +{ + uint64_t interval = ((uint64_t) LPC_CLOCK_REFERENCE + * (uint64_t) rtems_configuration_get_microseconds_per_tick()) / 1000000; + + /* Enable module */ + LPC_CLOCK_MODULE_ENABLE(); + + /* Reset timer */ + lpc_clock->tcr = LPC_TIMER_TCR_RST; + + /* Clear interrupt flags */ + lpc_clock->ir = LPC_TIMER_IR_ALL; + + /* Set timer mode */ + lpc_clock->ccr = 0; + + /* Timer is incremented every PERIPH_CLK tick */ + lpc_clock->pr = 0; + + /* Set match registers */ + lpc_clock->mr0 = (uint32_t) interval; + + /* Generate interrupt and reset counter on match with MR0 */ + lpc_clock->mcr = LPC_TIMER_MCR_MR0_INTR | LPC_TIMER_MCR_MR0_RST; + + /* No external match */ + lpc_clock->emr = 0x0; + + /* Enable timer */ + lpc_clock->tcr = LPC_TIMER_TCR_EN; + + /* Install timecounter */ + lpc_clock_tc.tc_get_timecount = lpc_clock_tc_get_timecount; + lpc_clock_tc.tc_counter_mask = 0xffffffff; + lpc_clock_tc.tc_frequency = LPC_CLOCK_REFERENCE; + lpc_clock_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(&lpc_clock_tc); +} + +static void lpc_clock_cleanup(void) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + /* Disable timer */ + lpc_clock->tcr = 0x0; + + /* Remove interrupt handler */ + sc = rtems_interrupt_handler_remove( + LPC_CLOCK_INTERRUPT, + (rtems_interrupt_handler) Clock_isr, + NULL + ); + if (sc != RTEMS_SUCCESSFUL) { + rtems_fatal_error_occurred(0xdeadbeef); + } +} + +#define Clock_driver_support_at_tick() lpc_clock_at_tick() +#define Clock_driver_support_initialize_hardware() lpc_clock_initialize() +#define Clock_driver_support_install_isr(isr) \ + lpc_clock_handler_install() + +#define Clock_driver_support_shutdown_hardware() lpc_clock_cleanup() + +/* Include shared source clock driver code */ +#include "../../../shared/dev/clock/clockimpl.h" + +#endif /* ARM_MULTILIB_ARCH_V4 */ -- cgit v1.2.3