summaryrefslogtreecommitdiffstats
path: root/bsps/m68k
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-19 06:35:52 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-20 09:57:01 +0200
commit7632906fc290b652416ab59eb5fb49356c064ed6 (patch)
treeac036b1f95637e044e10138ceea8d2b56d80ec97 /bsps/m68k
parentbsps: Move bspsmpgetcurrentprocessor.c to bsps (diff)
downloadrtems-7632906fc290b652416ab59eb5fb49356c064ed6.tar.bz2
bsps: Move clock drivers to bsps
This patch is a part of the BSP source reorganization. Update #3285.
Diffstat (limited to 'bsps/m68k')
-rw-r--r--bsps/m68k/av5282/clock/clock.c61
-rw-r--r--bsps/m68k/gen68340/clock/ckinit.c104
-rw-r--r--bsps/m68k/gen68360/clock/clock.c101
-rw-r--r--bsps/m68k/genmcf548x/clock/clock.c102
-rw-r--r--bsps/m68k/mcf52235/clock/clock.c106
-rw-r--r--bsps/m68k/mcf5225x/clock/clock.c106
-rw-r--r--bsps/m68k/mcf5235/clock/clock.c61
-rw-r--r--bsps/m68k/mcf5329/clock/clock.c105
-rw-r--r--bsps/m68k/mrm332/clock/ckinit.c75
-rw-r--r--bsps/m68k/mvme147/clock/ckinit.c82
-rw-r--r--bsps/m68k/mvme162/clock/ckinit.c89
-rw-r--r--bsps/m68k/mvme167/clock/ckinit.c159
-rw-r--r--bsps/m68k/uC5282/clock/clock.c161
13 files changed, 1312 insertions, 0 deletions
diff --git a/bsps/m68k/av5282/clock/clock.c b/bsps/m68k/av5282/clock/clock.c
new file mode 100644
index 0000000000..f6e42f254d
--- /dev/null
+++ b/bsps/m68k/av5282/clock/clock.c
@@ -0,0 +1,61 @@
+/*
+ * Use the last periodic interval timer (PIT3) as the system clock.
+ */
+
+#include <rtems.h>
+#include <bsp.h>
+#include <mcf5282/mcf5282.h>
+
+/*
+ * Use INTC0 base
+ */
+#define CLOCK_VECTOR (64+58)
+
+/*
+ * Periodic interval timer interrupt handler
+ */
+#define Clock_driver_support_at_tick() \
+ do { \
+ MCF5282_PIT3_PCSR |= MCF5282_PIT_PCSR_PIF; \
+ } while (0) \
+
+/*
+ * Attach clock interrupt handler
+ */
+#define Clock_driver_support_install_isr( _new ) \
+ set_vector(_new, CLOCK_VECTOR, 1)
+
+/*
+ * Turn off the clock
+ */
+#define Clock_driver_support_shutdown_hardware() \
+ do { \
+ MCF5282_PIT3_PCSR &= ~MCF5282_PIT_PCSR_EN; \
+ } while(0)
+
+/*
+ * Set up the clock hardware
+ *
+ * We need to have 1 interrupt every 10,000 microseconds
+ * so we need to set prescaler to 64 and the PMR register to 0x23FE
+ */
+#define Clock_driver_support_initialize_hardware() \
+ do { \
+ int level; \
+ int preScaleCode = 5; \
+ MCF5282_INTC0_ICR58 = MCF5282_INTC_ICR_IL(PIT3_IRQ_LEVEL) | \
+ MCF5282_INTC_ICR_IP(PIT3_IRQ_PRIORITY); \
+ rtems_interrupt_disable( level ); \
+ MCF5282_INTC0_IMRH &= ~MCF5282_INTC_IMRH_INT58; \
+ MCF5282_PIT3_PCSR &= ~MCF5282_PIT_PCSR_EN; \
+ rtems_interrupt_enable( level ); \
+ MCF5282_PIT3_PMR = 0x23FE; \
+ MCF5282_PIT3_PCSR = MCF5282_PIT_PCSR_PRE(preScaleCode) | \
+ MCF5282_PIT_PCSR_PIE | \
+ MCF5282_PIT_PCSR_RLD | \
+ MCF5282_PIT_PCSR_EN; \
+ } while (0)
+
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
+#include "../../../shared/dev/clock/clockimpl.h"
diff --git a/bsps/m68k/gen68340/clock/ckinit.c b/bsps/m68k/gen68340/clock/ckinit.c
new file mode 100644
index 0000000000..e099d91fb6
--- /dev/null
+++ b/bsps/m68k/gen68340/clock/ckinit.c
@@ -0,0 +1,104 @@
+/*
+ * This routine initializes the MC68340/349 Periodic Interval Timer
+ */
+
+/*
+ * Based on the `gen68360' board support package, and covered by the
+ * original distribution terms.
+ *
+ * Geoffroy Montel
+ * France Telecom - CNET/DSM/TAM/CAT
+ * 4, rue du Clos Courtel
+ * 35512 CESSON-SEVIGNE
+ * FRANCE
+ *
+ * e-mail: g_montel@yahoo.com
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2014.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * 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 <stdlib.h> /* for atexit() */
+#include <bsp.h>
+#include <m68340.h>
+#include <rtems/clockdrv.h>
+
+#define CLOCK_VECTOR 120 /* clock isr routine vector in the vbr */
+#define CLOCK_IRQ_LEVEL 6 /* clock isr level */
+
+/*
+ * Clock_driver_ticks is a monotonically increasing counter of the
+ * number of clock ticks since the driver was initialized.
+ */
+volatile uint32_t Clock_driver_ticks;
+
+/*
+ * Periodic interval timer interrupt handler
+ */
+static rtems_isr
+Clock_isr (rtems_vector_number vector)
+{
+ /*
+ * Announce the clock tick
+ */
+ Clock_driver_ticks++;
+ rtems_clock_tick();
+}
+
+void
+Clock_exit (void)
+{
+ /*
+ * Turn off periodic interval timer
+ */
+ SIMPITR = 0;
+}
+
+static void
+Install_clock (rtems_isr_entry clock_isr)
+{
+ uint32_t pitr_tmp;
+ uint32_t usecs_per_tick;
+
+ Clock_driver_ticks = 0;
+
+ set_vector (clock_isr, CLOCK_VECTOR, 1);
+
+ /* sets the Periodic Interrupt Control Register PICR */
+ SIMPICR = ( CLOCK_IRQ_LEVEL << 8 ) | ( CLOCK_VECTOR );
+
+ /* sets the PITR count value */
+ /* this assumes a 32.765 kHz crystal */
+
+ usecs_per_tick = rtems_configuration_get_microseconds_per_tick();
+ /* find out whether prescaler should be enabled or not */
+ if ( usecs_per_tick <= 31128 ) {
+ pitr_tmp = ( usecs_per_tick * 8192 ) / 1000000 ;
+ } else {
+ pitr_tmp = ( usecs_per_tick / 1000000 ) * 16;
+ /* enable it */
+ pitr_tmp |= 0x100;
+ }
+
+ SIMPITR = (unsigned char) pitr_tmp;
+
+ atexit (Clock_exit);
+}
+
+rtems_device_driver
+Clock_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ Install_clock (Clock_isr);
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/m68k/gen68360/clock/clock.c b/bsps/m68k/gen68360/clock/clock.c
new file mode 100644
index 0000000000..b95ca5d275
--- /dev/null
+++ b/bsps/m68k/gen68360/clock/clock.c
@@ -0,0 +1,101 @@
+/*
+ * This routine initializes the MC68360 Periodic Interval Timer
+ *
+ * The PIT has rather poor resolution, but it is easy to set up
+ * and requires no housekeeping once it is going.
+ *
+ * W. Eric Norum
+ * Saskatchewan Accelerator Laboratory
+ * University of Saskatchewan
+ * Saskatoon, Saskatchewan, CANADA
+ * eric@skatter.usask.ca
+ */
+
+#include <rtems.h>
+#include <bsp.h>
+#include <rtems/m68k/m68360.h>
+
+#define CLOCK_VECTOR 120
+#define CLOCK_IRQ_LEVEL 4
+
+char M360DefaultWatchdogFeeder = 1;
+
+/*
+ * RTEMS and hardware have different notions of clock rate.
+ */
+static unsigned long rtems_nsec_per_tick;
+static unsigned long pit_nsec_per_tick;
+static unsigned long nsec;
+
+/*
+ * Periodic interval timer interrupt handler
+ * See if it's really time for a `tick'
+ * Perform a dummy read of DPRAM (work around bug in Rev. B of the 68360).
+ * Feed the watchdog
+ * Application code can override this by
+ * setting M360DefaultWatchdogFeeder to zero.
+ */
+#define Clock_driver_support_at_tick() \
+ do { \
+ nsec += pit_nsec_per_tick; \
+ if (nsec >= rtems_nsec_per_tick) \
+ return; \
+ nsec -= rtems_nsec_per_tick; \
+ m360.dpram0[0]; \
+ if (M360DefaultWatchdogFeeder) { \
+ m360.swsr = 0x55; \
+ m360.swsr = 0xAA; \
+ } \
+ } while (0) \
+
+/*
+ * Attach clock interrupt handler
+ */
+#define Clock_driver_support_install_isr( _new ) \
+ set_vector(_new, CLOCK_VECTOR, 1)
+
+/*
+ * Turn off the clock
+ */
+#define Clock_driver_support_shutdown_hardware() \
+ do { \
+ m360.pitr &= ~0xFF; \
+ } while(0)
+
+/*
+ * Set up the clock hardware
+ * The rate at which the periodic interval timer
+ * can generate interrupts is almost certainly not
+ * the same as desired by the BSP configuration.
+ * Handle the difference by choosing the largest PIT
+ * interval which is less than or equal to the RTEMS
+ * interval and skipping some hardware interrupts.
+ * To reduce the jitter in the calls to RTEMS the
+ * hardware interrupt interval is never greater than
+ * the maximum non-prescaled value from the PIT.
+ *
+ * For a 25 MHz external clock the basic clock rate is
+ * 40 nsec * 128 * 4 = 20.48 usec/tick
+ */
+extern int m360_clock_rate;
+
+#define Clock_driver_support_initialize_hardware() \
+ do { \
+ unsigned int divisor; \
+ unsigned long nsec_per_chip_tick = 1000000000 / m360_clock_rate; \
+ unsigned long nsec_per_pit_tick = 512 * nsec_per_chip_tick; \
+ rtems_nsec_per_tick = rtems_configuration_get_microseconds_per_tick() * 1000; \
+ divisor = rtems_nsec_per_tick / nsec_per_pit_tick; \
+ if (divisor > 255) \
+ divisor = 255; \
+ else if (divisor == 0) \
+ divisor = 1; \
+ pit_nsec_per_tick = nsec_per_pit_tick * divisor; \
+ m360.pitr &= ~0x1FF; \
+ m360.picr = (CLOCK_IRQ_LEVEL << 8) | CLOCK_VECTOR; \
+ m360.pitr |= divisor; \
+ } while (0)
+
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
+#include "../../../shared/dev/clock/clockimpl.h"
diff --git a/bsps/m68k/genmcf548x/clock/clock.c b/bsps/m68k/genmcf548x/clock/clock.c
new file mode 100644
index 0000000000..68b7c5f61b
--- /dev/null
+++ b/bsps/m68k/genmcf548x/clock/clock.c
@@ -0,0 +1,102 @@
+/*===============================================================*\
+| Project: RTEMS generic mcf548x BSP |
++-----------------------------------------------------------------+
+| File: clock.c |
++-----------------------------------------------------------------+
+| The file contains the clock driver code of generic MCF548x BSP. |
++-----------------------------------------------------------------+
+| Copyright (c) 2007 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
++-----------------------------------------------------------------+
+| |
+| Parts of the code has been derived from the "dBUG source code" |
+| package Freescale is providing for M548X EVBs. The usage of |
+| the modified or unmodified code and it's integration into the |
+| generic mcf548x BSP has been done according to the Freescale |
+| license terms. |
+| |
+| The Freescale license terms can be reviewed in the file |
+| |
+| Freescale_license.txt |
+| |
++-----------------------------------------------------------------+
+| |
+| The generic mcf548x BSP has been developed on the basic |
+| structures and modules of the av5282 BSP. |
+| |
++-----------------------------------------------------------------+
+| |
+| 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. |
+| |
++-----------------------------------------------------------------+
+| |
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 12.11.07 1.0 ras |
+| |
+\*===============================================================*/
+
+/*
+ * Use first slice timer (SLT0) as the system clock.
+ *
+ */
+
+#include <rtems.h>
+#include <bsp.h>
+#include <bsp/irq-generic.h>
+#include <mcf548x/mcf548x.h>
+
+/*
+ * Use SLT 0
+ */
+#define CLOCK_IRQ MCF548X_IRQ_SLT0
+
+/*
+ * Periodic interval timer interrupt handler
+ */
+#define Clock_driver_support_at_tick() \
+ do { \
+ MCF548X_SLT_SSR0 = MCF548X_SLT_SSR_ST; \
+ } while (0) \
+
+/*
+ * Attach clock interrupt handler
+ */
+#define Clock_driver_support_install_isr( _new ) \
+ set_vector(_new, CLOCK_IRQ + 64, 1)
+
+/*
+ * Turn off the clock
+ */
+#define Clock_driver_support_shutdown_hardware() \
+ do { \
+ MCF548X_SLT_SCR0 &= ~(MCF548X_SLT_SCR_TEN | MCF548X_SLT_SCR_RUN | MCF548X_SLT_SCR_IEN); \
+ } while(0)
+
+/*
+ * Set up the clock hardware
+ *
+ * We need to have 1 interrupt every 10,000 microseconds
+ * XLB clock 100 MHz / MCF548X_SLT_SLTCNT0 = XLB clock/100
+ */
+#define Clock_driver_support_initialize_hardware() \
+ do { \
+ bsp_interrupt_vector_enable(CLOCK_IRQ); \
+ MCF548X_SLT_SLTCNT0 = get_CPU_clock_speed() \
+ / 1000 \
+ * rtems_configuration_get_microseconds_per_tick() \
+ / 1000; \
+ MCF548X_SLT_SCR0 |= (MCF548X_SLT_SCR_TEN | MCF548X_SLT_SCR_RUN | MCF548X_SLT_SCR_IEN); \
+ } while (0)
+
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
+#include "../../../shared/dev/clock/clockimpl.h"
+
diff --git a/bsps/m68k/mcf52235/clock/clock.c b/bsps/m68k/mcf52235/clock/clock.c
new file mode 100644
index 0000000000..a879a770b1
--- /dev/null
+++ b/bsps/m68k/mcf52235/clock/clock.c
@@ -0,0 +1,106 @@
+/*
+ * Use the last periodic interval timer (PIT2) as the system clock.
+ */
+
+#include <rtems.h>
+#include <rtems/timecounter.h>
+#include <bsp.h>
+
+/*
+ * Use INTC0 base
+ */
+#define CLOCK_VECTOR (64+56)
+
+static rtems_timecounter_simple mcf52235_tc;
+
+static uint32_t mcf52235_tc_get(rtems_timecounter_simple *tc)
+{
+ return MCF_PIT1_PCNTR;
+}
+
+static bool mcf52235_tc_is_pending(rtems_timecounter_simple *tc)
+{
+ return (MCF_PIT1_PCSR & MCF_PIT_PCSR_PIF) != 0;
+}
+
+static uint32_t mcf52235_tc_get_timecount(struct timecounter *tc)
+{
+ return rtems_timecounter_simple_downcounter_get(
+ tc,
+ mcf52235_tc_get,
+ mcf52235_tc_is_pending
+ );
+}
+
+static void mcf52235_tc_at_tick(rtems_timecounter_simple *tc)
+{
+ MCF_PIT1_PCSR |= MCF_PIT_PCSR_PIF;
+}
+
+static void mcf52235_tc_tick(void)
+{
+ rtems_timecounter_simple_downcounter_tick(
+ &mcf52235_tc,
+ mcf52235_tc_get,
+ mcf52235_tc_at_tick
+ );
+}
+
+/*
+ * Attach clock interrupt handler
+ */
+#define Clock_driver_support_install_isr( _new ) \
+ set_vector(_new, CLOCK_VECTOR, 1)
+
+/*
+ * Turn off the clock
+ */
+#define Clock_driver_support_shutdown_hardware() \
+ do { \
+ MCF_PIT1_PCSR &= ~MCF_PIT_PCSR_EN; \
+ } while (0)
+
+/*
+ * Set up the clock hardware
+ *
+ * We need to have 1 interrupt every rtems_configuration_get_microseconds_per_tick()
+ */
+static void Clock_driver_support_initialize_hardware(void)
+{
+ int level;
+ uint32_t pmr;
+ uint32_t preScaleCode = 0;
+ uint32_t clk = bsp_get_CPU_clock_speed() >> 1;
+ uint32_t tps = 1000000 / rtems_configuration_get_microseconds_per_tick();
+
+ while (preScaleCode < 15) {
+ pmr = (clk >> preScaleCode) / tps;
+ if (pmr < (1 << 15))
+ break;
+ preScaleCode++;
+ }
+
+ MCF_INTC0_ICR56 = MCF_INTC_ICR_IL(PIT3_IRQ_LEVEL) |
+ MCF_INTC_ICR_IP(PIT3_IRQ_PRIORITY);
+ rtems_interrupt_disable(level);
+ MCF_INTC0_IMRH &= ~MCF_INTC_IMRH_MASK56;
+ MCF_PIT1_PCSR &= ~MCF_PIT_PCSR_EN;
+ rtems_interrupt_enable(level);
+
+ MCF_PIT1_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) |
+ MCF_PIT_PCSR_OVW | MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD;
+ MCF_PIT1_PMR = pmr;
+ MCF_PIT1_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) |
+ MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD | MCF_PIT_PCSR_EN;
+
+ rtems_timecounter_simple_install(
+ &mcf52235_tc,
+ clk >> preScaleCode,
+ pmr,
+ mcf52235_tc_get_timecount
+ );
+}
+
+#define Clock_driver_timecounter_tick() mcf52235_tc_tick()
+
+#include "../../../shared/dev/clock/clockimpl.h"
diff --git a/bsps/m68k/mcf5225x/clock/clock.c b/bsps/m68k/mcf5225x/clock/clock.c
new file mode 100644
index 0000000000..b01c37aef7
--- /dev/null
+++ b/bsps/m68k/mcf5225x/clock/clock.c
@@ -0,0 +1,106 @@
+/*
+ * Use the last periodic interval timer (PIT2) as the system clock.
+ */
+
+#include <rtems.h>
+#include <rtems/timecounter.h>
+#include <bsp.h>
+
+/*
+ * Use INTC0 base
+ */
+#define CLOCK_VECTOR (64+56)
+
+static rtems_timecounter_simple mcf5225x_tc;
+
+static uint32_t mcf5225x_tc_get(rtems_timecounter_simple *tc)
+{
+ return MCF_PIT1_PCNTR;
+}
+
+static bool mcf5225x_tc_is_pending(rtems_timecounter_simple *tc)
+{
+ return (MCF_PIT1_PCSR & MCF_PIT_PCSR_PIF) != 0;
+}
+
+static uint32_t mcf5225x_tc_get_timecount(struct timecounter *tc)
+{
+ return rtems_timecounter_simple_downcounter_get(
+ tc,
+ mcf5225x_tc_get,
+ mcf5225x_tc_is_pending
+ );
+}
+
+static void mcf5225x_tc_at_tick(rtems_timecounter_simple *tc)
+{
+ MCF_PIT1_PCSR |= MCF_PIT_PCSR_PIF;
+}
+
+static void mcf5225x_tc_tick(void)
+{
+ rtems_timecounter_simple_downcounter_tick(
+ &mcf5225x_tc,
+ mcf5225x_tc_get,
+ mcf5225x_tc_at_tick
+ );
+}
+
+/*
+ * Attach clock interrupt handler
+ */
+#define Clock_driver_support_install_isr( _new ) \
+ set_vector(_new, CLOCK_VECTOR, 1)
+
+/*
+ * Turn off the clock
+ */
+#define Clock_driver_support_shutdown_hardware() \
+ do { \
+ MCF_PIT1_PCSR &= ~MCF_PIT_PCSR_EN; \
+ } while (0)
+
+/*
+ * Set up the clock hardware
+ *
+ * We need to have 1 interrupt every BSP_rtems_configuration_get_microseconds_per_tick()
+ */
+static void Clock_driver_support_initialize_hardware(void)
+{
+ int level;
+ uint32_t pmr;
+ uint32_t preScaleCode = 0;
+ uint32_t clk = bsp_get_CPU_clock_speed() >> 1;
+ uint32_t tps = 1000000 / rtems_configuration_get_microseconds_per_tick();
+
+ while (preScaleCode < 15) {
+ pmr = (clk >> preScaleCode) / tps;
+ if (pmr < (1 << 15))
+ break;
+ preScaleCode++;
+ }
+
+ MCF_INTC0_ICR56 = MCF_INTC_ICR_IL(PIT3_IRQ_LEVEL) |
+ MCF_INTC_ICR_IP(PIT3_IRQ_PRIORITY);
+ rtems_interrupt_disable(level);
+ MCF_INTC0_IMRH &= ~MCF_INTC_IMRH_MASK56;
+ MCF_PIT1_PCSR &= ~MCF_PIT_PCSR_EN;
+ rtems_interrupt_enable(level);
+
+ MCF_PIT1_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) |
+ MCF_PIT_PCSR_OVW | MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD;
+ MCF_PIT1_PMR = pmr;
+ MCF_PIT1_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) |
+ MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD | MCF_PIT_PCSR_EN;
+
+ rtems_timecounter_simple_install(
+ &mcf5225x_tc,
+ clk >> preScaleCode,
+ pmr,
+ mcf5225x_tc_get_timecount
+ );
+}
+
+#define Clock_driver_timecounter_tick() mcf5225x_tc_tick()
+
+#include "../../../shared/dev/clock/clockimpl.h"
diff --git a/bsps/m68k/mcf5235/clock/clock.c b/bsps/m68k/mcf5235/clock/clock.c
new file mode 100644
index 0000000000..db3a5850fb
--- /dev/null
+++ b/bsps/m68k/mcf5235/clock/clock.c
@@ -0,0 +1,61 @@
+/*
+ * Use the last periodic interval timer (PIT3) as the system clock.
+ */
+
+#include <rtems.h>
+#include <bsp.h>
+#include <mcf5235/mcf5235.h>
+
+/*
+ * Use INTC0 base
+ */
+#define CLOCK_VECTOR (64+39)
+
+/*
+ * Periodic interval timer interrupt handler
+ */
+#define Clock_driver_support_at_tick() \
+ do { \
+ MCF5235_PIT_PCSR3 |= MCF5235_PIT_PCSR_PIF; \
+ } while (0) \
+
+/*
+ * Attach clock interrupt handler
+ */
+#define Clock_driver_support_install_isr( _new ) \
+ set_vector(_new, CLOCK_VECTOR, 1)
+
+/*
+ * Turn off the clock
+ */
+#define Clock_driver_support_shutdown_hardware() \
+ do { \
+ MCF5235_PIT_PCSR3 &= ~MCF5235_PIT_PCSR_EN; \
+ } while(0)
+
+/*
+ * Set up the clock hardware
+ *
+ * We need to have 1 interrupt every 10,000 microseconds
+ * so we need to set prescaler to 64 and the PMR register to 0x2DC6
+ */
+#define Clock_driver_support_initialize_hardware() \
+ do { \
+ int level; \
+ int preScaleCode = 6; \
+ MCF5235_INTC0_ICR39 = MCF5235_INTC_ICR_IL(PIT3_IRQ_LEVEL) | \
+ MCF5235_INTC_ICR_IP(PIT3_IRQ_PRIORITY); \
+ rtems_interrupt_disable( level ); \
+ MCF5235_INTC0_IMRH &= ~MCF5235_INTC0_IMRH_INT39; \
+ MCF5235_PIT_PCSR3 &= ~MCF5235_PIT_PCSR_EN; \
+ rtems_interrupt_enable( level ); \
+ MCF5235_PIT_PMR3 = 0x2DC6; \
+ MCF5235_PIT_PCSR3 = MCF5235_PIT_PCSR_PRE(preScaleCode) | \
+ MCF5235_PIT_PCSR_PIE | \
+ MCF5235_PIT_PCSR_RLD | \
+ MCF5235_PIT_PCSR_EN; \
+ } while (0)
+
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
+#include "../../../shared/dev/clock/clockimpl.h"
diff --git a/bsps/m68k/mcf5329/clock/clock.c b/bsps/m68k/mcf5329/clock/clock.c
new file mode 100644
index 0000000000..5638238921
--- /dev/null
+++ b/bsps/m68k/mcf5329/clock/clock.c
@@ -0,0 +1,105 @@
+/*
+ * Use the last periodic interval timer (PIT2) as the system clock.
+ */
+
+#include <rtems.h>
+#include <rtems/timecounter.h>
+#include <bsp.h>
+
+/*
+ * Use INTC1 base
+ */
+#define CLOCK_VECTOR (128+46)
+
+static rtems_timecounter_simple mcf5329_tc;
+
+static uint32_t mcf5329_tc_get(rtems_timecounter_simple *tc)
+{
+ return MCF_PIT3_PCNTR;
+}
+
+static bool mcf5329_tc_is_pending(rtems_timecounter_simple *tc)
+{
+ return (MCF_PIT3_PCSR & MCF_PIT_PCSR_PIF) != 0;
+}
+
+static uint32_t mcf5329_tc_get_timecount(struct timecounter *tc)
+{
+ return rtems_timecounter_simple_downcounter_get(
+ tc,
+ mcf5329_tc_get,
+ mcf5329_tc_is_pending
+ );
+}
+
+static void mcf5329_tc_at_tick(rtems_timecounter_simple *tc)
+{
+ MCF_PIT3_PCSR |= MCF_PIT_PCSR_PIF;
+}
+
+static void mcf5329_tc_tick(void)
+{
+ rtems_timecounter_simple_downcounter_tick(
+ &mcf5329_tc,
+ mcf5329_tc_get,
+ mcf5329_tc_at_tick
+ );
+}
+
+/*
+ * Attach clock interrupt handler
+ */
+#define Clock_driver_support_install_isr( _new ) \
+ set_vector(_new, CLOCK_VECTOR, 1)
+
+/*
+ * Turn off the clock
+ */
+#define Clock_driver_support_shutdown_hardware() \
+ do { \
+ MCF_PIT3_PCSR &= ~MCF_PIT_PCSR_EN; \
+ } while (0)
+
+/*
+ * Set up the clock hardware
+ *
+ * We need to have 1 interrupt every rtems_configuration_get_microseconds_per_tick()
+ */
+static void Clock_driver_support_initialize_hardware(void)
+{
+ int level;
+ uint32_t pmr;
+ uint32_t preScaleCode = 0;
+ uint32_t clk = bsp_get_BUS_clock_speed();
+ uint32_t tps = 1000000 / rtems_configuration_get_microseconds_per_tick();
+
+ while (preScaleCode < 15) {
+ pmr = (clk >> preScaleCode) / tps;
+ if (pmr < (1 << 15))
+ break;
+ preScaleCode++;
+ }
+ MCF_INTC1_ICR46 = MCF_INTC_ICR_IL(PIT3_IRQ_LEVEL);
+
+ rtems_interrupt_disable(level);
+ MCF_INTC1_IMRH &= ~MCF_INTC_IMRH_INT_MASK46;
+ MCF_PIT3_PCSR &= ~MCF_PIT_PCSR_EN;
+ rtems_interrupt_enable(level);
+
+ MCF_PIT3_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) |
+ MCF_PIT_PCSR_OVW | MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD;
+ MCF_PIT3_PMR = pmr;
+ MCF_PIT3_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) |
+ MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD | MCF_PIT_PCSR_EN;
+
+ rtems_timecounter_simple_install(
+ &mcf5329_tc,
+ clk >> preScaleCode,
+ pmr,
+ mcf5329_tc_get_timecount
+ );
+}
+
+#define Clock_driver_timecounter_tick() mcf5329_tc_tick()
+
+#include "../../../shared/dev/clock/clockimpl.h"
diff --git a/bsps/m68k/mrm332/clock/ckinit.c b/bsps/m68k/mrm332/clock/ckinit.c
new file mode 100644
index 0000000000..273ff9abed
--- /dev/null
+++ b/bsps/m68k/mrm332/clock/ckinit.c
@@ -0,0 +1,75 @@
+/*
+ * This routine initailizes the periodic interrupt timer on
+ * the Motorola 68332.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2014.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * 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 <stdlib.h>
+#include <bsp.h>
+#include <mrm332.h>
+#include <rtems/clockdrv.h>
+#include <rtems/m68k/sim.h>
+
+#define CLOCK_VECTOR MRM_PIV
+
+uint32_t Clock_isrs; /* ISRs until next tick */
+volatile uint32_t Clock_driver_ticks; /* ticks since initialization */
+static rtems_isr_entry Old_ticker;
+
+void Clock_exit( void );
+
+static rtems_isr Clock_isr(rtems_vector_number vector)
+{
+ Clock_driver_ticks += 1;
+
+ if ( Clock_isrs == 1 ) {
+ rtems_clock_tick();
+ Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
+ }
+ else
+ Clock_isrs -= 1;
+}
+
+static void Install_clock(rtems_isr_entry clock_isr)
+{
+ Clock_driver_ticks = 0;
+ Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
+
+ Old_ticker = (rtems_isr_entry) set_vector( clock_isr, CLOCK_VECTOR, 1 );
+
+ /* enable 1mS interrupts */
+ *PITR = (unsigned short int)( SAM(0x09,0,PITM) );/* load counter */
+ *PICR = (unsigned short int) /* enable interrupt */
+ ( SAM(ISRL_PIT,8,PIRQL) | SAM(CLOCK_VECTOR,0,PIV) );
+
+ atexit( Clock_exit );
+}
+
+void Clock_exit( void )
+{
+ /* shutdown the periodic interrupt */
+ *PICR = (unsigned short int)
+ ( SAM(0,8,PIRQL) | SAM(CLOCK_VECTOR,0,PIV) );
+ /* ^^ zero disables interrupt */
+
+ /* do not restore old vector */
+}
+
+rtems_device_driver Clock_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ Install_clock( Clock_isr );
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/m68k/mvme147/clock/ckinit.c b/bsps/m68k/mvme147/clock/ckinit.c
new file mode 100644
index 0000000000..ce88255593
--- /dev/null
+++ b/bsps/m68k/mvme147/clock/ckinit.c
@@ -0,0 +1,82 @@
+/*
+ * This routine initializes the Tick Timer 2 on the MVME147 board.
+ * The tick frequency is 1 millisecond.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * 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.
+ *
+ * MVME147 port for TNI - Telecom Bretagne
+ * by Dominique LE CAMPION (Dominique.LECAMPION@enst-bretagne.fr)
+ * May 1996
+ */
+
+#include <stdlib.h>
+
+#include <bsp.h>
+#include <rtems/clockdrv.h>
+
+#define MS_COUNT 65376 /* 1ms */
+/* MS_COUNT = 0x10000 - 1e-3/6.25e-6 */
+#define CLOCK_INT_LEVEL 6 /* T2's interrupt level */
+
+uint32_t Clock_isrs; /* ISRs until next tick */
+volatile uint32_t Clock_driver_ticks; /* ticks since initialization */
+rtems_isr_entry Old_ticker;
+
+void Clock_exit( void );
+
+/*
+ * ISR Handler
+ */
+static rtems_isr Clock_isr(rtems_vector_number vector)
+{
+ Clock_driver_ticks += 1;
+ pcc->timer2_int_control |= 0x80; /* Acknowledge interr. */
+
+ if (Clock_isrs == 1) {
+ rtems_clock_tick();
+ Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
+ }
+ else
+ Clock_isrs -= 1;
+}
+
+static void Install_clock(rtems_isr_entry clock_isr )
+{
+
+ Clock_driver_ticks = 0;
+ Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
+
+ Old_ticker = (rtems_isr_entry) set_vector( clock_isr, TIMER_2_VECTOR, 1 );
+
+ pcc->timer2_int_control = 0x00; /* Disable T2 Interr. */
+ pcc->timer2_preload = MS_COUNT;
+ /* write preload value */
+ pcc->timer2_control = 0x07; /* clear T2 overflow counter, enable counter */
+ pcc->timer2_int_control = CLOCK_INT_LEVEL|0x08;
+ /* Enable Timer 2 and set its int. level */
+
+ atexit( Clock_exit );
+}
+
+void Clock_exit( void )
+{
+ pcc->timer2_int_control = 0x00; /* Disable T2 Interr. */
+}
+
+rtems_device_driver Clock_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ Install_clock( Clock_isr );
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/m68k/mvme162/clock/ckinit.c b/bsps/m68k/mvme162/clock/ckinit.c
new file mode 100644
index 0000000000..f4b680e170
--- /dev/null
+++ b/bsps/m68k/mvme162/clock/ckinit.c
@@ -0,0 +1,89 @@
+/*
+ * This routine initializes the Tick Timer 2 on the MVME162 board.
+ * The tick frequency is 1 millisecond.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * 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.
+ *
+ * Modifications of respective RTEMS file: COPYRIGHT (c) 1994.
+ * EISCAT Scientific Association. M.Savitski
+ *
+ * This material is a part of the MVME162 Board Support Package
+ * for the RTEMS executive. Its licensing policies are those of the
+ * RTEMS above.
+ */
+
+#include <stdlib.h>
+
+#include <bsp.h>
+#include <rtems/clockdrv.h>
+
+#define MS_COUNT 1000 /* T2's countdown constant (1 ms) */
+#define CLOCK_INT_LEVEL 6 /* T2's interrupt level */
+
+uint32_t Clock_isrs; /* ISRs until next tick */
+volatile uint32_t Clock_driver_ticks; /* ticks since initialization */
+rtems_isr_entry Old_ticker;
+
+void Clock_exit( void );
+
+#define CLOCK_VECTOR (VBR0 * 0x10 + 0x9)
+
+/*
+ * ISR Handler
+ */
+static rtems_isr Clock_isr(rtems_vector_number vector)
+{
+ Clock_driver_ticks += 1;
+ lcsr->timer_cnt_2 = 0; /* clear counter */
+ lcsr->intr_clear |= 0x02000000;
+
+ if ( Clock_isrs == 1 ) {
+ rtems_clock_tick();
+ Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
+ }
+ else
+ Clock_isrs -= 1;
+}
+
+static void Install_clock(rtems_isr_entry clock_isr )
+{
+
+ Clock_driver_ticks = 0;
+ Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
+
+ Old_ticker = (rtems_isr_entry) set_vector( clock_isr, CLOCK_VECTOR, 1 );
+ lcsr->vector_base |= MASK_INT; /* unmask VMEchip2 interrupts */
+ lcsr->to_ctl = 0xE7; /* prescaler to 1 MHz (see Appendix A1) */
+ lcsr->timer_cmp_2 = MS_COUNT;
+ lcsr->timer_cnt_2 = 0; /* clear counter */
+ lcsr->board_ctl |= 0x700; /* increment, reset-on-compare, and */
+ /* clear-overflow-cnt */
+
+ lcsr->intr_level[0] |= CLOCK_INT_LEVEL * 0x10; /* set int level */
+ lcsr->intr_ena |= 0x02000000; /* enable tick timer 2 interrupt */
+
+ atexit( Clock_exit );
+}
+
+void Clock_exit( void )
+{
+/* Dummy for now. See other m68k BSP's for code examples */
+}
+
+rtems_device_driver Clock_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ Install_clock( Clock_isr );
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/m68k/mvme167/clock/ckinit.c b/bsps/m68k/mvme167/clock/ckinit.c
new file mode 100644
index 0000000000..8ae7234b8f
--- /dev/null
+++ b/bsps/m68k/mvme167/clock/ckinit.c
@@ -0,0 +1,159 @@
+/*
+ * Implementation of the Clock_initialize() functions
+ * prototyped in rtems/c/src/lib/include/clockdrv.h.
+ *
+ * This port does not allow the application to select which timer on the
+ * MVME167 to use for the clock, nor does it allow the application to
+ * configure the clock. The clock uses the VMEchip2 Tick Timer #2. This
+ * timer is set up to raise a MC680x0 level-6 interrupt every 1 ms. The
+ * interrupt vector is 0x69.
+ *
+ * All page references are to the MVME166/MVME167/MVME187 Single Board
+ * Computer Programmer's Reference Guide (MVME187PG/D2) with the April
+ * 1993 supplements/addenda (MVME187PG/D2A1).
+ */
+
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * 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.
+ *
+ * Modifications of respective RTEMS files:
+ * Copyright (c) 1998, National Research Council of Canada
+ */
+
+#include <stdlib.h>
+#include <bsp.h>
+#include <rtems/clockdrv.h>
+
+#define MS_COUNT 1000 /* T2's countdown constant (1 ms) */
+#define CLOCK_INT_LEVEL 6 /* T2's interrupt level */
+#define CLOCK_VECTOR (VBR0 * 0x10 + 0x9) /* T2 is vector $X9 (p. 2-71)*/
+
+/*
+ * Clock_driver_ticks is a monotonically increasing counter of the number of
+ * VMEchip2 timer #2 ticks since the driver was initialized.
+ */
+volatile uint32_t Clock_driver_ticks;
+
+/*
+ * Clock_isrs is the number of clock ISRs until the next invocation of the
+ * RTEMS clock tick routine. This clock tick device driver gets an interrupt
+ * once a millisecond and counts down until the length of time between the
+ * user configured microseconds per tick has passed. This allows the clock
+ * device to "tick" faster than the kernel clock. Of course, the kernel clock
+ * cannot tick faster than the hardware clock. Therefore, the kernel clock
+ * ticks cannot occur more frequently than every 1 millisecond.
+ */
+uint32_t Clock_isrs;
+
+/*
+ * Records the previous clock ISR (should be NULL)
+ */
+rtems_isr_entry Old_ticker;
+
+/*
+ * Called when the kernel exits.
+ */
+void clock_exit( void );
+
+/*
+ * VMEchip2_T2_isr
+ *
+ * C ISR Handler. Increment the number of internal ticks. If it is time for a
+ * kernel clock tick (if Clock_isrs == 1), call rtems_clock_tick() to signal
+ * the event and reset the Clock_isrs counter; else, just decrement it.
+ */
+static rtems_isr VMEchip2_T2_isr(
+ rtems_vector_number vector
+)
+{
+ char overflow; /* Content of overflow counter */
+ long i;
+ long ct; /* Number of T2 ticks per RTEMS ticks */
+
+ ct = rtems_configuration_get_microseconds_per_tick() / 1000;
+
+ /*
+ * May have missed interrupts, so should look at the overflow counter.
+ */
+ lcsr->intr_clear |= 0x02000000; /* Clear the interrupt */
+ overflow = (lcsr->board_ctl >> 12) & 0xF;
+ lcsr->board_ctl |= 0x400; /* Reset overflow counter */
+
+ /* Attempt to protect against one more period */
+ if ( overflow == 0 )
+ overflow = 16;
+
+ Clock_driver_ticks += overflow; /* One or more internal ticks */
+
+ if ( Clock_isrs <= overflow ) {
+ /* If its time for kernel clock ticks, signal the events to RTEMS */
+ for( i = overflow - Clock_isrs; i >= 0; i -= ct ) {
+ rtems_clock_tick();
+ }
+ /* Reset the counter */
+ Clock_isrs = (uint32_t)-i;
+ }
+ else
+ Clock_isrs -= overflow;
+}
+
+/*
+ * VMEchip2_T2_initialize
+ *
+ * Initialize the VMEchip2 Tick Timer #2.
+ *
+ * THE VMECHIP2 PRESCALER REGISTER IS ASSUMED TO BE SET!
+ * The prescaler is used by all VMEchip2 timers, including the VMEbus grant
+ * timeout counter, the DMAC time off timer, the DMAC timer on timer, and the
+ * VMEbus global timeout timer. The prescaler value is normally set by the
+ * boot ROM to provide a 1 MHz clock to the timers. For a 25 MHz MVME167, the
+ * prescaler value should be 0xE7 (page 2-63).
+ */
+static void VMEchip2_T2_initialize( void )
+{
+ Clock_driver_ticks = 0;
+ Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
+
+ lcsr->intr_ena &= 0xFDFFFFFF; /* Disable tick timer 2 interrupt */
+ lcsr->intr_clear = 0x02000000; /* Clear tick timer 2 interrupt */
+ lcsr->intr_level[0] = /* Set tick timer 2 interrupt level */
+ (lcsr->intr_level[0] & 0xFFFFFF0F ) | (CLOCK_INT_LEVEL << 4);
+ lcsr->timer_cmp_2 = MS_COUNT; /* Period in compare register */
+ lcsr->timer_cnt_2 = 0; /* Clear tick timer 2 counter */
+ Old_ticker = /* Install C ISR */
+ (rtems_isr_entry) set_vector( VMEchip2_T2_isr, CLOCK_VECTOR, 1 );
+ lcsr->board_ctl |= 0x700; /* Start tick timer 2, reset-on-compare, */
+ /* and clear tick timer 2 overflow counter */
+ lcsr->intr_ena |= 0x02000000; /* Enable tick timer 2 interrupt */
+ lcsr->vector_base |= 0x00800000;/* Unmask VMEchip2 interrupts */
+ atexit( clock_exit ); /* Turn off T2 interrupts when we exit */
+}
+
+/*
+ * This routine stops the VMEchip2 T2 timer, disables its interrupt, and
+ * re-install the old interrupt vectors.
+ */
+void clock_exit( void )
+{
+ lcsr->board_ctl &= 0xFFFFFEFF; /* Stop tick timer 2 */
+ lcsr->intr_ena &= 0xFDFFFFFF; /* Disable tick timer 2 interrupt */
+ lcsr->intr_clear = 0x02000000; /* Clear tick timer 2 interrupt */
+
+ set_vector( Old_ticker, CLOCK_VECTOR, 1 );
+}
+
+rtems_device_driver Clock_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ VMEchip2_T2_initialize();
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/m68k/uC5282/clock/clock.c b/bsps/m68k/uC5282/clock/clock.c
new file mode 100644
index 0000000000..8fffdc0457
--- /dev/null
+++ b/bsps/m68k/uC5282/clock/clock.c
@@ -0,0 +1,161 @@
+/*
+ * Use the last periodic interval timer (PIT3) as the system clock.
+ *
+ * Author: W. Eric Norum <norume@aps.anl.gov>
+ *
+ * COPYRIGHT (c) 2005.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * 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 <rtems.h>
+#include <rtems/timecounter.h>
+#include <bsp.h>
+#include <mcf5282/mcf5282.h>
+
+/*
+ * CPU load counters
+ * Place in static RAM so updates don't hit the SDRAM
+ */
+#define IDLE_COUNTER __SRAMBASE.idle_counter
+#define FILTERED_IDLE __SRAMBASE.filtered_idle
+#define MAX_IDLE_COUNT __SRAMBASE.max_idle_count
+#define PITC_PER_TICK __SRAMBASE.pitc_per_tick
+#define NSEC_PER_PITC __SRAMBASE.nsec_per_pitc
+#define FILTER_SHIFT 6
+
+/*
+ * Use INTC0 base
+ */
+#define CLOCK_VECTOR (64+58)
+
+static rtems_timecounter_simple uC5282_tc;
+
+static uint32_t uC5282_tc_get(rtems_timecounter_simple *tc)
+{
+ return MCF5282_PIT3_PCNTR;
+}
+
+static bool uC5282_tc_is_pending(rtems_timecounter_simple *tc)
+{
+ return (MCF5282_PIT3_PCSR & MCF5282_PIT_PCSR_PIF) != 0;
+}
+
+static uint32_t uC5282_tc_get_timecount(struct timecounter *tc)
+{
+ return rtems_timecounter_simple_downcounter_get(
+ tc,
+ uC5282_tc_get,
+ uC5282_tc_is_pending
+ );
+}
+
+static void uC5282_tc_at_tick(rtems_timecounter_simple *tc)
+{
+ unsigned idle = IDLE_COUNTER;
+ IDLE_COUNTER = 0;
+ if (idle > MAX_IDLE_COUNT)
+ MAX_IDLE_COUNT = idle;
+ FILTERED_IDLE = idle + FILTERED_IDLE - (FILTERED_IDLE>>FILTER_SHIFT);
+ MCF5282_PIT3_PCSR |= MCF5282_PIT_PCSR_PIF;
+}
+
+static void uC5282_tc_tick(void)
+{
+ rtems_timecounter_simple_downcounter_tick(
+ &uC5282_tc,
+ uC5282_tc_get,
+ uC5282_tc_at_tick
+ );
+}
+
+/*
+ * Attach clock interrupt handler
+ */
+#define Clock_driver_support_install_isr( _new ) \
+ set_vector(_new, CLOCK_VECTOR, 1)
+
+/*
+ * Turn off the clock
+ */
+#define Clock_driver_support_shutdown_hardware() \
+ do { \
+ MCF5282_PIT3_PCSR &= ~MCF5282_PIT_PCSR_EN; \
+ } while(0)
+
+/*
+ * Set up the clock hardware
+ *
+ * f_pit = f_clk / 2^(preScaleCode+1) / N = 1/(us_per_tick/us_per_s)
+ *
+ * N = f_clk / 2^(preScaleCode+1) * us_per_tick / us_per_s
+ *
+ * ns_per_pit_clk = ns_per_s / (f_clk / 2^(preScaleCode+1))
+ * = ns_per_s * 2^(preScaleCode+1) / f_clk;
+ */
+#define Clock_driver_support_initialize_hardware() \
+ do { \
+ unsigned long long N; \
+ int level; \
+ int preScaleCode = 0; \
+ N = bsp_get_CPU_clock_speed(); \
+ N *= rtems_configuration_get_microseconds_per_tick(); \
+ N /= 2*1000000; /* min_prescale * us_per_s */ \
+ while ( N > 0x10000 ) { \
+ preScaleCode++; \
+ N >>= 1; \
+ } \
+ PITC_PER_TICK = N; \
+ N = 2000000000ULL << preScaleCode; \
+ N /= bsp_get_CPU_clock_speed(); \
+ NSEC_PER_PITC = N; \
+ IDLE_COUNTER = 0; \
+ FILTERED_IDLE = 0; \
+ MAX_IDLE_COUNT = 0; \
+ bsp_allocate_interrupt(PIT3_IRQ_LEVEL, PIT3_IRQ_PRIORITY); \
+ MCF5282_INTC0_ICR58 = MCF5282_INTC_ICR_IL(PIT3_IRQ_LEVEL) | \
+ MCF5282_INTC_ICR_IP(PIT3_IRQ_PRIORITY); \
+ rtems_interrupt_disable( level ); \
+ MCF5282_INTC0_IMRH &= ~MCF5282_INTC_IMRH_INT58; \
+ MCF5282_PIT3_PCSR &= ~MCF5282_PIT_PCSR_EN; \
+ rtems_interrupt_enable( level ); \
+ MCF5282_PIT3_PCSR = MCF5282_PIT_PCSR_PRE(preScaleCode) | \
+ MCF5282_PIT_PCSR_OVW | \
+ MCF5282_PIT_PCSR_PIE | \
+ MCF5282_PIT_PCSR_RLD; \
+ MCF5282_PIT3_PMR = PITC_PER_TICK - 1; \
+ MCF5282_PIT3_PCSR = MCF5282_PIT_PCSR_PRE(preScaleCode) | \
+ MCF5282_PIT_PCSR_PIE | \
+ MCF5282_PIT_PCSR_RLD | \
+ MCF5282_PIT_PCSR_EN; \
+ rtems_timecounter_simple_install( \
+ &uC5282_tc, \
+ bsp_get_CPU_clock_speed() >> (preScaleCode + 1), \
+ PITC_PER_TICK, \
+ uC5282_tc_get_timecount \
+ ); \
+ } while (0)
+
+/*
+ * Provide our own version of the idle task
+ */
+void * bsp_idle_thread(uint32_t ignored)
+{
+ /* Atomic increment */
+ for(;;)
+ __asm__ volatile ("addq.l #1,%0"::"m"(IDLE_COUNTER));
+}
+
+int bsp_cpu_load_percentage(void)
+{
+ return MAX_IDLE_COUNT ?
+ (100 - ((100 * (FILTERED_IDLE >> FILTER_SHIFT)) / MAX_IDLE_COUNT)) :
+ 0;
+}
+
+#define Clock_driver_timecounter_tick() uC5282_tc_tick()
+
+#include "../../../shared/dev/clock/clockimpl.h"