diff options
Diffstat (limited to 'c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c')
-rw-r--r-- | c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c b/c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c new file mode 100644 index 0000000000..ddb175d30a --- /dev/null +++ b/c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c @@ -0,0 +1,274 @@ +/** + * @file + * + * @brief Source file for timer functions. + */ + +/* + * Copyright (c) 2008 + * Embedded Brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * rtems@embedded-brains.de + * + * The license and distribution terms for this file may be found in the file + * LICENSE in this distribution or at http://www.rtems.com/license/LICENSE. + */ + +#include <rtems/bspIo.h> + +#include <mpc83xx/mpc83xx.h> +#include <mpc83xx/gtm.h> + +#define RTEMS_STATUS_CHECKS_USE_PRINTK + +#include <rtems/status-checks.h> + +#define MPC83XX_GTM_CHECK_INDEX( timer) \ + if (( timer) < 0 || ( timer) >= MPC83XX_GTM_NUMBER) { \ + return RTEMS_INVALID_NUMBER; \ + } + +#define MPC83XX_GTM_VARIABLES( timer) \ + int module = (timer) / 4; \ + int module_timer = (timer) % 4; \ + int high = module_timer / 2; \ + int low = module_timer % 2; \ + rtems_interrupt_level level; + +#define MPC83XX_GTM_CLOCK_MASK MPC83XX_GTM_CLOCK_EXTERN + +static const uint8_t mpc83xx_gmt_interrupt_vector_table [MPC83XX_GTM_NUMBER] = { 90, 78, 84, 72, 91, 79, 85, 73 }; + +static const uint8_t mpc83xx_gmt_interrupt_priority_table [MPC83XX_GTM_NUMBER] = { 113, 77, 95, 59, 116, 80, 98, 62 }; + +rtems_status_code mpc83xx_gtm_initialize( int timer, int clock) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + MPC83XX_GTM_VARIABLES( timer); + + uint8_t mask = 0xf << (low * 4); + uint8_t flags = 0x3 << (low * 4); + uint16_t reg = 0; + + MPC83XX_GTM_CHECK_INDEX( timer); + + rtems_interrupt_disable( level); + + reg = mpc83xx.gtm [module].gtcfr [high].reg; + mpc83xx.gtm [module].gtcfr [high].reg = (reg & ~mask) | flags; + + mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] = 0; + + rtems_interrupt_enable( level); + + sc = mpc83xx_gtm_set_clock( timer, clock); + CHECK_SC( sc, "Set clock"); + + sc = mpc83xx_gtm_set_value( timer, 0); + CHECK_SC( sc, "Set value"); + + sc = mpc83xx_gtm_set_reference( timer, 0); + CHECK_SC( sc, "Set reference"); + + sc = mpc83xx_gtm_set_prescale( timer, 0); + CHECK_SC( sc, "Set prescale"); + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_enable_restart( int timer, bool enable) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + rtems_interrupt_disable( level); + + if (enable) { + mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] |= 0x0008; + } else { + mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] &= ~0x0008; + } + + rtems_interrupt_enable( level); + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_set_clock( int timer, int clock) +{ + MPC83XX_GTM_VARIABLES( timer); + + uint16_t reg = 0; + + MPC83XX_GTM_CHECK_INDEX( timer); + + if (clock & ~MPC83XX_GTM_CLOCK_MASK) { + return RTEMS_INVALID_CLOCK; + } + + rtems_interrupt_disable( level); + + reg = mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low]; + mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] = (reg & ~MPC83XX_GTM_CLOCK_MASK) | clock; + + rtems_interrupt_enable( level); + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_get_clock( int timer, int *clock) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + *clock = mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] & MPC83XX_GTM_CLOCK_MASK; + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_start( int timer) +{ + MPC83XX_GTM_VARIABLES( timer); + + uint8_t flags = 0x2 << (low * 4); + + MPC83XX_GTM_CHECK_INDEX( timer); + + rtems_interrupt_disable( level); + mpc83xx.gtm [module].gtcfr [high].reg &= ~flags; + rtems_interrupt_enable( level); + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_stop( int timer) +{ + MPC83XX_GTM_VARIABLES( timer); + + uint8_t flags = 0x2 << (low * 4); + + MPC83XX_GTM_CHECK_INDEX( timer); + + rtems_interrupt_disable( level); + mpc83xx.gtm [module].gtcfr [high].reg |= flags; + rtems_interrupt_enable( level); + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_set_value( int timer, uint16_t value) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + mpc83xx.gtm [module].gt_tim_regs [high].gtcnr [low] = value; + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_get_value( int timer, uint16_t *value) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + *value = mpc83xx.gtm [module].gt_tim_regs [high].gtcnr [low]; + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_set_reference( int timer, uint16_t reference) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + mpc83xx.gtm [module].gt_tim_regs [high].gtrfr [low] = reference; + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_get_reference( int timer, uint16_t *reference) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + reference = mpc83xx.gtm [module].gt_tim_regs [high].gtrfr [low]; + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_set_prescale( int timer, uint8_t prescale) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + mpc83xx.gtm [module].gtpsr [module_timer] = prescale; + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_get_prescale( int timer, uint8_t *prescale) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + prescale = mpc83xx.gtm [module].gtpsr [module_timer]; + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_interrupt_get_vector( int timer, rtems_vector_number *vector) +{ + MPC83XX_GTM_CHECK_INDEX( timer); + + *vector = mpc83xx_gmt_interrupt_vector_table [timer]; + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_interrupt_enable( int timer) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + rtems_interrupt_disable( level); + mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] |= 0x0010; + rtems_interrupt_enable( level); + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_interrupt_disable( int timer) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + rtems_interrupt_disable( level); + mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] &= ~0x0010; + rtems_interrupt_enable( level); + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_interrupt_clear( int timer) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + mpc83xx.gtm [module].gtevr [module_timer] = 0x0002; + + return RTEMS_SUCCESSFUL; +} |