bsps: Move clock drivers to bsps

This patch is a part of the BSP source reorganization.

Update #3285.
This commit is contained in:
Sebastian Huber
2018-04-19 06:35:52 +02:00
parent 5c5b021f51
commit 7632906fc2
142 changed files with 140 additions and 140 deletions

View File

@@ -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"

View File

@@ -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;
}

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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"