mirror of https://github.com/OpenIPC/firmware.git
[no ci] Hisilicon: add hisilicon-osdrv-serdes package (#1154)
Co-authored-by: Signor Pellegrino <68112357+FlyRouter@users.noreply.github.com>pull/1158/head
parent
f003efd390
commit
511b2d4c8b
|
@ -25,7 +25,6 @@ source "$BR2_EXTERNAL_GENERAL_PATH/package/goke-osdrv-gk7205v200/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/grainmedia-osdrv-gm8136/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/grainmedia-osdrv-gm8136/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisi-gpio/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisi-gpio/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisilicon-opensdk/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisilicon-opensdk/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisilicon-osdrv1-sources/Config.in"
|
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisilicon-osdrv-hi3516av100/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisilicon-osdrv-hi3516av100/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisilicon-osdrv-hi3516cv100/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisilicon-osdrv-hi3516cv100/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisilicon-osdrv-hi3516cv200/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisilicon-osdrv-hi3516cv200/Config.in"
|
||||||
|
@ -34,15 +33,19 @@ source "$BR2_EXTERNAL_GENERAL_PATH/package/hisilicon-osdrv-hi3516cv500/Config.in
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisilicon-osdrv-hi3516ev200/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisilicon-osdrv-hi3516ev200/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisilicon-osdrv-hi3519v101/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisilicon-osdrv-hi3519v101/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisilicon-osdrv-hi3536dv100/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisilicon-osdrv-hi3536dv100/Config.in"
|
||||||
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisilicon-osdrv-serdes/Config.in"
|
||||||
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/hisilicon-osdrv1-sources/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/i2c-telemetry/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/i2c-telemetry/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-motors-t31/Config.in"
|
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-atbm603x-sdio-t31/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-atbm603x-sdio-t31/Config.in"
|
||||||
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-libimp-control/Config.in"
|
||||||
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-motors-t31/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-opensdk/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-opensdk/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-osdrv-t20/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-osdrv-t20/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-osdrv-t21/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-osdrv-t21/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-osdrv-t30/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-osdrv-t30/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-osdrv-t31/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-osdrv-t31/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-osdrv-t40/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-osdrv-t40/Config.in"
|
||||||
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-pwm/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/ipctool/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/ipctool/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/json-c-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/json-c-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/jsonfilter/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/jsonfilter/Config.in"
|
||||||
|
@ -51,22 +54,23 @@ source "$BR2_EXTERNAL_GENERAL_PATH/package/libcurl-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/libevent-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/libevent-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/libhv-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/libhv-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/libogg-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/libogg-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/librem-openipc/Config.in"
|
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/libre-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/libre-openipc/Config.in"
|
||||||
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/librem-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/libsrt-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/libsrt-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/libsrtp-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/libsrtp-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/libwebsockets-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/libwebsockets-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/linux-firmware-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/linux-firmware-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/linux-patcher/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/linux-patcher/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/majestic/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/logcat-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/majestic-fonts/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/majestic-fonts/Config.in"
|
||||||
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/majestic/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/mavfwd/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/mavfwd/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/mavlink-router/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/mavlink-router/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/mbedtls-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/mbedtls-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/microbe-web/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/microbe-web/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/microsnander/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/microsnander/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/mini/Config.in"
|
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/mini-snmpd-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/mini-snmpd-openipc/Config.in"
|
||||||
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/mini/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/motors/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/motors/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/mt7601u-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/mt7601u-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/nabto/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/nabto/Config.in"
|
||||||
|
@ -80,8 +84,8 @@ source "$BR2_EXTERNAL_GENERAL_PATH/package/rockchip-osdrv-rv11xx/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/rtl8188eus-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/rtl8188eus-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/rtl8188fu-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/rtl8188fu-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/rtl8188fu-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/rtl8188fu-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/rtl8189fs-openipc/Config.in"
|
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/rtl8189es-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/rtl8189es-openipc/Config.in"
|
||||||
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/rtl8189fs-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/rtl8192eu-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/rtl8192eu-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/rtl8733bu-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/rtl8733bu-openipc/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/rtl8812au-openipc/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/rtl8812au-openipc/Config.in"
|
||||||
|
@ -106,6 +110,3 @@ source "$BR2_EXTERNAL_GENERAL_PATH/package/xiongmai-osdrv-xm530/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/xmdp/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/xmdp/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/yaml-cli/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/yaml-cli/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/zerotier-one/Config.in"
|
source "$BR2_EXTERNAL_GENERAL_PATH/package/zerotier-one/Config.in"
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/logcat-openipc/Config.in"
|
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-pwm/Config.in"
|
|
||||||
source "$BR2_EXTERNAL_GENERAL_PATH/package/ingenic-libimp-control/Config.in"
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
config BR2_PACKAGE_HISILICON_OSDRV_SERDES
|
||||||
|
bool "hisilicon-osdrv-serdes"
|
||||||
|
help
|
||||||
|
HiSilicon SerDes kernel driver.
|
|
@ -0,0 +1,14 @@
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# hisilicon-osdrv-serdes
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
HISILICON_OSDRV_SERDES_SITE_METHOD = local
|
||||||
|
HISILICON_OSDRV_SERDES_SITE = $(HISILICON_OSDRV_SERDES_PKGDIR)/src
|
||||||
|
|
||||||
|
HISILICON_OSDRV_SERDES_MODULE_MAKE_OPTS = \
|
||||||
|
KSRC=$(LINUX_DIR)
|
||||||
|
|
||||||
|
$(eval $(kernel-module))
|
||||||
|
$(eval $(generic-package))
|
|
@ -0,0 +1,9 @@
|
||||||
|
obj-m := hi_serdes.o
|
||||||
|
hi_serdes-objs := serdes_comm.o thine_241a242_serdes.o
|
||||||
|
ccflags-y := -I $(PWD)/include
|
||||||
|
|
||||||
|
modules:
|
||||||
|
$(MAKE) -C $(KSRC) M=$(PWD) modules
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(MAKE) -C $(KSRC) M=$(PWD) clean
|
|
@ -0,0 +1,571 @@
|
||||||
|
#ifndef __HI_OSAL__
|
||||||
|
#define __HI_OSAL__
|
||||||
|
|
||||||
|
#define HI_OSAL_VERSION "1.0"
|
||||||
|
|
||||||
|
#include "osal_list.h"
|
||||||
|
|
||||||
|
#define osal_gfp_kernel 0
|
||||||
|
#define osal_gfp_atomic 1
|
||||||
|
extern void *osal_vmalloc(unsigned long size);
|
||||||
|
extern void osal_vfree(const void *addr);
|
||||||
|
extern void *osal_kmalloc(unsigned long size, unsigned int osal_gfp_flag);
|
||||||
|
extern void osal_kfree(const void *addr);
|
||||||
|
|
||||||
|
// atomic api
|
||||||
|
typedef struct {
|
||||||
|
void *atomic;
|
||||||
|
} osal_atomic_t;
|
||||||
|
|
||||||
|
#define OSAL_ATOMIC_INIT(i) { (i) }
|
||||||
|
|
||||||
|
extern int osal_atomic_init(osal_atomic_t *atomic);
|
||||||
|
extern void osal_atomic_destory(osal_atomic_t *atomic);
|
||||||
|
extern int osal_atomic_read(osal_atomic_t *v);
|
||||||
|
extern void osal_atomic_set(osal_atomic_t *v, int i);
|
||||||
|
extern int osal_atomic_inc_return(osal_atomic_t *v);
|
||||||
|
extern int osal_atomic_dec_return(osal_atomic_t *v);
|
||||||
|
|
||||||
|
// semaphore api
|
||||||
|
#define EINTR 4
|
||||||
|
typedef struct osal_semaphore {
|
||||||
|
void *sem;
|
||||||
|
} osal_semaphore_t;
|
||||||
|
extern int osal_sema_init(osal_semaphore_t *sem, int val);
|
||||||
|
extern int osal_down(osal_semaphore_t *sem);
|
||||||
|
extern int osal_down_interruptible(osal_semaphore_t *sem);
|
||||||
|
extern int osal_down_trylock(osal_semaphore_t *sem);
|
||||||
|
extern void osal_up(osal_semaphore_t *sem);
|
||||||
|
// notice:must be called when kmod exit, other wise will lead to memory leak;
|
||||||
|
extern void osal_sema_destory(osal_semaphore_t *sem);
|
||||||
|
|
||||||
|
// mutex api
|
||||||
|
typedef struct osal_mutex {
|
||||||
|
void *mutex;
|
||||||
|
} osal_mutex_t;
|
||||||
|
extern int osal_mutex_init(osal_mutex_t *mutex);
|
||||||
|
extern int osal_mutex_lock(osal_mutex_t *mutex);
|
||||||
|
extern int osal_mutex_lock_interruptible(osal_mutex_t *mutex);
|
||||||
|
extern int osal_mutex_trylock(osal_mutex_t *mutex);
|
||||||
|
extern void osal_mutex_unlock(osal_mutex_t *mutex);
|
||||||
|
// notice:must be called when kmod exit, other wise will lead to memory leak;
|
||||||
|
extern void osal_mutex_destory(osal_mutex_t *mutex);
|
||||||
|
|
||||||
|
// spin lock api
|
||||||
|
typedef struct osal_spinlock {
|
||||||
|
void *lock;
|
||||||
|
} osal_spinlock_t;
|
||||||
|
extern int osal_spin_lock_init(osal_spinlock_t *lock);
|
||||||
|
extern void osal_spin_lock(osal_spinlock_t *lock);
|
||||||
|
extern int osal_spin_trylock(osal_spinlock_t *lock);
|
||||||
|
extern void osal_spin_unlock(osal_spinlock_t *lock);
|
||||||
|
extern void osal_spin_lock_irqsave(osal_spinlock_t *lock, unsigned long *flags);
|
||||||
|
extern void osal_spin_unlock_irqrestore(osal_spinlock_t *lock, unsigned long *flags);
|
||||||
|
// notice:must be called when kmod exit, other wise will lead to memory leak;
|
||||||
|
extern void osal_spin_lock_destory(osal_spinlock_t *lock);
|
||||||
|
|
||||||
|
// wait api
|
||||||
|
typedef int (*osal_wait_cond_func_t)(const void *param);
|
||||||
|
|
||||||
|
typedef struct osal_wait {
|
||||||
|
void *wait;
|
||||||
|
} osal_wait_t;
|
||||||
|
#define ERESTARTSYS 512
|
||||||
|
|
||||||
|
extern unsigned long osal_msecs_to_jiffies(const unsigned int m);
|
||||||
|
extern int osal_wait_init(osal_wait_t *wait);
|
||||||
|
extern int osal_wait_interruptible(osal_wait_t *wait, osal_wait_cond_func_t func, void *param);
|
||||||
|
extern int osal_wait_uninterruptible(osal_wait_t *wait, osal_wait_cond_func_t func, void *param);
|
||||||
|
extern int osal_wait_timeout_interruptible(osal_wait_t *wait, osal_wait_cond_func_t func, void *param,
|
||||||
|
unsigned long ms);
|
||||||
|
extern int osal_wait_timeout_uninterruptible(osal_wait_t *wait, osal_wait_cond_func_t func, void *param,
|
||||||
|
unsigned long ms);
|
||||||
|
|
||||||
|
#define osal_wait_event_interruptible(wait, func, param) \
|
||||||
|
({ \
|
||||||
|
int __ret = 0; \
|
||||||
|
\
|
||||||
|
for (;;) { \
|
||||||
|
if (func(param)) { \
|
||||||
|
__ret = 0; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
__ret = osal_wait_timeout_interruptible(wait, (func), param, 100); \
|
||||||
|
if (__ret < 0) \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
__ret; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define osal_wait_event_uninterruptible(wait, func, param) \
|
||||||
|
({ \
|
||||||
|
int __ret = 0; \
|
||||||
|
\
|
||||||
|
for (;;) { \
|
||||||
|
if (func(param)) { \
|
||||||
|
__ret = 0; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
__ret = osal_wait_uninterruptible(wait, (func), param); \
|
||||||
|
if (__ret < 0) \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
__ret; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define osal_wait_event_timeout_interruptible(wait, func, param, timeout) \
|
||||||
|
({ \
|
||||||
|
int __ret = timeout; \
|
||||||
|
\
|
||||||
|
if ((func(param)) && !timeout) { \
|
||||||
|
__ret = 1; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
for (;;) { \
|
||||||
|
if (func(param)) { \
|
||||||
|
__ret = osal_msecs_to_jiffies(__ret); \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
__ret = osal_wait_timeout_interruptible(wait, (func), param, __ret); \
|
||||||
|
if (!__ret || __ret == -ERESTARTSYS) \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
__ret; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define osal_wait_event_timeout_uninterruptible(wait, func, param, timeout) \
|
||||||
|
({ \
|
||||||
|
int __ret = timeout; \
|
||||||
|
\
|
||||||
|
if ((func(param)) && !timeout) { \
|
||||||
|
__ret = 1; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
for (;;) { \
|
||||||
|
if (func(param)) { \
|
||||||
|
__ret = osal_msecs_to_jiffies(__ret); \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
__ret = osal_wait_timeout_uninterruptible(wait, (func), param, __ret); \
|
||||||
|
if (!__ret || __ret == -ERESTARTSYS) \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
__ret; \
|
||||||
|
})
|
||||||
|
|
||||||
|
extern void osal_wakeup(osal_wait_t *wait); // same as wake_up_all
|
||||||
|
extern void osal_wait_destory(osal_wait_t *wait);
|
||||||
|
|
||||||
|
// workqueue api
|
||||||
|
typedef struct osal_work_struct {
|
||||||
|
void *work;
|
||||||
|
void (*func)(struct osal_work_struct *work);
|
||||||
|
} osal_work_struct_t;
|
||||||
|
typedef void (*osal_work_func_t)(struct osal_work_struct *work);
|
||||||
|
|
||||||
|
extern int osal_init_work(struct osal_work_struct *work, osal_work_func_t func);
|
||||||
|
|
||||||
|
#define OSAL_INIT_WORK(_work, _func) \
|
||||||
|
do { \
|
||||||
|
osal_init_work((_work), (_func)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
extern int osal_schedule_work(struct osal_work_struct *work);
|
||||||
|
extern void osal_destroy_work(struct osal_work_struct *work);
|
||||||
|
|
||||||
|
// shedule
|
||||||
|
extern void osal_yield(void);
|
||||||
|
|
||||||
|
// interrupt api
|
||||||
|
enum osal_irqreturn {
|
||||||
|
OSAL_IRQ_NONE = (0 << 0),
|
||||||
|
OSAL_IRQ_HANDLED = (1 << 0),
|
||||||
|
OSAL_IRQ_WAKE_THREAD = (1 << 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int (*osal_irq_handler_t)(int, void *);
|
||||||
|
extern int osal_request_irq(unsigned int irq, osal_irq_handler_t handler, osal_irq_handler_t thread_fn,
|
||||||
|
const char *name, void *dev);
|
||||||
|
extern void osal_free_irq(unsigned int irq, void *dev);
|
||||||
|
extern int osal_in_interrupt(void);
|
||||||
|
|
||||||
|
#define OSAL_DIS_IRQ_CNT 2
|
||||||
|
typedef void (*osal_gic_handle_t)(unsigned int, unsigned int, void *);
|
||||||
|
extern int osal_register_gic_handle(unsigned int index, unsigned int irq, osal_gic_handle_t handle, const char *name,
|
||||||
|
void *dev);
|
||||||
|
extern int osal_unregister_gic_handle(unsigned int index, unsigned int irq, void *dev);
|
||||||
|
|
||||||
|
// task api
|
||||||
|
typedef struct osal_task {
|
||||||
|
void *task_struct;
|
||||||
|
} osal_task_t;
|
||||||
|
typedef int (*threadfn_t)(void *data);
|
||||||
|
extern osal_task_t *osal_kthread_create(threadfn_t thread, void *data, const char *name);
|
||||||
|
extern void osal_kthread_destory(osal_task_t *task, unsigned int stop_flag);
|
||||||
|
|
||||||
|
// string api
|
||||||
|
extern char *osal_strcpy(char *s1, const char *s2);
|
||||||
|
extern char *osal_strncpy(char *s1, const char *s2, int size);
|
||||||
|
extern int osal_strlcpy(char *s1, const char *s2, int size);
|
||||||
|
extern char *osal_strcat(char *s1, const char *s2);
|
||||||
|
extern char *osal_strncat(char *s1, const char *s2, int size);
|
||||||
|
extern int osal_strlcat(char *s1, const char *s2, int size);
|
||||||
|
extern int osal_strcmp(const char *s1, const char *s2);
|
||||||
|
extern int osal_strncmp(const char *s1, const char *s2, int size);
|
||||||
|
extern int osal_strnicmp(const char *s1, const char *s2, int size);
|
||||||
|
extern int osal_strcasecmp(const char *s1, const char *s2);
|
||||||
|
extern int osal_strncasecmp(const char *s1, const char *s2, int n);
|
||||||
|
extern char *osal_strchr(const char *s, int n);
|
||||||
|
extern char *osal_strnchr(const char *s, int count, int c);
|
||||||
|
extern char *osal_strrchr(const char *s, int c);
|
||||||
|
extern char *osal_strstr(const char *s1, const char *s2);
|
||||||
|
extern char *osal_strnstr(const char *s1, const char *s2, int n);
|
||||||
|
extern int osal_strlen(const char *s);
|
||||||
|
extern int osal_strnlen(const char *s, int size);
|
||||||
|
extern char *osal_strpbrk(const char *s1, const char *s2);
|
||||||
|
extern char *osal_strsep(char **s, const char *ct);
|
||||||
|
extern int osal_strspn(const char *s, const char *accept);
|
||||||
|
extern int osal_strcspn(const char *s, const char *reject);
|
||||||
|
extern void *osal_memset(void *str, int c, int count);
|
||||||
|
extern void *osal_memcpy(void *s1, const void *s2, int count);
|
||||||
|
extern void *osal_memmove(void *s1, const void *s2, int count);
|
||||||
|
extern void *osal_memscan(void *addr, int c, int size);
|
||||||
|
extern int osal_memcmp(const void *cs, const void *ct, int count);
|
||||||
|
extern void *osal_memchr(const void *s, int c, int n);
|
||||||
|
extern void *osal_memchr_inv(const void *s, int c, int n);
|
||||||
|
|
||||||
|
extern unsigned long long osal_strtoull(const char *cp, char **endp, unsigned int base);
|
||||||
|
extern unsigned long osal_strtoul(const char *cp, char **endp, unsigned int base);
|
||||||
|
extern long osal_strtol(const char *cp, char **endp, unsigned int base);
|
||||||
|
extern long long osal_strtoll(const char *cp, char **endp, unsigned int base);
|
||||||
|
extern int osal_snprintf(char *buf, int size, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
|
||||||
|
extern int osal_scnprintf(char *buf, int size, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
|
||||||
|
extern int osal_sprintf(char *buf, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
|
||||||
|
extern int osal_sscanf(const char *buf, const char *fmt, ...);
|
||||||
|
|
||||||
|
// addr translate
|
||||||
|
extern void *osal_ioremap(unsigned long phys_addr, unsigned long size);
|
||||||
|
extern void *osal_ioremap_nocache(unsigned long phys_addr, unsigned long size);
|
||||||
|
extern void *osal_ioremap_cached(unsigned long phys_addr, unsigned long size);
|
||||||
|
extern void osal_iounmap(void *addr);
|
||||||
|
|
||||||
|
#define osal_readl(x) (*((volatile int *)(x)))
|
||||||
|
#define osal_writel(v, x) (*((volatile int *)(x)) = (v))
|
||||||
|
|
||||||
|
extern unsigned long osal_copy_from_user(void *to, const void *from, unsigned long n);
|
||||||
|
extern unsigned long osal_copy_to_user(void *to, const void *from, unsigned long n);
|
||||||
|
|
||||||
|
#define OSAL_VERIFY_READ 0
|
||||||
|
#define OSAL_VERIFY_WRITE 1
|
||||||
|
extern int osal_access_ok(int type, const void *addr, unsigned long size);
|
||||||
|
|
||||||
|
// cache api
|
||||||
|
extern void osal_flush_cache_all(void);
|
||||||
|
extern void osal_cpuc_flush_dcache_area(void *addr, int size);
|
||||||
|
|
||||||
|
extern void osal_flush_dcache_area(void *kvirt, unsigned long phys_addr, unsigned long length);
|
||||||
|
extern int osal_flush_dcache_all(void);
|
||||||
|
|
||||||
|
// math
|
||||||
|
extern unsigned long long osal_div_u64(unsigned long long dividend, unsigned int divisor);
|
||||||
|
extern long long osal_div_s64(long long dividend, int divisor);
|
||||||
|
extern unsigned long long osal_div64_u64(unsigned long long dividend, unsigned long long divisor);
|
||||||
|
extern long long osal_div64_s64(long long dividend, long long divisor);
|
||||||
|
extern unsigned long long osal_div_u64_rem(unsigned long long dividend, unsigned int divisor);
|
||||||
|
extern long long osal_div_s64_rem(long long dividend, int divisor);
|
||||||
|
extern unsigned long long osal_div64_u64_rem(unsigned long long dividend, unsigned long long divisor);
|
||||||
|
extern unsigned int osal_random(void);
|
||||||
|
|
||||||
|
#define osal_max(x, y) ({ \
|
||||||
|
__typeof__(x) _max1 = (x); \
|
||||||
|
__typeof__(y) _max2 = (y); \
|
||||||
|
(void) (&_max1 == &_max2); \
|
||||||
|
_max1 > _max2 ? _max1 : _max2; })
|
||||||
|
|
||||||
|
#define osal_min(x, y) ({ \
|
||||||
|
__typeof__(x) _min1 = (x); \
|
||||||
|
__typeof__(y) _min2 = (y); \
|
||||||
|
(void) (&_min1 == &_min2); \
|
||||||
|
_min1 < _min2 ? _min1 : _min2; })
|
||||||
|
|
||||||
|
#define osal_abs(x) ({ \
|
||||||
|
long ret; \
|
||||||
|
if (sizeof(x) == sizeof(long)) { \
|
||||||
|
long __x = (x); \
|
||||||
|
ret = (__x < 0) ? -__x : __x; \
|
||||||
|
} else { \
|
||||||
|
int __x = (x); \
|
||||||
|
ret = (__x < 0) ? -__x : __x; \
|
||||||
|
} \
|
||||||
|
ret; \
|
||||||
|
})
|
||||||
|
|
||||||
|
// barrier
|
||||||
|
extern void osal_mb(void);
|
||||||
|
extern void osal_rmb(void);
|
||||||
|
extern void osal_wmb(void);
|
||||||
|
extern void osal_smp_mb(void);
|
||||||
|
extern void osal_smp_rmb(void);
|
||||||
|
extern void osal_smp_wmb(void);
|
||||||
|
extern void osal_isb(void);
|
||||||
|
extern void osal_dsb(void);
|
||||||
|
extern void osal_dmb(void);
|
||||||
|
|
||||||
|
// debug
|
||||||
|
extern int osal_printk(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
|
||||||
|
extern void osal_panic(const char *fmt, const char *fun, int line, const char *);
|
||||||
|
#define OSAL_BUG() \
|
||||||
|
do { \
|
||||||
|
} while (1)
|
||||||
|
|
||||||
|
#define OSAL_ASSERT(expr) \
|
||||||
|
do { \
|
||||||
|
if (!(expr)) { \
|
||||||
|
osal_printk("\nASSERT failed at:\n" \
|
||||||
|
" >Condition: %s\n", \
|
||||||
|
#expr); \
|
||||||
|
OSAL_BUG(); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define OSAL_BUG_ON(expr) \
|
||||||
|
do { \
|
||||||
|
if (expr) { \
|
||||||
|
osal_printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
|
||||||
|
OSAL_BUG(); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
// proc
|
||||||
|
typedef struct osal_proc_dir_entry {
|
||||||
|
char name[50];
|
||||||
|
void *proc_dir_entry;
|
||||||
|
int (*open)(struct osal_proc_dir_entry *entry);
|
||||||
|
int (*read)(struct osal_proc_dir_entry *entry);
|
||||||
|
int (*write)(struct osal_proc_dir_entry *entry, const char *buf, int count, long long *);
|
||||||
|
void *private;
|
||||||
|
void *seqfile;
|
||||||
|
struct osal_list_head node;
|
||||||
|
} osal_proc_entry_t;
|
||||||
|
extern osal_proc_entry_t *osal_create_proc_entry(const char *name, osal_proc_entry_t *parent);
|
||||||
|
extern osal_proc_entry_t *osal_proc_mkdir(const char *name, osal_proc_entry_t *parent);
|
||||||
|
extern void osal_remove_proc_entry(const char *name, osal_proc_entry_t *parent);
|
||||||
|
extern int osal_seq_printf(osal_proc_entry_t *entry, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
|
||||||
|
|
||||||
|
// device api
|
||||||
|
#ifndef _IOC_TYPECHECK
|
||||||
|
#include "osal_ioctl.h"
|
||||||
|
#endif
|
||||||
|
typedef struct osal_dev {
|
||||||
|
char name[48];
|
||||||
|
void *dev;
|
||||||
|
int minor;
|
||||||
|
struct osal_fileops *fops;
|
||||||
|
struct osal_pmops *osal_pmops;
|
||||||
|
} osal_dev_t;
|
||||||
|
|
||||||
|
typedef struct osal_vm {
|
||||||
|
void *vm;
|
||||||
|
} osal_vm_t;
|
||||||
|
|
||||||
|
#define OSAL_POLLIN 0x0001
|
||||||
|
#define OSAL_POLLPRI 0x0002
|
||||||
|
#define OSAL_POLLOUT 0x0004
|
||||||
|
#define OSAL_POLLERR 0x0008
|
||||||
|
#define OSAL_POLLHUP 0x0010
|
||||||
|
#define OSAL_POLLNVAL 0x0020
|
||||||
|
#define OSAL_POLLRDNORM 0x0040
|
||||||
|
#define OSAL_POLLRDBAND 0x0080
|
||||||
|
#define OSAL_POLLWRNORM 0x0100
|
||||||
|
|
||||||
|
typedef struct osal_poll {
|
||||||
|
void *poll_table;
|
||||||
|
void *data;
|
||||||
|
} osal_poll_t;
|
||||||
|
|
||||||
|
typedef struct osal_fileops {
|
||||||
|
int (*open)(void *private_data);
|
||||||
|
int (*read)(char *buf, int size, long *offset, void *private_data);
|
||||||
|
int (*write)(const char *buf, int size, long *offset, void *private_data);
|
||||||
|
long (*llseek)(long offset, int whence, void *private_data);
|
||||||
|
int (*release)(void *private_data);
|
||||||
|
long (*unlocked_ioctl)(unsigned int cmd, unsigned long arg, void *private_data);
|
||||||
|
unsigned int (*poll)(osal_poll_t *osal_poll, void *private_data);
|
||||||
|
int (*mmap)(osal_vm_t *vm, unsigned long start, unsigned long end, unsigned long vm_pgoff, void *private_data);
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
long (*compat_ioctl)(unsigned int cmd, unsigned long arg, void *private_data);
|
||||||
|
#endif
|
||||||
|
} osal_fileops_t;
|
||||||
|
|
||||||
|
typedef struct osal_pmops {
|
||||||
|
int (*pm_prepare)(osal_dev_t *dev);
|
||||||
|
void (*pm_complete)(osal_dev_t *dev);
|
||||||
|
int (*pm_suspend)(osal_dev_t *dev);
|
||||||
|
int (*pm_resume)(osal_dev_t *dev);
|
||||||
|
int (*pm_freeze)(osal_dev_t *dev);
|
||||||
|
int (*pm_thaw)(osal_dev_t *dev);
|
||||||
|
int (*pm_poweroff)(osal_dev_t *dev);
|
||||||
|
int (*pm_restore)(osal_dev_t *dev);
|
||||||
|
int (*pm_suspend_late)(osal_dev_t *dev);
|
||||||
|
int (*pm_resume_early)(osal_dev_t *dev);
|
||||||
|
int (*pm_freeze_late)(osal_dev_t *dev);
|
||||||
|
int (*pm_thaw_early)(osal_dev_t *dev);
|
||||||
|
int (*pm_poweroff_late)(osal_dev_t *dev);
|
||||||
|
int (*pm_restore_early)(osal_dev_t *dev);
|
||||||
|
int (*pm_suspend_noirq)(osal_dev_t *dev);
|
||||||
|
int (*pm_resume_noirq)(osal_dev_t *dev);
|
||||||
|
int (*pm_freeze_noirq)(osal_dev_t *dev);
|
||||||
|
int (*pm_thaw_noirq)(osal_dev_t *dev);
|
||||||
|
int (*pm_poweroff_noirq)(osal_dev_t *dev);
|
||||||
|
int (*pm_restore_noirq)(osal_dev_t *dev);
|
||||||
|
} osal_pmops_t;
|
||||||
|
|
||||||
|
#define OSAL_SEEK_SET 0
|
||||||
|
#define OSAL_SEEK_CUR 1
|
||||||
|
#define OSAL_SEEK_END 2
|
||||||
|
|
||||||
|
// #define PAGE_SHIFT 12
|
||||||
|
|
||||||
|
extern osal_dev_t *osal_createdev(const char *name);
|
||||||
|
extern int osal_destroydev(osal_dev_t *pdev);
|
||||||
|
extern int osal_registerdevice(osal_dev_t *pdev);
|
||||||
|
extern void osal_deregisterdevice(osal_dev_t *pdev);
|
||||||
|
extern void osal_poll_wait(osal_poll_t *table, osal_wait_t *wait);
|
||||||
|
extern void osal_pgprot_noncached(osal_vm_t *vm);
|
||||||
|
extern void osal_pgprot_cached(osal_vm_t *vm);
|
||||||
|
extern void osal_pgprot_writecombine(osal_vm_t *vm);
|
||||||
|
extern void osal_pgprot_stronglyordered(osal_vm_t *vm);
|
||||||
|
extern int osal_remap_pfn_range(osal_vm_t *vm, unsigned long addr, unsigned long pfn, unsigned long size);
|
||||||
|
extern int osal_io_remap_pfn_range(osal_vm_t *vm, unsigned long addr, unsigned long pfn, unsigned long size);
|
||||||
|
|
||||||
|
// timer
|
||||||
|
typedef struct osal_timer {
|
||||||
|
void *timer;
|
||||||
|
void (*function)(unsigned long);
|
||||||
|
unsigned long data;
|
||||||
|
} osal_timer_t;
|
||||||
|
|
||||||
|
typedef struct osal_timeval {
|
||||||
|
long tv_sec;
|
||||||
|
long tv_usec;
|
||||||
|
} osal_timeval_t;
|
||||||
|
|
||||||
|
typedef struct osal_rtc_time {
|
||||||
|
int tm_sec;
|
||||||
|
int tm_min;
|
||||||
|
int tm_hour;
|
||||||
|
int tm_mday;
|
||||||
|
int tm_mon;
|
||||||
|
int tm_year;
|
||||||
|
int tm_wday;
|
||||||
|
int tm_yday;
|
||||||
|
int tm_isdst;
|
||||||
|
} osal_rtc_time_t;
|
||||||
|
|
||||||
|
/* Return values for the timer callback function */
|
||||||
|
typedef enum hiOSAL_HRTIMER_RESTART_E {
|
||||||
|
OSAL_HRTIMER_NORESTART, /* < The timer will not be restarted. */
|
||||||
|
OSAL_HRTIMER_RESTART /* < The timer must be restarted. */
|
||||||
|
} OSAL_HRTIMER_RESTART_E;
|
||||||
|
|
||||||
|
/* hrtimer struct */
|
||||||
|
typedef struct osal_hrtimer {
|
||||||
|
void *timer;
|
||||||
|
OSAL_HRTIMER_RESTART_E (*function)(void *timer);
|
||||||
|
unsigned long interval; /* Unit ms */
|
||||||
|
} osal_hrtimer_t;
|
||||||
|
|
||||||
|
extern int osal_hrtimer_create(osal_hrtimer_t *phrtimer);
|
||||||
|
extern int osal_hrtimer_start(osal_hrtimer_t *phrtimer);
|
||||||
|
extern int osal_hrtimer_destory(osal_hrtimer_t *phrtimer);
|
||||||
|
|
||||||
|
extern int osal_timer_init(osal_timer_t *timer);
|
||||||
|
extern int osal_set_timer(osal_timer_t *timer, unsigned long interval); // ms
|
||||||
|
extern int osal_del_timer(osal_timer_t *timer);
|
||||||
|
extern int osal_timer_destory(osal_timer_t *timer);
|
||||||
|
|
||||||
|
extern unsigned long osal_msleep(unsigned int msecs);
|
||||||
|
extern void osal_udelay(unsigned int usecs);
|
||||||
|
extern void osal_mdelay(unsigned int msecs);
|
||||||
|
|
||||||
|
extern unsigned int osal_get_tickcount(void);
|
||||||
|
extern unsigned long long osal_sched_clock(void);
|
||||||
|
extern void osal_gettimeofday(osal_timeval_t *tv);
|
||||||
|
extern void osal_rtc_time_to_tm(unsigned long time, osal_rtc_time_t *tm);
|
||||||
|
extern void osal_rtc_tm_to_time(osal_rtc_time_t *tm, unsigned long *time);
|
||||||
|
extern int osal_rtc_valid_tm(struct osal_rtc_time *tm);
|
||||||
|
extern void osal_getjiffies(unsigned long long *pjiffies);
|
||||||
|
|
||||||
|
#define OSAL_O_ACCMODE 00000003
|
||||||
|
#define OSAL_O_RDONLY 00000000
|
||||||
|
#define OSAL_O_WRONLY 00000001
|
||||||
|
#define OSAL_O_RDWR 00000002
|
||||||
|
#define OSAL_O_CREAT 00000100
|
||||||
|
|
||||||
|
extern void *osal_klib_fopen(const char *filename, int flags, int mode);
|
||||||
|
extern void osal_klib_fclose(void *filp);
|
||||||
|
extern int osal_klib_fwrite(const char *buf, int len, void *filp);
|
||||||
|
extern int osal_klib_fread(char *buf, unsigned int len, void *filp);
|
||||||
|
|
||||||
|
// reboot
|
||||||
|
struct osal_notifier_block {
|
||||||
|
int (*notifier_call)(struct osal_notifier_block *nb, unsigned long action, void *data);
|
||||||
|
void *notifier_block;
|
||||||
|
};
|
||||||
|
typedef int (*osal_notifier_fn_t)(struct osal_notifier_block *nb, unsigned long action, void *data);
|
||||||
|
|
||||||
|
extern int osal_register_reboot_notifier(struct osal_notifier_block *nb);
|
||||||
|
extern int osal_unregister_reboot_notifier(struct osal_notifier_block *nb);
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#ifndef _OSAL_VA_LIST
|
||||||
|
|
||||||
|
#define _OSAL_VA_LIST
|
||||||
|
#define osal_va_list va_list
|
||||||
|
#define osal_va_arg(ap, T) va_arg(ap, T)
|
||||||
|
#define osal_va_end(ap) va_end(ap)
|
||||||
|
#define osal_va_start(ap, A) va_start(ap, A)
|
||||||
|
|
||||||
|
#endif /* va_arg */
|
||||||
|
|
||||||
|
#define NULL_STRING "NULL"
|
||||||
|
|
||||||
|
extern void osal_vprintk(const char *fmt, osal_va_list args);
|
||||||
|
extern int osal_vsnprintf(char *str, int size, const char *fmt, osal_va_list args);
|
||||||
|
|
||||||
|
#ifdef CONFIG_HISI_SNAPSHOT_BOOT
|
||||||
|
|
||||||
|
#ifndef OSAL_UMH_WAIT_PROC
|
||||||
|
#define OSAL_UMH_WAIT_PROC 2 /* wait for the process to complete */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int osal_call_usermodehelper_force(char *path, char **argv, char **envp, int wait);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int osal_platform_driver_register(void *drv);
|
||||||
|
void osal_platform_driver_unregister(void *drv);
|
||||||
|
void *osal_platform_get_resource_byname(void *dev, unsigned int type,
|
||||||
|
const char *name);
|
||||||
|
void *osal_platform_get_resource(void *dev, unsigned int type,
|
||||||
|
unsigned int num);
|
||||||
|
int osal_platform_get_irq(void *dev, unsigned int num);
|
||||||
|
int osal_platform_get_irq_byname(void *dev, const char *name);
|
||||||
|
|
||||||
|
#define osal_module_driver(osal_driver, osal_register, osal_unregister, ...) \
|
||||||
|
static int __init osal_driver##_init(void) \
|
||||||
|
{ \
|
||||||
|
return osal_register(&(osal_driver)); \
|
||||||
|
} \
|
||||||
|
module_init(osal_driver##_init); \
|
||||||
|
static void __exit osal_driver##_exit(void) \
|
||||||
|
{ \
|
||||||
|
osal_unregister(&(osal_driver)); \
|
||||||
|
} \
|
||||||
|
module_exit(osal_driver##_exit);
|
||||||
|
|
||||||
|
#define osal_module_platform_driver(platform_driver) \
|
||||||
|
osal_module_driver(platform_driver, osal_platform_driver_register, \
|
||||||
|
osal_platform_driver_unregister)
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* copyright (c) hisilicon technologies co., ltd. 2016-2019. all rights reserved.
|
||||||
|
* description: hi_serdes.h
|
||||||
|
* author: hisilicon multimedia software group
|
||||||
|
* create: 2019-05-17
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __HI_SERDES_H__
|
||||||
|
#define __HI_SERDES_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#endif /*end of #ifdef __cplusplus*/
|
||||||
|
|
||||||
|
typedef unsigned int serdes_dev_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SERDES_MODE_4LANE_LINEAR = 0,
|
||||||
|
SERDES_MODE_4LANE_WDR,
|
||||||
|
SERDES_MODE_2LANE_LINEAR,
|
||||||
|
SERDES_MODE_2LANE_WDR,
|
||||||
|
|
||||||
|
SERDES_MODE_BUTT,
|
||||||
|
} serdes_mode_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
serdes_dev_t devno; /* I2C_DEV */
|
||||||
|
serdes_mode_t serdes_mode;
|
||||||
|
unsigned char sendes_en;
|
||||||
|
unsigned char sensor_i2c_addr; /* serdes connected sensor's i2c addr */
|
||||||
|
} serdes_dev_attr_t;
|
||||||
|
|
||||||
|
#define HI_SERDES_IOC_MAGIC 'n'
|
||||||
|
|
||||||
|
/* init data lane, input mode, data type */
|
||||||
|
#define HI_SERDES_START _IOW(HI_SERDES_IOC_MAGIC, 0x01, serdes_dev_attr_t)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /*end of #ifdef __cplusplus*/
|
||||||
|
|
||||||
|
#endif /*end of #ifdef __HI_SERDES_H__*/
|
|
@ -0,0 +1,106 @@
|
||||||
|
#ifndef _DRV_IOCTL_H
|
||||||
|
#define _DRV_IOCTL_H
|
||||||
|
|
||||||
|
/* ioctl command encoding: 32 bits total, command in lower 16 bits,
|
||||||
|
* size of the parameter structure in the lower 14 bits of the
|
||||||
|
* upper 16 bits.
|
||||||
|
* Encoding the size of the parameter structure in the ioctl request
|
||||||
|
* is useful for catching programs compiled with old versions
|
||||||
|
* and to avoid overwriting user space outside the user buffer area.
|
||||||
|
* The highest 2 bits are reserved for indicating the ``access mode''.
|
||||||
|
* NOTE: This limits the max parameter size to 16kB -1 !
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following is for compatibility across the various Linux
|
||||||
|
* platforms. The generic ioctl numbering scheme doesn't really enforce
|
||||||
|
* a type field. De facto, however, the top 8 bits of the lower 16
|
||||||
|
* bits are indeed used as a type field, so we might just as well make
|
||||||
|
* this explicit here. Please be sure to use the decoding macros
|
||||||
|
* below from now on.
|
||||||
|
*/
|
||||||
|
#define _IOC_NRBITS 8
|
||||||
|
#define _IOC_TYPEBITS 8
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let any architecture override either of the following before
|
||||||
|
* including this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _IOC_SIZEBITS
|
||||||
|
#define _IOC_SIZEBITS 14
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _IOC_DIRBITS
|
||||||
|
#define _IOC_DIRBITS 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)
|
||||||
|
#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1)
|
||||||
|
#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1)
|
||||||
|
#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1)
|
||||||
|
|
||||||
|
#define _IOC_NRSHIFT 0
|
||||||
|
#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
|
||||||
|
#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
|
||||||
|
#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Direction bits, which any architecture can choose to override
|
||||||
|
* before including this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _IOC_NONE
|
||||||
|
#define _IOC_NONE 0U
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _IOC_WRITE
|
||||||
|
#define _IOC_WRITE 1U
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _IOC_READ
|
||||||
|
#define _IOC_READ 2U
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _IOC(dir, type, nr, size) \
|
||||||
|
(((dir) << _IOC_DIRSHIFT) | \
|
||||||
|
((type) << _IOC_TYPESHIFT) | \
|
||||||
|
((nr) << _IOC_NRSHIFT) | \
|
||||||
|
((size) << _IOC_SIZESHIFT))
|
||||||
|
|
||||||
|
// #define _IOC_TYPECHECK(t) (sizeof(t))
|
||||||
|
|
||||||
|
#ifdef __CHECKER__
|
||||||
|
#define _IOC_TYPECHECK(t) (sizeof(t))
|
||||||
|
#else
|
||||||
|
/* provoke compile error for invalid uses of size argument */
|
||||||
|
extern unsigned int __invalid_size_argument_for_IOC;
|
||||||
|
#define _IOC_TYPECHECK(t) \
|
||||||
|
((sizeof(t) == sizeof(t[1]) && \
|
||||||
|
sizeof(t) < (1 << _IOC_SIZEBITS)) \
|
||||||
|
? sizeof(t) \
|
||||||
|
: __invalid_size_argument_for_IOC)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* used to create numbers */
|
||||||
|
#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
|
||||||
|
#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
|
||||||
|
#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
|
||||||
|
#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
|
||||||
|
#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
|
||||||
|
#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
|
||||||
|
#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
|
||||||
|
|
||||||
|
/* used to decode ioctl numbers.. */
|
||||||
|
#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
|
||||||
|
#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
|
||||||
|
#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
|
||||||
|
#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
|
||||||
|
|
||||||
|
#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)
|
||||||
|
#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)
|
||||||
|
#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
|
||||||
|
#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)
|
||||||
|
#define IOCSIZE_SHIFT (_IOC_SIZESHIFT)
|
||||||
|
|
||||||
|
#endif /* _DRV_IOCTL_H */
|
|
@ -0,0 +1,742 @@
|
||||||
|
#ifndef _OSAL_LIST_H
|
||||||
|
#define _OSAL_LIST_H
|
||||||
|
|
||||||
|
#define OSAL_NULL (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simple doubly linked list implementation.
|
||||||
|
*
|
||||||
|
* Some of the internal functions ("__xxx") are useful when
|
||||||
|
* manipulating whole lists rather than single entries, as
|
||||||
|
* sometimes we already know the next/prev entries and we can
|
||||||
|
* generate better code by using them directly rather than
|
||||||
|
* using the generic single-entry routines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct osal_list_head {
|
||||||
|
struct osal_list_head *next, *prev;
|
||||||
|
};
|
||||||
|
#define OSAL_LIST_HEAD_INIT(name) \
|
||||||
|
{ \
|
||||||
|
&(name), &(name) \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OSAL_LIST_HEAD(name) \
|
||||||
|
struct osal_list_head name = OSAL_LIST_HEAD_INIT(name)
|
||||||
|
|
||||||
|
static inline void OSAL_INIT_LIST_HEAD(struct osal_list_head *list)
|
||||||
|
{
|
||||||
|
list->next = list;
|
||||||
|
list->prev = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Insert a new entry between two known consecutive entries.
|
||||||
|
*
|
||||||
|
* This is only for internal list manipulation where we know
|
||||||
|
* the prev/next entries already!
|
||||||
|
*/
|
||||||
|
static inline void osal___list_add(struct osal_list_head *new,
|
||||||
|
struct osal_list_head *prev,
|
||||||
|
struct osal_list_head *next)
|
||||||
|
{
|
||||||
|
next->prev = new;
|
||||||
|
new->next = next;
|
||||||
|
new->prev = prev;
|
||||||
|
prev->next = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_add - add a new entry
|
||||||
|
* @new: new entry to be added
|
||||||
|
* @head: list head to add it after
|
||||||
|
*
|
||||||
|
* Insert a new entry after the specified head.
|
||||||
|
* This is good for implementing stacks.
|
||||||
|
*/
|
||||||
|
static inline void osal_list_add(struct osal_list_head *new, struct osal_list_head *head)
|
||||||
|
{
|
||||||
|
osal___list_add(new, head, head->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_add_tail - add a new entry
|
||||||
|
* @new: new entry to be added
|
||||||
|
* @head: list head to add it before
|
||||||
|
*
|
||||||
|
* Insert a new entry before the specified head.
|
||||||
|
* This is useful for implementing queues.
|
||||||
|
*/
|
||||||
|
static inline void osal_list_add_tail(struct osal_list_head *new, struct osal_list_head *head)
|
||||||
|
{
|
||||||
|
osal___list_add(new, head->prev, head);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete a list entry by making the prev/next entries
|
||||||
|
* point to each other.
|
||||||
|
*
|
||||||
|
* This is only for internal list manipulation where we know
|
||||||
|
* the prev/next entries already!
|
||||||
|
*/
|
||||||
|
static inline void osal___list_del(struct osal_list_head *prev, struct osal_list_head *next)
|
||||||
|
{
|
||||||
|
next->prev = prev;
|
||||||
|
prev->next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_del - deletes entry from list.
|
||||||
|
* @entry: the element to delete from the list.
|
||||||
|
* Note: list_empty() on entry does not return true after this, the entry is
|
||||||
|
* in an undefined state.
|
||||||
|
*/
|
||||||
|
static inline void osal___list_del_entry(struct osal_list_head *entry)
|
||||||
|
{
|
||||||
|
osal___list_del(entry->prev, entry->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OSAL_LIST_POISON1 ((void *)0x00100100)
|
||||||
|
#define OSAL_LIST_POISON2 ((void *)0x00200200)
|
||||||
|
|
||||||
|
static inline void osal_list_del(struct osal_list_head *entry)
|
||||||
|
{
|
||||||
|
osal___list_del(entry->prev, entry->next);
|
||||||
|
entry->next = OSAL_LIST_POISON1;
|
||||||
|
entry->prev = OSAL_LIST_POISON2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_replace - replace old entry by new one
|
||||||
|
* @old : the element to be replaced
|
||||||
|
* @new : the new element to insert
|
||||||
|
*
|
||||||
|
* If @old was empty, it will be overwritten.
|
||||||
|
*/
|
||||||
|
static inline void osal_list_replace(struct osal_list_head *old,
|
||||||
|
struct osal_list_head *new)
|
||||||
|
{
|
||||||
|
new->next = old->next;
|
||||||
|
new->next->prev = new;
|
||||||
|
new->prev = old->prev;
|
||||||
|
new->prev->next = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void osal_list_replace_init(struct osal_list_head *old,
|
||||||
|
struct osal_list_head *new)
|
||||||
|
{
|
||||||
|
osal_list_replace(old, new);
|
||||||
|
OSAL_INIT_LIST_HEAD(old);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_del_init - deletes entry from list and reinitialize it.
|
||||||
|
* @entry: the element to delete from the list.
|
||||||
|
*/
|
||||||
|
static inline void osal_list_del_init(struct osal_list_head *entry)
|
||||||
|
{
|
||||||
|
osal___list_del_entry(entry);
|
||||||
|
OSAL_INIT_LIST_HEAD(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_move - delete from one list and add as another's head
|
||||||
|
* @list: the entry to move
|
||||||
|
* @head: the head that will precede our entry
|
||||||
|
*/
|
||||||
|
static inline void osal_list_move(struct osal_list_head *list, struct osal_list_head *head)
|
||||||
|
{
|
||||||
|
osal___list_del_entry(list);
|
||||||
|
osal_list_add(list, head);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_move_tail - delete from one list and add as another's tail
|
||||||
|
* @list: the entry to move
|
||||||
|
* @head: the head that will follow our entry
|
||||||
|
*/
|
||||||
|
static inline void osal_list_move_tail(struct osal_list_head *list,
|
||||||
|
struct osal_list_head *head)
|
||||||
|
{
|
||||||
|
osal___list_del_entry(list);
|
||||||
|
osal_list_add_tail(list, head);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_is_last - tests whether @list is the last entry in list @head
|
||||||
|
* @list: the entry to test
|
||||||
|
* @head: the head of the list
|
||||||
|
*/
|
||||||
|
static inline int osal_list_is_last(const struct osal_list_head *list,
|
||||||
|
const struct osal_list_head *head)
|
||||||
|
{
|
||||||
|
return list->next == head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_empty - tests whether a list is empty
|
||||||
|
* @head: the list to test.
|
||||||
|
*/
|
||||||
|
static inline int osal_list_empty(const struct osal_list_head *head)
|
||||||
|
{
|
||||||
|
return head->next == head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_empty_careful - tests whether a list is empty and not being modified
|
||||||
|
* @head: the list to test
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* tests whether a list is empty _and_ checks that no other CPU might be
|
||||||
|
* in the process of modifying either member (next or prev)
|
||||||
|
*
|
||||||
|
* NOTE: using list_empty_careful() without synchronization
|
||||||
|
* can only be safe if the only activity that can happen
|
||||||
|
* to the list entry is list_del_init(). Eg. it cannot be used
|
||||||
|
* if another CPU could re-list_add() it.
|
||||||
|
*/
|
||||||
|
static inline int osal_list_empty_careful(const struct osal_list_head *head)
|
||||||
|
{
|
||||||
|
struct osal_list_head *next = head->next;
|
||||||
|
return (next == head) && (next == head->prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_rotate_left - rotate the list to the left
|
||||||
|
* @head: the head of the list
|
||||||
|
*/
|
||||||
|
static inline void osal_list_rotate_left(struct osal_list_head *head)
|
||||||
|
{
|
||||||
|
struct osal_list_head *first;
|
||||||
|
|
||||||
|
if (!osal_list_empty(head)) {
|
||||||
|
first = head->next;
|
||||||
|
osal_list_move_tail(first, head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_is_singular - tests whether a list has just one entry.
|
||||||
|
* @head: the list to test.
|
||||||
|
*/
|
||||||
|
static inline int osal_list_is_singular(const struct osal_list_head *head)
|
||||||
|
{
|
||||||
|
return !osal_list_empty(head) && (head->next == head->prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void osal___list_cut_position(struct osal_list_head *list,
|
||||||
|
struct osal_list_head *head, struct osal_list_head *entry)
|
||||||
|
{
|
||||||
|
struct osal_list_head *new_first = entry->next;
|
||||||
|
list->next = head->next;
|
||||||
|
list->next->prev = list;
|
||||||
|
list->prev = entry;
|
||||||
|
entry->next = list;
|
||||||
|
head->next = new_first;
|
||||||
|
new_first->prev = head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_cut_position - cut a list into two
|
||||||
|
* @list: a new list to add all removed entries
|
||||||
|
* @head: a list with entries
|
||||||
|
* @entry: an entry within head, could be the head itself
|
||||||
|
* and if so we won't cut the list
|
||||||
|
*
|
||||||
|
* This helper moves the initial part of @head, up to and
|
||||||
|
* including @entry, from @head to @list. You should
|
||||||
|
* pass on @entry an element you know is on @head. @list
|
||||||
|
* should be an empty list or a list you do not care about
|
||||||
|
* losing its data.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static inline void osal_list_cut_position(struct osal_list_head *list,
|
||||||
|
struct osal_list_head *head, struct osal_list_head *entry)
|
||||||
|
{
|
||||||
|
if (osal_list_empty(head)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (osal_list_is_singular(head) &&
|
||||||
|
((head->next != entry) && (head != entry))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (entry == head) {
|
||||||
|
OSAL_INIT_LIST_HEAD(list);
|
||||||
|
} else {
|
||||||
|
osal___list_cut_position(list, head, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void osal___list_splice(const struct osal_list_head *list,
|
||||||
|
struct osal_list_head *prev,
|
||||||
|
struct osal_list_head *next)
|
||||||
|
{
|
||||||
|
struct osal_list_head *first = list->next;
|
||||||
|
struct osal_list_head *last = list->prev;
|
||||||
|
|
||||||
|
first->prev = prev;
|
||||||
|
prev->next = first;
|
||||||
|
|
||||||
|
last->next = next;
|
||||||
|
next->prev = last;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_splice - join two lists, this is designed for stacks
|
||||||
|
* @list: the new list to add.
|
||||||
|
* @head: the place to add it in the first list.
|
||||||
|
*/
|
||||||
|
static inline void osal_list_splice(const struct osal_list_head *list,
|
||||||
|
struct osal_list_head *head)
|
||||||
|
{
|
||||||
|
if (!osal_list_empty(list)) {
|
||||||
|
osal___list_splice(list, head, head->next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_splice_tail - join two lists, each list being a queue
|
||||||
|
* @list: the new list to add.
|
||||||
|
* @head: the place to add it in the first list.
|
||||||
|
*/
|
||||||
|
static inline void osal_list_splice_tail(struct osal_list_head *list,
|
||||||
|
struct osal_list_head *head)
|
||||||
|
{
|
||||||
|
if (!osal_list_empty(list)) {
|
||||||
|
osal___list_splice(list, head->prev, head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_splice_init - join two lists and reinitialise the emptied list.
|
||||||
|
* @list: the new list to add.
|
||||||
|
* @head: the place to add it in the first list.
|
||||||
|
*
|
||||||
|
* The list at @list is reinitialised
|
||||||
|
*/
|
||||||
|
static inline void osal_list_splice_init(struct osal_list_head *list,
|
||||||
|
struct osal_list_head *head)
|
||||||
|
{
|
||||||
|
if (!osal_list_empty(list)) {
|
||||||
|
osal___list_splice(list, head, head->next);
|
||||||
|
OSAL_INIT_LIST_HEAD(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_splice_tail_init - join two lists and reinitialise the emptied list
|
||||||
|
* @list: the new list to add.
|
||||||
|
* @head: the place to add it in the first list.
|
||||||
|
*
|
||||||
|
* Each of the lists is a queue.
|
||||||
|
* The list at @list is reinitialised
|
||||||
|
*/
|
||||||
|
static inline void osal_list_splice_tail_init(struct osal_list_head *list,
|
||||||
|
struct osal_list_head *head)
|
||||||
|
{
|
||||||
|
if (!osal_list_empty(list)) {
|
||||||
|
osal___list_splice(list, head->prev, head);
|
||||||
|
OSAL_INIT_LIST_HEAD(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef osal_offsetof
|
||||||
|
#ifdef __compiler_offsetof
|
||||||
|
#define osal_offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE, MEMBER)
|
||||||
|
#else
|
||||||
|
#define osal_offsetof(TYPE, MEMBER) ((int)(unsigned long)&((TYPE *)0)->MEMBER)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define osal_container_of(ptr, type, member) ({ \
|
||||||
|
const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
|
||||||
|
(type *)( (char *)__mptr - osal_offsetof(type,member) ); })
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_entry - get the struct for this entry
|
||||||
|
* @ptr: the &struct list_head pointer.
|
||||||
|
* @type: the type of the struct this is embedded in.
|
||||||
|
* @member: the name of the list_struct within the struct.
|
||||||
|
*/
|
||||||
|
#define osal_list_entry(ptr, type, member) \
|
||||||
|
osal_container_of(ptr, type, member)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_first_entry - get the first element from a list
|
||||||
|
* @ptr: the list head to take the element from.
|
||||||
|
* @type: the type of the struct this is embedded in.
|
||||||
|
* @member: the name of the list_struct within the struct.
|
||||||
|
*
|
||||||
|
* Note, that list is expected to be not empty.
|
||||||
|
*/
|
||||||
|
#define osal_list_first_entry(ptr, type, member) \
|
||||||
|
osal_list_entry((ptr)->next, type, member)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each - iterate over a list
|
||||||
|
* @pos: the &struct list_head to use as a loop cursor.
|
||||||
|
* @head: the head for your list.
|
||||||
|
*/
|
||||||
|
#define osal_list_for_each(pos, head) \
|
||||||
|
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __list_for_each - iterate over a list
|
||||||
|
* @pos: the &struct list_head to use as a loop cursor.
|
||||||
|
* @head: the head for your list.
|
||||||
|
*
|
||||||
|
* This variant doesn't differ from list_for_each() any more.
|
||||||
|
* We don't do prefetching in either case.
|
||||||
|
*/
|
||||||
|
#define osal___list_for_each(pos, head) \
|
||||||
|
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_prev - iterate over a list backwards
|
||||||
|
* @pos: the &struct list_head to use as a loop cursor.
|
||||||
|
* @head: the head for your list.
|
||||||
|
*/
|
||||||
|
#define osal_list_for_each_prev(pos, head) \
|
||||||
|
for (pos = (head)->prev; pos != (head); pos = pos->prev)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_safe - iterate over a list safe against removal of list entry
|
||||||
|
* @pos: the &struct list_head to use as a loop cursor.
|
||||||
|
* @n: another &struct list_head to use as temporary storage
|
||||||
|
* @head: the head for your list.
|
||||||
|
*/
|
||||||
|
#define osal_list_for_each_safe(pos, n, head) \
|
||||||
|
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||||
|
pos = n, n = pos->next)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
|
||||||
|
* @pos: the &struct list_head to use as a loop cursor.
|
||||||
|
* @n: another &struct list_head to use as temporary storage
|
||||||
|
* @head: the head for your list.
|
||||||
|
*/
|
||||||
|
#define osal_list_for_each_prev_safe(pos, n, head) \
|
||||||
|
for (pos = (head)->prev, n = pos->prev; \
|
||||||
|
pos != (head); \
|
||||||
|
pos = n, n = pos->prev)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry - iterate over list of given type
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_struct within the struct.
|
||||||
|
*/
|
||||||
|
#define osal_list_for_each_entry(pos, head, member) \
|
||||||
|
for (pos = osal_list_entry((head)->next, __typeof__(*pos), member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = osal_list_entry(pos->member.next, __typeof__(*pos), member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry_reverse - iterate backwards over list of given type.
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_struct within the struct.
|
||||||
|
*/
|
||||||
|
#define osal_list_for_each_entry_reverse(pos, head, member) \
|
||||||
|
for (pos = osal_list_entry((head)->prev, __typeof__(*pos), member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = osal_list_entry(pos->member.prev, __typeof__(*pos), member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
|
||||||
|
* @pos: the type * to use as a start point
|
||||||
|
* @head: the head of the list
|
||||||
|
* @member: the name of the list_struct within the struct.
|
||||||
|
*
|
||||||
|
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
|
||||||
|
*/
|
||||||
|
#define osal_list_prepare_entry(pos, head, member) \
|
||||||
|
((pos) ?: osal_list_entry(head, __typeof__(*pos), member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry_continue - continue iteration over list of given type
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_struct within the struct.
|
||||||
|
*
|
||||||
|
* Continue to iterate over list of given type, continuing after
|
||||||
|
* the current position.
|
||||||
|
*/
|
||||||
|
#define osal_list_for_each_entry_continue(pos, head, member) \
|
||||||
|
for (pos = osal_list_entry(pos->member.next, __typeof__(*pos), member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = osal_list_entry(pos->member.next, __typeof__(*pos), member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry_continue_reverse - iterate backwards from the given point
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_struct within the struct.
|
||||||
|
*
|
||||||
|
* Start to iterate over list of given type backwards, continuing after
|
||||||
|
* the current position.
|
||||||
|
*/
|
||||||
|
#define osal_list_for_each_entry_continue_reverse(pos, head, member) \
|
||||||
|
for (pos = osal_list_entry(pos->member.prev, __typeof__(*pos), member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = osal_list_entry(pos->member.prev, __typeof__(*pos), member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry_from - iterate over list of given type from the current point
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_struct within the struct.
|
||||||
|
*
|
||||||
|
* Iterate over list of given type, continuing from current position.
|
||||||
|
*/
|
||||||
|
#define osal_list_for_each_entry_from(pos, head, member) \
|
||||||
|
for (; &pos->member != (head); \
|
||||||
|
pos = osal_list_entry(pos->member.next, __typeof__(*pos), member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @n: another type * to use as temporary storage
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_struct within the struct.
|
||||||
|
*/
|
||||||
|
#define osal_list_for_each_entry_safe(pos, n, head, member) \
|
||||||
|
for (pos = osal_list_entry((head)->next, __typeof__(*pos), member), \
|
||||||
|
n = osal_list_entry(pos->member.next, __typeof__(*pos), member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = n, n = osal_list_entry(n->member.next, __typeof__(*n), member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry_safe_continue - continue list iteration safe against removal
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @n: another type * to use as temporary storage
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_struct within the struct.
|
||||||
|
*
|
||||||
|
* Iterate over list of given type, continuing after current point,
|
||||||
|
* safe against removal of list entry.
|
||||||
|
*/
|
||||||
|
#define osal_list_for_each_entry_safe_continue(pos, n, head, member) \
|
||||||
|
for (pos = osal_list_entry(pos->member.next, __typeof__(*pos), member), \
|
||||||
|
n = osal_list_entry(pos->member.next, __typeof__(*pos), member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = n, n = osal_list_entry(n->member.next, __typeof__(*n), member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry_safe_from - iterate over list from current point safe against removal
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @n: another type * to use as temporary storage
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_struct within the struct.
|
||||||
|
*
|
||||||
|
* Iterate over list of given type from current point, safe against
|
||||||
|
* removal of list entry.
|
||||||
|
*/
|
||||||
|
#define osal_list_for_each_entry_safe_from(pos, n, head, member) \
|
||||||
|
for (n = osal_list_entry(pos->member.next, __typeof__(*pos), member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = n, n = osal_list_entry(n->member.next, __typeof__(*n), member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @n: another type * to use as temporary storage
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_struct within the struct.
|
||||||
|
*
|
||||||
|
* Iterate backwards over list of given type, safe against removal
|
||||||
|
* of list entry.
|
||||||
|
*/
|
||||||
|
#define osal_list_for_each_entry_safe_reverse(pos, n, head, member) \
|
||||||
|
for (pos = osal_list_entry((head)->prev, __typeof__(*pos), member), \
|
||||||
|
n = osal_list_entry(pos->member.prev, __typeof__(*pos), member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = n, n = osal_list_entry(n->member.prev, __typeof__(*n), member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_safe_reset_next - reset a stale list_for_each_entry_safe loop
|
||||||
|
* @pos: the loop cursor used in the list_for_each_entry_safe loop
|
||||||
|
* @n: temporary storage used in list_for_each_entry_safe
|
||||||
|
* @member: the name of the list_struct within the struct.
|
||||||
|
*
|
||||||
|
* list_safe_reset_next is not safe to use in general if the list may be
|
||||||
|
* modified concurrently (eg. the lock is dropped in the loop body). An
|
||||||
|
* exception to this is if the cursor element (pos) is pinned in the list,
|
||||||
|
* and list_safe_reset_next is called after re-taking the lock and before
|
||||||
|
* completing the current iteration of the loop body.
|
||||||
|
*/
|
||||||
|
#define osal_list_safe_reset_next(pos, n, member) \
|
||||||
|
n = osal_list_entry(pos->member.next, __typeof__(*pos), member)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Double linked lists with a single pointer list head.
|
||||||
|
* Mostly useful for hash tables where the two pointer list head is
|
||||||
|
* too wasteful.
|
||||||
|
* You lose the ability to access the tail in O(1).
|
||||||
|
*/
|
||||||
|
struct osal_hlist_node {
|
||||||
|
struct osal_hlist_node *next, **pprev;
|
||||||
|
};
|
||||||
|
struct osal_hlist_head {
|
||||||
|
struct osal_hlist_node *first;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define OSAL_HLIST_HEAD_INIT \
|
||||||
|
{ \
|
||||||
|
.first = OSAL_NULL \
|
||||||
|
}
|
||||||
|
#define OSAL_HLIST_HEAD(name) struct osal_hlist_head name = { .first = OSAL_NULL }
|
||||||
|
#define INIT_OSAL_HLIST_HEAD(ptr) ((ptr)->first = OSAL_NULL)
|
||||||
|
static inline void INIT_OSAL_HLIST_NODE(struct osal_hlist_node *h)
|
||||||
|
{
|
||||||
|
h->next = OSAL_NULL;
|
||||||
|
h->pprev = OSAL_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int osal_hlist_unhashed(const struct osal_hlist_node *h)
|
||||||
|
{
|
||||||
|
return !h->pprev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int osal_hlist_empty(const struct osal_hlist_head *h)
|
||||||
|
{
|
||||||
|
return !h->first;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void osal___hlist_del(struct osal_hlist_node *n)
|
||||||
|
{
|
||||||
|
struct osal_hlist_node *next = n->next;
|
||||||
|
struct osal_hlist_node **pprev = n->pprev;
|
||||||
|
*pprev = next;
|
||||||
|
if (next) {
|
||||||
|
next->pprev = pprev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void osal_hlist_del(struct osal_hlist_node *n)
|
||||||
|
{
|
||||||
|
osal___hlist_del(n);
|
||||||
|
n->next = OSAL_LIST_POISON1;
|
||||||
|
n->pprev = OSAL_LIST_POISON2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void osal_hlist_del_init(struct osal_hlist_node *n)
|
||||||
|
{
|
||||||
|
if (!osal_hlist_unhashed(n)) {
|
||||||
|
osal___hlist_del(n);
|
||||||
|
INIT_OSAL_HLIST_NODE(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void osal_hlist_add_head(struct osal_hlist_node *n, struct osal_hlist_head *h)
|
||||||
|
{
|
||||||
|
struct osal_hlist_node *first = h->first;
|
||||||
|
n->next = first;
|
||||||
|
if (first) {
|
||||||
|
first->pprev = &n->next;
|
||||||
|
}
|
||||||
|
h->first = n;
|
||||||
|
n->pprev = &h->first;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* next must be != NULL */
|
||||||
|
static inline void osal_hlist_add_before(struct osal_hlist_node *n,
|
||||||
|
struct osal_hlist_node *next)
|
||||||
|
{
|
||||||
|
n->pprev = next->pprev;
|
||||||
|
n->next = next;
|
||||||
|
next->pprev = &n->next;
|
||||||
|
*(n->pprev) = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void osal_hlist_add_after(struct osal_hlist_node *n,
|
||||||
|
struct osal_hlist_node *next)
|
||||||
|
{
|
||||||
|
next->next = n->next;
|
||||||
|
n->next = next;
|
||||||
|
next->pprev = &n->next;
|
||||||
|
|
||||||
|
if (next->next) {
|
||||||
|
next->next->pprev = &next->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* after that we'll appear to be on some hlist and hlist_del will work */
|
||||||
|
static inline void osal_hlist_add_fake(struct osal_hlist_node *n)
|
||||||
|
{
|
||||||
|
n->pprev = &n->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Move a list from one list head to another. Fixup the pprev
|
||||||
|
* reference of the first entry if it exists.
|
||||||
|
*/
|
||||||
|
static inline void osal_hlist_move_list(struct osal_hlist_head *old,
|
||||||
|
struct osal_hlist_head *new)
|
||||||
|
{
|
||||||
|
new->first = old->first;
|
||||||
|
if (new->first) {
|
||||||
|
new->first->pprev = &new->first;
|
||||||
|
}
|
||||||
|
old->first = OSAL_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define osal_hlist_entry(ptr, type, member) osal_container_of(ptr, type, member)
|
||||||
|
|
||||||
|
#define osal_hlist_for_each(pos, head) \
|
||||||
|
for (pos = (head)->first; pos; pos = pos->next)
|
||||||
|
|
||||||
|
#define osal_hlist_for_each_safe(pos, n, head) \
|
||||||
|
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
|
||||||
|
pos = n)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hlist_for_each_entry - iterate over list of given type
|
||||||
|
* @tpos: the type * to use as a loop cursor.
|
||||||
|
* @pos: the &struct hlist_node to use as a loop cursor.
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the hlist_node within the struct.
|
||||||
|
*/
|
||||||
|
#define osal_hlist_for_each_entry(tpos, pos, head, member) \
|
||||||
|
for (pos = (head)->first; \
|
||||||
|
pos && \
|
||||||
|
({ tpos = osal_hlist_entry(pos, __typeof__(*tpos), member); 1; }); \
|
||||||
|
pos = pos->next)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point
|
||||||
|
* @tpos: the type * to use as a loop cursor.
|
||||||
|
* @pos: the &struct hlist_node to use as a loop cursor.
|
||||||
|
* @member: the name of the hlist_node within the struct.
|
||||||
|
*/
|
||||||
|
#define osal_hlist_for_each_entry_continue(tpos, pos, member) \
|
||||||
|
for (pos = (pos)->next; \
|
||||||
|
pos && \
|
||||||
|
({ tpos = osal_hlist_entry(pos, __typeof__(*tpos), member); 1; }); \
|
||||||
|
pos = pos->next)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hlist_for_each_entry_from - iterate over a hlist continuing from current point
|
||||||
|
* @tpos: the type * to use as a loop cursor.
|
||||||
|
* @pos: the &struct hlist_node to use as a loop cursor.
|
||||||
|
* @member: the name of the hlist_node within the struct.
|
||||||
|
*/
|
||||||
|
#define osal_hlist_for_each_entry_from(tpos, pos, member) \
|
||||||
|
for (; pos && \
|
||||||
|
({ tpos = osal_hlist_entry(pos, __typeof__(*tpos), member); 1; }); \
|
||||||
|
pos = pos->next)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||||
|
* @tpos: the type * to use as a loop cursor.
|
||||||
|
* @pos: the &struct hlist_node to use as a loop cursor.
|
||||||
|
* @n: another &struct hlist_node to use as temporary storage
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the hlist_node within the struct.
|
||||||
|
*/
|
||||||
|
#define osal_hlist_for_each_entry_safe(tpos, pos, n, head, member) \
|
||||||
|
for (pos = (head)->first; \
|
||||||
|
pos && ({ n = pos->next; 1; }) && \
|
||||||
|
({ tpos = osal_hlist_entry(pos, __typeof__(*tpos), member); 1; }); \
|
||||||
|
pos = n)
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* copyright (c) hisilicon technologies co., ltd. 2016-2019. all rights reserved.
|
||||||
|
* description: type.h
|
||||||
|
* author: hisilicon multimedia software group
|
||||||
|
* create: 2019-05-17
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TYPE_H__
|
||||||
|
#define __TYPE_H__
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/*----------------------------------------------*
|
||||||
|
* const defination *
|
||||||
|
*----------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL 0L
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HI_FALSE
|
||||||
|
#define HI_FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HI_TRUE
|
||||||
|
#define HI_TRUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HI_SUCCESS
|
||||||
|
#define HI_SUCCESS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HI_FAILURE
|
||||||
|
#define HI_FAILURE (-1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef unsigned char HI_U8;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* __TYPE_H__ */
|
||||||
|
|
|
@ -0,0 +1,378 @@
|
||||||
|
/*
|
||||||
|
* copyright (c) hisilicon technologies co., ltd. 2016-2019. all rights reserved.
|
||||||
|
* description: serdes_comm.c
|
||||||
|
* author: hisilicon multimedia software group
|
||||||
|
* create: 2019-05-17
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <asm/uaccess.h>
|
||||||
|
#ifndef __HuaweiLite__
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of_platform.h>
|
||||||
|
#include <linux/miscdevice.h>
|
||||||
|
#else
|
||||||
|
#include "i2c.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "hi_serdes.h"
|
||||||
|
#include "serdes_comm.h"
|
||||||
|
#include "type.h"
|
||||||
|
|
||||||
|
#define SERDES_DEV_NAME0 "serdes0"
|
||||||
|
#define SERDES_DEV_NAME1 "serdes1"
|
||||||
|
#define SERDES_I2C_BUF_MAX_NUM 8
|
||||||
|
#define ONT_BYTE_EQUAL_BIT_NUM 8
|
||||||
|
|
||||||
|
unsigned char sensor_dev_addr[SERDES_MAX_NUM] = {0};
|
||||||
|
unsigned char serdes_init_flag[SERDES_MAX_NUM] = {0};
|
||||||
|
static struct i2c_client *g_serdes_client[SERDES_MAX_NUM];
|
||||||
|
|
||||||
|
#ifndef __HuaweiLite__
|
||||||
|
static struct i2c_board_info g_thine_info =
|
||||||
|
{
|
||||||
|
I2C_BOARD_INFO(THINE_DEVICE_TYPE, (THINE_DEVICE_ADDR >> 1)),
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int serdes_i2c_write(unsigned char i2c_dev, unsigned char dev_addr,
|
||||||
|
unsigned int reg_addr, unsigned int reg_addr_num,
|
||||||
|
unsigned int data, unsigned int data_byte_num)
|
||||||
|
{
|
||||||
|
unsigned char tmp_buf[SERDES_I2C_BUF_MAX_NUM];
|
||||||
|
int ret = 0;
|
||||||
|
int idx = 0;
|
||||||
|
unsigned int try_count = 0;
|
||||||
|
struct i2c_client client;
|
||||||
|
|
||||||
|
if (i2c_dev >= SERDES_MAX_NUM) {
|
||||||
|
return HI_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_serdes_client[i2c_dev] == NULL) {
|
||||||
|
return HI_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
osal_memcpy(&client, g_serdes_client[i2c_dev], sizeof(struct i2c_client));
|
||||||
|
|
||||||
|
#ifdef __HuaweiLite__
|
||||||
|
client.addr = ((dev_addr >> 1) & 0xff);
|
||||||
|
|
||||||
|
/* reg_addr config */
|
||||||
|
if (reg_addr_num == 1) {
|
||||||
|
client.flags &= ~I2C_M_16BIT_REG;
|
||||||
|
tmp_buf[idx++] = reg_addr & 0xff;
|
||||||
|
} else {
|
||||||
|
client.flags |= I2C_M_16BIT_REG;
|
||||||
|
tmp_buf[idx++] = (reg_addr >> ONT_BYTE_EQUAL_BIT_NUM) & 0xff;
|
||||||
|
tmp_buf[idx++] = reg_addr & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* data config */
|
||||||
|
if (data_byte_num == 1) {
|
||||||
|
client.flags &= ~I2C_M_16BIT_DATA;
|
||||||
|
tmp_buf[idx++] = data & 0xff;
|
||||||
|
} else {
|
||||||
|
client.flags |= I2C_M_16BIT_DATA;
|
||||||
|
tmp_buf[idx++] = (data >> ONT_BYTE_EQUAL_BIT_NUM) & 0xff;
|
||||||
|
tmp_buf[idx++] = data & 0xff;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
client.addr = (dev_addr >> 1);
|
||||||
|
|
||||||
|
/* reg_addr config */
|
||||||
|
if (reg_addr_num == 1) {
|
||||||
|
tmp_buf[idx++] = reg_addr & 0xff;
|
||||||
|
} else {
|
||||||
|
tmp_buf[idx++] = (reg_addr >> ONT_BYTE_EQUAL_BIT_NUM) & 0xff;
|
||||||
|
tmp_buf[idx++] = reg_addr & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* data config */
|
||||||
|
if (data_byte_num == 1) {
|
||||||
|
tmp_buf[idx++] = data & 0xff;
|
||||||
|
} else {
|
||||||
|
tmp_buf[idx++] = (data >> ONT_BYTE_EQUAL_BIT_NUM) & 0xff;
|
||||||
|
tmp_buf[idx++] = data & 0xff;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
ret = hi_i2c_master_send(&client, (const char *)tmp_buf, idx);
|
||||||
|
if (ret == idx) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifdef __HuaweiLite__
|
||||||
|
else if ((ret == -EAGAIN))
|
||||||
|
#else
|
||||||
|
else if ((ret == -EAGAIN) && (in_atomic() || irqs_disabled()))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
try_count++;
|
||||||
|
if (try_count > 5) {
|
||||||
|
return HI_FAILURE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
osal_printk("[%s %d] hi_i2c_master_send error, reg_addr=0x%x, ret=%d.\n", __func__, __LINE__, reg_addr, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return HI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int serdes_i2c_read(unsigned char i2c_dev, const unsigned char dev_addr,
|
||||||
|
const unsigned int reg_addr, unsigned int *data)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
static struct i2c_msg msg[2];
|
||||||
|
unsigned char buffer[2];
|
||||||
|
struct i2c_client client;
|
||||||
|
|
||||||
|
if (i2c_dev >= SERDES_MAX_NUM) {
|
||||||
|
return HI_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_serdes_client[i2c_dev] == NULL) {
|
||||||
|
return HI_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
osal_memcpy(&client, g_serdes_client[i2c_dev], sizeof(struct i2c_client));
|
||||||
|
|
||||||
|
buffer[0] = reg_addr >> ONT_BYTE_EQUAL_BIT_NUM & 0xFF;
|
||||||
|
buffer[1] = reg_addr & 0xFF;
|
||||||
|
|
||||||
|
msg[0].addr = client.addr;
|
||||||
|
msg[0].flags = 0;
|
||||||
|
msg[0].len = 2;
|
||||||
|
msg[0].buf = buffer;
|
||||||
|
|
||||||
|
msg[1].addr = client.addr;
|
||||||
|
msg[1].flags = client.flags | I2C_M_RD;
|
||||||
|
msg[1].len = 1;
|
||||||
|
msg[1].buf = buffer;
|
||||||
|
|
||||||
|
ret = hi_i2c_transfer(client.adapter, msg, 2);
|
||||||
|
if (ret != 2) {
|
||||||
|
osal_printk("[%s %d] hi_i2c_transfer error, ret=%d.\n", __FUNCTION__, __LINE__, ret);
|
||||||
|
return HI_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*data = buffer[0];
|
||||||
|
|
||||||
|
return HI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_serdes_dev_attr(serdes_dev_attr_t* p_attr)
|
||||||
|
{
|
||||||
|
if (p_attr->devno >= SERDES_MAX_NUM) {
|
||||||
|
osal_printk("invalid serdes_dev number(%d)!\n", p_attr->devno);
|
||||||
|
return HI_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_attr->sendes_en != HI_TRUE && p_attr->sendes_en != HI_FALSE) {
|
||||||
|
osal_printk("invalid serdes_en(%d)!\n", p_attr->sendes_en);
|
||||||
|
return HI_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_attr->serdes_mode < SERDES_MODE_4LANE_LINEAR ||
|
||||||
|
p_attr->serdes_mode >= SERDES_MODE_BUTT) {
|
||||||
|
osal_printk("invalid serdes_mode(%d)!\n", p_attr->serdes_mode);
|
||||||
|
return HI_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return HI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __HuaweiLite__
|
||||||
|
static int serdes_ioctl(struct file *file, int cmd, unsigned long arg)
|
||||||
|
#else
|
||||||
|
static long serdes_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
serdes_dev_attr_t __user *argp = (serdes_dev_attr_t __user *)arg;
|
||||||
|
serdes_dev_attr_t serdes_dev_attr;
|
||||||
|
|
||||||
|
if (copy_from_user(&serdes_dev_attr, argp, sizeof(serdes_dev_attr_t))) {
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case HI_SERDES_START:
|
||||||
|
ret = check_serdes_dev_attr(&serdes_dev_attr);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
sensor_dev_addr[serdes_dev_attr.devno] = serdes_dev_attr.sensor_i2c_addr;
|
||||||
|
if ((serdes_dev_attr.sendes_en == HI_TRUE) &&
|
||||||
|
(serdes_init_flag[serdes_dev_attr.devno] == HI_FALSE)) {
|
||||||
|
serdes_thine_init(serdes_dev_attr.devno, serdes_dev_attr.serdes_mode);
|
||||||
|
serdes_init_flag[serdes_dev_attr.devno] = HI_TRUE;
|
||||||
|
} else if ((serdes_dev_attr.sendes_en == HI_FALSE) &&
|
||||||
|
(serdes_init_flag[serdes_dev_attr.devno] == HI_TRUE)){
|
||||||
|
serdes_thine_exit(serdes_dev_attr.devno);
|
||||||
|
serdes_init_flag[serdes_dev_attr.devno] = HI_FALSE;
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
osal_printk("kernel: no such serdes command %#x!\n", cmd);
|
||||||
|
return HI_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return HI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __HuaweiLite__
|
||||||
|
static int serdes_open(struct file *file)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int serdes_close(struct file *file)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const static struct file_operations_vfs serdes_fops = {
|
||||||
|
.open = serdes_open,
|
||||||
|
.close = serdes_close,
|
||||||
|
.ioctl = serdes_ioctl
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct i2c_client g_serdes_client_obj[SERDES_MAX_NUM];
|
||||||
|
static struct i2c_client *hi_serdes_i2c_client_init(int i2c_dev)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct i2c_client *i2c_client0 = &g_serdes_client_obj[i2c_dev];
|
||||||
|
i2c_client0->addr = THINE_DEVICE_ADDR >> 1;
|
||||||
|
i2c_client0->flags = 0;
|
||||||
|
ret = client_attach(i2c_client0, i2c_dev);
|
||||||
|
if (ret) {
|
||||||
|
dprintf("fail to attach g_serdes_client!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return &g_serdes_client_obj[i2c_dev];
|
||||||
|
}
|
||||||
|
|
||||||
|
int serdes_mod_init(void)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for (i = 0; i < SERDES_MAX_NUM; i++) {
|
||||||
|
g_serdes_client[i] = hi_serdes_i2c_client_init(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = register_driver("/dev/serdes0", &serdes_fops, 0666, 0);
|
||||||
|
if (ret) {
|
||||||
|
osal_printk("register serdes0 device failed with %#x!\n", ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = register_driver("/dev/serdes1", &serdes_fops, 0666, 0);
|
||||||
|
if (ret) {
|
||||||
|
osal_printk("register serdes1 device failed with %#x!\n", ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
osal_printk("\n====> register serdes0_1 success.\n");
|
||||||
|
|
||||||
|
return HI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serdes_mod_exit(void)
|
||||||
|
{
|
||||||
|
unregister_driver("/dev/serdes1");
|
||||||
|
unregister_driver("/dev/serdes0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static int serdes_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int serdes_close(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct file_operations serdes_fops = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.open = serdes_open,
|
||||||
|
.release = serdes_close,
|
||||||
|
.unlocked_ioctl = serdes_ioctl,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct miscdevice serdes_dev0 = {
|
||||||
|
.minor = MISC_DYNAMIC_MINOR,
|
||||||
|
.name = SERDES_DEV_NAME0,
|
||||||
|
.fops = &serdes_fops,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct miscdevice serdes_dev1 = {
|
||||||
|
.minor = MISC_DYNAMIC_MINOR,
|
||||||
|
.name = SERDES_DEV_NAME1,
|
||||||
|
.fops = &serdes_fops,
|
||||||
|
};
|
||||||
|
|
||||||
|
int serdes_mod_init(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int ret;
|
||||||
|
struct i2c_adapter *i2c_adapter;
|
||||||
|
|
||||||
|
for (i = 0; i < SERDES_MAX_NUM; i++) {
|
||||||
|
i2c_adapter = i2c_get_adapter(i);
|
||||||
|
if (i2c_adapter == NULL) {
|
||||||
|
osal_printk("i2c_get_adapter error!\n");
|
||||||
|
return HI_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_serdes_client[i] = i2c_new_device(i2c_adapter, &g_thine_info);
|
||||||
|
|
||||||
|
i2c_put_adapter(i2c_adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = misc_register(&serdes_dev0);
|
||||||
|
if (ret != HI_SUCCESS) {
|
||||||
|
osal_printk("kernel: register serdes_0 device failed!\n");
|
||||||
|
return HI_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = misc_register(&serdes_dev1);
|
||||||
|
if (ret != HI_SUCCESS) {
|
||||||
|
osal_printk("kernel: register serdes_1 device failed!\n");
|
||||||
|
return HI_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return HI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serdes_mod_exit(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < SERDES_MAX_NUM; i++) {
|
||||||
|
i2c_unregister_device(g_serdes_client[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
misc_deregister(&serdes_dev1);
|
||||||
|
misc_deregister(&serdes_dev0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(serdes_mod_init);
|
||||||
|
module_exit(serdes_mod_exit);
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_AUTHOR("hisilicon");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* copyright (c) hisilicon technologies co., ltd. 2016-2019. all rights reserved.
|
||||||
|
* description: serdes_comm.h
|
||||||
|
* author: hisilicon multimedia software group
|
||||||
|
* create: 2019-05-17
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __HI_SERDES_COMM_H__
|
||||||
|
#define __HI_SERDES_COMM_H__
|
||||||
|
|
||||||
|
#include "hi_osal.h"
|
||||||
|
|
||||||
|
#define THINE_DEVICE_TYPE "241a-242"
|
||||||
|
#define THINE_DEVICE_ADDR 0x16
|
||||||
|
|
||||||
|
#define SERDES_MAX_NUM 2
|
||||||
|
extern unsigned char sensor_dev_addr[SERDES_MAX_NUM];
|
||||||
|
|
||||||
|
int serdes_i2c_write(unsigned char i2c_dev, unsigned char dev_addr,
|
||||||
|
unsigned int reg_addr, unsigned int reg_addr_num,
|
||||||
|
unsigned int data, unsigned int data_byte_num);
|
||||||
|
|
||||||
|
int serdes_i2c_read(unsigned char i2c_dev, const unsigned char dev_addr,
|
||||||
|
const unsigned int reg_addr, unsigned int *data);
|
||||||
|
|
||||||
|
void serdes_thine_init(int i2c_dev, serdes_mode_t serdes_mode);
|
||||||
|
|
||||||
|
void serdes_thine_exit(int i2c_dev);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __HI_SERDES_COMM_H__
|
|
@ -0,0 +1,703 @@
|
||||||
|
/*
|
||||||
|
* copyright (c) hisilicon technologies co., ltd. 2016-2019. all rights reserved.
|
||||||
|
* description: thine_241a242_serdes.c
|
||||||
|
* author: hisilicon multimedia software group
|
||||||
|
* create: 2019-05-17
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "thine_241a242_serdes.h"
|
||||||
|
|
||||||
|
static inline void delay_us(const int us)
|
||||||
|
{
|
||||||
|
udelay(us);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for 242 */
|
||||||
|
void write_serdes_rx_register(unsigned char i2c_dev, const unsigned int reg_addr, const unsigned int data)
|
||||||
|
{
|
||||||
|
unsigned int reg_addr_num = 2;
|
||||||
|
unsigned int data_byte_num = 1;
|
||||||
|
unsigned char dev_addr = THINE_DEVICE_ADDR;
|
||||||
|
|
||||||
|
serdes_i2c_write(i2c_dev, dev_addr, reg_addr, reg_addr_num, data, data_byte_num);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_serdes_rx_1bype_register(unsigned char i2c_dev, const unsigned int reg_addr, const unsigned int data)
|
||||||
|
{
|
||||||
|
unsigned int reg_addr_num = 1;
|
||||||
|
unsigned int data_byte_num = 1;
|
||||||
|
unsigned char dev_addr = THINE_DEVICE_ADDR;
|
||||||
|
|
||||||
|
serdes_i2c_write(i2c_dev, dev_addr, reg_addr, reg_addr_num, data, data_byte_num);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_serdes_rx_register(unsigned char i2c_dev, const unsigned int reg_addr)
|
||||||
|
{
|
||||||
|
unsigned int r_data = 0;
|
||||||
|
unsigned char dev_addr = (THINE_DEVICE_ADDR + 1);
|
||||||
|
|
||||||
|
serdes_i2c_read(i2c_dev, dev_addr, reg_addr, &r_data);
|
||||||
|
return r_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for 241 */
|
||||||
|
void write_serdes_tx_1bype_register(unsigned char i2c_dev, unsigned int reg_addr, const unsigned int data)
|
||||||
|
{
|
||||||
|
unsigned int reg_addr_num = 1;
|
||||||
|
unsigned int data_byte_num = 1;
|
||||||
|
unsigned char dev_addr = (sensor_dev_addr[i2c_dev] << 1);
|
||||||
|
|
||||||
|
serdes_i2c_write(i2c_dev, dev_addr, reg_addr, reg_addr_num, data, data_byte_num);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_serdes_tx_2bype_register(unsigned char i2c_dev, const unsigned int reg_addr, const unsigned int data)
|
||||||
|
{
|
||||||
|
unsigned int reg_addr_num = 2;
|
||||||
|
unsigned int data_byte_num = 1;
|
||||||
|
unsigned char dev_addr = (sensor_dev_addr[i2c_dev] << 1);
|
||||||
|
|
||||||
|
serdes_i2c_write(i2c_dev, dev_addr, reg_addr, reg_addr_num, data, data_byte_num);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_serdes_data_rate(unsigned char i2c_dev, serdes_mode_t serdes_mode)
|
||||||
|
{
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
int result = 0;
|
||||||
|
#endif
|
||||||
|
if (serdes_mode == SERDES_MODE_4LANE_LINEAR) {
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1609, 0x00);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1609);
|
||||||
|
osal_printk("read 242 0x1609: 0x%x, should be 0x00\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x160A, 0x0C);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x160A);
|
||||||
|
osal_printk("read 242 0x160A: 0x%x, should be 0x0C\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x160B, 0x03);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x160B);
|
||||||
|
osal_printk("read 242 0x160B: 0x%x, should be 0x03\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x160C, 0x01);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x160C);
|
||||||
|
osal_printk("read 242 0x160C: 0x%x, should be 0x01\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x160D, 0x0C);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x160D);
|
||||||
|
osal_printk("read 242 0x160D: 0x%x, should be 0x0C\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x160E, 0x00);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x160E);
|
||||||
|
osal_printk("read 242 0x160E: 0x%x, should be 0x00\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x160F, 0x01);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x160F);
|
||||||
|
osal_printk("read 242 0x160F: 0x%x, should be 0x01\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1610, 0x00);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1610);
|
||||||
|
osal_printk("read 242 0x1610: 0x%x, should be 0x00\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1611, 0x02);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1611);
|
||||||
|
osal_printk("read 242 0x1611: 0x%x, should be 0x02\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1612, 0x02);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1612);
|
||||||
|
osal_printk("read 242 0x1612: 0x%x, should be 0x02\n", result);
|
||||||
|
#endif
|
||||||
|
} else if ((serdes_mode == SERDES_MODE_2LANE_LINEAR) ||
|
||||||
|
(serdes_mode == SERDES_MODE_4LANE_WDR)) {
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1609, 0x03);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1609);
|
||||||
|
osal_printk("read 242 0x1609: 0x%x, should be 0x03\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x160A, 0x0F);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x160A);
|
||||||
|
osal_printk("read 242 0x160A: 0x%x, should be 0x0F\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x160B, 0x05);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x160B);
|
||||||
|
osal_printk("read 242 0x160B: 0x%x, should be 0x05\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x160C, 0x01);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x160C);
|
||||||
|
osal_printk("read 242 0x160C: 0x%x, should be 0x01\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x160D, 0x0A);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x160D);
|
||||||
|
osal_printk("read 242 0x160D: 0x%x, should be 0x0A\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x160E, 0x02);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x160E);
|
||||||
|
osal_printk("read 242 0x160E: 0x%x, should be 0x02\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x160F, 0x02);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x160F);
|
||||||
|
osal_printk("read 242 0x160F: 0x%x, should be 0x02\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1610, 0x03);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1610);
|
||||||
|
osal_printk("read 242 0x1610: 0x%x, should be 0x03\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1611, 0x02);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1611);
|
||||||
|
osal_printk("read 242 0x1611: 0x%x, should be 0x02\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1612, 0x04);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1612);
|
||||||
|
osal_printk("read 242 0x1612: 0x%x, should be 0x04\n", result);
|
||||||
|
#endif
|
||||||
|
} else if (serdes_mode == SERDES_MODE_2LANE_WDR) {
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1609, 0x04);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1609);
|
||||||
|
osal_printk("read 242 0x1609: 0x%x, should be 0x04\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x160A, 0x23);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x160A);
|
||||||
|
osal_printk("read 242 0x160A: 0x%x, should be 0x23\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x160B, 0x08);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x160B);
|
||||||
|
osal_printk("read 242 0x160B: 0x%x, should be 0x08\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x160C, 0x01);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x160C);
|
||||||
|
osal_printk("read 242 0x160C: 0x%x, should be 0x01\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x160D, 0x11);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x160D);
|
||||||
|
osal_printk("read 242 0x160D: 0x%x, should be 0x11\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x160E, 0x09);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x160E);
|
||||||
|
osal_printk("read 242 0x160E: 0x%x, should be 0x09\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x160F, 0x06);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x160F);
|
||||||
|
osal_printk("read 242 0x160F: 0x%x, should be 0x06\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1610, 0x06);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1610);
|
||||||
|
osal_printk("read 242 0x1610: 0x%x, should be 0x06\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1611, 0x10);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1611);
|
||||||
|
osal_printk("read 242 0x1611: 0x%x, should be 0x10\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1612, 0x08);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1612);
|
||||||
|
osal_printk("read 242 0x1612: 0x%x, should be 0x08\n", result);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_serdes_cfg(serdes_mode_t serdes_mode, serdes_config *cfg)
|
||||||
|
{
|
||||||
|
if (serdes_mode == SERDES_MODE_4LANE_LINEAR) {
|
||||||
|
osal_memcpy(cfg, &imx307_4_lane_linear_12_bit_30_fps_cfg, sizeof(serdes_config));
|
||||||
|
} else if (serdes_mode == SERDES_MODE_4LANE_WDR) {
|
||||||
|
osal_memcpy(cfg, &imx307_4_lane_wdr_12_bit_30_fps_cfg, sizeof(serdes_config));
|
||||||
|
} else if (serdes_mode == SERDES_MODE_2LANE_LINEAR) {
|
||||||
|
osal_memcpy(cfg, &imx307_2_lane_linear_12_bit_30_fps_cfg, sizeof(serdes_config));
|
||||||
|
} else {
|
||||||
|
osal_memcpy(cfg, &imx307_2_lane_wdr_12_bit_30_fps_cfg, sizeof(serdes_config));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void serdes_241_242_init(unsigned char i2c_dev, serdes_mode_t serdes_mode)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
serdes_config cfg;
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
int result = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
get_serdes_cfg(serdes_mode, &cfg);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step1: THCV242 sub-link mode : THCV241A ID
|
||||||
|
------------------------------------------------------*/
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0050, 0x34);
|
||||||
|
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x0050);
|
||||||
|
osal_printk("read 242 0x0050: 0x%x, should be 0x34\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step1: THCV242 sub-link mode : pass throuth mode
|
||||||
|
------------------------------------------------------*/
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0004, 0x03);
|
||||||
|
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x0004);
|
||||||
|
osal_printk("read 242 0x0004: 0x%x, should be 0x3\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step2: THCV242 sub link en/pol : lane 0 enable polling off
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0010, 0x10); // polling off
|
||||||
|
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x0010);
|
||||||
|
osal_printk("read 242 0x0010: 0x%x, should be 0x10\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step3: THCV242 sub link power on
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1704, 0x01);
|
||||||
|
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1704);
|
||||||
|
osal_printk("read 242 0x1704: 0x%x, should be 0x1\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step4: THCV242 sub link tx term 50ohm
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0102, 0x02); // 50ohm
|
||||||
|
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x0102);
|
||||||
|
osal_printk("read 242 0x0102: 0x%x, should be 0x2\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step5: THCV242 sub link tx drv 12ma
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0103, 0x02); // 12m_a
|
||||||
|
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x0103);
|
||||||
|
osal_printk("read 242 0x0103: 0x%x, should be 0x2\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step6: THCV242 sub link rx term : 50ohm
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0104, 0x02); // 50ohm
|
||||||
|
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x0104);
|
||||||
|
osal_printk("read 242 0x0104: 0x%x, should be 0x2\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step7: THCV242 rx drv : 12ma
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0105, 0x02); // 12mA
|
||||||
|
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x0105);
|
||||||
|
osal_printk("read 242 0x0105: 0x%x, should be 0x2\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step8: THCV242 reserved setting : key is unlocked
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0100, 0x03);
|
||||||
|
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x0100);
|
||||||
|
osal_printk("read 242 0x0100: 0x%x, should be 0x3\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step9: THCV242 reserved setting : key2 is unlocked
|
||||||
|
------------------------------------------------------*/
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x010F, 0x25);
|
||||||
|
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x010F);
|
||||||
|
osal_printk("read 242 0x010F: 0x%x, should be 0x25\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step10: THCV242 reserved setting : sub link width
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x010A, 0x15); // 0x15 -> 0x18 -> 0x15
|
||||||
|
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x010A);
|
||||||
|
osal_printk("read 242 0x010A: 0x%x, should be 0x15\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0031, 0x02);
|
||||||
|
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x0031);
|
||||||
|
osal_printk("read 242 0x0031: 0x%x, should be 0x2\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0032, 0x10);
|
||||||
|
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x0032);
|
||||||
|
osal_printk("read 242 0x0032: 0x%x, should be 0x10\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step13: THCV241 bank is 00
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
write_serdes_tx_2bype_register(i2c_dev, 0x00FE, 0x11);
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0032, 0x00);
|
||||||
|
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x0032);
|
||||||
|
osal_printk("read 242 0x0032: 0x%x, should be 0x00\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step14: THCV241 sub link tx term / drv setting:50ohm 12ma
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x00F2, 0x22); // 50ohm/12mA
|
||||||
|
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x00F3, 0x22); // 50ohm/12mA
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step15: THCV241 reserved setting : key is unlocked
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x00F0, 0x03);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
THCV241 reserved setting : key 2 is unlocked
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x00FF, 0x19);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step16: THCV241 reserved setting : sub link width
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x00F6, 0x18); // 0x15
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step16: THCV241 I2C freq 400k_hz
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x00C9, 0x05);
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x00CA, 0x05);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step17: THCV242 sub link en/pol : lane 0 enable polling on
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0010, 0x11);
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step18: THCV241 bank is 10
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x00FE, 0x21);
|
||||||
|
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x002C, 0x01);
|
||||||
|
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x002D, cfg.pll_value[i]);
|
||||||
|
i += 1;
|
||||||
|
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0076, 0x10);
|
||||||
|
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0000, 0x00);
|
||||||
|
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0001, 0x00);
|
||||||
|
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x000F, 0x01);
|
||||||
|
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0011, cfg.pll_value[i]);
|
||||||
|
i += 1;
|
||||||
|
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0012, 0x00);
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0013, 0x00);
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0014, 0x00);
|
||||||
|
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0015, cfg.pll_value[i]);
|
||||||
|
i += 1;
|
||||||
|
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0016, 0x01);
|
||||||
|
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x002B, 0x07);
|
||||||
|
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x002F, 0x00);
|
||||||
|
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0005, 0x01);
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0006, 0x01);
|
||||||
|
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0027, 0x00);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
step19: THCV242
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1010, 0xA1);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1010);
|
||||||
|
osal_printk("read 242 0x1010: 0x%x, should be 0xa1\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1021, 0x20);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1021);
|
||||||
|
osal_printk("read 242 0x1021: 0x%x, should be 0x20\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1022, cfg.pll_value[i]);
|
||||||
|
i += 1;
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1022);
|
||||||
|
osal_printk("read 242 0x1022: 0x%x, should be 0x01\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1023, cfg.pll_value[i]);
|
||||||
|
i += 1;
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1023);
|
||||||
|
osal_printk("read 242 0x1023: 0x%x, should be 0x41--4L linear, 0x21--4L wdr\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1024, 0x00);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1024);
|
||||||
|
osal_printk("read 242 0x1024: 0x%x, should be 0x00\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1025, 0x00);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1025);
|
||||||
|
osal_printk("read 242 0x1025: 0x%x, should be 0x00\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1026, 0x00);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1026);
|
||||||
|
osal_printk("read 242 0x1026: 0x%x, should be 0x00\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1027, 0x07);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1027);
|
||||||
|
osal_printk("read 242 0x1027: 0x%x, should be 0x07\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1028, cfg.pll_value[i]);
|
||||||
|
i += 1;
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1028);
|
||||||
|
osal_printk("read 242 0x1028: 0x%x, should be 0x00--4lane, 0x2--2lane\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1030, 0x00);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1030);
|
||||||
|
osal_printk("read 242 0x1030: 0x%x, should be 0x00\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1100, 0x01);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1100);
|
||||||
|
osal_printk("read 242 0x1100: 0x%x, should be 0x01\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1101, 0x01);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1101);
|
||||||
|
osal_printk("read 242 0x1101: 0x%x, should be 0x01\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1102, 0x01);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1102);
|
||||||
|
osal_printk("read 242 0x1102: 0x%x, should be 0x01\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1600, 0x1A);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1600);
|
||||||
|
osal_printk("read 242 0x1600: 0x%x, should be 0x1a\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1605, cfg.pll_value[i]);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1605);
|
||||||
|
osal_printk("read 242 0x1605: 0x%x, should be 0x2b--4lane, 0x29--2lane\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1606, 0x45);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1606);
|
||||||
|
osal_printk("read 242 0x1606: 0x%x, should be 0x45\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
set_serdes_data_rate(i2c_dev, serdes_mode);
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1704, 0x11);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1704);
|
||||||
|
osal_printk("read 242 0x1704: 0x%x, should be 0x11\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1703, 0x01);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x1703);
|
||||||
|
osal_printk("read 242 0x1703: 0x%x, should be 0x01\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0032, 0x10);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x0032);
|
||||||
|
osal_printk("read 242 0x0032: 0x%x, should be 0x10\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0040, 0x1A);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x0040);
|
||||||
|
osal_printk("read 242 0x0040: 0x%x, should be 0x1a\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0041, 0x1A);
|
||||||
|
#if SERDES_DEBUG
|
||||||
|
result = read_serdes_rx_register(i2c_dev, 0x0041);
|
||||||
|
osal_printk("read 242 0x0041: 0x%x, should be 0x1a\n", result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serdes_242_reset(unsigned char i2c_dev)
|
||||||
|
{
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1701, 0x3F);
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1702, 0x01); // SW reset
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1703, 0x00); // PLL power down
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1704, 0x00); // Vx1HS Sub-Link power down
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0050, 0x34);
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0004, 0x03);
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0010, 0x10);
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x1704, 0x01); // Vx1HS Sub-Link power on
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0102, 0x02);
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0103, 0x02);
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0104, 0x02);
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0105, 0x02);
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0100, 0x03);
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x010F, 0x25);
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x010A, 0x15);
|
||||||
|
}
|
||||||
|
|
||||||
|
void serdes_241a_reset(unsigned char i2c_dev)
|
||||||
|
{
|
||||||
|
write_serdes_rx_1bype_register(i2c_dev, 0x0031, 0x02);
|
||||||
|
write_serdes_rx_1bype_register(i2c_dev, 0x0032, 0x00); // 1byte address, 1byte data access
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x00FE, 0x21); // THCV241 bank is 10
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0005, 0x00); // PLL Soft Reset Active
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0006, 0x00); // Vx1HS Soft Reset Active
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0021, 0x00); // MIPI Logic Reset
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0022, 0x00); // Logic Reset
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0023, 0x00); // MIPI Clock Reset
|
||||||
|
|
||||||
|
delay_us(1000);
|
||||||
|
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0021, 0x01); // MIPI Logic Reset
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0022, 0x01); // Logic Reset
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x0023, 0x01); // MIPI Clock Reset
|
||||||
|
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x00FE, 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
void serdes_241_242_exit(unsigned char i2c_dev)
|
||||||
|
{
|
||||||
|
serdes_242_reset(i2c_dev);
|
||||||
|
|
||||||
|
serdes_241a_reset(i2c_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void serdes_thine_init(int i2c_dev, serdes_mode_t serdes_mode)
|
||||||
|
{
|
||||||
|
serdes_241_242_init(i2c_dev, serdes_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void serdes_thine_exit(int i2c_dev)
|
||||||
|
{
|
||||||
|
serdes_241_242_exit(i2c_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void serdes_reset_unreset_sensor(unsigned char i2c_dev, int reset)
|
||||||
|
{
|
||||||
|
const unsigned int tmp = reset ? 0x00 : 0x30; // 10/11 -> 00/30
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0032, 0x00);
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0xFE, 0x21);
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x3E, tmp);
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0032, 0x10);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(serdes_reset_unreset_sensor);
|
||||||
|
|
||||||
|
void serdes_enable_disable_sensor_clock(unsigned char i2c_dev, int enable)
|
||||||
|
{
|
||||||
|
const unsigned int tmp = enable ? 0x10 : 0x50;
|
||||||
|
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0032, 0x00);
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0xFE, 0x21);
|
||||||
|
write_serdes_tx_1bype_register(i2c_dev, 0x76, tmp);
|
||||||
|
write_serdes_rx_register(i2c_dev, 0x0032, 0x10);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(serdes_enable_disable_sensor_clock);
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* copyright (c) hisilicon technologies co., ltd. 2016-2019. all rights reserved.
|
||||||
|
* description: thine_241a242_serdes.h
|
||||||
|
* author: hisilicon multimedia software group
|
||||||
|
* create: 2019-05-17
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __THINE_241A242_SERDES_H__
|
||||||
|
#define __THINE_241A242_SERDES_H__
|
||||||
|
|
||||||
|
#include <linux/delay.h>
|
||||||
|
|
||||||
|
#include "hi_serdes.h"
|
||||||
|
#include "serdes_comm.h"
|
||||||
|
#include "type.h"
|
||||||
|
|
||||||
|
#define SERDES_DEBUG 0
|
||||||
|
#define THINE_PLL_VALUE_NUM 7
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
HI_U8 pll_value[THINE_PLL_VALUE_NUM];
|
||||||
|
} serdes_config;
|
||||||
|
|
||||||
|
serdes_config imx307_4_lane_linear_12_bit_30_fps_cfg =
|
||||||
|
{
|
||||||
|
.pll_value = {0x13, 0x1b, 0x66, 0x01, 0x41, 0x00, 0x2b},
|
||||||
|
};
|
||||||
|
|
||||||
|
serdes_config imx307_4_lane_wdr_12_bit_30_fps_cfg =
|
||||||
|
{
|
||||||
|
.pll_value = {0x13, 0x18, 0x44, 0x02, 0x21, 0x00, 0x2b},
|
||||||
|
};
|
||||||
|
|
||||||
|
serdes_config imx307_2_lane_linear_12_bit_30_fps_cfg =
|
||||||
|
{
|
||||||
|
.pll_value = {0x11, 0x1b, 0x66, 0x01, 0x21, 0x02, 0x29},
|
||||||
|
};
|
||||||
|
|
||||||
|
serdes_config imx307_2_lane_wdr_12_bit_30_fps_cfg =
|
||||||
|
{
|
||||||
|
.pll_value = {0x11, 0x18, 0x44, 0x02, 0x11, 0x02, 0x29},
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* end of #ifdef __THINE_241A242_SERDES_H__ */
|
Loading…
Reference in New Issue