summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2012-01-23 11:19:22 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2012-01-23 11:19:22 +0100
commita762dc2a49fad0e7797806fefd34d144b6d998b2 (patch)
tree3f21a6ba6320a3a89581a3d1e2be5162bb8a904f /c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c
parentGoogle C++ Testing Framework 1.6.0. (diff)
downloadrtems-a762dc2a49fad0e7797806fefd34d144b6d998b2.tar.bz2
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.
Diffstat (limited to 'c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c')
-rw-r--r--c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c168
1 files changed, 114 insertions, 54 deletions
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
- * <rtems@embedded-brains.de>
+ * Copyright (c) 2009-2011 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.com/license/LICENSE.
*/
-#include <mpc55xx/regs.h>
-#include <mpc55xx/emios.h>
-
-#include <rtems.h>
-
#include <bsp.h>
#include <bsp/irq.h>
-#define RTEMS_STATUS_CHECKS_USE_PRINTK
+#include <mpc55xx/regs.h>
-#include <rtems/status-checks.h>
+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 <mpc55xx/emios.h>
-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