summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/powerpc
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2013-06-21 17:16:37 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-06-24 10:53:58 +0200
commit509e0f3ff3f83b40dc7d38e32f98225361d4f49f (patch)
treeae35af1ced33fe240d88906139fa7eb90fef1afd /c/src/lib/libbsp/powerpc
parentbsps/powerpc: Delete clock_4xx.c (diff)
downloadrtems-509e0f3ff3f83b40dc7d38e32f98225361d4f49f.tar.bz2
bsps/powerpc: Add PPC405 support for shared clock
Diffstat (limited to 'c/src/lib/libbsp/powerpc')
-rw-r--r--c/src/lib/libbsp/powerpc/shared/clock/clock.c110
1 files changed, 79 insertions, 31 deletions
diff --git a/c/src/lib/libbsp/powerpc/shared/clock/clock.c b/c/src/lib/libbsp/powerpc/shared/clock/clock.c
index f4ade6f75d..6d6089ebaf 100644
--- a/c/src/lib/libbsp/powerpc/shared/clock/clock.c
+++ b/c/src/lib/libbsp/powerpc/shared/clock/clock.c
@@ -7,7 +7,7 @@
*/
/*
- * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2008-2013 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Obere Lagerstr. 30
@@ -36,6 +36,8 @@
*/
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;
@@ -132,6 +134,28 @@ static int ppc_clock_exception_handler_booke( BSP_Exception_frame *frame, unsign
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;
+}
+
static uint32_t ppc_clock_nanoseconds_since_last_tick(void)
{
uint64_t k = ppc_clock_factor;
@@ -141,6 +165,19 @@ static uint32_t ppc_clock_nanoseconds_since_last_tick(void)
return (uint32_t) (((i - c) * k) >> 32);
}
+static uint32_t ppc_clock_nanoseconds_since_last_tick_ppc405(void)
+{
+ uint64_t k = ppc_clock_factor;
+ uint32_t i = ppc_clock_decrementer_value;
+ uint32_t c = i - PPC_SPECIAL_PURPOSE_REGISTER(PPC405_PIT);
+
+ if ((PPC_SPECIAL_PURPOSE_REGISTER(PPC405_TSR) & BOOKE_TSR_DIS) != 0) {
+ c = i - PPC_SPECIAL_PURPOSE_REGISTER(PPC405_PIT) + i;
+ }
+
+ return (uint32_t) ((c * k) >> 32);
+}
+
void Clock_exit(void)
{
/* Set the decrementer to the maximum value */
@@ -156,9 +193,6 @@ rtems_device_driver Clock_initialize( rtems_device_major_number major, rtems_dev
uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
uint32_t interval = (uint32_t) ((frequency * us_per_tick) / 1000000);
- /* Current CPU type */
- ppc_cpu_id_t cpu_type = get_ppc_cpu_type();
-
/* Make major/minor available to others such as shared memory driver */
rtems_clock_major = major;
rtems_clock_minor = minor;
@@ -172,46 +206,60 @@ rtems_device_driver Clock_initialize( rtems_device_major_number major, rtems_dev
*/
ppc_clock_tick = (void (*)(void)) rtems_clock_tick;
- /* Set the decrementer to the maximum value */
- ppc_set_decrementer_register( PPC_CLOCK_DECREMENTER_MAX);
-
/* Factor for nano seconds extension */
ppc_clock_factor = (1000000000ULL << 32) / frequency;
- /* Decrementer value */
- ppc_clock_decrementer_value = interval - 1;
+ 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");
- }
+ /* 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");
+ }
- /* Set the nanoseconds since last tick handler */
- rtems_clock_set_nanoseconds_extension( ppc_clock_nanoseconds_since_last_tick);
+ /* Set the nanoseconds since last tick handler */
+ rtems_clock_set_nanoseconds_extension( ppc_clock_nanoseconds_since_last_tick);
- if (ppc_cpu_is_bookE()) {
- /* Set decrementer auto-reload value */
- PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_DECAR, ppc_clock_decrementer_value);
+ 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);
+ /* 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;
- /* Enable decrementer and auto-reload */
- PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( BOOKE_TCR, BOOKE_TCR_DIE | BOOKE_TCR_ARE);
+ /* 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 {
- /* Here the decrementer value is actually the interval */
- ++ppc_clock_decrementer_value;
+ /* PIT interval value */
+ ppc_clock_decrementer_value = interval;
- /* Initialize next time base */
- ppc_clock_next_time_base = ppc_time_base() + ppc_clock_decrementer_value;
+ /* Set the nanoseconds since last tick handler */
+ rtems_clock_set_nanoseconds_extension(ppc_clock_nanoseconds_since_last_tick_ppc405);
/* Install exception handler */
- ppc_exc_set_handler( ASM_DEC_VECTOR, ppc_clock_exception_handler_first);
- }
+ ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, ppc_clock_exception_handler_ppc405);
- /* Set the decrementer value */
- ppc_set_decrementer_register( ppc_clock_decrementer_value);
+ /* 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);
+ }
return RTEMS_SUCCESSFUL;
}