mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-14 00:47:26 +00:00
e0f21e1cbc
'extern inline' is not portable across various C standards. To ensure compatiblity with various standards/compilers change the functions to static inline. This is a portable construct and serves as a comparable definition to 'extern inline' from the gnu90 standard. Additionally remove the function prototypes as they are not required due to the functions being declared static and functions are correctly ordered based on dependence. Signed-off-by: Nathan Rossi <nathan@nathanrossi.com> Cc: Michal Simek <monstr@monstr.eu> Cc: Tom Rini <trini@konsulko.com> Acked-by: Mans Rullgard <mans@mansr.com> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
375 lines
7.8 KiB
C
375 lines
7.8 KiB
C
#ifndef _MICROBLAZE_BITOPS_H
|
|
#define _MICROBLAZE_BITOPS_H
|
|
|
|
/*
|
|
* Copyright 1992, Linus Torvalds.
|
|
*/
|
|
|
|
#include <asm/byteorder.h> /* swab32 */
|
|
#include <asm/system.h> /* save_flags */
|
|
#include <asm-generic/bitops/fls.h>
|
|
#include <asm-generic/bitops/__fls.h>
|
|
#include <asm-generic/bitops/fls64.h>
|
|
#include <asm-generic/bitops/__ffs.h>
|
|
|
|
#ifdef __KERNEL__
|
|
/*
|
|
* The __ functions are not atomic
|
|
*/
|
|
|
|
/*
|
|
* ffz = Find First Zero in word. Undefined if no zero exists,
|
|
* so code should check against ~0UL first..
|
|
*/
|
|
static inline unsigned long ffz(unsigned long word)
|
|
{
|
|
unsigned long result = 0;
|
|
|
|
while(word & 1) {
|
|
result++;
|
|
word >>= 1;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
static inline void set_bit(int nr, volatile void *addr)
|
|
{
|
|
int * a = (int *) addr;
|
|
int mask;
|
|
unsigned long flags;
|
|
|
|
a += nr >> 5;
|
|
mask = 1 << (nr & 0x1f);
|
|
save_flags_cli(flags);
|
|
*a |= mask;
|
|
restore_flags(flags);
|
|
}
|
|
|
|
static inline void __set_bit(int nr, volatile void *addr)
|
|
{
|
|
int * a = (int *) addr;
|
|
int mask;
|
|
|
|
a += nr >> 5;
|
|
mask = 1 << (nr & 0x1f);
|
|
*a |= mask;
|
|
}
|
|
#define PLATFORM__SET_BIT
|
|
|
|
/*
|
|
* clear_bit() doesn't provide any barrier for the compiler.
|
|
*/
|
|
#define smp_mb__before_clear_bit() barrier()
|
|
#define smp_mb__after_clear_bit() barrier()
|
|
|
|
static inline void clear_bit(int nr, volatile void *addr)
|
|
{
|
|
int * a = (int *) addr;
|
|
int mask;
|
|
unsigned long flags;
|
|
|
|
a += nr >> 5;
|
|
mask = 1 << (nr & 0x1f);
|
|
save_flags_cli(flags);
|
|
*a &= ~mask;
|
|
restore_flags(flags);
|
|
}
|
|
|
|
#define __clear_bit(nr, addr) clear_bit(nr, addr)
|
|
#define PLATFORM__CLEAR_BIT
|
|
|
|
static inline void change_bit(int nr, volatile void *addr)
|
|
{
|
|
int mask;
|
|
unsigned long flags;
|
|
unsigned long *ADDR = (unsigned long *) addr;
|
|
|
|
ADDR += nr >> 5;
|
|
mask = 1 << (nr & 31);
|
|
save_flags_cli(flags);
|
|
*ADDR ^= mask;
|
|
restore_flags(flags);
|
|
}
|
|
|
|
static inline void __change_bit(int nr, volatile void *addr)
|
|
{
|
|
int mask;
|
|
unsigned long *ADDR = (unsigned long *) addr;
|
|
|
|
ADDR += nr >> 5;
|
|
mask = 1 << (nr & 31);
|
|
*ADDR ^= mask;
|
|
}
|
|
|
|
static inline int test_and_set_bit(int nr, volatile void *addr)
|
|
{
|
|
int mask, retval;
|
|
volatile unsigned int *a = (volatile unsigned int *) addr;
|
|
unsigned long flags;
|
|
|
|
a += nr >> 5;
|
|
mask = 1 << (nr & 0x1f);
|
|
save_flags_cli(flags);
|
|
retval = (mask & *a) != 0;
|
|
*a |= mask;
|
|
restore_flags(flags);
|
|
|
|
return retval;
|
|
}
|
|
|
|
static inline int __test_and_set_bit(int nr, volatile void *addr)
|
|
{
|
|
int mask, retval;
|
|
volatile unsigned int *a = (volatile unsigned int *) addr;
|
|
|
|
a += nr >> 5;
|
|
mask = 1 << (nr & 0x1f);
|
|
retval = (mask & *a) != 0;
|
|
*a |= mask;
|
|
return retval;
|
|
}
|
|
|
|
static inline int test_and_clear_bit(int nr, volatile void *addr)
|
|
{
|
|
int mask, retval;
|
|
volatile unsigned int *a = (volatile unsigned int *) addr;
|
|
unsigned long flags;
|
|
|
|
a += nr >> 5;
|
|
mask = 1 << (nr & 0x1f);
|
|
save_flags_cli(flags);
|
|
retval = (mask & *a) != 0;
|
|
*a &= ~mask;
|
|
restore_flags(flags);
|
|
|
|
return retval;
|
|
}
|
|
|
|
static inline int __test_and_clear_bit(int nr, volatile void *addr)
|
|
{
|
|
int mask, retval;
|
|
volatile unsigned int *a = (volatile unsigned int *) addr;
|
|
|
|
a += nr >> 5;
|
|
mask = 1 << (nr & 0x1f);
|
|
retval = (mask & *a) != 0;
|
|
*a &= ~mask;
|
|
return retval;
|
|
}
|
|
|
|
static inline int test_and_change_bit(int nr, volatile void *addr)
|
|
{
|
|
int mask, retval;
|
|
volatile unsigned int *a = (volatile unsigned int *) addr;
|
|
unsigned long flags;
|
|
|
|
a += nr >> 5;
|
|
mask = 1 << (nr & 0x1f);
|
|
save_flags_cli(flags);
|
|
retval = (mask & *a) != 0;
|
|
*a ^= mask;
|
|
restore_flags(flags);
|
|
|
|
return retval;
|
|
}
|
|
|
|
static inline int __test_and_change_bit(int nr, volatile void *addr)
|
|
{
|
|
int mask, retval;
|
|
volatile unsigned int *a = (volatile unsigned int *) addr;
|
|
|
|
a += nr >> 5;
|
|
mask = 1 << (nr & 0x1f);
|
|
retval = (mask & *a) != 0;
|
|
*a ^= mask;
|
|
return retval;
|
|
}
|
|
|
|
/*
|
|
* This routine doesn't need to be atomic.
|
|
*/
|
|
static inline int __constant_test_bit(int nr, const volatile void *addr)
|
|
{
|
|
return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
|
|
}
|
|
|
|
static inline int __test_bit(int nr, volatile void *addr)
|
|
{
|
|
int * a = (int *) addr;
|
|
int mask;
|
|
|
|
a += nr >> 5;
|
|
mask = 1 << (nr & 0x1f);
|
|
return ((mask & *a) != 0);
|
|
}
|
|
|
|
#define test_bit(nr,addr) \
|
|
(__builtin_constant_p(nr) ? \
|
|
__constant_test_bit((nr),(addr)) : \
|
|
__test_bit((nr),(addr)))
|
|
|
|
#define find_first_zero_bit(addr, size) \
|
|
find_next_zero_bit((addr), (size), 0)
|
|
|
|
static inline int find_next_zero_bit(void *addr, int size, int offset)
|
|
{
|
|
unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
|
|
unsigned long result = offset & ~31UL;
|
|
unsigned long tmp;
|
|
|
|
if (offset >= size)
|
|
return size;
|
|
size -= result;
|
|
offset &= 31UL;
|
|
if (offset) {
|
|
tmp = *(p++);
|
|
tmp |= ~0UL >> (32-offset);
|
|
if (size < 32)
|
|
goto found_first;
|
|
if (~tmp)
|
|
goto found_middle;
|
|
size -= 32;
|
|
result += 32;
|
|
}
|
|
while (size & ~31UL) {
|
|
if (~(tmp = *(p++)))
|
|
goto found_middle;
|
|
result += 32;
|
|
size -= 32;
|
|
}
|
|
if (!size)
|
|
return result;
|
|
tmp = *p;
|
|
|
|
found_first:
|
|
tmp |= ~0UL >> size;
|
|
found_middle:
|
|
return result + ffz(tmp);
|
|
}
|
|
|
|
/*
|
|
* hweightN: returns the hamming weight (i.e. the number
|
|
* of bits set) of a N-bit word
|
|
*/
|
|
|
|
#define hweight32(x) generic_hweight32(x)
|
|
#define hweight16(x) generic_hweight16(x)
|
|
#define hweight8(x) generic_hweight8(x)
|
|
|
|
|
|
static inline int ext2_set_bit(int nr, volatile void *addr)
|
|
{
|
|
int mask, retval;
|
|
unsigned long flags;
|
|
volatile unsigned char *ADDR = (unsigned char *) addr;
|
|
|
|
ADDR += nr >> 3;
|
|
mask = 1 << (nr & 0x07);
|
|
save_flags_cli(flags);
|
|
retval = (mask & *ADDR) != 0;
|
|
*ADDR |= mask;
|
|
restore_flags(flags);
|
|
return retval;
|
|
}
|
|
|
|
static inline int ext2_clear_bit(int nr, volatile void *addr)
|
|
{
|
|
int mask, retval;
|
|
unsigned long flags;
|
|
volatile unsigned char *ADDR = (unsigned char *) addr;
|
|
|
|
ADDR += nr >> 3;
|
|
mask = 1 << (nr & 0x07);
|
|
save_flags_cli(flags);
|
|
retval = (mask & *ADDR) != 0;
|
|
*ADDR &= ~mask;
|
|
restore_flags(flags);
|
|
return retval;
|
|
}
|
|
|
|
static inline int ext2_test_bit(int nr, const volatile void *addr)
|
|
{
|
|
int mask;
|
|
const volatile unsigned char *ADDR = (const unsigned char *) addr;
|
|
|
|
ADDR += nr >> 3;
|
|
mask = 1 << (nr & 0x07);
|
|
return ((mask & *ADDR) != 0);
|
|
}
|
|
|
|
#define ext2_find_first_zero_bit(addr, size) \
|
|
ext2_find_next_zero_bit((addr), (size), 0)
|
|
|
|
static inline unsigned long ext2_find_next_zero_bit(void *addr,
|
|
unsigned long size, unsigned long offset)
|
|
{
|
|
unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
|
|
unsigned long result = offset & ~31UL;
|
|
unsigned long tmp;
|
|
|
|
if (offset >= size)
|
|
return size;
|
|
size -= result;
|
|
offset &= 31UL;
|
|
if(offset) {
|
|
/* We hold the little endian value in tmp, but then the
|
|
* shift is illegal. So we could keep a big endian value
|
|
* in tmp, like this:
|
|
*
|
|
* tmp = __swab32(*(p++));
|
|
* tmp |= ~0UL >> (32-offset);
|
|
*
|
|
* but this would decrease preformance, so we change the
|
|
* shift:
|
|
*/
|
|
tmp = *(p++);
|
|
tmp |= __swab32(~0UL >> (32-offset));
|
|
if(size < 32)
|
|
goto found_first;
|
|
if(~tmp)
|
|
goto found_middle;
|
|
size -= 32;
|
|
result += 32;
|
|
}
|
|
while(size & ~31UL) {
|
|
if(~(tmp = *(p++)))
|
|
goto found_middle;
|
|
result += 32;
|
|
size -= 32;
|
|
}
|
|
if(!size)
|
|
return result;
|
|
tmp = *p;
|
|
|
|
found_first:
|
|
/* tmp is little endian, so we would have to swab the shift,
|
|
* see above. But then we have to swab tmp below for ffz, so
|
|
* we might as well do this here.
|
|
*/
|
|
return result + ffz(__swab32(tmp) | (~0UL << size));
|
|
found_middle:
|
|
return result + ffz(__swab32(tmp));
|
|
}
|
|
|
|
/* Bitmap functions for the minix filesystem. */
|
|
#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
|
|
#define minix_set_bit(nr,addr) set_bit(nr,addr)
|
|
#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
|
|
#define minix_test_bit(nr,addr) test_bit(nr,addr)
|
|
#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
|
|
|
|
/**
|
|
* hweightN - returns the hamming weight of a N-bit word
|
|
* @x: the word to weigh
|
|
*
|
|
* The Hamming Weight of a number is the total number of bits set in it.
|
|
*/
|
|
|
|
#define hweight32(x) generic_hweight32(x)
|
|
#define hweight16(x) generic_hweight16(x)
|
|
#define hweight8(x) generic_hweight8(x)
|
|
|
|
#endif /* __KERNEL__ */
|
|
|
|
#endif /* _MICROBLAZE_BITOPS_H */
|