From 511b2d4c8b2a39f539078dff2c4af72c69898ccf Mon Sep 17 00:00:00 2001 From: viktorxda <35473052+viktorxda@users.noreply.github.com> Date: Wed, 22 Nov 2023 18:22:40 +0100 Subject: [PATCH] [no ci] Hisilicon: add hisilicon-osdrv-serdes package (#1154) Co-authored-by: Signor Pellegrino <68112357+FlyRouter@users.noreply.github.com> --- general/package/Config.in | 19 +- .../package/hisilicon-osdrv-serdes/Config.in | 4 + .../hisilicon-osdrv-serdes.mk | 14 + .../hisilicon-osdrv-serdes/src/Makefile | 9 + .../src/include/hi_osal.h | 571 ++++++++++++++ .../src/include/hi_serdes.h | 48 ++ .../src/include/osal_ioctl.h | 106 +++ .../src/include/osal_list.h | 742 ++++++++++++++++++ .../hisilicon-osdrv-serdes/src/include/type.h | 51 ++ .../hisilicon-osdrv-serdes/src/serdes_comm.c | 378 +++++++++ .../hisilicon-osdrv-serdes/src/serdes_comm.h | 31 + .../src/thine_241a242_serdes.c | 703 +++++++++++++++++ .../src/thine_241a242_serdes.h | 45 ++ 13 files changed, 2712 insertions(+), 9 deletions(-) create mode 100644 general/package/hisilicon-osdrv-serdes/Config.in create mode 100644 general/package/hisilicon-osdrv-serdes/hisilicon-osdrv-serdes.mk create mode 100644 general/package/hisilicon-osdrv-serdes/src/Makefile create mode 100755 general/package/hisilicon-osdrv-serdes/src/include/hi_osal.h create mode 100755 general/package/hisilicon-osdrv-serdes/src/include/hi_serdes.h create mode 100755 general/package/hisilicon-osdrv-serdes/src/include/osal_ioctl.h create mode 100755 general/package/hisilicon-osdrv-serdes/src/include/osal_list.h create mode 100755 general/package/hisilicon-osdrv-serdes/src/include/type.h create mode 100755 general/package/hisilicon-osdrv-serdes/src/serdes_comm.c create mode 100755 general/package/hisilicon-osdrv-serdes/src/serdes_comm.h create mode 100755 general/package/hisilicon-osdrv-serdes/src/thine_241a242_serdes.c create mode 100755 general/package/hisilicon-osdrv-serdes/src/thine_241a242_serdes.h diff --git a/general/package/Config.in b/general/package/Config.in index 2c0da1e9..bdfc18ee 100644 --- a/general/package/Config.in +++ b/general/package/Config.in @@ -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/hisi-gpio/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-hi3516cv100/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-hi3519v101/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/ingenic-motors-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-osdrv-t20/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-t31/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/json-c-openipc/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/libhv-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/librem-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/libwebsockets-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/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/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/mbedtls-openipc/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/mini/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/mt7601u-openipc/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/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/rtl8189fs-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/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/yaml-cli/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" diff --git a/general/package/hisilicon-osdrv-serdes/Config.in b/general/package/hisilicon-osdrv-serdes/Config.in new file mode 100644 index 00000000..2d350c26 --- /dev/null +++ b/general/package/hisilicon-osdrv-serdes/Config.in @@ -0,0 +1,4 @@ +config BR2_PACKAGE_HISILICON_OSDRV_SERDES + bool "hisilicon-osdrv-serdes" + help + HiSilicon SerDes kernel driver. diff --git a/general/package/hisilicon-osdrv-serdes/hisilicon-osdrv-serdes.mk b/general/package/hisilicon-osdrv-serdes/hisilicon-osdrv-serdes.mk new file mode 100644 index 00000000..9c74fb0a --- /dev/null +++ b/general/package/hisilicon-osdrv-serdes/hisilicon-osdrv-serdes.mk @@ -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)) diff --git a/general/package/hisilicon-osdrv-serdes/src/Makefile b/general/package/hisilicon-osdrv-serdes/src/Makefile new file mode 100644 index 00000000..cf185eb4 --- /dev/null +++ b/general/package/hisilicon-osdrv-serdes/src/Makefile @@ -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 diff --git a/general/package/hisilicon-osdrv-serdes/src/include/hi_osal.h b/general/package/hisilicon-osdrv-serdes/src/include/hi_osal.h new file mode 100755 index 00000000..04231fab --- /dev/null +++ b/general/package/hisilicon-osdrv-serdes/src/include/hi_osal.h @@ -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 + +#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 diff --git a/general/package/hisilicon-osdrv-serdes/src/include/hi_serdes.h b/general/package/hisilicon-osdrv-serdes/src/include/hi_serdes.h new file mode 100755 index 00000000..b90e9082 --- /dev/null +++ b/general/package/hisilicon-osdrv-serdes/src/include/hi_serdes.h @@ -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__*/ diff --git a/general/package/hisilicon-osdrv-serdes/src/include/osal_ioctl.h b/general/package/hisilicon-osdrv-serdes/src/include/osal_ioctl.h new file mode 100755 index 00000000..0239a9ab --- /dev/null +++ b/general/package/hisilicon-osdrv-serdes/src/include/osal_ioctl.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 */ diff --git a/general/package/hisilicon-osdrv-serdes/src/include/osal_list.h b/general/package/hisilicon-osdrv-serdes/src/include/osal_list.h new file mode 100755 index 00000000..a7600245 --- /dev/null +++ b/general/package/hisilicon-osdrv-serdes/src/include/osal_list.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 diff --git a/general/package/hisilicon-osdrv-serdes/src/include/type.h b/general/package/hisilicon-osdrv-serdes/src/include/type.h new file mode 100755 index 00000000..7f8f7bae --- /dev/null +++ b/general/package/hisilicon-osdrv-serdes/src/include/type.h @@ -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__ */ + diff --git a/general/package/hisilicon-osdrv-serdes/src/serdes_comm.c b/general/package/hisilicon-osdrv-serdes/src/serdes_comm.c new file mode 100755 index 00000000..c7d02130 --- /dev/null +++ b/general/package/hisilicon-osdrv-serdes/src/serdes_comm.c @@ -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 +#include +#ifndef __HuaweiLite__ +#include +#include +#include +#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 + diff --git a/general/package/hisilicon-osdrv-serdes/src/serdes_comm.h b/general/package/hisilicon-osdrv-serdes/src/serdes_comm.h new file mode 100755 index 00000000..9a0f68a7 --- /dev/null +++ b/general/package/hisilicon-osdrv-serdes/src/serdes_comm.h @@ -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__ diff --git a/general/package/hisilicon-osdrv-serdes/src/thine_241a242_serdes.c b/general/package/hisilicon-osdrv-serdes/src/thine_241a242_serdes.c new file mode 100755 index 00000000..8b017448 --- /dev/null +++ b/general/package/hisilicon-osdrv-serdes/src/thine_241a242_serdes.c @@ -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); diff --git a/general/package/hisilicon-osdrv-serdes/src/thine_241a242_serdes.h b/general/package/hisilicon-osdrv-serdes/src/thine_241a242_serdes.h new file mode 100755 index 00000000..55715746 --- /dev/null +++ b/general/package/hisilicon-osdrv-serdes/src/thine_241a242_serdes.h @@ -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 + +#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__ */