diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-19 06:35:52 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-20 09:57:01 +0200 |
commit | 7632906fc290b652416ab59eb5fb49356c064ed6 (patch) | |
tree | ac036b1f95637e044e10138ceea8d2b56d80ec97 /bsps/m68k | |
parent | bsps: Move bspsmpgetcurrentprocessor.c to bsps (diff) | |
download | rtems-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.c | 61 | ||||
-rw-r--r-- | bsps/m68k/gen68340/clock/ckinit.c | 104 | ||||
-rw-r--r-- | bsps/m68k/gen68360/clock/clock.c | 101 | ||||
-rw-r--r-- | bsps/m68k/genmcf548x/clock/clock.c | 102 | ||||
-rw-r--r-- | bsps/m68k/mcf52235/clock/clock.c | 106 | ||||
-rw-r--r-- | bsps/m68k/mcf5225x/clock/clock.c | 106 | ||||
-rw-r--r-- | bsps/m68k/mcf5235/clock/clock.c | 61 | ||||
-rw-r--r-- | bsps/m68k/mcf5329/clock/clock.c | 105 | ||||
-rw-r--r-- | bsps/m68k/mrm332/clock/ckinit.c | 75 | ||||
-rw-r--r-- | bsps/m68k/mvme147/clock/ckinit.c | 82 | ||||
-rw-r--r-- | bsps/m68k/mvme162/clock/ckinit.c | 89 | ||||
-rw-r--r-- | bsps/m68k/mvme167/clock/ckinit.c | 159 | ||||
-rw-r--r-- | bsps/m68k/uC5282/clock/clock.c | 161 |
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" |