nt9856x/code/hdal/drivers/k_driver/source/include/rcw_macro.h
2023-03-28 15:07:53 +08:00

161 lines
5.8 KiB
C

/*
Driver Register Cache Word (RCW) operation header file.
Driver Register Cache Word (RCW) operation header file.
The macros defined in this header file is used to simply the register
bit field read and write. By adapting this way of register access,
it shall provide more error-proof and more readable way to write
drivers. It also does register access in load/store way which allow
one to accurately control the number of counts the register read and
write is proceeded from code writing.
@file RCWMacro.h
@ingroup mIDriver
@note Nothing.
Copyright Novatek Microelectronics Corp. 2010. All rights reserved.
*/
#ifndef __ASM_ARCH_NVT_IVOT_RCW_MACRO_H
#define __ASM_ARCH_NVT_IVOT_RCW_MACRO_H
#if defined(__FREERTOS)
#include <stdint.h>
#elif defined(__KERNEL__)
#include <linux/types.h>
#endif
/**
@addtogroup mIDriver
*/
//@{
//
// Register word value type
//
// The size in bits of this type should match the RCW type
#define REGVALUE uint32_t
#define UBITFIELD unsigned int /* Unsigned bit field */
#define BITFIELD signed int /* Signed bit field */
#define FALSE 0
#define TRUE 1
/**
@name Assert macros
*/
//@{
#define ASSERT_CONCAT_(a, b) a##b
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
#if defined(__COUNTER__)
#define STATIC_ASSERT(expr) \
enum { ASSERT_CONCAT(FAILED_STATIC_ASSERT_, __COUNTER__) = 1/(expr) }
#else
// This might cause compile error when writing STATIC_ASSERT at the same line
// in two (or more) files and one file include another one.
#define STATIC_ASSERT(expr) \
enum { ASSERT_CONCAT(FAILED_STATIC_ASSERT_, __LINE__) = 1/(expr) }
#endif
#define OUTW(addr,value) (*(REGVALUE volatile *)(addr) = (REGVALUE)(value))
#define INW(addr) (*(REGVALUE volatile *)(addr))
//
// Macros for Register Cache Word (RCW) type definition
//
// Each RCW type should be exactly the same size with REGVALUE type
// For example, to declare a Register Cache Word type:
//
// #define rcwname_OFS 0x00 /* the name of RCW corresponding register address offset
// should be in specific format with "_OFS" appended */
// REGDEF_BEGIN(rcwname)
// REGDEF_BIT(field1, 8) /* declare field1 as 8 bits width */
// REGDEF_BIT(field2, 8) /* declare field1 as 8 bits width */
// REGDEF_BIT(, 16) /* pad reserved (not-used) bits to fill RCW type same as REGVALUE size */
// REGDEF_END(rcwname)
//
// Register Cache Word type defintion header
#define REGDEF_BEGIN(name) \
typedef union \
{ \
REGVALUE reg; \
struct \
{
// Register Cache Word bit defintion
#define REGDEF_BIT(field, bits) \
UBITFIELD field : bits;
// Register Cache Word type defintion trailer
#define REGDEF_END(name) \
} bit; \
} T_##name; \
STATIC_ASSERT(sizeof(T_##name) == sizeof(REGVALUE));
// Macro to define register offset
#define REGDEF_OFFSET(name, ofs) static const uint32_t name##_OFS=(ofs);
//
// Macros for prerequisite stuff initialization for Register Cache Word
// operations
//
// Macro to set register base address for current module
// One must call this macro somewhere to set register I/O base address for
// current module, either globally or locally before any RCW operations is
// invoked
// What this macro set is only effective in current C file
#define REGDEF_SETIOBASE(base) static const uint32_t _REGIOBASE=(base)
// Macro to set register repeat group offset address in byte
// This macro is optional and only used where register with repeat group exist,
// only one repeat group is allowed in one file
// If registers with repeat group exist, then one only have to define the RCW type
// for the first group, respective group of registers can be accessed through
// RCW_LD2, RCW_ST2, RCW_LD2OF macros
// What this macro set is only effective in current C file
#define REGDEF_SETGRPOFS(grpofs) static const uint32_t _REGGRPOFS=(grpofs)
//
// Macros for Register Cache Word (RCW) operations
//
// These RCW operations are most likely to be used inside C functions
// It is not recommended to use RCW_DEF(RCW) in global scope which
// declare RCW as global variable
// RCW_LD/RCW_ST/RCW_LDOF pair is for normal single register access while
// RCW_LD2/RCW_ST2/RCW_LD2OF pair is for repeat group register access
// Beware that the RCW_LD/RCW_ST/RCW_LDOF and RCW_LD2/RCW_ST2/RCW_LD2OF
// must not be mixed used. e.g. use RCW_LD then RCW_ST2 or use RCW_LD2 then RCW_ST
//
// Register Cache Word declaration
#define RCW_DEF(RCW) T##_##RCW t##RCW
// Register Cache Word read from I/O
#define RCW_LD(RCW) t##RCW.reg = INW(_REGIOBASE+RCW##_OFS)
// Register Cache Word repeat from I/O for group read
#define RCW_LD2(RCW, grpidx) t##RCW.reg = INW(_REGIOBASE+RCW##_OFS+(grpidx)*_REGGRPOFS)
// Register Cache Word bit reference
#define RCW_OF(RCW) t##RCW.bit
// Register Cache Word reference
#define RCW_VAL(RCW) t##RCW.reg
// Register Cache Word write to I/O
#define RCW_ST(RCW) OUTW(_REGIOBASE+RCW##_OFS, t##RCW.reg)
// Register Cache Word write to I/O for repeat group
#define RCW_ST2(RCW, grpidx) OUTW(_REGIOBASE+RCW##_OFS+(grpidx)*_REGGRPOFS, t##RCW.reg)
// Register Cache Word read and reference to register cache word bit
// !!!need to check for compiler if support for this syntax
#define RCW_LDOF(RCW) ((T##_##RCW)(RCW_LD(RCW))).bit
// Register Cache Word read and reference to register cache word bit for repeat group
// !!!need to check for compiler if support for this syntax
#define RCW_LD2OF(RCW, grpidx) ((T##_##RCW)(RCW_LD2(RCW, grpidx))).bit
#define rcw_get_phy_addr(addr) ((addr) & 0x1FFFFFFF)
//@}
#endif /* __ASM_ARCH_NVT_IVOT_RCW_MACRO_H */