#ifndef _HAL_COMMON_H
#define _HAL_COMMON_H

#ifdef __cplusplus
extern "C"
{
#endif

#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "hal_log.h"

#ifndef min
#define min(a, b)  ((a) < (b) ? (a) : (b))
#endif

#ifndef max
#define max(a,b)   ((a) < (b) ? (b) : (a))
#endif

#ifndef MIN
#define MIN(a, b)  ((a) < (b) ? (a) : (b))
#endif

#ifndef MAX
#define MAX(a,b)   ((a) < (b) ? (b) : (a))
#endif

#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x)       (sizeof(x) / sizeof((x)[0]))
#endif

#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))

#ifndef ALIGN_UP
#define ALIGN_UP(x, a) __ALIGN_KERNEL((x), (a))
#endif

#ifndef ALIGN_DOWN
#define ALIGN_DOWN(x, a) __ALIGN_KERNEL((x) - ((a) - 1), (a))
#endif

#ifndef BIT
#define BIT(x) (1 << x)
#endif

#define get_bvalue(addr)    (*((volatile unsigned char  *)(addr)))
#define put_bvalue(addr, v) (*((volatile unsigned char  *)(addr)) = (unsigned char)(v))
#define get_hvalue(addr)    (*((volatile unsigned short *)(addr)))
#define put_hvalue(addr, v) (*((volatile unsigned short *)(addr)) = (unsigned short)(v))
#define get_wvalue(addr)    (*((volatile unsigned int   *)(addr)))
#define put_wvalue(addr, v) (*((volatile unsigned int   *)(addr)) = (unsigned int)(v))

#define set_byte(addr, v)    (*((volatile unsigned char  *)(addr)) |=  (unsigned char)(v))
#define clr_byte(addr, v)    (*((volatile unsigned char  *)(addr)) &= ~(unsigned char)(v))
#define set_half_word(addr, v)   (*((volatile unsigned short *)(addr)) |=  (unsigned short)(v))
#define clr_half_word(addr, v)   (*((volatile unsigned short *)(addr)) &= ~(unsigned short)(v))
#define set_word(addr, v)   (*((volatile unsigned int   *)(addr)) |=  (unsigned int)(v))
#define clr_word(addr, v)   (*((volatile unsigned int   *)(addr)) &= ~(unsigned int)(v))

#ifndef readb
#define readb(addr)     (*((volatile unsigned char  *)(addr)))
#endif
#ifndef readw
#define readw(addr)     (*((volatile unsigned short *)(addr)))
#endif
#ifndef readl
#define readl(addr)     (*((volatile unsigned int  *)(unsigned long)(addr)))
#endif
#ifndef writeb
#define writeb(v, addr) (*((volatile unsigned char  *)(addr)) = (unsigned char)(v))
#endif
#ifndef writew
#define writew(v, addr) (*((volatile unsigned short *)(addr)) = (unsigned short)(v))
#endif
#ifndef writel
#define writel(v, addr) (*((volatile unsigned int   *)(unsigned long)(addr)) = (unsigned int)(v))
#endif

#define cmp_wvalue(addr, v) (v == (*((volatile unsigned int *) (addr))))

/* common register access operation. */
#define hal_readb(reg)          (*(volatile uint8_t  *)(long)(reg))
#define hal_readw(reg)          (*(volatile uint16_t *)(reg))
#define hal_readl(reg)          (*(volatile uint32_t *)(reg))
#define hal_writeb(value,reg)   (*(volatile uint8_t  *)(long)(reg) = (value))
#define hal_writew(value,reg)   (*(volatile uint16_t *)(reg) = (value))
#define hal_writel(value,reg)   (*(volatile uint32_t *)(reg) = (value))

#ifndef OK
#define OK      (0)
#endif
//#ifndef FAIL
//#define FAIL    (-1)
//#endif
#ifndef TRUE
#define TRUE    (1)
#endif
#ifndef FALSE
#define FALSE   (0)
#endif
#ifndef true
#define true     1
#endif
#ifndef false
#define false    0
#endif

#ifndef NULL
#define NULL    0
#endif

#define CACHELINE_LEN (64)

typedef uint64_t  u64;
typedef uint32_t  u32;
typedef uint16_t  u16;
typedef uint8_t   u8;
typedef int64_t  s64;
typedef int32_t  s32;
typedef int16_t  s16;
typedef int8_t   s8;

#define HAL_ARG_UNUSED(NAME)   (void)(NAME)

/* general function pointer defines */
typedef s32(*__pCBK_t)(void *p_arg);            /* call-back */
typedef s32(*__pISR_hdle_t)(void *p_arg);       /* ISR */

typedef s32(*__pNotifier_t)(u32 message, u32 aux);  /* notifer call-back */
typedef s32(*__pCPUExceptionHandler)(void);         /* cpu exception handler pointer */

#define BUG() do {                                                             \
        printf("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
        backtrace(NULL, NULL, 0, 0, printf);                                   \
        while(1);                                                              \
    } while (0)

#ifndef BUG_ON
#define BUG_ON(condition)   do { if (unlikely(condition)) BUG(); } while (0)
#define WARN_ON(condition)  ({                                          \
        int __ret_warn_on = !!(condition);                              \
        unlikely(__ret_warn_on);                                        \
    })
#endif

#ifndef WARN
#define WARN(condition, format...) ({                                   \
        int __ret_warn_on = !!(condition);                              \
        if(__ret_warn_on)                                               \
            printf(format);                                             \
        unlikely(__ret_warn_on);                                        \
    })
#endif

#ifdef CONFIG_DEBUG_BACKTRACE
#define hal_assert(ex)                                                  \
    if (!(ex)) {                                                        \
        printk("%s line %d, fatal error.\n", __func__, __LINE__);       \
        backtrace(NULL, NULL, 0, 0, printf);                            \
        while(1);                                                       \
    }
#else
#define hal_assert(ex)                                                  \
    if (!(ex)) {                                                        \
        printk("assertion failed at func:%s, line:%d",                  \
                 __FUNCTION__, __LINE__);                               \
        while(1);                                                       \
    }
#endif

// version combine.
#define SPV_HAL_VERSION_MAJOR_MINOR(major, minor)     (((major) << 8) | (minor))

typedef struct SPV_hal_version
{
    // API version NO.
    uint16_t api;

    // Driver version NO.
    uint16_t drv;
} SPV_hal_version_t;

// General return code of hal driver.
#define SPV_HAL_OK                     0UL
// Unspecified error.
#define SPV_HAL_ERROR                 -1UL
// Hal is busy.
#define SPV_HAL_ERROR_BUSY            -2UL
// Timout occured.
#define SPV_HAL_ERROR_TIMEOUT         -3UL
// Operaion not supported.
#define SPV_HAL_ERROR_UNSUPOT         -4UL
// Parameter error.
#define SPV_HAL_ERROR_PARAERR         -5UL
// Start of driver specific errors.
#define SPV_HAL_ERROR_DRVSPECIFIC     -6UL


#ifdef __cplusplus
}
#endif

#endif  /*SPV_HAL_COMMON_H*/

