| #ifndef _BITS_BITOPS_H | |
| #define _BITS_BITOPS_H | |
| /** @file | |
| * | |
| * RISC-V bit operations | |
| * | |
| */ | |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); | |
| #include <stdint.h> | |
| /** | |
| * Test and set bit atomically | |
| * | |
| * @v bit Bit to set | |
| * @v bits Bit field | |
| * @ret old Old value of bit (zero or non-zero) | |
| */ | |
| static inline __attribute__ (( always_inline )) int | |
| test_and_set_bit ( unsigned int bit, volatile void *bits ) { | |
| unsigned int index = ( bit / 32 ); | |
| unsigned int offset = ( bit % 32 ); | |
| volatile uint32_t *word = ( ( ( volatile uint32_t * ) bits ) + index ); | |
| uint32_t mask = ( 1U << offset ); | |
| uint32_t old; | |
| __asm__ __volatile__ ( "amoor.w %0, %2, %1" | |
| : "=r" ( old ), "+A" ( *word ) | |
| : "r" ( mask ) ); | |
| return ( !! ( old & mask ) ); | |
| } | |
| /** | |
| * Test and clear bit atomically | |
| * | |
| * @v bit Bit to set | |
| * @v bits Bit field | |
| * @ret old Old value of bit (zero or non-zero) | |
| */ | |
| static inline __attribute__ (( always_inline )) int | |
| test_and_clear_bit ( unsigned int bit, volatile void *bits ) { | |
| unsigned int index = ( bit / 32 ); | |
| unsigned int offset = ( bit % 32 ); | |
| volatile uint32_t *word = ( ( ( volatile uint32_t * ) bits ) + index ); | |
| uint32_t mask = ( 1U << offset ); | |
| uint32_t old; | |
| __asm__ __volatile__ ( "amoand.w %0, %2, %1" | |
| : "=r" ( old ), "+A" ( *word ) | |
| : "r" ( ~mask ) ); | |
| return ( !! ( old & mask ) ); | |
| } | |
| /** | |
| * Set bit atomically | |
| * | |
| * @v bit Bit to set | |
| * @v bits Bit field | |
| */ | |
| static inline __attribute__ (( always_inline )) void | |
| set_bit ( unsigned int bit, volatile void *bits ) { | |
| test_and_set_bit ( bit, bits ); | |
| } | |
| /** | |
| * Clear bit atomically | |
| * | |
| * @v bit Bit to set | |
| * @v bits Bit field | |
| */ | |
| static inline __attribute__ (( always_inline )) void | |
| clear_bit ( unsigned int bit, volatile void *bits ) { | |
| test_and_clear_bit ( bit, bits ); | |
| } | |
| #endif /* _BITS_BITOPS_H */ |