[rtems commit] bsps/powerpc: Add PPC405 support for shared clock

Sebastian Huber sebh at rtems.org
Mon Jun 24 08:48:40 UTC 2013


Module:    rtems
Branch:    master
Commit:    509e0f3ff3f83b40dc7d38e32f98225361d4f49f
Changeset: http://git.rtems.org/rtems/commit/?id=509e0f3ff3f83b40dc7d38e32f98225361d4f49f

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Fri Jun 21 17:16:37 2013 +0200

bsps/powerpc: Add PPC405 support for shared clock

---

 c/src/lib/libbsp/powerpc/shared/clock/clock.c |  110 ++++++++++++++++++-------
 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 f4ade6f..6d6089e 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;
 }




More information about the vc mailing list