GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
|
||||
ifneq ($(srctree),)
|
||||
KERNEL_DIR := $(srctree)
|
||||
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
|
||||
else
|
||||
SDK_DIR := $(shell cd $(CURDIR)/../../../../../.. && /bin/pwd)
|
||||
endif
|
||||
|
||||
include $(SDK_DIR)/build/base.mk
|
||||
|
||||
export TRANSFER_TYPE := SPI
|
||||
|
||||
MOD_NAME := xm_msensor_chip
|
||||
|
||||
SRCS := ./main/msensor.c
|
||||
SRCS += ./proc/msensor_chip_proc.c
|
||||
SRCS += ./sensor_dev/icm42670/icm42670.c
|
||||
SRCS += ./sensor_dev/icm42670/msensor_gpio.c
|
||||
SRCS += ./transfer_type/spi/spi_dev.c
|
||||
|
||||
SDK_KER_CFLAGS += -I$(GMP_DIR)/include
|
||||
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/include
|
||||
SDK_KER_CFLAGS += -I$(GMP_DIR)/usr/include
|
||||
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/osal/include
|
||||
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/msensor_chip/proc
|
||||
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/msensor_chip/sensor_dev/icm42670
|
||||
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/msensor_chip/transfer_type/spi
|
||||
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/msensor_spi/spi
|
||||
|
||||
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/include
|
||||
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/msensor_chip/main
|
||||
#SDK_KER_CFLAGS += -I$(PWD)/pub
|
||||
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/ext_inc
|
||||
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/msensor_spi
|
||||
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/msensor_mng/include
|
||||
|
||||
SDK_KER_CFLAGS += -DTRANSFER_SPI
|
||||
SDK_KER_CFLAGS += -DICM42670_PARAM_PROC
|
||||
|
||||
SDK_KER_CFLAGS += -DCONFIG_PROC_SHOW_SUPPORT
|
||||
|
||||
$(info SDK_KER_CFLAGS=$(SDK_KER_CFLAGS))
|
||||
$(info SRCS=$(SRCS))
|
||||
$(info SDK_DIR=$(SDK_DIR))
|
||||
$(info CURDIR=$(CURDIR))
|
||||
include $(SDK_DIR)/build/sdk_ko_rules.mk
|
||||
@@ -0,0 +1,712 @@
|
||||
/*
|
||||
* Copyright (c); XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "msensor.h"
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include "osal.h"
|
||||
#include "mmz.h"
|
||||
#include "msensor_ext.h"
|
||||
#include "msensor_chip_ioctl.h"
|
||||
#include "msensor.h"
|
||||
#include "msensor_exe.h"
|
||||
#include "icm42670.h"
|
||||
|
||||
#define UMAP_MSENSOR_CHIP_MINOR_BASE 153
|
||||
#define UMAP_DEVNANME_MSENSOR_CHIP_BASE "msensor_chip"
|
||||
|
||||
#if (defined CONFIG_PROC_SHOW_SUPPORT)
|
||||
#include "msensor_chip_proc.h"
|
||||
#endif
|
||||
|
||||
static osal_dev_t *g_msensor_chip_dev = XMEDIA_NULL;
|
||||
|
||||
static xmedia_s32 g_msensor_init[XMEDIA_MSENSOR_MAX_DEV_NUM] = { XMEDIA_FALSE};
|
||||
static xmedia_bool g_msensor_start[XMEDIA_MSENSOR_MAX_DEV_NUM] = { XMEDIA_FALSE};
|
||||
xmedia_msensor_param *g_msensor_param [XMEDIA_MSENSOR_MAX_DEV_NUM] = { XMEDIA_NULL};
|
||||
static triger_config g_triger_data[XMEDIA_MSENSOR_MAX_DEV_NUM] = { 0 };
|
||||
static osal_atomic_t g_msensor_chip_user_ref[XMEDIA_MSENSOR_MAX_DEV_NUM] = { 0 };
|
||||
|
||||
#define safe_kfree(memory) \
|
||||
do { \
|
||||
if ((memory) != XMEDIA_NULL) { \
|
||||
osal_kfree(memory); \
|
||||
memory = XMEDIA_NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
xmedia_msensor_param *msensor_chip_get_param(xmedia_s32 dev)
|
||||
{
|
||||
return g_msensor_param[dev];
|
||||
}
|
||||
|
||||
xmedia_bool msensor_chip_get_status(xmedia_s32 dev)
|
||||
{
|
||||
return g_msensor_start[dev];
|
||||
}
|
||||
|
||||
#ifdef MNGBUFF_ENABLE
|
||||
xmedia_s32 msensor_chip_int_callback(xmedia_s32 dev, xmedia_msensor_data *msensor_data)
|
||||
{
|
||||
xmedia_s32 ret = XMEDIA_SUCCESS;
|
||||
|
||||
if (msensor_data == XMEDIA_NULL) {
|
||||
MSENSOR_ERR_TRACE("dev %d msensor_data is null\n", dev);
|
||||
return XMEDIA_ERRCODE_NULL_PTR;
|
||||
}
|
||||
|
||||
ret = msensor_mng_write_data_to_buf(dev, msensor_data);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
MSENSOR_ERR_TRACE("dev %d write data tobuf failed!(ret:0x%x)\n", dev, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_init_mng_buf(xmedia_s32 dev, xmedia_msensor_attr msensor_attr,
|
||||
xmedia_msensor_buf_attr *msensor_buf_attr, xmedia_msensor_config *msensor_config)
|
||||
{
|
||||
xmedia_s32 ret = XMEDIA_SUCCESS;
|
||||
|
||||
if ((msensor_buf_attr == XMEDIA_NULL) || (msensor_config == XMEDIA_NULL)) {
|
||||
MSENSOR_ERR_TRACE("dev %d msensor_buf_attr or msensor_config is null!\n", dev);
|
||||
return XMEDIA_ERRCODE_NULL_PTR;
|
||||
}
|
||||
|
||||
ret = msensor_mng_buf_init(dev, &msensor_attr, msensor_buf_attr, msensor_config);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
MSENSOR_ERR_TRACE("dev %d init mng buff failed!(ret:0x%x)\n", dev, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_exit_mng_buf(xmedia_s32 dev)
|
||||
{
|
||||
xmedia_s32 ret = XMEDIA_SUCCESS;
|
||||
|
||||
ret = msensor_mng_buf_exit(dev);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
MSENSOR_ERR_TRACE("dev %d exit mng buff failed!(ret:0x%x)\n", dev, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//todo,待确认,释放需要通过ioctl开放get cfg接口
|
||||
static xmedia_s32 msensor_chip_get_cfg(xmedia_s32 dev, xmedia_msensor_param *msensor_param)
|
||||
{
|
||||
if (g_msensor_param[dev] == XMEDIA_NULL) {
|
||||
MSENSOR_ERR_TRACE("dev %d msensor_param is null\n", dev);
|
||||
return XMEDIA_ERRCODE_NULL_PTR;
|
||||
}
|
||||
|
||||
if (msensor_param == XMEDIA_NULL) {
|
||||
MSENSOR_ERR_TRACE("dev %d input param is null\n", dev);
|
||||
return XMEDIA_ERRCODE_NULL_PTR;
|
||||
}
|
||||
|
||||
osal_memcpy(msensor_param, g_msensor_param[dev], sizeof(xmedia_msensor_param));
|
||||
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
// todo,通过ioctl开放get data接口
|
||||
xmedia_s32 msensor_chip_get_data(xmedia_s32 dev)
|
||||
{
|
||||
xmedia_s32 ret;
|
||||
|
||||
ret = chip_get_data_for_one_frm(dev);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
MSENSOR_ERR_TRACE("dev %d get data failed!\n", dev);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_register_mng_callback(xmedia_s32 dev)
|
||||
{
|
||||
xmedia_s32 ret;
|
||||
|
||||
msensor_mng_callback callback = { 0 };
|
||||
|
||||
callback.pfn_get_config_from_chip = msensor_chip_get_cfg;
|
||||
callback.pfn_write_data_to_buf = msensor_chip_get_data;
|
||||
|
||||
ret = msensor_mng_register_call_back(dev, &callback);
|
||||
if(ret != XMEDIA_SUCCESS) {
|
||||
MSENSOR_ERR_TRACE("dev %d register msensor callback failed\n", dev);
|
||||
return XMEDIA_FAILURE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static xmedia_void msensor_chip_unregister_mng_callback(xmedia_s32 dev)
|
||||
{
|
||||
msensor_mng_unregister_call_back(dev);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static xmedia_s32 msensor_chip_open(xmedia_void *private_data)
|
||||
{
|
||||
xmedia_unused(private_data);
|
||||
MSENSOR_ERR_TRACE("msensor open\n");
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_release(xmedia_void *private_data)
|
||||
{
|
||||
xmedia_unused(private_data);
|
||||
MSENSOR_ERR_TRACE("msensor close\n");
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_freeze(osal_dev_t *dev)
|
||||
{
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_restore(osal_dev_t *dev)
|
||||
{
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
/* msensor chip ioctl functions */
|
||||
static xmedia_s32 msensor_chip_drv_user_start(xmedia_s32 dev, xmedia_uintptr_t arg)
|
||||
{
|
||||
if (g_msensor_init[dev] == XMEDIA_FALSE) {
|
||||
MSENSOR_ERR_TRACE("dev %d msensor is not init!\n", dev);
|
||||
return XMEDIA_FAILURE;
|
||||
}
|
||||
|
||||
if (g_msensor_start[dev] == XMEDIA_TRUE) {
|
||||
MSENSOR_ERR_TRACE("dev %d msensor is already start!\n", dev);
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
xmedia_unused(arg);
|
||||
|
||||
chip_fifo_data_reset(dev);
|
||||
|
||||
osal_msleep(100); // 1.16 fix acc && gyro pts not sync problem
|
||||
|
||||
if (g_triger_data[dev].triger_mode == TRIGER_TIMER) {
|
||||
chip_timer_run(dev);
|
||||
} else if (g_triger_data[dev].triger_mode == TRIGER_EXTERN_INTERRUPT) {
|
||||
chip_interrupt_run(dev);
|
||||
} else {
|
||||
MSENSOR_ERR_TRACE("not triger_mode %d\n",g_triger_data[dev].triger_mode);
|
||||
return XMEDIA_FAILURE;
|
||||
}
|
||||
|
||||
g_msensor_start[dev] = XMEDIA_TRUE;
|
||||
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_drv_user_stop(xmedia_s32 dev, xmedia_uintptr_t arg)
|
||||
{
|
||||
if (g_msensor_init[dev] == XMEDIA_FALSE) {
|
||||
MSENSOR_ERR_TRACE("dev %d msensor is not init!\n", dev);
|
||||
return XMEDIA_FAILURE;
|
||||
}
|
||||
|
||||
if (g_msensor_start[dev] == XMEDIA_FALSE) {
|
||||
MSENSOR_ERR_TRACE("dev %d msensor is already stop!\n", dev);
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
xmedia_unused(arg);
|
||||
|
||||
if (g_triger_data[dev].triger_mode == TRIGER_TIMER) {
|
||||
chip_timer_stop(dev);
|
||||
} else if (g_triger_data[dev].triger_mode == TRIGER_EXTERN_INTERRUPT) {
|
||||
chip_interrupt_stop(dev);
|
||||
} else {
|
||||
MSENSOR_ERR_TRACE("not triger_mode %d\n",g_triger_data[dev].triger_mode);
|
||||
return XMEDIA_FAILURE;
|
||||
}
|
||||
|
||||
g_msensor_start[dev] = XMEDIA_FALSE;
|
||||
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_drv_user_init(xmedia_s32 dev, xmedia_uintptr_t arg)
|
||||
{
|
||||
xmedia_s32 ret;
|
||||
xmedia_msensor_param *msensor_param;
|
||||
|
||||
if (g_msensor_init[dev] == XMEDIA_TRUE) {
|
||||
MSENSOR_ERR_TRACE("dev %d msensor is already inited!\n", dev);
|
||||
return XMEDIA_FAILURE;
|
||||
}
|
||||
msensor_param = (xmedia_msensor_param *)(arg);
|
||||
ret = mmz_check_phyaddr(msensor_param->buf_attr.phys_addr, msensor_param->buf_attr.buf_len);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
MSENSOR_ERR_TRACE("dev %d check mem share failed, buf_attr.phys_addr is 0x%llx\n", dev,
|
||||
msensor_param->buf_attr.phys_addr);
|
||||
return XMEDIA_FAILURE;
|
||||
}
|
||||
|
||||
osal_memcpy(g_msensor_param[dev], (xmedia_void *)arg, sizeof(xmedia_msensor_param));
|
||||
|
||||
if (((XMEDIA_MSENSOR_DEVICE_GYRO & g_msensor_param[dev]->attr.device_mask) &&
|
||||
(g_msensor_param[dev]->config.gyro_config.odr == 0)) ||
|
||||
((XMEDIA_MSENSOR_DEVICE_ACC & g_msensor_param[dev]->attr.device_mask) &&
|
||||
(g_msensor_param[dev]->config.acc_config.odr == 0))) {
|
||||
MSENSOR_ERR_TRACE("dev %d msensor param err!\n", dev);
|
||||
return XMEDIA_FAILURE;
|
||||
}
|
||||
|
||||
g_msensor_param[dev]->config.gyro_config.temperature_max = MOTIONSENSOR_MAX_TEMP;
|
||||
g_msensor_param[dev]->config.gyro_config.temperature_min = MOTIONSENSOR_MIN_TEMP;
|
||||
g_msensor_param[dev]->config.acc_config.temperature_max = MOTIONSENSOR_MAX_TEMP;
|
||||
g_msensor_param[dev]->config.acc_config.temperature_min = MOTIONSENSOR_MIN_TEMP;
|
||||
/* init senser */
|
||||
ret = chip_dev_init(dev, g_msensor_param[dev]);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
MSENSOR_ERR_TRACE("dev %d chip dev init failed! ret=%x\n", dev, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = chip_get_triger_config(dev, &g_triger_data[dev]);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
MSENSOR_ERR_TRACE("dev %d imu get triger config failed! ret=%x\n", dev, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef MNGBUFF_ENABLE
|
||||
/* buff init, fix in this */
|
||||
msensor_chip_init_mng_buf(dev, g_msensor_param[dev]->attr, &g_msensor_param[dev]->buf_attr,
|
||||
&g_msensor_param[dev]->config);
|
||||
#endif
|
||||
g_msensor_init[dev] = XMEDIA_TRUE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_drv_user_deinit(xmedia_s32 dev, xmedia_uintptr_t arg)
|
||||
{
|
||||
xmedia_s32 ret = XMEDIA_SUCCESS;
|
||||
|
||||
if (g_msensor_init[dev] == XMEDIA_FALSE) {
|
||||
MSENSOR_ERR_TRACE("dev %d msensor has not inited!\n", dev);
|
||||
return XMEDIA_FAILURE;
|
||||
}
|
||||
|
||||
if (g_msensor_start[dev] == XMEDIA_TRUE) {
|
||||
MSENSOR_ERR_TRACE("dev %d please stop msensor first!\n", dev);
|
||||
return XMEDIA_FAILURE;
|
||||
}
|
||||
|
||||
xmedia_unused(arg);
|
||||
|
||||
g_msensor_init[dev] = XMEDIA_FALSE;
|
||||
chip_dev_exit(dev, g_msensor_param[dev]);
|
||||
#ifdef MNGBUFF_ENABLE
|
||||
ret = msensor_chip_exit_mng_buf(dev);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
MSENSOR_ERR_TRACE("dev %d exit mng buf failed! ret=%x\n", dev, ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_drv_user_get_param(xmedia_s32 dev, xmedia_uintptr_t arg)
|
||||
{
|
||||
xmedia_s32 ret;
|
||||
|
||||
ret = mmz_check_phyaddr(g_msensor_param[dev]->buf_attr.phys_addr, g_msensor_param[dev]->buf_attr.buf_len);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
MSENSOR_ERR_TRACE("dev %d check mem share failed, buf_attr.phys_addr is 0x%llx\n", dev,
|
||||
g_msensor_param[dev]->buf_attr.phys_addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
osal_memcpy((xmedia_msensor_param *)arg, g_msensor_param[dev], sizeof(xmedia_msensor_param));
|
||||
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
/* only for debug: send and save yuv */
|
||||
static xmedia_s32 msensor_chip_drv_user_mng_init(xmedia_s32 dev, xmedia_uintptr_t arg)
|
||||
{
|
||||
xmedia_s32 ret;
|
||||
xmedia_msensor_param *msensor_param = XMEDIA_NULL;
|
||||
|
||||
if (g_msensor_init[dev] == XMEDIA_TRUE) {
|
||||
MSENSOR_ERR_TRACE("dev %d msensor is already inited!\n", dev);
|
||||
return XMEDIA_FAILURE;
|
||||
}
|
||||
msensor_param = (xmedia_msensor_param *)(arg);
|
||||
ret = mmz_check_phyaddr(msensor_param->buf_attr.phys_addr, msensor_param->buf_attr.buf_len);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
MSENSOR_ERR_TRACE("dev %d check mem share failed, buf_attr.phys_addr is 0x%llx\n",
|
||||
dev, msensor_param->buf_attr.phys_addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
osal_memcpy(g_msensor_param[dev], (xmedia_void *)arg, sizeof(xmedia_msensor_param));
|
||||
|
||||
if (((XMEDIA_MSENSOR_DEVICE_GYRO & g_msensor_param[dev]->attr.device_mask) &&
|
||||
(g_msensor_param[dev]->config.gyro_config.odr == 0)) ||
|
||||
((XMEDIA_MSENSOR_DEVICE_ACC & g_msensor_param[dev]->attr.device_mask) &&
|
||||
(g_msensor_param[dev]->config.acc_config.odr == 0))) {
|
||||
MSENSOR_ERR_TRACE("dev %d msensor param error\n", dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* init senser */
|
||||
ret = chip_dev_mng_init(dev, g_msensor_param[dev]);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
MSENSOR_ERR_TRACE("dev %d mng init failed! ret=%x\n", dev, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef MNGBUFF_ENABLE
|
||||
/* buff init, fix in this */
|
||||
msensor_chip_init_mng_buf(dev, g_msensor_param[dev]->attr, &g_msensor_param[dev]->buf_attr,
|
||||
&g_msensor_param[dev]->config);
|
||||
#endif
|
||||
g_msensor_init[dev] = XMEDIA_TRUE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_drv_start(xmedia_s32 dev, xmedia_ulong arg)
|
||||
{
|
||||
return msensor_chip_drv_user_start(dev, (xmedia_uintptr_t)arg);
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_drv_stop(xmedia_s32 dev, xmedia_ulong arg)
|
||||
{
|
||||
return msensor_chip_drv_user_stop(dev, (xmedia_uintptr_t)arg);
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_drv_init(xmedia_s32 dev, xmedia_ulong arg)
|
||||
{
|
||||
return msensor_chip_drv_user_init(dev, (xmedia_uintptr_t)arg);
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_drv_deinit(xmedia_s32 dev, xmedia_ulong arg)
|
||||
{
|
||||
return msensor_chip_drv_user_deinit(dev, (xmedia_uintptr_t)arg);
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_drv_get_param(xmedia_s32 dev, xmedia_ulong arg)
|
||||
{
|
||||
return msensor_chip_drv_user_get_param(dev, (xmedia_uintptr_t)arg);
|
||||
}
|
||||
|
||||
/* only for debug: send and save yuv */
|
||||
static xmedia_s32 msensor_chip_drv_mng_init(xmedia_s32 dev, xmedia_ulong arg)
|
||||
{
|
||||
return msensor_chip_drv_user_mng_init(dev, (xmedia_uintptr_t)arg);
|
||||
}
|
||||
|
||||
typedef xmedia_s32 (*msensor_ctl_ptr_func)(xmedia_s32 dev, xmedia_ulong arg);
|
||||
|
||||
typedef struct {
|
||||
xmedia_u32 cmd;
|
||||
msensor_ctl_ptr_func ptr_func;
|
||||
} msensor_ioctl_func_item;
|
||||
|
||||
static msensor_ioctl_func_item g_msensor_chip_cmd_list[] = {
|
||||
{ MSENSOR_CMD_START, msensor_chip_drv_start },
|
||||
{ MSENSOR_CMD_STOP, msensor_chip_drv_stop },
|
||||
{ MSENSOR_CMD_CREATE, msensor_chip_drv_init },
|
||||
{ MSENSOR_CMD_DESTROY, msensor_chip_drv_deinit },
|
||||
{ MSENSOR_CMD_GET_PARAM, msensor_chip_drv_get_param },
|
||||
{ MSENSOR_CMD_MNG_INIT, msensor_chip_drv_mng_init }, /* only for debug: send and save yuv */
|
||||
};
|
||||
|
||||
static xmedia_s32 msensor_chip_do_ioctl(xmedia_s32 dev, xmedia_u32 cmd, xmedia_ulong arg)
|
||||
{
|
||||
xmedia_s32 i;
|
||||
|
||||
for (i = 0; i < sizeof(g_msensor_chip_cmd_list) / sizeof(g_msensor_chip_cmd_list[0]); i++) {
|
||||
if (cmd == g_msensor_chip_cmd_list[i].cmd) {
|
||||
return g_msensor_chip_cmd_list[i].ptr_func(dev, arg);
|
||||
}
|
||||
}
|
||||
|
||||
MSENSOR_ERR_TRACE("dev %d msensor chip ioctl cmd 0x%x not supported!\n", dev, cmd);
|
||||
|
||||
return XMEDIA_ERRCODE_NOT_SUPPORT;
|
||||
}
|
||||
xmedia_slong msensor_chip_ioctl(xmedia_u32 cmd, xmedia_ulong arg, xmedia_void *private_data)
|
||||
{
|
||||
xmedia_s32 ret;
|
||||
xmedia_s32 dev;
|
||||
|
||||
if (cmd == MSENSOR_CMD_CHIP_BIND_FLAG2FD) {
|
||||
*(xmedia_u32 *)private_data = *(xmedia_u32 *)arg;
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
dev = *(xmedia_u32 *)private_data;
|
||||
|
||||
osal_atomic_inc_return(&g_msensor_chip_user_ref[dev]);
|
||||
|
||||
ret = msensor_chip_do_ioctl(dev, cmd, arg);
|
||||
|
||||
osal_atomic_dec_return(&g_msensor_chip_user_ref[dev]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct osal_fileops g_msensor_chip_fileop = {
|
||||
.open = msensor_chip_open,
|
||||
.unlocked_ioctl = msensor_chip_ioctl,
|
||||
.release = msensor_chip_release,
|
||||
};
|
||||
|
||||
struct osal_pmops g_msensor_chip_drv_ops = {
|
||||
.pm_freeze = msensor_chip_freeze,
|
||||
.pm_restore = msensor_chip_restore,
|
||||
};
|
||||
|
||||
static xmedia_s32 msensor_chip_param_init(xmedia_void)
|
||||
{
|
||||
xmedia_s32 i ,j;
|
||||
|
||||
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
|
||||
g_msensor_param[i] = (xmedia_msensor_param *)osal_kmalloc(sizeof(xmedia_msensor_param), osal_gfp_kernel);
|
||||
if (g_msensor_param[i] == XMEDIA_NULL) {
|
||||
osal_printk("kmalloc memory failed\n");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
(xmedia_void) osal_memset(g_msensor_param[i], 0, sizeof(xmedia_msensor_param));
|
||||
g_msensor_start[i] = XMEDIA_FALSE;
|
||||
}
|
||||
return XMEDIA_SUCCESS;
|
||||
|
||||
failed:
|
||||
for (j = i - 1; j >= 0; j--) {
|
||||
osal_kfree(g_msensor_param[j]);
|
||||
}
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_param_exit(xmedia_void)
|
||||
{
|
||||
xmedia_s32 i;
|
||||
|
||||
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
|
||||
if(g_msensor_param[i] == XMEDIA_NULL) {
|
||||
osal_printk("msensor_param is null, nothing to exit \n");
|
||||
} else {
|
||||
osal_kfree(g_msensor_param[i]);
|
||||
g_msensor_param[i] = XMEDIA_NULL;
|
||||
}
|
||||
g_msensor_start[i] = XMEDIA_FALSE;
|
||||
}
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_sensor_init(xmedia_void)
|
||||
{
|
||||
xmedia_s32 ret;
|
||||
xmedia_s32 i , j;
|
||||
|
||||
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
|
||||
ret = chip_sensor_init(i);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
osal_printk("init sensor! failed ret=%x\n", ret);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
return XMEDIA_SUCCESS;
|
||||
failed:
|
||||
for (j = i - 1; j >= 0; j--) {
|
||||
chip_sensor_exit(j);
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static xmedia_void msensor_chip_sensor_exit(xmedia_void)
|
||||
{
|
||||
xmedia_s32 i;
|
||||
|
||||
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
|
||||
chip_sensor_exit(i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_register_mng_callback_init(xmedia_void)
|
||||
{
|
||||
xmedia_s32 ret;
|
||||
xmedia_s32 i;
|
||||
|
||||
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
|
||||
ret = msensor_chip_register_mng_callback(i);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
osal_printk("register mng callback failed! ret=%x\n", ret);
|
||||
return XMEDIA_FAILURE;
|
||||
}
|
||||
}
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
static xmedia_void msensor_chip_register_mng_callback_exit(xmedia_void)
|
||||
{
|
||||
xmedia_s32 i;
|
||||
|
||||
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
|
||||
msensor_chip_unregister_mng_callback(i);
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_atomic_init(xmedia_void)
|
||||
{
|
||||
xmedia_s32 ret;
|
||||
xmedia_s32 i ,j;
|
||||
|
||||
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
|
||||
ret = osal_atomic_init(&g_msensor_chip_user_ref[i]);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
osal_printk("atomic init failed. \n");
|
||||
goto failed;
|
||||
}
|
||||
osal_atomic_set(&g_msensor_chip_user_ref[i], 0);
|
||||
}
|
||||
return XMEDIA_SUCCESS;
|
||||
failed:
|
||||
for (j = i - 1; j >= 0; j--) {
|
||||
osal_atomic_destory(&g_msensor_chip_user_ref[j]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static xmedia_void msensor_chip_atomic_exit(xmedia_void)
|
||||
{
|
||||
xmedia_s32 i;
|
||||
|
||||
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
|
||||
osal_atomic_destroy(&g_msensor_chip_user_ref[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
xmedia_s32 msensor_chip_module_init(xmedia_void)
|
||||
{
|
||||
xmedia_s32 ret;
|
||||
|
||||
ret = msensor_chip_param_init();
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
osal_printk("init param failed! ret=%x\n", ret);
|
||||
goto FAIL0;
|
||||
}
|
||||
|
||||
ret = msensor_chip_sensor_init();
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
osal_printk("init sensor failed! ret=%x\n", ret);
|
||||
goto FAIL1;
|
||||
}
|
||||
|
||||
#ifdef MNGBUFF_ENABLE
|
||||
ret = msensor_chip_register_mng_callback_init();
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
osal_printk("init sensor failed! ret=%x\n", ret);
|
||||
goto FAIL2;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = msensor_chip_atomic_init();
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
osal_printk("init sensor failed! ret=%x\n", ret);
|
||||
goto FAIL3;
|
||||
}
|
||||
|
||||
g_msensor_chip_dev = osal_createdev(UMAP_DEVNANME_MSENSOR_CHIP_BASE);
|
||||
if (g_msensor_chip_dev == XMEDIA_NULL) {
|
||||
osal_printk("msensor: create device failed\n");
|
||||
goto FAIL4;
|
||||
}
|
||||
|
||||
g_msensor_chip_dev->fops = &g_msensor_chip_fileop;
|
||||
g_msensor_chip_dev->minor = UMAP_MSENSOR_CHIP_MINOR_BASE;
|
||||
g_msensor_chip_dev->osal_pmops = &g_msensor_chip_drv_ops;
|
||||
ret = osal_registerdevice(g_msensor_chip_dev);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
osal_printk("register msensor device failed!\n");
|
||||
goto FAIL5;
|
||||
}
|
||||
|
||||
#if (defined CONFIG_PROC_SHOW_SUPPORT) && (defined ICM42670_PARAM_PROC)
|
||||
ret = mpu_proc_init();
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
goto FAIL6;
|
||||
}
|
||||
#endif
|
||||
osal_printk("load xm_msensor_chip.ko OK!\n");
|
||||
return XMEDIA_SUCCESS;
|
||||
|
||||
FAIL6:
|
||||
osal_deregisterdevice(g_msensor_chip_dev);
|
||||
FAIL5:
|
||||
osal_destroydev(g_msensor_chip_dev);
|
||||
FAIL4:
|
||||
msensor_chip_atomic_exit();
|
||||
FAIL3:
|
||||
msensor_chip_register_mng_callback_exit();
|
||||
FAIL2:
|
||||
msensor_chip_sensor_exit();
|
||||
FAIL1:
|
||||
msensor_chip_param_exit();
|
||||
FAIL0:
|
||||
osal_printk("load xm_msensor_chip.ko failed !\n");
|
||||
return XMEDIA_FAILURE;
|
||||
}
|
||||
|
||||
xmedia_void msensor_chip_module_exit(xmedia_void)
|
||||
{
|
||||
msensor_chip_atomic_exit();
|
||||
#ifdef MNGBUFF_ENABLE
|
||||
msensor_chip_register_mng_callback_exit();
|
||||
#endif
|
||||
msensor_chip_sensor_exit();
|
||||
msensor_chip_param_exit();
|
||||
osal_deregisterdevice(g_msensor_chip_dev);
|
||||
osal_destroydev(g_msensor_chip_dev);
|
||||
|
||||
#if (defined CONFIG_PROC_SHOW_SUPPORT)
|
||||
mpu_proc_exit();
|
||||
#endif
|
||||
|
||||
osal_printk("unload xm_msensor_chip.ko OK!\n");
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
module_init(msensor_chip_module_init);
|
||||
module_exit(msensor_chip_module_exit);
|
||||
|
||||
MODULE_AUTHOR("otlicon");
|
||||
MODULE_DESCRIPTION("motion_sensor driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
#else
|
||||
int __init msensor_chip_driver_init(void)
|
||||
{
|
||||
return msensor_chip_module_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c); XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __MSENSOR_H__
|
||||
#define __MSENSOR_H__
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sched.h>
|
||||
#include "xmedia_msensor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* end of #ifdef __cplusplus */
|
||||
|
||||
#define MNGBUFF_ENABLE
|
||||
|
||||
#define DATA_RATE_RESERVED 0x00
|
||||
#define DATA_RATE_25HZ 0x06
|
||||
#define DATA_RATE_50HZ 0x07
|
||||
#define DATA_RATE_100HZ 0x08
|
||||
#define DATA_RATE_200HZ 0x09
|
||||
#define DATA_RATE_400HZ 0x0A
|
||||
#define DATA_RATE_800HZ 0x0B
|
||||
#define DATA_RATE_1600HZ 0x0C
|
||||
#define DATA_RATE_3200HZ 0x0D
|
||||
|
||||
#define GYRO_FULL_SCALE_RANGE_250DPS (250 << 10)
|
||||
#define GYRO_FULL_SCALE_RANGE_500DPS (500 << 10)
|
||||
#define GYRO_FULL_SCALE_RANGE_1KDPS (1000 << 10)
|
||||
#define GYRO_FULL_SCALE_RANGE_2KDPS (2000 << 10)
|
||||
#define GYRO_FULL_SCALE_RANGE_31DPS ((3125 << 10) / 100)
|
||||
#define GYRO_FULL_SCALE_RANGE_62DPS ((625 << 10) / 10)
|
||||
#define GYRO_FULL_SCALE_RANGE_125DPS (125 << 10)
|
||||
|
||||
#define ACCEL_UI_FULL_SCALE_RANGE_2G 1
|
||||
#define ACCEL_UI_FULL_SCALE_RANGE_4G 2
|
||||
#define ACCEL_UI_FULL_SCALE_RANGE_8G 3
|
||||
#define ACCEL_UI_FULL_SCALE_RANGE_16G 4
|
||||
|
||||
#define ACCEL_OIS_FULL_SCALE_RANGE_1G 5
|
||||
#define ACCEL_OIS_FULL_SCALE_RANGE_2G 6
|
||||
#define ACCEL_OIS_FULL_SCALE_RANGE_4G 7
|
||||
#define ACCEL_OIS_FULL_SCALE_RANGE_8G 8
|
||||
|
||||
#define MOTIONSENSOR_MAX_TEMP 85
|
||||
#define MOTIONSENSOR_MIN_TEMP (-40)
|
||||
|
||||
typedef enum {
|
||||
GYRO_OUTPUT_DATA_RATE_32KHZ = 32000,
|
||||
GYRO_OUTPUT_DATA_RATE_8KHZ = 8000,
|
||||
GYRO_OUTPUT_DATA_RATE_3200HZ = 3200,
|
||||
GYRO_OUTPUT_DATA_RATE_1600HZ = 1600,
|
||||
GYRO_OUTPUT_DATA_RATE_800HZ = 800,
|
||||
GYRO_OUTPUT_DATA_RATE_400HZ = 400,
|
||||
GYRO_OUTPUT_DATA_RATE_200HZ = 200,
|
||||
GYRO_OUTPUT_DATA_RATE_100HZ = 100,
|
||||
GYRO_OUTPUT_DATA_RATE_50HZ = 50,
|
||||
GYRO_OUTPUT_DATA_RATE_25HZ = 25,
|
||||
GYRO_OUTPUT_DATA_RATE_UNDER_1KHZ,
|
||||
GYRO_OUTPUT_DATA_RATE_BUTT
|
||||
} msensor_gyro_output_data_rate;
|
||||
|
||||
typedef enum {
|
||||
GYRO_BAND_WIDTH_16HZ,
|
||||
GYRO_BAND_WIDTH_25HZ,
|
||||
GYRO_BAND_WIDTH_34HZ,
|
||||
GYRO_BAND_WIDTH_53HZ,
|
||||
GYRO_BAND_WIDTH_73HZ,
|
||||
GYRO_BAND_WIDTH_121HZ,
|
||||
GYRO_BAND_WIDTH_180HZ,
|
||||
GYRO_BAND_WIDTH_BUTT
|
||||
} msensor_gyro_band_width;
|
||||
|
||||
typedef enum {
|
||||
ACCEL_OUTPUT_DATA_RATE_4KHZ = 4000,
|
||||
ACCEL_OUTPUT_DATA_RATE_1KHZ = 1000,
|
||||
ACCEL_OUTPUT_DATA_RATE_1600HZ = 1600,
|
||||
ACCEL_OUTPUT_DATA_RATE_800HZ = 800,
|
||||
ACCEL_OUTPUT_DATA_RATE_400HZ = 400,
|
||||
ACCEL_OUTPUT_DATA_RATE_200HZ = 200,
|
||||
ACCEL_OUTPUT_DATA_RATE_100HZ = 100,
|
||||
ACCEL_OUTPUT_DATA_RATE_50HZ = 50,
|
||||
ACCEL_OUTPUT_DATA_RATE_25HZ = 25,
|
||||
ACCEL_OUTPUT_DATA_RATE_UNDER_1KHZ,
|
||||
ACCEL_OUTPUT_DATA_RATE_BUTT
|
||||
} msensor_accel_output_data_rate;
|
||||
|
||||
typedef enum {
|
||||
GYRO_FULL_SCALE_SET_250DPS = 250 << 10, /* 250 dps */
|
||||
GYRO_FULL_SCALE_SET_500DPS = 500 << 10, /* 500 dps */
|
||||
GYRO_FULL_SCALE_SET_1KDPS = 1000 << 10, /* 1000 dps */
|
||||
GYRO_FULL_SCALE_SET_2KDPS = 2000 << 10, /* 2000 dps */
|
||||
GYRO_FULL_SCALE_SET_31DPS = (3125 << 10) / 100, /* 31.25 dps : 3125 / 100 */
|
||||
GYRO_FULL_SCALE_SET_62DPS = (625 << 10) / 10, /* 62.5 dps : 625 / 10 */
|
||||
GYRO_FULL_SCALE_SET_125DPS = 125 << 10, /* 125 dps */
|
||||
GYRO_FULL_SCALE_SET_BUTT
|
||||
} msensor_gyro_full_scale_range;
|
||||
|
||||
typedef enum {
|
||||
ACCEL_UI_FULL_SCALE_SET_2G = 2 << 10,
|
||||
ACCEL_UI_FULL_SCALE_SET_4G = 4 << 10,
|
||||
ACCEL_UI_FULL_SCALE_SET_8G = 8 << 10,
|
||||
ACCEL_UI_FULL_SCALE_SET_16G = 16 << 10,
|
||||
ACCEL_UI_FULL_SCALE_SET_BUTT
|
||||
} msensor_accel_ui_full_scale_range;
|
||||
|
||||
typedef enum {
|
||||
ACCEL_OIS_FULL_SCALE_SET_1G = 1,
|
||||
ACCEL_OIS_FULL_SCALE_SET_2G = 2,
|
||||
ACCEL_OIS_FULL_SCALE_SET_4G = 4,
|
||||
ACCEL_OIS_FULL_SCALE_SET_8G = 8,
|
||||
ACCEL_OIS_FULL_SCALE_SET_BUTT
|
||||
} msensor_accel_ois_full_scale_range;
|
||||
|
||||
typedef enum {
|
||||
ACCEL_BAND_WIDTH_16HZ,
|
||||
ACCEL_BAND_WIDTH_25HZ,
|
||||
ACCEL_BAND_WIDTH_34HZ,
|
||||
ACCEL_BAND_WIDTH_53HZ,
|
||||
ACCEL_BAND_WIDTH_73HZ,
|
||||
ACCEL_BAND_WIDTH_121HZ,
|
||||
ACCEL_BAND_WIDTH_180HZ,
|
||||
ACCEL_BAND_WIDTH_BUTT
|
||||
} msensor_accel_band_width;
|
||||
|
||||
typedef enum {
|
||||
TRIGER_TIMER = 0,
|
||||
TRIGER_EXTERN_INTERRUPT,
|
||||
TRIGER_BUTT
|
||||
} msensor_triger_mode;
|
||||
|
||||
typedef struct {
|
||||
xmedia_u32 interval; /* unit :us */
|
||||
} timer_param;
|
||||
|
||||
typedef struct {
|
||||
xmedia_u32 interrupt_num;
|
||||
} extern_interrupt_param;
|
||||
|
||||
typedef union {
|
||||
timer_param timer_config;
|
||||
extern_interrupt_param extern_interrupt_config;
|
||||
} msensor_triger_info;
|
||||
|
||||
typedef struct {
|
||||
msensor_triger_mode triger_mode;
|
||||
msensor_triger_info triger_info;
|
||||
} triger_config;
|
||||
|
||||
typedef struct {
|
||||
xmedia_u32 cmd;
|
||||
xmedia_s32 (*func)(xmedia_uintptr_t arg);
|
||||
} msensor_chip_info;
|
||||
|
||||
xmedia_msensor_param *msensor_chip_get_param(xmedia_s32 dev);
|
||||
xmedia_bool msensor_chip_get_status(xmedia_s32 dev);
|
||||
xmedia_s32 msensor_chip_int_callback(xmedia_s32 dev, xmedia_msensor_data *msensor_data);
|
||||
|
||||
#define print_info(fmt, arg...) osal_printk("fun:%s,%d " fmt, __func__, __LINE__, ##arg)
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* end of #ifdef __cplusplus */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c); XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "msensor_chip_proc.h"
|
||||
#include <linux/kernel.h>
|
||||
#include "osal.h"
|
||||
#include "msensor.h"
|
||||
#include "icm42670.h"
|
||||
|
||||
#define MSENSOR_CHIP_INFO "msensor_chip"
|
||||
#define MSENSOR_CHIP_VERSION_INFO "msensor_chip debug 0.0.0.1"
|
||||
|
||||
static xmedia_char *msensor_triger_mode2_str(msensor_triger_mode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case TRIGER_TIMER:
|
||||
return "TIMER";
|
||||
case TRIGER_EXTERN_INTERRUPT:
|
||||
return "GPIO_INTERRUPT";
|
||||
default:
|
||||
return "error";
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
|
||||
static xmedia_void msensor_print_proc_title(osal_proc_entry_t *s, xmedia_char *title)
|
||||
{
|
||||
xmedia_s32 i;
|
||||
|
||||
for (i = 0; i < 50; i++) {
|
||||
osal_seq_printf(s, "-");
|
||||
}
|
||||
|
||||
osal_seq_printf(s, title);
|
||||
|
||||
for (i = 0; i < 50; i++) {
|
||||
osal_seq_printf(s, "-");
|
||||
}
|
||||
osal_seq_printf(s, "\n");
|
||||
}
|
||||
|
||||
static xmedia_s32 msensor_chip_proc_show(osal_proc_entry_t *s)
|
||||
{
|
||||
xmedia_s32 i;
|
||||
xmedia_msensor_param *msensor_param = XMEDIA_NULL;
|
||||
icm42670_dev_info *dev_info = XMEDIA_NULL;
|
||||
|
||||
|
||||
osal_seq_printf(s,
|
||||
"[msensor] version:[" MSENSOR_CHIP_VERSION_INFO "], build time["__DATE__
|
||||
", "__TIME__
|
||||
"]\n");
|
||||
|
||||
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
|
||||
if(msensor_chip_get_status(i) == XMEDIA_FALSE) {
|
||||
continue;
|
||||
}
|
||||
msensor_param = msensor_chip_get_param(i);
|
||||
dev_info = chip_get_dev_info(i);
|
||||
msensor_print_proc_title(s, "common parameter");
|
||||
osal_seq_printf(s, "%24s %24s %24s\n", "dev_no", "trigle_mode", "fifo_en");
|
||||
osal_seq_printf(s, "%24d %24s %24d\n", i, msensor_triger_mode2_str(dev_info->triger_data.triger_mode), dev_info->fifo_en);
|
||||
|
||||
if (msensor_param->attr.device_mask & XMEDIA_MSENSOR_DEVICE_GYRO) {
|
||||
msensor_print_proc_title(s, "gyro parameter");
|
||||
osal_seq_printf(s, "%24s\n", "##ICM42670##");
|
||||
|
||||
osal_seq_printf(s, "%24s %24s %24s %24s %24s\n", "sample_rate", "full-scale-range", "datawidth",
|
||||
"max-chip-temperature", "min-chip-temperature");
|
||||
osal_seq_printf(s, "%24d %24d %24d %24d %24d\n", msensor_param->config.gyro_config.odr,
|
||||
msensor_param->config.gyro_config.fsr, msensor_param->config.gyro_config.data_width,
|
||||
msensor_param->config.gyro_config.temperature_max,
|
||||
msensor_param->config.gyro_config.temperature_min);
|
||||
}
|
||||
if (msensor_param->attr.device_mask & XMEDIA_MSENSOR_DEVICE_ACC) {
|
||||
msensor_print_proc_title(s, "accelerometer parameter");
|
||||
|
||||
osal_seq_printf(s, "%24s\n", "##ICM42670##");
|
||||
|
||||
osal_seq_printf(s, "%24s %24s %24s %24s %24s\n", "sample_rate", "full-scale-range", "datawidth",
|
||||
"max-chip-temperature", "min-chip-temperature");
|
||||
osal_seq_printf(s, "%24d %24d %24d %24d %24d\n", msensor_param->config.acc_config.odr,
|
||||
msensor_param->config.acc_config.fsr, msensor_param->config.acc_config.data_width,
|
||||
msensor_param->config.acc_config.temperature_max,
|
||||
msensor_param->config.acc_config.temperature_min);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
xmedia_s32 mpu_proc_init(xmedia_void)
|
||||
{
|
||||
osal_proc_entry_t *msensor_chip_entry = XMEDIA_NULL;
|
||||
|
||||
msensor_chip_entry = osal_create_proc_entry(MSENSOR_CHIP_INFO, XMEDIA_NULL);
|
||||
if (msensor_chip_entry == XMEDIA_NULL) {
|
||||
printk("osal_create_proc_entry failed!\n");
|
||||
return XMEDIA_FAILURE;
|
||||
}
|
||||
|
||||
msensor_chip_entry->read = msensor_chip_proc_show;
|
||||
msensor_chip_entry->write = XMEDIA_NULL;
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
void mpu_proc_exit(xmedia_void)
|
||||
{
|
||||
osal_remove_proc_entry(MSENSOR_CHIP_INFO, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c); XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __MSENSOR_CHIP_PROC_H__
|
||||
#define __MSENSOR_CHIP_PROC_H__
|
||||
|
||||
#include "xmedia_type.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define MAX_LEN 32
|
||||
|
||||
xmedia_s32 mpu_proc_init(xmedia_void);
|
||||
xmedia_void mpu_proc_exit(xmedia_void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* end of #ifdef __cplusplus */
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c); XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ICM42670_H
|
||||
#define ICM42670_H
|
||||
|
||||
#include "msensor.h"
|
||||
#include "osal.h"
|
||||
#include "linux/workqueue.h"
|
||||
#include "linux/hrtimer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* end of #ifdef __cplusplus */
|
||||
|
||||
#define ICM42670_DEV_ADDR 0x68
|
||||
#define I2C_DEV_NUM 0x1
|
||||
|
||||
#define ICM42670_VALID_DATA_BIT 16
|
||||
|
||||
#define div_0_to_1(a) (((a) == 0) ? 1 : (a))
|
||||
|
||||
#define TRUE_REGISTER_VALUE 0x01
|
||||
#define RESET_OFFSET 0x04
|
||||
#define CLKSET_VALUE 0x01
|
||||
|
||||
// MREGs
|
||||
#define MREG1 0
|
||||
#define MREG2 1
|
||||
#define MREG3 2
|
||||
|
||||
#define ICM42670_SELFID 0x67 // ICM42670 device id default value
|
||||
#define ICM42670_FIFO_MAX_RECORD 140
|
||||
#define ICM42670_FIFO_R_MAX_SIZE 1152
|
||||
|
||||
#define ROOMTEMP_OFFSET (25 * (0x1 << 10))
|
||||
#define GRADIENT_TEMP (0x1 << 10)
|
||||
#define TEMP_SENSITIVITY 128
|
||||
|
||||
/* icm42670 interrupt pin reg */
|
||||
#define INT_GPIO_CHIP 4 //7
|
||||
#define INT_GPIO_OFFSET 6 //2
|
||||
|
||||
#define TIME_RECORD_CNT 10
|
||||
#define DATA_RECORD_CNT (TIME_RECORD_CNT)
|
||||
|
||||
typedef struct {
|
||||
xmedia_msensor_gyro_config gyro_config;
|
||||
xmedia_u32 band_width;
|
||||
xmedia_u64 last_pts;
|
||||
} msensor_gyro_status;
|
||||
|
||||
typedef struct {
|
||||
xmedia_msensor_acc_config acc_config;
|
||||
xmedia_u32 band_width;
|
||||
xmedia_u64 last_pts;
|
||||
} msensor_acc_status;
|
||||
|
||||
typedef struct {
|
||||
xmedia_msensor_sample_data accel_cur_data;
|
||||
xmedia_msensor_sample_data gyro_cur_data;
|
||||
xmedia_msensor_sample_data magn_data;
|
||||
struct i2c_client *client;
|
||||
struct spi_device *xmedia_spi;
|
||||
struct task_struct *read_data_task;
|
||||
struct task_struct *get_data_kthread;
|
||||
osal_work_struct_t work;
|
||||
xmedia_u8 power_mode;
|
||||
xmedia_u8 flag_acc_fifo_enabled;
|
||||
xmedia_u8 flag_gyro_fifo_enabled;
|
||||
xmedia_u8 flag_fifo_incomming;
|
||||
xmedia_u8 *fifo_buf;
|
||||
xmedia_u32 fifo_length;
|
||||
xmedia_u8 record_num;
|
||||
xmedia_u8 enable_kthread;
|
||||
xmedia_u8 fifo_en;
|
||||
triger_config triger_data;
|
||||
struct hrtimer hrtimer;
|
||||
xmedia_u8 thread_wakeup;
|
||||
osal_semaphore_t g_sem;
|
||||
msensor_acc_status acc_status;
|
||||
msensor_gyro_status gyro_status;
|
||||
xmedia_s32 temperature;
|
||||
xmedia_s32 irq_num;
|
||||
xmedia_s32 workqueue_call_times;
|
||||
osal_wait_t wait_call_stop_working;
|
||||
} icm42670_dev_info;
|
||||
|
||||
icm42670_dev_info *chip_get_dev_info(xmedia_s32 dev);
|
||||
xmedia_s32 chip_fifo_data_reset(xmedia_s32 dev);
|
||||
xmedia_s32 chip_get_triger_config(xmedia_s32 dev, triger_config *triger_data);
|
||||
|
||||
xmedia_s32 chip_dev_init(xmedia_s32 dev, xmedia_msensor_param *msensor_param);
|
||||
xmedia_s32 chip_dev_mng_init(xmedia_s32 dev, xmedia_msensor_param *msensor_param);
|
||||
xmedia_void chip_dev_exit(xmedia_s32 dev, xmedia_msensor_param *msensor_param);
|
||||
|
||||
xmedia_s32 chip_sensor_init(xmedia_s32 dev);
|
||||
xmedia_void chip_sensor_exit(xmedia_s32 dev);
|
||||
xmedia_s32 chip_timer_run(xmedia_s32 dev);
|
||||
xmedia_s32 chip_interrupt_run(xmedia_s32 dev);
|
||||
xmedia_s32 chip_timer_stop(xmedia_s32 dev);
|
||||
xmedia_s32 chip_interrupt_stop(xmedia_s32 dev);
|
||||
xmedia_s32 chip_get_data_for_one_frm(xmedia_s32 dev);
|
||||
|
||||
/*
|
||||
* otp_pwr_down
|
||||
* 0: to power up OTP for read/write operation.
|
||||
* 1: to power down OTP to save power.
|
||||
* This bit is automatically set to 1 when OTP copy operation is complete.
|
||||
*/
|
||||
#define OTP_CTRL7_OTP_PWR_DOWN_POS 0x01
|
||||
#define OTP_CTRL7_OTP_PWR_DOWN_MASK (0x01 << OTP_CTRL7_OTP_PWR_DOWN_POS)
|
||||
/* ---------------------------------------------------------------------------
|
||||
* register MREG_FPGA
|
||||
* ---------------------------------------------------------------------------*/
|
||||
/* ---------------------------------------------------------------------------
|
||||
* register ROM
|
||||
* ---------------------------------------------------------------------------*/
|
||||
#define ACCEL_DATA_SIZE 6
|
||||
#define GYRO_DATA_SIZE 6
|
||||
#define TEMP_DATA_SIZE 2
|
||||
|
||||
#define FIFO_HEADER_SIZE 1
|
||||
#define FIFO_ACCEL_DATA_SIZE ACCEL_DATA_SIZE
|
||||
#define FIFO_GYRO_DATA_SIZE GYRO_DATA_SIZE
|
||||
#define FIFO_TEMP_DATA_SIZE 1
|
||||
#define FIFO_TS_FSYNC_SIZE 2
|
||||
#define FIFO_TEMP_HIGH_RES_SIZE 1
|
||||
#define FIFO_ACCEL_GYRO_HIGH_RES_SIZE 3
|
||||
|
||||
/*
|
||||
* Hysteresis high peak threshold (mg) added to the threshold after the initial threshold is met.
|
||||
* Use type APEX_CONFIG5_HIGHG_PEAK_TH_HYST_t to define highG peak hysteresis
|
||||
* These types are defined in inv_imu_defs.h.
|
||||
*/
|
||||
#define HIGHG_PEAK_HYSTERESIS APEX_CONFIG5_HIGHG_PEAK_TH_HYST_156MG
|
||||
|
||||
/* Initial WOM threshold to be applied to IMU in mg */
|
||||
#define WOM_THRESHOLD_INITIAL_MG 200
|
||||
|
||||
/*
|
||||
* HighG frequencies
|
||||
* Use type APEX_CONFIG1_DMP_ODR_t to define DMP frequency
|
||||
* These types are defined in inv_imu_defs.h.
|
||||
*
|
||||
* \note The frequency modes to run the HighG are :
|
||||
* APEX_CONFIG1_DMP_ODR_25Hz (Low Power mode),
|
||||
* APEX_CONFIG1_DMP_ODR_50Hz (Performance mode)
|
||||
*/
|
||||
#define HIGHG_FREQUENCY_MODE APEX_CONFIG1_DMP_ODR_50Hz
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* end of #ifdef __cplusplus */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* ________________________________________________________________________________________________________
|
||||
* Copyright (c) 2017 InvenSense Inc. All rights reserved.
|
||||
*
|
||||
* This software, related documentation and any modifications thereto (collectively "Software") is subject
|
||||
* to InvenSense and its licensors' intellectual property rights under U.S. and international copyright
|
||||
* and other intellectual property rights laws.
|
||||
*
|
||||
* InvenSense and its licensors retain all intellectual property and proprietary rights in and to the Software
|
||||
* and any use, reproduction, disclosure or distribution of the Software without an express license agreement
|
||||
* from InvenSense is strictly prohibited.
|
||||
*
|
||||
* EXCEPT AS OTHERWISE PROVIDED IN A LICENSE AGREEMENT BETWEEN THE PARTIES, THE SOFTWARE IS
|
||||
* PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* EXCEPT AS OTHERWISE PROVIDED IN A LICENSE AGREEMENT BETWEEN THE PARTIES, IN NO EVENT SHALL
|
||||
* INVENSENSE BE LIABLE FOR ANY DIRECT, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY
|
||||
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THE SOFTWARE.
|
||||
* ________________________________________________________________________________________________________
|
||||
*/
|
||||
|
||||
/** @defgroup Apex APEX
|
||||
* @brief High-level functions to drive APEX features
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @file inv_imu_apex.h */
|
||||
|
||||
#ifndef _INV_IMU_APEX_H_
|
||||
#define _INV_IMU_APEX_H_
|
||||
|
||||
#include "inv_imu_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct inv_imu_device;
|
||||
|
||||
/** IMU APEX inputs parameters definition */
|
||||
typedef struct {
|
||||
APEX_CONFIG3_PEDO_AMP_TH_t pedo_amp_th;
|
||||
uint8_t pedo_step_cnt_th;
|
||||
uint8_t pedo_step_det_th;
|
||||
APEX_CONFIG4_PEDO_SB_TIMER_TH_t pedo_sb_timer_th;
|
||||
APEX_CONFIG4_PEDO_HI_ENRGY_TH_t pedo_hi_enrgy_th;
|
||||
APEX_CONFIG5_TILT_WAIT_TIME_t tilt_wait_time;
|
||||
APEX_CONFIG2_DMP_POWER_SAVE_TIME_t power_save_time;
|
||||
APEX_CONFIG0_DMP_POWER_SAVE_t power_save;
|
||||
APEX_CONFIG9_SENSITIVITY_MODE_t sensitivity_mode;
|
||||
APEX_CONFIG2_LOW_ENERGY_AMP_TH_t low_energy_amp_th;
|
||||
APEX_CONFIG9_SMD_SENSITIVITY_t smd_sensitivity;
|
||||
APEX_CONFIG9_FF_DEBOUNCE_DURATION_t ff_debounce_duration;
|
||||
APEX_CONFIG12_FF_MAX_DURATION_t ff_max_duration_cm;
|
||||
APEX_CONFIG12_FF_MIN_DURATION_t ff_min_duration_cm;
|
||||
APEX_CONFIG10_LOWG_PEAK_TH_t lowg_peak_th;
|
||||
APEX_CONFIG5_LOWG_PEAK_TH_HYST_t lowg_peak_hyst;
|
||||
APEX_CONFIG10_LOWG_TIME_TH_SAMPLES_t lowg_samples_th;
|
||||
APEX_CONFIG11_HIGHG_PEAK_TH_t highg_peak_th;
|
||||
APEX_CONFIG5_HIGHG_PEAK_TH_HYST_t highg_peak_hyst;
|
||||
APEX_CONFIG11_HIGHG_TIME_TH_SAMPLES_t highg_samples_th;
|
||||
} inv_imu_apex_parameters_t;
|
||||
|
||||
/** APEX pedometer outputs */
|
||||
typedef struct inv_imu_apex_step_activity {
|
||||
/** Number of steps taken */
|
||||
uint16_t step_cnt;
|
||||
|
||||
/** Walk/run cadence in number of samples.
|
||||
* Format is u6.2. (at 50Hz and 2Hz walk frequency, if the cadency
|
||||
* is 25 samples, the register will output 100).
|
||||
*/
|
||||
uint8_t step_cadence;
|
||||
|
||||
/** Detected activity.
|
||||
* Unknown (0), Walk (1) or Run (2)
|
||||
*/
|
||||
uint8_t activity_class;
|
||||
} inv_imu_apex_step_activity_t;
|
||||
|
||||
/** @brief Enable Free Fall.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
int inv_imu_apex_enable_ff(struct inv_imu_device *s);
|
||||
|
||||
/** @brief Disable Free Fall.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
int inv_imu_apex_disable_ff(struct inv_imu_device *s);
|
||||
|
||||
/** @brief Enable Significant Motion Detection.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
* @warning SMD requires to have the pedometer enabled to work.
|
||||
*/
|
||||
int inv_imu_apex_enable_smd(struct inv_imu_device *s);
|
||||
|
||||
/** @brief Disable Significant Motion Detection.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
int inv_imu_apex_disable_smd(struct inv_imu_device *s);
|
||||
|
||||
/** @brief Fill the APEX parameters structure with all the default parameters for APEX algorithms.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[out] apex_inputs Default input parameters.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
int inv_imu_apex_init_parameters_struct(struct inv_imu_device * s,
|
||||
inv_imu_apex_parameters_t *apex_inputs);
|
||||
|
||||
/** @brief Configures DMP parameters for APEX algorithms.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] apex_inputs The requested input parameters.
|
||||
* @return 0 on success, negative value on error.
|
||||
* @warning APEX inputs can't change on the fly, this should be called before enabling
|
||||
* any APEX features.
|
||||
* @warning This API can't be called twice within 10 ms.
|
||||
*/
|
||||
int inv_imu_apex_configure_parameters(struct inv_imu_device * s,
|
||||
const inv_imu_apex_parameters_t *apex_inputs);
|
||||
|
||||
/** @brief Returns current DMP parameters for APEX algorithms.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[out] apex_params The current parameter, fetched from registers.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
int inv_imu_apex_get_parameters(struct inv_imu_device *s, inv_imu_apex_parameters_t *apex_params);
|
||||
|
||||
/** @brief Configure DMP Output Data Rate for APEX algorithms.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] frequency The requested frequency.
|
||||
* @return 0 on success, negative value on error.
|
||||
* @warning Accel frequency must be higher or equal to DMP frequency.
|
||||
*/
|
||||
int inv_imu_apex_set_frequency(struct inv_imu_device *s, const APEX_CONFIG1_DMP_ODR_t frequency);
|
||||
|
||||
/** @brief Enable APEX algorithm Pedometer.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
int inv_imu_apex_enable_pedometer(struct inv_imu_device *s);
|
||||
|
||||
/** @brief Disable APEX algorithm Pedometer.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
int inv_imu_apex_disable_pedometer(struct inv_imu_device *s);
|
||||
|
||||
/** @brief Enable APEX algorithm Tilt.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
int inv_imu_apex_enable_tilt(struct inv_imu_device *s);
|
||||
|
||||
/** @brief Disable APEX algorithm Tilt.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
int inv_imu_apex_disable_tilt(struct inv_imu_device *s);
|
||||
|
||||
/** @brief Retrieve APEX pedometer outputs and format them
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[out] apex_activity Apex step and activity data value.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
int inv_imu_apex_get_data_activity(struct inv_imu_device * s,
|
||||
inv_imu_apex_step_activity_t *apex_activity);
|
||||
|
||||
/** @brief Retrieve APEX free fall outputs and format them
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[out] freefall_duration Free fall duration in number of sample.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
int inv_imu_apex_get_data_free_fall(struct inv_imu_device *s, uint16_t *freefall_duration);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _INV_IMU_APEX_H_ */
|
||||
|
||||
/** @} */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,444 @@
|
||||
/*
|
||||
* ________________________________________________________________________________________________________
|
||||
* Copyright (c) 2017 InvenSense Inc. All rights reserved.
|
||||
*
|
||||
* This software, related documentation and any modifications thereto (collectively "Software") is subject
|
||||
* to InvenSense and its licensors' intellectual property rights under U.S. and international copyright
|
||||
* and other intellectual property rights laws.
|
||||
*
|
||||
* InvenSense and its licensors retain all intellectual property and proprietary rights in and to the Software
|
||||
* and any use, reproduction, disclosure or distribution of the Software without an express license agreement
|
||||
* from InvenSense is strictly prohibited.
|
||||
*
|
||||
* EXCEPT AS OTHERWISE PROVIDED IN A LICENSE AGREEMENT BETWEEN THE PARTIES, THE SOFTWARE IS
|
||||
* PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* EXCEPT AS OTHERWISE PROVIDED IN A LICENSE AGREEMENT BETWEEN THE PARTIES, IN NO EVENT SHALL
|
||||
* INVENSENSE BE LIABLE FOR ANY DIRECT, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY
|
||||
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THE SOFTWARE.
|
||||
* ________________________________________________________________________________________________________
|
||||
*/
|
||||
|
||||
/** @defgroup Driver Driver
|
||||
* @brief High-level functions to drive the device
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @file inv_imu_driver.h */
|
||||
|
||||
#ifndef _INV_IMU_DRIVER_H_
|
||||
#define _INV_IMU_DRIVER_H_
|
||||
|
||||
#include "inv_imu_defs.h"
|
||||
#include "inv_imu_transport.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Max FSR values for accel */
|
||||
#define ACCEL_CONFIG0_FS_SEL_MAX ACCEL_CONFIG0_FS_SEL_16g
|
||||
|
||||
/** Max FSR values for gyro */
|
||||
#define GYRO_CONFIG0_FS_SEL_MAX GYRO_CONFIG0_FS_SEL_2000dps
|
||||
|
||||
/** Max user offset value for accel (mg) */
|
||||
#define ACCEL_OFFUSER_MAX_MG 1000
|
||||
|
||||
/** Max user offset value for gyro (dps) */
|
||||
#define GYRO_OFFUSER_MAX_DPS 64
|
||||
|
||||
/** Max buffer size mirrored from FIFO at polling time */
|
||||
#define FIFO_MIRRORING_SIZE 16 * 258 // packet size * max_count = 4kB
|
||||
|
||||
/** Accel start-up time */
|
||||
#define ACC_STARTUP_TIME_US 10000
|
||||
|
||||
/** Gyro start-up time */
|
||||
#define GYR_STARTUP_TIME_US 70000
|
||||
|
||||
/** Sensor identifier for UI control function */
|
||||
enum inv_imu_sensor {
|
||||
INV_SENSOR_ACCEL, /**< Accelerometer */
|
||||
INV_SENSOR_GYRO, /**< Gyroscope */
|
||||
INV_SENSOR_FSYNC_EVENT, /**< FSYNC */
|
||||
INV_SENSOR_TEMPERATURE, /**< Chip temperature */
|
||||
INV_SENSOR_DMP_PEDOMETER_EVENT, /**< Pedometer: step detected */
|
||||
INV_SENSOR_DMP_PEDOMETER_COUNT, /**< Pedometer: step counter */
|
||||
INV_SENSOR_DMP_TILT, /**< Tilt */
|
||||
INV_SENSOR_DMP_FF, /**< FreeFall */
|
||||
INV_SENSOR_DMP_LOWG, /**< Low G */
|
||||
INV_SENSOR_DMP_SMD, /**< Significant Motion Detection */
|
||||
INV_SENSOR_MAX
|
||||
};
|
||||
|
||||
/** Configure Fifo usage */
|
||||
typedef enum {
|
||||
INV_IMU_FIFO_DISABLED = 0, /**< Fifo is disabled and data source is sensors registers */
|
||||
INV_IMU_FIFO_ENABLED = 1, /**< Fifo is used as data source */
|
||||
} INV_IMU_FIFO_CONFIG_t;
|
||||
|
||||
/** Sensor event structure definition */
|
||||
typedef struct {
|
||||
xmedia_s32 sensor_mask;
|
||||
xmedia_u16 timestamp_fsync;
|
||||
xmedia_s16 accel[3];
|
||||
xmedia_s16 gyro[3];
|
||||
xmedia_s16 temperature;
|
||||
xmedia_s8 accel_high_res[3];
|
||||
xmedia_s8 gyro_high_res[3];
|
||||
} inv_imu_sensor_event_t;
|
||||
|
||||
/** IMU driver states definition */
|
||||
struct inv_imu_device {
|
||||
/** Transport layer.
|
||||
* @warning Must be the first one of struct inv_imu_device
|
||||
*/
|
||||
struct inv_imu_transport transport;
|
||||
|
||||
/** callback executed by:
|
||||
* * inv_imu_get_data_from_fifo (if FIFO is used).
|
||||
* * inv_imu_get_data_from_registers (if FIFO isn't used).
|
||||
* May be NULL if above API are not used by application
|
||||
*/
|
||||
void (*sensor_event_cb)(xmedia_s32 dev, xmedia_u16 packet_count, xmedia_u16 idx, xmedia_u64 time_inter,
|
||||
inv_imu_sensor_event_t *event);
|
||||
|
||||
xmedia_u8 fifo_data[FIFO_MIRRORING_SIZE]; /**< FIFO mirroring memory area */
|
||||
xmedia_u8 dmp_is_on; /**< DMP started status */
|
||||
xmedia_u8 endianness_data; /**< Data endianness configuration */
|
||||
xmedia_u8 fifo_highres_enabled; /**< Highres mode configuration */
|
||||
INV_IMU_FIFO_CONFIG_t fifo_is_used; /**< FIFO configuration */
|
||||
xmedia_u64 gyro_start_time_us; /**< Gyro start time used to discard first samples */
|
||||
xmedia_u64 accel_start_time_us; /**< Accel start time used to discard first samples */
|
||||
};
|
||||
|
||||
/** Interrupt enum state for INT1, INT2, and IBI */
|
||||
typedef enum {
|
||||
INV_IMU_DISABLE = 0,
|
||||
INV_IMU_ENABLE
|
||||
} inv_imu_interrupt_value;
|
||||
|
||||
/** Interrupt definition */
|
||||
typedef struct {
|
||||
inv_imu_interrupt_value INV_UI_FSYNC;
|
||||
inv_imu_interrupt_value INV_UI_DRDY;
|
||||
inv_imu_interrupt_value INV_FIFO_THS;
|
||||
inv_imu_interrupt_value INV_FIFO_FULL;
|
||||
inv_imu_interrupt_value INV_SMD;
|
||||
inv_imu_interrupt_value INV_WOM_X;
|
||||
inv_imu_interrupt_value INV_WOM_Y;
|
||||
inv_imu_interrupt_value INV_WOM_Z;
|
||||
inv_imu_interrupt_value INV_FF;
|
||||
inv_imu_interrupt_value INV_LOWG;
|
||||
inv_imu_interrupt_value INV_STEP_DET;
|
||||
inv_imu_interrupt_value INV_STEP_CNT_OVFL;
|
||||
inv_imu_interrupt_value INV_TILT_DET;
|
||||
} inv_imu_interrupt_parameter_t;
|
||||
|
||||
/** @brief Initializes device.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] serif Pointer on serial interface structure.
|
||||
* @param[in] sensor_event_cb Callback executed when a new sensor event is available. *
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_init(xmedia_s32 dev, struct inv_imu_device *s, struct inv_imu_serif *serif,
|
||||
void (*sensor_event_cb)(xmedia_s32 dev, xmedia_u16 packet_count, xmedia_u16 idx, xmedia_u64 time_inter,
|
||||
inv_imu_sensor_event_t *event));
|
||||
|
||||
/** @brief Reset device by reloading OTPs.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_device_reset(xmedia_s32 dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief return WHOAMI value.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[out] who_am_i WHOAMI for device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_get_who_am_i(xmedia_s32 dev, struct inv_imu_device *s, xmedia_u8 *who_am_i);
|
||||
|
||||
/** @brief Enable/put accel in low power mode.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_enable_accel_low_power_mode(xmedia_s32 dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Enable/put accel in low noise mode.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_enable_accel_low_noise_mode(xmedia_s32 dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Disable all 3 axes of accel.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_disable_accel(xmedia_s32 dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Enable/put gyro in low noise mode.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_enable_gyro_low_noise_mode(xmedia_s32 dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Disable all 3 axes of gyro.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_disable_gyro(xmedia_s32 dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Enable fsync tagging functionality.
|
||||
* * Enables fsync.
|
||||
* * Enables timestamp to registers. Once fsync is enabled fsync counter is pushed to
|
||||
* fifo instead of timestamp. So timestamp is made available in registers. Note that
|
||||
* this increase power consumption.
|
||||
* * Enables fsync related interrupt.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_enable_fsync(xmedia_s32 dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Disable fsync tagging functionality.
|
||||
* * Disables fsync.
|
||||
* * Disables timestamp to registers. Once fsync is disabled timestamp is pushed to fifo
|
||||
* instead of fsync counter. So in order to decrease power consumption, timestamp is no
|
||||
* more available in registers.
|
||||
* * Disables fsync related interrupt.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_disable_fsync(xmedia_s32 dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Configure which interrupt source can trigger INT1.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] interrupt_to_configure Structure with the corresponding state to manage INT1.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_set_config_int1(xmedia_s32 dev, struct inv_imu_device *s, inv_imu_interrupt_parameter_t *interrupt_to_configure);
|
||||
|
||||
/** @brief Retrieve interrupts configuration.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] interrupt_to_configure Structure with the corresponding state to manage INT1.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_get_config_int1(xmedia_s32 dev, struct inv_imu_device *s, inv_imu_interrupt_parameter_t *interrupt_to_configure);
|
||||
|
||||
/** @brief Configure which interrupt source can trigger INT2.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] interrupt_to_configure Structure with the corresponding state to INT2.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_set_config_int2(xmedia_s32 dev, struct inv_imu_device *s, inv_imu_interrupt_parameter_t *interrupt_to_configure);
|
||||
|
||||
/** @brief Retrieve interrupts configuration.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] interrupt_to_configure Structure with the corresponding state to manage INT2.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_get_config_int2(xmedia_s32 dev, struct inv_imu_device *s, inv_imu_interrupt_parameter_t *interrupt_to_configure);
|
||||
|
||||
/** @brief Read all registers containing data (temperature, accelerometer and gyroscope).
|
||||
* Then it calls sensor_event_cb function passed at init for each packet.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_get_data_from_registers(xmedia_s32 dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Read all available packets from the FIFO.
|
||||
* For each packet function builds a sensor event containing packet data
|
||||
* and validity information. Then it calls sensor_event_cb funtion passed
|
||||
* at init for each packet.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return Number of valid packets read on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_get_data_from_fifo(xmedia_s32 dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Converts ACCEL_CONFIG0_ODR_t or GYRO_CONFIG0_ODR_t enums to period expressed in us.
|
||||
* @param[in] odr_bitfield An ACCEL_CONFIG0_ODR_t or GYRO_CONFIG0_ODR_t enum.
|
||||
* @return The corresponding period expressed in us.
|
||||
*/
|
||||
xmedia_u32 inv_imu_convert_odr_bitfield_to_us(xmedia_s32 dev, xmedia_u32 odr_bitfield);
|
||||
|
||||
/** @brief Configure accel Output Data Rate.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] frequency The requested frequency.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_set_accel_frequency(xmedia_s32 dev, struct inv_imu_device *s, const ACCEL_CONFIG0_ODR_t frequency);
|
||||
|
||||
/** @brief Configure gyro Output Data Rate.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] frequency The requested frequency.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_set_gyro_frequency(xmedia_s32 dev, struct inv_imu_device *s, const GYRO_CONFIG0_ODR_t frequency);
|
||||
|
||||
/** @brief Set accel full scale range.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] accel_fsr_g Requested full scale range.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_set_accel_fsr(xmedia_s32 dev, struct inv_imu_device *s, ACCEL_CONFIG0_FS_SEL_t accel_fsr_g);
|
||||
|
||||
/** @brief Access accel full scale range.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[out] accel_fsr_g Current full scale range.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_get_accel_fsr(xmedia_s32 dev, struct inv_imu_device *s, ACCEL_CONFIG0_FS_SEL_t *accel_fsr_g);
|
||||
|
||||
/** @brief Set gyro full scale range.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] gyro_fsr_dps Requested full scale range.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_set_gyro_fsr(xmedia_s32 dev, struct inv_imu_device *s, GYRO_CONFIG0_FS_SEL_t gyro_fsr_dps);
|
||||
|
||||
/** @brief Access gyro full scale range.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[out] gyro_fsr_dps Current full scale range.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_get_gyro_fsr(xmedia_s32 dev, struct inv_imu_device *s, GYRO_CONFIG0_FS_SEL_t *gyro_fsr_dps);
|
||||
|
||||
/** @brief Set accel Low-Power averaging value.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] acc_avg Requested averaging value.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_set_accel_lp_avg(xmedia_s32 dev, struct inv_imu_device *s, ACCEL_CONFIG1_ACCEL_FILT_AVG_t acc_avg);
|
||||
|
||||
/** @brief Set accel Low-Noise bandwidth value.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] acc_bw Requested averaging value.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_set_accel_ln_bw(xmedia_s32 dev, struct inv_imu_device *s, ACCEL_CONFIG1_ACCEL_FILT_BW_t acc_bw);
|
||||
|
||||
/** @brief Set gyro Low-Noise bandwidth value.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] gyr_bw Requested averaging value.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_set_gyro_ln_bw(xmedia_s32 dev, struct inv_imu_device *s, GYRO_CONFIG1_GYRO_FILT_BW_t gyr_bw);
|
||||
|
||||
/** @brief Set timestamp resolution.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] timestamp_resol Requested timestamp resolution.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_set_timestamp_resolution(xmedia_s32 dev, struct inv_imu_device *s, const TMST_CONFIG1_RESOL_t timestamp_resol);
|
||||
|
||||
/** @brief Reset IMU fifo.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_reset_fifo(xmedia_s32 dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Enable 20 bits raw acc and raw gyr data in fifo.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_enable_high_resolution_fifo(xmedia_s32 dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Disable 20 bits raw acc and raw gyr data in fifo.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_disable_high_resolution_fifo(xmedia_s32 dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Configure Fifo.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] fifo_config Fifo configuration method.
|
||||
* Enabled: data are pushed to FIFO and FIFO THS interrupt is set.
|
||||
* Disabled: data are not pused to FIFO and DRDY interrupt is set.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_configure_fifo(xmedia_s32 dev, struct inv_imu_device *s, INV_IMU_FIFO_CONFIG_t fifo_config);
|
||||
|
||||
/** @brief Get timestamp resolution
|
||||
* @param[in] s Pointer to device.
|
||||
* @return The timestamp resolution in us or 0 in case of error
|
||||
*/
|
||||
xmedia_u32 inv_imu_get_timestamp_resolution_us(xmedia_s32 dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Enable Wake On Motion.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] wom_x_th Threshold value for the Wake on Motion Interrupt for X-axis accel.
|
||||
* @param[in] wom_y_th Threshold value for the Wake on Motion Interrupt for Y-axis accel.
|
||||
* @param[in] wom_z_th Threshold value for the Wake on Motion Interrupt for Z-axis accel.
|
||||
* @param[in] wom_int Select which mode between AND/OR is used to generate interrupt.
|
||||
* @param[in] wom_dur Select the number of overthreshold event to wait
|
||||
* before generating interrupt.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_configure_wom(xmedia_s32 dev, struct inv_imu_device *s, const xmedia_u8 wom_x_th, const xmedia_u8 wom_y_th,
|
||||
const xmedia_u8 wom_z_th, WOM_CONFIG_WOM_INT_MODE_t wom_int,
|
||||
WOM_CONFIG_WOM_INT_DUR_t wom_dur);
|
||||
|
||||
/** @brief Enable Wake On Motion.
|
||||
* WoM requests to have the accelerometer enabled to work.
|
||||
* As a consequence Fifo water-mark interrupt is disabled to only trigger WoM interrupts.
|
||||
* To have good performance, it's recommended to set accel ODR to 20ms
|
||||
* and in Low Power Mode.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_enable_wom(xmedia_s32 dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Disable Wake On Motion.
|
||||
* Fifo water-mark interrupt is re-enabled when WoM is disabled.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_disable_wom(xmedia_s32 dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Start DMP for APEX algorithms and selftest.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_start_dmp(xmedia_s32 dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Reset DMP for APEX algorithms and selftest.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] sram_reset Reset mode for the SRAM.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_reset_dmp(xmedia_s32 dev, struct inv_imu_device *s, const APEX_CONFIG0_DMP_MEM_RESET_t sram_reset);
|
||||
|
||||
/** @brief Set the UI endianness and set the inv_device endianness field.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] endianness Endianness to be set.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_set_endianness(xmedia_s32 dev, struct inv_imu_device *s, INTF_CONFIG0_DATA_ENDIAN_t endianness);
|
||||
|
||||
/** @brief Read the UI endianness and set the inv_device endianness field.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_get_endianness(xmedia_s32 dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Configure Fifo decimation.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] dec_factor Requested decimation factor value from 2 to 256.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
xmedia_s32 inv_imu_configure_fifo_data_rate(xmedia_s32 dev, struct inv_imu_device *s, FDR_CONFIG_FDR_SEL_t dec_factor);
|
||||
|
||||
/** @brief Return driver version x.y.z-suffix as a xmedia_char array
|
||||
* @return driver version a xmedia_char array "x.y.z-suffix"
|
||||
*/
|
||||
const xmedia_char *inv_imu_get_version(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _INV_IMU_DRIVER_H_ */
|
||||
|
||||
/** @} */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* ________________________________________________________________________________________________________
|
||||
* Copyright (c) 2015-2015 InvenSense Inc. All rights reserved.
|
||||
*
|
||||
* This software, related documentation and any modifications thereto (collectively "Software") is subject
|
||||
* to InvenSense and its licensors' intellectual property rights under U.S. and international copyright
|
||||
* and other intellectual property rights laws.
|
||||
*
|
||||
* InvenSense and its licensors retain all intellectual property and proprietary rights in and to the Software
|
||||
* and any use, reproduction, disclosure or distribution of the Software without an express license agreement
|
||||
* from InvenSense is strictly prohibited.
|
||||
*
|
||||
* EXCEPT AS OTHERWISE PROVIDED IN A LICENSE AGREEMENT BETWEEN THE PARTIES, THE SOFTWARE IS
|
||||
* PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* EXCEPT AS OTHERWISE PROVIDED IN A LICENSE AGREEMENT BETWEEN THE PARTIES, IN NO EVENT SHALL
|
||||
* INVENSENSE BE LIABLE FOR ANY DIRECT, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY
|
||||
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THE SOFTWARE.
|
||||
* ________________________________________________________________________________________________________
|
||||
*/
|
||||
|
||||
/** @defgroup Transport Transport
|
||||
* @brief Abstraction layer to access device's registers
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @file inv_imu_transport.h */
|
||||
|
||||
#ifndef _INV_IMU_TRANSPORT_H_
|
||||
#define _INV_IMU_TRANSPORT_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* forward declaration */
|
||||
struct inv_imu_device;
|
||||
|
||||
/** Available serial interface type. */
|
||||
typedef enum {
|
||||
UI_I2C, /**< Selects I2C interface. */
|
||||
UI_SPI4, /**< Selects 4-wire SPI interface. */
|
||||
UI_SPI3 /**< Selects 3-wire SPI interface. */
|
||||
} SERIAL_IF_TYPE_t;
|
||||
|
||||
/** Serial interface definition */
|
||||
struct inv_imu_serif {
|
||||
void *context;
|
||||
int (*read_reg)(xmedia_s32 dev, struct inv_imu_serif *serif, uint8_t reg, uint8_t *buf, uint32_t len);
|
||||
int (*write_reg)(xmedia_s32 dev, struct inv_imu_serif *serif, uint8_t reg, const uint8_t *buf, uint32_t len);
|
||||
uint32_t max_read;
|
||||
uint32_t max_write;
|
||||
SERIAL_IF_TYPE_t serif_type;
|
||||
};
|
||||
|
||||
/** Transport interface definition. */
|
||||
struct inv_imu_transport {
|
||||
/** Serial interface object.
|
||||
* @warning Must be the first object in this structure.
|
||||
*/
|
||||
struct inv_imu_serif serif;
|
||||
|
||||
/** Contains mirrored values of some IP registers. */
|
||||
struct register_cache {
|
||||
uint8_t pwr_mgmt0_reg;
|
||||
uint8_t gyro_config0_reg;
|
||||
uint8_t accel_config0_reg;
|
||||
uint8_t tmst_config1_reg;
|
||||
} register_cache;
|
||||
|
||||
/** Internal counter for MCLK requests. */
|
||||
uint8_t need_mclk_cnt;
|
||||
};
|
||||
|
||||
/** @brief Init cache variable.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
int inv_imu_init_transport(int32_t dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Reads data from a register on IMU.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] reg Register address to be read.
|
||||
* @param[in] len Number of byte to be read.
|
||||
* @param[out] buf Output data from the register.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
int inv_imu_read_reg(int32_t dev, struct inv_imu_device *s, uint32_t reg, uint32_t len, uint8_t *buf);
|
||||
|
||||
/** @brief Writes data to a register on IMU.
|
||||
* @param[in] s Pointer to device.
|
||||
* @param[in] reg Register address to be written.
|
||||
* @param[in] len Number of byte to be written.
|
||||
* @param[in] buf Input data to write.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
int inv_imu_write_reg(int32_t dev, struct inv_imu_device *s, uint32_t reg, uint32_t len, const uint8_t *buf);
|
||||
|
||||
/** @brief Enable MCLK.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
int inv_imu_switch_on_mclk(int32_t dev, struct inv_imu_device *s);
|
||||
|
||||
/** @brief Disable MCLK.
|
||||
* @param[in] s Pointer to device.
|
||||
* @return 0 on success, negative value on error.
|
||||
*/
|
||||
int inv_imu_switch_off_mclk(int32_t dev, struct inv_imu_device *s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _INV_IMU_TRANSPORT_H_ */
|
||||
|
||||
/** @} */
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c); XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "msensor_gpio.h"
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/io.h>
|
||||
#include "icm42670.h"
|
||||
|
||||
xmedia_s32 gpio_init(xmedia_void)
|
||||
{
|
||||
xmedia_s32 ret;
|
||||
|
||||
ret = gpio_request(gpio_num(INT_GPIO_CHIP, INT_GPIO_OFFSET), "icm42670_irq");
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
print_info("irq GPIO request failed: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpio_direction_input(gpio_num(INT_GPIO_CHIP, INT_GPIO_OFFSET));
|
||||
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
xmedia_s32 gpio_deinit(xmedia_void)
|
||||
{
|
||||
gpio_free(gpio_num(INT_GPIO_CHIP, INT_GPIO_OFFSET));
|
||||
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c); XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __MSENSOR_GPIO_H__
|
||||
#define __MSENSOR_GPIO_H__
|
||||
|
||||
#include "xmedia_type.h"
|
||||
#include <linux/gpio.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* end of #ifdef __cplusplus */
|
||||
|
||||
#define gpio_num(gpio_chip_num, gpio_offset_num) ((gpio_chip_num) * 8 + (gpio_offset_num))
|
||||
|
||||
xmedia_s32 gpio_init(xmedia_void);
|
||||
xmedia_s32 gpio_deinit(xmedia_void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* end of #ifdef __cplusplus */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c); XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
/* include <liteos/i2c.h> */
|
||||
#include "i2c_dev.h"
|
||||
#include "linux/i2c.h"
|
||||
#include "msensor.h"
|
||||
|
||||
struct i2c_client g_i2c_client_obj; /* i2c control struct */
|
||||
#define SLAVE_ADDR 0x34 /* i2c dev addr */
|
||||
#define SLAVE_REG_ADDR 0x300f /* i2c dev register */
|
||||
|
||||
/* client initial */
|
||||
static xmedia_s32 i2c_client_init(struct i2c_client **xmedia_i2c_client)
|
||||
{
|
||||
xmedia_s32 ret;
|
||||
|
||||
/* struct i2c_client * i2c_client0 is &g_i2c_client_obj */
|
||||
/* i2c_client0->addr is SLAVE_ADDR >> 1 */
|
||||
xmedia_i2c_client->addr = ICM40690_DEV_ADDR;
|
||||
|
||||
ret = client_attach(*xmedia_i2c_client, 0);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
dprintf("fail to attach client!\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static xmedia_s32 sample_i2c_write(struct i2c_client *xmedia_i2c_client, xmedia_u8 reg_addr, const xmedia_u8 *reg_data,
|
||||
xmedia_u32 cnt)
|
||||
{
|
||||
xmedia_s32 ret;
|
||||
|
||||
/* struct i2c_client * i2c_client0 is & g_i2c_client_obj */
|
||||
xmedia_char buf[4] = { 0 }; /* 4 buf */
|
||||
/* i2c_client_init */
|
||||
buf[0] = reg_addr & 0xff;
|
||||
osal_memcpy(&buf[1], reg_data, cnt);
|
||||
/* buf[1] is (SLAVE_REG_ADDR >> 8) & 0xff */
|
||||
/* buf[2] is 0x03 write value to i2c */
|
||||
/* call I2C standard function drv to write */
|
||||
ret = i2c_master_send(xmedia_i2c_client, &buf, cnt + 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static xmedia_s32 sample_i2c_read(struct i2c_client *xmedia_i2c_client, xmedia_u8 reg_addr, xmedia_u8 *reg_data,
|
||||
xmedia_u32 cnt)
|
||||
{
|
||||
xmedia_s32 ret = XMEDIA_SUCCESS;
|
||||
|
||||
/* struct i2c_client *i2c_client0 is & g_i2c_client_obj */
|
||||
struct i2c_rdwr_data rdwr;
|
||||
struct i2c_msg msg[2]; /* 2 msg */
|
||||
xmedia_u8 recvbuf[4]; /* 4 bytes */
|
||||
(xmedia_void) osal_memset(recvbuf, 0x0, sizeof(recvbuf));
|
||||
/* i2c_client_init */
|
||||
msg[0].addr = xmedia_i2c_client->addr;
|
||||
msg[0].flags = xmedia_i2c_client->flags & I2C_M_TEN;
|
||||
msg[0].len = 1;
|
||||
msg[0].buf = reg_addr;
|
||||
msg[1].addr = xmedia_i2c_client->addr;
|
||||
msg[1].flags = xmedia_i2c_client->flags & I2C_M_TEN;
|
||||
msg[1].flags |= I2C_M_RD;
|
||||
msg[1].len = cnt;
|
||||
msg[1].buf = reg_data;
|
||||
/* rdwr.msgs = &msg[0] */
|
||||
rdwr.nmsgs = 2; /* 2 msg */
|
||||
recvbuf[0] = SLAVE_REG_ADDR & 0xff;
|
||||
recvbuf[1] = (SLAVE_REG_ADDR >> 8) & 0xff; /* 8 bits */
|
||||
i2c_transfer(xmedia_i2c_client->adapter, msg, rdwr.nmsgs);
|
||||
/* dprintf("val is 0x%x\n",recvbuf[0]) buf[0] save the value read from i2c dev */
|
||||
return ret;
|
||||
}
|
||||
|
||||
xmedia_u8 msensor_i2c_write(struct i2c_client *xmedia_i2c_client, xmedia_u8 reg_addr, const xmedia_u8 *reg_data,
|
||||
xmedia_u32 cnt)
|
||||
{
|
||||
return sample_i2c_write(xmedia_i2c_client, reg_addr, reg_data, cnt);
|
||||
}
|
||||
|
||||
xmedia_u8 msensor_i2c_read(struct i2c_client *xmedia_i2c_client, xmedia_u8 reg_addr, xmedia_u8 *reg_data,
|
||||
xmedia_u32 cnt)
|
||||
{
|
||||
return sample_i2c_read(xmedia_i2c_client, reg_addr, reg_data, cnt);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c); XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __I2C_DEV_H__
|
||||
#define __I2C_DEV_H__
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include "xmedia_type.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* end of #ifdef __cplusplus */
|
||||
|
||||
xmedia_u8 msensor_i2c_write(struct i2c_client *xmedia_i2c_client,
|
||||
xmedia_u8 reg_addr, const xmedia_u8 *reg_data,xmedia_u32 cnt);
|
||||
xmedia_u8 msensor_i2c_read(struct i2c_client *xmedia_i2c_client,
|
||||
xmedia_u8 reg_addr, xmedia_u8 *reg_data, xmedia_u32 cnt);
|
||||
xmedia_u32 msensor_i2c_get_frequency(struct i2c_client *xmedia_i2c_client, xmedia_s32 *frequency);
|
||||
xmedia_u32 msensor_i2c_init(struct i2c_client **xmedia_i2c_client,
|
||||
struct i2c_board_info xmedia_i2c_board_info, xmedia_s32 adapt_num);
|
||||
|
||||
xmedia_void msensor_i2c_exit(struct i2c_client **xmedia_i2c_client);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* end of #ifdef __cplusplus */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright (c); XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "spi_dev.h"
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include "common.h"
|
||||
#include "msensor.h"
|
||||
|
||||
#define REG_WIDTH 1
|
||||
|
||||
static xmedia_u32 g_csn = 0;
|
||||
static spinlock_t g_lock_rd;
|
||||
|
||||
static xmedia_u32 g_bus_num = 1;
|
||||
|
||||
module_param(g_bus_num, uint, S_IRUGO);
|
||||
MODULE_PARM_DESC(g_bus_num, "spi bus number");
|
||||
module_param(g_csn, uint, S_IRUGO);
|
||||
MODULE_PARM_DESC(g_csn, "chip select number");
|
||||
|
||||
struct spi_master *g_xmedia_master;
|
||||
|
||||
static xmedia_s32 ssp_func_write(struct spi_device *xmedia_spi, xmedia_u8 addr, const xmedia_u8 *data, xmedia_u32 cnt)
|
||||
{
|
||||
struct spi_master *master = g_xmedia_master;
|
||||
static struct spi_transfer t;
|
||||
static struct spi_message msg;
|
||||
static xmedia_u8 buf[4] = { 0 }; /* 4 byte buf */
|
||||
xmedia_s16 ret;
|
||||
xmedia_ulong flags;
|
||||
|
||||
if (xmedia_spi == XMEDIA_NULL) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
xmedia_unused(cnt);
|
||||
|
||||
/* check spi_message is or no finish */
|
||||
spin_lock_irqsave(&master->queue_lock, flags);
|
||||
|
||||
if (msg.state != XMEDIA_NULL) {
|
||||
MSENSOR_ERR_TRACE("msg.state not null!!\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&master->queue_lock, flags);
|
||||
|
||||
buf[0] = addr;
|
||||
buf[0] &= (~0x80);
|
||||
buf[1] = *data;
|
||||
|
||||
t.tx_buf = buf;
|
||||
t.len = 2; /* length 2 */
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&t, &msg);
|
||||
|
||||
msg.state = &msg;
|
||||
ret = spi_sync(xmedia_spi, &msg);
|
||||
if (ret != 0) {
|
||||
MSENSOR_ERR_TRACE(" spi_async() error(%d)!\n", ret);
|
||||
return -EAGAIN;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static xmedia_s32 ssp_func_read(struct spi_device *xmedia_spi, xmedia_u8 addr, xmedia_u8 *data, xmedia_u32 cnt)
|
||||
{
|
||||
struct spi_master *master = g_xmedia_master;
|
||||
static struct spi_transfer t;
|
||||
static struct spi_message msg;
|
||||
static xmedia_u8 buf[4] = { 0 }; /* 4 byte buf */
|
||||
xmedia_s16 ret;
|
||||
xmedia_ulong flags;
|
||||
static xmedia_u8 body[1024] = { 0 }; /* 1024 byte buf */
|
||||
|
||||
if (xmedia_spi == XMEDIA_NULL) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* check spi_message is or no finish */
|
||||
spin_lock_irqsave(&master->queue_lock, flags);
|
||||
|
||||
if (msg.state != XMEDIA_NULL) {
|
||||
MSENSOR_ERR_TRACE("msg.state not null!!(%x)\n", addr);
|
||||
spin_unlock_irqrestore(&master->queue_lock, flags);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&master->queue_lock, flags);
|
||||
|
||||
buf[0] = addr;
|
||||
buf[0] |= 0x80;
|
||||
buf[1] = 0;
|
||||
|
||||
t.tx_buf = buf;
|
||||
t.rx_buf = body;
|
||||
t.len = cnt + 1;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&t, &msg);
|
||||
msg.state = &msg;
|
||||
ret = spi_sync(xmedia_spi, &msg);
|
||||
if (ret != 0) {
|
||||
MSENSOR_ERR_TRACE(" spi_async() error(%d)!\n", ret);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
osal_memcpy(data, body + 1, cnt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
xmedia_s32 msensor_spi_write(struct spi_device *xmedia_spi, xmedia_u8 addr, const xmedia_u8 *data, xmedia_u32 cnt)
|
||||
{
|
||||
return ssp_func_write(xmedia_spi, addr, data, cnt);
|
||||
}
|
||||
|
||||
xmedia_s32 msensor_spi_read(struct spi_device *xmedia_spi, xmedia_u8 addr, xmedia_u8 *data, xmedia_u32 cnt)
|
||||
{
|
||||
xmedia_s16 ret;
|
||||
|
||||
ret = ssp_func_read(xmedia_spi, addr, data, cnt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
xmedia_s32 msensor_spi_init(struct spi_device **xmedia_spi)
|
||||
{
|
||||
xmedia_s32 status = XMEDIA_SUCCESS;
|
||||
struct device *d = XMEDIA_NULL;
|
||||
xmedia_char *spi_name = XMEDIA_NULL;
|
||||
xmedia_s32 spi_name_len;
|
||||
|
||||
g_xmedia_master = spi_busnum_to_master(g_bus_num);
|
||||
if (g_xmedia_master == XMEDIA_NULL) {
|
||||
status = -ENXIO;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
spi_name_len = strlen(dev_name(&g_xmedia_master->dev)) + 10; /* extend 10 */
|
||||
|
||||
spi_name = osal_kmalloc(spi_name_len, osal_gfp_kernel);
|
||||
if (spi_name == XMEDIA_NULL) {
|
||||
status = -ENOMEM;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
(xmedia_void) osal_memset(spi_name, 0, spi_name_len);
|
||||
if (osal_sprintf(spi_name, "%s.%u", dev_name(&g_xmedia_master->dev), g_csn) == XMEDIA_FAILURE) {
|
||||
status = XMEDIA_FAILURE;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
d = bus_find_device_by_name(&spi_bus_type, XMEDIA_NULL, spi_name);
|
||||
if (d == XMEDIA_NULL) {
|
||||
status = -ENXIO;
|
||||
goto err1;
|
||||
}
|
||||
*xmedia_spi = to_spi_device(d);
|
||||
if (*xmedia_spi == XMEDIA_NULL) {
|
||||
status = -ENXIO;
|
||||
goto err2;
|
||||
}
|
||||
|
||||
spin_lock_init(&g_lock_rd);
|
||||
err2:
|
||||
put_device(d);
|
||||
err1:
|
||||
if (spi_name != XMEDIA_NULL) {
|
||||
osal_kfree(spi_name);
|
||||
spi_name = XMEDIA_NULL;
|
||||
}
|
||||
err0:
|
||||
return status;
|
||||
}
|
||||
|
||||
xmedia_s32 msensor_spi_deinit(const struct spi_device *spi_device)
|
||||
{
|
||||
xmedia_unused(spi_device);
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c); XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __SPI_DEV_H__
|
||||
#define __SPI_DEV_H__
|
||||
|
||||
#include "xmedia_type.h"
|
||||
#include "osal.h"
|
||||
#include "xmedia_debug.h"
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* end of #ifdef __cplusplus */
|
||||
|
||||
xmedia_s32 msensor_spi_write(struct spi_device *xmedia_spi, xmedia_u8 addr, const xmedia_u8 *data, xmedia_u32 cnt);
|
||||
xmedia_s32 msensor_spi_read(struct spi_device *xmedia_spi, xmedia_u8 addr, xmedia_u8 *data, xmedia_u32 cnt);
|
||||
xmedia_s32 msensor_spi_init(struct spi_device **xmedia_spi);
|
||||
xmedia_s32 msensor_spi_deinit(const struct spi_device *spi_device);
|
||||
|
||||
#ifndef MSENSOR_ERR_TRACE
|
||||
#define MSENSOR_ERR_TRACE(fmt, ...) \
|
||||
printk(KERN_ERR "[Func]:%s [Line]:%d [Info]:" fmt, __FUNCTION__, __LINE__, \
|
||||
##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* end of #ifdef __cplusplus */
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user