#ifndef _BITS_BITOPS_H #define _BITS_BITOPS_H /** @file * * RISC-V bit operations * */ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include /** * 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 */