273 lines
6.4 KiB
C
273 lines
6.4 KiB
C
/*
|
|
* =====================================================================================
|
|
*
|
|
* Filename: support.h
|
|
*
|
|
* Description: misc utilities definition.
|
|
*
|
|
* Version: 2.0
|
|
* Create: 2017-11-03 11:34:34
|
|
* Revision: none
|
|
* Compiler: gcc version 6.3.0 (crosstool-NG crosstool-ng-1.23.0)
|
|
*
|
|
* Author: caozilong@allwinnertech.com
|
|
* Organization: BU1-PSW
|
|
* Last Modified: 2020-03-25 12:20:13
|
|
*
|
|
* =====================================================================================
|
|
*/
|
|
|
|
#ifndef __SUPPORT_H__
|
|
#define __SUPPORT_H__
|
|
#include <typedef.h>
|
|
#include <kapi.h>
|
|
#include <libc.h>
|
|
|
|
/*
|
|
* Generic macro to convert pointers to values for comparison purposes.
|
|
*/
|
|
#ifndef p2n
|
|
#define p2n(p) ((ptrdiff_t)((ptrdiff_t*)(p)))
|
|
#endif
|
|
|
|
/*
|
|
* min()/max() macros that also do
|
|
* strict type-checking.. See the
|
|
* "unnecessary" pointer comparison.
|
|
*/
|
|
#ifndef min
|
|
#define min(x,y) ({ \
|
|
typeof(x) _x = (x); \
|
|
typeof(y) _y = (y); \
|
|
(void) (&_x == &_y); \
|
|
_x < _y ? _x : _y; })
|
|
#endif
|
|
|
|
#ifndef max
|
|
#define max(x,y) ({ \
|
|
typeof(x) _x = (x); \
|
|
typeof(y) _y = (y); \
|
|
(void) (&_x == &_y); \
|
|
_x > _y ? _x : _y; })
|
|
#endif
|
|
|
|
/*
|
|
* ..and if you can't take the strict
|
|
* types, you can specify one yourself.
|
|
*
|
|
* Or not use min/max at all, of course.
|
|
*/
|
|
#define min_t(type,x,y) \
|
|
({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
|
|
#define max_t(type,x,y) \
|
|
({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
|
|
|
|
|
|
//#define BITS_PER_LONG 32
|
|
//#define BITS_PER_LONG_LONG 64
|
|
|
|
#ifndef ALIGN
|
|
#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1))
|
|
#endif
|
|
#define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1))
|
|
#ifndef INT_MAX
|
|
#define INT_MAX ((int)(~0U>>1))
|
|
#endif
|
|
#ifndef INT_MIN
|
|
#define INT_MIN (-INT_MAX - 1)
|
|
#endif
|
|
#ifndef UINT_MAX
|
|
#define UINT_MAX (~0U)
|
|
#endif
|
|
#ifndef LONG_MAX
|
|
#define LONG_MAX ((long)(~0UL>>1))
|
|
#endif
|
|
#ifndef LONG_MIN
|
|
#define LONG_MIN (-LONG_MAX - 1)
|
|
#endif
|
|
#ifndef ULONG_MAX
|
|
#define ULONG_MAX (~0UL)
|
|
#endif
|
|
#ifndef LLONG_MAX
|
|
#define LLONG_MAX ((long long)(~0ULL>>1))
|
|
#endif
|
|
#ifndef LLONG_MIN
|
|
#define LLONG_MIN (-LLONG_MAX - 1)
|
|
#endif
|
|
#ifndef ULLONG_MAX
|
|
#define ULLONG_MAX (~0ULL)
|
|
#endif
|
|
|
|
#ifndef DATA_TYPE_X_BOOL
|
|
#define DATA_TYPE_X_BOOL
|
|
typedef enum
|
|
{
|
|
#ifndef FALSE
|
|
FALSE = 0,
|
|
#endif
|
|
#ifndef NO
|
|
NO = 0,
|
|
#endif
|
|
#ifndef ZERO
|
|
ZERO = 0,
|
|
#endif
|
|
#ifndef TRUE
|
|
TRUE = 1,
|
|
#endif
|
|
#ifndef YES
|
|
YES = 1,
|
|
#endif
|
|
#ifndef ONE
|
|
ONE = 1,
|
|
#endif
|
|
#ifndef OK
|
|
OK = 0,
|
|
#endif
|
|
#ifndef FAIL
|
|
FAIL = -1,
|
|
#endif
|
|
} BOOL;
|
|
#endif
|
|
/*
|
|
* Check at compile time that something is of a particular type.
|
|
* Always evaluates to 1 so you may use it easily in comparisons.
|
|
*/
|
|
#define typecheck(type,x) \
|
|
({ type __dummy; \
|
|
typeof(x) __dummy2; \
|
|
(void)(&__dummy == &__dummy2); \
|
|
1; \
|
|
})
|
|
|
|
static inline int is_power_of_2(unsigned long n)
|
|
{
|
|
return (n != 0 && ((n & (n - 1)) == 0));
|
|
}
|
|
|
|
/* round "x" up/down to next multiple of "align" (which must be a power of 2) */
|
|
#define ROUND_UP(x, align) \
|
|
(((unsigned long)(x) + ((unsigned long)(align) - 1)) & \
|
|
~((unsigned long)(align) - 1))
|
|
#define ROUND_DOWN(x, align) \
|
|
((unsigned long)(x) & ~((unsigned long)(align) - 1))
|
|
|
|
//#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
|
|
|
|
/**
|
|
* test_bit - Determine whether a bit is set
|
|
* @nr: bit number to test
|
|
* @addr: Address to start counting from
|
|
*/
|
|
static inline int test_bit(int nr, long *addr)
|
|
{
|
|
int mask;
|
|
addr += nr >> 5;
|
|
mask = 1 << (nr & 0x1f);
|
|
return ((mask & *addr) != 0);
|
|
}
|
|
|
|
/*
|
|
* These functions are the basis of our bit ops.
|
|
*
|
|
* First, the atomic bitops. These use native endian.
|
|
*/
|
|
static inline void set_bit(unsigned int bit, volatile unsigned long *p)
|
|
{
|
|
unsigned long flags;
|
|
unsigned long mask = 1UL << (bit & 31);
|
|
p += bit >> 5;
|
|
ENTER_CRITICAL(flags);
|
|
*p |= mask;
|
|
EXIT_CRITICAL(flags);
|
|
}
|
|
|
|
static inline void clear_bit(unsigned int bit, volatile unsigned long *p)
|
|
{
|
|
unsigned long flags;
|
|
unsigned long mask = 1UL << (bit & 31);
|
|
p += bit >> 5;
|
|
ENTER_CRITICAL(flags);
|
|
*p &= ~mask;
|
|
EXIT_CRITICAL(flags);
|
|
}
|
|
|
|
static inline void change_bit(unsigned int bit, volatile unsigned long *p)
|
|
{
|
|
unsigned long flags;
|
|
unsigned long mask = 1UL << (bit & 31);
|
|
p += bit >> 5;
|
|
ENTER_CRITICAL(flags);
|
|
*p ^= mask;
|
|
EXIT_CRITICAL(flags);
|
|
}
|
|
|
|
static inline int test_and_set_bit(unsigned int bit, volatile unsigned long *p)
|
|
{
|
|
unsigned long flags;
|
|
unsigned int res;
|
|
unsigned long mask = 1UL << (bit & 31);
|
|
p += bit >> 5;
|
|
ENTER_CRITICAL(flags);
|
|
res = *p;
|
|
*p = res | mask;
|
|
EXIT_CRITICAL(flags);
|
|
return res & mask;
|
|
}
|
|
|
|
static inline int test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
|
|
{
|
|
unsigned long flags;
|
|
unsigned int res;
|
|
unsigned long mask = 1UL << (bit & 31);
|
|
p += bit >> 5;
|
|
ENTER_CRITICAL(flags);
|
|
res = *p;
|
|
*p = res & ~mask;
|
|
EXIT_CRITICAL(flags);
|
|
return res & mask;
|
|
}
|
|
|
|
static inline int test_and_change_bit(unsigned int bit, volatile unsigned long *p)
|
|
{
|
|
unsigned long flags;
|
|
unsigned int res;
|
|
unsigned long mask = 1UL << (bit & 31);
|
|
p += bit >> 5;
|
|
ENTER_CRITICAL(flags);
|
|
res = *p;
|
|
*p = res ^ mask;
|
|
EXIT_CRITICAL(flags);
|
|
return res & mask;
|
|
}
|
|
|
|
/* -------------------------------- jiffies -----------------------------*/
|
|
#define HZ 100
|
|
#define jiffies ((unsigned long)rt_tick_get())
|
|
|
|
/*
|
|
* These inlines deal with timer wrapping correctly. You are
|
|
* strongly encouraged to use them
|
|
* 1. Because people otherwise forget
|
|
* 2. Because if the timer wrap changes in future you won't have to
|
|
* alter your driver code.
|
|
*
|
|
* time_after(a,b) returns true if the time a is after time b.
|
|
*
|
|
* Do this with "<0" and ">=0" to only test the sign of the result. A
|
|
* good compiler would generate better code (and a really good compiler
|
|
* wouldn't care). Gcc is currently neither.
|
|
*/
|
|
#define time_after(a,b) \
|
|
(typecheck(unsigned long, a) && \
|
|
typecheck(unsigned long, b) && \
|
|
((int)(b) - (int)(a) < 0))
|
|
#define time_before(a,b) time_after(b,a)
|
|
|
|
#define time_after_eq(a,b) \
|
|
(typecheck(unsigned long, a) && \
|
|
typecheck(unsigned long, b) && \
|
|
((int)(a) - (int)(b) >= 0))
|
|
#define time_before_eq(a,b) time_after_eq(b,a)
|
|
|
|
#endif /* __SUPPORT_H__ */
|