From d3c321367c659f195f1bf03efc2ce5487e1848de Mon Sep 17 00:00:00 2001 From: Thomas Doerfler Date: Fri, 18 Jul 2008 15:56:48 +0000 Subject: Changed special purpose register inline functions to macros. fixed some minors in mpc83xx support added file for mpc55xx watchdog support --- c/src/lib/libcpu/powerpc/ChangeLog | 15 + c/src/lib/libcpu/powerpc/Makefile.am | 4 +- .../lib/libcpu/powerpc/mpc55xx/include/watchdog.h | 59 ++++ c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c | 4 +- .../libcpu/powerpc/new-exceptions/raw_exception.c | 2 +- c/src/lib/libcpu/powerpc/preinstall.am | 4 + .../powerpc/shared/include/powerpc-utility.h | 344 ++++++++++----------- 7 files changed, 251 insertions(+), 181 deletions(-) create mode 100644 c/src/lib/libcpu/powerpc/mpc55xx/include/watchdog.h (limited to 'c/src/lib/libcpu') diff --git a/c/src/lib/libcpu/powerpc/ChangeLog b/c/src/lib/libcpu/powerpc/ChangeLog index 5033d9087f..f9dc8605d2 100644 --- a/c/src/lib/libcpu/powerpc/ChangeLog +++ b/c/src/lib/libcpu/powerpc/ChangeLog @@ -1,3 +1,18 @@ +2008-07-18 Sebastian Huber + + * shared/include/powerpc-utility.h: Changed special purpose register + inline functions to macros. Added macros to set and clear bits for + SPRs and DCRs. + + * new-exceptions/raw_exception.c: The watchdog exception for e200 is + now asynchronous. + + * mpc83xx/gtm/gtm.c: Bugfix for some value assignments. + + * mpc55xx/include/watchdog.h: New file. + + * Makefile.am: Install mpc55xx/include/watchdog.h for MPC55XX. + 2008-07-18 Thomas Doerfler * mpc83xx/network/tsec.c: Initialize PHY registers late enough, diff --git a/c/src/lib/libcpu/powerpc/Makefile.am b/c/src/lib/libcpu/powerpc/Makefile.am index d0e719aff4..45c1d2b9a0 100644 --- a/c/src/lib/libcpu/powerpc/Makefile.am +++ b/c/src/lib/libcpu/powerpc/Makefile.am @@ -429,8 +429,8 @@ include_mpc55xx_HEADERS = mpc55xx/include/regs.h \ mpc55xx/include/dspi.h \ mpc55xx/include/edma.h \ mpc55xx/include/mpc55xx.h \ - mpc55xx/include/esci.h - + mpc55xx/include/esci.h \ + mpc55xx/include/watchdog.h # IRQ noinst_PROGRAMS += mpc55xx/irq.rel diff --git a/c/src/lib/libcpu/powerpc/mpc55xx/include/watchdog.h b/c/src/lib/libcpu/powerpc/mpc55xx/include/watchdog.h new file mode 100644 index 0000000000..2c00621076 --- /dev/null +++ b/c/src/lib/libcpu/powerpc/mpc55xx/include/watchdog.h @@ -0,0 +1,59 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief Header file for the watchdog timer. + */ + +/* + * 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. + */ + +#ifndef LIBCPU_POWERPC_MPC55XX_WATCHDOG_H +#define LIBCPU_POWERPC_MPC55XX_WATCHDOG_H + +#include + +#include + +#include + +static inline void mpc55xx_watchdog_clear() +{ + PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_TSR, BOOKE_TSR_WIS); +} + +static inline void mpc55xx_watchdog_enable_interrupt( bool enable) +{ + if (enable) { + PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( BOOKE_TCR, BOOKE_TCR_WIE); + } else { + PPC_CLEAR_SPECIAL_PURPOSE_REGISTER_BITS( BOOKE_TCR, BOOKE_TCR_WIE); + } +} + +static inline rtems_status_code mpc55xx_watchdog_set_time_base_bit( uint32_t bit) +{ + if (bit > 63) { + return RTEMS_INVALID_NUMBER; + } + + PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS_MASKED( + BOOKE_TCR, + BOOKE_TCR_WP( bit) | BOOKE_TCR_WPEXT( bit >> 2), + BOOKE_TCR_WP_MASK | BOOKE_TCR_WPEXT_MASK + ); + + return RTEMS_SUCCESSFUL; +} + +#endif /* LIBCPU_POWERPC_MPC55XX_WATCHDOG_H */ diff --git a/c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c b/c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c index ddb175d30a..3974c56941 100644 --- a/c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c +++ b/c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c @@ -200,7 +200,7 @@ rtems_status_code mpc83xx_gtm_get_reference( int timer, uint16_t *reference) MPC83XX_GTM_CHECK_INDEX( timer); - reference = mpc83xx.gtm [module].gt_tim_regs [high].gtrfr [low]; + *reference = mpc83xx.gtm [module].gt_tim_regs [high].gtrfr [low]; return RTEMS_SUCCESSFUL; } @@ -222,7 +222,7 @@ rtems_status_code mpc83xx_gtm_get_prescale( int timer, uint8_t *prescale) MPC83XX_GTM_CHECK_INDEX( timer); - prescale = mpc83xx.gtm [module].gtpsr [module_timer]; + *prescale = mpc83xx.gtm [module].gtpsr [module_timer]; return RTEMS_SUCCESSFUL; } diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/raw_exception.c b/c/src/lib/libcpu/powerpc/new-exceptions/raw_exception.c index 06ed62423d..795661fa7c 100644 --- a/c/src/lib/libcpu/powerpc/new-exceptions/raw_exception.c +++ b/c/src/lib/libcpu/powerpc/new-exceptions/raw_exception.c @@ -266,7 +266,7 @@ static const cat_ini_t e200_vector_categories [LAST_VALID_EXC + 1] = { [ASM_SYS_VECTOR] = PPC_EXC_CLASSIC, [ASM_BOOKE_DEC_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC, [ASM_BOOKE_FIT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC, - [ASM_BOOKE_WDOG_VECTOR] = PPC_EXC_BOOKE_CRITICAL, + [ASM_BOOKE_WDOG_VECTOR] = PPC_EXC_BOOKE_CRITICAL | PPC_EXC_ASYNC, [ASM_BOOKE_ITLBMISS_VECTOR] = PPC_EXC_CLASSIC, [ASM_BOOKE_DTLBMISS_VECTOR] = PPC_EXC_CLASSIC, diff --git a/c/src/lib/libcpu/powerpc/preinstall.am b/c/src/lib/libcpu/powerpc/preinstall.am index b9973945b9..e6b86878b5 100644 --- a/c/src/lib/libcpu/powerpc/preinstall.am +++ b/c/src/lib/libcpu/powerpc/preinstall.am @@ -294,4 +294,8 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc55xx/mpc55xx.h $(PROJECT_INCLUDE)/mpc55xx/esci.h: mpc55xx/include/esci.h $(PROJECT_INCLUDE)/mpc55xx/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/mpc55xx/esci.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc55xx/esci.h + +$(PROJECT_INCLUDE)/mpc55xx/watchdog.h: mpc55xx/include/watchdog.h $(PROJECT_INCLUDE)/mpc55xx/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/mpc55xx/watchdog.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc55xx/watchdog.h endif diff --git a/c/src/lib/libcpu/powerpc/shared/include/powerpc-utility.h b/c/src/lib/libcpu/powerpc/shared/include/powerpc-utility.h index f138884086..bfbf919e2c 100644 --- a/c/src/lib/libcpu/powerpc/shared/include/powerpc-utility.h +++ b/c/src/lib/libcpu/powerpc/shared/include/powerpc-utility.h @@ -239,184 +239,176 @@ static inline void ppc_set_decrementer_register( uint32_t dec) PPC_Set_decrementer( dec); } -#define PPC_STRINGOF(x) #x - -/* Do not use the following macros. Use the inline functions instead. */ - -#define PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER( spr) \ - uint32_t val; \ - asm volatile ( \ - "mfspr %0, " #spr \ - : "=r" (val) \ - ); \ - return val; - -#define PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER_EXPAND( spr) \ - PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER( spr) - -#define PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER( spr, val) \ - asm volatile ( \ - "mtspr " #spr ", %0" \ - : \ - : "r" (val) \ - ); - -#define PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER_EXPAND( spr, val) \ - PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER( spr, val) - -/* - * PPC4xx have Device Control Registers... +/** + * @brief Preprocessor magic for stringification of @a x. */ -#define PPC_DEVICE_CONTROL_REGISTER(dcr) \ - ({uint32_t val;asm volatile ("mfdcr %0," PPC_STRINGOF(dcr) \ - : "=r" (val)); val;}) - -#define PPC_SET_DEVICE_CONTROL_REGISTER(dcr,val) \ - do { \ - asm volatile ("mtdcr " PPC_STRINGOF(dcr)",%0" \ - :: "r" (val)); \ - } while (0) - - -static inline uint32_t ppc_special_purpose_register_0() -{ - PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER_EXPAND( SPRG0); -} - -static inline void ppc_set_special_purpose_register_0( uint32_t val) -{ - PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER_EXPAND( SPRG0, val); -} - -static inline uint32_t ppc_special_purpose_register_1() -{ - PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER_EXPAND( SPRG1); -} - -static inline void ppc_set_special_purpose_register_1( uint32_t val) -{ - PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER_EXPAND( SPRG1, val); -} - -static inline uint32_t ppc_special_purpose_register_2() -{ - PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER_EXPAND( SPRG2); -} - -static inline void ppc_set_special_purpose_register_2( uint32_t val) -{ - PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER_EXPAND( SPRG2, val); -} - -static inline uint32_t ppc_special_purpose_register_3() -{ - PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER_EXPAND( SPRG3); -} - -static inline void ppc_set_special_purpose_register_3( uint32_t val) -{ - PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER_EXPAND( SPRG3, val); -} - -static inline uint32_t ppc_special_purpose_register_4() -{ - PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER_EXPAND( SPRG4); -} - -static inline void ppc_set_special_purpose_register_4( uint32_t val) -{ - PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER_EXPAND( SPRG4, val); -} - -static inline uint32_t ppc_special_purpose_register_5() -{ - PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER_EXPAND( SPRG5); -} - -static inline void ppc_set_special_purpose_register_5( uint32_t val) -{ - PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER_EXPAND( SPRG5, val); -} - -static inline uint32_t ppc_special_purpose_register_6() -{ - PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER_EXPAND( SPRG6); -} - -static inline void ppc_set_special_purpose_register_6( uint32_t val) -{ - PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER_EXPAND( SPRG6, val); -} - -static inline uint32_t ppc_special_purpose_register_7() -{ - PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER_EXPAND( SPRG7); -} - -static inline void ppc_set_special_purpose_register_7( uint32_t val) -{ - PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER_EXPAND( SPRG7, val); -} - -static inline uint32_t ppc_user_special_purpose_register_0() -{ - PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER_EXPAND( USPRG0); -} - -static inline void ppc_set_user_special_purpose_register_0( uint32_t val) -{ - PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER_EXPAND( USPRG0, val); -} +#define PPC_STRINGOF( x) #x -static inline uint32_t ppc_timer_control_register() -{ - PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER_EXPAND( BOOKE_TCR); -} +/** + * @brief Returns the value of the Special Purpose Register with number @a spr. + * + * @note This macro uses a GNU C extension. + */ +#define PPC_SPECIAL_PURPOSE_REGISTER( spr) \ + ( { \ + uint32_t val; \ + asm volatile ( \ + "mfspr %0, " PPC_STRINGOF( spr) \ + : "=r" (val) \ + ); \ + val;\ + } ) -static inline void ppc_set_timer_control_register( uint32_t val) -{ - PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER_EXPAND( BOOKE_TCR, val); -} +/** + * @brief Sets the Special Purpose Register with number @a spr to the value in + * @a val. + */ +#define PPC_SET_SPECIAL_PURPOSE_REGISTER( spr, val) \ + do { \ + asm volatile ( \ + "mtspr " PPC_STRINGOF( spr) ", %0" \ + : \ + : "r" (val) \ + ); \ + } while (0) -static inline uint32_t ppc_timer_status_register() -{ - PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER_EXPAND( BOOKE_TSR); -} +/** + * @brief Sets in the Special Purpose Register with number @a spr all bits + * which are set in @a bits. + * + * Interrupts are disabled throughout this operation. + */ +#define PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( spr, bits) \ + do { \ + rtems_interrupt_level level; \ + uint32_t val; \ + rtems_interrupt_disable( level); \ + val = PPC_SPECIAL_PURPOSE_REGISTER( spr); \ + val |= bits; \ + PPC_SET_SPECIAL_PURPOSE_REGISTER( spr, val); \ + rtems_interrupt_enable( level); \ + } while (0) -static inline void ppc_set_timer_status_register( uint32_t val) -{ - PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER_EXPAND( BOOKE_TSR, val); -} +/** + * @brief Sets in the Special Purpose Register with number @a spr all bits + * which are set in @a bits. The previous register value will be masked with + * @a mask. + * + * Interrupts are disabled throughout this operation. + */ +#define PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS_MASKED( spr, bits, mask) \ + do { \ + rtems_interrupt_level level; \ + uint32_t val; \ + rtems_interrupt_disable( level); \ + val = PPC_SPECIAL_PURPOSE_REGISTER( spr); \ + val &= ~mask; \ + val |= bits; \ + PPC_SET_SPECIAL_PURPOSE_REGISTER( spr, val); \ + rtems_interrupt_enable( level); \ + } while (0) -static inline uint32_t ppc_decrementer_auto_reload_register() -{ - PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER_EXPAND( BOOKE_DECAR); -} +/** + * @brief Clears in the Special Purpose Register with number @a spr all bits + * which are set in @a bits. + * + * Interrupts are disabled throughout this operation. + */ +#define PPC_CLEAR_SPECIAL_PURPOSE_REGISTER_BITS( spr, bits) \ + do { \ + rtems_interrupt_level level; \ + uint32_t val; \ + rtems_interrupt_disable( level); \ + val = PPC_SPECIAL_PURPOSE_REGISTER( spr); \ + val &= ~bits; \ + PPC_SET_SPECIAL_PURPOSE_REGISTER( spr, val); \ + rtems_interrupt_enable( level); \ + } while (0) -static inline void ppc_set_decrementer_auto_reload_register( uint32_t val) -{ - PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER_EXPAND( BOOKE_DECAR, val); -} +/** + * @brief Returns the value of the Device Control Register with number @a dcr. + * + * The PowerPC 4XX family has Device Control Registers. + * + * @note This macro uses a GNU C extension. + */ +#define PPC_DEVICE_CONTROL_REGISTER( dcr) \ + ( { \ + uint32_t val; \ + asm volatile ( \ + "mfdcr %0, " PPC_STRINGOF( dcr) \ + : "=r" (val) \ + ); \ + val;\ + } ) -static inline uint32_t ppc_hardware_implementation_dependent_register_0() -{ - PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER_EXPAND( HID0); -} +/** + * @brief Sets the Device Control Register with number @a dcr to the value in + * @a val. + * + * The PowerPC 4XX family has Device Control Registers. + */ +#define PPC_SET_DEVICE_CONTROL_REGISTER( dcr, val) \ + do { \ + asm volatile ( \ + "mtdcr " PPC_STRINGOF( dcr) ", %0" \ + : \ + : "r" (val) \ + ); \ + } while (0) -static inline void ppc_set_hardware_implementation_dependent_register_0( uint32_t val) -{ - PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER_EXPAND( HID0, val); -} +/** + * @brief Sets in the Device Control Register with number @a dcr all bits + * which are set in @a bits. + * + * Interrupts are disabled throughout this operation. + */ +#define PPC_SET_DEVICE_CONTROL_REGISTER_BITS( dcr, bits) \ + do { \ + rtems_interrupt_level level; \ + uint32_t val; \ + rtems_interrupt_disable( level); \ + val = PPC_DEVICE_CONTROL_REGISTER( dcr); \ + val |= bits; \ + PPC_SET_DEVICE_CONTROL_REGISTER( dcr, val); \ + rtems_interrupt_enable( level); \ + } while (0) -static inline uint32_t ppc_hardware_implementation_dependent_register_1() -{ - PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER_EXPAND( HID1); -} +/** + * @brief Sets in the Device Control Register with number @a dcr all bits + * which are set in @a bits. The previous register value will be masked with + * @a mask. + * + * Interrupts are disabled throughout this operation. + */ +#define PPC_SET_DEVICE_CONTROL_REGISTER_BITS_MASKED( dcr, bits, mask) \ + do { \ + rtems_interrupt_level level; \ + uint32_t val; \ + rtems_interrupt_disable( level); \ + val = PPC_DEVICE_CONTROL_REGISTER( dcr); \ + val &= ~mask; \ + val |= bits; \ + PPC_SET_DEVICE_CONTROL_REGISTER( dcr, val); \ + rtems_interrupt_enable( level); \ + } while (0) -static inline void ppc_set_hardware_implementation_dependent_register_1( uint32_t val) -{ - PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER_EXPAND( HID1, val); -} +/** + * @brief Clears in the Device Control Register with number @a dcr all bits + * which are set in @a bits. + * + * Interrupts are disabled throughout this operation. + */ +#define PPC_CLEAR_DEVICE_CONTROL_REGISTER_BITS( dcr, bits) \ + do { \ + rtems_interrupt_level level; \ + uint32_t val; \ + rtems_interrupt_disable( level); \ + val = PPC_DEVICE_CONTROL_REGISTER( dcr); \ + val &= ~bits; \ + PPC_SET_DEVICE_CONTROL_REGISTER( dcr, val); \ + rtems_interrupt_enable( level); \ + } while (0) static inline uint32_t ppc_time_base() { @@ -429,17 +421,17 @@ static inline uint32_t ppc_time_base() static inline void ppc_set_time_base( uint32_t val) { - PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER_EXPAND( TBWL, val); + PPC_SET_SPECIAL_PURPOSE_REGISTER( TBWL, val); } static inline uint32_t ppc_time_base_upper() { - PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER_EXPAND( TBRU); + return PPC_SPECIAL_PURPOSE_REGISTER( TBRU); } static inline void ppc_set_time_base_upper( uint32_t val) { - PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER_EXPAND( TBWU, val); + PPC_SET_SPECIAL_PURPOSE_REGISTER( TBWU, val); } static inline uint64_t ppc_time_base_64() @@ -457,18 +449,18 @@ static inline void ppc_set_time_base_64( uint64_t val) #include .macro LA reg, addr - lis \reg, (\addr)@h - ori \reg, \reg, (\addr)@l + lis \reg, (\addr)@h + ori \reg, \reg, (\addr)@l .endm .macro LWI reg, value lis \reg, (\value)@h - ori \reg, \reg, (\value)@l + ori \reg, \reg, (\value)@l .endm .macro LW reg, addr - lis \reg, \addr@ha - lwz \reg, \addr@l(\reg) + lis \reg, \addr@ha + lwz \reg, \addr@l(\reg) .endm /* @@ -502,7 +494,7 @@ static inline void ppc_set_time_base_64( uint64_t val) * Obtain interrupt mask */ .macro GET_INTERRUPT_MASK mask - mfspr \mask, sprg0 + mfspr \mask, sprg0 .endm /* -- cgit v1.2.3